From cfa28e0426e7a202feec08012327b273987bae0b Mon Sep 17 00:00:00 2001 From: Ryan Mathis Date: Wed, 28 Apr 2021 12:02:46 -0700 Subject: [PATCH] Added delete to sources detail --- ui/package.json | 1 + ui/src/app/dashboard/container/SourcesTab.js | 15 +- .../component/MetadataConfiguration.js | 33 --- .../app/metadata/component/MetadataHeader.js | 6 +- .../app/metadata/component/MetadataOptions.js | 71 +++++- .../component/properties/ArrayProperty.js | 18 +- .../component/properties/PropertyValue.js | 4 +- .../component/DeleteSourceConfirmation.js | 58 +++++ .../domain/source/component/SourceList.js | 223 ++++++------------ ui/src/app/metadata/hoc/MetadataXmlLoader.js | 8 +- ui/yarn.lock | 13 + 11 files changed, 234 insertions(+), 216 deletions(-) create mode 100644 ui/src/app/metadata/domain/source/component/DeleteSourceConfirmation.js diff --git a/ui/package.json b/ui/package.json index 0e4e626b2..eeb591172 100644 --- a/ui/package.json +++ b/ui/package.json @@ -20,6 +20,7 @@ "react-infinite-scroll-component": "^6.1.0", "react-router-dom": "^5.2.0", "react-scripts": "4.0.3", + "react-scroll": "^1.8.2", "reactstrap": "^8.9.0", "sass": "^1.32.11", "use-http": "^1.0.20", diff --git a/ui/src/app/dashboard/container/SourcesTab.js b/ui/src/app/dashboard/container/SourcesTab.js index 073aeaa86..94305795b 100644 --- a/ui/src/app/dashboard/container/SourcesTab.js +++ b/ui/src/app/dashboard/container/SourcesTab.js @@ -11,21 +11,18 @@ export function SourcesTab () { const [sources, setSources] = React.useState([]); - const { get, del, response } = useMetadataEntities('source'); + const { get, response } = useMetadataEntities('source', { + cachePolicy: 'no-cache' + }); async function loadSources() { - const sources = await get('/') + const sources = await get('/'); if (response.ok) { setSources(sources); } } - async function deleteSource(id) { - await del(`/${id}`); - if (response.ok) { - loadSources(); - } - } + const updateSources = () => loadSources(); /*eslint-disable react-hooks/exhaustive-deps*/ React.useEffect(() => { loadSources() }, []); @@ -40,7 +37,7 @@ export function SourcesTab () {
- {(searched) => } + {(searched) => }
diff --git a/ui/src/app/metadata/component/MetadataConfiguration.js b/ui/src/app/metadata/component/MetadataConfiguration.js index 4a4584ce2..1ccd73d73 100644 --- a/ui/src/app/metadata/component/MetadataConfiguration.js +++ b/ui/src/app/metadata/component/MetadataConfiguration.js @@ -35,36 +35,3 @@ export function MetadataConfiguration ({ configuration }) { ); } - -/* -
-
-
-

- - 0{{ i + 1 }} - - {{ section.label | translate }} -

-
- -
-
-
- -
- Option - - Value - {{ date | date:DATE_FORMAT }} - -
- -
-
-
-
*/ \ No newline at end of file diff --git a/ui/src/app/metadata/component/MetadataHeader.js b/ui/src/app/metadata/component/MetadataHeader.js index d9fcdc3da..d8a2baa85 100644 --- a/ui/src/app/metadata/component/MetadataHeader.js +++ b/ui/src/app/metadata/component/MetadataHeader.js @@ -3,9 +3,9 @@ import FormattedDate from '../../core/components/FormattedDate'; import Translate from '../../i18n/components/translate'; -export function MetadataHeader ({ model, current = true, enabled = true }) { +export function MetadataHeader ({ model, current = true, enabled = true, children, ...props }) { return ( -
+
@@ -17,7 +17,7 @@ export function MetadataHeader ({ model, current = true, enabled = true }) { By{model.createdBy }
- + {children}

diff --git a/ui/src/app/metadata/component/MetadataOptions.js b/ui/src/app/metadata/component/MetadataOptions.js index 374713f12..13ce53b00 100644 --- a/ui/src/app/metadata/component/MetadataOptions.js +++ b/ui/src/app/metadata/component/MetadataOptions.js @@ -1,7 +1,9 @@ -import { faArrowDown, faHistory } from '@fortawesome/free-solid-svg-icons'; -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import React from 'react'; -import { Link, useParams } from 'react-router-dom'; +import { faArrowDown, faHistory, faTrash } from '@fortawesome/free-solid-svg-icons'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { Link, useHistory, useParams } from 'react-router-dom'; + +import { scroller } from 'react-scroll'; import Translate from '../../i18n/components/translate'; @@ -12,25 +14,48 @@ import { MetadataConfiguration } from './MetadataConfiguration'; import { useMetadataConfiguration } from '../hooks/configuration'; import { MetadataViewToggle } from './MetadataViewToggle'; +import { DeleteSourceConfirmation } from '../domain/source/component/DeleteSourceConfirmation'; export function MetadataOptions () { const metadata = React.useContext(MetadataObjectContext); + const history = useHistory(); const { type, id } = useParams(); const configuration = useMetadataConfiguration([metadata]); + const onScrollTo = (element, offset = 0) => { + scroller.scrollTo(element, { + duration: 500, + smooth: true, + offset + }); + }; + + const redirectOnDelete = () => history.push('/dashboard'); + return ( - <> -

+ + {(onDeleteSource) => + <> +
+ enabled={type === 'source' ? metadata.serviceEnabled : metadata.enabled} + model={metadata}> + {type === 'source' && + + } + - + } + ); } \ No newline at end of file diff --git a/ui/src/app/metadata/component/properties/ArrayProperty.js b/ui/src/app/metadata/component/properties/ArrayProperty.js index 979ed95f2..6fa440c2f 100644 --- a/ui/src/app/metadata/component/properties/ArrayProperty.js +++ b/ui/src/app/metadata/component/properties/ArrayProperty.js @@ -43,9 +43,9 @@ export function ArrayProperty ({ property, columns, index, onPreview }) {
{ property.name }
{range.map((i) => -
+
{Object.keys(property.items.properties).map((prop, n) => -
+
{property.differences && Changed: } {property.items.properties &&
@@ -53,7 +53,15 @@ export function ArrayProperty ({ property, columns, index, onPreview }) {
} { property.value.map((version, vIdx) => - + + {version && version[vIdx] && + + } + {(!version || !version[vIdx]) &&
+ - +
+ } +
)}
)} @@ -75,7 +83,7 @@ export function ArrayProperty ({ property, columns, index, onPreview }) { {(v && v.length > 0) &&
    {v.map((item, idx) => -
  • 1 ? 'py-2' : ''} ${'border-0'}`}> +
  • 1 ? 'py-2' : ''} ${'border-0'}`}> {onPreview && isUrl(item) && <>   } - { item } +
  • )}
diff --git a/ui/src/app/metadata/component/properties/PropertyValue.js b/ui/src/app/metadata/component/properties/PropertyValue.js index 91b51d5cd..6ca8e8f53 100644 --- a/ui/src/app/metadata/component/properties/PropertyValue.js +++ b/ui/src/app/metadata/component/properties/PropertyValue.js @@ -18,11 +18,11 @@ export function PropertyValue ({ name, value, columns }) { id={`Popover-${id}`} className="d-block text-truncate" role="definition" - style={{ width }}> + style={columns ? { width } : {}}> {value !== undefined ? value.toString() : (value === false) ? value.toString() : '-'} - {value} + {value.toString()} : '-'} diff --git a/ui/src/app/metadata/domain/source/component/DeleteSourceConfirmation.js b/ui/src/app/metadata/domain/source/component/DeleteSourceConfirmation.js new file mode 100644 index 000000000..b322d096e --- /dev/null +++ b/ui/src/app/metadata/domain/source/component/DeleteSourceConfirmation.js @@ -0,0 +1,58 @@ +import React from 'react'; + +import { Button, Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons'; + +import { useMetadataEntity } from '../../../hooks/api'; +import Translate from '../../../../i18n/components/translate'; +import { noop } from 'lodash'; + +export function DeleteSourceConfirmation ({children}) { + + const { del, response } = useMetadataEntity('source'); + + const cb = React.useRef(null); + + const [deleting, setDeleting] = React.useState(null); + + const onConfirm = (id, cb = () => {}) => { + deleteSource(deleting); + setDeleting(null); + } + + const onDeleteSource = (id, onComplete) => { + setDeleting(id); + cb.current = onComplete; + }; + + async function deleteSource(id) { + await del(`/${id}`); + if (response.ok) { + cb.current && typeof cb.current === 'function' ? cb.current() : noop(); + } + } + + return ( + <> + {children(onDeleteSource)} + setDeleting(null)}> + setDeleting(null)}>Delete Metadata Source? + + +

+ You are deleting a metadata source. This cannot be undone. Continue? +

+
+ + {' '} + + +
+ + ); +} \ No newline at end of file diff --git a/ui/src/app/metadata/domain/source/component/SourceList.js b/ui/src/app/metadata/domain/source/component/SourceList.js index ae59abf06..3315ff74f 100644 --- a/ui/src/app/metadata/domain/source/component/SourceList.js +++ b/ui/src/app/metadata/domain/source/component/SourceList.js @@ -1,171 +1,88 @@ import React from 'react'; import { Link } from 'react-router-dom'; -import { Badge, UncontrolledPopover, PopoverBody, Button, Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap'; +import { Badge, UncontrolledPopover, PopoverBody } from 'reactstrap'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { faTrash, faExclamationTriangle, faCheck } from '@fortawesome/free-solid-svg-icons'; +import { faTrash, faCheck } from '@fortawesome/free-solid-svg-icons'; import FormattedDate from '../../../../core/components/FormattedDate'; import Translate from '../../../../i18n/components/translate'; import { Scroller } from '../../../../dashboard/component/Scroller'; +import { DeleteSourceConfirmation } from './DeleteSourceConfirmation'; export default function SourceList({ entities, onDelete, onEnable }) { - - const [modal, setModal] = React.useState(false); - - const toggle = () => setModal(!modal); - - const [deleting, setDeleting] = React.useState(null); - - const deleteSource = (id) => { - onDelete(deleting); - setDeleting(null); - } - return ( - <> - - {(limited) => -
- - - - - - - - - - - - - - {limited.map((source, idx) => - - - - - - - + + {(onDeleteSource) => + + {(limited) => +
+ +
TitleEntity IDAuthorCreated DateEnabled
- {source.serviceProviderName} - - {source.entityId} - - {source.createdBy} - - {onEnable ? - - : - - - - } - - - {source.serviceEnabled && - - A metadata source must be disabled before it can be deleted. - - } -
+ + + + + + + + - )} - -
TitleEntity IDAuthorCreated DateEnabled
-
- } -
- setDeleting(null)}> - Delete Metadata Source? - - -

- You are deleting a metadata source. This cannot be undone. Continue? -

-
- - {' '} - - -
- + + + {limited.map((source, idx) => + + + {source.serviceProviderName} + + + {source.entityId} + + + {source.createdBy} + + + + {onEnable ? + + : + + + + } + + + + {source.serviceEnabled && + + A metadata source must be disabled before it can be deleted. + + } + + + )} + + +
+ } + + } + ); } - -/* - - - {{ resolver.name }} - - - {{ resolver.name }} - - {{ resolver.getDisplayId() }} - {{ resolver.createdBy ? resolver.createdBy : '—' }} - - {{ resolver.getCreationDate() ? (resolver.getCreationDate() | customDate) : '—' }} - - - - - - Incomplete Form - - - - - - - - - {{ (resolver.enabled ? 'value.enabled' : 'value.disabled') | translate }} - - - - - - - - */ \ No newline at end of file diff --git a/ui/src/app/metadata/hoc/MetadataXmlLoader.js b/ui/src/app/metadata/hoc/MetadataXmlLoader.js index 5b5d1e4ab..ffc1c8bcf 100644 --- a/ui/src/app/metadata/hoc/MetadataXmlLoader.js +++ b/ui/src/app/metadata/hoc/MetadataXmlLoader.js @@ -10,7 +10,7 @@ export function MetadataXmlLoader({ children }) { const { get, response } = useMetadataEntityXml(type); - const [xml, setXml] = React.useState([]); + const [xml, setXml] = React.useState(); async function loadMetadataXml(id) { const data = await get(`/${id}`) @@ -20,7 +20,11 @@ export function MetadataXmlLoader({ children }) { } /*eslint-disable react-hooks/exhaustive-deps*/ - React.useEffect(() => { loadMetadataXml(id) }, [id]); + React.useEffect(() => { + if (type === 'source') { + loadMetadataXml(id) + } + }, [id]); return ( diff --git a/ui/yarn.lock b/ui/yarn.lock index bc509ce9c..06eb13aa0 100644 --- a/ui/yarn.lock +++ b/ui/yarn.lock @@ -7017,6 +7017,11 @@ lodash.templatesettings@^4.0.0: dependencies: lodash._reinterpolate "^3.0.0" +lodash.throttle@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4" + integrity sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ= + lodash.uniq@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" @@ -9227,6 +9232,14 @@ react-scripts@4.0.3: optionalDependencies: fsevents "^2.1.3" +react-scroll@^1.8.2: + version "1.8.2" + resolved "https://registry.yarnpkg.com/react-scroll/-/react-scroll-1.8.2.tgz#68e35b74ae296c88e7863393c9fd49f05afa29f5" + integrity sha512-f2ZEG5fsPbPTySI9ekcFpETCcNlqbmwbQj9hhzYK8tkgv+PA8APatSt66o/q0KSkDZxyT98ONTtXp9x0lyowEw== + dependencies: + lodash.throttle "^4.1.1" + prop-types "^15.7.2" + react-transition-group@^2.3.1: version "2.9.0" resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-2.9.0.tgz#df9cdb025796211151a436c69a8f3b97b5b07c8d"