Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WEB: Implement managed service cloning & notification ui & config/secrets ui #226

Merged
merged 4 commits into from
Jun 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
127 changes: 124 additions & 3 deletions gql-queries-generator/doc/queries.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,6 @@ query consoleListAllClusters($search: SearchCluster, $pagination: CursorPaginati
cursor
node {
accountName
clusterPublicEndpoint
clusterSvcCIDR
createdBy {
userEmail
Expand Down Expand Up @@ -3172,6 +3171,17 @@ mutation consoleCreateClusterMSv($service: ClusterManagedServiceIn!) {
}
}

mutation consoleCloneClusterMSv($clusterName: String!, $sourceMsvcName: String!, $destinationMsvcName: String!, $displayName: String!) {
infra_cloneClusterManagedService(
clusterName: $clusterName
sourceMsvcName: $sourceMsvcName
destinationMsvcName: $destinationMsvcName
displayName: $displayName
) {
id
}
}

mutation consoleUpdateClusterMSv($service: ClusterManagedServiceIn!) {
infra_updateClusterManagedService(service: $service) {
id
Expand Down Expand Up @@ -3335,7 +3345,6 @@ query consoleGetByokCluster($name: String!) {
syncScheduledAt
}
updateTime
clusterPublicEndpoint
clusterSvcCIDR
globalVPN
}
Expand All @@ -3347,7 +3356,6 @@ query consoleListByokClusters($search: SearchCluster, $pagination: CursorPaginat
cursor
node {
accountName
clusterPublicEndpoint
clusterSvcCIDR
createdBy {
userEmail
Expand Down Expand Up @@ -4296,6 +4304,119 @@ query consoleListGlobalVpnDevices($gvpn: String!, $search: SearchGlobalVPNDevice
}
}

mutation consoleUpdateNotificationConfig($config: NotificationConfIn!) {
comms_updateNotificationConfig(config: $config) {
id
}
}

mutation consoleUpdateSubscriptionConfig($config: SubscriptionIn!, $commsUpdateSubscriptionConfigId: ID!) {
comms_updateSubscriptionConfig(
config: $config
id: $commsUpdateSubscriptionConfigId
) {
id
}
}

mutation consoleMarkAllNotificationAsRead {
comms_markAllNotificationAsRead
}

query consoleGetNotificationConfig {
comms_getNotificationConfig {
accountName
createdBy {
userEmail
userId
userName
}
creationTime
email {
enabled
mailAddress
}
id
lastUpdatedBy {
userEmail
userId
userName
}
markedForDeletion
recordVersion
slack {
enabled
url
}
telegram {
chatId
enabled
token
}
updateTime
webhook {
enabled
url
}
}
}

query consoleGetSubscriptionConfig($commsGetSubscriptionConfigId: ID!) {
comms_getSubscriptionConfig(id: $commsGetSubscriptionConfigId) {
accountName
createdBy {
userEmail
userId
userName
}
creationTime
enabled
id
lastUpdatedBy {
userEmail
userId
userName
}
mailAddress
markedForDeletion
recordVersion
updateTime
}
}

query consoleListNotifications($pagination: CursorPaginationIn) {
comms_listNotifications(pagination: $pagination) {
edges {
cursor
node {
accountName
content {
body
image
link
subject
title
}
creationTime
id
markedForDeletion
notificationType
priority
read
recordVersion
updateTime
}
}
pageInfo {
endCursor
hasNextPage
hasPreviousPage
startCursor
}
totalCount
}
}

query iotconsoleAccountCheckNameAvailability($name: String!) {
accounts_checkNameAvailability(name: $name) {
result
Expand Down
32 changes: 32 additions & 0 deletions src/apps/console/components/icons.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,32 @@
import React from 'react';

export const AvatarNotification = ({ size = 16 }: { size?: number }) => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width={size}
height={size}
fill="none"
viewBox="0 0 25 26"
>
<rect width="24" height="24" x="0.5" y="1" fill="#fff" rx="12" />
<rect width="24" height="24" x="0.5" y="1" stroke="#E4E4E7" rx="12" />
<path
fill="#111827"
d="M4.813 13l3.17-8.73H9.27L12.482 13h-1.171L9.458 7.82c-.113-.32-.246-.718-.398-1.195-.149-.48-.33-1.092-.545-1.834h.21c-.21.75-.394 1.37-.55 1.857-.153.485-.28.875-.381 1.172L5.996 13H4.812zm1.593-2.438V9.59h4.483v.973H6.406zm10.237 2.59c-.63 0-1.176-.101-1.641-.304-.461-.204-.822-.487-1.084-.85a2.468 2.468 0 01-.445-1.283h1.142c.031.328.143.6.334.814.192.211.436.37.733.475.3.101.62.152.96.152a2.76 2.76 0 001.061-.193c.317-.129.567-.31.75-.545.184-.234.276-.506.276-.814 0-.282-.08-.51-.24-.686a1.756 1.756 0 00-.628-.434A6.52 6.52 0 0017 9.186l-1.055-.3c-.703-.198-1.25-.484-1.64-.855-.39-.37-.586-.845-.586-1.424 0-.492.133-.921.398-1.289a2.602 2.602 0 011.078-.861c.453-.203.961-.305 1.524-.305.574 0 1.082.102 1.523.305.442.203.79.48 1.043.832.258.348.395.742.41 1.184h-1.09a1.302 1.302 0 00-.609-.985c-.355-.234-.793-.351-1.312-.351-.375 0-.706.062-.99.187-.282.121-.5.29-.657.504-.156.211-.234.453-.234.727 0 .304.093.55.281.738.191.184.416.328.674.434.262.101.498.181.709.24l.873.24c.234.063.492.148.773.258.285.11.557.256.815.44.258.179.468.41.633.69.168.278.252.62.252 1.026 0 .477-.125.906-.375 1.29-.247.382-.606.685-1.079.907-.472.223-1.045.334-1.716.334z"
/>
<rect width="24" height="24" x="0.5" y="1" fill="#fff" rx="12" />
<path
fill="#4B5563"
fillRule="evenodd"
d="M12.5 11.786c1.974 0 3.574-1.63 3.574-3.64 0-2.012-1.6-3.642-3.574-3.642-1.974 0-3.574 1.63-3.574 3.641s1.6 3.641 3.574 3.641zm0 9.71c3.003 0 5.686-1.423 7.434-3.641-1.748-2.219-4.431-3.641-7.434-3.641s-5.686 1.422-7.434 3.64c1.748 2.22 4.431 3.642 7.434 3.642z"
clipRule="evenodd"
/>
<circle cx="4.5" cy="5" r="4" fill="#DC2626" />
</svg>
);
};

export {
Warning,
WarningCircleFill,
Expand Down Expand Up @@ -101,4 +130,7 @@ export {
CalendarCheckFill,
PlugsConnected,
ListDashes,
BellFill,
UserCircle,
Sliders,
} from '@jengaicons/react';
2 changes: 1 addition & 1 deletion src/apps/console/components/types.d.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export type IShowDialog<T = null> = {
export interface IDialog<A = null, T = null> {
show: IShowDialog<A>;
setShow: React.Dispatch<React.SetStateAction<IShowDialog<A>>>;
onSubmit?: (data: T) => void;
onSubmit?: (data: T, extra?: any) => void;
}

// Subheader action types
Expand Down
23 changes: 18 additions & 5 deletions src/apps/console/page-components/app/general.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import { parseName } from '~/console/server/r-utils/common';
import { FadeIn } from '~/console/page-components/util';
import { NameIdView } from '~/console/components/name-id-view';
import { BottomNavigation, GitDetailRaw } from '~/console/components/commons';
import { registryHost } from '~/lib/configs/base-url.cjs';
// import { registryHost } from '~/lib/configs/base-url.cjs';
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (complexity): Consider removing commented-out code and simplifying validation logic.

The new code introduces several complexities that could be avoided:

  1. Commented Out Code: The presence of commented-out code (e.g., RepoSelector) clutters the codebase and can be confusing for future developers. It's better to remove unused code entirely.

  2. Inline Validation: The inline validation for imageUrl using Yup.string().matches() is harder to read, especially with complex regex patterns. Consider simplifying or documenting the regex for clarity.

  3. Redundant Code: The TextInput component for imageUrl is added directly in the JSX, but the commented-out RepoSelector code remains. This makes it unclear whether RepoSelector is intended to be removed or reused.

  4. Error Handling: Error handling for imageUrl is done directly in the JSX, which can be less clear than a more centralized approach.

Consider refactoring to remove unnecessary comments, simplify validation logic, and handle errors more clearly. This will make the code easier to read, understand, and maintain.

import { useOutletContext } from '@remix-run/react';
import RepoSelector from '~/console/page-components/app/components';
// import RepoSelector from '~/console/page-components/app/components';
import AppBuildIntegration from '~/console/page-components/app/app-build-integration';
import { TextInput } from '~/components/atoms/input';
import { useEffect, useState } from 'react';
Expand Down Expand Up @@ -147,7 +147,10 @@ const AppGeneral = ({ mode = 'new' }: { mode: 'edit' | 'new' }) => {
validationSchema: Yup.object({
name: Yup.string().required(),
displayName: Yup.string().required(),
imageUrl: Yup.string(),
imageUrl: Yup.string().matches(
/^\w(\w|[-/])+?(?::(\w|[-])+)?\w$/,
'Invalid image format'
),
manualRepo: Yup.string().when(
['imageUrl', 'imageMode'],
([imageUrl, imageMode], schema) => {
Expand Down Expand Up @@ -377,7 +380,17 @@ const AppGeneral = ({ mode = 'new' }: { mode: 'edit' | 'new' }) => {
size="sm"
/> */}

{values.imageMode === 'default' && (
<TextInput
size="lg"
label="Image name"
placeholder="Enter Image name"
value={values.imageUrl}
onChange={handleChange('imageUrl')}
error={!!errors.imageUrl}
message={errors.imageUrl}
/>

{/* {values.imageMode === 'default' && (
<RepoSelector
tag={values.imageUrl.split(':')[1]}
repo={
Expand Down Expand Up @@ -406,7 +419,7 @@ const AppGeneral = ({ mode = 'new' }: { mode: 'edit' | 'new' }) => {
}}
error={errors.manualRepo}
/>
)}
)} */}

{buildData?.name && values.imageMode === 'git' && !isEdited && (
<GitDetailRaw
Expand Down
27 changes: 25 additions & 2 deletions src/apps/console/routes/_a+/onboarding+/$a+/attach-new-cluster.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useNavigate, useParams } from '@remix-run/react';
import { toast } from '~/components/molecule/toast';
import useForm from '~/root/lib/client/hooks/use-form';
import useForm, { dummyEvent } from '~/root/lib/client/hooks/use-form';
import Yup from '~/root/lib/server/helpers/yup';
import { handleError } from '~/root/lib/utils/common';
import { useConsoleApi } from '~/console/server/gql/api-provider';
Expand All @@ -11,6 +11,8 @@ import MultiStepProgress, {
} from '~/console/components/multi-step-progress';
import { BottomNavigation } from '~/console/components/commons';
import FillerCloudProvider from '~/console/assets/filler-cloud-provider';
import { Checkbox } from '~/components/atoms/checkbox';
import Banner from '~/components/molecule/banner';

const AttachNewCluster = () => {
const { a: accountName } = useParams();
Expand All @@ -21,6 +23,7 @@ const AttachNewCluster = () => {
initialValues: {
name: '',
displayName: '',
visibilityMode: true,
isNameError: false,
},
validationSchema: Yup.object({
Expand All @@ -35,6 +38,9 @@ const AttachNewCluster = () => {
metadata: {
name: val.name,
},
visibility: {
mode: val.visibilityMode ? 'public' : 'private',
},
},
});
if (e) {
Expand Down Expand Up @@ -78,7 +84,7 @@ const AttachNewCluster = () => {
/>
<MultiStepProgress.Step step={2} label="Attach Kubernetes Cluster">
<div className="flex flex-col gap-3xl">
<div className="flex flex-col">
<div className="flex flex-col gap-2xl">
<NameIdView
resType="cluster"
displayName={values.displayName}
Expand All @@ -89,6 +95,23 @@ const AttachNewCluster = () => {
handleChange={handleChange}
nameErrorLabel="isNameError"
/>
<Checkbox
label="Public"
checked={values.visibilityMode}
onChange={(val) => {
handleChange('visibilityMode')(dummyEvent(val));
}}
/>
<Banner
type="info"
body={
<span className="bodyMd-medium">
{values.visibilityMode === true
? 'Public mode assumes cluster is accessible to public internet'
: 'In Private mode traffic is routed via a kloudlite gateway'}
</span>
}
/>
</div>
<BottomNavigation
secondaryButton={{
Expand Down
Loading
Loading