Skip to content

Commit

Permalink
Implemented approval on detail page
Browse files Browse the repository at this point in the history
  • Loading branch information
rmathis committed Oct 19, 2022
1 parent 24094ee commit 8ff78b6
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 52 deletions.
37 changes: 6 additions & 31 deletions ui/src/app/admin/container/ApprovalActions.js
Original file line number Diff line number Diff line change
@@ -1,44 +1,23 @@
import React from 'react';
import { DeleteConfirmation } from '../../core/components/DeleteConfirmation';
import { useMetadataApprover, useMetadataEntity } from '../../metadata/hooks/api';
import { useMetadataApprover } from '../../metadata/hooks/api';

import { NotificationContext, createNotificationAction, NotificationTypes } from '../../notifications/hoc/Notifications';

export function ApprovalActions ({type = 'source', children}) {

const { dispatch } = React.useContext(NotificationContext);

const { del, response } = useMetadataEntity('source', {
cachePolicy: 'no-cache'
});

const activator = useMetadataApprover('source');
const approver = useMetadataApprover('source');

async function approveEntity(entity, enabled, cb = () => {}) {
await activator.patch(`${type === 'source' ? entity.id : entity.resourceId}/${enabled ? 'approve' : 'unapprove'}`);
if (activator?.response.ok) {
await approver.patch(`${type === 'source' ? entity.id : entity.resourceId}/${enabled ? 'approve' : 'unapprove'}`);
if (approver?.response.ok) {
dispatch(createNotificationAction(
`Metadata ${type} has been ${enabled ? 'approved' : 'unapproved'}.`
));
cb();
} else {
const { errorCode, errorMessage, cause } = activator?.response?.data;
dispatch(createNotificationAction(
`${errorCode}: ${errorMessage} ${cause ? `-${cause}` : ''}`,
NotificationTypes.ERROR
));
}
}

async function deleteEntity(id, cb = () => {}) {
await del(`/${id}`);
if (response.ok) {
dispatch(createNotificationAction(
`Metadata ${type} has been deleted.`
));
cb();
} else {
const { errorCode, errorMessage, cause } = activator?.response?.data;
const { errorCode, errorMessage, cause } = approver?.response?.data;
dispatch(createNotificationAction(
`${errorCode}: ${errorMessage} ${cause ? `-${cause}` : ''}`,
NotificationTypes.ERROR
Expand All @@ -47,10 +26,6 @@ export function ApprovalActions ({type = 'source', children}) {
}

return (
<DeleteConfirmation title={`message.delete-${type}-title`} body={`message.delete-${type}-body`}>
{(block) =>
<>{children(approveEntity, (id, cb) => block(() => deleteEntity(id, cb)))}</>
}
</DeleteConfirmation>
<>{children(approveEntity)}</>
);
}
5 changes: 0 additions & 5 deletions ui/src/app/core/user/UserContext.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,6 @@ function useCanEnable() {
return isAdmin || isEnabler;
}

function useCanApprove() {
return true;
}

function useIsApprover() {
const user = useCurrentUser();
return user.canApprove;
Expand Down Expand Up @@ -114,7 +110,6 @@ export {
useIsAdminOrInGroup,
useIsApprover,
useCanEnable,
useCanApprove,
useCurrentUserLoading,
useCurrentUserLoader,
useUserGroupRegexValidator,
Expand Down
36 changes: 21 additions & 15 deletions ui/src/app/metadata/domain/source/component/SourceList.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ export default function SourceList({ entities, onDelete, onEnable, onApprove, on
<th className="w-25"><Translate value="label.entity-id">Entity ID</Translate></th>
<th className=""><Translate value="label.author">Author</Translate></th>
<th className=""><Translate value="label.creation-date">Created Date</Translate></th>
<th className="text-center"><Translate value="label.approval">Approval</Translate></th>
<th className="text-center"><Translate value="label.enabled">Enabled</Translate></th>
{onApprove && <th className="text-center"><Translate value="label.approval">Approval</Translate></th>}
{isAdmin && onChangeGroup && <th className=""><Translate value="label.group">Group</Translate></th> }
{onDelete && isAdmin &&
<th className="w-auto">
Expand All @@ -62,38 +62,44 @@ export default function SourceList({ entities, onDelete, onEnable, onApprove, on
<td className="align-middle"><FormattedDate date={source.createdDate} /></td>
<td className="text-center align-middle">
<span className="d-flex justify-content-center align-items-center">
{onEnable && (canEnable && source.approved) ?
{onApprove ?
<Form.Check
type="switch"
id={`enable-switch-${source.id}`}
id={`approve-switch-${source.id}`}
size="lg"
aria-label={translator(source.serviceEnabled ? 'label.disable' : 'label.enable')}
onChange={({ target: { checked } }) => onEnable(source, checked)}
checked={source.serviceEnabled}
aria-label={translator(source.approved ? 'label.disapprove' : 'label.approve')}
onChange={({ target: { checked } }) => onApprove(source, checked)}
checked={source.approved}
>
</Form.Check>
:
<Badge variant={source.serviceEnabled ? 'success' : 'danger'}>
<Translate value={source.serviceEnabled ? 'value.enabled' : 'value.disabled'}></Translate>
<Badge bg={source.approved ? 'success' : 'danger'}>
<Translate value={source.approved ? 'value.approved' : 'value.disapproved'}></Translate>
</Badge>
}
}
</span>
</td>
{onApprove &&
<td className="text-center align-middle">
<span className="d-flex justify-content-center align-items-center">
{onEnable && (canEnable && source.approved) ?
<Form.Check
type="switch"
id={`approve-switch-${source.id}`}
id={`enable-switch-${source.id}`}
size="lg"
aria-label={translator(source.approved ? 'label.disapprove' : 'label.approve')}
onChange={({ target: { checked } }) => onApprove(source, checked)}
checked={source.approved}
aria-label={translator(source.serviceEnabled ? 'label.disable' : 'label.enable')}
onChange={({ target: { checked } }) => onEnable(source, checked)}
checked={source.serviceEnabled}
>
</Form.Check>
:
<Badge bg={source.serviceEnabled ? 'success' : 'danger'}>
<Translate value={source.serviceEnabled ? 'value.enabled' : 'value.disabled'}></Translate>
</Badge>
}
</span>
</td>
}


{isAdmin && onChangeGroup &&
<td className="align-middle">
<label htmlFor={`group-${source.serviceProviderName}`} className="sr-only"><Translate value="action.source-group">Group</Translate></label>
Expand Down
17 changes: 16 additions & 1 deletion ui/src/app/metadata/view/MetadataOptions.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ import { MetadataFilterConfigurationList } from '../domain/filter/component/Meta
import { MetadataFilterTypes } from '../domain/filter';
import { useMetadataSchema } from '../hooks/schema';
import { FilterableProviders } from '../domain/provider';
import { useCanEnable, useIsAdmin } from '../../core/user/UserContext';
import { useCanEnable, useIsAdmin, useIsApprover } from '../../core/user/UserContext';
import { ApprovalActions } from '../../admin/container/ApprovalActions';

export function MetadataOptions ({reload}) {

Expand Down Expand Up @@ -54,6 +55,7 @@ export function MetadataOptions ({reload}) {

const canEnable = useCanEnable();
const isAdmin = useIsAdmin();
const canApprove = useIsApprover();

return (
<MetadataActions type={type}>
Expand All @@ -78,6 +80,19 @@ export function MetadataOptions ({reload}) {
<FontAwesomeIcon size="lg" icon={enabled ? faToggleOn : faToggleOff} />
</Button>
}
{canApprove &&
<ApprovalActions>
{(approve) =>
<Button variant={metadata.approved ? 'outline-success' : 'outline-success' } size="sm" className=""
onClick={() => approve(metadata, !metadata.approved, reload)}>
<span className=" me-1">
<Translate value={metadata.approved ? 'label.disapprove' : 'label.approve'} />
</span>
<FontAwesomeIcon size="lg" icon={metadata.approved ? faToggleOn : faToggleOff} />
</Button>
}
</ApprovalActions>
}
{type === 'source' && remove && isAdmin &&
<Button
size="sm"
Expand Down

0 comments on commit 8ff78b6

Please sign in to comment.