Skip to content

Commit

Permalink
Updated bundle admin
Browse files Browse the repository at this point in the history
  • Loading branch information
rmathis committed Sep 2, 2021
1 parent 1d744f7 commit c097f0c
Show file tree
Hide file tree
Showing 13 changed files with 249 additions and 21 deletions.
38 changes: 38 additions & 0 deletions backend/src/main/resources/bundle.schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"type": "object",
"required": [
"name"
],
"properties": {
"name": {
"type": "string",
"title": "label.bundle-name",
"description": "tooltip.bundle-name",
"minLength": 1,
"maxLength": 255
},
"attributes": {
"type": "array",
"title": "label.attributes",
"description": "Attribute table - select the attributes you want to bundle (default unchecked)",
"items": {
"type": "string",
"enum": [
"eduPersonPrincipalName",
"uid",
"mail",
"surname",
"givenName",
"eduPersonAffiliation",
"eduPersonScopedAffiliation",
"eduPersonPrimaryAffiliation",
"eduPersonEntitlement",
"eduPersonAssurance",
"eduPersonUniqueId",
"employeeNumber"
]
},
"uniqueItems": true
}
}
}
6 changes: 5 additions & 1 deletion backend/src/main/resources/i18n/messages.properties
Original file line number Diff line number Diff line change
Expand Up @@ -493,7 +493,11 @@ label.by=By
label.source=Metadata Source
label.provider=Metadata Provider


label.bundle-name=Bundle name
action.add-new-bundle=Add bundle
tooltip.bundle-name=A user friendly name to identify the bundle
action.attribute-bundles=Attribute bundles
label.new-attribute-bundle=New attribute bundle

message.user-role-admin-group=Cannot change group for ROLE_ADMIN users.

Expand Down
38 changes: 38 additions & 0 deletions ui/public/assets/schema/attribute/bundle.schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"type": "object",
"required": [
"name"
],
"properties": {
"name": {
"type": "string",
"title": "label.bundle-name",
"description": "tooltip.bundle-name",
"minLength": 1,
"maxLength": 255
},
"attributes": {
"type": "array",
"title": "label.attributes",
"description": "Attribute table - select the attributes you want to bundle (default unchecked)",
"items": {
"type": "string",
"enum": [
"eduPersonPrincipalName",
"uid",
"mail",
"surname",
"givenName",
"eduPersonAffiliation",
"eduPersonScopedAffiliation",
"eduPersonPrimaryAffiliation",
"eduPersonEntitlement",
"eduPersonAssurance",
"eduPersonUniqueId",
"employeeNumber"
]
},
"uniqueItems": true
}
}
}
1 change: 1 addition & 0 deletions ui/public/assets/schema/source/metadata-source.json
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,7 @@
"type": "string",
"enum": [
"eduPersonPrincipalName",
{"name": "foo", "attributes": []},
"uid",
"mail",
"surname",
Expand Down
20 changes: 10 additions & 10 deletions ui/src/app/core/components/Header.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import Dropdown from 'react-bootstrap/Dropdown';

import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';

import { faTh, faSignOutAlt, faPlusCircle, faCube, faCubes, faUsersCog, faSpinner, faUserCircle, faCog, faFileArchive, faUserTag } from '@fortawesome/free-solid-svg-icons';
import { faTh, faSignOutAlt, faPlusCircle, faCube, faCubes, faUsersCog, faSpinner, faUserCircle, faCog, faFileArchive, faUserTag, faBoxOpen, faTags, faIdBadge } from '@fortawesome/free-solid-svg-icons';

import Translate from '../../i18n/components/translate';
import { useTranslator } from '../../i18n/hooks';
Expand Down Expand Up @@ -49,16 +49,16 @@ export function Header () {
</div>
<Dropdown className="border-md-right px-2" id="metadata-nav-dropdown">
<Dropdown.Toggle variant="link" id="metadata-nav-dropdown-toggle" size="sm">
<FontAwesomeIcon icon={faPlusCircle} className="mr-2" />
<FontAwesomeIcon icon={faPlusCircle} className="mr-2" fixedWidth />
<Translate value={'action.add-new'} />
</Dropdown.Toggle>
<Dropdown.Menu>
<Dropdown.Item as={Link} to="/metadata/source/new" className="text-primary py-2" id="metadata-nav-dropdown-source">
<FontAwesomeIcon icon={faCube} className="mr-2" />
<FontAwesomeIcon icon={faCube} className="mr-2" fixedWidth />
<Translate value="action.add-new-source" />
</Dropdown.Item>
{isAdmin && <Dropdown.Item as={Link} to="/metadata/provider/new" className="text-primary py-2" id="metadata-nav-dropdown-provider">
<FontAwesomeIcon icon={faCubes} className="mr-2" />
<FontAwesomeIcon icon={faCubes} className="mr-2" fixedWidth />
<Translate value="action.add-new-provider" />
</Dropdown.Item> }
</Dropdown.Menu>
Expand All @@ -71,19 +71,19 @@ export function Header () {
</Dropdown.Toggle>
<Dropdown.Menu>
<Dropdown.Item as={Link} to="/metadata/attributes" className="text-primary py-2" id="advanced-nav-dropdown-attr">
<FontAwesomeIcon icon={faCube} className="mr-2" />
<FontAwesomeIcon icon={faTags} className="mr-2" fixedWidth />
<Translate value="action.custom-entity-attributes" />
</Dropdown.Item>
<Dropdown.Item as={Link} to="/metadata/attributes/bundles" className="text-primary py-2" id="advanced-nav-dropdown-bundles">
<FontAwesomeIcon icon={faFileArchive} className="mr-2" />
<Dropdown.Item as={Link} to="/metadata/attributes/bundles" className="text-primary py-2" id="advanced-nav-dropdown-bundles">
<FontAwesomeIcon icon={faBoxOpen} className="mr-2" fixedWidth />
<Translate value="action.attribute-bundles" />
</Dropdown.Item>
<Dropdown.Item as={Link} to="/groups" className="text-primary py-2" id="advanced-nav-dropdown-groups">
<FontAwesomeIcon icon={faUsersCog} className="mr-2" />
<FontAwesomeIcon icon={faUsersCog} className="mr-2" fixedWidth/>
<Translate value="action.groups" />
</Dropdown.Item>
<Dropdown.Item as={Link} to="/roles" className="text-primary py-2" id="advanced-nav-dropdown-roles">
<FontAwesomeIcon icon={faUserTag} className="mr-2" />
<FontAwesomeIcon icon={faIdBadge} className="mr-2" fixedWidth />
<Translate value="action.roles" />
</Dropdown.Item>
</Dropdown.Menu>
Expand All @@ -100,7 +100,7 @@ export function Header () {
<div class="dropdown-divider"></div>
<Dropdown.Item href="/logout" target="_self" className="text-primary" aria-label={translator('action.logout')}
id="user-nav-dropdown-logout">
<FontAwesomeIcon icon={faSignOutAlt} className="mr-2" />
<FontAwesomeIcon icon={faSignOutAlt} className="mr-2" fixedWidth />
<Translate value="action.logout">Logout</Translate>
</Dropdown.Item>
</Dropdown.Menu>
Expand Down
10 changes: 9 additions & 1 deletion ui/src/app/metadata/Attribute.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { NewAttribute } from './new/NewAttribute';
import { MetadataAttributeEdit } from './view/MetadataAttributeEdit';
import { MetadataAttributeList } from './view/MetadataAttributeList';
import { MetadataAttributeBundles } from './view/MetadataAttributeBundles';
import { NewBundle } from './new/NewBundle';
import { MetadataAttributeBundleEdit } from './view/MetadataAttributeBundleEdit';

export function Attribute() {

Expand All @@ -25,9 +27,15 @@ export function Attribute() {
<Route path={`${path}/:id/edit`} render={() =>
<MetadataAttributeEdit />
} />
<Route path={`${path}/bundles`} render={() =>
<Route exact path={`${path}/bundles`} render={() =>
<MetadataAttributeBundles />
} />
<Route exact path={`${path}/bundles/new`} render={() =>
<NewBundle />
} />
<Route exact path={`${path}/bundles/:id/edit`} render={() =>
<MetadataAttributeBundleEdit />
} />
<Redirect exact path={`${path}`} to={`${path}/list`} />
</Switch>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ export const AttributeBundleDefinition = {
schema: `/assets/schema/attribute/bundle.schema.json`,

uiSchema: {

attributes: {
'ui:widget': 'AttributeReleaseWidget'
}
},

parser: (data) => {
Expand Down
56 changes: 56 additions & 0 deletions ui/src/app/metadata/editor/AttributeBundleEditor.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import React from 'react';
import { MetadataFormContext, setFormDataAction, setFormErrorAction } from '../hoc/MetadataFormContext';
import { MetadataDefinitionContext, MetadataSchemaContext } from '../hoc/MetadataSchema';
import { transformErrors } from '../domain/transform';

import Form from '@rjsf/bootstrap-4';

import { fields, widgets } from '../../form/component';
import { templates } from '../../form/component';

function ErrorListTemplate() {
return (<></>);
}

export function AttributeBundleEditor({ children }) {

const definition = React.useContext(MetadataDefinitionContext);
const schema = React.useContext(MetadataSchemaContext);

const { state, dispatch } = React.useContext(MetadataFormContext);
const { metadata, errors } = state;

const onChange = (changes) => {
dispatch(setFormDataAction(changes.formData));
dispatch(setFormErrorAction(changes.errors));
// setBlocking(true);
};

return (
<div className="container-fluid">
<div className="d-flex justify-content-end align-items-center">
{children(metadata, errors)}
</div>
<hr />
<div className="row">
<div className="col-12 col-lg-12 order-2">
<Form formData={metadata}
noHtml5Validate={true}
onChange={(form) => onChange(form)}
schema={schema}
uiSchema={definition.uiSchema}
FieldTemplate={templates.FieldTemplate}
ObjectFieldTemplate={templates.ObjectFieldTemplate}
ArrayFieldTemplate={templates.ArrayFieldTemplate}
fields={fields}
widgets={widgets}
liveValidate={true}
ErrorList={ErrorListTemplate}
transformErrors={transformErrors}>
<></>
</Form>
</div>
</div>
</div>
);
}
81 changes: 81 additions & 0 deletions ui/src/app/metadata/new/NewBundle.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import React from 'react';
import { faSave, faSpinner } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import Button from 'react-bootstrap/Button';

import { Prompt, useHistory } from 'react-router';
import Translate from '../../i18n/components/translate';

import { AttributeBundleDefinition } from '../domain/attribute/AttributeBundleDefinition';
import MetadataSchema from '../hoc/MetadataSchema';
import { MetadataForm } from '../hoc/MetadataFormContext';
import { AttributeBundleEditor } from '../editor/AttributeBundleEditor';
import { AttributeBundleApi } from '../hoc/attribute/AttributeBundleApi';

export function NewBundle() {
const history = useHistory();

console.log('hi')

const definition = AttributeBundleDefinition;

const [blocking, setBlocking] = React.useState(false);

const cancel = () => {
gotoDetail();
};

const gotoDetail = (state = null) => {
setBlocking(false);
history.push(`/metadata/attributes/bundles`, state);
};

return (
<AttributeBundleApi>
{(load, find, create, update, remove, loading) =>
<div className="container-fluid p-3">
<Prompt
when={blocking}
message={location =>
`message.unsaved-editor`
}
/>
<section className="section" tabIndex="0">
<div className="section-header bg-info p-2 text-white">
<div className="row justify-content-between">
<div className="col-md-12">
<span className="display-6"><Translate value="label.new-attribute-bundle">Add a new attribute bundle</Translate></span>
</div>
</div>
</div>
<div className="section-body p-4 border border-top-0 border-info">
<MetadataSchema type={AttributeBundleDefinition}>
<MetadataForm>
<AttributeBundleEditor definition={definition}>
{(bundle, errors) =>
<React.Fragment>
<Button variant="info" className="mr-2"
type="button"
onClick={() => create(bundle)}
disabled={errors.length > 0 || loading}
aria-label="Save changes to the metadata source. You will return to the dashboard">
<FontAwesomeIcon icon={loading ? faSpinner : faSave} pulse={loading} />&nbsp;
<Translate value="action.save">Save</Translate>
</Button>
<Button variant="secondary"
type="button"
onClick={() => cancel()} aria-label="Cancel changes, go back to dashboard">
<Translate value="action.cancel">Cancel</Translate>
</Button>
</React.Fragment>
}
</AttributeBundleEditor>
</MetadataForm>
</MetadataSchema>
</div>
</section>
</div>
}
</AttributeBundleApi>
);
}
8 changes: 4 additions & 4 deletions ui/src/app/metadata/view/MetadataAttributeBundleEdit.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export function MetadataAttributeBundleEdit() {

const gotoDetail = (state = null) => {
setBlocking(false);
history.push(`/metadata/attributes`, state);
history.push(`/metadata/attributes/bundles`, state);
};

return (
Expand Down Expand Up @@ -58,15 +58,15 @@ export function MetadataAttributeBundleEdit() {
<React.Fragment>
<Button variant="info" className="mr-2"
type="button"
onClick={() => save(filter)}
onClick={() => update(filter)}
disabled={errors.length > 0 || loading}
aria-label="Save changes to the metadata source. You will return to the dashboard">
aria-label="Save changes to the bundle">
<FontAwesomeIcon icon={loading ? faSpinner : faSave} pulse={loading} />&nbsp;
<Translate value="action.save">Save</Translate>
</Button>
<Button variant="secondary"
type="button"
onClick={() => cancel()} aria-label="Cancel changes, go back to dashboard">
onClick={() => cancel()} aria-label="Cancel changes, go back to bundle list">
<Translate value="action.cancel">Cancel</Translate>
</Button>
</React.Fragment>
Expand Down
2 changes: 1 addition & 1 deletion ui/src/app/metadata/view/MetadataAttributeBundles.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export function MetadataAttributeBundles({ entities, onDelete }) {
</div>
<div className="p-3">
<div className="d-flex justify-content-end w-100">
<Link to="./new" className="btn btn-sm btn-success">
<Link to="./bundles/new" className="btn btn-sm btn-success">
<FontAwesomeIcon icon={faPlusCircle} /> &nbsp;
<Translate value="action.add-new-bundle">Add new bundle</Translate>
</Link>
Expand Down
4 changes: 2 additions & 2 deletions ui/src/app/metadata/view/MetadataAttributeEdit.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,13 +86,13 @@ export function MetadataAttributeEdit() {
type="button"
onClick={() => save(filter)}
disabled={errors.length > 0 || loading}
aria-label="Save changes to the metadata source. You will return to the dashboard">
aria-label="Save changes to the custom attribute. You will return to the attribute list">
<FontAwesomeIcon icon={loading ? faSpinner : faSave} pulse={loading} />&nbsp;
<Translate value="action.save">Save</Translate>
</Button>
<Button variant="secondary"
type="button"
onClick={() => cancel()} aria-label="Cancel changes, go back to dashboard">
onClick={() => cancel()} aria-label="Cancel changes, go back to attribute list">
<Translate value="action.cancel">Cancel</Translate>
</Button>
</React.Fragment>
Expand Down
Loading

0 comments on commit c097f0c

Please sign in to comment.