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

feature: set password to undefined when no change is desired. #2010

Merged
merged 1 commit into from
Nov 5, 2023
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
10 changes: 7 additions & 3 deletions react/src/components/ContainerRegistryEditorModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,97 +17,101 @@
}
const ContainerRegistryEditorModal: React.FC<
ContainerRegistryEditorModalProps
> = ({
existingHostnames,
containerRegistryFrgmt = null,
onOk,
...modalProps
}) => {
const { t } = useTranslation();
const [form] = Form.useForm();

const [messageAPI, contextHolder] = message.useMessage();
const [modal, modalContextHolder] = Modal.useModal();

const containerRegistry = useFragment(
graphql`
fragment ContainerRegistryEditorModalFragment on ContainerRegistry {
id
hostname
config {
url
type
project
username
ssl_verify
}
}
`,
containerRegistryFrgmt,
);
const [commitCreateRegistry, isInflightCreateRegistry] =
useMutation<ContainerRegistryEditorModalCreateMutation>(graphql`
mutation ContainerRegistryEditorModalCreateMutation(
$hostname: String!
$props: CreateContainerRegistryInput!
) {
create_container_registry(hostname: $hostname, props: $props) {
container_registry {
id
hostname
config {
url
type
project
username
password
ssl_verify
}
}
}
}
`);

Check warning on line 69 in react/src/components/ContainerRegistryEditorModal.tsx

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🧾 Statement is not covered

Warning! Not covered statement

const [commitModifyRegistry, isInflightModifyRegistry] =
useMutation<ContainerRegistryEditorModalModifyMutation>(graphql`
mutation ContainerRegistryEditorModalModifyMutation(
$hostname: String!
$props: ModifyContainerRegistryInput!
) {
modify_container_registry(hostname: $hostname, props: $props) {
container_registry {
id
hostname
config {
url
type
project
username
password
ssl_verify
}
}
}
}
`);

Check warning on line 92 in react/src/components/ContainerRegistryEditorModal.tsx

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🧾 Statement is not covered

Warning! Not covered statement

const handleSave = async () => {
return form
.validateFields()
.then((values) => {
const mutationVariables = {
hostname: values.hostname,
props: {
url: values.config.url,
type: values.config.type,
project:
values.config.project === 'docker'
? undefined
: values.config.project,
username: _.isEmpty(values.config.username)
? null
: values.config.username,
password: _.isEmpty(values.config.password)
? null
: values.config.password,
password: values.isChangedPassword
? _.isEmpty(values.config.password)
? null // unset

Check warning on line 112 in react/src/components/ContainerRegistryEditorModal.tsx

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🌿 Branch is not covered

Warning! Not covered branch
: values.config.password

Check warning on line 113 in react/src/components/ContainerRegistryEditorModal.tsx

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🌿 Branch is not covered

Warning! Not covered branch

Check warning on line 113 in react/src/components/ContainerRegistryEditorModal.tsx

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🌿 Branch is not covered

Warning! Not covered branch
: undefined, // no change

Check warning on line 114 in react/src/components/ContainerRegistryEditorModal.tsx

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🌿 Branch is not covered

Warning! Not covered branch
},
};

Check warning on line 116 in react/src/components/ContainerRegistryEditorModal.tsx

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🧾 Statement is not covered

Warning! Not covered statement
if (containerRegistry) {
Expand Down
8 changes: 5 additions & 3 deletions react/src/components/ContainerRegistryList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,42 +42,43 @@
>
>[0];

const ContainerRegistryList = () => {
const baiClient = useSuspendedBackendaiClient();
const [fetchKey, updateFetchKey] = useUpdatableState('initial-fetch');
const [isPendingReload, startReloadTransition] = useTransition();
const painKiller = usePainKiller();
const [messageAPI, contextHolder] = message.useMessage();
const { container_registries, domain } =
useLazyLoadQuery<ContainerRegistryListQuery>(
graphql`
query ContainerRegistryListQuery($domain: String!) {
container_registries {
...ContainerRegistryEditorModalFragment
id
hostname
config {
url
type
project
username
password
ssl_verify
}
}
domain(name: $domain) {
name
allowed_docker_registries
}
}
`,
{
domain: baiClient._config.domainName,
},
{
fetchPolicy: 'network-only',
fetchKey,
},
);

Check warning on line 81 in react/src/components/ContainerRegistryList.tsx

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🧾 Statement is not covered

Warning! Not covered statement

const [commitDeleteMutation, isInFlightDeleteMutation] =
useMutation<ContainerRegistryListDeleteMutation>(graphql`
Expand Down Expand Up @@ -191,313 +192,314 @@
.catch(handleReScanError);
};

return (
<Flex
direction="column"
align="stretch"
style={{
flex: 1,
// height: 'calc(100vh - 183px)',
}}
>
{contextHolder}
<Flex
direction="row"
justify="end"
gap={'sm'}
style={{ padding: token.paddingSM }}
>
<Button
type="primary"
icon={<PlusOutlined />}
onClick={() => {
setIsNewModalOpen(true);
}}
>
{t('registry.AddRegistry')}
</Button>
<Tooltip title={t('button.Refresh')}>
<Button
loading={isPendingReload}
icon={<ReloadOutlined />}
onClick={() => {
startReloadTransition(() => {
updateFetchKey();
});
}}
/>
</Tooltip>
</Flex>
<Table
scroll={{ x: 'max-content' }}
pagination={false}
columns={[
// {
// title: '#',
// dataIndex: 'id',
// },
{
title: t('registry.Hostname'),
dataIndex: 'hostname',
// fixed: 'left',
},
{
title: t('registry.RegistryURL'),
dataIndex: ['config', 'url'],
},
{
title: t('registry.Type'),
dataIndex: ['config', 'type'],
},
{
title: t('registry.HarborProject'),
render: (value, record) => {
return _.map(record.config?.project, (prjName) => {
return <Tag key={prjName}>{prjName || ''}</Tag>;
});
},
},
{
title: t('registry.Username'),
dataIndex: ['config', 'username'],
},
// {
// title: t('registry.Password')
// },
{
title: t('registry.Password'),
dataIndex: ['config', 'password'],
},
{
title: t('general.Enabled'),
render: (value, record) => {
const isEnabled = _.includes(
domain?.allowed_docker_registries,
record.hostname,
);
return (
<Switch
checked={
inFlightHostName === record.hostname + fetchKey
? !isEnabled
: isEnabled
}
disabled={isPendingReload || isInFlightDomationMutation}
loading={inFlightHostName === record.hostname + fetchKey}
onChange={(isOn) => {
if (!_.isString(record.hostname)) return;
let newAllowedDockerRegistries = _.clone(
domain?.allowed_docker_registries || [],
) as string[];
if (isOn) {
newAllowedDockerRegistries.push(record.hostname);
} else {
newAllowedDockerRegistries = _.without(
newAllowedDockerRegistries,
record.hostname,
);
}

setInFlightHostName(record.hostname + fetchKey);
commitDomainMutation({
variables: {
domain: baiClient._config.domainName,
allowed_docker_registries: newAllowedDockerRegistries,
},
onCompleted: (data) => {
startReloadTransition(() => {
updateFetchKey();
});

messageAPI.info({
key: 'registry-enabled',
content: isOn
? t('registry.RegistryTurnedOn')
: t('registry.RegistryTurnedOff'),
});
},
});
}}
/>
// <Button type="primary">
// {record?.config?.ssl_verify ? 'Yes' : 'No'}
// </Button>
);
},
},
{
title: t('general.Control'),
fixed: 'right',
render(value, record, index) {
return (
<Flex>
<Tooltip title={t('button.Edit')}>
<Button
size="large"
style={{
color: token.colorInfo,
}}
type="text"
icon={<SettingOutlined />}
onClick={() => {
setEditingRegistry(record);
}}
/>
</Tooltip>
<Tooltip title={t('button.Delete')}>
<Button
size="large"
danger
type="text"
icon={<DeleteOutlined />}
onClick={() => {
setDeletingRegistry(record);
}}
/>
</Tooltip>
<Tooltip title={t('maintenance.RescanImages')}>
<Button
size="large"
type="text"
icon={
<SyncOutlined
onClick={() => {
record.hostname && rescanImage(record.hostname);
}}
/>
}
/>
</Tooltip>
</Flex>
);
},
},
]}
dataSource={filterNonNullItems(container_registries)}
/>
<ContainerRegistryEditorModal
containerRegistryFrgmt={editingRegistry}
existingHostnames={_.map(
container_registries,
(r) => r?.hostname || '',
)}
open={!!editingRegistry || isNewModalOpen}
onOk={(type) => {
if (type === 'create') {
updateFetchKey();
messageAPI.info(t('registry.RegistrySuccessfullyAdded'));
} else if (type === 'modify') {
messageAPI.info(t('registry.RegistrySuccessfullyModified'));
}
setEditingRegistry(null);
setIsNewModalOpen(false);
}}
onCancel={() => {
setEditingRegistry(null);
setIsNewModalOpen(false);
}}
centered={false}
/>
<BAIModal
title={
<>
<ExclamationCircleOutlined
style={{
color: token.colorWarning,
}}
/>{' '}
{t('dialog.warning.CannotBeUndone')}
</>
}
okText={t('button.Delete')}
okButtonProps={{
danger: true,
disabled: deletingConfirmText !== deletingRegistry?.hostname,
}}
onOk={() => {
if (deletingRegistry) {
commitDeleteMutation({
variables: {
hostname: deletingRegistry.hostname || '',
},
onCompleted: (response, error) => {
if (error) {
setDeletingRegistry(null);
messageAPI.error({
key: 'registry-deletion-failed',
content: t('dialog.ErrorOccurred'),
});
} else {
startReloadTransition(() => {
updateFetchKey();
});
messageAPI.info({
key: 'registry-deleted',
content: t('registry.RegistrySuccessfullyDeleted'),
});
setDeletingRegistry(null);
}
},
onError: (error) => {
messageAPI.error({
key: 'registry-deletion-failed',
content: t('dialog.ErrorOccurred'),
});
},
});
} else {
setDeletingRegistry(null);
}
}}
confirmLoading={isInFlightDeleteMutation}
onCancel={() => {
setDeletingRegistry(null);
}}
destroyOnClose
open={!!deletingRegistry}
>
<Flex
direction="column"
align="stretch"
gap="sm"
style={{
marginTop: token.marginMD,
}}
>
<Typography.Text>
<Typography.Text code>{deletingRegistry?.hostname}</Typography.Text>{' '}
{t('registry.TypeRegistryNameToDelete')}
</Typography.Text>
<Form>
<Form.Item
name={'confirmText'}
// help="asdf"
// validateStatus={
// deletingConfirmText &&
// deletingConfirmText !== deletingRegistry?.hostname
// ? 'error'
// : undefined
// }
rules={[
{
required: true,
message: t('registry.HostnameDoesNotMatch'),
validator: async () => {
if (deletingConfirmText === deletingRegistry?.hostname) {
return Promise.resolve();
}
return Promise.reject();
},
},
]}
>
<Input
autoComplete="off"
value={deletingConfirmText}
onChange={(e) => setDeletingConfirmText(e.target.value)}
/>
</Form.Item>
</Form>
</Flex>
</BAIModal>
</Flex>
);

Check warning on line 502 in react/src/components/ContainerRegistryList.tsx

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🧾 Statement is not covered

Warning! Not covered statement
};

Check warning on line 503 in react/src/components/ContainerRegistryList.tsx

View workflow job for this annotation

GitHub Actions / Coverage annotations (🧪 jest-coverage-report-action)

🧾 Statement is not covered

Warning! Not covered statement

export default ContainerRegistryList;