Skip to content
Open
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
7 changes: 6 additions & 1 deletion libs/i18n/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -841,6 +841,8 @@
"Select a repository to generate the full URL": "Select a repository to generate the full URL",
"Suffix that will be combined with the repository's base URL to invoke the HTTP service. Can include query parameters.": "Suffix that will be combined with the repository's base URL to invoke the HTTP service. Can include query parameters.",
"Path of the file where the response will be stored in the device filesystem.": "Path of the file where the response will be stored in the device filesystem.",
"Only Git repositories can be used for Git configurations.": "Only Git repositories can be used for Git configurations.",
"Only HTTP repositories can be used for HTTP configurations.": "Only HTTP repositories can be used for HTTP configurations.",
"Register all MicroShift devices to ACM": "Register all MicroShift devices to ACM",
"Select this when all the devices in the fleet are running MicroShift and you want to register them to ACM.": "Select this when all the devices in the fleet are running MicroShift and you want to register them to ACM.",
"To remove registration, you'll need to uncheck this option and also remove the clusters from ACM's clusters list": "To remove registration, you'll need to uncheck this option and also remove the clusters from ACM's clusters list",
Expand Down Expand Up @@ -1075,9 +1077,9 @@
"Accessible": "Accessible",
"Not accessible": "Not accessible",
"Missing repository": "Missing repository",
"Create repository": "Create repository",
"Repository": "Repository",
"Select a repository": "Select a repository",
"Create repository": "Create repository",
"Max file size {{ maxFileSize }} KB": "Max file size {{ maxFileSize }} KB",
"Max file size {{ maxFileSize }} MB": "Max file size {{ maxFileSize }} MB",
"File exceeds maximum allowed size.": "File exceeds maximum allowed size.",
Expand Down Expand Up @@ -1202,6 +1204,7 @@
"Management-ready by default": "Management-ready by default",
"The agent is automatically included in this image. This ensures your devices are ready to be managed immediately after they are deployed.": "The agent is automatically included in this image. This ensures your devices are ready to be managed immediately after they are deployed.",
"Target repository": "Target repository",
"Only OCI registries can be used for image builds.": "Only OCI registries can be used for image builds.",
"Storage repository for your completed image.": "Storage repository for your completed image.",
"Image name": "Image name",
"The image name that will be pushed to the repository. For example: flightctl/rhel-bootc": "The image name that will be pushed to the repository. For example: flightctl/rhel-bootc",
Expand Down Expand Up @@ -1528,6 +1531,8 @@
"Token": "Token",
"SSH private key": "SSH private key",
"Private key passphrase": "Private key passphrase",
"Repository type": "Repository type",
"Why is this repository type enforced?": "Why is this repository type enforced?",
"Use Git repository": "Use Git repository",
"Use HTTP service": "Use HTTP service",
"Use OCI registry": "Use OCI registry",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ const ConfigWithRepositoryTemplateForm = ({
isReadOnly,
canCreateRepo,
}: ConfigWithRepositoryTemplateFormProps) => {
const { t } = useTranslation();
const { values } = useFormikContext<DeviceSpecConfigFormValues>();

const ct = values.configTemplates[index] as HttpConfigTemplate | GitConfigTemplate;
Expand All @@ -139,6 +140,12 @@ const ConfigWithRepositoryTemplateForm = ({
isReadOnly={isReadOnly}
repoRefetch={repoRefetch}
isRequired
options={{
enforcedRepoTypeMessage:
repoType === RepoSpecType.RepoSpecTypeGit
? t('Only Git repositories can be used for Git configurations.')
: t('Only HTTP repositories can be used for HTTP configurations.'),
}}
/>
{repoType === RepoSpecType.RepoSpecTypeGit && (
<GitConfigForm template={ct as GitConfigTemplate} index={index} isReadOnly={isReadOnly} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ const OutputImageStep = () => {
isRequired
options={{
writeAccessOnly: true,
enforcedRepoTypeMessage: t('Only OCI registries can be used for image builds.'),
}}
validateRepoSelection={writableRepoValidation}
helperText={t('Storage repository for your completed image.')}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ const SourceImageStep = () => {
canCreateRepo={canCreateRepo}
repoRefetch={refetch}
isRequired
options={{
enforcedRepoTypeMessage: t('Only OCI registries can be used for image builds.'),
}}
/>
<FormGroup label={t('Image name')} fieldId="image-name" isRequired>
{baseImages.length ? (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,15 @@ import {
ModalBody,
ModalFooter,
ModalHeader,
Popover,
Split,
SplitItem,
} from '@patternfly/react-core';

import { FieldArray, Formik, useField, useFormikContext } from 'formik';
import * as Yup from 'yup';
import { Trans } from 'react-i18next';
import { MinusCircleIcon, PlusCircleIcon } from '@patternfly/react-icons/dist/js/icons';
import { MinusCircleIcon, OutlinedQuestionCircleIcon, PlusCircleIcon } from '@patternfly/react-icons/dist/js/icons';

import { useTranslation } from '../../../hooks/useTranslation';
import { useFetch } from '../../../hooks/useFetch';
Expand All @@ -32,6 +33,7 @@ import CreateResourceSyncsForm from './CreateResourceSyncsForm';

import {
getInitValues,
getRepoTypeLabel,
getRepository,
getRepositoryPatches,
getResourceSync,
Expand Down Expand Up @@ -185,7 +187,13 @@ const AdvancedSection = () => {
);
};

const RepositoryType = ({ isEdit }: { isEdit?: boolean }) => {
const RepositoryType = ({
isEdit,
enforcedRepoTypeMessage,
}: {
isEdit?: boolean;
enforcedRepoTypeMessage?: string;
}) => {
const { t } = useTranslation();
const { values, setFieldValue, validateForm } = useFormikContext<RepositoryFormValues>();
const [showConfirmChangeType, setShowConfirmChangeType] = React.useState<RepoSpecType | undefined>();
Expand All @@ -194,7 +202,26 @@ const RepositoryType = ({ isEdit }: { isEdit?: boolean }) => {
return null;
}

const isRepoTypeChangeDisabled = values.allowedRepoTypes?.length === 1;
// When we don't want to hide the repository type, but a single repoType can be chosen, we show a clarifying message.
const enforcedRepoType = values.allowedRepoTypes?.length === 1 ? values.allowedRepoTypes[0] : undefined;
if (enforcedRepoType) {
const repoTypeLabel = getRepoTypeLabel(t, enforcedRepoType);
return (
<FormGroup label={t('Repository type')}>
{repoTypeLabel}
{enforcedRepoTypeMessage && (
<Popover bodyContent={enforcedRepoTypeMessage}>
<Button
variant="plain"
isInline
icon={<OutlinedQuestionCircleIcon />}
aria-label={t('Why is this repository type enforced?')}
/>
</Popover>
Comment thread
coderabbitai[bot] marked this conversation as resolved.
)}
</FormGroup>
);
}

const doChangeRepoType = (toType: RepoSpecType) => {
if (toType === RepoSpecType.RepoSpecTypeGit) {
Expand Down Expand Up @@ -245,7 +272,6 @@ const RepositoryType = ({ isEdit }: { isEdit?: boolean }) => {
checkedValue={RepoSpecType.RepoSpecTypeGit}
onChangeCustom={onRepoTypeChange}
noDefaultOnChange
isDisabled={isRepoTypeChangeDisabled}
/>
</SplitItem>
<SplitItem>
Expand All @@ -256,7 +282,6 @@ const RepositoryType = ({ isEdit }: { isEdit?: boolean }) => {
checkedValue={RepoSpecType.RepoSpecTypeHttp}
onChangeCustom={onRepoTypeChange}
noDefaultOnChange
isDisabled={isRepoTypeChangeDisabled}
/>
</SplitItem>
<SplitItem>
Expand All @@ -267,7 +292,6 @@ const RepositoryType = ({ isEdit }: { isEdit?: boolean }) => {
checkedValue={RepoSpecType.RepoSpecTypeOci}
onChangeCustom={onRepoTypeChange}
noDefaultOnChange
isDisabled={isRepoTypeChangeDisabled}
/>
</SplitItem>
</Split>
Expand Down Expand Up @@ -347,9 +371,11 @@ const TagsField = ({
export const RepositoryForm = ({
isEdit,
accessModeDisabledReason,
enforcedRepoTypeMessage,
}: {
isEdit?: boolean;
accessModeDisabledReason?: string;
enforcedRepoTypeMessage?: string;
}) => {
const { t } = useTranslation();
const { values } = useFormikContext<RepositoryFormValues>();
Expand Down Expand Up @@ -384,7 +410,7 @@ export const RepositoryForm = ({
</FormGroup>
)}

<RepositoryType isEdit={isEdit} />
<RepositoryType isEdit={isEdit} enforcedRepoTypeMessage={enforcedRepoTypeMessage} />
{isOciRepo && (
<FormSection>
<FormGroup label={t('Scheme')}>
Expand Down Expand Up @@ -533,6 +559,7 @@ const CreateRepositoryFormContent = ({ isEdit, onClose, options, children }: Cre
<Grid hasGutter>
<RepositoryForm
isEdit={isEdit}
enforcedRepoTypeMessage={options?.enforcedRepoTypeMessage}
accessModeDisabledReason={
options?.writeAccessOnly
? t('Access mode must be set to read and write for this repository type')
Expand Down Expand Up @@ -591,6 +618,8 @@ export type CreateRepositoryFormProps = {
canUseResourceSyncs?: boolean;
showRepoTypes?: boolean;
allowedRepoTypes?: RepoSpecType[];
// Message to display when a single repository type is enforced
enforcedRepoTypeMessage?: string;
writeAccessOnly?: boolean;
};
};
Expand Down
36 changes: 7 additions & 29 deletions libs/ui-components/src/components/form/RepositorySelect.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,6 @@
import * as React from 'react';
import { useField, useFormikContext } from 'formik';
import {
Button,
Flex,
FlexItem,
FormGroup,
Icon,
MenuFooter,
SelectList,
SelectOption,
Stack,
StackItem,
} from '@patternfly/react-core';
import { PlusCircleIcon } from '@patternfly/react-icons/dist/js/icons/plus-circle-icon';
import { Flex, FlexItem, FormGroup, Icon, SelectList, SelectOption, Stack, StackItem } from '@patternfly/react-core';
import { ExclamationCircleIcon } from '@patternfly/react-icons/dist/js/icons/exclamation-circle-icon';
import { TFunction } from 'react-i18next';

Expand Down Expand Up @@ -118,6 +106,7 @@ type RepositorySelectProps = {
repoRefetch?: VoidFunction;
options?: {
writeAccessOnly?: boolean;
enforcedRepoTypeMessage?: string;
};
isRequired?: boolean;
validateRepoSelection?: (repo: Repository) => string | undefined;
Expand Down Expand Up @@ -182,6 +171,10 @@ const RepositorySelect = ({
void setFieldValue(name, repo.metadata.name, true);
};

const addAction = canCreateRepo
? { label: t('Create repository'), onAdd: () => setCreateRepoModalOpen(true) }
: undefined;

return (
<>
<FormGroup label={label || t('Repository')} isRequired={isRequired}>
Expand All @@ -191,24 +184,9 @@ const RepositorySelect = ({
withStatusIcon
placeholderText={t('Select a repository')}
isDisabled={isReadOnly}
addAction={addAction}
>
<ReadOnlyRepositoryListItem invalidRepoItems={invalidRepoItems} />

{canCreateRepo && (
<MenuFooter>
<Button
variant="link"
isInline
icon={<PlusCircleIcon />}
onClick={() => {
setCreateRepoModalOpen(true);
}}
isDisabled={isReadOnly}
>
{t('Create repository')}
</Button>
</MenuFooter>
)}
</FormSelect>

{helperText && <DefaultHelperText helperText={helperText} />}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ type CreateRepositoryModalProps = {
onSuccess: (repository: Repository) => void;
options?: {
writeAccessOnly?: boolean;
enforcedRepoTypeMessage?: string;
};
};

Expand All @@ -26,6 +27,7 @@ const CreateRepositoryModal = ({ type, onClose, onSuccess, options }: CreateRepo
options={{
canUseResourceSyncs: false,
allowedRepoTypes: [type],
enforcedRepoTypeMessage: options?.enforcedRepoTypeMessage,
writeAccessOnly: options?.writeAccessOnly,
}}
/>
Expand Down
Loading