@performant-software/semantic-components 0.5.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 (218) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +0 -0
  3. package/build/index.js +2 -0
  4. package/build/index.js.map +1 -0
  5. package/build/main.css +786 -0
  6. package/index.js +1 -0
  7. package/package.json +37 -0
  8. package/src/components/AccordionDataList.css +8 -0
  9. package/src/components/AccordionDataList.js +224 -0
  10. package/src/components/AccordionList.css +27 -0
  11. package/src/components/AccordionList.js +596 -0
  12. package/src/components/AccordionSelector.css +3 -0
  13. package/src/components/AccordionSelector.js +359 -0
  14. package/src/components/ArrowButtons.css +4 -0
  15. package/src/components/ArrowButtons.js +38 -0
  16. package/src/components/AssociatedDropdown.css +44 -0
  17. package/src/components/AssociatedDropdown.js +338 -0
  18. package/src/components/BooleanIcon.css +0 -0
  19. package/src/components/BooleanIcon.js +33 -0
  20. package/src/components/CancelButton.css +0 -0
  21. package/src/components/CancelButton.js +25 -0
  22. package/src/components/ColorButton.css +4 -0
  23. package/src/components/ColorButton.js +34 -0
  24. package/src/components/ColorPickerModal.css +3 -0
  25. package/src/components/ColorPickerModal.js +77 -0
  26. package/src/components/ColumnResize.css +9 -0
  27. package/src/components/ColumnResize.js +20 -0
  28. package/src/components/DataList.css +0 -0
  29. package/src/components/DataList.js +531 -0
  30. package/src/components/DataTable.css +43 -0
  31. package/src/components/DataTable.js +596 -0
  32. package/src/components/DataTableColumnSelector.css +10 -0
  33. package/src/components/DataTableColumnSelector.js +146 -0
  34. package/src/components/DateInput.css +6 -0
  35. package/src/components/DateInput.js +58 -0
  36. package/src/components/DatePicker.css +72 -0
  37. package/src/components/DatePicker.js +81 -0
  38. package/src/components/DescriptorField.css +0 -0
  39. package/src/components/DescriptorField.js +42 -0
  40. package/src/components/DownloadButton.css +0 -0
  41. package/src/components/DownloadButton.js +23 -0
  42. package/src/components/Draggable.css +0 -0
  43. package/src/components/Draggable.js +94 -0
  44. package/src/components/DropdownButton.css +3 -0
  45. package/src/components/DropdownButton.js +65 -0
  46. package/src/components/DropdownMenu.css +0 -0
  47. package/src/components/DropdownMenu.js +68 -0
  48. package/src/components/EditModal.css +8 -0
  49. package/src/components/EditModal.js +99 -0
  50. package/src/components/EditPage.css +7 -0
  51. package/src/components/EditPage.js +249 -0
  52. package/src/components/EmbeddedList.css +7 -0
  53. package/src/components/EmbeddedList.js +278 -0
  54. package/src/components/FileInputButton.css +0 -0
  55. package/src/components/FileInputButton.js +54 -0
  56. package/src/components/FileUpload.css +31 -0
  57. package/src/components/FileUpload.js +188 -0
  58. package/src/components/FileUploadModal.css +0 -0
  59. package/src/components/FileUploadModal.js +408 -0
  60. package/src/components/FuzzyDate.css +8 -0
  61. package/src/components/FuzzyDate.js +575 -0
  62. package/src/components/GoogleMap.css +0 -0
  63. package/src/components/GoogleMap.js +105 -0
  64. package/src/components/GooglePlacesSearch.css +0 -0
  65. package/src/components/GooglePlacesSearch.js +43 -0
  66. package/src/components/HorizontalCards.css +50 -0
  67. package/src/components/HorizontalCards.js +226 -0
  68. package/src/components/ItemCollection.css +3 -0
  69. package/src/components/ItemCollection.js +159 -0
  70. package/src/components/ItemList.css +0 -0
  71. package/src/components/ItemList.js +126 -0
  72. package/src/components/Items.css +19 -0
  73. package/src/components/Items.js +365 -0
  74. package/src/components/ItemsToggle.css +0 -0
  75. package/src/components/ItemsToggle.js +168 -0
  76. package/src/components/KeyboardField.css +4 -0
  77. package/src/components/KeyboardField.js +147 -0
  78. package/src/components/LazyDocument.css +21 -0
  79. package/src/components/LazyDocument.js +113 -0
  80. package/src/components/LazyImage.css +21 -0
  81. package/src/components/LazyImage.js +119 -0
  82. package/src/components/LazyVideo.css +21 -0
  83. package/src/components/LazyVideo.js +131 -0
  84. package/src/components/LinkButton.css +8 -0
  85. package/src/components/LinkButton.js +23 -0
  86. package/src/components/LinkLabel.css +8 -0
  87. package/src/components/LinkLabel.js +29 -0
  88. package/src/components/List.css +8 -0
  89. package/src/components/List.js +761 -0
  90. package/src/components/ListFilters.css +0 -0
  91. package/src/components/ListFilters.js +408 -0
  92. package/src/components/ListLoader.css +8 -0
  93. package/src/components/ListLoader.js +32 -0
  94. package/src/components/ListTable.css +3 -0
  95. package/src/components/ListTable.js +86 -0
  96. package/src/components/LoginModal.css +7 -0
  97. package/src/components/LoginModal.js +102 -0
  98. package/src/components/MasonryGrid.css +48 -0
  99. package/src/components/MasonryGrid.js +202 -0
  100. package/src/components/MediaGallery.css +37 -0
  101. package/src/components/MediaGallery.js +148 -0
  102. package/src/components/MediaGrid.css +72 -0
  103. package/src/components/MediaGrid.js +74 -0
  104. package/src/components/MediaList.css +3 -0
  105. package/src/components/MediaList.js +98 -0
  106. package/src/components/ModalDropdown.css +11 -0
  107. package/src/components/ModalDropdown.js +84 -0
  108. package/src/components/NestedAccordion.css +41 -0
  109. package/src/components/NestedAccordion.js +276 -0
  110. package/src/components/PhotoViewer.css +3 -0
  111. package/src/components/PhotoViewer.js +36 -0
  112. package/src/components/PlayButton.css +3 -0
  113. package/src/components/PlayButton.js +37 -0
  114. package/src/components/RemoteDropdown.css +13 -0
  115. package/src/components/RemoteDropdown.js +368 -0
  116. package/src/components/SaveButton.css +0 -0
  117. package/src/components/SaveButton.js +31 -0
  118. package/src/components/Section.css +0 -0
  119. package/src/components/Section.js +41 -0
  120. package/src/components/Selectize.css +11 -0
  121. package/src/components/Selectize.js +297 -0
  122. package/src/components/SelectizeHeader.css +3 -0
  123. package/src/components/SelectizeHeader.js +40 -0
  124. package/src/components/TabbedModal.css +14 -0
  125. package/src/components/TabbedModal.js +165 -0
  126. package/src/components/TabsMenu.css +0 -0
  127. package/src/components/TabsMenu.js +35 -0
  128. package/src/components/TagsList.css +0 -0
  129. package/src/components/TagsList.js +43 -0
  130. package/src/components/Thumbnail.css +0 -0
  131. package/src/components/Thumbnail.js +47 -0
  132. package/src/components/Toaster.css +9 -0
  133. package/src/components/Toaster.js +73 -0
  134. package/src/components/VideoFrameSelector.css +3 -0
  135. package/src/components/VideoFrameSelector.js +148 -0
  136. package/src/components/VideoPlayer.css +3 -0
  137. package/src/components/VideoPlayer.js +55 -0
  138. package/src/components/VideoPlayerButton.css +17 -0
  139. package/src/components/VideoPlayerButton.js +17 -0
  140. package/src/components/ViewXML.css +0 -0
  141. package/src/components/ViewXML.js +72 -0
  142. package/src/i18n/en.json +204 -0
  143. package/src/i18n/i18n.js +24 -0
  144. package/src/index.js +76 -0
  145. package/types/components/AccordionDataList.js.flow +224 -0
  146. package/types/components/AccordionList.js.flow +596 -0
  147. package/types/components/AccordionSelector.js.flow +359 -0
  148. package/types/components/ArrowButtons.js.flow +38 -0
  149. package/types/components/AssociatedDropdown.js.flow +338 -0
  150. package/types/components/BooleanIcon.js.flow +33 -0
  151. package/types/components/CancelButton.js.flow +25 -0
  152. package/types/components/ColorButton.js.flow +34 -0
  153. package/types/components/ColorPickerModal.js.flow +77 -0
  154. package/types/components/ColumnResize.js.flow +20 -0
  155. package/types/components/DataList.js.flow +531 -0
  156. package/types/components/DataTable.js.flow +596 -0
  157. package/types/components/DataTableColumnSelector.js.flow +146 -0
  158. package/types/components/DataView.js.flow +125 -0
  159. package/types/components/DateInput.js.flow +58 -0
  160. package/types/components/DatePicker.js.flow +81 -0
  161. package/types/components/DescriptorField.js.flow +42 -0
  162. package/types/components/DownloadButton.js.flow +23 -0
  163. package/types/components/Draggable.js.flow +94 -0
  164. package/types/components/DropdownButton.js.flow +65 -0
  165. package/types/components/DropdownMenu.js.flow +68 -0
  166. package/types/components/EditModal.js.flow +99 -0
  167. package/types/components/EditPage.js.flow +249 -0
  168. package/types/components/EmbeddedList.js.flow +278 -0
  169. package/types/components/FileInputButton.js.flow +54 -0
  170. package/types/components/FileUpload.js.flow +188 -0
  171. package/types/components/FileUploadModal.js.flow +408 -0
  172. package/types/components/FuzzyDate.js.flow +575 -0
  173. package/types/components/GoogleMap.js.flow +105 -0
  174. package/types/components/GooglePlacesSearch.js.flow +43 -0
  175. package/types/components/HorizontalCards.js.flow +226 -0
  176. package/types/components/ItemCollection.js.flow +159 -0
  177. package/types/components/ItemList.js.flow +126 -0
  178. package/types/components/Items.js.flow +365 -0
  179. package/types/components/ItemsToggle.js.flow +168 -0
  180. package/types/components/KeyboardField.js.flow +147 -0
  181. package/types/components/LazyDocument.js.flow +113 -0
  182. package/types/components/LazyImage.js.flow +119 -0
  183. package/types/components/LazyVideo.js.flow +131 -0
  184. package/types/components/LinkButton.js.flow +23 -0
  185. package/types/components/LinkLabel.js.flow +29 -0
  186. package/types/components/List.js.flow +761 -0
  187. package/types/components/ListFilters.js.flow +408 -0
  188. package/types/components/ListLoader.js.flow +32 -0
  189. package/types/components/ListTable.js.flow +86 -0
  190. package/types/components/LoginModal.js.flow +102 -0
  191. package/types/components/MasonryGrid.js.flow +202 -0
  192. package/types/components/MediaGallery.js.flow +148 -0
  193. package/types/components/MediaGrid.js.flow +74 -0
  194. package/types/components/MediaList.js.flow +98 -0
  195. package/types/components/MenuBar.js.flow +77 -0
  196. package/types/components/MenuSidebar.js.flow +72 -0
  197. package/types/components/ModalDropdown.js.flow +84 -0
  198. package/types/components/NestedAccordion.js.flow +276 -0
  199. package/types/components/PhotoViewer.js.flow +36 -0
  200. package/types/components/PlayButton.js.flow +37 -0
  201. package/types/components/RemoteDropdown.js.flow +368 -0
  202. package/types/components/SaveButton.js.flow +31 -0
  203. package/types/components/Section.js.flow +41 -0
  204. package/types/components/Selectize.js.flow +297 -0
  205. package/types/components/SelectizeHeader.js.flow +40 -0
  206. package/types/components/TabbedModal.js.flow +165 -0
  207. package/types/components/TabsMenu.js.flow +35 -0
  208. package/types/components/TagsList.js.flow +43 -0
  209. package/types/components/Thumbnail.js.flow +47 -0
  210. package/types/components/Toaster.js.flow +73 -0
  211. package/types/components/VideoFrameSelector.js.flow +148 -0
  212. package/types/components/VideoPlayer.js.flow +55 -0
  213. package/types/components/VideoPlayerButton.js.flow +17 -0
  214. package/types/components/ViewXML.js.flow +72 -0
  215. package/types/hooks/Imageable.js.flow +54 -0
  216. package/types/i18n/i18n.js.flow +24 -0
  217. package/types/index.js.flow +78 -0
  218. package/webpack.config.js +3 -0
@@ -0,0 +1,596 @@
1
+ // @flow
2
+
3
+ import { Timer, Utility } from '@performant-software/shared-components';
4
+ import React, { Component } from 'react';
5
+ import {
6
+ Button,
7
+ Checkbox,
8
+ Confirm,
9
+ Grid,
10
+ Header,
11
+ Input,
12
+ Message,
13
+ Pagination
14
+ } from 'semantic-ui-react';
15
+ import _ from 'underscore';
16
+ import i18n from '../i18n/i18n';
17
+ import EditModal from './EditModal';
18
+ import NestedAccordion from './NestedAccordion';
19
+ import Toaster from './Toaster';
20
+ import './AccordionList.css';
21
+
22
+ type Props = {
23
+ buttons: Array<Object>,
24
+ canAddItem?: (item: any) => boolean,
25
+ canCopyItem?: (item: any) => boolean,
26
+ canDeleteItem?: (item: any) => boolean,
27
+ canEditItem?: (item: any) => boolean,
28
+ className?: string,
29
+ collectionName: string,
30
+ getChildItems: (items: Array<any>, item: any) => Array<any>,
31
+ getRootItems: (items: Array<any>) => Array<any>,
32
+ hideAddRootButton: boolean,
33
+ lazyLoad: boolean,
34
+ modal?: {
35
+ component: Component<{}>,
36
+ onAddItem: (item: any) => any,
37
+ props: any,
38
+ state: any,
39
+ },
40
+ onCopy: (item: any) => any,
41
+ onDelete: (item: any) => Promise<any>,
42
+ onRowSelect: (?any, ?any, ?any) => void,
43
+ onSave: (item: any) => Promise<any>,
44
+ onSearch: (?number | ?string, ?number | ?string) => Promise<any>,
45
+ onSelectAll: (?any, ?any, ?any, ?any) => void,
46
+ pagination: boolean,
47
+ renderItem: (item: any) => string | Component<{}>,
48
+ selectable: boolean,
49
+ selectedRows: Array<{id: number}>,
50
+ showRecordCount: boolean,
51
+ showToggle: (item: any) => boolean,
52
+ };
53
+
54
+ type State = {
55
+ count: number,
56
+ items: Array<any>,
57
+ modalAdd: boolean,
58
+ modalDelete: boolean,
59
+ page: ?number,
60
+ pages: ?number,
61
+ saved: boolean,
62
+ searchQuery: string,
63
+ selectedItem: ?any
64
+ };
65
+
66
+ class AccordionList extends Component<Props, State> {
67
+ static defaultProps: any;
68
+
69
+ /**
70
+ * Constructs a new AccordionList component.
71
+ *
72
+ * @param props
73
+ */
74
+ constructor(props: Props) {
75
+ super(props);
76
+
77
+ this.state = {
78
+ count: 0,
79
+ items: [],
80
+ modalAdd: false,
81
+ modalDelete: false,
82
+ page: 1,
83
+ pages: 1,
84
+ saved: false,
85
+ searchQuery: '',
86
+ selectedItem: null
87
+ };
88
+ }
89
+
90
+ /**
91
+ * Executes the initial search.
92
+ */
93
+ componentDidMount() {
94
+ this.onSearch();
95
+ }
96
+
97
+ /**
98
+ * Displays the add modal for the selected item.
99
+ *
100
+ * @param item
101
+ */
102
+ onAddButton(item: any) {
103
+ let selectedItem = item;
104
+ if (this.props.modal && this.props.modal.onAddItem) {
105
+ selectedItem = this.props.modal.onAddItem(item);
106
+ }
107
+
108
+ this.setState({ modalAdd: true, selectedItem });
109
+ }
110
+
111
+ /**
112
+ * Deletes the currently selected item.
113
+ *
114
+ * @returns {*}
115
+ */
116
+ onDelete() {
117
+ const item = this.state.selectedItem;
118
+
119
+ return this.props
120
+ .onDelete(item)
121
+ .then(() => {
122
+ this.setState((state) => ({
123
+ modalDelete: false,
124
+ selectedItem: null,
125
+ items: _.reject(state.items, (i) => i === item)
126
+ }));
127
+ });
128
+ }
129
+
130
+ /**
131
+ * Displays the delete modal and sets the selected item.
132
+ *
133
+ * @param item
134
+ */
135
+ onDeleteButton(item: any) {
136
+ this.setState({ modalDelete: true, selectedItem: item });
137
+ }
138
+
139
+ /**
140
+ * Displays the edit modal and sets the selected item.
141
+ *
142
+ * @param item
143
+ */
144
+ onEditButton(item: any) {
145
+ this.setState({ modalAdd: true, selectedItem: item });
146
+ }
147
+
148
+ /**
149
+ * Copies the selected item and displays the add/edit modal.
150
+ *
151
+ * @param selectedItem
152
+ */
153
+ onCopyButton(selectedItem: any) {
154
+ let copy;
155
+ if (this.props.onCopy) {
156
+ copy = this.props.onCopy(selectedItem);
157
+ if (Utility.isPromise(copy)) {
158
+ copy.then((item) => {
159
+ this.setState({ selectedItem: item, modalAdd: true });
160
+ });
161
+ } else {
162
+ copy = _.omit(selectedItem, 'id', 'uid');
163
+ this.setState({ selectedItem: copy, modalAdd: true });
164
+ }
165
+ }
166
+ }
167
+
168
+ /**
169
+ * Lazy-loads the children of the passed item and sets them on the state..
170
+ *
171
+ * @param item
172
+ */
173
+ onItemToggle(item: any) {
174
+ if (!item.loaded && this.props.lazyLoad) {
175
+ this.onSearch(item.id).then(() => {
176
+ // Set the "loaded" property on item to prevent multiple API calls
177
+ this.setState((state) => ({
178
+ items: _.map(state.items, (i) => (i.id === item.id ? { ...i, loaded: true } : i))
179
+ }));
180
+ });
181
+ }
182
+ }
183
+
184
+ /**
185
+ * Changes active page and fetches new set of paginated data.
186
+ */
187
+ onPageChange(e: any, selectedPage: any) {
188
+ this.setState({ page: selectedPage.activePage }, () => this.onSearch());
189
+ }
190
+
191
+ /**
192
+ * Saves the passed item.
193
+ *
194
+ * @param item
195
+ *
196
+ * @returns {*}
197
+ */
198
+ onSave(item: any) {
199
+ return this.props
200
+ .onSave(item)
201
+ .then((saved) => {
202
+ this.setState((state) => ({
203
+ modalAdd: false,
204
+ selectedItem: false,
205
+ saved: true,
206
+ items: item.id ? _.map(state.items, (i) => (i.id === saved.id ? saved : i)) : [...state.items, saved]
207
+ }));
208
+ });
209
+ }
210
+
211
+ /**
212
+ * Executes the search and sets the returned items on the state.
213
+ *
214
+ * @param parentId
215
+ *
216
+ * @returns {*}
217
+ */
218
+ onSearch(parentId?: number) {
219
+ if (this.props.lazyLoad) {
220
+ return this.props
221
+ .onSearch(parentId, this.state.searchQuery)
222
+ .then(({ data }) => {
223
+ const items = data[this.props.collectionName];
224
+ this.setState((state) => (parentId
225
+ ? { items: [...state.items || [], ...items] }
226
+ : { items }));
227
+ });
228
+ }
229
+ // for models that use a join table or a relationship
230
+ // structure other than nestable node levels/ancestors
231
+ return this.props
232
+ .onSearch(this.state.searchQuery, this.state.page)
233
+ .then(({ data }) => {
234
+ const items = data[this.props.collectionName];
235
+ this.setState({ items });
236
+ if (this.props.showRecordCount) {
237
+ this.setState({ count: data.list.count });
238
+ }
239
+ if (this.props.pagination) {
240
+ const pageCount = data.list.pages;
241
+ this.setState({ pages: pageCount });
242
+ }
243
+ });
244
+ }
245
+
246
+ /**
247
+ * Sets the search query on the state.
248
+ *
249
+ * @param e
250
+ * @param value
251
+ */
252
+ onSearchChange(e: Event, { value }: any) {
253
+ this.setState({ searchQuery: value });
254
+ }
255
+
256
+ /**
257
+ * Renders the AccordionList component.
258
+ *
259
+ * @returns {*}
260
+ */
261
+ render() {
262
+ return (
263
+ <div
264
+ className={['accordion-list', this.props.className || ''].join(' ')}
265
+ >
266
+ <Header
267
+ className='accordion-header'
268
+ >
269
+ <Input
270
+ autoFocus
271
+ className='search'
272
+ icon='search'
273
+ onKeyDown={Timer.clearSearchTimer.bind(this)}
274
+ onKeyUp={Timer.setSearchTimer.bind(this, this.onSearch.bind(this))}
275
+ onChange={this.onSearchChange.bind(this)}
276
+ size='mini'
277
+ type='text'
278
+ value={this.state.searchQuery}
279
+ />
280
+ { this.renderHeaderAddButton() }
281
+ { this.props.buttons.map((b) => b.render()) }
282
+ </Header>
283
+ { this.renderSubHeader() }
284
+ <NestedAccordion
285
+ getChildItems={this.props.getChildItems.bind(this, this.state.items)}
286
+ onItemToggle={this.onItemToggle.bind(this)}
287
+ renderItem={this.props.renderItem.bind(this)}
288
+ renderRight={this.renderRight.bind(this)}
289
+ rootItems={this.props.getRootItems(this.state.items)}
290
+ showToggle={this.props.showToggle.bind(this)}
291
+ />
292
+ { this.renderFooter() }
293
+ { this.renderAddModal() }
294
+ <Confirm
295
+ content={i18n.t('AccordionList.deleteContent')}
296
+ header={i18n.t('AccordionList.deleteHeader')}
297
+ open={this.state.modalDelete}
298
+ onCancel={() => this.setState({ modalDelete: false, selectedItem: null })}
299
+ onConfirm={this.onDelete.bind(this)}
300
+ />
301
+ { this.state.saved && (
302
+ <Toaster
303
+ onDismiss={() => this.setState({ saved: false })}
304
+ type={Toaster.MessageTypes.positive}
305
+ >
306
+ <Message.Header
307
+ content={i18n.t('Common.messages.save.header')}
308
+ />
309
+ <Message.Content
310
+ content={i18n.t('Common.messages.save.content')}
311
+ />
312
+ </Toaster>
313
+ )}
314
+ </div>
315
+ );
316
+ }
317
+
318
+ /**
319
+ * Renders the add button for the passed item (if applicable).
320
+ *
321
+ * @param item
322
+ *
323
+ * @returns {null|*}
324
+ */
325
+ renderAddButton(item: any) {
326
+ if (this.props.canAddItem && !this.props.canAddItem(item)) {
327
+ return null;
328
+ }
329
+
330
+ return (
331
+ <Button
332
+ basic
333
+ compact
334
+ icon='plus'
335
+ onClick={this.onAddButton.bind(this, item)}
336
+ />
337
+ );
338
+ }
339
+
340
+ renderSelectAll() {
341
+ if (!this.props.selectable && !this.props.onSelectAll) {
342
+ return null;
343
+ }
344
+
345
+ const selectedRowIds = this.props.selectedRows.map((r) => r.id);
346
+ const itemsOnPage = this.state.items ? this.state.items : [];
347
+ const toBeSelected = itemsOnPage.reduce((tbs, item) => (
348
+ selectedRowIds.includes(item.id) ? tbs : [...tbs, item]), []);
349
+
350
+ return (
351
+ <Checkbox
352
+ onClick={(e, el) => this.props.onSelectAll(el, toBeSelected, this.state.items, e)}
353
+ checked={!toBeSelected.length}
354
+ />
355
+ );
356
+ }
357
+
358
+ renderSubHeader() {
359
+ return (
360
+ <div className='sub-header'>
361
+ { this.renderSelectAll() }
362
+ </div>
363
+ );
364
+ }
365
+
366
+ /**
367
+ * Renders the add modal.
368
+ *
369
+ * @returns {null|*}
370
+ */
371
+ renderAddModal() {
372
+ if (!(this.state.modalAdd && this.props.modal)) {
373
+ return null;
374
+ }
375
+ const { component, props } = this.props.modal;
376
+
377
+ return (
378
+ <EditModal
379
+ component={component}
380
+ item={this.state.selectedItem}
381
+ onClose={() => this.setState({ modalAdd: false, selectedItem: null })}
382
+ onSave={this.onSave.bind(this)}
383
+ {...props}
384
+ />
385
+ );
386
+ }
387
+
388
+ /**
389
+ * Renders the delete button for the passed item (if applicable).
390
+ *
391
+ * @param item
392
+ *
393
+ * @returns {null|*}
394
+ */
395
+ renderDeleteButton(item: any) {
396
+ if (this.props.canDeleteItem && !this.props.canDeleteItem(item)) {
397
+ return null;
398
+ }
399
+
400
+ return (
401
+ <Button
402
+ basic
403
+ compact
404
+ icon='trash'
405
+ onClick={this.onDeleteButton.bind(this, item)}
406
+ />
407
+ );
408
+ }
409
+
410
+ /**
411
+ * Renders the edit button for the passed item (if applicable).
412
+ *
413
+ * @param item
414
+ *
415
+ * @returns {null|*}
416
+ */
417
+ renderEditButton(item: any) {
418
+ if (this.props.canEditItem && !this.props.canEditItem(item)) {
419
+ return null;
420
+ }
421
+
422
+ return (
423
+ <Button
424
+ basic
425
+ compact
426
+ icon='edit'
427
+ onClick={this.onEditButton.bind(this, item)}
428
+ />
429
+ );
430
+ }
431
+
432
+ /**
433
+ * Renders the copy button for the passed item (if applicable).
434
+ *
435
+ * @param item
436
+ *
437
+ * @returns {null|*}
438
+ */
439
+ renderCopyButton(item: any) {
440
+ if (this.props.canCopyItem && !this.props.canCopyItem(item)) {
441
+ return null;
442
+ }
443
+
444
+ return (
445
+ <Button
446
+ basic
447
+ compact
448
+ icon='copy'
449
+ onClick={() => this.onCopyButton(item)}
450
+ />
451
+ );
452
+ }
453
+
454
+ /**
455
+ * Renders the header add button.
456
+ *
457
+ * @returns {null|*}
458
+ */
459
+ renderHeaderAddButton() {
460
+ if (!this.props.modal || this.props.hideAddRootButton) {
461
+ return null;
462
+ }
463
+
464
+ return (
465
+ <Button
466
+ basic
467
+ className='add-button'
468
+ content={i18n.t('Common.buttons.add')}
469
+ icon='plus'
470
+ onClick={() => this.setState({ modalAdd: true })}
471
+ />
472
+ );
473
+ }
474
+
475
+ /**
476
+ * Renders the record count component.
477
+ *
478
+ * @returns {null|*}
479
+ */
480
+ renderRecordCount() {
481
+ const recordCount = this.state.count;
482
+ if (!recordCount) {
483
+ return null;
484
+ }
485
+
486
+ return (
487
+ <span className='record-count'>
488
+ {`${Number(recordCount).toLocaleString()} ${i18n.t('AccordionList.record', { count: recordCount })}`}
489
+ </span>
490
+ );
491
+ }
492
+
493
+ /**
494
+ * Renders the pagination button row.
495
+ *
496
+ * @returns {null|*}
497
+ */
498
+ renderPagination() {
499
+ if (!this.props.pagination) {
500
+ return null;
501
+ }
502
+
503
+ return (
504
+ <Pagination
505
+ activePage={this.state.page}
506
+ onPageChange={this.onPageChange.bind(this)}
507
+ size='mini'
508
+ totalPages={this.state.pages}
509
+ />
510
+ );
511
+ }
512
+
513
+ /**
514
+ * Renders the footer.
515
+ *
516
+ * @returns {null|*}
517
+ */
518
+ renderFooter() {
519
+ if (this.props.pagination || this.props.showRecordCount) {
520
+ return (
521
+ <div className='footer'>
522
+ <Grid
523
+ columns={2}
524
+ >
525
+ <Grid.Column
526
+ textAlign='left'
527
+ >
528
+ { this.renderRecordCount() }
529
+ </Grid.Column>
530
+ <Grid.Column
531
+ textAlign='right'
532
+ >
533
+ { this.renderPagination() }
534
+ </Grid.Column>
535
+ </Grid>
536
+ </div>
537
+ );
538
+ }
539
+ return null;
540
+ }
541
+
542
+ /**
543
+ * Renders the select checkbox for the passed item.
544
+ *
545
+ * @returns {null|*}
546
+ */
547
+ renderSelectCheckbox(item: {id: number}) {
548
+ if (!this.props.selectable) {
549
+ return null;
550
+ }
551
+ const selected = this.props.selectedRows.find((r) => r.id === item.id);
552
+ return (
553
+ <Checkbox
554
+ key={`select-checkbox-${item.id}`}
555
+ className='row-select-checkbox'
556
+ onClick={(e, el) => this.props.onRowSelect(el, item, e)}
557
+ checked={!!selected}
558
+ />
559
+ );
560
+ }
561
+
562
+ /**
563
+ * Renders the right side of the passed item.
564
+ *
565
+ * @param item
566
+ *
567
+ * @returns {*}
568
+ */
569
+ renderRight(item: any) {
570
+ return (
571
+ <>
572
+ <Button.Group>
573
+ { this.renderAddButton(item) }
574
+ { this.renderEditButton(item) }
575
+ { this.renderCopyButton(item) }
576
+ { this.renderDeleteButton(item) }
577
+ </Button.Group>
578
+ { this.renderSelectCheckbox(item) }
579
+ </>
580
+ );
581
+ }
582
+ }
583
+
584
+ AccordionList.defaultProps = {
585
+ buttons: [],
586
+ canAddItem: () => true,
587
+ canDeleteItem: () => true,
588
+ canEditItem: () => true,
589
+ canCopyItem: () => false,
590
+ className: '',
591
+ lazyLoad: true,
592
+ modal: undefined,
593
+ pagination: false
594
+ };
595
+
596
+ export default AccordionList;
@@ -0,0 +1,3 @@
1
+ .accordion-selector .ui.button.add-button {
2
+ margin-left: 10px;
3
+ }