@blaze-cms/plugin-data-ui 0.131.0-core-styles.0 → 0.131.0-project-admin-customisations.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -1
- package/README.md +42 -0
- package/lib/components/EntityDataListing/EntityDataListing.js +3 -24
- package/lib/components/EntityDataListing/EntityDataListing.js.map +1 -1
- package/lib/components/EntityManager/Entity/EntitiyNavLinks/EntityNavLinks.js +39 -0
- package/lib/components/EntityManager/Entity/EntitiyNavLinks/EntityNavLinks.js.map +1 -0
- package/lib/components/EntityManager/Entity/EntitiyNavLinks/index.js +12 -0
- package/lib/components/EntityManager/Entity/EntitiyNavLinks/index.js.map +1 -0
- package/lib/components/EntityManager/Entity/Entity.js +15 -2
- package/lib/components/EntityManager/Entity/Entity.js.map +1 -1
- package/lib/components/EntityManager/Entity/SideBarRelations/container/CustomSidebarInfoContainer.js +44 -0
- package/lib/components/EntityManager/Entity/SideBarRelations/container/CustomSidebarInfoContainer.js.map +1 -0
- package/lib/components/EntityManager/Entity/SideBarRelations/helpers/build-dynamic-query.js +32 -0
- package/lib/components/EntityManager/Entity/SideBarRelations/helpers/build-dynamic-query.js.map +1 -0
- package/lib/components/EntityManager/Entity/SideBarRelations/hooks/useCustomSidebarData.js +45 -0
- package/lib/components/EntityManager/Entity/SideBarRelations/hooks/useCustomSidebarData.js.map +1 -0
- package/lib/components/EntityManager/Entity/SideBarRelations/index.js +12 -2
- package/lib/components/EntityManager/Entity/SideBarRelations/index.js.map +1 -1
- package/lib/components/EntityManager/Entity/SideBarRelations/presentational/CustomSidebarInfo.js +38 -0
- package/lib/components/EntityManager/Entity/SideBarRelations/presentational/CustomSidebarInfo.js.map +1 -0
- package/lib/components/InfoBoxes/InfoBoxes.js +36 -0
- package/lib/components/InfoBoxes/InfoBoxes.js.map +1 -0
- package/lib/components/InfoBoxes/container/InfoBoxContainer.js +44 -0
- package/lib/components/InfoBoxes/container/InfoBoxContainer.js.map +1 -0
- package/lib/components/InfoBoxes/helpers/build-dynamic-query.js +25 -0
- package/lib/components/InfoBoxes/helpers/build-dynamic-query.js.map +1 -0
- package/lib/components/InfoBoxes/hooks/useData.js +42 -0
- package/lib/components/InfoBoxes/hooks/useData.js.map +1 -0
- package/lib/components/InfoBoxes/hooks/useInfoBox.js +26 -0
- package/lib/components/InfoBoxes/hooks/useInfoBox.js.map +1 -0
- package/lib/components/InfoBoxes/index.js +12 -0
- package/lib/components/InfoBoxes/index.js.map +1 -0
- package/lib/components/InfoBoxes/presentational/InfoBox.js +46 -0
- package/lib/components/InfoBoxes/presentational/InfoBox.js.map +1 -0
- package/lib/components/ListingTable/ListingTable.js +19 -33
- package/lib/components/ListingTable/ListingTable.js.map +1 -1
- package/lib/components/ListingTable/ListingTableContent/ListingTableContent.js +9 -14
- package/lib/components/ListingTable/ListingTableContent/ListingTableContent.js.map +1 -1
- package/lib/components/ListingTable/mappers/populate-rows.js +92 -26
- package/lib/components/ListingTable/mappers/populate-rows.js.map +1 -1
- package/lib/index.js +3 -11
- package/lib/index.js.map +1 -1
- package/lib/utils/add-content-menu-items.js +64 -13
- package/lib/utils/add-content-menu-items.js.map +1 -1
- package/lib-es/components/EntityDataListing/EntityDataListing.js +3 -14
- package/lib-es/components/EntityDataListing/EntityDataListing.js.map +1 -1
- package/lib-es/components/EntityManager/Entity/EntitiyNavLinks/EntityNavLinks.js +30 -0
- package/lib-es/components/EntityManager/Entity/EntitiyNavLinks/EntityNavLinks.js.map +1 -0
- package/lib-es/components/EntityManager/Entity/EntitiyNavLinks/index.js +3 -0
- package/lib-es/components/EntityManager/Entity/EntitiyNavLinks/index.js.map +1 -0
- package/lib-es/components/EntityManager/Entity/Entity.js +15 -2
- package/lib-es/components/EntityManager/Entity/Entity.js.map +1 -1
- package/lib-es/components/EntityManager/Entity/SideBarRelations/container/CustomSidebarInfoContainer.js +30 -0
- package/lib-es/components/EntityManager/Entity/SideBarRelations/container/CustomSidebarInfoContainer.js.map +1 -0
- package/lib-es/components/EntityManager/Entity/SideBarRelations/helpers/build-dynamic-query.js +26 -0
- package/lib-es/components/EntityManager/Entity/SideBarRelations/helpers/build-dynamic-query.js.map +1 -0
- package/lib-es/components/EntityManager/Entity/SideBarRelations/hooks/useCustomSidebarData.js +39 -0
- package/lib-es/components/EntityManager/Entity/SideBarRelations/hooks/useCustomSidebarData.js.map +1 -0
- package/lib-es/components/EntityManager/Entity/SideBarRelations/index.js +12 -2
- package/lib-es/components/EntityManager/Entity/SideBarRelations/index.js.map +1 -1
- package/lib-es/components/EntityManager/Entity/SideBarRelations/presentational/CustomSidebarInfo.js +24 -0
- package/lib-es/components/EntityManager/Entity/SideBarRelations/presentational/CustomSidebarInfo.js.map +1 -0
- package/lib-es/components/InfoBoxes/InfoBoxes.js +28 -0
- package/lib-es/components/InfoBoxes/InfoBoxes.js.map +1 -0
- package/lib-es/components/InfoBoxes/container/InfoBoxContainer.js +30 -0
- package/lib-es/components/InfoBoxes/container/InfoBoxContainer.js.map +1 -0
- package/lib-es/components/InfoBoxes/helpers/build-dynamic-query.js +25 -0
- package/lib-es/components/InfoBoxes/helpers/build-dynamic-query.js.map +1 -0
- package/lib-es/components/InfoBoxes/hooks/useData.js +37 -0
- package/lib-es/components/InfoBoxes/hooks/useData.js.map +1 -0
- package/lib-es/components/InfoBoxes/hooks/useInfoBox.js +19 -0
- package/lib-es/components/InfoBoxes/hooks/useInfoBox.js.map +1 -0
- package/lib-es/components/InfoBoxes/index.js +3 -0
- package/lib-es/components/InfoBoxes/index.js.map +1 -0
- package/lib-es/components/InfoBoxes/presentational/InfoBox.js +31 -0
- package/lib-es/components/InfoBoxes/presentational/InfoBox.js.map +1 -0
- package/lib-es/components/ListingTable/ListingTable.js +19 -32
- package/lib-es/components/ListingTable/ListingTable.js.map +1 -1
- package/lib-es/components/ListingTable/ListingTableContent/ListingTableContent.js +12 -15
- package/lib-es/components/ListingTable/ListingTableContent/ListingTableContent.js.map +1 -1
- package/lib-es/components/ListingTable/mappers/populate-rows.js +76 -24
- package/lib-es/components/ListingTable/mappers/populate-rows.js.map +1 -1
- package/lib-es/index.js +1 -9
- package/lib-es/index.js.map +1 -1
- package/lib-es/utils/add-content-menu-items.js +49 -5
- package/lib-es/utils/add-content-menu-items.js.map +1 -1
- package/package.json +10 -9
- package/src/components/EntityDataListing/EntityDataListing.js +3 -12
- package/src/components/EntityManager/Entity/EntitiyNavLinks/EntityNavLinks.js +26 -0
- package/src/components/EntityManager/Entity/EntitiyNavLinks/index.js +3 -0
- package/src/components/EntityManager/Entity/Entity.js +9 -0
- package/src/components/EntityManager/Entity/SideBarRelations/container/CustomSidebarInfoContainer.js +22 -0
- package/src/components/EntityManager/Entity/SideBarRelations/helpers/build-dynamic-query.js +33 -0
- package/src/components/EntityManager/Entity/SideBarRelations/hooks/useCustomSidebarData.js +28 -0
- package/src/components/EntityManager/Entity/SideBarRelations/index.js +34 -16
- package/src/components/EntityManager/Entity/SideBarRelations/presentational/CustomSidebarInfo.js +33 -0
- package/src/components/InfoBoxes/InfoBoxes.js +24 -0
- package/src/components/InfoBoxes/container/InfoBoxContainer.js +22 -0
- package/src/components/InfoBoxes/helpers/build-dynamic-query.js +25 -0
- package/src/components/InfoBoxes/hooks/useData.js +20 -0
- package/src/components/InfoBoxes/hooks/useInfoBox.js +13 -0
- package/src/components/InfoBoxes/index.js +3 -0
- package/src/components/InfoBoxes/presentational/InfoBox.js +34 -0
- package/src/components/ListingTable/ListingTable.js +23 -22
- package/src/components/ListingTable/ListingTableContent/ListingTableContent.js +9 -18
- package/src/components/ListingTable/mappers/populate-rows.js +83 -18
- package/src/index.js +1 -8
- package/src/utils/add-content-menu-items.js +45 -3
|
@@ -7,6 +7,8 @@ import { formFieldTypes } from '@blaze-cms/react-form-builder';
|
|
|
7
7
|
import classnames from 'classnames';
|
|
8
8
|
import { VersionsList } from '@blaze-cms/versioning-ui';
|
|
9
9
|
import { PUBLISHED, UNPUBLISHED } from '../../../../constants';
|
|
10
|
+
import CustomSidebarInfoContainer from './container/CustomSidebarInfoContainer';
|
|
11
|
+
import EntityNavLinks from '../EntitiyNavLinks';
|
|
10
12
|
|
|
11
13
|
const SideBarRelations = ({ schema, onChange, formData, entity }) => {
|
|
12
14
|
const { relation: RelationComponent } = formFieldTypes;
|
|
@@ -18,7 +20,9 @@ const SideBarRelations = ({ schema, onChange, formData, entity }) => {
|
|
|
18
20
|
status
|
|
19
21
|
} = formData;
|
|
20
22
|
const client = useApolloClient();
|
|
23
|
+
|
|
21
24
|
const [relationsComponents, setRelationsComponents] = useState(null);
|
|
25
|
+
|
|
22
26
|
useEffect(
|
|
23
27
|
() => {
|
|
24
28
|
(async () => {
|
|
@@ -64,28 +68,42 @@ const SideBarRelations = ({ schema, onChange, formData, entity }) => {
|
|
|
64
68
|
return (
|
|
65
69
|
<div className="sidebar" data-testid="sideBarRelations-main-div">
|
|
66
70
|
<div className="sidebar__content">
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
<div className="
|
|
70
|
-
<
|
|
71
|
-
|
|
71
|
+
<div className="sidebar__status">
|
|
72
|
+
{formattedCreated && (
|
|
73
|
+
<div className="sidebar__top">
|
|
74
|
+
<div className="sidebar__status__wrapper">
|
|
75
|
+
<b>Status</b>
|
|
76
|
+
<span className={statusClassName}>{formattedStatus}</span>
|
|
77
|
+
</div>
|
|
78
|
+
{formattedStatus === PUBLISHED && (
|
|
79
|
+
<p>
|
|
80
|
+
{formattedStatus} on: <span> {formattedPublished}</span>
|
|
81
|
+
</p>
|
|
82
|
+
)}
|
|
72
83
|
</div>
|
|
73
|
-
|
|
84
|
+
)}
|
|
85
|
+
|
|
86
|
+
{!schema.displayProperties.adminMainInfoProperty && (
|
|
87
|
+
<>
|
|
74
88
|
<p>
|
|
75
|
-
|
|
89
|
+
Created: <span>{formattedCreated}</span>
|
|
76
90
|
</p>
|
|
77
|
-
|
|
91
|
+
<p>
|
|
92
|
+
Updated: <span>{formattedUpdated}</span>
|
|
93
|
+
</p>
|
|
94
|
+
</>
|
|
95
|
+
)}
|
|
78
96
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
</div>
|
|
86
|
-
)}
|
|
97
|
+
<CustomSidebarInfoContainer
|
|
98
|
+
id={itemId}
|
|
99
|
+
schema={schema}
|
|
100
|
+
displayProperties={schema.displayProperties}
|
|
101
|
+
/>
|
|
102
|
+
</div>
|
|
87
103
|
|
|
88
104
|
<VersionsList itemEntity={itemEntity} itemId={itemId} interfaces={interfaces} />
|
|
105
|
+
<EntityNavLinks schema={schema} />
|
|
106
|
+
|
|
89
107
|
{relationsComponents &&
|
|
90
108
|
relationsComponents.map(({ id, staticData, schema: entitySchema }) => (
|
|
91
109
|
<RelationComponent
|
package/src/components/EntityManager/Entity/SideBarRelations/presentational/CustomSidebarInfo.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import PropTypes from 'prop-types';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
|
|
4
|
+
const CustomSidebarInfo = ({ items, customSidebarInfoKey }) => {
|
|
5
|
+
if (!items) return null;
|
|
6
|
+
|
|
7
|
+
const customSidebarInfoItems = items.map(item =>
|
|
8
|
+
Object.values(item)
|
|
9
|
+
.map(info => {
|
|
10
|
+
if (!info.label || !info.value) return null;
|
|
11
|
+
|
|
12
|
+
return (
|
|
13
|
+
<p>
|
|
14
|
+
{info.label}: <span>{info.value}</span>
|
|
15
|
+
</p>
|
|
16
|
+
);
|
|
17
|
+
})
|
|
18
|
+
.filter(Boolean)
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<div className="custom-sidebar-info" key={customSidebarInfoKey}>
|
|
23
|
+
<div className="custom-sidebar-info--container">{customSidebarInfoItems}</div>
|
|
24
|
+
</div>
|
|
25
|
+
);
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export default CustomSidebarInfo;
|
|
29
|
+
|
|
30
|
+
CustomSidebarInfo.propTypes = {
|
|
31
|
+
customSidebarInfoKey: PropTypes.string.isRequired,
|
|
32
|
+
items: PropTypes.array.isRequired
|
|
33
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import PropTypes from 'prop-types';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import InfoBoxContainer from './container/InfoBoxContainer';
|
|
4
|
+
|
|
5
|
+
const InfoBoxes = ({ id, schema }) => {
|
|
6
|
+
const {
|
|
7
|
+
displayProperties: { adminInfoBoxes = [] }
|
|
8
|
+
} = schema;
|
|
9
|
+
|
|
10
|
+
if (adminInfoBoxes.length <= 0) {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
return adminInfoBoxes.map(infoBox => (
|
|
15
|
+
<InfoBoxContainer id={id} schema={schema} key={infoBox.key} infoBox={infoBox} />
|
|
16
|
+
));
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export default InfoBoxes;
|
|
20
|
+
|
|
21
|
+
InfoBoxes.propTypes = {
|
|
22
|
+
id: PropTypes.string.isRequired,
|
|
23
|
+
schema: PropTypes.object.isRequired
|
|
24
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import PropTypes from 'prop-types';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import useData from '../hooks/useData';
|
|
4
|
+
import InfoBox from '../presentational/InfoBox';
|
|
5
|
+
|
|
6
|
+
const InfoBoxContainer = ({ id, schema, infoBox }) => {
|
|
7
|
+
const { data } = useData({ id, schema, infoBox });
|
|
8
|
+
|
|
9
|
+
if (!data || !Object.keys(data) || Object.keys(data).length === 0) return null;
|
|
10
|
+
|
|
11
|
+
const items = Object.values(data).flatMap(item => Object.values(item));
|
|
12
|
+
|
|
13
|
+
return <InfoBox items={items} infoBoxKey={infoBox.key} />;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export default InfoBoxContainer;
|
|
17
|
+
|
|
18
|
+
InfoBoxContainer.propTypes = {
|
|
19
|
+
id: PropTypes.string.isRequired,
|
|
20
|
+
infoBox: PropTypes.object.isRequired,
|
|
21
|
+
schema: PropTypes.object.isRequired
|
|
22
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { gql } from '@apollo/client';
|
|
2
|
+
import { BlazeError } from '@blaze-cms/core-errors';
|
|
3
|
+
|
|
4
|
+
export default function buildDynamicQuery({ id, schema, infoBox }) {
|
|
5
|
+
if (!schema || !schema.actions || !schema.actions.get || !schema.properties) {
|
|
6
|
+
throw new BlazeError(
|
|
7
|
+
'DataEntity query requires get action, properties and fields from entity schema'
|
|
8
|
+
);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const fields = `${infoBox.property} {
|
|
12
|
+
label
|
|
13
|
+
value
|
|
14
|
+
}`;
|
|
15
|
+
|
|
16
|
+
return {
|
|
17
|
+
query: gql`query getInfoBoxData($id: String!){
|
|
18
|
+
${schema.actions.get}( id: $id ) {
|
|
19
|
+
id
|
|
20
|
+
${fields}
|
|
21
|
+
__typename
|
|
22
|
+
}
|
|
23
|
+
}`
|
|
24
|
+
};
|
|
25
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { useQuery, gql } from '@apollo/client';
|
|
2
|
+
import useInfoBoxData from './useInfoBox';
|
|
3
|
+
|
|
4
|
+
function useData({ id, schema, infoBox }) {
|
|
5
|
+
const { query } = useInfoBoxData({ id, schema, infoBox });
|
|
6
|
+
|
|
7
|
+
const infoBoxQuery =
|
|
8
|
+
query ||
|
|
9
|
+
gql`
|
|
10
|
+
query {
|
|
11
|
+
__typename
|
|
12
|
+
}
|
|
13
|
+
`;
|
|
14
|
+
|
|
15
|
+
const { data = {}, loading, error } = useQuery(infoBoxQuery, { variables: { id }, skip: !query });
|
|
16
|
+
|
|
17
|
+
return { data: data.__typename !== 'Query' ? data : null, loading, error };
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export default useData;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import buildDynamicQuery from '../helpers/build-dynamic-query';
|
|
2
|
+
|
|
3
|
+
function useInfoBox({ id, schema, infoBox }) {
|
|
4
|
+
const { query } = buildDynamicQuery({
|
|
5
|
+
id,
|
|
6
|
+
schema,
|
|
7
|
+
infoBox
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
return { query: query || null };
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export default useInfoBox;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import PropTypes from 'prop-types';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
|
|
4
|
+
const InfoBox = ({ items, infoBoxKey }) => {
|
|
5
|
+
if (!items) return null;
|
|
6
|
+
|
|
7
|
+
const infoBoxItems = items.map(item =>
|
|
8
|
+
Object.values(item)
|
|
9
|
+
.map(info => {
|
|
10
|
+
if (!info.label || !info.value) return null;
|
|
11
|
+
|
|
12
|
+
return (
|
|
13
|
+
<div className="info-box--item" key={`${infoBoxKey}-${info.label.toLowerCase()}`}>
|
|
14
|
+
<div className="info-box--label">{info.label}: </div>
|
|
15
|
+
<div className="info-box--value">{info.value}</div>
|
|
16
|
+
</div>
|
|
17
|
+
);
|
|
18
|
+
})
|
|
19
|
+
.filter(Boolean)
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<div className="info-box" key={infoBoxKey}>
|
|
24
|
+
<div className="info-box--container">{infoBoxItems}</div>
|
|
25
|
+
</div>
|
|
26
|
+
);
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export default InfoBox;
|
|
30
|
+
|
|
31
|
+
InfoBox.propTypes = {
|
|
32
|
+
infoBoxKey: PropTypes.string.isRequired,
|
|
33
|
+
items: PropTypes.array.isRequired
|
|
34
|
+
};
|
|
@@ -3,18 +3,18 @@ import React, { useEffect, useState, Fragment } from 'react';
|
|
|
3
3
|
import PropTypes from 'prop-types';
|
|
4
4
|
import { withRouter, Link } from 'react-router-dom';
|
|
5
5
|
import More from '@blaze-react/more';
|
|
6
|
-
import { MainContext, useMainContext } from '@blaze-cms/admin-ui-utils';
|
|
7
6
|
import { PageHeader, DeleteAction } from '@blaze-cms/admin';
|
|
8
7
|
import { useToasts } from '@blaze-react/toaster';
|
|
8
|
+
import { RenderHook } from '@blaze-cms/plugin-render-hooks-ui';
|
|
9
9
|
import ListingTableContent from './ListingTableContent';
|
|
10
10
|
import availableActions from '../EntityManager/Entity/actions-handlers';
|
|
11
11
|
import { fetchData } from './service';
|
|
12
|
-
import { populateRows, formatRows } from './mappers/populate-rows';
|
|
12
|
+
import { populateRows, formatRows, getParsedRowData } from './mappers/populate-rows';
|
|
13
13
|
import { getDefaultQueryParams } from '../../utils/get-default-query-params';
|
|
14
14
|
|
|
15
15
|
const OVER_SCAN_BUFFER = 10;
|
|
16
16
|
|
|
17
|
-
const ListingTable = ({ match, entitySchema
|
|
17
|
+
const ListingTable = ({ match, entitySchema }) => {
|
|
18
18
|
const [tableData, setTableData] = useState({});
|
|
19
19
|
const [modalStatus, setModalStatus] = useState(false);
|
|
20
20
|
const [itemToDelete, setItemToDelete] = useState({});
|
|
@@ -23,7 +23,6 @@ const ListingTable = ({ match, entitySchema, selectedMenuItem }) => {
|
|
|
23
23
|
const [verifiedRanges, setVerifiedRanges] = useState([]);
|
|
24
24
|
const queryParamsDefault = getDefaultQueryParams({ schema: entitySchema });
|
|
25
25
|
const [queryParams, setQueryParams] = useState(queryParamsDefault);
|
|
26
|
-
const { menuItems, setMenuItems } = useMainContext(MainContext);
|
|
27
26
|
const client = useApolloClient();
|
|
28
27
|
const { addToast } = useToasts();
|
|
29
28
|
|
|
@@ -47,6 +46,7 @@ const ListingTable = ({ match, entitySchema, selectedMenuItem }) => {
|
|
|
47
46
|
entitySchema,
|
|
48
47
|
rows: data
|
|
49
48
|
});
|
|
49
|
+
|
|
50
50
|
setTableData(populatedTable);
|
|
51
51
|
setPreviousSchema({ id: entitySchema.id });
|
|
52
52
|
}
|
|
@@ -55,17 +55,7 @@ const ListingTable = ({ match, entitySchema, selectedMenuItem }) => {
|
|
|
55
55
|
[client, entitySchema, match.url, previousSchema.id, queryParams] // eslint-disable-line react-hooks/exhaustive-deps
|
|
56
56
|
);
|
|
57
57
|
|
|
58
|
-
const onCloseCardPrompt = () =>
|
|
59
|
-
const updatedSelectedMenuItem = {
|
|
60
|
-
...selectedMenuItem,
|
|
61
|
-
isDisplayedPrompt: false
|
|
62
|
-
};
|
|
63
|
-
const [{ header, items }] = menuItems;
|
|
64
|
-
const updatedItems = items.map(
|
|
65
|
-
item => (item.name === selectedMenuItem.name ? updatedSelectedMenuItem : item)
|
|
66
|
-
);
|
|
67
|
-
setMenuItems([{ header, items: updatedItems }]);
|
|
68
|
-
};
|
|
58
|
+
const onCloseCardPrompt = () => null;
|
|
69
59
|
|
|
70
60
|
const toggleModal = item => {
|
|
71
61
|
setModalStatus(!!item);
|
|
@@ -109,13 +99,19 @@ const ListingTable = ({ match, entitySchema, selectedMenuItem }) => {
|
|
|
109
99
|
queryParams: sortQueryParams
|
|
110
100
|
}
|
|
111
101
|
});
|
|
112
|
-
const { columns } = tableData;
|
|
102
|
+
const { columns, isEnquiry } = tableData;
|
|
113
103
|
const [firstColumn] = columns;
|
|
114
104
|
|
|
115
105
|
setTableData({
|
|
116
106
|
...tableData,
|
|
117
107
|
appliedSort: { [property]: direction },
|
|
118
|
-
rows: formatRows({
|
|
108
|
+
rows: formatRows({
|
|
109
|
+
rows: getParsedRowData(data),
|
|
110
|
+
url: match.url,
|
|
111
|
+
toggleModal,
|
|
112
|
+
firstColumn,
|
|
113
|
+
isEnquiry
|
|
114
|
+
})
|
|
119
115
|
});
|
|
120
116
|
};
|
|
121
117
|
|
|
@@ -137,7 +133,12 @@ const ListingTable = ({ match, entitySchema, selectedMenuItem }) => {
|
|
|
137
133
|
});
|
|
138
134
|
const updatedRows = [
|
|
139
135
|
...tableData.rows,
|
|
140
|
-
...formatRows({
|
|
136
|
+
...formatRows({
|
|
137
|
+
rows: getParsedRowData(data),
|
|
138
|
+
url: match.url,
|
|
139
|
+
toggleModal,
|
|
140
|
+
isEnquiry: tableData.isEnquiry
|
|
141
|
+
})
|
|
141
142
|
];
|
|
142
143
|
|
|
143
144
|
setVerifiedRanges([...verifiedRanges, loadIndex]);
|
|
@@ -151,6 +152,7 @@ const ListingTable = ({ match, entitySchema, selectedMenuItem }) => {
|
|
|
151
152
|
};
|
|
152
153
|
|
|
153
154
|
if (!tableData || !tableData.rows) return 'loading';
|
|
155
|
+
const showAddButton = !!tableData.rows.length && !tableData.isEnquiry;
|
|
154
156
|
|
|
155
157
|
return (
|
|
156
158
|
<div className="page">
|
|
@@ -162,7 +164,7 @@ const ListingTable = ({ match, entitySchema, selectedMenuItem }) => {
|
|
|
162
164
|
/>
|
|
163
165
|
)}
|
|
164
166
|
<PageHeader title={entitySchema.displayName} subtitle="">
|
|
165
|
-
{
|
|
167
|
+
{showAddButton && (
|
|
166
168
|
<Fragment>
|
|
167
169
|
<Link
|
|
168
170
|
data-testid="addEntity"
|
|
@@ -181,13 +183,13 @@ const ListingTable = ({ match, entitySchema, selectedMenuItem }) => {
|
|
|
181
183
|
</Fragment>
|
|
182
184
|
)}
|
|
183
185
|
</PageHeader>
|
|
186
|
+
<RenderHook hookKey="entity:listing:main:top" schema={entitySchema} />
|
|
184
187
|
<ListingTableContent
|
|
185
188
|
overScanBuffer={OVER_SCAN_BUFFER}
|
|
186
189
|
onSort={handleSort}
|
|
187
190
|
onRenderItems={handleRenderedItems}
|
|
188
191
|
tableData={tableData}
|
|
189
192
|
onCloseCardPrompt={onCloseCardPrompt}
|
|
190
|
-
selectedMenuItem={selectedMenuItem}
|
|
191
193
|
scrollToIndex={scrollToIndex}
|
|
192
194
|
/>
|
|
193
195
|
</div>
|
|
@@ -195,8 +197,7 @@ const ListingTable = ({ match, entitySchema, selectedMenuItem }) => {
|
|
|
195
197
|
};
|
|
196
198
|
ListingTable.propTypes = {
|
|
197
199
|
entitySchema: PropTypes.object.isRequired,
|
|
198
|
-
match: PropTypes.object.isRequired
|
|
199
|
-
selectedMenuItem: PropTypes.object.isRequired
|
|
200
|
+
match: PropTypes.object.isRequired
|
|
200
201
|
};
|
|
201
202
|
|
|
202
203
|
export default withRouter(ListingTable);
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import Table from '@blaze-react/table';
|
|
3
3
|
import PropTypes from 'prop-types';
|
|
4
|
-
import {
|
|
5
|
-
import { Link, withRouter } from 'react-router-dom';
|
|
4
|
+
import { withRouter } from 'react-router-dom';
|
|
6
5
|
|
|
7
6
|
const ListingTableContent = ({
|
|
8
7
|
tableData,
|
|
@@ -17,12 +16,14 @@ const ListingTableContent = ({
|
|
|
17
16
|
scrollToIndex
|
|
18
17
|
}) => {
|
|
19
18
|
const displayTable = tableData && tableData.rows && !!tableData.rows.length;
|
|
19
|
+
const { isEnquiry } = tableData;
|
|
20
|
+
const className = `page__content${isEnquiry ? ' array-table' : ''}`;
|
|
20
21
|
|
|
21
22
|
return (
|
|
22
23
|
<>
|
|
23
|
-
{displayTable
|
|
24
|
+
{displayTable && (
|
|
24
25
|
<>
|
|
25
|
-
<div className=
|
|
26
|
+
<div className={className}>
|
|
26
27
|
<Table
|
|
27
28
|
scrollToIndex={scrollToIndex}
|
|
28
29
|
onSort={onSort}
|
|
@@ -30,23 +31,12 @@ const ListingTableContent = ({
|
|
|
30
31
|
overScanBuffer={overScanBuffer}
|
|
31
32
|
onRenderItems={onRenderItems}
|
|
32
33
|
data={tableData}
|
|
33
|
-
checkboxes
|
|
34
|
+
checkboxes={!isEnquiry}
|
|
34
35
|
onSelect={handleSelect}
|
|
35
36
|
data-testid="listing-table-content"
|
|
36
37
|
/>
|
|
37
38
|
</div>
|
|
38
39
|
</>
|
|
39
|
-
) : (
|
|
40
|
-
selectedMenuItem.isDisplayedPrompt && (
|
|
41
|
-
<CardPrompt onClose={onCloseCardPrompt} data-testid="card-prompt">
|
|
42
|
-
<Link
|
|
43
|
-
className="button button--rounded button--cta"
|
|
44
|
-
to={`${match.url}/create`}
|
|
45
|
-
data-testid="add-button">
|
|
46
|
-
Add
|
|
47
|
-
</Link>
|
|
48
|
-
</CardPrompt>
|
|
49
|
-
)
|
|
50
40
|
)}
|
|
51
41
|
</>
|
|
52
42
|
);
|
|
@@ -55,7 +45,7 @@ const ListingTableContent = ({
|
|
|
55
45
|
ListingTableContent.propTypes = {
|
|
56
46
|
tableData: PropTypes.object.isRequired,
|
|
57
47
|
onCloseCardPrompt: PropTypes.func.isRequired,
|
|
58
|
-
selectedMenuItem: PropTypes.object
|
|
48
|
+
selectedMenuItem: PropTypes.object,
|
|
59
49
|
match: PropTypes.shape({
|
|
60
50
|
url: PropTypes.string
|
|
61
51
|
}).isRequired,
|
|
@@ -73,7 +63,8 @@ ListingTableContent.defaultProps = {
|
|
|
73
63
|
onClickRow: () => {},
|
|
74
64
|
overScanBuffer: 0,
|
|
75
65
|
scrollToIndex: 0,
|
|
76
|
-
onRenderItems: () => {}
|
|
66
|
+
onRenderItems: () => {},
|
|
67
|
+
selectedMenuItem: null
|
|
77
68
|
};
|
|
78
69
|
|
|
79
70
|
export default withRouter(ListingTableContent);
|
|
@@ -3,18 +3,22 @@ import { Link } from 'react-router-dom';
|
|
|
3
3
|
import TableActions from '../TableActions';
|
|
4
4
|
import { ACTIONS } from '../../../constants';
|
|
5
5
|
|
|
6
|
-
const formatRows = ({ rows, url, toggleModal, label, firstColumn = 'name' }) =>
|
|
6
|
+
const formatRows = ({ rows, url, toggleModal, label, firstColumn = 'name', isEnquiry }) =>
|
|
7
7
|
rows.map(data => {
|
|
8
8
|
const editUrl = `${url}/update/${data.id}`;
|
|
9
|
-
|
|
9
|
+
const rowProps = {
|
|
10
10
|
...data,
|
|
11
11
|
[firstColumn]: (
|
|
12
12
|
<Link to={editUrl} role="button">
|
|
13
13
|
{data[firstColumn]}
|
|
14
14
|
</Link>
|
|
15
|
-
)
|
|
16
|
-
actions: <TableActions editUrl={editUrl} data={data} showDeleteModal={toggleModal} />
|
|
15
|
+
)
|
|
17
16
|
};
|
|
17
|
+
if (!isEnquiry)
|
|
18
|
+
rowProps.actions = (
|
|
19
|
+
<TableActions editUrl={editUrl} data={data} showDeleteModal={toggleModal} />
|
|
20
|
+
);
|
|
21
|
+
return rowProps;
|
|
18
22
|
});
|
|
19
23
|
|
|
20
24
|
const getSanitizedColumnLabel = columnProp => {
|
|
@@ -28,22 +32,82 @@ const getSanitizedColumnLabel = columnProp => {
|
|
|
28
32
|
return sanitizedChar;
|
|
29
33
|
};
|
|
30
34
|
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
const buildArrayRowContent = rowData => (
|
|
36
|
+
<div className="table-row-list">
|
|
37
|
+
{rowData.map(rowGroup => (
|
|
38
|
+
<div className="table-row-list__group">
|
|
39
|
+
{rowGroup.map(({ label, value, url }) => (
|
|
40
|
+
<div className="table-row-list__group__item">
|
|
41
|
+
<span className="table-row-list__group__item__label"> {label}:</span>
|
|
42
|
+
{url ? (
|
|
43
|
+
<Link to={url} role="button" className="table-row-list__group__item__value">
|
|
44
|
+
{value}
|
|
45
|
+
</Link>
|
|
46
|
+
) : (
|
|
47
|
+
<span className="table-row-list__group__item__value"> {value}</span>
|
|
48
|
+
)}
|
|
49
|
+
</div>
|
|
50
|
+
))}
|
|
51
|
+
</div>
|
|
52
|
+
))}
|
|
53
|
+
</div>
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
const buildArrayRowData = rowData => {
|
|
57
|
+
const dataGroups = [];
|
|
58
|
+
const groups = Math.ceil(rowData.length / 3) || 1;
|
|
59
|
+
for (let index = 0; index < groups; index += 1) {
|
|
60
|
+
const currentStart = index * groups;
|
|
61
|
+
dataGroups[index] = rowData.slice(currentStart, currentStart + 3);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return buildArrayRowContent(dataGroups);
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
const getParsedRowData = rows =>
|
|
68
|
+
rows.map(rowData =>
|
|
69
|
+
Object.keys(rowData).reduce((acc, key) => {
|
|
70
|
+
const parsedData = Array.isArray(rowData[key])
|
|
71
|
+
? buildArrayRowData(rowData[key])
|
|
72
|
+
: rowData[key];
|
|
73
|
+
return { ...acc, [key]: parsedData };
|
|
74
|
+
}, {})
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
const getColumnsAndLabels = (listingProperties, allProperties, rows) => {
|
|
78
|
+
const columns = [];
|
|
79
|
+
const labels = {};
|
|
80
|
+
|
|
81
|
+
listingProperties.forEach(listingProperty => {
|
|
82
|
+
const propKey = listingProperty.includes(' ') ? listingProperty.split(' ')[0] : listingProperty;
|
|
83
|
+
const { label } = allProperties[propKey] || {};
|
|
84
|
+
columns.push(propKey);
|
|
85
|
+
labels[propKey] = label || getSanitizedColumnLabel(propKey);
|
|
86
|
+
});
|
|
87
|
+
const parsedRowData = getParsedRowData(rows);
|
|
88
|
+
|
|
89
|
+
return { columns, labels, parsedRowData };
|
|
37
90
|
};
|
|
38
91
|
|
|
39
92
|
const populateRows = ({ toggleModal, url, entitySchema, rows }) => {
|
|
40
|
-
const {
|
|
41
|
-
|
|
93
|
+
const {
|
|
94
|
+
id: schemaId,
|
|
95
|
+
listingProperties,
|
|
96
|
+
properties,
|
|
97
|
+
dynamicProperties = {},
|
|
98
|
+
formProperties
|
|
99
|
+
} = entitySchema;
|
|
100
|
+
|
|
101
|
+
const isEnquiry = schemaId === 'enquiry';
|
|
102
|
+
const columnOptions = !isEnquiry ? [...listingProperties, ACTIONS] : [...listingProperties];
|
|
103
|
+
|
|
104
|
+
const allProperties = { ...properties, ...dynamicProperties };
|
|
105
|
+
const { columns, labels, parsedRowData } = getColumnsAndLabels(
|
|
106
|
+
columnOptions,
|
|
107
|
+
allProperties,
|
|
108
|
+
rows
|
|
109
|
+
);
|
|
42
110
|
const [firstColumn] = columns;
|
|
43
|
-
const labels = {
|
|
44
|
-
...getColumnLabels(listingProperties, properties, dynamicProperties),
|
|
45
|
-
[ACTIONS]: ACTIONS
|
|
46
|
-
};
|
|
47
111
|
|
|
48
112
|
return {
|
|
49
113
|
identification: 'id',
|
|
@@ -51,8 +115,9 @@ const populateRows = ({ toggleModal, url, entitySchema, rows }) => {
|
|
|
51
115
|
columns,
|
|
52
116
|
labels,
|
|
53
117
|
orderBy: [...formProperties],
|
|
54
|
-
rows: formatRows({ firstColumn, rows, url, toggleModal })
|
|
118
|
+
rows: formatRows({ firstColumn, rows: parsedRowData, url, toggleModal, isEnquiry }),
|
|
119
|
+
isEnquiry
|
|
55
120
|
};
|
|
56
121
|
};
|
|
57
122
|
|
|
58
|
-
export { populateRows, formatRows };
|
|
123
|
+
export { populateRows, formatRows, getParsedRowData };
|
package/src/index.js
CHANGED
|
@@ -12,14 +12,7 @@ const EntityManager = React.lazy(() =>
|
|
|
12
12
|
);
|
|
13
13
|
|
|
14
14
|
export default async function load(app) {
|
|
15
|
-
|
|
16
|
-
const sectionKey = 'content';
|
|
17
|
-
|
|
18
|
-
app.events.once('load:menu-section', addSection => {
|
|
19
|
-
addSection(sectionKey, { header: 'content', order: 100 });
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
app.events.once('load:menu-items', getAddContentMenuItems(app, sectionKey));
|
|
15
|
+
app.events.once('admin:menu:config:load', getAddContentMenuItems(app));
|
|
23
16
|
|
|
24
17
|
app.events.once('load:custom:field:type', addFieldType => {
|
|
25
18
|
Object.keys(formFieldTypes).forEach(type => {
|
|
@@ -2,8 +2,8 @@ import { getQuery } from '@blaze-cms/admin-ui-utils';
|
|
|
2
2
|
|
|
3
3
|
const { MENU_PERMISSIONS } = require('../constants');
|
|
4
4
|
|
|
5
|
-
function getAddContentMenuItems(app
|
|
6
|
-
return async
|
|
5
|
+
function getAddContentMenuItems(app) {
|
|
6
|
+
return async ({ addConfig }) => {
|
|
7
7
|
const client = app.getClient();
|
|
8
8
|
const {
|
|
9
9
|
data: { getEntitySchemas }
|
|
@@ -14,9 +14,51 @@ function getAddContentMenuItems(app, sectionKey) {
|
|
|
14
14
|
canDoActions: MENU_PERMISSIONS
|
|
15
15
|
}
|
|
16
16
|
});
|
|
17
|
+
|
|
18
|
+
if (!getEntitySchemas || !getEntitySchemas.length) return; // no items so don't add section
|
|
19
|
+
|
|
20
|
+
const menuItems = {};
|
|
21
|
+
const sectionMenuItems = { content: {} };
|
|
22
|
+
|
|
23
|
+
getEntitySchemas.forEach(({ id, displayName, displayProperties }) => {
|
|
24
|
+
if (!displayProperties) return null;
|
|
25
|
+
|
|
26
|
+
const { adminMenu: { sectionKey = 'content' } = {} } = displayProperties;
|
|
27
|
+
const sectionItems = sectionMenuItems[sectionKey] || {};
|
|
28
|
+
sectionItems[id] = {
|
|
29
|
+
label: displayName,
|
|
30
|
+
uri: `/data-listing/${id}`
|
|
31
|
+
};
|
|
32
|
+
sectionMenuItems[sectionKey] = sectionItems;
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
const menuConfig = {
|
|
36
|
+
main: {
|
|
37
|
+
items: {
|
|
38
|
+
content: {
|
|
39
|
+
label: 'Content',
|
|
40
|
+
loadOpen: true,
|
|
41
|
+
order: 10,
|
|
42
|
+
items: menuItems
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
Object.entries(sectionMenuItems).forEach(([sectionKey, sectionItems]) => {
|
|
49
|
+
const sectionConfig = menuConfig.main.items[sectionKey] || {};
|
|
50
|
+
sectionConfig.items = sectionItems;
|
|
51
|
+
menuConfig.main.items[sectionKey] = sectionConfig;
|
|
52
|
+
});
|
|
53
|
+
|
|
17
54
|
getEntitySchemas.forEach(({ id, displayName }) => {
|
|
18
|
-
|
|
55
|
+
menuItems[id] = {
|
|
56
|
+
label: displayName,
|
|
57
|
+
uri: `/data-listing/${id}`
|
|
58
|
+
};
|
|
19
59
|
});
|
|
60
|
+
|
|
61
|
+
addConfig(menuConfig);
|
|
20
62
|
};
|
|
21
63
|
}
|
|
22
64
|
|