@truedat/dd 4.54.7 → 4.54.9

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,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [4.54.8] 2022-10-28
4
+
5
+ ### Changed
6
+
7
+ - [TD-3646] StructuresBulkUpdate uses GraphQL to render preprocessed
8
+ template with domain if only one is selected
9
+
3
10
  ## [4.54.0] 2022-10-21
4
11
 
5
12
  ### Added
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@truedat/dd",
3
- "version": "4.54.7",
3
+ "version": "4.54.9",
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.16.4",
35
35
  "@testing-library/react": "^12.0.0",
36
36
  "@testing-library/user-event": "^13.2.1",
37
- "@truedat/test": "4.54.7",
37
+ "@truedat/test": "4.54.9",
38
38
  "babel-jest": "^28.1.0",
39
39
  "babel-plugin-dynamic-import-node": "^2.3.3",
40
40
  "babel-plugin-lodash": "^3.3.4",
@@ -88,9 +88,9 @@
88
88
  },
89
89
  "dependencies": {
90
90
  "@apollo/client": "^3.7.0",
91
- "@truedat/auth": "4.54.7",
92
- "@truedat/core": "4.54.7",
93
- "@truedat/df": "4.54.7",
91
+ "@truedat/auth": "4.54.9",
92
+ "@truedat/core": "4.54.9",
93
+ "@truedat/df": "4.54.9",
94
94
  "lodash": "^4.17.21",
95
95
  "path-to-regexp": "^1.7.0",
96
96
  "prop-types": "^15.8.1",
@@ -112,5 +112,5 @@
112
112
  "react-dom": ">= 16.8.6 < 17",
113
113
  "semantic-ui-react": ">= 0.88.2 < 2.1"
114
114
  },
115
- "gitHead": "5fc1e696a1449d9e0b68531f109cc7a8a2dd9543"
115
+ "gitHead": "27f711249723050708a6f6f4de3ab5029069c4d7"
116
116
  }
@@ -1,5 +1,5 @@
1
1
  import _ from "lodash/fp";
2
- import React from "react";
2
+ import React, { useState } from "react";
3
3
  import PropTypes from "prop-types";
4
4
  import {
5
5
  Button,
@@ -12,247 +12,191 @@ import {
12
12
  } from "semantic-ui-react";
13
13
  import { connect } from "react-redux";
14
14
  import { FormattedMessage } from "react-intl";
15
- import { ConfirmModal, HistoryBackButton } from "@truedat/core/components";
16
- import { selectTemplate } from "@truedat/df/routines";
15
+ import {
16
+ ConfirmModal,
17
+ HistoryBackButton,
18
+ Loading,
19
+ } from "@truedat/core/components";
20
+ import { useTemplate } from "@truedat/core/hooks";
17
21
  import { applyTemplateWithoutDefaults } from "@truedat/df/utils";
18
- import { compose } from "redux";
19
- import { withRouter } from "react-router-dom";
20
22
  import { bulkUpdateStructures } from "../routines";
21
23
 
22
24
  const DynamicForm = React.lazy(() =>
23
25
  import("@truedat/df/components/DynamicForm")
24
26
  );
25
27
 
26
- const TemplateLoader = React.lazy(() =>
27
- import("@truedat/df/templates/components/TemplateLoader")
28
- );
29
-
30
- const initialState = {
31
- content: {},
32
- };
33
-
34
- const isValid = _.conforms({
35
- domain_id: _.isFinite,
36
- });
37
-
38
- const actions = (handleSubmit, autoPublish) => {
39
- const standardActions = [
40
- {
41
- key: "no",
42
- secondary: true,
43
- content: <FormattedMessage id="confirmation.no" />,
44
- },
45
- {
46
- key: "yes",
47
- primary: true,
48
- content: (
49
- <FormattedMessage id="structures.edit.bulk.confirmation.update" />
50
- ),
51
- onClick: handleSubmit(false),
52
- },
53
- ];
54
-
55
- return autoPublish
56
- ? [
57
- ...standardActions,
58
- {
59
- key: "yesWithAutoPublish",
60
- primary: true,
61
- content: (
62
- <FormattedMessage id="structures.edit.bulk.confirmation.update.publish" />
63
- ),
64
- onClick: handleSubmit(true),
65
- },
66
- ]
67
- : standardActions;
68
- };
69
-
70
- const isEmptyNumberOrObject = (value) =>
71
- (_.isNumber(value) && _.isNil(value)) ||
72
- (!_.isNumber(value) && _.isEmpty(value));
28
+ const isEmptyValue = (value) => !_.isNumber(value) && _.isEmpty(value);
73
29
 
74
- export class StructuresBulkUpdate extends React.Component {
75
- static propTypes = {
76
- applyTemplate: PropTypes.func,
77
- autoPublish: PropTypes.object,
78
- bulkUpdateStructures: PropTypes.func,
79
- loading: PropTypes.bool,
80
- selectTemplate: PropTypes.func,
81
- structureCount: PropTypes.number,
82
- template: PropTypes.object,
83
- templateId: PropTypes.number,
84
- templatesLoaded: PropTypes.bool,
85
- enabled: PropTypes.bool,
86
- };
87
-
88
- state = initialState;
89
-
90
- componentDidMount() {
91
- const { templateId, selectTemplate } = this.props;
92
- if (templateId) {
93
- selectTemplate({ id: templateId });
94
- }
95
- }
96
-
97
- componentDidUpdate(prevProps) {
98
- const { templateId, selectTemplate } = this.props;
99
- if (prevProps.templateId != templateId) {
100
- selectTemplate({ id: templateId });
101
- }
102
- }
103
-
104
- handleContentChange = (content) => this.setState({ content });
105
-
106
- isInvalid = () => _.negate(isValid)(this.state);
30
+ export const StructuresBulkUpdate = ({
31
+ structureFilters,
32
+ structureTypes,
33
+ structureCount,
34
+ bulkUpdateStructures,
35
+ bulkUpdateStructuresLoading,
36
+ publishAllowed,
37
+ }) => {
38
+ const [content, setContent] = useState({});
39
+
40
+ const findTemplateName = (name) =>
41
+ _.flow(_.find({ name }), _.prop("template.name"))(structureTypes);
42
+
43
+ const templateName = _.flow(
44
+ _.getOr([], "type.raw"),
45
+ _.cond([
46
+ [(types) => _.size(types) == 1, _.flow(_.head, findTemplateName)],
47
+ [_.stubTrue, _.constant("")],
48
+ ])
49
+ )(structureFilters);
50
+
51
+ const domainIds = _.flow(
52
+ _.path("taxonomy"),
53
+ _.map("id"),
54
+ _.cond([
55
+ [(domains) => _.size(domains) == 1, _.identity],
56
+ [_.stubTrue, _.constant(null)],
57
+ ])
58
+ )(structureFilters);
59
+
60
+ const { data, loading } = useTemplate({ name: templateName, domainIds });
61
+ const template = _.prop("template")(data);
62
+
63
+ if (!template)
64
+ return (
65
+ <Message>
66
+ <Message.Header>
67
+ <FormattedMessage id="structures.bulkUpdateStructures.no.structures.header" />
68
+ </Message.Header>
69
+ <p>
70
+ <FormattedMessage id="structures.bulkUpdateStructures.no.structures.body" />
71
+ </p>
72
+ </Message>
73
+ );
107
74
 
108
- handleSubmit = (autoPublish) => (e) => {
75
+ const handleSubmit = (autoPublish) => (e) => {
109
76
  e.preventDefault();
110
- const { applyTemplate, bulkUpdateStructures, structureCount } = this.props;
111
77
 
112
- const content = _.flow(
113
- _.prop("content"),
114
- applyTemplate,
115
- _.omitBy(isEmptyNumberOrObject)
116
- )(this.state);
78
+ const parsedContent = _.flow(
79
+ applyTemplateWithoutDefaults(template),
80
+ _.omitBy(isEmptyValue)
81
+ )(content);
117
82
 
118
83
  bulkUpdateStructures({
119
- update_attributes: { df_content: content },
84
+ update_attributes: { df_content: parsedContent },
120
85
  structureCount,
121
86
  autoPublish,
122
87
  });
123
88
  };
124
89
 
125
- render() {
126
- const {
127
- autoPublish,
128
- enabled,
129
- loading,
130
- structureCount,
131
- template,
132
- templateId,
133
- templatesLoaded,
134
- } = this.props;
135
- const { content } = this.state;
136
- const disableAction = !template || _.isEmpty(template);
137
-
138
- return templatesLoaded ? (
139
- <Container as={Segment} text>
140
- <TemplateLoader />
141
- {enabled ? (
142
- <>
143
- <Header as="h2">
144
- <Icon name="book" />
145
- <Header.Content>
146
- <FormattedMessage id="structures.header.edit.bulk" />
147
- </Header.Content>
148
- </Header>
149
- <Header as="h3">
150
- <Header.Content>
151
- <FormattedMessage
152
- id="structures.header.edit.bulk.structures_count"
153
- values={{ structures_count: structureCount }}
154
- />
155
- </Header.Content>
156
- </Header>
157
- <Header as="h4">
158
- <Header.Content>
159
- <FormattedMessage id="structures.header.edit.bulk.info_message" />
160
- </Header.Content>
161
- </Header>
162
- <Form loading={loading}>
163
- {template && templateId && (
164
- <DynamicForm
165
- onChange={this.handleContentChange}
166
- applyTemplate={applyTemplateWithoutDefaults}
167
- content={content}
168
- />
169
- )}
170
- <ConfirmModal
171
- actions={actions(this.handleSubmit, autoPublish)}
172
- trigger={
173
- <Button
174
- primary
175
- disabled={disableAction}
176
- content={<FormattedMessage id="actions.save" />}
177
- />
178
- }
179
- header={
180
- <FormattedMessage id="structures.edit.bulk.confirmation.header" />
181
- }
182
- content={
183
- <FormattedMessage
184
- id="structures.edit.bulk.confirmation.content"
185
- values={{ structures_count: structureCount }}
186
- />
187
- }
188
- onConfirm={this.handleSubmit}
90
+ return loading || !template ? (
91
+ <Loading />
92
+ ) : (
93
+ <Container as={Segment} text>
94
+ <>
95
+ <Header as="h2">
96
+ <Icon name="book" />
97
+ <Header.Content>
98
+ <FormattedMessage id="structures.header.edit.bulk" />
99
+ </Header.Content>
100
+ </Header>
101
+ <Header as="h3">
102
+ <Header.Content>
103
+ <FormattedMessage
104
+ id="structures.header.edit.bulk.structures_count"
105
+ values={{ structureCount }}
106
+ />
107
+ </Header.Content>
108
+ </Header>
109
+ <Header as="h4">
110
+ <Header.Content>
111
+ <FormattedMessage id="structures.header.edit.bulk.info_message" />
112
+ </Header.Content>
113
+ </Header>
114
+ <Form loading={bulkUpdateStructuresLoading}>
115
+ {template && (
116
+ <DynamicForm
117
+ onChange={setContent}
118
+ template={template}
119
+ applyTemplate={applyTemplateWithoutDefaults}
120
+ content={content}
121
+ />
122
+ )}
123
+ <ConfirmModal
124
+ actions={[
125
+ {
126
+ key: "no",
127
+ secondary: true,
128
+ content: <FormattedMessage id="confirmation.no" />,
129
+ },
130
+ {
131
+ key: "yes",
132
+ primary: true,
133
+ content: (
134
+ <FormattedMessage id="structures.edit.bulk.confirmation.update" />
135
+ ),
136
+ onClick: handleSubmit(false),
137
+ },
138
+ ...(publishAllowed
139
+ ? [
140
+ {
141
+ key: "yesWithAutoPublish",
142
+ primary: true,
143
+ content: (
144
+ <FormattedMessage id="structures.edit.bulk.confirmation.update.publish" />
145
+ ),
146
+ onClick: handleSubmit(true),
147
+ },
148
+ ]
149
+ : []),
150
+ ]}
151
+ trigger={
152
+ <Button
153
+ primary
154
+ content={<FormattedMessage id="actions.save" />}
189
155
  />
190
- <HistoryBackButton
191
- content={<FormattedMessage id="actions.cancel" />}
156
+ }
157
+ header={
158
+ <FormattedMessage id="structures.edit.bulk.confirmation.header" />
159
+ }
160
+ content={
161
+ <FormattedMessage
162
+ id="structures.edit.bulk.confirmation.content"
163
+ values={{ structureCount }}
192
164
  />
193
- </Form>
194
- </>
195
- ) : (
196
- <Message>
197
- <Message.Header>
198
- <FormattedMessage id="structures.bulkUpdateStructures.no.structures.header" />
199
- </Message.Header>
200
- <p>
201
- <FormattedMessage id="structures.bulkUpdateStructures.no.structures.body" />
202
- </p>
203
- </Message>
204
- )}
205
- </Container>
206
- ) : null;
207
- }
208
- }
165
+ }
166
+ onConfirm={handleSubmit}
167
+ />
168
+ <HistoryBackButton
169
+ content={<FormattedMessage id="actions.cancel" />}
170
+ />
171
+ </Form>
172
+ </>
173
+ </Container>
174
+ );
175
+ };
209
176
 
210
- const findTemplate = (structureTypes, templates, structure) => {
211
- if (
212
- !_.isEmpty(structureTypes) &&
213
- !_.isEmpty(templates) &&
214
- _.prop("type")(structure)
215
- ) {
216
- const structureType = _.find(_.propEq("name", structure.type))(
217
- structureTypes
218
- );
219
- const template = _.find(
220
- _.propEq("id", _.path("template.id")(structureType))
221
- )(templates);
222
- return _.prop("id")(template);
223
- } else {
224
- return null;
225
- }
177
+ StructuresBulkUpdate.propTypes = {
178
+ structureFilters: PropTypes.object,
179
+ structureTypes: PropTypes.array,
180
+ structureCount: PropTypes.number,
181
+ bulkUpdateStructures: PropTypes.func,
182
+ bulkUpdateStructuresLoading: PropTypes.bool,
183
+ publishAllowed: PropTypes.bool,
226
184
  };
227
185
 
228
186
  const mapStateToProps = ({
229
- bulkUpdateStructuresLoading,
230
- templateLoading,
231
- templatesLoading,
232
- structureCount,
233
- templates,
234
- template,
235
- structures,
187
+ structureFilters,
236
188
  structureTypes,
237
- structureTypesLoading,
189
+ structureCount,
190
+ bulkUpdateStructuresLoading,
238
191
  structuresActions,
239
- }) => {
240
- const structure = _.head(structures);
241
- const templateId = findTemplate(structureTypes, templates, structure);
242
- return {
243
- loading: templateLoading || bulkUpdateStructuresLoading,
244
- template,
245
- templateId,
246
- applyTemplate: applyTemplateWithoutDefaults(template),
247
- structureCount,
248
- structureTypesLoaded: !structureTypesLoading,
249
- templatesLoaded: !templatesLoading && !_.isEmpty(templates),
250
- autoPublish: structuresActions?.autoPublish,
251
- enabled: !!templateId && !!structuresActions?.bulkUpdate,
252
- };
253
- };
192
+ }) => ({
193
+ structureFilters,
194
+ structureTypes,
195
+ structureCount,
196
+ bulkUpdateStructuresLoading,
197
+ publishAllowed: !!structuresActions?.autoPublish,
198
+ });
254
199
 
255
- export default compose(
256
- withRouter,
257
- connect(mapStateToProps, { bulkUpdateStructures, selectTemplate })
258
- )(StructuresBulkUpdate);
200
+ export default connect(mapStateToProps, { bulkUpdateStructures })(
201
+ StructuresBulkUpdate
202
+ );
@@ -1,172 +1,123 @@
1
1
  import _ from "lodash/fp";
2
2
  import React from "react";
3
- import { shallow } from "enzyme";
4
- import { applyTemplateWithoutDefaults } from "@truedat/df/utils";
5
- import { StructuresBulkUpdate } from "../StructuresBulkUpdate";
3
+ import { waitFor } from "@testing-library/react";
4
+ import userEvent from "@testing-library/user-event";
5
+ import { templateByNameMock } from "@truedat/test/mocks";
6
+ import { render } from "@truedat/test/render";
7
+ import StructuresBulkUpdate from "../StructuresBulkUpdate";
8
+ import { bulkUpdateStructures } from "../../routines";
6
9
 
7
10
  describe("<StructuresBulkUpdate />", () => {
8
- const selectTemplate = jest.fn();
9
- const applyTemplate = jest.fn();
10
- const props = {
11
- loading: false,
12
- template: { id: 1, template: "template1" },
13
- templateId: 1,
14
- selectTemplate,
15
- structureCount: 10,
16
- applyTemplate,
17
- templatesLoaded: true,
18
- structureTypes: [{ name: "doc", template_id: 1 }],
19
- structureTypesLoaded: true,
20
- enabled: true,
11
+ const renderOpts = {
12
+ mocks: [templateByNameMock({ name: "template1", domainIds: [1] })],
13
+ state: {
14
+ structureCount: 10,
15
+ structureTypes: [{ name: "structType", template: { name: "template1" } }],
16
+ structureFilters: {
17
+ "type.raw": ["structType"],
18
+ taxonomy: [{ id: 1 }],
19
+ },
20
+ },
21
+ fallback: "lazy",
21
22
  };
22
23
 
23
- it("matches the latest snapshot", () => {
24
- const wrapper = shallow(<StructuresBulkUpdate {...props} />);
25
- expect(wrapper).toMatchSnapshot();
26
- });
24
+ it("matches the latest snapshot", async () => {
25
+ const { container, queryByText } = render(
26
+ <StructuresBulkUpdate />,
27
+ renderOpts
28
+ );
27
29
 
28
- it("calls selectTemplate when component mounts", () => {
29
- jest.spyOn(StructuresBulkUpdate.prototype, "componentDidMount");
30
- shallow(<StructuresBulkUpdate {...props} />);
31
- expect(
32
- StructuresBulkUpdate.prototype.componentDidMount.mock.calls.length
33
- ).toBe(1);
34
- expect(props.selectTemplate).toHaveBeenCalledTimes(2);
35
- });
30
+ await waitFor(() => expect(queryByText(/lazy/i)).not.toBeInTheDocument());
31
+ await waitFor(() =>
32
+ expect(queryByText(/loading/i)).not.toBeInTheDocument()
33
+ );
36
34
 
37
- it("calls selectTemplate when component updates", () => {
38
- jest.spyOn(StructuresBulkUpdate.prototype, "componentDidUpdate");
39
- const calls = props.selectTemplate.mock.calls.length;
40
- const wrapper = shallow(<StructuresBulkUpdate {...props} />);
41
- wrapper.setProps({ templateId: 1 });
42
- expect(
43
- StructuresBulkUpdate.prototype.componentDidUpdate.mock.calls.length
44
- ).toBe(1);
45
- expect(props.selectTemplate).toHaveBeenCalledTimes(calls + 1);
35
+ expect(container).toMatchSnapshot();
46
36
  });
47
37
 
48
- it("DynamicForm rendered if template and template_id informed", () => {
49
- const wrapper = shallow(<StructuresBulkUpdate {...props} />);
50
- expect(
51
- wrapper
52
- .find("Form")
53
- .dive()
54
- .findWhere((n) => n.prop("onChange"))
55
- ).toHaveLength(1);
38
+ it("renders empty when no filters are selected", async () => {
39
+ const thisRenderOpts = _.update("state.structureFilters", () => ({}))(
40
+ renderOpts
41
+ );
42
+
43
+ const { container } = render(<StructuresBulkUpdate />, thisRenderOpts);
44
+
45
+ expect(container).toMatchSnapshot();
56
46
  });
57
47
 
58
- it("dispatches bulkUpdateStructures on modal confirmation", () => {
59
- const e = { preventDefault: jest.fn() };
60
- const bulkUpdateStructures = jest.fn();
61
- const wrapper = shallow(
62
- <StructuresBulkUpdate
63
- bulkUpdateStructures={bulkUpdateStructures}
64
- {...props}
65
- />
48
+ it("Publish button is available with autoPublish action", async () => {
49
+ const dispatch = jest.fn();
50
+ const thisRenderOpts = _.update("state.structuresActions", () => ({
51
+ autoPublish: { method: "POST" },
52
+ }))(renderOpts);
53
+
54
+ const { container, findByText, queryByText, findByRole } = render(
55
+ <StructuresBulkUpdate />,
56
+ { ...thisRenderOpts, dispatch }
57
+ );
58
+
59
+ await waitFor(() => expect(queryByText(/lazy/i)).not.toBeInTheDocument());
60
+ await waitFor(() =>
61
+ expect(queryByText(/loading/i)).not.toBeInTheDocument()
66
62
  );
67
63
 
68
- wrapper
69
- .find("Form")
70
- .dive()
71
- .findWhere((n) => n.prop("actions"))
72
- .prop("actions")[1]
73
- .onClick(e);
64
+ userEvent.type(await findByRole("textbox"), "bar");
74
65
 
75
- expect(bulkUpdateStructures.mock.calls.length).toBe(1);
76
- });
66
+ userEvent.click(await findByText("Save"));
67
+
68
+ expect(container).toMatchSnapshot();
77
69
 
78
- it("calls bulkUpdateStructures excluding empty content on onClick", () => {
79
- const template = {
80
- content: [
81
- {
82
- fields: [
83
- {
84
- cardinality: "1",
85
- default: 3,
86
- label: "description",
87
- name: "description",
88
- type: "string",
89
- values: null,
90
- widget: "string",
91
- },
92
- {
93
- cardinality: "1",
94
- default: 3,
95
- label: "number",
96
- name: "number",
97
- type: "integer",
98
- values: null,
99
- widget: "number",
100
- },
101
- {
102
- cardinality: "1",
103
- default: "22-03-2020",
104
- label: "date",
105
- name: "date",
106
- type: "date",
107
- values: null,
108
- widget: "date",
109
- },
110
- {
111
- cardinality: "?",
112
- default: "19-05-2020 18:10:00",
113
- label: "datetime",
114
- name: "datetime",
115
- type: "datetime",
116
- values: null,
117
- widget: "datetime",
118
- },
119
- ],
120
- is_secret: false,
121
- name: "",
70
+ expect(queryByText(/Update and publish/i)).toBeInTheDocument();
71
+
72
+ userEvent.click(await findByText(/Update and publish/i));
73
+
74
+ expect(dispatch).toHaveBeenLastCalledWith({
75
+ ...bulkUpdateStructures(),
76
+ payload: {
77
+ autoPublish: true,
78
+ structureCount: 10,
79
+ update_attributes: {
80
+ df_content: {
81
+ field1: "bar",
82
+ },
122
83
  },
123
- ],
124
- id: 10,
125
- label: "foo",
126
- name: "foo",
127
- scope: "dd",
128
- };
129
-
130
- const props = {
131
- loading: false,
132
- template,
133
- selectTemplate,
134
- templateId: 10,
135
- applyTemplate: applyTemplateWithoutDefaults(template),
136
- structureCount: 3,
137
- selectedDomain: { id: 1 },
138
- templatesLoaded: true,
139
- bulkUpdateStructures: jest.fn(),
140
- enabled: true,
141
- };
142
- const wrapper = shallow(<StructuresBulkUpdate {...props} />);
143
- wrapper.setState({
144
- content: {
145
- number: 0,
146
- date: "",
147
- datetime: "",
148
- description: "",
149
84
  },
150
85
  });
151
- _.find({ key: "yes" })(
152
- wrapper
153
- .find("ConfirmModal")
154
- .dive()
155
- .find("Modal")
156
- .dive()
157
- .find("ModalActions")
158
- .props().actions
159
- ).onClick({ preventDefault() {} });
160
-
161
- expect(props.bulkUpdateStructures.mock.calls.length).toBe(1);
162
- expect(props.bulkUpdateStructures).toHaveBeenCalledWith({
163
- autoPublish: false,
164
- update_attributes: {
165
- df_content: {
166
- number: 0,
86
+ });
87
+
88
+ it("Publish button is not available without autoPublish action", async () => {
89
+ const dispatch = jest.fn();
90
+ const { container, findByText, queryByText, findByRole } = render(
91
+ <StructuresBulkUpdate />,
92
+ { ...renderOpts, dispatch }
93
+ );
94
+
95
+ await waitFor(() => expect(queryByText(/lazy/i)).not.toBeInTheDocument());
96
+ await waitFor(() =>
97
+ expect(queryByText(/loading/i)).not.toBeInTheDocument()
98
+ );
99
+
100
+ userEvent.type(await findByRole("textbox"), "bar");
101
+
102
+ userEvent.click(await findByText("Save"));
103
+
104
+ expect(container).toMatchSnapshot();
105
+
106
+ expect(queryByText(/Update and publish/i)).not.toBeInTheDocument();
107
+
108
+ userEvent.click(await findByText("Update"));
109
+
110
+ expect(dispatch).toHaveBeenLastCalledWith({
111
+ ...bulkUpdateStructures(),
112
+ payload: {
113
+ autoPublish: false,
114
+ structureCount: 10,
115
+ update_attributes: {
116
+ df_content: {
117
+ field1: "bar",
118
+ },
167
119
  },
168
120
  },
169
- structureCount: 3,
170
121
  });
171
122
  });
172
123
  });
@@ -1,112 +1,277 @@
1
1
  // Jest Snapshot v1, https://goo.gl/fbAQLP
2
2
 
3
- exports[`<StructuresBulkUpdate /> matches the latest snapshot 1`] = `
4
- <Container
5
- as={[Function]}
6
- text={true}
7
- >
8
- <lazy />
9
- <Header
10
- as="h2"
3
+ exports[`<StructuresBulkUpdate /> Publish button is available with autoPublish action 1`] = `
4
+ <div>
5
+ <div
6
+ class="ui segment ui text container"
11
7
  >
12
- <Icon
13
- as="i"
14
- name="book"
15
- />
16
- <HeaderContent>
17
- <MemoizedFormattedMessage
18
- id="structures.header.edit.bulk"
8
+ <h2
9
+ class="ui header"
10
+ >
11
+ <i
12
+ aria-hidden="true"
13
+ class="book icon"
19
14
  />
20
- </HeaderContent>
21
- </Header>
22
- <Header
23
- as="h3"
15
+ <div
16
+ class="content"
17
+ >
18
+ Edit Structures
19
+ </div>
20
+ </h2>
21
+ <h3
22
+ class="ui header"
23
+ >
24
+ <div
25
+ class="content"
26
+ >
27
+ Selected structures: "10"
28
+ </div>
29
+ </h3>
30
+ <h4
31
+ class="ui header"
32
+ >
33
+ <div
34
+ class="content"
35
+ >
36
+ Only modify fields to be updated
37
+ </div>
38
+ </h4>
39
+ <form
40
+ class="ui form"
41
+ >
42
+ <div
43
+ class="ui segment"
44
+ >
45
+ <h4
46
+ class="ui header"
47
+ >
48
+ g1
49
+ </h4>
50
+ <div
51
+ class="field"
52
+ >
53
+ <label>
54
+ field1
55
+ </label>
56
+ <div
57
+ class="field"
58
+ >
59
+ <div
60
+ class="ui input"
61
+ >
62
+ <input
63
+ name="field1"
64
+ placeholder="field1"
65
+ type="text"
66
+ value="bar"
67
+ />
68
+ </div>
69
+ </div>
70
+ </div>
71
+ </div>
72
+ <button
73
+ class="ui primary button"
74
+ >
75
+ Save
76
+ </button>
77
+ <a
78
+ class="ui secondary button"
79
+ href="/"
80
+ role="button"
81
+ >
82
+ Cancel
83
+ </a>
84
+ </form>
85
+ </div>
86
+ </div>
87
+ `;
88
+
89
+ exports[`<StructuresBulkUpdate /> Publish button is not available without autoPublish action 1`] = `
90
+ <div>
91
+ <div
92
+ class="ui segment ui text container"
24
93
  >
25
- <HeaderContent>
26
- <MemoizedFormattedMessage
27
- id="structures.header.edit.bulk.structures_count"
28
- values={
29
- Object {
30
- "structures_count": 10,
31
- }
32
- }
94
+ <h2
95
+ class="ui header"
96
+ >
97
+ <i
98
+ aria-hidden="true"
99
+ class="book icon"
33
100
  />
34
- </HeaderContent>
35
- </Header>
36
- <Header
37
- as="h4"
101
+ <div
102
+ class="content"
103
+ >
104
+ Edit Structures
105
+ </div>
106
+ </h2>
107
+ <h3
108
+ class="ui header"
109
+ >
110
+ <div
111
+ class="content"
112
+ >
113
+ Selected structures: "10"
114
+ </div>
115
+ </h3>
116
+ <h4
117
+ class="ui header"
118
+ >
119
+ <div
120
+ class="content"
121
+ >
122
+ Only modify fields to be updated
123
+ </div>
124
+ </h4>
125
+ <form
126
+ class="ui form"
127
+ >
128
+ <div
129
+ class="ui segment"
130
+ >
131
+ <h4
132
+ class="ui header"
133
+ >
134
+ g1
135
+ </h4>
136
+ <div
137
+ class="field"
138
+ >
139
+ <label>
140
+ field1
141
+ </label>
142
+ <div
143
+ class="field"
144
+ >
145
+ <div
146
+ class="ui input"
147
+ >
148
+ <input
149
+ name="field1"
150
+ placeholder="field1"
151
+ type="text"
152
+ value="bar"
153
+ />
154
+ </div>
155
+ </div>
156
+ </div>
157
+ </div>
158
+ <button
159
+ class="ui primary button"
160
+ >
161
+ Save
162
+ </button>
163
+ <a
164
+ class="ui secondary button"
165
+ href="/"
166
+ role="button"
167
+ >
168
+ Cancel
169
+ </a>
170
+ </form>
171
+ </div>
172
+ </div>
173
+ `;
174
+
175
+ exports[`<StructuresBulkUpdate /> matches the latest snapshot 1`] = `
176
+ <div>
177
+ <div
178
+ class="ui segment ui text container"
179
+ style=""
38
180
  >
39
- <HeaderContent>
40
- <MemoizedFormattedMessage
41
- id="structures.header.edit.bulk.info_message"
181
+ <h2
182
+ class="ui header"
183
+ >
184
+ <i
185
+ aria-hidden="true"
186
+ class="book icon"
42
187
  />
43
- </HeaderContent>
44
- </Header>
45
- <Form
46
- as="form"
47
- loading={false}
188
+ <div
189
+ class="content"
190
+ >
191
+ Edit Structures
192
+ </div>
193
+ </h2>
194
+ <h3
195
+ class="ui header"
196
+ >
197
+ <div
198
+ class="content"
199
+ >
200
+ Selected structures: "10"
201
+ </div>
202
+ </h3>
203
+ <h4
204
+ class="ui header"
205
+ >
206
+ <div
207
+ class="content"
208
+ >
209
+ Only modify fields to be updated
210
+ </div>
211
+ </h4>
212
+ <form
213
+ class="ui form"
214
+ >
215
+ <div
216
+ class="ui segment"
217
+ >
218
+ <h4
219
+ class="ui header"
220
+ >
221
+ g1
222
+ </h4>
223
+ <div
224
+ class="field"
225
+ >
226
+ <label>
227
+ field1
228
+ </label>
229
+ <div
230
+ class="field"
231
+ >
232
+ <div
233
+ class="ui input"
234
+ >
235
+ <input
236
+ name="field1"
237
+ placeholder="field1"
238
+ type="text"
239
+ value=""
240
+ />
241
+ </div>
242
+ </div>
243
+ </div>
244
+ </div>
245
+ <button
246
+ class="ui primary button"
247
+ >
248
+ Save
249
+ </button>
250
+ <a
251
+ class="ui secondary button"
252
+ href="/"
253
+ role="button"
254
+ >
255
+ Cancel
256
+ </a>
257
+ </form>
258
+ </div>
259
+ </div>
260
+ `;
261
+
262
+ exports[`<StructuresBulkUpdate /> renders empty when no filters are selected 1`] = `
263
+ <div>
264
+ <div
265
+ class="ui message"
48
266
  >
49
- <lazy
50
- applyTemplate={[Function]}
51
- content={Object {}}
52
- onChange={[Function]}
53
- />
54
- <ConfirmModal
55
- actions={
56
- Array [
57
- Object {
58
- "content": <Memo(MemoizedFormattedMessage)
59
- id="confirmation.no"
60
- />,
61
- "key": "no",
62
- "secondary": true,
63
- },
64
- Object {
65
- "content": <Memo(MemoizedFormattedMessage)
66
- id="structures.edit.bulk.confirmation.update"
67
- />,
68
- "key": "yes",
69
- "onClick": [Function],
70
- "primary": true,
71
- },
72
- ]
73
- }
74
- content={
75
- <Memo(MemoizedFormattedMessage)
76
- id="structures.edit.bulk.confirmation.content"
77
- values={
78
- Object {
79
- "structures_count": 10,
80
- }
81
- }
82
- />
83
- }
84
- header={
85
- <Memo(MemoizedFormattedMessage)
86
- id="structures.edit.bulk.confirmation.header"
87
- />
88
- }
89
- onConfirm={[Function]}
90
- trigger={
91
- <Button
92
- as="button"
93
- content={
94
- <Memo(MemoizedFormattedMessage)
95
- id="actions.save"
96
- />
97
- }
98
- disabled={false}
99
- primary={true}
100
- />
101
- }
102
- />
103
- <HistoryBackButton
104
- content={
105
- <Memo(MemoizedFormattedMessage)
106
- id="actions.cancel"
107
- />
108
- }
109
- />
110
- </Form>
111
- </Container>
267
+ <div
268
+ class="header"
269
+ >
270
+ Empty Search
271
+ </div>
272
+ <p>
273
+ No structures selected
274
+ </p>
275
+ </div>
276
+ </div>
112
277
  `;
@@ -474,7 +474,7 @@ export default {
474
474
 
475
475
  "structures.crumbs.top": "Structures",
476
476
  "structures.edit.bulk.confirmation.content":
477
- "{structures_count} structures will be updated. Are you sure?",
477
+ "{structureCount} structures will be updated. Are you sure?",
478
478
  "structures.edit.bulk.confirmation.header": "Bulk update",
479
479
  "structures.edit.bulk.confirmation.update": "Update",
480
480
  "structures.edit.bulk.confirmation.update.publish": "Update and publish",
@@ -495,7 +495,7 @@ export default {
495
495
  "structures.header.edit.bulk.info_message":
496
496
  "Only modify fields to be updated",
497
497
  "structures.header.edit.bulk.structures_count":
498
- 'Selected structures: "{structures_count}"',
498
+ 'Selected structures: "{structureCount}"',
499
499
  "structures.loading.header": "Loading structures...",
500
500
  "structures.not_found.body":
501
501
  "No structures have been found matching these filters.",
@@ -485,7 +485,7 @@ export default {
485
485
  "¡Actualización finalizada! subidos {count_ids} errores {count_errors}",
486
486
  "structures.crumbs.top": "Estructuras",
487
487
  "structures.edit.bulk.confirmation.content":
488
- "Se van a actualizar {structures_count} estructuras. ¿Estás seguro?",
488
+ "Se van a actualizar {structureCount} estructuras. ¿Estás seguro?",
489
489
  "structures.edit.bulk.confirmation.header": "Actualización masiva",
490
490
  "structures.edit.bulk.confirmation.update": "Actualizar",
491
491
  "structures.edit.bulk.confirmation.update.publish": "Actualizar y publicar",
@@ -508,7 +508,7 @@ export default {
508
508
  "structures.header.edit.bulk.info_message":
509
509
  "Rellenar únicamente los campos que se quieran actualizar",
510
510
  "structures.header.edit.bulk.structures_count":
511
- 'Estructuras seleccionadas: "{structures_count}"',
511
+ 'Estructuras seleccionadas: "{structureCount}"',
512
512
  "structures.loading.header": "Cargando estructuras...",
513
513
  "structures.not_found.body":
514
514
  "No existe ningún elemento para la búsqueda aplicada",
@@ -18,7 +18,7 @@ describe("selectors: selectedTypesSelector", () => {
18
18
 
19
19
  it("should return the values of the type.raw filter if present", () => {
20
20
  const values = ["foo", "bar"];
21
- const state = { structureActiveFilters: { "type.raw": values } };
21
+ const state = { structureFilters: { "type.raw": values } };
22
22
  expect(selectedTypesSelector(state)).toBe(values);
23
23
  });
24
24
  });
@@ -43,7 +43,7 @@ describe("selectors: bulkUpdateDisabledSelector", () => {
43
43
  structuresLoading: false,
44
44
  structures: [{ type: "foo" }],
45
45
  structureTypes: [{ name: "foo" }],
46
- structureActiveFilters: { "type.raw": values },
46
+ structureFilters: { "type.raw": values },
47
47
  };
48
48
 
49
49
  it("should return false if a single type is selected which has a template, etc.", () => {
@@ -2,7 +2,7 @@ import _ from "lodash/fp";
2
2
  import { createSelector } from "reselect";
3
3
 
4
4
  export const selectedTypesSelector = createSelector(
5
- _.prop("structureActiveFilters"),
5
+ _.prop("structureFilters"),
6
6
  _.prop("type.raw")
7
7
  );
8
8