|
@@ -1,43 +1,53 @@
|
|
|
-import React, {
|
|
|
|
|
- useEffect, useState, useCallback, type JSX,
|
|
|
|
|
-} from 'react';
|
|
|
|
|
-
|
|
|
|
|
-import { PageGrant, GroupType } from '@growi/core';
|
|
|
|
|
|
|
+import { GroupType, PageGrant } from '@growi/core';
|
|
|
|
|
+import { type JSX, useCallback, useEffect, useState } from 'react';
|
|
|
import { useTranslation } from 'react-i18next';
|
|
import { useTranslation } from 'react-i18next';
|
|
|
|
|
+import { Modal, ModalBody, ModalFooter, ModalHeader } from 'reactstrap';
|
|
|
import {
|
|
import {
|
|
|
- Modal, ModalHeader, ModalBody, ModalFooter,
|
|
|
|
|
-} from 'reactstrap';
|
|
|
|
|
-
|
|
|
|
|
-import { UserGroupPageGrantStatus, type IPageGrantData } from '~/interfaces/page';
|
|
|
|
|
-import type { PopulatedGrantedGroup, IRecordApplicableGrant, IResGrantData } from '~/interfaces/page-grant';
|
|
|
|
|
|
|
+ type IPageGrantData,
|
|
|
|
|
+ UserGroupPageGrantStatus,
|
|
|
|
|
+} from '~/interfaces/page';
|
|
|
|
|
+import type {
|
|
|
|
|
+ IRecordApplicableGrant,
|
|
|
|
|
+ IResGrantData,
|
|
|
|
|
+ PopulatedGrantedGroup,
|
|
|
|
|
+} from '~/interfaces/page-grant';
|
|
|
import { useCurrentUser } from '~/states/global';
|
|
import { useCurrentUser } from '~/states/global';
|
|
|
import { useCurrentPageData } from '~/states/page';
|
|
import { useCurrentPageData } from '~/states/page';
|
|
|
import { useSWRxApplicableGrant, useSWRxCurrentGrantData } from '~/stores/page';
|
|
import { useSWRxApplicableGrant, useSWRxCurrentGrantData } from '~/stores/page';
|
|
|
|
|
|
|
|
type ModalProps = {
|
|
type ModalProps = {
|
|
|
- isOpen: boolean
|
|
|
|
|
- pageId: string
|
|
|
|
|
- dataApplicableGrant: IRecordApplicableGrant
|
|
|
|
|
- currentAndParentPageGrantData: IResGrantData
|
|
|
|
|
- close(): void
|
|
|
|
|
-}
|
|
|
|
|
|
|
+ isOpen: boolean;
|
|
|
|
|
+ pageId: string;
|
|
|
|
|
+ dataApplicableGrant: IRecordApplicableGrant;
|
|
|
|
|
+ currentAndParentPageGrantData: IResGrantData;
|
|
|
|
|
+ close(): void;
|
|
|
|
|
+};
|
|
|
|
|
|
|
|
const FixPageGrantModal = (props: ModalProps): JSX.Element => {
|
|
const FixPageGrantModal = (props: ModalProps): JSX.Element => {
|
|
|
const { t } = useTranslation();
|
|
const { t } = useTranslation();
|
|
|
|
|
|
|
|
const {
|
|
const {
|
|
|
- isOpen, pageId, dataApplicableGrant, currentAndParentPageGrantData, close,
|
|
|
|
|
|
|
+ isOpen,
|
|
|
|
|
+ pageId,
|
|
|
|
|
+ dataApplicableGrant,
|
|
|
|
|
+ currentAndParentPageGrantData,
|
|
|
|
|
+ close,
|
|
|
} = props;
|
|
} = props;
|
|
|
|
|
|
|
|
- const [selectedGrant, setSelectedGrant] = useState<PageGrant>(PageGrant.GRANT_RESTRICTED);
|
|
|
|
|
|
|
+ const [selectedGrant, setSelectedGrant] = useState<PageGrant>(
|
|
|
|
|
+ PageGrant.GRANT_RESTRICTED,
|
|
|
|
|
+ );
|
|
|
|
|
|
|
|
const [isGroupSelectModalShown, setIsGroupSelectModalShown] = useState(false);
|
|
const [isGroupSelectModalShown, setIsGroupSelectModalShown] = useState(false);
|
|
|
- const [selectedGroups, setSelectedGroups] = useState<PopulatedGrantedGroup[]>([]);
|
|
|
|
|
|
|
+ const [selectedGroups, setSelectedGroups] = useState<PopulatedGrantedGroup[]>(
|
|
|
|
|
+ [],
|
|
|
|
|
+ );
|
|
|
|
|
|
|
|
// Alert message state
|
|
// Alert message state
|
|
|
const [shouldShowModalAlert, setShowModalAlert] = useState<boolean>(false);
|
|
const [shouldShowModalAlert, setShowModalAlert] = useState<boolean>(false);
|
|
|
|
|
|
|
|
- const applicableGroups = dataApplicableGrant[PageGrant.GRANT_USER_GROUP]?.applicableGroups;
|
|
|
|
|
|
|
+ const applicableGroups =
|
|
|
|
|
+ dataApplicableGrant[PageGrant.GRANT_USER_GROUP]?.applicableGroups;
|
|
|
|
|
|
|
|
// Reset state when opened
|
|
// Reset state when opened
|
|
|
useEffect(() => {
|
|
useEffect(() => {
|
|
@@ -49,17 +59,21 @@ const FixPageGrantModal = (props: ModalProps): JSX.Element => {
|
|
|
}, [isOpen]);
|
|
}, [isOpen]);
|
|
|
|
|
|
|
|
const groupListItemClickHandler = (group: PopulatedGrantedGroup) => {
|
|
const groupListItemClickHandler = (group: PopulatedGrantedGroup) => {
|
|
|
- if (selectedGroups.find(g => g.item._id === group.item._id) != null) {
|
|
|
|
|
- setSelectedGroups(selectedGroups.filter(g => g.item._id !== group.item._id));
|
|
|
|
|
- }
|
|
|
|
|
- else {
|
|
|
|
|
|
|
+ if (selectedGroups.find((g) => g.item._id === group.item._id) != null) {
|
|
|
|
|
+ setSelectedGroups(
|
|
|
|
|
+ selectedGroups.filter((g) => g.item._id !== group.item._id),
|
|
|
|
|
+ );
|
|
|
|
|
+ } else {
|
|
|
setSelectedGroups([...selectedGroups, group]);
|
|
setSelectedGroups([...selectedGroups, group]);
|
|
|
}
|
|
}
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- const submit = async() => {
|
|
|
|
|
|
|
+ const submit = async () => {
|
|
|
// Validate input values
|
|
// Validate input values
|
|
|
- if (selectedGrant === PageGrant.GRANT_USER_GROUP && selectedGroups.length === 0) {
|
|
|
|
|
|
|
+ if (
|
|
|
|
|
+ selectedGrant === PageGrant.GRANT_USER_GROUP &&
|
|
|
|
|
+ selectedGroups.length === 0
|
|
|
|
|
+ ) {
|
|
|
setShowModalAlert(true);
|
|
setShowModalAlert(true);
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
@@ -70,69 +84,89 @@ const FixPageGrantModal = (props: ModalProps): JSX.Element => {
|
|
|
const apiv3Put = (await import('~/client/util/apiv3-client')).apiv3Put;
|
|
const apiv3Put = (await import('~/client/util/apiv3-client')).apiv3Put;
|
|
|
await apiv3Put(`/page/${pageId}/grant`, {
|
|
await apiv3Put(`/page/${pageId}/grant`, {
|
|
|
grant: selectedGrant,
|
|
grant: selectedGrant,
|
|
|
- userRelatedGrantedGroups: selectedGroups.length !== 0 ? selectedGroups.map((g) => {
|
|
|
|
|
- return { item: g.item._id, type: g.type };
|
|
|
|
|
- }) : null,
|
|
|
|
|
|
|
+ userRelatedGrantedGroups:
|
|
|
|
|
+ selectedGroups.length !== 0
|
|
|
|
|
+ ? selectedGroups.map((g) => {
|
|
|
|
|
+ return { item: g.item._id, type: g.type };
|
|
|
|
|
+ })
|
|
|
|
|
+ : null,
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
const toastSuccess = (await import('~/client/util/toastr')).toastSuccess;
|
|
const toastSuccess = (await import('~/client/util/toastr')).toastSuccess;
|
|
|
toastSuccess(t('Successfully updated'));
|
|
toastSuccess(t('Successfully updated'));
|
|
|
- }
|
|
|
|
|
- catch (err) {
|
|
|
|
|
|
|
+ } catch (err) {
|
|
|
const toastError = (await import('~/client/util/toastr')).toastError;
|
|
const toastError = (await import('~/client/util/toastr')).toastError;
|
|
|
toastError(t('Failed to update'));
|
|
toastError(t('Failed to update'));
|
|
|
}
|
|
}
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- const getGrantLabel = useCallback((isForbidden: boolean, grantData?: IPageGrantData): string => {
|
|
|
|
|
-
|
|
|
|
|
- if (isForbidden) {
|
|
|
|
|
- return t('fix_page_grant.modal.grant_label.isForbidden');
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ const getGrantLabel = useCallback(
|
|
|
|
|
+ (isForbidden: boolean, grantData?: IPageGrantData): string => {
|
|
|
|
|
+ if (isForbidden) {
|
|
|
|
|
+ return t('fix_page_grant.modal.grant_label.isForbidden');
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- if (grantData == null) {
|
|
|
|
|
- return t('fix_page_grant.modal.grant_label.isForbidden');
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ if (grantData == null) {
|
|
|
|
|
+ return t('fix_page_grant.modal.grant_label.isForbidden');
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- if (grantData.grant === 1) {
|
|
|
|
|
- return t('fix_page_grant.modal.grant_label.public');
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ if (grantData.grant === 1) {
|
|
|
|
|
+ return t('fix_page_grant.modal.grant_label.public');
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- if (grantData.grant === 4) {
|
|
|
|
|
- return t('fix_page_grant.modal.radio_btn.only_me');
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ if (grantData.grant === 4) {
|
|
|
|
|
+ return t('fix_page_grant.modal.radio_btn.only_me');
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- if (grantData.grant === 5) {
|
|
|
|
|
- const groupGrantData = grantData.groupGrantData;
|
|
|
|
|
- if (groupGrantData != null) {
|
|
|
|
|
- const userRelatedGrantedGroups = groupGrantData.userRelatedGroups.filter(group => group.status === UserGroupPageGrantStatus.isGranted);
|
|
|
|
|
- if (userRelatedGrantedGroups.length > 0) {
|
|
|
|
|
- const grantedGroupNames = [
|
|
|
|
|
- ...userRelatedGrantedGroups.map(group => group.name),
|
|
|
|
|
- ...groupGrantData.nonUserRelatedGrantedGroups.map(group => group.name),
|
|
|
|
|
- ];
|
|
|
|
|
- return `${t('fix_page_grant.modal.radio_btn.grant_group')} (${grantedGroupNames.join(', ')})`;
|
|
|
|
|
|
|
+ if (grantData.grant === 5) {
|
|
|
|
|
+ const groupGrantData = grantData.groupGrantData;
|
|
|
|
|
+ if (groupGrantData != null) {
|
|
|
|
|
+ const userRelatedGrantedGroups =
|
|
|
|
|
+ groupGrantData.userRelatedGroups.filter(
|
|
|
|
|
+ (group) => group.status === UserGroupPageGrantStatus.isGranted,
|
|
|
|
|
+ );
|
|
|
|
|
+ if (userRelatedGrantedGroups.length > 0) {
|
|
|
|
|
+ const grantedGroupNames = [
|
|
|
|
|
+ ...userRelatedGrantedGroups.map((group) => group.name),
|
|
|
|
|
+ ...groupGrantData.nonUserRelatedGrantedGroups.map(
|
|
|
|
|
+ (group) => group.name,
|
|
|
|
|
+ ),
|
|
|
|
|
+ ];
|
|
|
|
|
+ return `${t('fix_page_grant.modal.radio_btn.grant_group')} (${grantedGroupNames.join(', ')})`;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
- }
|
|
|
|
|
|
|
|
|
|
- return t('fix_page_grant.modal.grant_label.isForbidden');
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ return t('fix_page_grant.modal.grant_label.isForbidden');
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- throw Error('cannot get grant label'); // this error can't be throwed
|
|
|
|
|
- }, [t]);
|
|
|
|
|
|
|
+ throw Error('cannot get grant label'); // this error can't be throwed
|
|
|
|
|
+ },
|
|
|
|
|
+ [t],
|
|
|
|
|
+ );
|
|
|
|
|
|
|
|
const renderGrantDataLabel = useCallback(() => {
|
|
const renderGrantDataLabel = useCallback(() => {
|
|
|
- const { isForbidden, currentPageGrant, parentPageGrant } = currentAndParentPageGrantData;
|
|
|
|
|
|
|
+ const { isForbidden, currentPageGrant, parentPageGrant } =
|
|
|
|
|
+ currentAndParentPageGrantData;
|
|
|
|
|
|
|
|
const currentGrantLabel = getGrantLabel(false, currentPageGrant);
|
|
const currentGrantLabel = getGrantLabel(false, currentPageGrant);
|
|
|
const parentGrantLabel = getGrantLabel(isForbidden, parentPageGrant);
|
|
const parentGrantLabel = getGrantLabel(isForbidden, parentPageGrant);
|
|
|
|
|
|
|
|
return (
|
|
return (
|
|
|
<>
|
|
<>
|
|
|
- <p className="mt-3">{ t('fix_page_grant.modal.grant_label.parentPageGrantLabel') + parentGrantLabel }</p>
|
|
|
|
|
- <p>{ t('fix_page_grant.modal.grant_label.currentPageGrantLabel') + currentGrantLabel }</p>
|
|
|
|
|
- {/* eslint-disable-next-line react/no-danger */}
|
|
|
|
|
- <p dangerouslySetInnerHTML={{ __html: t('fix_page_grant.modal.grant_label.docLink') }} />
|
|
|
|
|
|
|
+ <p className="mt-3">
|
|
|
|
|
+ {t('fix_page_grant.modal.grant_label.parentPageGrantLabel') +
|
|
|
|
|
+ parentGrantLabel}
|
|
|
|
|
+ </p>
|
|
|
|
|
+ <p>
|
|
|
|
|
+ {t('fix_page_grant.modal.grant_label.currentPageGrantLabel') +
|
|
|
|
|
+ currentGrantLabel}
|
|
|
|
|
+ </p>
|
|
|
|
|
+ <p
|
|
|
|
|
+ // biome-ignore lint/security/noDangerouslySetInnerHtml: ignore
|
|
|
|
|
+ dangerouslySetInnerHTML={{
|
|
|
|
|
+ __html: t('fix_page_grant.modal.grant_label.docLink'),
|
|
|
|
|
+ }}
|
|
|
|
|
+ />
|
|
|
</>
|
|
</>
|
|
|
);
|
|
);
|
|
|
}, [t, currentAndParentPageGrantData, getGrantLabel]);
|
|
}, [t, currentAndParentPageGrantData, getGrantLabel]);
|
|
@@ -142,9 +176,7 @@ const FixPageGrantModal = (props: ModalProps): JSX.Element => {
|
|
|
|
|
|
|
|
if (!isGrantAvailable) {
|
|
if (!isGrantAvailable) {
|
|
|
return (
|
|
return (
|
|
|
- <p className="m-5">
|
|
|
|
|
- { t('fix_page_grant.modal.no_grant_available') }
|
|
|
|
|
- </p>
|
|
|
|
|
|
|
+ <p className="m-5">{t('fix_page_grant.modal.no_grant_available')}</p>
|
|
|
);
|
|
);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -152,8 +184,13 @@ const FixPageGrantModal = (props: ModalProps): JSX.Element => {
|
|
|
<>
|
|
<>
|
|
|
<ModalBody>
|
|
<ModalBody>
|
|
|
<div>
|
|
<div>
|
|
|
- {/* eslint-disable-next-line react/no-danger */}
|
|
|
|
|
- <p className="mb-2" dangerouslySetInnerHTML={{ __html: t('fix_page_grant.modal.need_to_fix_grant') }} />
|
|
|
|
|
|
|
+ <p
|
|
|
|
|
+ className="mb-2"
|
|
|
|
|
+ // biome-ignore lint/security/noDangerouslySetInnerHtml: ignore
|
|
|
|
|
+ dangerouslySetInnerHTML={{
|
|
|
|
|
+ __html: t('fix_page_grant.modal.need_to_fix_grant'),
|
|
|
|
|
+ }}
|
|
|
|
|
+ />
|
|
|
|
|
|
|
|
{/* grant data label */}
|
|
{/* grant data label */}
|
|
|
{renderGrantDataLabel()}
|
|
{renderGrantDataLabel()}
|
|
@@ -165,12 +202,17 @@ const FixPageGrantModal = (props: ModalProps): JSX.Element => {
|
|
|
name="grantRestricted"
|
|
name="grantRestricted"
|
|
|
id="grantRestricted"
|
|
id="grantRestricted"
|
|
|
type="radio"
|
|
type="radio"
|
|
|
- disabled={!(PageGrant.GRANT_RESTRICTED in dataApplicableGrant)}
|
|
|
|
|
|
|
+ disabled={
|
|
|
|
|
+ !(PageGrant.GRANT_RESTRICTED in dataApplicableGrant)
|
|
|
|
|
+ }
|
|
|
checked={selectedGrant === PageGrant.GRANT_RESTRICTED}
|
|
checked={selectedGrant === PageGrant.GRANT_RESTRICTED}
|
|
|
onChange={() => setSelectedGrant(PageGrant.GRANT_RESTRICTED)}
|
|
onChange={() => setSelectedGrant(PageGrant.GRANT_RESTRICTED)}
|
|
|
/>
|
|
/>
|
|
|
- <label className="form-label form-check-label" htmlFor="grantRestricted">
|
|
|
|
|
- { t('fix_page_grant.modal.radio_btn.restrected') }
|
|
|
|
|
|
|
+ <label
|
|
|
|
|
+ className="form-label form-check-label"
|
|
|
|
|
+ htmlFor="grantRestricted"
|
|
|
|
|
+ >
|
|
|
|
|
+ {t('fix_page_grant.modal.radio_btn.restrected')}
|
|
|
</label>
|
|
</label>
|
|
|
</div>
|
|
</div>
|
|
|
<div className="form-check mb-3">
|
|
<div className="form-check mb-3">
|
|
@@ -183,8 +225,11 @@ const FixPageGrantModal = (props: ModalProps): JSX.Element => {
|
|
|
checked={selectedGrant === PageGrant.GRANT_OWNER}
|
|
checked={selectedGrant === PageGrant.GRANT_OWNER}
|
|
|
onChange={() => setSelectedGrant(PageGrant.GRANT_OWNER)}
|
|
onChange={() => setSelectedGrant(PageGrant.GRANT_OWNER)}
|
|
|
/>
|
|
/>
|
|
|
- <label className="form-label form-check-label" htmlFor="grantUser">
|
|
|
|
|
- { t('fix_page_grant.modal.radio_btn.only_me') }
|
|
|
|
|
|
|
+ <label
|
|
|
|
|
+ className="form-label form-check-label"
|
|
|
|
|
+ htmlFor="grantUser"
|
|
|
|
|
+ >
|
|
|
|
|
+ {t('fix_page_grant.modal.radio_btn.only_me')}
|
|
|
</label>
|
|
</label>
|
|
|
</div>
|
|
</div>
|
|
|
<div className="form-check d-flex mb-3">
|
|
<div className="form-check d-flex mb-3">
|
|
@@ -193,12 +238,17 @@ const FixPageGrantModal = (props: ModalProps): JSX.Element => {
|
|
|
name="grantUserGroup"
|
|
name="grantUserGroup"
|
|
|
id="grantUserGroup"
|
|
id="grantUserGroup"
|
|
|
type="radio"
|
|
type="radio"
|
|
|
- disabled={!(PageGrant.GRANT_USER_GROUP in dataApplicableGrant)}
|
|
|
|
|
|
|
+ disabled={
|
|
|
|
|
+ !(PageGrant.GRANT_USER_GROUP in dataApplicableGrant)
|
|
|
|
|
+ }
|
|
|
checked={selectedGrant === PageGrant.GRANT_USER_GROUP}
|
|
checked={selectedGrant === PageGrant.GRANT_USER_GROUP}
|
|
|
onChange={() => setSelectedGrant(PageGrant.GRANT_USER_GROUP)}
|
|
onChange={() => setSelectedGrant(PageGrant.GRANT_USER_GROUP)}
|
|
|
/>
|
|
/>
|
|
|
- <label className="form-label form-check-label" htmlFor="grantUserGroup">
|
|
|
|
|
- { t('fix_page_grant.modal.radio_btn.grant_group') }
|
|
|
|
|
|
|
+ <label
|
|
|
|
|
+ className="form-label form-check-label"
|
|
|
|
|
+ htmlFor="grantUserGroup"
|
|
|
|
|
+ >
|
|
|
|
|
+ {t('fix_page_grant.modal.radio_btn.grant_group')}
|
|
|
</label>
|
|
</label>
|
|
|
<div className="dropdown ms-2">
|
|
<div className="dropdown ms-2">
|
|
|
<button
|
|
<button
|
|
@@ -208,28 +258,24 @@ const FixPageGrantModal = (props: ModalProps): JSX.Element => {
|
|
|
onClick={() => setIsGroupSelectModalShown(true)}
|
|
onClick={() => setIsGroupSelectModalShown(true)}
|
|
|
>
|
|
>
|
|
|
<span className="float-start ms-2">
|
|
<span className="float-start ms-2">
|
|
|
- {
|
|
|
|
|
- selectedGroups.length === 0
|
|
|
|
|
- ? t('fix_page_grant.modal.select_group_default_text')
|
|
|
|
|
- : selectedGroups.map(g => g.item.name).join(', ')
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ {selectedGroups.length === 0
|
|
|
|
|
+ ? t('fix_page_grant.modal.select_group_default_text')
|
|
|
|
|
+ : selectedGroups.map((g) => g.item.name).join(', ')}
|
|
|
</span>
|
|
</span>
|
|
|
</button>
|
|
</button>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
- {
|
|
|
|
|
- shouldShowModalAlert && (
|
|
|
|
|
- <p className="alert alert-warning">
|
|
|
|
|
- {t('fix_page_grant.modal.alert_message')}
|
|
|
|
|
- </p>
|
|
|
|
|
- )
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ {shouldShowModalAlert && (
|
|
|
|
|
+ <p className="alert alert-warning">
|
|
|
|
|
+ {t('fix_page_grant.modal.alert_message')}
|
|
|
|
|
+ </p>
|
|
|
|
|
+ )}
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
</ModalBody>
|
|
</ModalBody>
|
|
|
<ModalFooter>
|
|
<ModalFooter>
|
|
|
<button type="button" className="btn btn-primary" onClick={submit}>
|
|
<button type="button" className="btn btn-primary" onClick={submit}>
|
|
|
- { t('fix_page_grant.modal.btn_label') }
|
|
|
|
|
|
|
+ {t('fix_page_grant.modal.btn_label')}
|
|
|
</button>
|
|
</button>
|
|
|
</ModalFooter>
|
|
</ModalFooter>
|
|
|
</>
|
|
</>
|
|
@@ -240,7 +286,7 @@ const FixPageGrantModal = (props: ModalProps): JSX.Element => {
|
|
|
<>
|
|
<>
|
|
|
<Modal size="lg" isOpen={isOpen} toggle={close}>
|
|
<Modal size="lg" isOpen={isOpen} toggle={close}>
|
|
|
<ModalHeader tag="h4" toggle={close}>
|
|
<ModalHeader tag="h4" toggle={close}>
|
|
|
- { t('fix_page_grant.modal.title') }
|
|
|
|
|
|
|
+ {t('fix_page_grant.modal.title')}
|
|
|
</ModalHeader>
|
|
</ModalHeader>
|
|
|
{renderModalBodyAndFooter()}
|
|
{renderModalBodyAndFooter()}
|
|
|
</Modal>
|
|
</Modal>
|
|
@@ -249,31 +295,46 @@ const FixPageGrantModal = (props: ModalProps): JSX.Element => {
|
|
|
isOpen={isGroupSelectModalShown}
|
|
isOpen={isGroupSelectModalShown}
|
|
|
toggle={() => setIsGroupSelectModalShown(false)}
|
|
toggle={() => setIsGroupSelectModalShown(false)}
|
|
|
>
|
|
>
|
|
|
- <ModalHeader tag="h4" toggle={() => setIsGroupSelectModalShown(false)}>
|
|
|
|
|
|
|
+ <ModalHeader
|
|
|
|
|
+ tag="h4"
|
|
|
|
|
+ toggle={() => setIsGroupSelectModalShown(false)}
|
|
|
|
|
+ >
|
|
|
{t('user_group.select_group')}
|
|
{t('user_group.select_group')}
|
|
|
</ModalHeader>
|
|
</ModalHeader>
|
|
|
<ModalBody>
|
|
<ModalBody>
|
|
|
- <>
|
|
|
|
|
- { applicableGroups.map((group) => {
|
|
|
|
|
- const groupIsGranted = selectedGroups?.find(g => g.item._id === group.item._id) != null;
|
|
|
|
|
- const activeClass = groupIsGranted ? 'active' : '';
|
|
|
|
|
-
|
|
|
|
|
- return (
|
|
|
|
|
- <button
|
|
|
|
|
- className={`btn btn-outline-primary w-100 d-flex justify-content-start mb-3 align-items-center p-3 ${activeClass}`}
|
|
|
|
|
- type="button"
|
|
|
|
|
- key={group.item._id}
|
|
|
|
|
- onClick={() => groupListItemClickHandler(group)}
|
|
|
|
|
- >
|
|
|
|
|
- <span className="align-middle"><input type="checkbox" checked={groupIsGranted} /></span>
|
|
|
|
|
- <h5 className="d-inline-block ml-3">{group.item.name}</h5>
|
|
|
|
|
- {group.type === GroupType.externalUserGroup && <span className="ml-2 badge badge-pill badge-info">{group.item.provider}</span>}
|
|
|
|
|
- {/* TODO: Replace <div className="small">(TBD) List group members</div> */}
|
|
|
|
|
- </button>
|
|
|
|
|
- );
|
|
|
|
|
- }) }
|
|
|
|
|
- <button type="button" className="btn btn-primary mt-2 float-right" onClick={() => setIsGroupSelectModalShown(false)}>{t('Done')}</button>
|
|
|
|
|
- </>
|
|
|
|
|
|
|
+ {applicableGroups.map((group) => {
|
|
|
|
|
+ const groupIsGranted =
|
|
|
|
|
+ selectedGroups?.find((g) => g.item._id === group.item._id) !=
|
|
|
|
|
+ null;
|
|
|
|
|
+ const activeClass = groupIsGranted ? 'active' : '';
|
|
|
|
|
+
|
|
|
|
|
+ return (
|
|
|
|
|
+ <button
|
|
|
|
|
+ className={`btn btn-outline-primary w-100 d-flex justify-content-start mb-3 align-items-center p-3 ${activeClass}`}
|
|
|
|
|
+ type="button"
|
|
|
|
|
+ key={group.item._id}
|
|
|
|
|
+ onClick={() => groupListItemClickHandler(group)}
|
|
|
|
|
+ >
|
|
|
|
|
+ <span className="align-middle">
|
|
|
|
|
+ <input type="checkbox" checked={groupIsGranted} />
|
|
|
|
|
+ </span>
|
|
|
|
|
+ <h5 className="d-inline-block ml-3">{group.item.name}</h5>
|
|
|
|
|
+ {group.type === GroupType.externalUserGroup && (
|
|
|
|
|
+ <span className="ml-2 badge badge-pill badge-info">
|
|
|
|
|
+ {group.item.provider}
|
|
|
|
|
+ </span>
|
|
|
|
|
+ )}
|
|
|
|
|
+ {/* TODO: Replace <div className="small">(TBD) List group members</div> */}
|
|
|
|
|
+ </button>
|
|
|
|
|
+ );
|
|
|
|
|
+ })}
|
|
|
|
|
+ <button
|
|
|
|
|
+ type="button"
|
|
|
|
|
+ className="btn btn-primary mt-2 float-right"
|
|
|
|
|
+ onClick={() => setIsGroupSelectModalShown(false)}
|
|
|
|
|
+ >
|
|
|
|
|
+ {t('Done')}
|
|
|
|
|
+ </button>
|
|
|
</ModalBody>
|
|
</ModalBody>
|
|
|
</Modal>
|
|
</Modal>
|
|
|
)}
|
|
)}
|
|
@@ -291,18 +352,27 @@ export const FixPageGrantAlert = (): JSX.Element => {
|
|
|
|
|
|
|
|
const [isOpen, setOpen] = useState<boolean>(false);
|
|
const [isOpen, setOpen] = useState<boolean>(false);
|
|
|
|
|
|
|
|
- const { data: dataIsGrantNormalized } = useSWRxCurrentGrantData(currentUser != null ? pageId : null);
|
|
|
|
|
- const { data: dataApplicableGrant } = useSWRxApplicableGrant(currentUser != null ? pageId : null);
|
|
|
|
|
|
|
+ const { data: dataIsGrantNormalized } = useSWRxCurrentGrantData(
|
|
|
|
|
+ currentUser != null ? pageId : null,
|
|
|
|
|
+ );
|
|
|
|
|
+ const { data: dataApplicableGrant } = useSWRxApplicableGrant(
|
|
|
|
|
+ currentUser != null ? pageId : null,
|
|
|
|
|
+ );
|
|
|
|
|
|
|
|
// Dependencies
|
|
// Dependencies
|
|
|
if (pageData == null) {
|
|
if (pageData == null) {
|
|
|
|
|
+ // biome-ignore lint/complexity/noUselessFragments: ignore
|
|
|
return <></>;
|
|
return <></>;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (!hasParent) {
|
|
if (!hasParent) {
|
|
|
|
|
+ // biome-ignore lint/complexity/noUselessFragments: ignore
|
|
|
return <></>;
|
|
return <></>;
|
|
|
}
|
|
}
|
|
|
- if (dataIsGrantNormalized?.isGrantNormalized == null || dataIsGrantNormalized.isGrantNormalized) {
|
|
|
|
|
|
|
+ if (
|
|
|
|
|
+ dataIsGrantNormalized?.isGrantNormalized == null ||
|
|
|
|
|
+ dataIsGrantNormalized.isGrantNormalized
|
|
|
|
|
+ ) {
|
|
|
return <></>;
|
|
return <></>;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -310,27 +380,31 @@ export const FixPageGrantAlert = (): JSX.Element => {
|
|
|
<>
|
|
<>
|
|
|
<div className="alert alert-warning py-3 ps-4 d-flex flex-column flex-lg-row">
|
|
<div className="alert alert-warning py-3 ps-4 d-flex flex-column flex-lg-row">
|
|
|
<div className="flex-grow-1 d-flex align-items-center">
|
|
<div className="flex-grow-1 d-flex align-items-center">
|
|
|
- <span className="material-symbols-outlined mx-1" aria-hidden="true">error</span>
|
|
|
|
|
|
|
+ <span className="material-symbols-outlined mx-1" aria-hidden="true">
|
|
|
|
|
+ error
|
|
|
|
|
+ </span>
|
|
|
{t('fix_page_grant.alert.description')}
|
|
{t('fix_page_grant.alert.description')}
|
|
|
</div>
|
|
</div>
|
|
|
<div className="d-flex align-items-end align-items-lg-center">
|
|
<div className="d-flex align-items-end align-items-lg-center">
|
|
|
- <button type="button" className="btn btn-info btn-sm rounded-pill px-3" onClick={() => setOpen(true)}>
|
|
|
|
|
|
|
+ <button
|
|
|
|
|
+ type="button"
|
|
|
|
|
+ className="btn btn-info btn-sm rounded-pill px-3"
|
|
|
|
|
+ onClick={() => setOpen(true)}
|
|
|
|
|
+ >
|
|
|
{t('fix_page_grant.alert.btn_label')}
|
|
{t('fix_page_grant.alert.btn_label')}
|
|
|
</button>
|
|
</button>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
- {
|
|
|
|
|
- pageId != null && dataApplicableGrant != null && (
|
|
|
|
|
- <FixPageGrantModal
|
|
|
|
|
- isOpen={isOpen}
|
|
|
|
|
- pageId={pageId}
|
|
|
|
|
- dataApplicableGrant={dataApplicableGrant}
|
|
|
|
|
- currentAndParentPageGrantData={dataIsGrantNormalized.grantData}
|
|
|
|
|
- close={() => setOpen(false)}
|
|
|
|
|
- />
|
|
|
|
|
- )
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ {pageId != null && dataApplicableGrant != null && (
|
|
|
|
|
+ <FixPageGrantModal
|
|
|
|
|
+ isOpen={isOpen}
|
|
|
|
|
+ pageId={pageId}
|
|
|
|
|
+ dataApplicableGrant={dataApplicableGrant}
|
|
|
|
|
+ currentAndParentPageGrantData={dataIsGrantNormalized.grantData}
|
|
|
|
|
+ close={() => setOpen(false)}
|
|
|
|
|
+ />
|
|
|
|
|
+ )}
|
|
|
</>
|
|
</>
|
|
|
);
|
|
);
|
|
|
};
|
|
};
|