0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2025-03-31 22:51:25 -05:00

Merge pull request #4726 from logto-io/gao-console-org-13

refactor(console): fixing to-dos
This commit is contained in:
Gao Sun 2023-10-24 23:42:51 -05:00 committed by GitHub
commit 6068eb3686
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 68 additions and 25 deletions

View file

@ -3,3 +3,9 @@
.rolesTransfer {
height: 360px;
}
.errorMessage {
font: var(--font-body-2);
color: var(--color-error);
margin-top: _.unit(1);
}

View file

@ -7,13 +7,20 @@ import SourceEntitiesBox, { type Props as SourceProps } from './components/Sourc
import TargetEntitiesBox from './components/TargetEntitiesBox';
import * as styles from './index.module.scss';
function EntitiesTransfer<T extends Identifiable>(props: SourceProps<T>) {
type Props<T extends Identifiable> = SourceProps<T> & {
errorMessage?: string;
};
function EntitiesTransfer<T extends Identifiable>({ errorMessage, ...props }: Props<T>) {
return (
<div className={classNames(transferLayout.container, styles.rolesTransfer)}>
<SourceEntitiesBox {...props} />
<div className={transferLayout.verticalBar} />
<TargetEntitiesBox {...props} />
</div>
<>
<div className={classNames(transferLayout.container, styles.rolesTransfer)}>
<SourceEntitiesBox {...props} />
<div className={transferLayout.verticalBar} />
<TargetEntitiesBox {...props} />
</div>
{errorMessage && <div className={styles.errorMessage}>{errorMessage}</div>}
</>
);
}

View file

@ -145,7 +145,7 @@ function MultiSelect<T extends string>({
className={styles.dropdown}
anchorRef={selectRef}
>
{filteredOptions.length === 0 && <div className={styles.noResult}>No result</div>}
{filteredOptions.length === 0 && <div className={styles.noResult}>{t('errors.empty')}</div>}
{filteredOptions.map(({ value, title }) => (
<DropdownItem
key={value}

View file

@ -27,12 +27,10 @@ function AddMembersToOrganization({ organization, isOpen, onClose }: Props) {
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
const tAction = useActionTranslation();
const api = useApi();
const {
reset,
control,
handleSubmit,
formState: { errors }, // TODO: handle errors
} = useForm<{ users: User[]; scopes: Array<Option<string>> }>({
const { reset, control, handleSubmit } = useForm<{
users: User[];
scopes: Array<Option<string>>;
}>({
defaultValues: { users: [], scopes: [] },
});
const [isLoading, setIsLoading] = useState(false);
@ -101,8 +99,17 @@ function AddMembersToOrganization({ organization, isOpen, onClose }: Props) {
<Controller
name="users"
control={control}
render={({ field: { onChange, value } }) => (
rules={{
validate: (value) => {
if (value.length === 0) {
return t('organization_details.at_least_one_user');
}
return true;
},
}}
render={({ field: { onChange, value }, fieldState: { error } }) => (
<EntitiesTransfer
errorMessage={error?.message}
searchProps={{
pathname: 'api/users',
parameters: {
@ -110,7 +117,7 @@ function AddMembersToOrganization({ organization, isOpen, onClose }: Props) {
},
}}
selectedEntities={value}
emptyPlaceholder="errors.email_pattern_error"
emptyPlaceholder="errors.empty"
renderEntity={(entity) => <UserItem entity={entity} />}
onChange={onChange}
/>

View file

@ -46,16 +46,8 @@ function Members({ organization }: Props) {
const tAction = useActionTranslation();
const [isModalOpen, setIsModalOpen] = useState(false);
const [userToBeEdited, setUserToBeEdited] = useState<UserWithOrganizationRoles>();
if (error) {
return null; // TODO: error handling
}
if (!response) {
return null; // TODO: loading
}
const [data, totalCount] = response;
const isLoading = !response && !error;
const [data, totalCount] = response ?? [];
return (
<>
@ -66,6 +58,8 @@ function Members({ organization }: Props) {
pageSize,
onChange: setPage,
}}
isLoading={isLoading}
errorMessage={error?.toString()}
rowGroups={[{ key: 'data', data }]}
columns={[
{

View file

@ -39,6 +39,8 @@ const organization_details = {
search_role_placeholder: 'Type to search for roles',
/** UNTRANSLATED */
search_user_placeholder: 'Type to search for users',
/** UNTRANSLATED */
at_least_one_user: 'At least one user is required.',
};
export default Object.freeze(organization_details);

View file

@ -21,6 +21,7 @@ const organization_details = {
'Once removed, the user will lose their membership and roles in this organization. This action cannot be undone.',
search_role_placeholder: 'Type to search for roles',
search_user_placeholder: 'Type to search for users',
at_least_one_user: 'At least one user is required.',
};
export default Object.freeze(organization_details);

View file

@ -39,6 +39,8 @@ const organization_details = {
search_role_placeholder: 'Type to search for roles',
/** UNTRANSLATED */
search_user_placeholder: 'Type to search for users',
/** UNTRANSLATED */
at_least_one_user: 'At least one user is required.',
};
export default Object.freeze(organization_details);

View file

@ -39,6 +39,8 @@ const organization_details = {
search_role_placeholder: 'Type to search for roles',
/** UNTRANSLATED */
search_user_placeholder: 'Type to search for users',
/** UNTRANSLATED */
at_least_one_user: 'At least one user is required.',
};
export default Object.freeze(organization_details);

View file

@ -39,6 +39,8 @@ const organization_details = {
search_role_placeholder: 'Type to search for roles',
/** UNTRANSLATED */
search_user_placeholder: 'Type to search for users',
/** UNTRANSLATED */
at_least_one_user: 'At least one user is required.',
};
export default Object.freeze(organization_details);

View file

@ -39,6 +39,8 @@ const organization_details = {
search_role_placeholder: 'Type to search for roles',
/** UNTRANSLATED */
search_user_placeholder: 'Type to search for users',
/** UNTRANSLATED */
at_least_one_user: 'At least one user is required.',
};
export default Object.freeze(organization_details);

View file

@ -39,6 +39,8 @@ const organization_details = {
search_role_placeholder: 'Type to search for roles',
/** UNTRANSLATED */
search_user_placeholder: 'Type to search for users',
/** UNTRANSLATED */
at_least_one_user: 'At least one user is required.',
};
export default Object.freeze(organization_details);

View file

@ -39,6 +39,8 @@ const organization_details = {
search_role_placeholder: 'Type to search for roles',
/** UNTRANSLATED */
search_user_placeholder: 'Type to search for users',
/** UNTRANSLATED */
at_least_one_user: 'At least one user is required.',
};
export default Object.freeze(organization_details);

View file

@ -39,6 +39,8 @@ const organization_details = {
search_role_placeholder: 'Type to search for roles',
/** UNTRANSLATED */
search_user_placeholder: 'Type to search for users',
/** UNTRANSLATED */
at_least_one_user: 'At least one user is required.',
};
export default Object.freeze(organization_details);

View file

@ -39,6 +39,8 @@ const organization_details = {
search_role_placeholder: 'Type to search for roles',
/** UNTRANSLATED */
search_user_placeholder: 'Type to search for users',
/** UNTRANSLATED */
at_least_one_user: 'At least one user is required.',
};
export default Object.freeze(organization_details);

View file

@ -39,6 +39,8 @@ const organization_details = {
search_role_placeholder: 'Type to search for roles',
/** UNTRANSLATED */
search_user_placeholder: 'Type to search for users',
/** UNTRANSLATED */
at_least_one_user: 'At least one user is required.',
};
export default Object.freeze(organization_details);

View file

@ -39,6 +39,8 @@ const organization_details = {
search_role_placeholder: 'Type to search for roles',
/** UNTRANSLATED */
search_user_placeholder: 'Type to search for users',
/** UNTRANSLATED */
at_least_one_user: 'At least one user is required.',
};
export default Object.freeze(organization_details);

View file

@ -39,6 +39,8 @@ const organization_details = {
search_role_placeholder: 'Type to search for roles',
/** UNTRANSLATED */
search_user_placeholder: 'Type to search for users',
/** UNTRANSLATED */
at_least_one_user: 'At least one user is required.',
};
export default Object.freeze(organization_details);

View file

@ -39,6 +39,8 @@ const organization_details = {
search_role_placeholder: 'Type to search for roles',
/** UNTRANSLATED */
search_user_placeholder: 'Type to search for users',
/** UNTRANSLATED */
at_least_one_user: 'At least one user is required.',
};
export default Object.freeze(organization_details);

View file

@ -39,6 +39,8 @@ const organization_details = {
search_role_placeholder: 'Type to search for roles',
/** UNTRANSLATED */
search_user_placeholder: 'Type to search for users',
/** UNTRANSLATED */
at_least_one_user: 'At least one user is required.',
};
export default Object.freeze(organization_details);