@bigbinary/neeto-folders-frontend 1.1.6 → 1.1.7

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 (3) hide show
  1. package/README.md +285 -27
  2. package/package.json +1 -1
  3. package/types.d.ts +81 -1
package/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # neeto-folders-nano
2
2
 
3
- The `neeto-folders-nano` acts as the source of truth for the new nano's structure,
4
- configs, data etc.
3
+ The `neeto-folders-nano` acts as the source of truth for the new nano's
4
+ structure, configs, data etc.
5
5
 
6
6
  ## Contents
7
7
 
@@ -37,13 +37,7 @@ configs, data etc.
37
37
  bundle install
38
38
  ```
39
39
 
40
- 3. Add this line to your application's `config/routes.rb` file
41
-
42
- ```ruby
43
- mount NeetoFoldersEngine::Engine => "/neeto_folders_engine"
44
- ```
45
-
46
- 4. Add required migrations in the `db/migrate` folder. Run the following
40
+ 3. Add required migrations in the `db/migrate` folder. Run the following
47
41
  commands to copy the migrations from the engine to the host application.
48
42
 
49
43
  ```shell
@@ -53,23 +47,60 @@ configs, data etc.
53
47
 
54
48
  #### Usage
55
49
 
56
- 1. Replace NeetoFoldersNano with your project name
50
+ 1. Define the folder model in your application by extending the
51
+ `NeetoFoldersEngine::Folder` base class. Below is the sample code in
52
+ NeetoRecord that defines a `RecordingFolder` model by extending the
53
+ `NeetoFoldersEngine::Folder` to manage recordings.
54
+
55
+ ```ruby
56
+ class RecordingFolder < NeetoFoldersEngine::Folder
57
+ has_many :recordings, -> { unscope(where: :deleted_at) }, foreign_key: :folder_id, dependent: :nullify
58
+ ```
57
59
 
58
- Create a `script.rb` file in the project root and paste the script from the
59
- following file.
60
+ `NeetoFoldersEngine` also expects a instance method `items` to be defined in
61
+ the extended class. This enables the `NeetoFoldersEngine` to keep track of
62
+ the count of items in the folder. Below is a sample code from NeetoRecord.
60
63
 
61
- [Replace project name script](./docs/engine/replace-project-name-script.md)
64
+ ```ruby
65
+ def items
66
+ recordings
67
+ end
68
+ ```
62
69
 
63
- 2. Run the file using the following command:
70
+ 2. Include the `NeetoFoldersEngine::Folderable` in the model which should belong
71
+ to a folder. Order of include is important. Include `Folderable` after
72
+ `Deletable` from neeto-commons-backend to allow `Folderable` to override the
73
+ `soft_delete` method.
64
74
 
65
- ```shell
66
- ruby script.rb
75
+ ```ruby
76
+ include NeetoFoldersEngine::Folderable
67
77
  ```
68
78
 
69
- Notes ⚠️
79
+ 3. `NeetoFoldersEngine` also exposes a controller class
80
+ `NeetoFoldersEngine::FoldersController` with `index`, `show`, `create`,
81
+ `update`, `destroy`, `bulk_update`, `bulk_destroy`, and `reorder` actions to
82
+ manage folders. The host application can extend this class to manage their
83
+ folders. Make sure the routes are properly configured to direct to these
84
+ actions.
70
85
 
71
- - Don't commit this file.
72
- - Project name should be given in PascalCase.
86
+ Similar to the `RecordingFolder < NeetoFoldersEngine::Folder`, the
87
+ `NeetoFoldersEngine::FoldersController` base controller expects a `folders`
88
+ method to be defined in the extended class that allows the controller to
89
+ target folder instances that belongs to a particular type. Given below is
90
+ sample definition in NeetoRecord which extracts recording folders that should
91
+ be managed by the extended controller.
92
+
93
+ ```ruby
94
+ class Api::V1::FoldersController < NeetoFoldersEngine::FoldersController
95
+
96
+ private
97
+
98
+ def folders
99
+ @_folders ||= @organization.recording_folders.includes(:recordings)
100
+ end
101
+ end
102
+
103
+ ```
73
104
 
74
105
  ### Frontend package
75
106
 
@@ -82,21 +113,248 @@ Notes ⚠️
82
113
  ```
83
114
 
84
115
  ### Instructions for development
85
- Check the [Frontend package development guide](https://neeto-engineering.neetokb.com/p/a-d34cb4b0) for step-by-step instructions to develop the frontend package.
116
+
117
+ Check the
118
+ [Frontend package development guide](https://neeto-engineering.neetokb.com/p/a-d34cb4b0)
119
+ for step-by-step instructions to develop the frontend package.
86
120
 
87
121
  #### Usage
88
122
 
89
- 1. Import `WelcomeScreen` component from "@bigbinary/neeto-folders-frontend"
123
+ `neeto-folders-frontend` exports a set of components, hooks, utils and constants
124
+ to be integrated in the host application.
90
125
 
91
- ```javascript
92
- import React from "react";
126
+ Most of the above exports accepts a configuration object with certain
127
+ properties. Given below is the structure of default `config` object. You can
128
+ pass your own config object as argument or props to customize behaviors that
129
+ suits the host product. Define this constant in a constant file and customize
130
+ certain properties such as params as necessary.
93
131
 
94
- import { WelcomeScreen } from "@bigbinary/neeto-folders-frontend";
132
+ ```js
133
+ {
95
134
 
96
- const App = () => <WelcomeScreen />;
135
+ type: "FOLDER", // A unique type key for query keys.
136
+ maxDepth: 2, // Maximum allowed depth for folder tree
137
+ folderPath: "/folders/:folderId", // Path for handling URL redirections and params matching.
138
+ itemLabel: t("common.items"), // For displaying the item label in counts
139
+ itemKeys: [], // For invalidation purposes. Keys in this array will be invalidated along with folders.
140
+ params: {}, // Params to be passed to APIs along with other params. Can be used for sorting and similar.
141
+ api: { // Folder CRUD methods.
142
+ fetch: noop,
143
+ get: noop,
144
+ create: noop,
145
+ update: noop,
146
+ destroy: noop,
147
+ bulkUpdate: noop,
148
+ bulkDestroy: noop,
149
+ }
150
+ }
151
+ ```
97
152
 
98
- export default App;
99
- ```
153
+ #### Components
154
+
155
+ ```js
156
+ import * as components from "@bigbinary/neeto-folders-frontend/components";
157
+ ```
158
+
159
+ 1. `FoldersContext`: This component renders all alerts and panes related to
160
+ folders. Make sure this component is included in some part of your
161
+ application.
162
+
163
+ ###### Props:
164
+
165
+ - `config`: A config object to customize the folders behavior.
166
+
167
+ Sample usage:
168
+
169
+ ```jsx
170
+ import { FoldersContext } from "@bigbinary/neeto-folders-frontend/components";
171
+ // ....
172
+ <FoldersContext config={foldersConfig}>
173
+ <ApplicationComponent>
174
+ </FoldersContext>
175
+ ```
176
+
177
+ 2. `FoldersTree`: This component renders the folders in tree a tree structure.
178
+
179
+ ###### Props:
180
+
181
+ - `config`: A config object to customize the folders behavior.
182
+
183
+ Sample usage:
184
+
185
+ ```jsx
186
+ import { FoldersTree } from "@bigbinary/neeto-folders-frontend/components";
187
+ // ....
188
+ <FoldersTree config={foldersConfig} />;
189
+ ```
190
+
191
+ 3. `FoldersList`: Component renders list of folders. If no folder is
192
+ selected/active, renders list of root folders. If inside a selected folder,
193
+ renders list of sub-folders. The active folder is identified based on the
194
+ param in the URL that matches the `folderPath` in the `config` object.
195
+
196
+ ###### Props:
197
+
198
+ - `config`: A config object to customize the folders behavior.
199
+
200
+ - `selection`: An array of folder ids indicating id of selected folders for
201
+ bulk selection.
202
+
203
+ - `onSelect`: Callback triggered when checkbox is selected for a folder item
204
+ for bulk selection.
205
+
206
+ Sample usage:
207
+
208
+ ```jsx
209
+ import { FoldersList } from "@bigbinary/neeto-folders-frontend/components";
210
+ // ....
211
+ <FoldersList
212
+ config={foldersConfig}
213
+ onSelect={onSelectFolder}
214
+ selection={folderSelection}
215
+ />;
216
+ ```
217
+
218
+ 4. `MoveToFoldersPane`: This component can be used in host applications to move
219
+ items to a folder. Component renders current list of folders in pane with
220
+ radio buttons and invokes callbacks for folder selections.
221
+
222
+ ###### Props:
223
+
224
+ - `isOpen`: Boolean value that controls pane visibility.
225
+
226
+ - `item`: An item object that is to be moved to the folder.
227
+
228
+ - `config`: A config object to customize the folders behavior.
229
+
230
+ - `submitButtonProps`: Pane "Submit" button overrides.
231
+
232
+ - `cancelButtonProps`: Pane "Cancel" button overrides.
233
+
234
+ - `removeButtonProps`: Pane "Remove from folder" button overrides. Note that
235
+ the button will be hidden unless the `onRemove` prop is supplied.
236
+
237
+ - `onSubmit(folderId)`: Callback invoked with id of selected folder on
238
+ submit.
239
+
240
+ - `onClose()`: Callback invoked when the pane is closed.
241
+
242
+ - `onRemove()`: Callback invoked when the Remove from folder button is
243
+ pressed. Note that the button will be hidden unless this prop is supplied.
244
+
245
+ - `onSelect`: Callback triggered when checkbox is selected for a folder item
246
+ for bulk selection.
247
+
248
+ Sample usage:
249
+
250
+ ```jsx
251
+ import { MoveToFoldersPane } from "@bigbinary/neeto-folders-frontend/components";
252
+ // ....
253
+ <MoveToFoldersPane
254
+ item={itemToMove}
255
+ onSelect={onSelectFolder}
256
+ selection={folderSelection}
257
+ />;
258
+ ```
259
+
260
+ #### Hooks
261
+
262
+ ```js
263
+ import * as hooks from "@bigbinary/neeto-folders-frontend/hooks";
264
+ ```
265
+
266
+ 1. `useFolders(config)`: Hook that return the data for all folders in tree
267
+ structure.
268
+
269
+ ###### Arguments:
270
+
271
+ - `config`: A config object to customize the folders behavior.
272
+
273
+ ###### Returns:
274
+
275
+ - `isLoading`: `true` when data is being fetched for active folder. `false`
276
+ otherwise.
277
+
278
+ - `folders`: Data of all folders of given type in tree structure.
279
+
280
+ 2. `useFolder(config)`: Hook that return the data related to current active
281
+ folder based on URL param.
282
+
283
+ ###### Arguments:
284
+
285
+ - `config`: A config object to customize the folders behavior.
286
+
287
+ ###### Returns:
288
+
289
+ - `isLoading`: `true` when data is being fetched for active folder. `false`
290
+ otherwise.
291
+
292
+ - `folderId`: SID of the current active folder based on URL param.
293
+
294
+ - `folder`: Data of the current folder if exists.
295
+
296
+ 3. `useFolderActions(config)`: Hook that return a set of callbacks to trigger
297
+ actions from host application.
298
+
299
+ ###### Arguments:
300
+
301
+ - `config`: A config object to customize the folders behavior.
302
+
303
+ ###### Returns:
304
+
305
+ - `isPending`: `true` when action is in progress. `false` otherwise.
306
+
307
+ - `onAdd()`: Initiates the folder create action.
308
+
309
+ - `onEdit(folder)`: Initiates the folder edit action. Accepts `folder` data
310
+ as argument.
311
+
312
+ - `onMove(folder)`: Initiates the folder edit action. Accepts `folder` data
313
+ as argument.
314
+
315
+ - `onDelete(folder)`: Initiates the folders delete action. Accepts `folder`
316
+ data as argument.
317
+
318
+ - `onReorder()`: Initiates the reorder folder action. Opens the "Reorder"
319
+ pane.
320
+
321
+ #### Utils
322
+
323
+ ```js
324
+ import * as utils from "@bigbinary/neeto-folders-frontend/utils";
325
+ ```
326
+
327
+ 1. pathToFolder(folders, folderId):
328
+
329
+ ###### Arguments:
330
+
331
+ - `folders`: Folders data in tree structure, returned by the `useFolders`
332
+ hook.
333
+
334
+ - `folderId`: Target folder id.
335
+
336
+ Returns an flattened array of folders from root folder to current folder with
337
+ id `folderId`. Useful for showing breadcrumbs and similar.
338
+
339
+ #### Constants
340
+
341
+ ```js
342
+ import * as constants from "@bigbinary/neeto-folders-frontend/constants";
343
+ ```
344
+
345
+ 1. `QUERY_KEYS`: Use query keys to target React Query actions such as
346
+ invalidations.
347
+
348
+ - `[QUERY_KEYS.FOLDERS]`: Targets every query related to folders.
349
+
350
+ - `[QUERY_KEYS.FOLDERS, config.folderType]`: Targets every query related to
351
+ folders of particular type.
352
+
353
+ - `[QUERY_KEYS.FOLDERS, config.folderType, QUERY_KEYS.LIST]`: Targets folders
354
+ list.
355
+
356
+ - `[QUERY_KEYS.FOLDERS, config.folderType, QUERY_KEYS.DETAILS, folderId]`:
357
+ Target folder details of a folder with id `folderId`
100
358
 
101
359
  ## Instructions for Publishing
102
360
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bigbinary/neeto-folders-frontend",
3
- "version": "1.1.6",
3
+ "version": "1.1.7",
4
4
  "description": "A repo acts as the source of truth for the new nano's structure, configs, data etc.",
5
5
  "license": "UNLICENSED",
6
6
  "homepage": "https://github.com/bigbinary/neeto-folders-nano",
package/types.d.ts CHANGED
@@ -1,3 +1,83 @@
1
1
  import React from "react";
2
2
 
3
- export const WelcomeScreen = React.FC<{}>;
3
+ type ApiMethod = () => Promise<any>;
4
+
5
+ interface Config {
6
+ type: string;
7
+ maxDepth: number;
8
+ folderPath: string;
9
+ itemLabel: string;
10
+ itemKeys: string[];
11
+ params: { [key: string]: any };
12
+ api: {
13
+ fetch: ApiMethod;
14
+ get: ApiMethod;
15
+ create: ApiMethod;
16
+ update: ApiMethod;
17
+ destroy: ApiMethod;
18
+ bulkUpdate: ApiMethod;
19
+ bulkDestroy: ApiMethod;
20
+ };
21
+ }
22
+
23
+ interface Folder {
24
+ name: string;
25
+ sid: string;
26
+ type: string;
27
+ item_count: number;
28
+ [key: string]: any;
29
+ }
30
+
31
+ interface QueryKeys {
32
+ FOLDERS: string;
33
+ LIST: string;
34
+ DETAILS: string;
35
+ }
36
+
37
+ export const QUERY_KEYS: QueryKeys;
38
+
39
+ export const FoldersList: React.FC<{
40
+ config: Config;
41
+ selection: string[];
42
+ onSelect: (folderId: string) => void;
43
+ }>;
44
+
45
+ export const FoldersTree: React.FC<{
46
+ config: Config;
47
+ }>;
48
+
49
+ export const MoveToFolderPane: React.FC<{
50
+ isOpen: boolean;
51
+ config: Config;
52
+ item: Folder | any;
53
+ submitButtonProps: object;
54
+ cancelButtonProps: object;
55
+ removeButtonProps: object;
56
+ onSubmit: (folderId: string) => void;
57
+ onClose: () => void;
58
+ onRemove: () => void;
59
+ }>;
60
+
61
+ export const FoldersContext: React.FC<{
62
+ config: Config;
63
+ children: React.ReactNode;
64
+ }>;
65
+
66
+ export const useFolder: (config: Config) => {
67
+ isLoading: boolean;
68
+ folderId: string;
69
+ folder: Folder | null;
70
+ };
71
+
72
+ export const useFolders: (config: Config) => {
73
+ isLoading: boolean;
74
+ folders: Folder[];
75
+ };
76
+
77
+ export const useFolderActions: (config: Config) => {
78
+ onEdit: (item: Folder) => void;
79
+ onMove: (item: Folder) => void;
80
+ onDelete: (item: Folder) => void;
81
+ };
82
+
83
+ export const pathToFolder: (folders: Folder[], folderId: string) => string;