Skip to content

Commit

Permalink
feat(crux-ui): node script & add deployment & config json editor impr…
Browse files Browse the repository at this point in the history
…ovements (#681)
  • Loading branch information
robot9706 committed Jun 13, 2023
1 parent a035758 commit 8c81730
Show file tree
Hide file tree
Showing 7 changed files with 89 additions and 68 deletions.
3 changes: 2 additions & 1 deletion web/crux-ui/e2e/deployment.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { ProjectType } from '@app/models'
import { projectUrl, ROUTE_DASHBOARD, ROUTE_TEAMS } from '@app/routes'
import { expect, Page, test } from '@playwright/test'
import { DAGENT_NODE, NGINX_TEST_IMAGE_WITH_TAG } from './utils/common'
import { DAGENT_NODE, NGINX_TEST_IMAGE_WITH_TAG, USER_FULLNAME } from './utils/common'
import { createNode } from './utils/nodes'
import {
addDeploymentToVersion,
Expand Down
2 changes: 0 additions & 2 deletions web/crux-ui/e2e/nodes.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,14 +84,12 @@ test('Generate script should show the curl command and the script', async ({ pag
const script = await page.locator('textarea[readonly]')
const timer = await page.locator('label.text-dyo-turquoise')
const discardButton = await page.locator('button:has-text("Discard")').first()
const copyButton = await page.locator('button:has-text("Copy")')

await expect(curl).toBeVisible()
await expect(curl).toHaveValue(/curl/)
await expect(script).toBeVisible()
await expect(timer).toBeVisible()
await expect(discardButton).toBeVisible()
await expect(copyButton).toBeVisible()
})

test('Generate script should show script type selector for Docker', async ({ page }) => {
Expand Down
7 changes: 5 additions & 2 deletions web/crux-ui/e2e/utils/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ export const MAILSLURPER_TIMEOUT = 30000 // millis
export const USER_EMAIL = 'john.doe@example.com'
export const USER_PASSWORD = 'TestPw23233'
export const USER_TEAM = "John's Team"
export const USER_FIRSTNAME = 'John'
export const USER_LASTNAME = 'Doe'
export const USER_FULLNAME = `${USER_FIRSTNAME} ${USER_LASTNAME}`

export const DAGENT_NODE = 'dagent-deployable'
export const SCREENSHOTS_FOLDER = 'screenshots'
Expand Down Expand Up @@ -96,8 +99,8 @@ export const createUser = async (
traits: {
email,
name: {
first: 'John',
last: 'Doe',
first: USER_FIRSTNAME,
last: USER_LASTNAME,
},
},
credentials: {
Expand Down
3 changes: 3 additions & 0 deletions web/crux-ui/public/copy-alt.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
33 changes: 19 additions & 14 deletions web/crux-ui/src/components/nodes/dyo-node-setup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import DyoButton from '@app/elements/dyo-button'
import DyoChips from '@app/elements/dyo-chips'
import DyoForm from '@app/elements/dyo-form'
import { DyoHeading } from '@app/elements/dyo-heading'
import DyoIcon from '@app/elements/dyo-icon'
import { DyoInput } from '@app/elements/dyo-input'
import { DyoLabel } from '@app/elements/dyo-label'
import DyoSwitch from '@app/elements/dyo-switch'
Expand Down Expand Up @@ -198,16 +199,24 @@ const DyoNodeSetup = (props: DyoNodeSetupProps) => {
) : (
<>
<div className="flex flex-col">
<DyoInput
label={t('command')}
className="bg-gray-900"
readOnly
grow
defaultValue={node.install.command}
onFocus={ev => ev.target.select()}
/>

<div className="flex flex-row">
<DyoLabel className="mt-8 mb-2.5 whitespace-nowrap">{t('command')}</DyoLabel>

<div className="flex flex-row items-center">
<DyoInput
className="bg-gray-900"
containerClassName="flex-1"
readOnly
grow
defaultValue={node.install.command}
onFocus={ev => ev.target.select()}
/>

<div onClick={onCopyScript} className="cursor-pointer ml-2 h-11 w-11 flex items-center justify-center">
<DyoIcon size="md" src="/copy-alt.svg" alt={t('copy')} />
</div>
</div>

<div className="flex flex-row mt-2">
<DyoLabel className="text-white mr-2">{t('scriptExpiresIn')}</DyoLabel>

<TimeLabel textColor="text-dyo-turquoise" seconds={remaining} />
Expand All @@ -218,10 +227,6 @@ const DyoNodeSetup = (props: DyoNodeSetupProps) => {
<DyoButton className="px-4 py-2 mr-4" secondary onClick={onDiscard}>
{t('common:discard')}
</DyoButton>

<DyoButton className="px-4 py-2 mr-auto" outlined onClick={onCopyScript}>
{t('common:copy')}
</DyoButton>
</div>

<div className="flex flex-col">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,6 @@ const AddDeploymentCard = (props: AddDeploymentCardProps) => {

const { data: nodes, error: fetchNodesError } = useSWR<DyoNode[]>(API_NODES, fetcher)

useEffect(() => {
if (nodes && nodes.length < 1) {
toast.error(t('nodeRequired'))
}
}, [nodes, t])

const handleApiError = defaultApiErrorHandler(t)

const formik = useDyoFormik({
Expand Down Expand Up @@ -76,6 +70,15 @@ const AddDeploymentCard = (props: AddDeploymentCardProps) => {
},
})

useEffect(() => {
if (nodes && nodes.length < 1) {
toast.error(t('nodeRequired'))
}
if (nodes?.length === 1 && !formik.values.nodeId) {
formik.setFieldValue('nodeId', nodes[0].id)
}
}, [nodes, t])

return (
<DyoCard className={className}>
<div className="flex flex-row">
Expand Down
94 changes: 51 additions & 43 deletions web/crux-ui/src/models/container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -401,49 +401,57 @@ const removeId = <T extends { id: string }>(item: T): Omit<T, 'id'> => {
return newItem
}

export const imageConfigToJsonContainerConfig = (config: Partial<ContainerConfigData>): JsonContainerConfig => ({
...config,
commands: keyArrayToJson(config.commands),
args: keyArrayToJson(config.args),
networks: keyArrayToJson(config.networks),
customHeaders: keyArrayToJson(config.customHeaders),
extraLBAnnotations: keyValueArrayToJson(config.extraLBAnnotations),
environment: keyValueArrayToJson(config.environment),
capabilities: keyValueArrayToJson(config.capabilities),
secrets: config.secrets?.map(it => ({ key: it.key, required: it.required })),
portRanges: config.portRanges?.map(it => removeId(it)),
ports: config.ports?.map(it => removeId(it)),
storage: config.storage,
logConfig: config.logConfig
? {
...config.logConfig,
options: keyValueArrayToJson(config.logConfig?.options),
}
: null,
initContainers: config.initContainers?.map(container => ({
...removeId(container),
command: keyArrayToJson(container.command),
args: keyArrayToJson(container.args),
environment: keyValueArrayToJson(container.environment),
volumes: container.volumes?.map(vit => removeId(vit)),
})),
volumes: config.volumes?.map(it => removeId(it)),
dockerLabels: keyValueArrayToJson(config.dockerLabels),
annotations: config.annotations
? {
deployment: keyValueArrayToJson(config.annotations.deployment),
service: keyValueArrayToJson(config.annotations.service),
ingress: keyValueArrayToJson(config.annotations.ingress),
}
: null,
labels: config.labels
? {
deployment: keyValueArrayToJson(config.labels.deployment),
service: keyValueArrayToJson(config.labels.service),
ingress: keyValueArrayToJson(config.labels.ingress),
}
: null,
})
export const imageConfigToJsonContainerConfig = (config: Partial<ContainerConfigData>): JsonContainerConfig => {
const jsonConfig = {
...config,
commands: keyArrayToJson(config.commands),
args: keyArrayToJson(config.args),
networks: keyArrayToJson(config.networks),
customHeaders: keyArrayToJson(config.customHeaders),
extraLBAnnotations: keyValueArrayToJson(config.extraLBAnnotations),
environment: keyValueArrayToJson(config.environment),
capabilities: keyValueArrayToJson(config.capabilities),
secrets: config.secrets?.map(it => ({ key: it.key, required: it.required })),
portRanges: config.portRanges?.map(it => removeId(it)),
ports: config.ports?.map(it => removeId(it)),
storage: config.storage,
logConfig: config.logConfig
? {
...config.logConfig,
options: keyValueArrayToJson(config.logConfig?.options),
}
: null,
initContainers: config.initContainers?.map(container => ({
...removeId(container),
command: keyArrayToJson(container.command),
args: keyArrayToJson(container.args),
environment: keyValueArrayToJson(container.environment),
volumes: container.volumes?.map(vit => removeId(vit)),
})),
volumes: config.volumes?.map(it => removeId(it)),
dockerLabels: keyValueArrayToJson(config.dockerLabels),
annotations: config.annotations
? {
deployment: keyValueArrayToJson(config.annotations.deployment),
service: keyValueArrayToJson(config.annotations.service),
ingress: keyValueArrayToJson(config.annotations.ingress),
}
: null,
labels: config.labels
? {
deployment: keyValueArrayToJson(config.labels.deployment),
service: keyValueArrayToJson(config.labels.service),
ingress: keyValueArrayToJson(config.labels.ingress),
}
: null,
}

const configObject = jsonConfig as any
delete configObject.id
delete configObject.imageId

return jsonConfig
}

export const instanceConfigToJsonInstanceConfig = (
config: InstanceContainerConfigData,
Expand Down

0 comments on commit 8c81730

Please sign in to comment.