diff --git a/Taskfile.yaml b/Taskfile.yaml index 0ae03f4d6..86c957591 100644 --- a/Taskfile.yaml +++ b/Taskfile.yaml @@ -76,9 +76,7 @@ tasks: - | pnpm gql:parse cd src/generated && pnpm tsgen - - # cd src/generated/plugin && pnpm build - # cd ../ && pnpm tsgen + cd ../.. && pnpm fake storybook: cmds: @@ -96,6 +94,7 @@ tasks: BASE_URL=kloudlite.io URL_SUFFIX="" COOKIE_DOMAIN=".kloudlite.io" + GATEWAY_URL="http://gateway.karthik-testing.svc.cluster.local" case {{.app}} in "auth") @@ -136,7 +135,7 @@ tasks: ;; esac - URL_SUFFIX=$URL_SUFFIX COOKIE_DOMAIN=$COOKIE_DOMAIN BASE_URL=$BASE_URL PORT=$PORT APP={{.app}} pnpm serve + GATEWAY_URL=$GATEWAY_URL URL_SUFFIX=$URL_SUFFIX COOKIE_DOMAIN=$COOKIE_DOMAIN BASE_URL=$BASE_URL PORT=$PORT APP={{.app}} pnpm serve build: preconditions: diff --git a/fake-data-generator/gen.ts b/fake-data-generator/gen.ts index b0629d3bb..71563a97f 100644 --- a/fake-data-generator/gen.ts +++ b/fake-data-generator/gen.ts @@ -82,8 +82,10 @@ global.location = new URL( fs.writeFileSync( './fake-data-generator/fake.js', - `const fake = ${JSON.stringify(data, null, 2)}; - export default fake; -` + `// Generated file, Generated for skeletons + +const fake = ${JSON.stringify(data, null, 2)}; + +export default fake;` ); })(); diff --git a/gql-queries-generator/doc/queries.graphql b/gql-queries-generator/doc/queries.graphql index 94690d833..eeb98ec69 100644 --- a/gql-queries-generator/doc/queries.graphql +++ b/gql-queries-generator/doc/queries.graphql @@ -1242,7 +1242,31 @@ query consoleListRouters($projectName: String!, $envName: String!, $search: Sear projectName recordVersion spec { + backendProtocol + basicAuth { + enabled + secretName + username + } + cors { + allowCredentials + enabled + origins + } domains + https { + clusterIssuer + enabled + forceRedirect + } + ingressClass + maxBodySizeInMB + rateLimit { + connections + enabled + rpm + rps + } routes { app lambda @@ -1368,6 +1392,14 @@ mutation consoleUpdateConfig($projectName: String!, $envName: String!, $config: } } +mutation consoleDeleteConfig($projectName: String!, $envName: String!, $configName: String!) { + core_deleteConfig( + projectName: $projectName + envName: $envName + configName: $configName + ) +} + query consoleGetConfig($projectName: String!, $envName: String!, $name: String!) { core_getConfig(projectName: $projectName, envName: $envName, name: $name) { binaryData @@ -2814,6 +2846,7 @@ query consoleListBuildRuns($repoName: String!, $search: SearchBuildRuns, $pq: Cu edges { cursor node { + id clusterName creationTime markedForDeletion @@ -3671,7 +3704,7 @@ query consoleListConsoleVpnDevices($search: CoreSearchVPNDevices, $pq: CursorPag host target } - deviceNamespace + activeNamespace disabled nodeSelector ports { @@ -3707,7 +3740,7 @@ query consoleGetConsoleVpnDevice($name: String!) { host target } - deviceNamespace + activeNamespace disabled nodeSelector ports { @@ -3758,7 +3791,7 @@ query consoleListConsoleVpnDevicesForUser { host target } - deviceNamespace + activeNamespace disabled nodeSelector ports { @@ -3778,13 +3811,85 @@ mutation consoleDeleteConsoleVpnDevice($deviceName: String!) { core_deleteVPNDevice(deviceName: $deviceName) } -query authCli_CoreCheckNameAvailability($resType: ConsoleResType!, $name: String!) { - core_checkNameAvailability(resType: $resType, name: $name) { - result - suggestedNames +mutation consoleCreateImagePullSecret($projectName: String!, $envName: String!, $imagePullSecretIn: ImagePullSecretIn!) { + core_createImagePullSecret( + projectName: $projectName + envName: $envName + imagePullSecretIn: $imagePullSecretIn + ) { + id } } +query consoleListImagePullSecrets($projectName: String!, $envName: String!, $search: SearchImagePullSecrets, $pq: CursorPaginationIn) { + core_listImagePullSecrets( + projectName: $projectName + envName: $envName + search: $search + pq: $pq + ) { + edges { + cursor + node { + createdBy { + userEmail + userId + userName + } + creationTime + displayName + dockerConfigJson + environmentName + format + lastUpdatedBy { + userEmail + userId + userName + } + markedForDeletion + metadata { + generation + name + namespace + } + projectName + recordVersion + registryPassword + registryURL + registryUsername + syncStatus { + action + error + lastSyncedAt + recordVersion + state + syncScheduledAt + } + updateTime + } + } + pageInfo { + endCursor + hasNextPage + hasPreviousPage + startCursor + } + totalCount + } +} + +mutation authCli_CoreUpdateDevicePorts($deviceName: String!, $ports: [PortIn!]!) { + core_updateVPNDevicePorts(deviceName: $deviceName, ports: $ports) +} + +mutation authCli_CoreUpdateDeviceEnv($deviceName: String!, $projectName: String!, $envName: String!) { + core_updateVPNDeviceEnv( + deviceName: $deviceName + projectName: $projectName + envName: $envName + ) +} + query authCli_listCoreDevices { core_listVPNDevicesForUser { displayName @@ -3804,7 +3909,7 @@ query authCli_listCoreDevices { host target } - deviceNamespace + activeNamespace disabled ports { port @@ -3822,7 +3927,7 @@ query authCli_getCoreDevice($name: String!) { } projectName spec { - deviceNamespace + activeNamespace disabled ports { port @@ -3838,7 +3943,13 @@ query authCli_getCoreDevice($name: String!) { mutation authCli_createCoreDevice($vpnDevice: ConsoleVPNDeviceIn!) { core_createVPNDevice(vpnDevice: $vpnDevice) { - id + metadata { + name + } + wireguardConfig { + encoding + value + } } } @@ -3846,6 +3957,127 @@ mutation authCli_updateCoreDevicePorts($deviceName: String!, $ports: [PortIn!]!) core_updateVPNDevicePorts(deviceName: $deviceName, ports: $ports) } +query authCli_getDevice($clusterName: String!, $name: String!) { + infra_getVPNDevice(clusterName: $clusterName, name: $name) { + displayName + markedForDeletion + metadata { + name + namespace + } + spec { + cnameRecords { + host + target + } + activeNamespace + nodeSelector + ports { + port + targetPort + } + } + status { + isReady + message { + RawMessage + } + } + wireguardConfig { + encoding + value + } + } +} + +query authCli_listDevices($pq: CursorPaginationIn, $clusterName: String) { + infra_listVPNDevices(clusterName: $clusterName, pq: $pq) { + edges { + node { + displayName + metadata { + name + } + spec { + activeNamespace + disabled + nodeSelector + ports { + port + targetPort + } + } + status { + isReady + message { + RawMessage + } + } + wireguardConfig { + encoding + value + } + } + } + } +} + +mutation authCli_updateDevice($clusterName: String!, $vpnDevice: VPNDeviceIn!) { + infra_updateVPNDevice(clusterName: $clusterName, vpnDevice: $vpnDevice) { + metadata { + name + } + spec { + activeNamespace + cnameRecords { + target + host + } + ports { + targetPort + port + } + } + status { + message { + RawMessage + } + isReady + } + } +} + +mutation authCli_updateDevicePort($clusterName: String!, $deviceName: String!, $ports: [PortIn!]!) { + infra_updateVPNDevicePorts( + clusterName: $clusterName + deviceName: $deviceName + ports: $ports + ) +} + +mutation authCli_updateDeviceNs($clusterName: String!, $deviceName: String!, $namespace: String!) { + infra_updateVPNDeviceNs( + clusterName: $clusterName + deviceName: $deviceName + namespace: $namespace + ) +} + +mutation authCli_createDevice($clusterName: String!, $vpnDevice: VPNDeviceIn!) { + infra_createVPNDevice(clusterName: $clusterName, vpnDevice: $vpnDevice) { + metadata { + name + } + } +} + +query authCli_CoreCheckNameAvailability($resType: ConsoleResType!, $name: String!) { + core_checkNameAvailability(resType: $resType, name: $name) { + result + suggestedNames + } +} + query authCli_getMresKeys($projectName: String!, $envName: String!, $name: String!) { core_getManagedResouceOutputKeys( projectName: $projectName @@ -3891,15 +4123,7 @@ query authCli_infraCheckNameAvailability($resType: ResType!, $name: String!, $cl } } -mutation authCli_createDevice($clusterName: String!, $vpnDevice: VPNDeviceIn!) { - infra_createVPNDevice(clusterName: $clusterName, vpnDevice: $vpnDevice) { - metadata { - name - } - } -} - -query authCli_getConfigSecretMap($projectName: String!, $envName: String!, $configQueries: [ConfigKeyRefIn], $secretQueries: [SecretKeyRefIn!]) { +query authCli_getConfigSecretMap($projectName: String!, $envName: String!, $configQueries: [ConfigKeyRefIn], $secretQueries: [SecretKeyRefIn!], $mresQueries: [ManagedResourceKeyRefIn]) { configs: core_getConfigValues( projectName: $projectName envName: $envName @@ -3918,6 +4142,15 @@ query authCli_getConfigSecretMap($projectName: String!, $envName: String!, $conf secretName value } + mreses: core_getManagedResouceOutputKeyValues( + keyrefs: $mresQueries + envName: $envName + projectName: $projectName + ) { + key + mresName + value + } } mutation authCli_interceptApp($projectName: String!, $envName: String!, $appname: String!, $deviceName: String!, $intercept: Boolean!) { @@ -3938,22 +4171,6 @@ query authCli_getEnvironment($projectName: String!, $name: String!) { } } -mutation authCli_updateDeviceNs($clusterName: String!, $deviceName: String!, $namespace: String!) { - infra_updateVPNDeviceNs( - clusterName: $clusterName - deviceName: $deviceName - namespace: $namespace - ) -} - -mutation authCli_updateDevicePort($clusterName: String!, $deviceName: String!, $ports: [PortIn!]!) { - infra_updateVPNDevicePorts( - clusterName: $clusterName - deviceName: $deviceName - ports: $ports - ) -} - query authCli_getSecret($projectName: String!, $envName: String!, $name: String!) { core_getSecret(projectName: $projectName, envName: $envName, name: $name) { displayName @@ -4159,96 +4376,6 @@ query authCli_listSecrets($projectName: String!, $envName: String!, $pq: CursorP } } -mutation authCli_updateDevice($clusterName: String!, $vpnDevice: VPNDeviceIn!) { - infra_updateVPNDevice(clusterName: $clusterName, vpnDevice: $vpnDevice) { - metadata { - name - } - spec { - deviceNamespace - cnameRecords { - target - host - } - ports { - targetPort - port - } - } - status { - message { - RawMessage - } - isReady - } - } -} - -query authCli_listDevices($pq: CursorPaginationIn) { - infra_listVPNDevices(pq: $pq) { - edges { - node { - displayName - metadata { - name - } - spec { - deviceNamespace - disabled - nodeSelector - ports { - port - targetPort - } - } - status { - isReady - message { - RawMessage - } - } - wireguardConfig { - encoding - value - } - } - } - } -} - -query authCli_getDevice($clusterName: String!, $name: String!) { - infra_getVPNDevice(clusterName: $clusterName, name: $name) { - displayName - markedForDeletion - metadata { - name - namespace - } - spec { - cnameRecords { - host - target - } - deviceNamespace - nodeSelector - ports { - port - targetPort - } - } - status { - isReady - message { - RawMessage - } - } - wireguardConfig { - encoding - value - } - } -} - query authCli_listEnvironments($projectName: String!, $pq: CursorPaginationIn) { core_listEnvironments(projectName: $projectName, pq: $pq) { edges { diff --git a/src/apps/auth/routes/_providers+/_layout.tsx b/src/apps/auth/routes/_providers+/_layout.tsx index bdcc19e49..18cd857b8 100644 --- a/src/apps/auth/routes/_providers+/_layout.tsx +++ b/src/apps/auth/routes/_providers+/_layout.tsx @@ -28,14 +28,6 @@ export const restActions = async (ctx: IRemixCtx) => { logger.error(checkError); } - if (checkData.find((v) => !v.enabled)) { - return { - githubLoginUrl: '', - gitlabLoginUrl: '', - googleLoginUrl: '', - }; - } - const { data, errors } = await GQLServerHandler( ctx.request ).loginPageInitUrls(); @@ -51,9 +43,15 @@ export const restActions = async (ctx: IRemixCtx) => { } = data || {}; return { - githubLoginUrl, - gitlabLoginUrl, - googleLoginUrl, + githubLoginUrl: checkData.find((v) => v.provider === 'github' && !v.enabled) + ? '' + : githubLoginUrl, + gitlabLoginUrl: checkData.find((v) => v.provider === 'gitlab' && !v.enabled) + ? '' + : gitlabLoginUrl, + googleLoginUrl: checkData.find((v) => v.provider === 'google' && !v.enabled) + ? '' + : googleLoginUrl, }; }; diff --git a/src/apps/auth/server/gql/cli-queries.ts b/src/apps/auth/server/gql/cli-queries.ts index f56cee3cb..a060711e6 100644 --- a/src/apps/auth/server/gql/cli-queries.ts +++ b/src/apps/auth/server/gql/cli-queries.ts @@ -2,8 +2,10 @@ import gql from 'graphql-tag'; import { IExecutor } from '~/root/lib/server/helpers/execute-query-with-context'; import { infraQueries } from './queries/infra-queries'; +import { vpnQueries } from './queries/device-queries'; export const cliQueries = (executor: IExecutor) => ({ + ...vpnQueries(executor), ...infraQueries(executor), cli_getMresKeys: executor( gql` @@ -101,27 +103,6 @@ export const cliQueries = (executor: IExecutor) => ({ vars: (_: any) => {}, } ), - cli_createDevice: executor( - gql` - mutation Infra_createVPNDevice( - $clusterName: String! - $vpnDevice: VPNDeviceIn! - ) { - infra_createVPNDevice( - clusterName: $clusterName - vpnDevice: $vpnDevice - ) { - metadata { - name - } - } - } - `, - { - transformer: (data: any) => data.infra_createVPNDevice, - vars: (_: any) => {}, - } - ), cli_getConfigSecretMap: executor( gql` @@ -130,6 +111,7 @@ export const cliQueries = (executor: IExecutor) => ({ $envName: String! $configQueries: [ConfigKeyRefIn] $secretQueries: [SecretKeyRefIn!] + $mresQueries: [ManagedResourceKeyRefIn] ) { configs: core_getConfigValues( projectName: $projectName @@ -149,6 +131,15 @@ export const cliQueries = (executor: IExecutor) => ({ secretName value } + mreses: core_getManagedResouceOutputKeyValues( + keyrefs: $mresQueries + envName: $envName + projectName: $projectName + ) { + key + mresName + value + } } `, { @@ -156,9 +147,9 @@ export const cliQueries = (executor: IExecutor) => ({ return { configs: data.configs, secrets: data.secrets, + mreses: data.mreses, }; }, - vars: (_: any) => {}, } ), @@ -200,44 +191,6 @@ export const cliQueries = (executor: IExecutor) => ({ vars: (_: any) => {}, } ), - cli_updateDeviceNs: executor( - gql` - mutation Infra_updateVPNDeviceNs( - $clusterName: String! - $deviceName: String! - $namespace: String! - ) { - infra_updateVPNDeviceNs( - clusterName: $clusterName - deviceName: $deviceName - namespace: $namespace - ) - } - `, - { - transformer: (data: any) => data.infra_updateVPNDeviceNs, - vars: (_: any) => {}, - } - ), - cli_updateDevicePort: executor( - gql` - mutation Mutation( - $clusterName: String! - $deviceName: String! - $ports: [PortIn!]! - ) { - infra_updateVPNDevicePorts( - clusterName: $clusterName - deviceName: $deviceName - ports: $ports - ) - } - `, - { - transformer: (data: any) => data.infra_updateVPNDevicePorts, - vars: (_: any) => {}, - } - ), cli_getSecret: executor( gql` query Core_getSecret( @@ -503,121 +456,6 @@ export const cliQueries = (executor: IExecutor) => ({ vars: (_: any) => {}, } ), - cli_updateDevice: executor( - gql` - mutation Mutation($clusterName: String!, $vpnDevice: VPNDeviceIn!) { - infra_updateVPNDevice( - clusterName: $clusterName - vpnDevice: $vpnDevice - ) { - metadata { - name - } - spec { - deviceNamespace - cnameRecords { - target - host - } - ports { - targetPort - port - } - } - status { - message { - RawMessage - } - isReady - } - } - } - `, - { - transformer: (data: any) => data.infra_updateVPNDevice, - vars: (_: any) => {}, - } - ), - cli_listDevices: executor( - gql` - query Infra_listVPNDevices($pq: CursorPaginationIn) { - infra_listVPNDevices(pq: $pq) { - edges { - node { - displayName - metadata { - name - } - spec { - deviceNamespace - disabled - nodeSelector - ports { - port - targetPort - } - } - status { - isReady - message { - RawMessage - } - } - wireguardConfig { - encoding - value - } - } - } - } - } - `, - { - transformer: (data: any) => data.infra_listVPNDevices, - vars: (_: any) => {}, - } - ), - - cli_getDevice: executor( - gql` - query Infra_getVPNDevice($clusterName: String!, $name: String!) { - infra_getVPNDevice(clusterName: $clusterName, name: $name) { - displayName - markedForDeletion - metadata { - name - namespace - } - spec { - cnameRecords { - host - target - } - deviceNamespace - nodeSelector - ports { - port - targetPort - } - } - status { - isReady - message { - RawMessage - } - } - wireguardConfig { - encoding - value - } - } - } - `, - { - transformer: (data: any) => data.infra_getVPNDevice, - vars: (_: any) => {}, - } - ), cli_listEnvironments: executor( gql` diff --git a/src/apps/auth/server/gql/queries/device-queries.ts b/src/apps/auth/server/gql/queries/device-queries.ts new file mode 100644 index 000000000..d7bca0a14 --- /dev/null +++ b/src/apps/auth/server/gql/queries/device-queries.ts @@ -0,0 +1,315 @@ +import gql from 'graphql-tag'; +import { IExecutor } from '~/root/lib/server/helpers/execute-query-with-context'; + +export const vpnQueries = (executor: IExecutor) => ({ + cli_CoreUpdateDevicePorts: executor( + gql` + mutation Core_updateVPNDevicePorts( + $deviceName: String! + $ports: [PortIn!]! + ) { + core_updateVPNDevicePorts(deviceName: $deviceName, ports: $ports) + } + `, + { + transformer: (data: any) => data.core_updateVPNDevicePorts, + vars: (_: any) => {}, + } + ), + cli_CoreUpdateDeviceEnv: executor( + gql` + mutation Core_updateVPNDeviceEnv( + $deviceName: String! + $projectName: String! + $envName: String! + ) { + core_updateVPNDeviceEnv( + deviceName: $deviceName + projectName: $projectName + envName: $envName + ) + } + `, + { + transformer: (data: any) => data.core_updateVPNDeviceEnv, + vars: (_: any) => {}, + } + ), + + cli_listCoreDevices: executor( + gql` + query Core_listVPNDevicesForUser { + core_listVPNDevicesForUser { + displayName + environmentName + metadata { + name + } + projectName + status { + isReady + message { + RawMessage + } + } + spec { + cnameRecords { + host + target + } + activeNamespace + disabled + ports { + port + targetPort + } + } + } + } + `, + { + transformer: (data: any) => data.core_listVPNDevicesForUser, + vars: (_: any) => {}, + } + ), + cli_getCoreDevice: executor( + gql` + query Core_getVPNDevice($name: String!) { + core_getVPNDevice(name: $name) { + displayName + metadata { + name + } + projectName + spec { + activeNamespace + disabled + ports { + port + targetPort + } + } + wireguardConfig { + encoding + value + } + } + } + `, + { + transformer: (data: any) => data.core_getVPNDevice, + vars: (_: any) => {}, + } + ), + cli_createCoreDevice: executor( + gql` + mutation Core_createVPNDevice($vpnDevice: ConsoleVPNDeviceIn!) { + core_createVPNDevice(vpnDevice: $vpnDevice) { + metadata { + name + } + wireguardConfig { + encoding + value + } + } + } + `, + { + transformer: (data: any) => data.core_createVPNDevice, + vars: (_: any) => {}, + } + ), + + cli_updateCoreDevicePorts: executor( + gql` + mutation Mutation($deviceName: String!, $ports: [PortIn!]!) { + core_updateVPNDevicePorts(deviceName: $deviceName, ports: $ports) + } + `, + { + transformer: (data: any) => data.core_updateVPNDevicePorts, + vars: (_: any) => {}, + } + ), + + cli_getDevice: executor( + gql` + query Infra_getVPNDevice($clusterName: String!, $name: String!) { + infra_getVPNDevice(clusterName: $clusterName, name: $name) { + displayName + markedForDeletion + metadata { + name + namespace + } + spec { + cnameRecords { + host + target + } + activeNamespace + nodeSelector + ports { + port + targetPort + } + } + status { + isReady + message { + RawMessage + } + } + wireguardConfig { + encoding + value + } + } + } + `, + { + transformer: (data: any) => data.infra_getVPNDevice, + vars: (_: any) => {}, + } + ), + + cli_listDevices: executor( + gql` + query Infra_listVPNDevices( + $pq: CursorPaginationIn + $clusterName: String + ) { + infra_listVPNDevices(clusterName: $clusterName, pq: $pq) { + edges { + node { + displayName + metadata { + name + } + spec { + activeNamespace + disabled + nodeSelector + ports { + port + targetPort + } + } + status { + isReady + message { + RawMessage + } + } + wireguardConfig { + encoding + value + } + } + } + } + } + `, + { + transformer: (data: any) => data.infra_listVPNDevices, + vars: (_: any) => {}, + } + ), + + cli_updateDevice: executor( + gql` + mutation Mutation($clusterName: String!, $vpnDevice: VPNDeviceIn!) { + infra_updateVPNDevice( + clusterName: $clusterName + vpnDevice: $vpnDevice + ) { + metadata { + name + } + spec { + activeNamespace + cnameRecords { + target + host + } + ports { + targetPort + port + } + } + status { + message { + RawMessage + } + isReady + } + } + } + `, + { + transformer: (data: any) => data.infra_updateVPNDevice, + vars: (_: any) => {}, + } + ), + + cli_updateDevicePort: executor( + gql` + mutation Mutation( + $clusterName: String! + $deviceName: String! + $ports: [PortIn!]! + ) { + infra_updateVPNDevicePorts( + clusterName: $clusterName + deviceName: $deviceName + ports: $ports + ) + } + `, + { + transformer: (data: any) => data.infra_updateVPNDevicePorts, + vars: (_: any) => {}, + } + ), + cli_updateDeviceNs: executor( + gql` + mutation Infra_updateVPNDeviceNs( + $clusterName: String! + $deviceName: String! + $namespace: String! + ) { + infra_updateVPNDeviceNs( + clusterName: $clusterName + deviceName: $deviceName + namespace: $namespace + ) + } + `, + { + transformer: (data: any) => data.infra_updateVPNDeviceNs, + vars: (_: any) => {}, + } + ), + cli_createDevice: executor( + gql` + mutation Infra_createVPNDevice( + $clusterName: String! + $vpnDevice: VPNDeviceIn! + ) { + infra_createVPNDevice( + clusterName: $clusterName + vpnDevice: $vpnDevice + ) { + metadata { + name + } + } + } + `, + { + transformer: (data: any) => data.infra_createVPNDevice, + vars: (_: any) => {}, + } + ), +}); diff --git a/src/apps/auth/server/gql/queries/infra-queries.ts b/src/apps/auth/server/gql/queries/infra-queries.ts index 9942877e1..a53ea1479 100644 --- a/src/apps/auth/server/gql/queries/infra-queries.ts +++ b/src/apps/auth/server/gql/queries/infra-queries.ts @@ -19,94 +19,4 @@ export const infraQueries = (executor: IExecutor) => ({ vars: (_: any) => {}, } ), - cli_listCoreDevices: executor( - gql` - query Core_listVPNDevicesForUser { - core_listVPNDevicesForUser { - displayName - environmentName - metadata { - name - } - projectName - status { - isReady - message { - RawMessage - } - } - spec { - cnameRecords { - host - target - } - deviceNamespace - disabled - ports { - port - targetPort - } - } - } - } - `, - { - transformer: (data: any) => data.core_listVPNDevicesForUser, - vars: (_: any) => {}, - } - ), - cli_getCoreDevice: executor( - gql` - query Core_getVPNDevice($name: String!) { - core_getVPNDevice(name: $name) { - displayName - metadata { - name - } - projectName - spec { - deviceNamespace - disabled - ports { - port - targetPort - } - } - wireguardConfig { - encoding - value - } - } - } - `, - { - transformer: (data: any) => data.core_getVPNDevice, - vars: (_: any) => {}, - } - ), - cli_createCoreDevice: executor( - gql` - mutation Core_createVPNDevice($vpnDevice: ConsoleVPNDeviceIn!) { - core_createVPNDevice(vpnDevice: $vpnDevice) { - id - } - } - `, - { - transformer: (data: any) => data.core_createVPNDevice, - vars: (_: any) => {}, - } - ), - - cli_updateCoreDevicePorts: executor( - gql` - mutation Mutation($deviceName: String!, $ports: [PortIn!]!) { - core_updateVPNDevicePorts(deviceName: $deviceName, ports: $ports) - } - `, - { - transformer: (data: any) => data.core_updateVPNDevicePorts, - vars: (_: any) => {}, - } - ), }); diff --git a/src/apps/console/components/color-generator.tsx b/src/apps/console/components/color-generator.tsx index 600457511..ed534eadf 100644 --- a/src/apps/console/components/color-generator.tsx +++ b/src/apps/console/components/color-generator.tsx @@ -69,4 +69,8 @@ const generateColor = (str = '#', contrast: Contrast = 'dark') => { )}, ${generateColorFromName(`${str + str + str}`, cc, contrast)})`; }; +export const generatePlainColor = (str = '#') => { + const cc = colorCode(str); + return generateColorFromName(str, cc, 'dark'); +}; export default generateColor; diff --git a/src/apps/console/components/console-list-components.tsx b/src/apps/console/components/console-list-components.tsx index 464f75cb7..7135a10d0 100644 --- a/src/apps/console/components/console-list-components.tsx +++ b/src/apps/console/components/console-list-components.tsx @@ -109,6 +109,7 @@ const ListTitle = ({ {title && (
{title}
} > @@ -135,13 +136,8 @@ const listFlex = ({ key }: { key: string }) => ({ render: () =>
, }); -const listTitleClass = 'w-[180px] min-w-[180px] max-w-[180px] mr-2xl'; - -export { - ListBody, - ListItem, - ListTitle, - ListSecondary, - listFlex, - listTitleClass, +const listClass = { + title: 'w-[180px] min-w-[180px] max-w-[180px] mr-2xl', + author: 'w-[180px] min-w-[180px] max-w-[180px]', }; +export { ListBody, ListItem, ListTitle, ListSecondary, listFlex, listClass }; diff --git a/src/apps/console/components/git-repo-selector.tsx b/src/apps/console/components/git-repo-selector.tsx index 8ed495cf7..27410e2fc 100644 --- a/src/apps/console/components/git-repo-selector.tsx +++ b/src/apps/console/components/git-repo-selector.tsx @@ -1,37 +1,30 @@ import { CircleFill, - GitBranch, GithubLogoFill, GitlabLogoFill, ListBullets, LockSimple, LockSimpleOpen, - Pencil, Plus, Search, } from '@jengaicons/react'; import { AnimatePresence, motion } from 'framer-motion'; -import { useEffect, useState } from 'react'; +import { useCallback, useEffect, useState } from 'react'; import { Button } from '~/components/atoms/button'; import { TextInput } from '~/components/atoms/input'; import Select from '~/components/atoms/select'; import { dayjs } from '~/components/molecule/dayjs'; -import { generateKey } from '~/components/utils'; import useCustomSwr from '~/root/lib/client/hooks/use-custom-swr'; -import useForm, { dummyEvent } from '~/root/lib/client/hooks/use-form'; import { githubAppName } from '~/root/lib/configs/base-url.cjs'; -import Yup from '~/root/lib/server/helpers/yup'; import { SWRResponse } from 'swr'; -import ButtonGroup from '~/components/atoms/button-group'; +import Radio from '~/components/atoms/radio'; import { useConsoleApi } from '../server/gql/api-provider'; import { IGithubInstallations, IGitlabGroups, } from '../server/gql/queries/git-queries'; -import { DIALOG_TYPE, popupWindow } from '../utils/commons'; -import List from './list'; +import { popupWindow } from '../utils/commons'; import Pulsable from './pulsable'; -import { IDialog, IShowDialog } from './types.d'; const ADD_GITHUB_ACCOUNT_VALUE = 'add-github-account'; const SWITCH_GIT_PROVIDER_VALUE = 'switch-git-provider'; @@ -161,159 +154,18 @@ const useGitlabProvider = ({ }; interface IBranch { repo: string; - branch: string | null | undefined; + branch: string; provider: 'github' | 'gitlab'; } -const BranchChooser = ({ - show, - setShow, - onSubmit, -}: IDialog) => { - const [fetchedBranches, setFetchedBranches] = useState< - { label: string; value: string }[] - >([]); - const { setRepoUrl: setGithubRepoUrl, branches: githubBrances } = - useGithubProvider({ - fetchInstallations: false, - }); - - const { setRepId: setGitlabRepoUrl, branches: gitlabBrances } = - useGitlabProvider({ fetchGroups: false }); - - const [selectedBranch, setSelectedBranch] = useState< - (typeof fetchedBranches)[number] | undefined - >(); - - const onClose = (e: any) => { - setSelectedBranch(undefined); - setShow(e); - }; - - const { errors, handleChange, resetValues, setValues, submit } = useForm({ - initialValues: { - branch: '', - }, - validationSchema: Yup.object({ - branch: Yup.string().required(), - }), - onSubmit: async () => { - if (selectedBranch && show?.data?.repo) { - onSubmit?.({ - branch: selectedBranch.value, - repo: show?.data?.repo, - provider: show.data.provider, - }); - resetValues(); - onClose(null); - } - }, - }); - - useEffect(() => { - if (show) { - switch (show.data?.provider) { - case 'github': - setGithubRepoUrl(show.data?.repo ? show.data.repo : null); - break; - case 'gitlab': - setGitlabRepoUrl(show.data?.repo ? show.data.repo : null); - break; - default: - break; - } - if (show.data?.branch) { - setSelectedBranch({ - label: show?.data?.branch, - value: show?.data?.branch, - }); - setValues({ branch: show.data.branch }); - } - } - }, [show]); - - useEffect(() => { - if (show?.data) { - switch (show.data.provider) { - case 'github': - setFetchedBranches( - githubBrances.data?.map((gb) => ({ - label: gb.name || '', - value: gb.name || '', - })) || [] - ); - break; - case 'gitlab': - setFetchedBranches( - gitlabBrances.data?.map((gb) => ({ - label: gb.name || '', - value: gb.name || '', - })) || [] - ); - break; - default: - setFetchedBranches([]); - break; - } - } else { - setFetchedBranches([]); - } - }, [githubBrances.data, gitlabBrances.data]); - - return ( - -
- options} + value={selectedAccount} + onChange={(res) => { + if ( + ![ + ADD_GITHUB_ACCOUNT_VALUE, + SWITCH_GIT_PROVIDER_VALUE, + ].includes(res.value) + ) { + setRepo(''); + setSelectedAccount(res); + switch (provider) { + case 'github': + setOrganization(res.label); + break; + case 'gitlab': + setGroupId(res.value); + break; + default: + break; + } + } else if (res.value === SWITCH_GIT_PROVIDER_VALUE) { + setProviderSwitch(true); + } else if (res.value === ADD_GITHUB_ACCOUNT_VALUE) { + popupWindow({ + url: githubInstallUrl, + }); + } + }} + /> +
+
-
-
-
- -
- + ( + (provider === 'github' ? githubBranches : gitlabBranches) + .data || [] + )?.map((d) => ({ label: d.name || '', value: d.name || '' })) + } + onChange={({ value }) => { + setSelectedBranch({ branch: value, provider, repo }); + onChange?.({ branch: value, provider, repo }); }} + error={!!error} + message={error} /> - - {showProviderSwitch && ( - -
- Select a Git provider to import an existing project from a - Git Repository. -
-
-
-
- )} -
-
- )} - - {showBranchChooser && ( - { - setSelectedBranch(val); - onChange?.(val); - }} - /> - )} - + +
+
); }; diff --git a/src/apps/console/components/key-value-pair.tsx b/src/apps/console/components/key-value-pair.tsx index 72c8843d4..1d329a3f9 100644 --- a/src/apps/console/components/key-value-pair.tsx +++ b/src/apps/console/components/key-value-pair.tsx @@ -14,6 +14,7 @@ interface IKeyValuePair { label?: ReactNode; message?: ReactNode; error?: boolean; + size?: 'lg' | 'md'; } const KeyValuePair = ({ onChange, @@ -21,6 +22,7 @@ const KeyValuePair = ({ label, message, error, + size, }: IKeyValuePair) => { const newItem = [{ key: '', value: '', id: uuid() }]; const [items, setItems] = useState>>(newItem); @@ -66,9 +68,10 @@ const KeyValuePair = ({ {label} )} {items.map((item) => ( -
+
- } - variant="plain" - disabled={items.length < 2} - onClick={() => { - setItems(items.filter((i) => i.id !== item.id)); - }} - /> +
+ } + variant="plain" + disabled={items.length < 2} + onClick={() => { + setItems(items.filter((i) => i.id !== item.id)); + }} + /> +
))}
diff --git a/src/apps/console/components/logger.tsx b/src/apps/console/components/logger.tsx index ef363ace0..f62a8cf0f 100644 --- a/src/apps/console/components/logger.tsx +++ b/src/apps/console/components/logger.tsx @@ -14,9 +14,8 @@ import { useSearch, } from '~/root/lib/client/helpers/search-filter'; import useClass from '~/root/lib/client/hooks/use-class'; -import logger from '~/root/lib/client/helpers/log'; import { socketUrl } from '~/root/lib/configs/base-url.cjs'; -import generateColor from './color-generator'; +import { generatePlainColor } from './color-generator'; import Pulsable from './pulsable'; import { logsMockData } from '../dummy/data'; @@ -331,8 +330,9 @@ const LogLine = ({
+
{ + console.log('data', ref.current); + (async () => { if (follow && ref.current) { // @ts-ignore - ref.current.scrollTo(0, ref.current.scrollHeight); + ref.current.scrollToIndex({ + index: data.length - 1, + }); } })(); }, [data, maxLines]); @@ -469,11 +475,15 @@ const LogBlock = ({ >
- + {(log, index) => { return ( { }; w.onopen = () => { + // console.log('socket connected'); res(w); }; w.onerror = (e) => { + console.error(e); rej(e); }; w.onclose = () => { // wsclient.send(newMessage({ event: 'unsubscribe', data: 'test' })); - logger.log('socket disconnected'); + // logger.log('socket disconnected'); }; } catch (e) { rej(e); @@ -633,6 +645,7 @@ const useSocketLogs = ({ url, account, cluster, trackingId }: IuseLog) => { setIsLoading(true); const client = await wsclient; + console.log('client', client); setSocState(client); diff --git a/src/apps/console/components/multi-step-progress-wrapper.tsx b/src/apps/console/components/multi-step-progress-wrapper.tsx new file mode 100644 index 000000000..6798fa0fc --- /dev/null +++ b/src/apps/console/components/multi-step-progress-wrapper.tsx @@ -0,0 +1,55 @@ +import { ArrowLeft } from '@jengaicons/react'; +import { Link } from '@remix-run/react'; +import { ReactNode } from 'react'; +import { Button } from '~/components/atoms/button'; + +type ITitleSection = { + title: ReactNode; + subTitle: ReactNode; +}; +const TitleSection = ({ title, subTitle }: ITitleSection) => { + return ( +
+
{title}
+
{subTitle}
+
+
+ ); +}; + +interface IProgressWrapper extends ITitleSection { + children: ReactNode; + backButton?: { + to: string; + content: string; + }; +} +const MultiStepProgressWrapper = ({ + subTitle, + title, + children, + backButton, +}: IProgressWrapper) => { + return ( +
+
+
+ {backButton && ( +
+ {children} +
+
+ ); +}; + +export default MultiStepProgressWrapper; diff --git a/src/apps/console/components/multi-step-progress.tsx b/src/apps/console/components/multi-step-progress.tsx new file mode 100644 index 000000000..62d488885 --- /dev/null +++ b/src/apps/console/components/multi-step-progress.tsx @@ -0,0 +1,174 @@ +import { Check } from '@jengaicons/react'; +import React, { + Children, + ReactElement, + ReactNode, + useRef, + useState, +} from 'react'; +import { cn } from '~/components/utils'; + +interface IUseMultiStepProgress { + defaultStep: number; + totalSteps: number; +} +export const useMultiStepProgress = ({ + defaultStep = 1, + totalSteps = 1, +}: IUseMultiStepProgress) => { + const [currentIndex, setCurrentIndex] = useState(defaultStep); + + const nextStep = () => { + if (currentIndex < totalSteps) { + setCurrentIndex((prev) => prev + 1); + } + }; + const prevStep = () => { + if (currentIndex > 1) { + setCurrentIndex((prev) => prev - 1); + } + }; + + const jumpStep = (step: number) => { + setCurrentIndex(step); + }; + + const reset = () => { + setCurrentIndex(1); + }; + return { currentStep: currentIndex, nextStep, prevStep, reset, jumpStep }; +}; + +type IProgressTrackerItem = { + active?: boolean; + completed?: boolean; + label: ReactNode; + children?: ReactNode; + onClick?: () => void; + hasBorder: boolean; + index: number; + noJump?: boolean; +}; + +function ProgressTrackerItem( + props: IProgressTrackerItem & { children?: ReactNode } +) { + const { + children, + active = false, + completed = false, + label, + onClick, + hasBorder, + index, + noJump, + } = props; + + return ( +
+
+ + + {label} + +
+
{children}
+
+ ); +} + +interface IStep { + children?: ReactNode; + label: ReactNode; + step: number; + className?: string; +} +const Step = ({ children, step, className, label: _label }: IStep) => { + return ( +
+ {children} +
+ ); +}; + +interface IMultiStepProgress { + children: ReactElement | ReactElement[]; + currentStep: number; + jumpStep: (step: number) => void; + noJump?: boolean; +} +const Root = ({ + children, + currentStep, + jumpStep, + noJump, +}: IMultiStepProgress) => { + let child = children; + // @ts-ignore + if (child.type === React.Fragment) { + // @ts-ignore + child = child.props.children; + } + + return ( +
+ {Children.map(child, (ch, index) => { + return ( + { + if (index + 1 < currentStep) { + if (!noJump) { + jumpStep(index + 1); + } + } + }} + > + {currentStep === ch.props.step ? ( +
{ch.props.children}
+ ) : null} +
+ ); + })} +
+ ); +}; + +const MultiStepProgress = { + Root, + Step, +}; + +export default MultiStepProgress; diff --git a/src/apps/console/components/raw-wrapper.tsx b/src/apps/console/components/raw-wrapper.tsx index 38cd27d24..156cbc6cd 100644 --- a/src/apps/console/components/raw-wrapper.tsx +++ b/src/apps/console/components/raw-wrapper.tsx @@ -89,13 +89,13 @@ function RawWrapper({ } interface ITitleBox { - title: ReactNode; - subtitle: ReactNode; + title?: ReactNode; + subtitle?: ReactNode; } export const TitleBox = ({ title, subtitle }: ITitleBox) => { return (
-
{title}
+ {title &&
{title}
} {subtitle &&
{subtitle}
}
); diff --git a/src/apps/console/components/wip.tsx b/src/apps/console/components/wip.tsx index b248e076d..2d8b39f2b 100644 --- a/src/apps/console/components/wip.tsx +++ b/src/apps/console/components/wip.tsx @@ -4,7 +4,7 @@ import { EmptyState } from '~/console/components/empty-state'; const Wip = () => { return (
- } /> + } />
); }; diff --git a/src/apps/console/page-components/app-states.tsx b/src/apps/console/page-components/app-states.tsx index 3a0b9fee3..6a7d8c7ed 100644 --- a/src/apps/console/page-components/app-states.tsx +++ b/src/apps/console/page-components/app-states.tsx @@ -214,6 +214,11 @@ export const useAppState = () => { }; }; +export const clearAppState = () => { + if (typeof window === 'undefined') return; + sessionStorage.removeItem('state'); +}; + export const AppContextProvider = ({ children, initialAppState, diff --git a/src/apps/console/page-components/config-resource.tsx b/src/apps/console/page-components/config-resource.tsx index eff6b541a..0862f7009 100644 --- a/src/apps/console/page-components/config-resource.tsx +++ b/src/apps/console/page-components/config-resource.tsx @@ -250,8 +250,8 @@ const ConfigResources = ({ throw new Error('Project and Environment name is required!.'); } try { - const { errors } = await api.deleteSecret({ - secretName: parseName(showDeleteDialog), + const { errors } = await api.deleteConfig({ + configName: parseName(showDeleteDialog), projectName: project, envName: workspace, }); diff --git a/src/apps/console/page-components/new-cluster.tsx b/src/apps/console/page-components/new-cluster.tsx index 0eeb12a95..24d60f3ee 100644 --- a/src/apps/console/page-components/new-cluster.tsx +++ b/src/apps/console/page-components/new-cluster.tsx @@ -23,10 +23,13 @@ import { validateClusterCloudProvider, } from '../server/r-utils/common'; import { ensureAccountClientSide } from '../server/utils/auth-utils'; -// import { IAccountContext } from '../routes/_main+/$account+/_layout'; -import ProgressWrapper from '../components/progress-wrapper'; import { NameIdView } from '../components/name-id-view'; import { ReviewComponent } from '../routes/_main+/$account+/$project+/$environment+/new-app/app-review'; +import MultiStepProgress, { + useMultiStepProgress, +} from '../components/multi-step-progress'; +import MultiStepProgressWrapper from '../components/multi-step-progress-wrapper'; +import { TitleBox } from '../components/raw-wrapper'; type props = | { @@ -38,13 +41,10 @@ type props = cloudProvider: IProviderSecret; }; -type steps = 'Configure cluster' | 'Review'; - export const NewCluster = ({ providerSecrets, cloudProvider }: props) => { const { cloudprovider: cp } = useParams(); const isOnboarding = !!cp; - // const [showUnsavedChanges, setShowUnsavedChanges] = useState(false); const api = useConsoleApi(); const cloudProviders = useMemo( @@ -66,9 +66,11 @@ export const NewCluster = ({ providerSecrets, cloudProvider }: props) => { const { a: accountName } = useParams(); - // const { account } = useOutletContext(); - const [activeState, setActiveState] = useState('Configure cluster'); - const isActive = (step: steps) => step === activeState; + const { currentStep, jumpStep, nextStep } = useMultiStepProgress({ + defaultStep: isOnboarding ? 4 : 1, + totalSteps: isOnboarding ? 4 : 2, + }); + const navigate = useNavigate(); const [selectedProvider, setSelectedProvider] = useState< @@ -155,11 +157,12 @@ export const NewCluster = ({ providerSecrets, cloudProvider }: props) => { } }; - switch (activeState) { - case 'Configure cluster': - setActiveState('Review'); + switch (currentStep) { + case 1: + nextStep(); break; - case 'Review': + case 2: + case 4: await submit(); break; default: @@ -170,20 +173,11 @@ export const NewCluster = ({ providerSecrets, cloudProvider }: props) => { const getView = () => { return ( -
{ - if (!values.isNameError) { - handleSubmit(e); - } else { - e.preventDefault(); - } - }} - > -
- A cluster is a group of interconnected elements working together as a - single unit. -
+
+
{
) : (
)} - - ); - }; - - const getReviewView = () => { - return ( -
- { - setActiveState('Configure cluster'); - }} - > -
-
-
- Cluster name -
-
{values.name}
-
-
-
- Cloud provider -
-
- {values.cloudProvider} -
-
- {values.cloudProvider === 'aws' && ( -
-
Region
-
{values.region}
-
- )} -
-
- Availability Mode -
-
- {values.availabilityMode === 'HA' - ? 'High Availability' - : 'Development'} -
-
-
-
-
-
-
+
); }; - - const items = () => { - return isOnboarding - ? [ - { - label: 'Create Team', - active: false, - id: 1, - completed: true, - }, - { - label: 'Add your Cloud Provider', - active: false, - id: 3, - completed: true, - }, - { - label: 'Validate Cloud Provider', - active: false, - id: 4, - completed: true, - }, - { - label: 'Setup First Cluster', - active: true, - id: 5, - completed: false, - children: getView(), - }, - ] - : [ - { - label: 'Configure cluster', - active: isActive('Configure cluster'), - completed: false, - children: isActive('Configure cluster') ? getView() : null, - }, - { - label: 'Review', - active: isActive('Review'), - completed: false, - children: isActive('Review') ? getReviewView() : null, - }, - ]; - }; - return ( - { - if (!isOnboarding) { - if (isActive('Review')) { - setActiveState('Configure cluster'); - } +
{ + if (!values.isNameError) { + handleSubmit(e); + } else { + e.preventDefault(); } }} - /> + > + + + {!isOnboarding ? ( + <> + + {getView()} + + + { + jumpStep(1); + }} + > +
+
+
+ Cluster name +
+
{values.name}
+
+
+
+ Cloud provider +
+
+ {values.cloudProvider} +
+
+ {values.cloudProvider === 'aws' && ( +
+
+ Region +
+
+ {values.region} +
+
+ )} +
+
+ Availability Mode +
+
+ {values.availabilityMode === 'HA' + ? 'High Availability' + : 'Development'} +
+
+
+
+
+
+
+ + ) : ( + <> + + + + + {getView()} + + + )} +
+
+
); }; diff --git a/src/apps/console/page-components/new-project.tsx b/src/apps/console/page-components/new-project.tsx index a25caee64..d7d69c391 100644 --- a/src/apps/console/page-components/new-project.tsx +++ b/src/apps/console/page-components/new-project.tsx @@ -1,7 +1,6 @@ /* eslint-disable no-nested-ternary */ import { ArrowRight } from '@jengaicons/react'; import { useLoaderData, useNavigate, useParams } from '@remix-run/react'; -import { useState } from 'react'; import { Button } from '~/components/atoms/button'; import { toast } from '~/components/molecule/toast'; import useForm, { dummyEvent } from '~/root/lib/client/hooks/use-form'; @@ -9,38 +8,37 @@ import Yup from '~/root/lib/server/helpers/yup'; import { handleError } from '~/root/lib/utils/common'; import Select from '~/components/atoms/select'; import { parseName, parseNodes } from '../server/r-utils/common'; -import { keyconstants } from '../server/r-utils/key-constants'; -import { - ensureAccountClientSide, - ensureClusterClientSide, -} from '../server/utils/auth-utils'; +import { ensureAccountClientSide } from '../server/utils/auth-utils'; import { INewProjectFromAccountLoader } from '../routes/_a+/$a+/new-project'; -import ProgressWrapper from '../components/progress-wrapper'; import { useConsoleApi } from '../server/gql/api-provider'; import { NameIdView } from '../components/name-id-view'; import { ReviewComponent } from '../routes/_main+/$account+/$project+/$environment+/new-app/app-review'; +import MultiStepProgress, { + useMultiStepProgress, +} from '../components/multi-step-progress'; +import MultiStepProgressWrapper from '../components/multi-step-progress-wrapper'; +import { TitleBox } from '../components/raw-wrapper'; -type steps = 'Configure project' | 'Review'; const NewProject = () => { - const { cluster: clusterName } = useParams(); - const isOnboarding = !!clusterName; const { clustersData } = useLoaderData(); const clusters = parseNodes(clustersData); - const [activeState, setActiveState] = useState('Configure project'); - const isActive = (step: steps) => step === activeState; - const api = useConsoleApi(); const navigate = useNavigate(); const params = useParams(); const { a: accountName } = params; + const { currentStep, jumpStep, nextStep } = useMultiStepProgress({ + defaultStep: 1, + totalSteps: 2, + }); + const { values, errors, handleSubmit, handleChange, isLoading } = useForm({ initialValues: { name: '', displayName: '', - clusterName: isOnboarding ? clusterName : clusters[0]?.metadata?.name, + clusterName: '', nodeType: '', isNameError: false, }, @@ -52,16 +50,11 @@ const NewProject = () => { onSubmit: async (val) => { const submit = async () => { try { - ensureClusterClientSide({ cluster: val.clusterName }); ensureAccountClientSide({ account: accountName }); const { errors: e } = await api.createProject({ project: { metadata: { name: val.name, - annotations: { - [keyconstants.displayName]: val.displayName, - [keyconstants.nodeType]: val.nodeType, - }, }, clusterName: val.clusterName, displayName: val.displayName, @@ -81,11 +74,11 @@ const NewProject = () => { } }; - switch (activeState) { - case 'Configure project': - setActiveState('Review'); + switch (currentStep) { + case 1: + nextStep(); break; - case 'Review': + case 2: await submit(); break; default: @@ -94,143 +87,113 @@ const NewProject = () => { }, }); - const getView = () => { - return ( -
{ - if (!values.isNameError) { - handleSubmit(e); - } else { - e.preventDefault(); - } + return ( + { + if (!values.isNameError) { + handleSubmit(e); + } else { + e.preventDefault(); + } + }} + > + -
- Create your project under production effortlessly. -
- - - - {!isOnboarding && ( - parseName(c) === values.clusterName) + ?.displayName || values.clusterName, + value: values.clusterName, + }} + options={async () => [ + ...clusters.map((clster) => ({ + label: clster.displayName, + value: parseName(clster), + cluster: clster, + render: () => ( +
+
{clster.displayName}
+
+ {parseName(clster)} +
+
+ ), + })), + ]} + onChange={(v) => { + handleChange('clusterName')(dummyEvent(v.value)); + }} + /> +
+
-
{values.name}
-
-
Cluster
-
{values.clusterName}
+ + + { + jumpStep(1); + }} + > +
+
+
+ Project name +
+
{values.name}
+
+
+
+ Cluster +
+
+ {values.clusterName} +
+
+
+
+
+
-
- -
-
- - ); - }; - - const getItems = () => { - return [ - { - label: 'Configure project', - active: isActive('Configure project'), - completed: false, - children: isActive('Configure project') ? getView() : null, - }, - { - label: 'Review', - active: isActive('Review'), - completed: false, - children: isActive('Review') ? getReviewView() : null, - }, - ]; - }; - - return ( - { - if (!isOnboarding) { - if (isActive('Review')) { - setActiveState('Configure project'); - } - } - }} - /> + + + + ); }; diff --git a/src/apps/console/routes/_main+/$account+/$project+/$environment+/apps/apps-resources.tsx b/src/apps/console/routes/_main+/$account+/$project+/$environment+/apps/apps-resources.tsx index 40327bb67..ec5ec9388 100644 --- a/src/apps/console/routes/_main+/$account+/$project+/$environment+/apps/apps-resources.tsx +++ b/src/apps/console/routes/_main+/$account+/$project+/$environment+/apps/apps-resources.tsx @@ -13,8 +13,8 @@ import { ListItem, ListSecondary, ListTitle, + listClass, listFlex, - listTitleClass, } from '~/console/components/console-list-components'; import Grid from '~/console/components/grid'; import List from '~/console/components/list'; @@ -175,7 +175,7 @@ const ListView = ({ items = [], onAction }: IResource) => { columns={[ { key: generateKey(keyPrefix, name + id), - className: listTitleClass, + className: listClass.title, render: () => , }, status, @@ -184,7 +184,7 @@ const ListView = ({ items = [], onAction }: IResource) => { intercept && !!intercept.enabled ? { key: generateKey(keyPrefix, `${name + id}intercept`), - className: listTitleClass, + className: listClass.title, render: () => ( { listFlex({ key: 'flex-1' }), { key: generateKey(keyPrefix, updateInfo.author), - className: 'w-[180px]', + className: listClass.author, render: () => ( { const Apps = () => { const { promise } = useLoaderData(); + useEffect(() => { + clearAppState(); + }, []); + return ( {({ appsData }) => { const apps = parseNodes(appsData); diff --git a/src/apps/console/routes/_main+/$account+/$project+/$environment+/cs+/_layout.tsx b/src/apps/console/routes/_main+/$account+/$project+/$environment+/cs+/_layout.tsx index dd678cfce..af544934b 100644 --- a/src/apps/console/routes/_main+/$account+/$project+/$environment+/cs+/_layout.tsx +++ b/src/apps/console/routes/_main+/$account+/$project+/$environment+/cs+/_layout.tsx @@ -1,20 +1,16 @@ import { Outlet, useOutletContext } from '@remix-run/react'; -import { useSubNavData } from '~/root/lib/client/hooks/use-create-subnav-action'; import SidebarLayout from '~/console/components/sidebar-layout'; import { IEnvironmentContext } from '../_layout'; const ProjectConfigAndSecrets = () => { const rootContext = useOutletContext(); - const subNavAction = useSubNavData(); return ( { const { pageInfo, totalCount } = configsData; return ( - <> - {configs.length > 0 && ( - + 0 && (
diff --git a/src/apps/console/routes/_main+/$account+/$project+/$environment+/new-managed-resource/_index.tsx b/src/apps/console/routes/_main+/$account+/$project+/$environment+/new-managed-resource/_index.tsx index 1285ee80e..0125b5ab6 100644 --- a/src/apps/console/routes/_main+/$account+/$project+/$environment+/new-managed-resource/_index.tsx +++ b/src/apps/console/routes/_main+/$account+/$project+/$environment+/new-managed-resource/_index.tsx @@ -546,7 +546,7 @@ const App = ({ services }: { services: ExtractNodeType[] }) => { msvcRef: { name: parseName(selectedService?.service), namespace: - selectedService?.service?.metadata?.namespace || '', + selectedService?.service?.spec?.targetNamespace || '', apiVersion: selectedService?.service?.spec?.msvcSpec.serviceTemplate .apiVersion || '', diff --git a/src/apps/console/routes/_main+/$account+/$project+/$environment+/router+/$router+/routes/handle-route.tsx b/src/apps/console/routes/_main+/$account+/$project+/$environment+/router+/$router+/routes/handle-route.tsx index d4ea2863f..14fd00d13 100644 --- a/src/apps/console/routes/_main+/$account+/$project+/$environment+/router+/$router+/routes/handle-route.tsx +++ b/src/apps/console/routes/_main+/$account+/$project+/$environment+/router+/$router+/routes/handle-route.tsx @@ -50,7 +50,10 @@ const Root = (props: IDialog) => { useForm({ initialValues: isUpdate ? { - path: props.data.path, + path: + props.data.path?.[0] === '/' + ? props.data.path.substring(1) + : props.data.path, app: props.data.app || '', port: `${props.data.port}`, } @@ -84,7 +87,7 @@ const Root = (props: IDialog) => { router: { displayName: router.displayName, spec: { - domains: router.spec.domains, + ...router.spec, routes: [ ...(router.spec.routes?.map((r) => ({ path: r.path, @@ -114,7 +117,7 @@ const Root = (props: IDialog) => { router: { displayName: router.displayName, spec: { - domains: router.spec.domains, + ...router.spec, routes: [ ...(router.spec.routes diff --git a/src/apps/console/routes/_main+/$account+/$project+/$environment+/routers/handle-router.tsx b/src/apps/console/routes/_main+/$account+/$project+/$environment+/routers/handle-router.tsx index 724fe313c..6aa26716b 100644 --- a/src/apps/console/routes/_main+/$account+/$project+/$environment+/routers/handle-router.tsx +++ b/src/apps/console/routes/_main+/$account+/$project+/$environment+/routers/handle-router.tsx @@ -21,7 +21,6 @@ import Select from '~/components/atoms/select'; import useCustomSwr from '~/root/lib/client/hooks/use-custom-swr'; import { IDomains } from '~/console/server/gql/queries/domain-queries'; import { useMapper } from '~/components/utils'; -import { da } from '@faker-js/faker'; type IDialog = IDialogBase>; @@ -107,6 +106,7 @@ const Root = (props: IDialog) => { name: val.name, }, spec: { + ...props.data.spec, domains: selectedDomains.map((sd) => sd.value), https: { enabled: true, diff --git a/src/apps/console/routes/_main+/$account+/$project+/$environment+/routers/router-resources.tsx b/src/apps/console/routes/_main+/$account+/$project+/$environment+/routers/router-resources.tsx index bdb4c66ce..c9f03804a 100644 --- a/src/apps/console/routes/_main+/$account+/$project+/$environment+/routers/router-resources.tsx +++ b/src/apps/console/routes/_main+/$account+/$project+/$environment+/routers/router-resources.tsx @@ -1,13 +1,11 @@ import { Trash, PencilLine } from '@jengaicons/react'; import { useState } from 'react'; -import { toast } from '~/components/molecule/toast'; -import { generateKey, titleCase } from '~/components/utils'; +import { generateKey } from '~/components/utils'; import { - ListBody, ListItem, ListTitle, + listClass, listFlex, - listTitleClass, } from '~/console/components/console-list-components'; import DeleteDialog from '~/console/components/delete-dialog'; import Grid from '~/console/components/grid'; @@ -138,14 +136,14 @@ const ListView = ({ items, onAction }: IResource) => { columns={[ { key: generateKey(keyPrefix, name + id), - className: listTitleClass, + className: listClass.title, render: () => , }, status, listFlex({ key: 'flex-1' }), { key: generateKey(keyPrefix, updateInfo.author), - className: 'w-[180px]', + className: listClass.author, render: () => ( { const rootContext = useOutletContext(); - const subNavAction = useSubNavData(); return ( diff --git a/src/apps/console/routes/_main+/$account+/$project+/$environment+/settings+/image-pull-secrets/_index.tsx b/src/apps/console/routes/_main+/$account+/$project+/$environment+/settings+/image-pull-secrets/_index.tsx new file mode 100644 index 000000000..7c1d7dd9b --- /dev/null +++ b/src/apps/console/routes/_main+/$account+/$project+/$environment+/settings+/image-pull-secrets/_index.tsx @@ -0,0 +1,99 @@ +import { Plus, PlusFill } from '@jengaicons/react'; +import { defer } from '@remix-run/node'; +import { useLoaderData } from '@remix-run/react'; +import { Button } from '~/components/atoms/button.jsx'; +import { LoadingComp, pWrapper } from '~/console/components/loading-component'; +import Wrapper from '~/console/components/wrapper'; +import { GQLServerHandler } from '~/console/server/gql/saved-queries'; +import { parseNodes } from '~/console/server/r-utils/common'; +import { + ensureAccountSet, + ensureClusterSet, +} from '~/console/server/utils/auth-utils'; +import { getPagination, getSearch } from '~/console/server/utils/common'; +import { IRemixCtx } from '~/root/lib/types/common'; +import { useState } from 'react'; +import Tools from './tools'; +import ImagePullSecretsResources from './image-pull-secrets-resources'; +import HandleImagePullSecret from './handle-image-pull-secret'; + +export const loader = async (ctx: IRemixCtx) => { + ensureAccountSet(ctx); + ensureClusterSet(ctx); + const { project, environment } = ctx.params; + + const promise = pWrapper(async () => { + const { data, errors } = await GQLServerHandler( + ctx.request + ).listImagePullSecrets({ + envName: environment, + projectName: project, + pq: getPagination(ctx), + search: getSearch(ctx), + }); + if (errors) { + throw errors[0]; + } + return { imagePullSecretsData: data }; + }); + + return defer({ promise }); +}; + +const Routers = () => { + const { promise } = useLoaderData(); + const [visible, setVisible] = useState(false); + + return ( + <> + + {({ imagePullSecretsData }) => { + const imagePullSecrets = parseNodes(imagePullSecretsData); + if (!imagePullSecrets) { + return null; + } + return ( + 0 && ( +