@truedat/dd 4.40.9 → 4.40.10

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 CHANGED
@@ -1,5 +1,16 @@
1
1
  # Changelog
2
2
 
3
+ ## [4.40.10] 2022-03-21
4
+
5
+ ### Changed
6
+
7
+ - [TD-4447] Support for associating metadata filters with a structure type
8
+
9
+ ### Removed
10
+
11
+ - [TD-4303] `GET /api/data_structure_types/lite` was removed, reverted
12
+ corresponding changes from [TD-4344]
13
+
3
14
  ## [4.40.7] 2022-03-18
4
15
 
5
16
  ### Added
@@ -10,7 +21,7 @@
10
21
 
11
22
  ### Changed
12
23
 
13
- - [TD-4500] Remove unnecessary domain_id attribute on GrantRequestApprovalForm
24
+ - [TD-4500] Remove unnecessary `domain_id` attribute on `GrantRequestApprovalForm`
14
25
 
15
26
  ## [4.40.2] 2022-03-14
16
27
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@truedat/dd",
3
- "version": "4.40.9",
3
+ "version": "4.40.10",
4
4
  "description": "Truedat Web Data Dictionary",
5
5
  "sideEffects": false,
6
6
  "jsnext:main": "src/index.js",
@@ -34,7 +34,7 @@
34
34
  "@testing-library/jest-dom": "^5.14.1",
35
35
  "@testing-library/react": "^12.0.0",
36
36
  "@testing-library/user-event": "^13.2.1",
37
- "@truedat/test": "4.40.9",
37
+ "@truedat/test": "4.40.10",
38
38
  "babel-jest": "^27.0.6",
39
39
  "babel-plugin-dynamic-import-node": "^2.3.3",
40
40
  "babel-plugin-lodash": "^3.3.4",
@@ -84,9 +84,9 @@
84
84
  ]
85
85
  },
86
86
  "dependencies": {
87
- "@truedat/auth": "4.40.9",
88
- "@truedat/core": "4.40.9",
89
- "@truedat/df": "4.40.9",
87
+ "@truedat/auth": "4.40.10",
88
+ "@truedat/core": "4.40.10",
89
+ "@truedat/df": "4.40.10",
90
90
  "lodash": "^4.17.21",
91
91
  "path-to-regexp": "^1.7.0",
92
92
  "prop-types": "^15.7.2",
@@ -107,5 +107,5 @@
107
107
  "react-dom": ">= 16.8.6 < 17",
108
108
  "semantic-ui-react": ">= 0.88.2 < 2.1"
109
109
  },
110
- "gitHead": "618928c0c77ccea1e95b9a6d3255ecf8cbed0c90"
110
+ "gitHead": "2a753ab01d2f856c32336cebc938b83f4bc97ea6"
111
111
  }
package/src/api.js CHANGED
@@ -31,7 +31,6 @@ const API_STRUCTURE_TAG = "/api/data_structure_tags/:id";
31
31
  const API_STRUCTURE_TAGS = "/api/data_structure_tags";
32
32
  const API_STRUCTURE_TYPE = "/api/data_structure_types/:id";
33
33
  const API_STRUCTURE_TYPES = "/api/data_structure_types";
34
- const API_STRUCTURE_TYPES_LITE = "/api/data_structure_types/lite";
35
34
  const API_STRUCTURES_TAG = "/api/data_structures/:data_structure_id/tags/:id";
36
35
  const API_STRUCTURES_TAGS = "/api/data_structures/:data_structure_id/tags";
37
36
  const API_USER_SEARCH_FILTERS = "/api/user_search_filters";
@@ -77,7 +76,6 @@ export {
77
76
  API_STRUCTURE_TAGS,
78
77
  API_STRUCTURE_TYPE,
79
78
  API_STRUCTURE_TYPES,
80
- API_STRUCTURE_TYPES_LITE,
81
79
  API_USER_SEARCH_FILTERS,
82
80
  API_USER_SEARCH_FILTER,
83
81
  API_GET_USER_SEARCH_FILTERS,
@@ -48,7 +48,7 @@ export const DictionaryRoutes = () => {
48
48
  path={STRUCTURES}
49
49
  render={() => (
50
50
  <>
51
- <StructureTypesLoader liteRequest={true} />
51
+ <StructureTypesLoader />
52
52
  <SystemsLoader />
53
53
  <StructuresRoutes />
54
54
  </>
@@ -58,7 +58,7 @@ export const DictionaryRoutes = () => {
58
58
  path={SYSTEMS}
59
59
  render={() => (
60
60
  <>
61
- <StructureTypesLoader liteRequest={true} />
61
+ <StructureTypesLoader />
62
62
  <SystemsLoader />
63
63
  <SystemsRoutes />
64
64
  </>
@@ -68,7 +68,7 @@ export const DictionaryRoutes = () => {
68
68
  path={STRUCTURE_TAGS}
69
69
  render={() => (
70
70
  <>
71
- <StructureTypesLoader liteRequest={true} />
71
+ <StructureTypesLoader />
72
72
  <StructureTagsRoutes />
73
73
  </>
74
74
  )}
@@ -77,7 +77,7 @@ export const DictionaryRoutes = () => {
77
77
  path={STRUCTURE_TYPES}
78
78
  render={() => (
79
79
  <>
80
- <StructureTypesLoader liteRequest={true} />
80
+ <StructureTypesLoader />
81
81
  <StructureTypesRoutes />
82
82
  </>
83
83
  )}
@@ -86,7 +86,7 @@ export const DictionaryRoutes = () => {
86
86
  path={PROFILE_GROUP}
87
87
  render={() => (
88
88
  <>
89
- <StructureTypesLoader liteRequest={true} />
89
+ <StructureTypesLoader />
90
90
  <Route render={() => <ProfileGroupLoader />} />
91
91
  <Switch>
92
92
  <Route
@@ -0,0 +1,42 @@
1
+ import _ from "lodash/fp";
2
+ import React from "react";
3
+ import PropTypes from "prop-types";
4
+ import { Controller } from "react-hook-form";
5
+ import { useIntl } from "react-intl";
6
+ import { Form } from "semantic-ui-react";
7
+
8
+ export const MetadataFiltersInput = ({ control, fieldOptions, fields }) => {
9
+ const { formatMessage } = useIntl();
10
+ return (
11
+ <Controller
12
+ control={control}
13
+ name="filters"
14
+ defaultValue={_.isArray(fields) ? fields : []}
15
+ render={({ onBlur, onChange, value }) => (
16
+ <Form.Dropdown
17
+ name="filters"
18
+ label={formatMessage({ id: "structureType.filters" })}
19
+ search
20
+ selection
21
+ clearable
22
+ multiple
23
+ options={fieldOptions}
24
+ onBlur={onBlur}
25
+ onChange={(_e, { value }) => onChange(value)}
26
+ placeholder={formatMessage({
27
+ id: "structureType.filters.placeholder",
28
+ })}
29
+ value={value}
30
+ />
31
+ )}
32
+ />
33
+ );
34
+ };
35
+
36
+ MetadataFiltersInput.propTypes = {
37
+ control: PropTypes.object,
38
+ fieldOptions: PropTypes.array,
39
+ fields: PropTypes.array,
40
+ };
41
+
42
+ export default MetadataFiltersInput;
@@ -35,7 +35,7 @@ export const StructureSelector = ({
35
35
  return (
36
36
  <Segment>
37
37
  <StructuresLoader pageSize={pageSize} defaultFilters={defaultFilters} />
38
- <StructureTypesLoader liteRequest={true} />
38
+ <StructureTypesLoader />
39
39
  <StructureFiltersLoader defaultFilters={defaultFilters} />
40
40
  <StructuresSearch />
41
41
  <StructureSelectedFilters />
@@ -3,7 +3,7 @@ import React from "react";
3
3
  import PropTypes from "prop-types";
4
4
  import { connect } from "react-redux";
5
5
  import { useForm, useFieldArray, Controller } from "react-hook-form";
6
- import { useIntl } from "react-intl";
6
+ import { useIntl, FormattedMessage } from "react-intl";
7
7
  import {
8
8
  accentInsensitiveOrder,
9
9
  accentInsensitivePathOrder,
@@ -11,6 +11,7 @@ import {
11
11
  import { HistoryBackButton } from "@truedat/core/components";
12
12
  import { Button, Form } from "semantic-ui-react";
13
13
  import { updateStructureType } from "../routines";
14
+ import MetadataFiltersInput from "./MetadataFiltersInput";
14
15
  import MetadataViewForm from "./MetadataViewForm";
15
16
 
16
17
  export const StructureTypeForm = ({
@@ -24,6 +25,7 @@ export const StructureTypeForm = ({
24
25
  const { handleSubmit, control, formState } = useForm({
25
26
  mode: "all",
26
27
  defaultValues: {
28
+ filters: structureType?.filters || [],
27
29
  metadata_views: structureType?.metadata_views || [],
28
30
  template_id: structureType?.template?.id || "",
29
31
  translation: structureType?.translation || "",
@@ -88,6 +90,13 @@ export const StructureTypeForm = ({
88
90
  />
89
91
  )}
90
92
  />
93
+ {_.isEmpty(structureType?.metadata_fields) ? null : (
94
+ <MetadataFiltersInput
95
+ control={control}
96
+ fieldOptions={fieldOptions}
97
+ fields={structureType.metadata_fields}
98
+ />
99
+ )}
91
100
  {metadata_views.map(({ id, name, fields }, idx) => (
92
101
  <MetadataViewForm
93
102
  key={id}
@@ -107,9 +116,11 @@ export const StructureTypeForm = ({
107
116
  loading={saving}
108
117
  content={formatMessage({ id: "actions.save" })}
109
118
  />
110
- <Button as="a" floated="left" onClick={() => append({ name: "" })}>
111
- Add Metadata View
112
- </Button>
119
+ {_.isEmpty(structureType?.metadata_fields) ? null : (
120
+ <Button as="a" floated="left" onClick={() => append({ name: "" })}>
121
+ <FormattedMessage id="structureType.actions.addMetadataView" />
122
+ </Button>
123
+ )}
113
124
  <HistoryBackButton content={formatMessage({ id: "actions.cancel" })} />
114
125
  </div>
115
126
  </Form>
@@ -6,21 +6,19 @@ import { clearStructureTypes, fetchStructureTypes } from "../routines";
6
6
  export const StructureTypesLoader = ({
7
7
  clearStructureTypes,
8
8
  fetchStructureTypes,
9
- liteRequest = false,
10
9
  }) => {
11
10
  useEffect(() => {
12
- fetchStructureTypes({ liteRequest });
11
+ fetchStructureTypes();
13
12
  return () => {
14
13
  clearStructureTypes();
15
14
  };
16
- }, [clearStructureTypes, fetchStructureTypes, liteRequest]);
15
+ }, [clearStructureTypes, fetchStructureTypes]);
17
16
  return null;
18
17
  };
19
18
 
20
19
  StructureTypesLoader.propTypes = {
21
20
  clearStructureTypes: PropTypes.func,
22
21
  fetchStructureTypes: PropTypes.func,
23
- liteRequest: PropTypes.bool,
24
22
  };
25
23
 
26
24
  export default connect(null, { clearStructureTypes, fetchStructureTypes })(
@@ -50,9 +50,7 @@ export const StructureTypeRow = ({
50
50
  <Table.Cell>
51
51
  {_.flow(_.map("name"), _.join(", "))(metadata_views)}
52
52
  </Table.Cell>
53
- {hasMetadataFields && (
54
- <Table.Cell className="text-right">{metadata_fields?.length}</Table.Cell>
55
- )}
53
+ <Table.Cell className="text-right">{metadata_fields?.length}</Table.Cell>
56
54
  </Table.Row>
57
55
  );
58
56
 
@@ -67,8 +65,6 @@ StructureTypeRow.propTypes = {
67
65
 
68
66
  export const StructureTypesTable = ({ structureTypes, loading }) => {
69
67
  const { formatMessage } = useIntl();
70
- const hasMetadataFields =
71
- _.filter("metadata_fields")(structureTypes).length > 0;
72
68
  return loading ? null : (
73
69
  <Table basic definition>
74
70
  <Table.Header>
@@ -83,21 +79,15 @@ export const StructureTypesTable = ({ structureTypes, loading }) => {
83
79
  <Table.HeaderCell
84
80
  content={formatMessage({ id: "structureType.metadataViews" })}
85
81
  />
86
- {hasMetadataFields && (
87
- <Table.HeaderCell
88
- className="text-right"
89
- content={formatMessage({ id: "structureType.metadataFields" })}
90
- />
91
- )}
82
+ <Table.HeaderCell
83
+ className="text-right"
84
+ content={formatMessage({ id: "structureType.metadataFields" })}
85
+ />
92
86
  </Table.Row>
93
87
  </Table.Header>
94
88
  <Table.Body>
95
89
  {structureTypes.map((props, key) => (
96
- <StructureTypeRow
97
- key={key}
98
- {...props}
99
- hasMetadataFields={hasMetadataFields}
100
- />
90
+ <StructureTypeRow key={key} {...props} />
101
91
  ))}
102
92
  </Table.Body>
103
93
  </Table>
@@ -6,7 +6,8 @@ const structureType = {
6
6
  id: 123,
7
7
  name: "foo",
8
8
  template_id: 1,
9
- metadata_fields: ["one"],
9
+ filters: ["one"],
10
+ metadata_fields: ["one", "two"],
10
11
  metadata_views: [
11
12
  { name: "default", fields: ["one"] },
12
13
  { name: "custom", fields: [] },
@@ -24,7 +25,10 @@ const renderOpts = {
24
25
  "actions.cancel": "cancel",
25
26
  "actions.save": "save",
26
27
  "metadataView.fields": "Fields",
27
- "metadataView.fields.placeholder": "Placeholder",
28
+ "metadataView.fields.placeholder": "select fields",
29
+ "structureType.actions.addMetadataView": "add metadata view",
30
+ "structureType.filters": "filters",
31
+ "structureType.filters.placeholder": "select filters",
28
32
  "structureType.template": "template",
29
33
  "structureType.translation": "translation",
30
34
  },
@@ -5,9 +5,7 @@ exports[`<StructureSelector /> matches the latest snapshot 1`] = `
5
5
  <Connect(StructuresLoader)
6
6
  pageSize={7}
7
7
  />
8
- <Connect(StructureTypesLoader)
9
- liteRequest={true}
10
- />
8
+ <Connect(StructureTypesLoader) />
11
9
  <Connect(FiltersLoader) />
12
10
  <Connect(StructuresSearch) />
13
11
  <injectIntl(Connect(SelectedFilters)) />
@@ -71,6 +71,72 @@ exports[`<StructureTypeForm /> matches the latest snapshot 1`] = `
71
71
  </div>
72
72
  </div>
73
73
  </div>
74
+ <div
75
+ class="field"
76
+ >
77
+ <label>
78
+ filters
79
+ </label>
80
+ <div
81
+ aria-expanded="false"
82
+ class="ui multiple search selection dropdown"
83
+ name="filters"
84
+ role="combobox"
85
+ >
86
+ <a
87
+ class="ui label"
88
+ value="one"
89
+ >
90
+ one
91
+ <i
92
+ aria-hidden="true"
93
+ class="delete icon"
94
+ />
95
+ </a>
96
+ <input
97
+ aria-autocomplete="list"
98
+ autocomplete="off"
99
+ class="search"
100
+ tabindex="0"
101
+ type="text"
102
+ value=""
103
+ />
104
+ <span
105
+ class="sizer"
106
+ />
107
+ <div
108
+ aria-atomic="true"
109
+ aria-live="polite"
110
+ class="divider text"
111
+ role="alert"
112
+ >
113
+ select filters
114
+ </div>
115
+ <i
116
+ aria-hidden="true"
117
+ class="dropdown icon clear"
118
+ />
119
+ <div
120
+ aria-multiselectable="true"
121
+ class="menu transition"
122
+ role="listbox"
123
+ >
124
+ <div
125
+ aria-checked="false"
126
+ aria-selected="true"
127
+ class="selected item"
128
+ role="option"
129
+ style="pointer-events: all;"
130
+ >
131
+ <span
132
+ class="text"
133
+ >
134
+ two
135
+ </span>
136
+ </div>
137
+ </div>
138
+ </div>
139
+ </div>
74
140
  <div
75
141
  class="ui segment"
76
142
  >
@@ -136,7 +202,7 @@ exports[`<StructureTypeForm /> matches the latest snapshot 1`] = `
136
202
  class="divider text"
137
203
  role="alert"
138
204
  >
139
- Placeholder
205
+ select fields
140
206
  </div>
141
207
  <i
142
208
  aria-hidden="true"
@@ -148,9 +214,17 @@ exports[`<StructureTypeForm /> matches the latest snapshot 1`] = `
148
214
  role="listbox"
149
215
  >
150
216
  <div
151
- class="message"
217
+ aria-checked="false"
218
+ aria-selected="true"
219
+ class="selected item"
220
+ role="option"
221
+ style="pointer-events: all;"
152
222
  >
153
- No results found.
223
+ <span
224
+ class="text"
225
+ >
226
+ two
227
+ </span>
154
228
  </div>
155
229
  </div>
156
230
  </div>
@@ -211,7 +285,7 @@ exports[`<StructureTypeForm /> matches the latest snapshot 1`] = `
211
285
  class="divider default text"
212
286
  role="alert"
213
287
  >
214
- Placeholder
288
+ select fields
215
289
  </div>
216
290
  <i
217
291
  aria-hidden="true"
@@ -235,6 +309,19 @@ exports[`<StructureTypeForm /> matches the latest snapshot 1`] = `
235
309
  one
236
310
  </span>
237
311
  </div>
312
+ <div
313
+ aria-checked="false"
314
+ aria-selected="false"
315
+ class="item"
316
+ role="option"
317
+ style="pointer-events: all;"
318
+ >
319
+ <span
320
+ class="text"
321
+ >
322
+ two
323
+ </span>
324
+ </div>
238
325
  </div>
239
326
  </div>
240
327
  </div>
@@ -254,7 +341,7 @@ exports[`<StructureTypeForm /> matches the latest snapshot 1`] = `
254
341
  class="ui left floated button"
255
342
  role="button"
256
343
  >
257
- Add Metadata View
344
+ add metadata view
258
345
  </a>
259
346
  <a
260
347
  class="ui secondary button"
@@ -329,6 +329,9 @@ export default {
329
329
  "structureTags.empty": "There are no Structure Tags yet",
330
330
  "structureTags.header": "Structure tags management",
331
331
  "structureTags.subheader": "Tags for Data Catalog",
332
+ "structureType.actions.addMetadataView": "Add Metadata View",
333
+ "structureType.filters": "Filters",
334
+ "structureType.filters.placeholder": "Select filterable fields",
332
335
  "structureType.metadataFields": "Metadata Fields",
333
336
  "structureType.metadataViews": "Metadata Views",
334
337
  "structureType.name": "Type",
@@ -333,6 +333,9 @@ export default {
333
333
  "structureTags.empty": "Aún no hay ninguna Etiqueta de Estructura",
334
334
  "structureTags.header": "Gestión de Etiquetas de Estructuras",
335
335
  "structureTags.subheader": "Etiquetas para el Catálogo de Datos",
336
+ "structureType.actions.addMetadataView": "Añadir vista de metadata",
337
+ "structureType.filters": "Filtros",
338
+ "structureType.filters.placeholder": "Seleccionar campos filtrables",
336
339
  "structureType.metadataFields": "Campos de metadata",
337
340
  "structureType.metadataViews": "Vistas de metadata",
338
341
  "structureType.name": "Tipo",
@@ -1,14 +1,12 @@
1
1
  import { call, put, takeLatest } from "redux-saga/effects";
2
2
  import { apiJson, JSON_OPTS } from "@truedat/core/services/api";
3
3
  import { fetchStructureTypes } from "../routines";
4
- import { API_STRUCTURE_TYPES, API_STRUCTURE_TYPES_LITE } from "../api";
4
+ import { API_STRUCTURE_TYPES } from "../api";
5
5
 
6
- export function* fetchStructureTypesSaga({ payload }) {
6
+ export function* fetchStructureTypesSaga() {
7
7
  try {
8
- const { liteRequest } = payload;
9
8
  yield put(fetchStructureTypes.request());
10
- const url = liteRequest ? API_STRUCTURE_TYPES_LITE : API_STRUCTURE_TYPES;
11
- const { data } = yield call(apiJson, url, JSON_OPTS);
9
+ const { data } = yield call(apiJson, API_STRUCTURE_TYPES, JSON_OPTS);
12
10
  yield put(fetchStructureTypes.success(data));
13
11
  } catch (error) {
14
12
  if (error.response) {