@performant-software/semantic-components 0.5.1 → 0.5.4

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 (32) hide show
  1. package/build/index.js +1 -1
  2. package/build/index.js.map +1 -1
  3. package/build/main.css +5 -0
  4. package/package.json +5 -5
  5. package/src/components/DataList.js +10 -2
  6. package/src/components/DataTableColumnSelector.js +37 -33
  7. package/src/components/DataView.css +4 -0
  8. package/src/components/DataView.js +407 -0
  9. package/src/components/MenuBar.css +0 -0
  10. package/src/components/MenuBar.js +82 -0
  11. package/src/components/MenuSidebar.css +0 -0
  12. package/src/components/MenuSidebar.js +84 -0
  13. package/src/components/ReferenceCodeDropdown.css +0 -0
  14. package/src/components/ReferenceCodeDropdown.js +118 -0
  15. package/src/components/ReferenceCodeModal.css +0 -0
  16. package/src/components/ReferenceCodeModal.js +32 -0
  17. package/src/components/ReferenceTableModal.css +0 -0
  18. package/src/components/ReferenceTableModal.js +67 -0
  19. package/src/components/ReferenceTablesList.css +0 -0
  20. package/src/components/ReferenceTablesList.js +44 -0
  21. package/src/i18n/en.json +32 -0
  22. package/src/index.js +7 -0
  23. package/types/components/DataList.js.flow +10 -2
  24. package/types/components/DataTableColumnSelector.js.flow +37 -33
  25. package/types/components/DataView.js.flow +302 -20
  26. package/types/components/MenuBar.js.flow +9 -4
  27. package/types/components/MenuSidebar.js.flow +18 -6
  28. package/types/components/ReferenceCodeDropdown.js.flow +118 -0
  29. package/types/components/ReferenceCodeModal.js.flow +32 -0
  30. package/types/components/ReferenceTableModal.js.flow +67 -0
  31. package/types/components/ReferenceTablesList.js.flow +44 -0
  32. package/types/index.js.flow +5 -0
@@ -0,0 +1,84 @@
1
+ // @flow
2
+
3
+ import React, { useCallback } from 'react';
4
+ import {
5
+ Header,
6
+ Menu,
7
+ Ref,
8
+ type HeaderProps,
9
+ type MenuItemProps
10
+ } from 'semantic-ui-react';
11
+ import _ from 'underscore';
12
+
13
+ type Props = {
14
+ contextRef: {
15
+ current: ?HTMLElement
16
+ },
17
+ header: HeaderProps,
18
+ items: Array<HeaderProps | MenuItemProps>
19
+ };
20
+
21
+ const MenuSidebar = ({
22
+ contextRef,
23
+ header,
24
+ items,
25
+ ...props
26
+ }: Props) => {
27
+ /**
28
+ * Renders the passed item as a menu.
29
+ *
30
+ * @type {unknown}
31
+ */
32
+ const renderMenu = useCallback((item, index) => (
33
+ <Menu.Item
34
+ key={index}
35
+ >
36
+ <Menu.Header
37
+ {...item}
38
+ />
39
+ <Menu.Menu>
40
+ { _.map(item.items, (i) => renderItem(i)) }
41
+ </Menu.Menu>
42
+ </Menu.Item>
43
+ ), []);
44
+
45
+ /**
46
+ * Renders the passed item as a menu item.
47
+ *
48
+ * @type {unknown}
49
+ */
50
+ const renderMenuItem = useCallback((item, index) => (
51
+ <Menu.Item
52
+ key={index}
53
+ {...item}
54
+ />
55
+ ), []);
56
+
57
+ /**
58
+ * Renders the passed item.
59
+ *
60
+ * @type {function(*): *}
61
+ */
62
+ const renderItem = useCallback((item) => (item.items ? renderMenu(item) : renderMenuItem(item)), []);
63
+
64
+ return (
65
+ <Ref
66
+ innerRef={contextRef}
67
+ >
68
+ <Menu
69
+ {...props}
70
+ fixed='left'
71
+ vertical
72
+ >
73
+ <Menu.Item>
74
+ <Header
75
+ {...header}
76
+ />
77
+ </Menu.Item>
78
+ { _.map(items, (item) => renderItem(item)) }
79
+ </Menu>
80
+ </Ref>
81
+ );
82
+ };
83
+
84
+ export default MenuSidebar;
File without changes
@@ -0,0 +1,118 @@
1
+ // @flow
2
+
3
+ import { ReferenceCodesService } from '@performant-software/shared-components';
4
+ import React, {
5
+ useCallback,
6
+ useEffect,
7
+ useMemo,
8
+ useState
9
+ } from 'react';
10
+ import _ from 'underscore';
11
+ import { Dropdown } from 'semantic-ui-react';
12
+
13
+ type Item = {
14
+ reference_table_id: number,
15
+ key: string
16
+ };
17
+
18
+ type Props = {
19
+ fluid?: boolean,
20
+ multiple?: boolean,
21
+ onChange: (item: Item) => void,
22
+ placeholder?: string,
23
+ referenceTable: string,
24
+ value: Item | Array<Item>
25
+ };
26
+
27
+ const ReferenceCodeDropdown = (props: Props) => {
28
+ const [loading, setLoading] = useState(false);
29
+ const [options, setOptions] = useState([]);
30
+
31
+ /**
32
+ * Converts the passed ID to a reference code item.
33
+ *
34
+ * @type {function(*): {reference_code_id: *}}
35
+ */
36
+ const toItem = useCallback((id) => ({
37
+ reference_code_id: id
38
+ }), []);
39
+
40
+ /**
41
+ * Converts the passed reference code to a dropdown option.
42
+ *
43
+ * @type {function(*): {text: *, value: *, key: *}}
44
+ */
45
+ const toOption = useCallback((referenceCode) => ({
46
+ key: referenceCode.id,
47
+ value: referenceCode.id,
48
+ text: referenceCode.name
49
+ }), []);
50
+
51
+ /**
52
+ * Converts the selected values and calls the onChange prop.
53
+ *
54
+ * @type {(function(*, {value: *}): void)|*}
55
+ */
56
+ const onChange = useCallback((e, { value }) => {
57
+ let values;
58
+
59
+ if (props.multiple) {
60
+ values = value;
61
+ } else {
62
+ values = _.compact([value]);
63
+ }
64
+
65
+ props.onChange(_.map(values, toItem));
66
+ }, [toItem, props.multiple, props.onChange]);
67
+
68
+ /**
69
+ * Sets the "value" variable for the Dropdown component.
70
+ */
71
+ const value = useMemo(() => {
72
+ const v = _.pluck(_.filter(props.value, (x) => !x._destroy), 'reference_code_id');
73
+ return props.multiple ? v : _.first(v);
74
+ }, [props.multiple, props.value]);
75
+
76
+ /**
77
+ * Loads the list of reference codes from the server.
78
+ */
79
+ useEffect(() => {
80
+ setLoading(true);
81
+
82
+ const params = {
83
+ per_page: 0,
84
+ reference_table: props.referenceTable,
85
+ sort_by: 'name'
86
+ };
87
+
88
+ ReferenceCodesService
89
+ .fetchAll(params)
90
+ .then(({ data }) => setOptions(_.map(data.reference_codes, toOption)))
91
+ .finally(() => setLoading(false));
92
+ }, [toOption]);
93
+
94
+ return (
95
+ <Dropdown
96
+ clearable
97
+ disabled={loading}
98
+ fluid={props.fluid}
99
+ loading={loading}
100
+ multiple={props.multiple}
101
+ onChange={onChange}
102
+ options={options}
103
+ placeholder={props.placeholder}
104
+ search
105
+ selection
106
+ selectOnBlur={false}
107
+ value={value}
108
+ />
109
+ );
110
+ };
111
+
112
+ ReferenceCodeDropdown.defaultProps = {
113
+ fluid: true,
114
+ multiple: false,
115
+ placeholder: undefined
116
+ };
117
+
118
+ export default ReferenceCodeDropdown;
File without changes
@@ -0,0 +1,32 @@
1
+ // @flow
2
+
3
+ import type { EditContainerProps } from '@performant-software/shared-components';
4
+ import React from 'react';
5
+ import { Form, Modal } from 'semantic-ui-react';
6
+ import i18n from '../i18n/i18n';
7
+
8
+ const ReferenceCodeModal = (props: EditContainerProps) => (
9
+ <Modal
10
+ as={Form}
11
+ centered={false}
12
+ open
13
+ >
14
+ <Modal.Header
15
+ content={props.item.id
16
+ ? i18n.t('ReferenceCodeModal.title.edit')
17
+ : i18n.t('ReferenceCodeModal.title.add')}
18
+ />
19
+ <Modal.Content>
20
+ <Form.Input
21
+ error={props.isError('name')}
22
+ label={i18n.t('ReferenceCodeModal.labels.name')}
23
+ onChange={props.onTextInputChange.bind(this, 'name')}
24
+ required={props.isRequired('name')}
25
+ value={props.item.name}
26
+ />
27
+ </Modal.Content>
28
+ { props.children }
29
+ </Modal>
30
+ );
31
+
32
+ export default ReferenceCodeModal;
File without changes
@@ -0,0 +1,67 @@
1
+ // @flow
2
+
3
+ import type { EditContainerProps } from '@performant-software/shared-components';
4
+ import React from 'react';
5
+ import { Form, Header, Modal } from 'semantic-ui-react';
6
+ import EmbeddedList from './EmbeddedList';
7
+ import ReferenceCodeModal from './ReferenceCodeModal';
8
+ import i18n from '../i18n/i18n';
9
+
10
+ const ReferenceTableModal = (props: EditContainerProps) => (
11
+ <Modal
12
+ as={Form}
13
+ centered={false}
14
+ className='reference-table-modal'
15
+ open
16
+ >
17
+ <Modal.Header
18
+ content={props.item.id
19
+ ? i18n.t('ReferenceTableModal.title.edit')
20
+ : i18n.t('ReferenceTableModal.title.add')}
21
+ />
22
+ <Modal.Content>
23
+ <Form.Input
24
+ error={props.isError('name')}
25
+ label={i18n.t('ReferenceTableModal.labels.name')}
26
+ onChange={props.onTextInputChange.bind(this, 'name')}
27
+ required={props.isRequired('name')}
28
+ value={props.item.name}
29
+ />
30
+ <Form.Input
31
+ error={props.isError('key')}
32
+ label={i18n.t('ReferenceTableModal.labels.key')}
33
+ onChange={props.onTextInputChange.bind(this, 'key')}
34
+ required={props.isRequired('key')}
35
+ value={props.item.key}
36
+ />
37
+ <Header
38
+ content={i18n.t('ReferenceTableModal.labels.referenceCodes')}
39
+ />
40
+ <EmbeddedList
41
+ actions={[{
42
+ name: 'edit'
43
+ }, {
44
+ name: 'copy'
45
+ }, {
46
+ name: 'delete'
47
+ }]}
48
+ columns={[{
49
+ name: 'name',
50
+ label: i18n.t('ReferenceTableModal.referenceCodes.columns.name')
51
+ }]}
52
+ items={props.item.reference_codes}
53
+ modal={{
54
+ component: ReferenceCodeModal,
55
+ props: {
56
+ required: ['name']
57
+ }
58
+ }}
59
+ onDelete={props.onDeleteChildAssociation.bind(this, 'reference_codes')}
60
+ onSave={props.onSaveChildAssociation.bind(this, 'reference_codes')}
61
+ />
62
+ </Modal.Content>
63
+ { props.children }
64
+ </Modal>
65
+ );
66
+
67
+ export default ReferenceTableModal;
File without changes
@@ -0,0 +1,44 @@
1
+ // @flow
2
+
3
+ import { ReferenceTablesService } from '@performant-software/shared-components';
4
+ import React from 'react';
5
+ import ListTable from './ListTable';
6
+ import ReferenceTableModal from './ReferenceTableModal';
7
+
8
+ const ReferenceTablesList = () => (
9
+ <ListTable
10
+ actions={[{
11
+ name: 'edit'
12
+ }, {
13
+ name: 'copy'
14
+ }, {
15
+ name: 'delete'
16
+ }]}
17
+ collectionName='reference_tables'
18
+ columns={[{
19
+ name: 'name',
20
+ label: 'Name',
21
+ sortable: true
22
+ }, {
23
+ name: 'key',
24
+ label: 'Key',
25
+ sortable: true
26
+ }]}
27
+ modal={{
28
+ component: ReferenceTableModal,
29
+ props: {
30
+ onInitialize: (id) => (
31
+ ReferenceTablesService
32
+ .fetchOne(id)
33
+ .then(({ data }) => data.reference_table)
34
+ ),
35
+ required: ['name', 'key']
36
+ }
37
+ }}
38
+ onDelete={(referenceTable) => ReferenceTablesService.delete(referenceTable)}
39
+ onLoad={(params) => ReferenceTablesService.fetchAll(params)}
40
+ onSave={(referenceTable) => ReferenceTablesService.save(referenceTable)}
41
+ />
42
+ );
43
+
44
+ export default ReferenceTablesList;
package/src/i18n/en.json CHANGED
@@ -60,6 +60,13 @@
60
60
  },
61
61
  "loading": "Loading"
62
62
  },
63
+ "DataView": {
64
+ "labels": {
65
+ "details": "Details",
66
+ "noSort": "No sort",
67
+ "sortBy": "Sort by {{column}}"
68
+ }
69
+ },
63
70
  "EditProvider": {
64
71
  "errors": {
65
72
  "general": "Something went wrong while saving the record. Please make sure all required fields are filled out.",
@@ -176,6 +183,31 @@
176
183
  "loginErrorHeader": "Invalid Credentials",
177
184
  "password": "Password"
178
185
  },
186
+ "ReferenceCodeModal": {
187
+ "labels": {
188
+ "name": "Name"
189
+ },
190
+ "title": {
191
+ "add": "Add Reference Code",
192
+ "edit": "Edit Reference Code"
193
+ }
194
+ },
195
+ "ReferenceTableModal": {
196
+ "labels": {
197
+ "key": "Key",
198
+ "name": "Name",
199
+ "referenceCodes": "Reference Codes"
200
+ },
201
+ "referenceCodes": {
202
+ "columns": {
203
+ "name": "Name"
204
+ }
205
+ },
206
+ "title": {
207
+ "add": "Add Reference Table",
208
+ "edit": "Edit Reference Table"
209
+ }
210
+ },
179
211
  "RemoteDropdown": {
180
212
  "labels": {
181
213
  "add": "Add",
package/src/index.js CHANGED
@@ -12,6 +12,7 @@ export { default as ColorButton } from './components/ColorButton';
12
12
  export { default as ColorPickerModal } from './components/ColorPickerModal';
13
13
  export { default as useDataList } from './components/DataList';
14
14
  export { default as DataTable } from './components/DataTable';
15
+ export { default as DataView } from './components/DataView';
15
16
  export { default as DateInput } from './components/DateInput';
16
17
  export { default as DatePicker } from './components/DatePicker';
17
18
  export { default as DescriptorField } from './components/DescriptorField';
@@ -47,10 +48,16 @@ export { default as MasonryGrid } from './components/MasonryGrid';
47
48
  export { default as MediaGallery } from './components/MediaGallery';
48
49
  export { default as MediaGrid } from './components/MediaGrid';
49
50
  export { default as MediaList } from './components/MediaList';
51
+ export { default as MenuBar } from './components/MenuBar';
52
+ export { default as MenuSidebar } from './components/MenuSidebar';
50
53
  export { default as ModalDropdown } from './components/ModalDropdown';
51
54
  export { default as NestedAccordion } from './components/NestedAccordion';
52
55
  export { default as PlayButton } from './components/PlayButton';
53
56
  export { default as PhotoViewer } from './components/PhotoViewer';
57
+ export { default as ReferenceCodeDropdown } from './components/ReferenceCodeDropdown';
58
+ export { default as ReferenceCodeModal } from './components/ReferenceCodeModal';
59
+ export { default as ReferenceTableModal } from './components/ReferenceTableModal';
60
+ export { default as ReferenceTablesList } from './components/ReferenceTablesList';
54
61
  export { default as RemoteDropdown } from './components/RemoteDropdown';
55
62
  export { default as SaveButton } from './components/SaveButton';
56
63
  export { default as Section } from './components/Section';
@@ -19,10 +19,10 @@ type Props = {
19
19
  props?: any,
20
20
  onChange?: (filter: any) => Promise<any>
21
21
  },
22
- onDelete: (item: any) => Promise<any>,
22
+ onDelete?: (item: any) => Promise<any>,
23
23
  onDeleteAll?: () => Promise<any>,
24
24
  onLoad: (params: any) => Promise<any>,
25
- onSave: (item: any) => Promise<any>,
25
+ onSave?: (item: any) => Promise<any>,
26
26
  perPageOptions?: Array<number>,
27
27
  polling?: number,
28
28
  resolveErrors?: (error: any) => Array<string>,
@@ -251,6 +251,10 @@ const useDataList = (WrappedComponent: ComponentType<any>) => (
251
251
  * @returns {Q.Promise<any> | Promise<R> | Promise<any> | void | *}
252
252
  */
253
253
  onDelete(selectedItem: any) {
254
+ if (!this.props.onDelete) {
255
+ return Promise.resolve();
256
+ }
257
+
254
258
  return this.props
255
259
  .onDelete(selectedItem)
256
260
  .then(this.afterDelete.bind(this))
@@ -333,6 +337,10 @@ const useDataList = (WrappedComponent: ComponentType<any>) => (
333
337
  * @returns {Q.Promise<any> | Promise<R> | Promise<any> | void | *}
334
338
  */
335
339
  onSave(item: any) {
340
+ if (!this.props.onSave) {
341
+ return Promise.resolve();
342
+ }
343
+
336
344
  return Promise.resolve(this.props.onSave(item))
337
345
  .then(() => this.setState({ saved: true }, this.fetchData.bind(this)));
338
346
  }
@@ -1,6 +1,6 @@
1
1
  // @flow
2
2
 
3
- import React, { Component, type ComponentType } from 'react';
3
+ import React, { Component, type ComponentType, type Element } from 'react';
4
4
  import { Checkbox, Dropdown, Icon } from 'semantic-ui-react';
5
5
  import _ from 'underscore';
6
6
  import Draggable from './Draggable';
@@ -10,7 +10,8 @@ import type { Column } from './DataTable';
10
10
 
11
11
  type Props = {
12
12
  className: string,
13
- columns: Array<Column>
13
+ columns: Array<Column>,
14
+ renderListHeader?: () => Element<any>
14
15
  };
15
16
 
16
17
  type State = {
@@ -107,37 +108,40 @@ const useColumnSelector = (WrappedComponent: ComponentType<any>) => (
107
108
  */
108
109
  renderHeader() {
109
110
  return (
110
- <Dropdown
111
- basic
112
- button
113
- icon='cog'
114
- className='icon configure-button open-right'
115
- simple
116
- >
117
- <Dropdown.Menu>
118
- { this.state.columns
119
- .filter((c) => c.label && c.label.length)
120
- .map((c, index) => (
121
- <Draggable
122
- id={c.name}
123
- index={index}
124
- key={c.name}
125
- onDrag={this.onDrag.bind(this)}
126
- >
127
- <Dropdown.Item>
128
- <Icon
129
- name='bars'
130
- />
131
- <Checkbox
132
- checked={!c.hidden}
133
- label={c.label}
134
- onClick={this.onColumnCheckbox.bind(this, c)}
135
- />
136
- </Dropdown.Item>
137
- </Draggable>
138
- ))}
139
- </Dropdown.Menu>
140
- </Dropdown>
111
+ <>
112
+ { this.props.renderListHeader && this.props.renderListHeader() }
113
+ <Dropdown
114
+ basic
115
+ button
116
+ icon='cog'
117
+ className='icon configure-button open-right'
118
+ simple
119
+ >
120
+ <Dropdown.Menu>
121
+ { this.state.columns
122
+ .filter((c) => c.label && c.label.length)
123
+ .map((c, index) => (
124
+ <Draggable
125
+ id={c.name}
126
+ index={index}
127
+ key={c.name}
128
+ onDrag={this.onDrag.bind(this)}
129
+ >
130
+ <Dropdown.Item>
131
+ <Icon
132
+ name='bars'
133
+ />
134
+ <Checkbox
135
+ checked={!c.hidden}
136
+ label={c.label}
137
+ onClick={this.onColumnCheckbox.bind(this, c)}
138
+ />
139
+ </Dropdown.Item>
140
+ </Draggable>
141
+ ))}
142
+ </Dropdown.Menu>
143
+ </Dropdown>
144
+ </>
141
145
  );
142
146
  }
143
147
  }