@truedat/dd 4.48.12 → 4.49.1

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.
Files changed (89) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/package.json +5 -5
  3. package/src/api/fragments.js +2 -2
  4. package/src/api/mutations.js +33 -11
  5. package/src/api/queries.js +37 -10
  6. package/src/api.js +0 -4
  7. package/src/components/DictionaryRoutes.js +4 -4
  8. package/src/components/StructureSummary.js +12 -22
  9. package/src/components/StructureTag.js +83 -54
  10. package/src/components/StructureTagForm.js +149 -89
  11. package/src/components/StructureTags.js +57 -27
  12. package/src/components/Tag.js +62 -0
  13. package/src/components/TagCards.js +85 -0
  14. package/src/components/TagCrumbs.js +25 -0
  15. package/src/components/TagForm.js +102 -0
  16. package/src/components/TagStructureButton.js +58 -0
  17. package/src/components/Tags.js +33 -0
  18. package/src/components/TagsRoutes.js +39 -0
  19. package/src/components/__tests__/StructureSummary.spec.js +0 -7
  20. package/src/components/__tests__/StructureTag.spec.js +79 -5
  21. package/src/components/__tests__/StructureTagForm.spec.js +99 -50
  22. package/src/components/__tests__/Tag.spec.js +11 -0
  23. package/src/components/__tests__/{StructureTagsCards.spec.js → TagCards.spec.js} +10 -10
  24. package/src/components/__tests__/TagCrumbs.spec.js +10 -0
  25. package/src/components/__tests__/TagForm.spec.js +72 -0
  26. package/src/components/__tests__/Tags.spec.js +10 -0
  27. package/src/components/__tests__/__snapshots__/StructureSummary.spec.js.snap +18 -42
  28. package/src/components/__tests__/__snapshots__/StructureTag.spec.js.snap +10 -30
  29. package/src/components/__tests__/__snapshots__/StructureTagForm.spec.js.snap +255 -51
  30. package/src/components/__tests__/__snapshots__/Tag.spec.js.snap +36 -0
  31. package/src/components/__tests__/__snapshots__/{StructureTagsCards.spec.js.snap → TagCards.spec.js.snap} +1 -1
  32. package/src/components/__tests__/__snapshots__/TagCrumbs.spec.js.snap +102 -0
  33. package/src/components/__tests__/__snapshots__/TagForm.spec.js.snap +70 -0
  34. package/src/components/__tests__/__snapshots__/{StructureTags.spec.js.snap → Tags.spec.js.snap} +1 -1
  35. package/src/messages/en.js +25 -30
  36. package/src/messages/es.js +25 -30
  37. package/src/reducers/__tests__/{editableStructureTags.spec.js → availableTags.spec.js} +7 -11
  38. package/src/reducers/__tests__/structureTagSaving.spec.js +36 -0
  39. package/src/reducers/__tests__/tagSaving.spec.js +32 -0
  40. package/src/reducers/{editableStructureTags.js → availableTags.js} +2 -2
  41. package/src/reducers/index.js +6 -12
  42. package/src/reducers/structureRedirect.js +7 -7
  43. package/src/reducers/structureTagSaving.js +12 -10
  44. package/src/reducers/tagSaving.js +18 -0
  45. package/src/routines.js +5 -6
  46. package/src/sagas/__tests__/createTag.spec.js +81 -0
  47. package/src/sagas/__tests__/deleteStructureTag.spec.js +11 -12
  48. package/src/sagas/__tests__/deleteTag.spec.js +76 -0
  49. package/src/sagas/__tests__/tagStructure.spec.js +86 -0
  50. package/src/sagas/__tests__/updateTag.spec.js +81 -0
  51. package/src/sagas/createTag.js +29 -0
  52. package/src/sagas/deleteStructureTag.js +12 -9
  53. package/src/sagas/deleteTag.js +34 -0
  54. package/src/sagas/index.js +15 -18
  55. package/src/sagas/tagStructure.js +37 -0
  56. package/src/sagas/updateTag.js +23 -0
  57. package/src/components/LinkStructureTagForm.js +0 -163
  58. package/src/components/LinkedStructureTag.js +0 -124
  59. package/src/components/StructureLinkTagButton.js +0 -47
  60. package/src/components/StructureTagsCards.js +0 -92
  61. package/src/components/StructureTagsCrumbs.js +0 -44
  62. package/src/components/StructureTagsRoutes.js +0 -45
  63. package/src/components/TagsHeader.js +0 -32
  64. package/src/components/__tests__/LinkStructureTagForm.spec.js +0 -184
  65. package/src/components/__tests__/LinkedStructureTag.spec.js +0 -133
  66. package/src/components/__tests__/StructureTags.spec.js +0 -14
  67. package/src/components/__tests__/StructureTagsCrumbs.spec.js +0 -13
  68. package/src/components/__tests__/__snapshots__/LinkStructureTagForm.spec.js.snap +0 -456
  69. package/src/components/__tests__/__snapshots__/LinkedStructureTag.spec.js.snap +0 -16
  70. package/src/components/__tests__/__snapshots__/StructureTagsCrumbs.spec.js.snap +0 -36
  71. package/src/reducers/__tests__/deletingStructureTags.spec.js +0 -30
  72. package/src/reducers/__tests__/linkedStructureTags.spec.js +0 -69
  73. package/src/reducers/__tests__/linkedStructureTagsLoading.spec.js +0 -32
  74. package/src/reducers/__tests__/linkingStructureTags.spec.js +0 -30
  75. package/src/reducers/__tests__/structureTagsSaving.spec.js +0 -40
  76. package/src/reducers/deletingStructureTags.js +0 -16
  77. package/src/reducers/linkedStructureTags.js +0 -28
  78. package/src/reducers/linkedStructureTagsLoading.js +0 -16
  79. package/src/reducers/linkingStructureTags.js +0 -16
  80. package/src/sagas/__tests__/createStructureTag.spec.js +0 -85
  81. package/src/sagas/__tests__/deleteLinkStructureTag.spec.js +0 -96
  82. package/src/sagas/__tests__/fetchLinksStructureTags.spec.js +0 -105
  83. package/src/sagas/__tests__/linkStructureTag.spec.js +0 -102
  84. package/src/sagas/__tests__/updateStructureTag.spec.js +0 -84
  85. package/src/sagas/createStructureTag.js +0 -29
  86. package/src/sagas/deleteLinkStructureTag.js +0 -29
  87. package/src/sagas/fetchLinksStructureTags.js +0 -31
  88. package/src/sagas/linkStructureTag.js +0 -30
  89. package/src/sagas/updateStructureTag.js +0 -23
@@ -1,163 +0,0 @@
1
- import _ from "lodash/fp";
2
- import React from "react";
3
- import { useForm, Controller } from "react-hook-form";
4
- import { Button, Container, Form } from "semantic-ui-react";
5
- import { connect } from "react-redux";
6
- import PropTypes from "prop-types";
7
- import { useIntl } from "react-intl";
8
- import { accentInsensitivePathOrder } from "@truedat/core/services/sort";
9
- import { deleteLinkStructureTag, linkStructureTag } from "../routines";
10
-
11
- export const LinkStructureTagForm = ({
12
- deleteLinkStructureTag,
13
- comment,
14
- linkedStructureTags,
15
- linkId,
16
- linkStructureTag,
17
- structureId,
18
- structureTags,
19
- tagId,
20
- }) => {
21
- const { formatMessage } = useIntl();
22
- const allTags = _.map("id")(structureTags);
23
- const availableTags = _.negate(_.isNil)(tagId)
24
- ? allTags
25
- : _.difference(
26
- allTags,
27
- _.map(_.path("_embedded.data_structure_tag.id"))(linkedStructureTags)
28
- );
29
- const options = _.flow(
30
- _.filter(({ id }) => _.includes(id)(availableTags)),
31
- _.sortBy(accentInsensitivePathOrder("name")),
32
- _.map(({ id, name, description }) => ({
33
- value: id,
34
- text: name,
35
- description: description,
36
- }))
37
- )(structureTags);
38
- const defaultTag = _.negate(_.isNil)(tagId)
39
- ? tagId
40
- : _.size(options) === 1
41
- ? _.head(options).value
42
- : null;
43
- const submitTitle = _.isNil(tagId)
44
- ? "structure.tag.add"
45
- : "structure.tag.edit";
46
- const onSubmit = (params) => {
47
- const payload = {
48
- structureId,
49
- tagId: params.tag,
50
- tag: { comment: params.comment },
51
- };
52
- linkStructureTag(payload);
53
- };
54
- const doDelete = () => deleteLinkStructureTag({ structureId, tagId });
55
- const { handleSubmit, control, formState } = useForm({
56
- mode: "all",
57
- defaultValues: {
58
- comment: comment || "",
59
- tag: defaultTag,
60
- },
61
- });
62
- const { isDirty, isValid } = formState;
63
- return (
64
- <Container className="link-structure-tag-form">
65
- <Form onSubmit={handleSubmit(onSubmit)}>
66
- <Controller
67
- control={control}
68
- name="tag"
69
- rules={{ required: true }}
70
- render={({
71
- field: { onBlur, onChange, value },
72
- fieldState: { error },
73
- }) => (
74
- <Form.Dropdown
75
- name="tag"
76
- disabled={_.negate(_.isNil)(tagId)}
77
- error={!!error}
78
- placeholder={formatMessage({
79
- id: "structure.tag.dropdown.placeholder",
80
- })}
81
- label={formatMessage({ id: "structure.tag.dropdown.label" })}
82
- onBlur={onBlur}
83
- onChange={(_e, { value }) => onChange(value)}
84
- clearable
85
- search
86
- selection
87
- options={options}
88
- value={value}
89
- />
90
- )}
91
- />
92
- <Controller
93
- control={control}
94
- name="comment"
95
- render={({
96
- field: { onBlur, onChange, value },
97
- fieldState: { error },
98
- }) => (
99
- <Form.TextArea
100
- data-testid="comment-id"
101
- error={!!error}
102
- name="comment"
103
- label={formatMessage({ id: "structure.tag.textArea.label" })}
104
- placeholder={formatMessage({
105
- id: "structure.tag.textArea.placeholder",
106
- })}
107
- onBlur={onBlur}
108
- onChange={(_e, { value }) => onChange(value)}
109
- value={value}
110
- />
111
- )}
112
- />
113
- <div className="actions">
114
- <Button
115
- type="submit"
116
- disabled={(!isDirty && options.length > 1) || !isValid}
117
- primary
118
- content={formatMessage({ id: submitTitle })}
119
- />
120
- {_.negate(_.isNil)(linkId) && (
121
- <Button
122
- type="button"
123
- onClick={doDelete}
124
- secondary
125
- content={formatMessage({ id: "structure.tag.delete" })}
126
- />
127
- )}
128
- </div>
129
- </Form>
130
- </Container>
131
- );
132
- };
133
-
134
- LinkStructureTagForm.propTypes = {
135
- deleteLinkStructureTag: PropTypes.func,
136
- comment: PropTypes.string,
137
- linkedStructureTags: PropTypes.array,
138
- linkId: PropTypes.number,
139
- linkStructureTag: PropTypes.func,
140
- structureId: PropTypes.number,
141
- structureTags: PropTypes.array,
142
- tagId: PropTypes.number,
143
- };
144
-
145
- const mapStateToProps = ({
146
- linkedStructureTags,
147
- structure,
148
- editableStructureTags,
149
- }) => ({
150
- linkedStructureTags,
151
- structureId: _.prop("id")(structure),
152
- structureTags: editableStructureTags,
153
- });
154
-
155
- const mapDispatchToProps = {
156
- deleteLinkStructureTag,
157
- linkStructureTag,
158
- };
159
-
160
- export default connect(
161
- mapStateToProps,
162
- mapDispatchToProps
163
- )(LinkStructureTagForm);
@@ -1,124 +0,0 @@
1
- import _ from "lodash/fp";
2
- import React, { useEffect, useState } from "react";
3
- import PropTypes from "prop-types";
4
- import { useIntl } from "react-intl";
5
- import { Icon, Label, Popup, Header } from "semantic-ui-react";
6
- import { connect } from "react-redux";
7
- import LinkStructureTagForm from "./LinkStructureTagForm";
8
-
9
- export const LinkedStructureTag = ({
10
- id,
11
- _embedded,
12
- editable,
13
- comment,
14
- loading,
15
- structureTags,
16
- }) => {
17
- const { formatMessage } = useIntl();
18
- const name = _embedded.data_structure_tag.name;
19
- const description = _embedded.data_structure_tag.description;
20
- const tagId = _embedded.data_structure_tag.id;
21
- const [openDescription, setOpenDescription] = useState(false);
22
- const [openForm, setOpenForm] = useState(false);
23
-
24
- useEffect(() => {
25
- if (loading) setOpenForm(false);
26
- }, [loading, setOpenForm]);
27
-
28
- const trigger = editable ? <Icon link name="edit" /> : null;
29
-
30
- const renderTooltip = () => {
31
- const descriptionTooltip = _.isEmpty(description) ? null : (
32
- <Header as="h2" subheader={description} />
33
- );
34
-
35
- const commentTooltip = _.isEmpty(comment) ? null : (
36
- <>
37
- <Header
38
- as="h5"
39
- content={formatMessage({ id: "structure.tag.tooltip.commentTitle" })}
40
- />
41
- <p>{comment}</p>
42
- </>
43
- );
44
-
45
- return (
46
- <>
47
- {descriptionTooltip}
48
- {commentTooltip}
49
- </>
50
- );
51
- };
52
-
53
- return (
54
- <Popup
55
- basic
56
- open={openDescription}
57
- onOpen={() => {
58
- const commentCondition = !_.isEmpty(comment);
59
- const descriptionCondition = !_.isEmpty(description);
60
- const openFormCondition = !openForm;
61
-
62
- const openTooltipCondition =
63
- (commentCondition || descriptionCondition) && openFormCondition;
64
-
65
- if (openTooltipCondition) setOpenDescription(true);
66
- }}
67
- onClose={() => setOpenDescription(false)}
68
- positionFixed
69
- className="popup-tag"
70
- trigger={
71
- <Label tag style={{ marginLeft: "1.5em" }}>
72
- {_.isEmpty(structureTags) ? null : (
73
- <Popup
74
- on="click"
75
- basic
76
- onOpen={() => {
77
- setOpenForm(true);
78
- setOpenDescription(false);
79
- }}
80
- onClose={() => setOpenForm(false)}
81
- open={openForm}
82
- flowing
83
- content={
84
- <LinkStructureTagForm
85
- comment={comment}
86
- linkId={id}
87
- tagId={tagId}
88
- />
89
- }
90
- position="bottom center"
91
- size="large"
92
- positionFixed
93
- trigger={trigger}
94
- />
95
- )}
96
-
97
- {name}
98
- </Label>
99
- }
100
- >
101
- {renderTooltip()}
102
- </Popup>
103
- );
104
- };
105
-
106
- LinkedStructureTag.propTypes = {
107
- _embedded: PropTypes.object,
108
- comment: PropTypes.string,
109
- editable: PropTypes.bool,
110
- id: PropTypes.number,
111
- loading: PropTypes.bool,
112
- structureTags: PropTypes.array,
113
- };
114
-
115
- const mapStateToProps = ({
116
- editableStructureTags,
117
- linkingStructureTags,
118
- deletingStructureTags,
119
- }) => ({
120
- loading: linkingStructureTags || deletingStructureTags,
121
- structureTags: editableStructureTags,
122
- });
123
-
124
- export default connect(mapStateToProps)(LinkedStructureTag);
@@ -1,47 +0,0 @@
1
- import _ from "lodash/fp";
2
- import React, { useState } from "react";
3
- import { Button, Popup } from "semantic-ui-react";
4
- import { useIntl } from "react-intl";
5
- import { connect } from "react-redux";
6
- import PropTypes from "prop-types";
7
- import LinkStructureTagForm from "./LinkStructureTagForm";
8
-
9
- export const StructureLinkTagButton = ({ structureTags }) => {
10
- const { formatMessage } = useIntl();
11
- const [open, setOpen] = useState(false);
12
-
13
- return _.isEmpty(structureTags) ? null : (
14
- <Popup
15
- on="click"
16
- basic
17
- flowing
18
- onOpen={() => setOpen(true)}
19
- onClose={() => setOpen(false)}
20
- open={open}
21
- content={<LinkStructureTagForm structureTags={structureTags} />}
22
- position="bottom center"
23
- size="large"
24
- positionFixed
25
- trigger={
26
- <Button
27
- style={{ marginLeft: "0.5em" }}
28
- icon="plus"
29
- size="tiny"
30
- circular
31
- basic
32
- content={formatMessage({ id: "structure.add.tag" })}
33
- />
34
- }
35
- />
36
- );
37
- };
38
-
39
- StructureLinkTagButton.propTypes = {
40
- structureTags: PropTypes.array,
41
- };
42
-
43
- const mapStateToProps = ({ editableStructureTags }) => ({
44
- structureTags: editableStructureTags,
45
- });
46
-
47
- export default connect(mapStateToProps)(StructureLinkTagButton);
@@ -1,92 +0,0 @@
1
- import _ from "lodash/fp";
2
- import React from "react";
3
- import PropTypes from "prop-types";
4
- import { connect } from "react-redux";
5
- import { Link } from "react-router-dom";
6
- import { Button, Card, Message, Icon } from "semantic-ui-react";
7
- import { FormattedMessage } from "react-intl";
8
- import { useQuery } from "@apollo/client";
9
- import { ConfirmModal, Loading } from "@truedat/core/components";
10
- import { linkTo } from "@truedat/core/routes";
11
- import { accentInsensitivePathOrder } from "@truedat/core/services/sort";
12
- import { STRUCTURE_TAGS_QUERY } from "../api/queries";
13
- import { deleteStructureTag } from "../routines";
14
-
15
- const EmptyMessage = () => (
16
- <Message icon info>
17
- <Icon name="folder open outline" />
18
- <Message.Content>
19
- <Message.Header>
20
- <FormattedMessage id="structureTags.empty" />
21
- </Message.Header>
22
- </Message.Content>
23
- </Message>
24
- );
25
-
26
- export const StructureTagsCards = ({ deleteStructureTag, structureTags }) => {
27
- if (_.isEmpty(structureTags)) return <EmptyMessage />;
28
- return (
29
- <Card.Group>
30
- {structureTags.map((structureTag) => (
31
- <Card key={structureTag?.id}>
32
- <Card.Content>
33
- <Card.Header
34
- as={Link}
35
- to={linkTo.STRUCTURE_TAGS_EDIT({ id: structureTag.id })}
36
- >
37
- {_.prop("name")(structureTag)}
38
- </Card.Header>
39
- <Card.Description>
40
- {_.prop("description")(structureTag)}
41
- </Card.Description>
42
- </Card.Content>
43
- <Card.Content extra>
44
- <div className="ui actions">
45
- <ConfirmModal
46
- icon="trash"
47
- trigger={<Button icon="trash" basic color="red" />}
48
- header={
49
- <FormattedMessage id="structureTags.actions.delete.confirmation.header" />
50
- }
51
- content={
52
- structureTag.structureCount > 0 ? (
53
- <FormattedMessage
54
- id="structureTags.actions.delete.confirmation.content"
55
- values={{
56
- name: <i>{`'${structureTag.name}'`}</i>,
57
- count: structureTag.structureCount,
58
- }}
59
- />
60
- ) : (
61
- <FormattedMessage
62
- id="structureTags.actions.delete.noStructures.confirmation.content"
63
- values={{ name: <i>{`'${structureTag.name}'`}</i> }}
64
- />
65
- )
66
- }
67
- onConfirm={() => deleteStructureTag({ id: structureTag.id })}
68
- />
69
- </div>
70
- </Card.Content>
71
- </Card>
72
- ))}
73
- </Card.Group>
74
- );
75
- };
76
-
77
- StructureTagsCards.propTypes = {
78
- structureTags: PropTypes.array,
79
- deleteStructureTag: PropTypes.func,
80
- };
81
-
82
- export const StructureTagsCardsLoader = (props) => {
83
- const { loading, error, data } = useQuery(STRUCTURE_TAGS_QUERY);
84
- if (error) return null;
85
- if (loading) return <Loading />;
86
- const structureTags = _.sortBy(accentInsensitivePathOrder("name"))(
87
- data?.structureTags || []
88
- );
89
- return <StructureTagsCards structureTags={structureTags} {...props} />;
90
- };
91
-
92
- export default connect(null, { deleteStructureTag })(StructureTagsCardsLoader);
@@ -1,44 +0,0 @@
1
- import _ from "lodash/fp";
2
- import React from "react";
3
- import PropTypes from "prop-types";
4
- import { Breadcrumb } from "semantic-ui-react";
5
- import { Link } from "react-router-dom";
6
- import { FormattedMessage } from "react-intl";
7
- import { STRUCTURE_TAGS, linkTo } from "@truedat/core/routes";
8
-
9
- export const StructureTagsCrumbs = ({ structureTag, action }) => {
10
- const rootBreadcrumb =
11
- !_.isEmpty(structureTag) && action
12
- ? { as: Link, to: linkTo.STRUCTURE_TAG(structureTag), active: false }
13
- : { active: true };
14
- return (
15
- <Breadcrumb>
16
- <Breadcrumb.Section as={Link} to={STRUCTURE_TAGS} active={false}>
17
- <FormattedMessage id="structureTags.crumbs.root" />
18
- </Breadcrumb.Section>
19
- {_.isEmpty(structureTag) ? null : (
20
- <>
21
- <Breadcrumb.Divider icon="right angle" />
22
- <Breadcrumb.Section {...rootBreadcrumb}>
23
- {structureTag.name}
24
- </Breadcrumb.Section>
25
- </>
26
- )}
27
- {action ? (
28
- <>
29
- <Breadcrumb.Divider icon="right angle" />
30
- <Breadcrumb.Section active>
31
- <FormattedMessage id={action} />
32
- </Breadcrumb.Section>
33
- </>
34
- ) : null}
35
- </Breadcrumb>
36
- );
37
- };
38
-
39
- StructureTagsCrumbs.propTypes = {
40
- structureTag: PropTypes.object,
41
- action: PropTypes.string,
42
- };
43
-
44
- export default StructureTagsCrumbs;
@@ -1,45 +0,0 @@
1
- import React from "react";
2
- import { Route, Switch, useParams } from "react-router-dom";
3
- import { useQuery } from "@apollo/client";
4
- import { Unauthorized } from "@truedat/core/components";
5
- import { useAuthorized } from "@truedat/core/hooks";
6
- import {
7
- STRUCTURE_TAGS,
8
- STRUCTURE_TAGS_EDIT,
9
- STRUCTURE_TAGS_NEW,
10
- } from "@truedat/core/routes";
11
- import { STRUCTURE_TAG_QUERY } from "../api/queries";
12
- import StructureTag from "./StructureTag";
13
- import StructureTags from "./StructureTags";
14
-
15
- export const StructureTagLoader = () => {
16
- const { id } = useParams();
17
- const { loading, error, data } = useQuery(STRUCTURE_TAG_QUERY, {
18
- variables: { id },
19
- });
20
- if (error) return null;
21
- const structureTag = data?.structureTag;
22
- return <StructureTag id={id} structureTag={structureTag} loading={loading} />;
23
- };
24
-
25
- export const AuthorizedStructureTagsRoutes = () => (
26
- <Switch>
27
- <Route exact path={STRUCTURE_TAGS_NEW} render={() => <StructureTag />} />
28
- <Route exact path={STRUCTURE_TAGS} render={() => <StructureTags />} />
29
- <Route path={STRUCTURE_TAGS_EDIT} render={() => <StructureTagLoader />} />
30
- </Switch>
31
- );
32
-
33
- export const StructureTagsRoutes = () => {
34
- const authorized = useAuthorized();
35
- return (
36
- <Route
37
- path={STRUCTURE_TAGS}
38
- render={() =>
39
- authorized ? <AuthorizedStructureTagsRoutes /> : <Unauthorized />
40
- }
41
- />
42
- );
43
- };
44
-
45
- export default StructureTagsRoutes;
@@ -1,32 +0,0 @@
1
- import _ from "lodash/fp";
2
- import React from "react";
3
- import { connect } from "react-redux";
4
- import PropTypes from "prop-types";
5
- import LinkedStructureTag from "./LinkedStructureTag";
6
- import StructureLinkTagButton from "./StructureLinkTagButton";
7
-
8
- export const TagsHeader = ({ linkedStructureTags, editable }) => (
9
- <>
10
- {_.isEmpty(linkedStructureTags)
11
- ? null
12
- : _.flow(
13
- _.sortBy("inserted_at"),
14
- _.map.convert({ cap: false })((link, i) => (
15
- <LinkedStructureTag key={i} editable={editable} {...link} />
16
- ))
17
- )(linkedStructureTags)}
18
- <StructureLinkTagButton />
19
- </>
20
- );
21
-
22
- TagsHeader.propTypes = {
23
- editable: PropTypes.bool,
24
- linkedStructureTags: PropTypes.array,
25
- };
26
-
27
- const mapStateToProps = ({ linkedStructureTags, editableStructureTags }) => ({
28
- linkedStructureTags,
29
- editable: !!editableStructureTags,
30
- });
31
-
32
- export default connect(mapStateToProps)(TagsHeader);