Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
rmathis committed Sep 1, 2021
1 parent 786d737 commit 254a0b1
Show file tree
Hide file tree
Showing 10 changed files with 315 additions and 5 deletions.
10 changes: 10 additions & 0 deletions ui/public/data/bundles.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[
{
"resourceId": "abc",
"name": "Bundle 1",
"attributes": [
"abc123",
"xyz456"
]
}
]
12 changes: 7 additions & 5 deletions ui/src/app/core/components/Header.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,9 @@ import { Link } from 'react-router-dom';
import Nav from 'react-bootstrap/Nav';
import Navbar from 'react-bootstrap/Navbar';
import Dropdown from 'react-bootstrap/Dropdown';
import OverlayTrigger from 'react-bootstrap/OverlayTrigger';
import Tooltip from 'react-bootstrap/Tooltip';

import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faTh, faSignOutAlt, faPlusCircle, faCube, faCubes, faUsersCog, faUser, faSpinner, faUserCircle } from '@fortawesome/free-solid-svg-icons';
import { faTh, faSignOutAlt, faPlusCircle, faCube, faCubes, faUsersCog, faSpinner, faUserCircle, faCog, faLayerGroup, faFileArchive } from '@fortawesome/free-solid-svg-icons';

import Translate from '../../i18n/components/translate';
import { useTranslator } from '../../i18n/hooks';
Expand Down Expand Up @@ -67,14 +65,18 @@ export function Header () {
{isAdmin &&
<Dropdown className="border-md-right px-2" id="basic-nav-dropdown">
<Dropdown.Toggle variant="link" id="dropdown-basic" size="sm">
<FontAwesomeIcon icon={faPlusCircle} className="mr-2" />
<FontAwesomeIcon icon={faCog} className="mr-2" />
<Translate value={'action.advanced'} />
</Dropdown.Toggle>
<Dropdown.Menu>
<Dropdown.Item as={Link} to="/metadata/attributes" className="text-primary py-2">
<FontAwesomeIcon icon={faCube} className="mr-2" />
<Translate value="action.custom-entity-attributes" />
</Dropdown.Item>
<Dropdown.Item as={Link} to="/metadata/attributes/bundles" className="text-primary py-2">
<FontAwesomeIcon icon={faFileArchive} className="mr-2" />
<Translate value="action.attribute-bundles" />
</Dropdown.Item>
<Dropdown.Item as={Link} to="/groups" className="text-primary py-2">
<FontAwesomeIcon icon={faUsersCog} className="mr-2" />
<Translate value="action.groups" />
Expand All @@ -84,7 +86,7 @@ export function Header () {
}
<Dropdown className="pl-2" id="basic-nav-dropdown">
<Dropdown.Toggle variant="link" id="dropdown-basic" size="sm" bsPrefix="dropdown-toggle-shibui">
<FontAwesomeIcon icon={faUserCircle} size="" className="mr-2" />
<FontAwesomeIcon icon={faUserCircle} size="lg" className="mr-2" />
<Translate value={'action.logged-in'} params={{ username }} />
</Dropdown.Toggle>
<Dropdown.Menu alignRight={true}>
Expand Down
4 changes: 4 additions & 0 deletions ui/src/app/metadata/Attribute.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { MetadataAttributes } from './hoc/MetadataAttributes';
import { NewAttribute } from './new/NewAttribute';
import { MetadataAttributeEdit } from './view/MetadataAttributeEdit';
import { MetadataAttributeList } from './view/MetadataAttributeList';
import { MetadataAttributeBundles } from './view/MetadataAttributeBundles';

export function Attribute() {

Expand All @@ -24,6 +25,9 @@ export function Attribute() {
<Route path={`${path}/:id/edit`} render={() =>
<MetadataAttributeEdit />
} />
<Route path={`${path}/bundles`} render={() =>
<MetadataAttributeBundles />
} />
<Redirect exact path={`${path}`} to={`${path}/list`} />
</Switch>
);
Expand Down
29 changes: 29 additions & 0 deletions ui/src/app/metadata/domain/attribute/AttributeBundleDefinition.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { defaultsDeep } from "lodash";

export const AttributeBundleDefinition = {
label: 'Metadata Attribute Bundle',
type: '@MetadataAttributeBundle',
steps: [],
schema: `/assets/schema/attribute/bundle.schema.json`,

uiSchema: {

},

parser: (data) => {
return data;
},

formatter: (changes) => {
return changes;
}
}

export const CustomAttributeEditor = {
...AttributeBundleDefinition,
uiSchema: defaultsDeep({
attributeType: {
'ui:disabled': true
}
}, AttributeBundleDefinition.uiSchema)
};
69 changes: 69 additions & 0 deletions ui/src/app/metadata/hoc/attribute/AttributeBundleApi.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import React from 'react';
import useFetch from 'use-http';
import API_BASE_PATH from '../../../App.constant';

import { DeleteConfirmation } from '../../../core/components/DeleteConfirmation';
import { createNotificationAction, NotificationContext } from '../../../notifications/hoc/Notifications';

const api = '/custom/entity/bundles'

export function AttributeBundleApi({ id, children }) {

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

const { get, put, post, del, response, loading } = useFetch(`/data/bundles.json`, {
cachePolicy: 'no-cache'
});

async function load(cb) {
const b = await get(``);
if (response.ok) {
cb && cb(b);
}
}

async function find(id, cb) {
const b = await get(`/${id }`);
if (response.ok) {
cb && cb(b);
}
}

async function update(id, body, cb) {
const b = await put(`/${id}`, body);
if (response.ok) {
dispatch(createNotificationAction(
`Bundle has been updated.`
));
cb && cb(b);
}
}

async function create(body, cb) {
const b = await post(``, body);
if (response.ok) {
dispatch(createNotificationAction(
`Bundle has been created.`
));
cb && cb(b);
}
}

async function remove(id, cb = () => { }) {
await del(`/${id}`);
if (response.ok) {
dispatch(createNotificationAction(
`Bundle has been deleted.`
));
cb();
}
}

return (
<DeleteConfirmation title={`message.delete-attribute-title`} body={`message.delete-attribute-body`}>
{(block) =>
<div>{children(load, find, create, update, (id) => block(() => remove(id)), loading)}</div>
}
</DeleteConfirmation>
);
}
14 changes: 14 additions & 0 deletions ui/src/app/metadata/hoc/attribute/AttributeBundleList.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import React from 'react';

export function AttributeBundleList({ load, children }) {

const [bundles, setBundles] = React.useState([]);

React.useEffect(() => {
load((list) => setBundles(list));
}, []);

return (
<React.Fragment>{children(bundles)}</React.Fragment>
);
}
14 changes: 14 additions & 0 deletions ui/src/app/metadata/hoc/attribute/AttributeBundleSelector.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import React from 'react';
import { useParams } from 'react-router-dom';

export function AttributeBundleSelector({ id, find, children }) {
const [bundle, setBundle] = React.useState([]);

React.useEffect(() => {
find(id, (item) => setBundle(item));
}, []);

return (
<React.Fragment>{children(bundle)}</React.Fragment>
);
}
Empty file.
86 changes: 86 additions & 0 deletions ui/src/app/metadata/view/MetadataAttributeBundleEdit.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
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, useParams } from 'react-router';
import Translate from '../../i18n/components/translate';
import { MetadataAttributeEditor } from '../editor/MetadataAttributeEditor';

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

export function MetadataAttributeBundleEdit() {
const { id } = useParams();
const history = useHistory();

const definition = AttributeBundleDefinition;

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

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

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

return (
<AttributeBundleApi>
{(load, find, create, update, remove, loading) =>
<AttributeBundleSelector id={ id } find={find}>
{(bundle) => <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">Add a new metadata attribute</Translate></span>
</div>
</div>
</div>
<div className="section-body p-4 border border-top-0 border-info">
<MetadataSchema type={AttributeBundleDefinition}>
{bundle &&
<MetadataForm initial={bundle}>
<MetadataAttributeEditor definition={definition}>
{(filter, errors) =>
<React.Fragment>
<Button variant="info" className="mr-2"
type="button"
onClick={() => save(filter)}
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>
}
</MetadataAttributeEditor>
</MetadataForm>
}
</MetadataSchema>
</div>
</section>
</div>
}
</AttributeBundleSelector>
}
</AttributeBundleApi>
);
}
82 changes: 82 additions & 0 deletions ui/src/app/metadata/view/MetadataAttributeBundles.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import React from 'react';
import { faEdit, faPlusCircle, faTrash } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';

import Button from 'react-bootstrap/Button';
import { Link } from 'react-router-dom';

import { Translate } from '../../i18n/components/translate';
import { useTranslator } from '../../i18n/hooks';

import { AttributeBundleApi } from '../hoc/attribute/AttributeBundleApi';

import { AttributeBundleList } from '../hoc/attribute/AttributeBundleList';

export function MetadataAttributeBundles({ entities, onDelete }) {

const translator = useTranslator();

return (
<AttributeBundleApi>
{(load, find, create, update, remove, loading) =>
<AttributeBundleList load={load}>
{(bundles) =>
<div className="container-fluid p-3">
<section className="section">
<div className="section-body border border-top-0 border-primary">
<div className="section-header bg-primary p-2 text-light">
<span className="lead">
<Translate value="label.custom-entity-attributes">Attribute Bundles</Translate>
</span>
</div>
<div className="p-3">
<div className="d-flex justify-content-end w-100">
<Link to="./new" className="btn btn-sm btn-success">
<FontAwesomeIcon icon={faPlusCircle} /> &nbsp;
<Translate value="action.add-new-bundle">Add new bundle</Translate>
</Link>
</div>
<div className="table-responsive mt-3">
<table className="table table-striped w-100 table-hover">
<thead>
<tr>
<th>
<Translate value="label.bundle-name">Bundle Name</Translate>
</th>
<th><span className="sr-only"><Translate value="label.actions">Actions</Translate></span></th>
</tr>
</thead>
<tbody>
{bundles.map((bundle, i) =>
<tr key={i}>
<td>{bundle.name}</td>
<td className="text-right">
<Link to={`../attributes/bundles/${bundle.resourceId}/edit`} className="btn btn-link text-primary">
<FontAwesomeIcon icon={faEdit} size="lg" />
<span className="sr-only">
<Translate value="action.edit">Edit</Translate>
</span>
</Link>
<Button variant="link" className="text-danger" onClick={() => remove(bundle.resourceId)}>
<FontAwesomeIcon icon={faTrash} size="lg" />
<span className="sr-only">
<Translate value="action.delete">Delete</Translate>
</span>
</Button>
</td>
</tr>
)}
</tbody>
</table>
</div>
</div>
</div>

</section>
</div>
}
</AttributeBundleList>
}
</AttributeBundleApi>
);
}

0 comments on commit 254a0b1

Please sign in to comment.