@bigbinary/neeto-filters-frontend 3.0.6 → 3.0.8
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/README.md +225 -293
- package/dist/index.cjs.js +3 -2
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -1,233 +1,240 @@
|
|
|
1
1
|
# neeto-filters-nano
|
|
2
|
+
The `neeto-filters-nano` manages filters across neeto products. The nano exports the `@bigbinary/neeto-filters-frontend` NPM package and `neeto-filters-engine` Rails engine for development.
|
|
3
|
+
|
|
4
|
+
# Contents
|
|
5
|
+
1. [Development with Host Application](#development-with-host-application)
|
|
6
|
+
- [Engine](#engine)
|
|
7
|
+
- [Installation](#installation)
|
|
8
|
+
- [Usage](#usage)
|
|
9
|
+
- [Frontend package](#frontend-package)
|
|
10
|
+
- [Installation](#installation-1)
|
|
11
|
+
- [Components](#components)
|
|
12
|
+
2. [Instructions for Publishing](#instructions-for-publishing)
|
|
13
|
+
|
|
14
|
+
# Development with Host Application
|
|
15
|
+
## Engine
|
|
16
|
+
The engine is used to manage filters across neeto products.
|
|
2
17
|
|
|
3
|
-
|
|
4
|
-
|
|
18
|
+
### Installation
|
|
19
|
+
1. Add this line to your application's Gemfile:
|
|
20
|
+
```ruby
|
|
21
|
+
source "NEETO_GEM_SERVER_URL" do
|
|
22
|
+
# ..existing gems
|
|
5
23
|
|
|
6
|
-
|
|
24
|
+
gem 'neeto-filters-engine'
|
|
25
|
+
end
|
|
26
|
+
```
|
|
27
|
+
2. And then execute:
|
|
28
|
+
```zsh
|
|
29
|
+
bundle install
|
|
30
|
+
```
|
|
31
|
+
3. Add this line to your application's `config/routes.rb` file:
|
|
32
|
+
```ruby
|
|
33
|
+
mount NeetoFiltersEngine::Engine, at: "/neeto_filters"
|
|
34
|
+
```
|
|
35
|
+
4. Execute the following command to generate the migration to generate the `neeto_filters_engine_segments` table.
|
|
36
|
+
```zsh
|
|
37
|
+
rails g neeto_filters_engine:install
|
|
38
|
+
```
|
|
39
|
+
5. Add the following line to `models/organization.rb` file.
|
|
40
|
+
```ruby
|
|
41
|
+
has_many :segments, class_name: "NeetoFiltersEngine::Segment", dependent: :destroy
|
|
42
|
+
```
|
|
7
43
|
|
|
8
|
-
|
|
44
|
+
### Usage
|
|
45
|
+
You can learn more about setup and usage here:
|
|
46
|
+
1. [Models](/docs/engine/models.md)
|
|
47
|
+
2. [Verify Installation](/docs/engine/verify_installation.md)
|
|
9
48
|
|
|
49
|
+
## Frontend package
|
|
10
50
|
### Installation
|
|
51
|
+
1. Install the latest `neeto-filters-frontend` package using the below command:
|
|
52
|
+
```zsh
|
|
53
|
+
yarn add @bigbinary/neeto-filters-frontend
|
|
54
|
+
```
|
|
55
|
+
2. `neeto-filters-frontend` has a few peer dependencies that are required for the proper functioning of the package. Install all the peer dependencies using the below command:
|
|
56
|
+
```zsh
|
|
57
|
+
yarn add @bigbinary/neetoui @bigbinary/neeto-icons axios@0.27.2 classnames@2.3.1 dayjs@1.11.1 formik@2.2.0 ramda@0.28.0 react-router-dom@5.3.0 react-router-nav-prompt@0.4.1 react-toastify@9.0.1 yup@0.32.11
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Components
|
|
61
|
+
#### 1. `Filters` ([source code](https://github.com/bigbinary/neeto-filters-nano/blob/472fc52c3358a822bdb7d1a9d6fe7eed6335247a/app/javascript/src/components/Filters.jsx))
|
|
62
|
+
|
|
63
|
+
**Props**
|
|
64
|
+
- `isOpen`: To specify whether the Pane component is open or not.
|
|
65
|
+
- `setIsOpen`: To trigger the isOpen state.
|
|
66
|
+
- `columns`: The list of columns/fields that needs to be represented in the filters pane.
|
|
67
|
+
- `onChange`: To specify the callback function that is triggered whenever a filter is applied or cleared. This function will get the updated filters as argument.
|
|
68
|
+
- `onSelectorsChange`: To specify the callback function that is triggered
|
|
69
|
+
whenever a selector value is changed. This function will get the updated
|
|
70
|
+
selectors as argument.
|
|
71
|
+
- `buttonProps`: To specify the props to be passed to the button component.
|
|
72
|
+
- `paneProps`: To specify the props to be passed to the pane component.
|
|
73
|
+
- `isSearchable`: To specify whether you need a search bar in filters pane to search through filter fields.
|
|
74
|
+
- `className`: To specify classes to the Filters component.
|
|
75
|
+
- `keyword`: To specify the props related to searching.
|
|
76
|
+
- `childrenKeys`: The list of keys which has to be cleared from url during clear filters operation.
|
|
77
|
+
- `children`: To specify the custom components specific to the host application.
|
|
78
|
+
- `size`: To specify the width of the filters pane. It accepts "xsmall" (default), "small", and "large" as value.
|
|
79
|
+
|
|
80
|
+
**Configuration**
|
|
81
|
+
- Refer to the [Filters](/docs/frontend/filters.md) section for detailed information on the available configurations for the `Filters` component.
|
|
82
|
+
|
|
83
|
+
**Usage**
|
|
84
|
+
```jsx
|
|
85
|
+
import React, { useMemo, useState } from "react";
|
|
86
|
+
|
|
87
|
+
import { Bar, Container, SubHeader } from "neetomolecules";
|
|
88
|
+
import { Filters } from "neetoFilters";
|
|
89
|
+
|
|
90
|
+
const App = () => {
|
|
91
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
92
|
+
const [showMenuBar, setShowMenuBar] = useState(false);
|
|
93
|
+
|
|
94
|
+
const { t } = useTranslation();
|
|
95
|
+
|
|
96
|
+
return (
|
|
97
|
+
<Container>
|
|
98
|
+
<SubHeader
|
|
99
|
+
rightActionBlock={
|
|
100
|
+
<Filters
|
|
101
|
+
{...{ isOpen, setIsOpen }}
|
|
102
|
+
isSearchable
|
|
103
|
+
columns={FILTER_COLUMNS}
|
|
104
|
+
keyword={SEARCH_TERM_PROPS}
|
|
105
|
+
/>
|
|
106
|
+
}
|
|
107
|
+
/>
|
|
108
|
+
</Container>
|
|
109
|
+
);
|
|
110
|
+
};
|
|
11
111
|
|
|
12
|
-
|
|
13
|
-
yarn add @bigbinary/neeto-filters-frontend
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
**neetoFilters** has a few peer dependencies that are required for the proper
|
|
17
|
-
functioning of the package. Install all the peer dependencies using the below
|
|
18
|
-
command:
|
|
19
|
-
|
|
20
|
-
```bash
|
|
21
|
-
yarn add @bigbinary/neetoui @bigbinary/neeto-icons axios@0.27.2 classnames@2.3.1 dayjs@1.11.1 formik@2.2.0 ramda@0.28.0 react-router-dom@5.3.0 react-router-nav-prompt@0.4.1 react-toastify@9.0.1 yup@0.32.11
|
|
112
|
+
export default App;
|
|
22
113
|
```
|
|
23
114
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
neeto-filters-frontend exports 2 components (`Filters` & `Bar`) and 2 functions
|
|
27
|
-
(`buildFiltersFromURL()` & `buildSelectorsFromURL()`).
|
|
28
|
-
|
|
29
|
-
#### 1. `Filters` component
|
|
115
|
+
#### 2. `Bar` ([source code](https://github.com/bigbinary/neeto-filters-nano/blob/472fc52c3358a822bdb7d1a9d6fe7eed6335247a/app/javascript/src/components/Bar/index.jsx))
|
|
30
116
|
|
|
31
|
-
|
|
117
|
+
**Props**
|
|
118
|
+
- `columns`: The list of columns/fields that needs to be represented in the filters pane.
|
|
119
|
+
- `onChange`: To specify the callback function that is triggered whenever a filter is applied or cleared. This function will get the updated filters as argument.
|
|
120
|
+
- `setIsPaneOpen`: To trigger the isOpen state.
|
|
121
|
+
- `className`: To specify classes to the Bar component.
|
|
122
|
+
- `keyword`: To specify the props related to searching.
|
|
123
|
+
- `onSelectorsChange`: To specify the callback function that is triggered whenever a selector value is changed. This function will get the updated selectors as argument.
|
|
124
|
+
- `childrenKeys`: The list of keys which has to be cleared from url during clear filters operation.
|
|
125
|
+
- `entity`: The entity associated with the filters.
|
|
126
|
+
- `defaultSegmentName`: The name of segment which results all entities without applying any filter. Default name is "All results".
|
|
32
127
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
filters pane.
|
|
37
|
-
4. **onChange**: To specify the callback function that is triggered whenever a
|
|
38
|
-
filter is applied or cleared. This function will get the updated filters as
|
|
39
|
-
argument.
|
|
40
|
-
5. **onSelectorsChange**: To specify the callback function that is triggered
|
|
41
|
-
whenever a selector value is changed. This function will get the updated
|
|
42
|
-
selectors as argument.
|
|
43
|
-
6. **buttonProps**: To specify the props to be passed to the button component.
|
|
44
|
-
7. **paneProps**: To specify the props to be passed to the pane component.
|
|
45
|
-
8. **isSearchable**: To specify whether you need a search bar in filters pane
|
|
46
|
-
to search through filter fields.
|
|
47
|
-
9. **className**: To specify classes to the Filters component.
|
|
48
|
-
10. **keyword**: To specify the props related to searching.
|
|
49
|
-
11. **childrenKeys** The list of keys which has to be cleared from url during
|
|
50
|
-
clear filters operation.
|
|
51
|
-
12. **children**: To specify the custom components specific to the host
|
|
52
|
-
application.
|
|
53
|
-
13. **size**: To specify the width of the filters pane. It accepts "xsmall"
|
|
54
|
-
(default), "small", and "large" as value.
|
|
55
|
-
|
|
56
|
-
Here is an example of `keyword` prop:
|
|
128
|
+
All these props must be same as that passed to the `Filters` component. The
|
|
129
|
+
option to save filters as segments will be enabled only when the entity prop is
|
|
130
|
+
passed to the component.
|
|
57
131
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
132
|
+
**Usage**
|
|
133
|
+
```jsx
|
|
134
|
+
import React, { useMemo, useState } from "react";
|
|
135
|
+
|
|
136
|
+
import Bar from "neetomolecules/SubHeader";
|
|
137
|
+
import Container from "neetomolecules/Container";
|
|
138
|
+
|
|
139
|
+
import { Segments, buildFilterColumns } from "neetoFilters";
|
|
140
|
+
import useUsers from "hooks/useUsers";
|
|
141
|
+
|
|
142
|
+
const App = () => {
|
|
143
|
+
const { usersData } = useUsers();
|
|
144
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
145
|
+
const [fields, setFields] = useState([]);
|
|
146
|
+
|
|
147
|
+
const { t } = useTranslation();
|
|
148
|
+
const filterColumns = useMemo(
|
|
149
|
+
() =>
|
|
150
|
+
buildFilterColumns({
|
|
151
|
+
names: usersData.names,
|
|
152
|
+
emails: usersData.emails,
|
|
153
|
+
fields,
|
|
154
|
+
}),
|
|
155
|
+
[usersData.users, fields]
|
|
156
|
+
);
|
|
157
|
+
|
|
158
|
+
return (
|
|
159
|
+
<Container>
|
|
160
|
+
<SubHeader
|
|
161
|
+
leftActionBlock={
|
|
162
|
+
<Bar
|
|
163
|
+
columns={filterColumns}
|
|
164
|
+
entity="User"
|
|
165
|
+
setIsPaneOpen={setIsOpen}
|
|
166
|
+
/>
|
|
167
|
+
}
|
|
168
|
+
/>
|
|
169
|
+
</Container>
|
|
170
|
+
);
|
|
63
171
|
};
|
|
64
|
-
```
|
|
65
172
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
> :memo: **Note:** If you wish to conduct a search for the keyword among
|
|
69
|
-
> multiple columns spanning different tables in the DB, then you should pass the
|
|
70
|
-
> name of the models corresponding to the tables as value of `models` prop.
|
|
71
|
-
>
|
|
72
|
-
> Example:
|
|
73
|
-
>
|
|
74
|
-
> If you are querying the user records and searching the keyword among users'
|
|
75
|
-
> name and users' organization name, then node will be like:
|
|
76
|
-
>
|
|
77
|
-
> `node = "first_name,last_name,organization.name"`
|
|
78
|
-
>
|
|
79
|
-
> And the model should be:
|
|
80
|
-
>
|
|
81
|
-
> `model = "User,Organization"`
|
|
82
|
-
|
|
83
|
-
Here is an example for the `columns` prop:
|
|
84
|
-
|
|
85
|
-
```js
|
|
86
|
-
export const SAMPLE_FILTER_FIELDS = [
|
|
87
|
-
{
|
|
88
|
-
key: "name",
|
|
89
|
-
node: "first_name,last_name",
|
|
90
|
-
label: "Name",
|
|
91
|
-
suffixComponent: () => <Component />
|
|
92
|
-
type: "text",
|
|
93
|
-
preprocessor: (value) => value.trim(),
|
|
94
|
-
},
|
|
95
|
-
{
|
|
96
|
-
key: "email",
|
|
97
|
-
node: "email",
|
|
98
|
-
label: "Email",
|
|
99
|
-
type: "multi_option",
|
|
100
|
-
values: [map(toLabelAndValue,["oliver@example.com", "eve@example.com"])],
|
|
101
|
-
},
|
|
102
|
-
{
|
|
103
|
-
key: "createdAt",
|
|
104
|
-
node: "created_at",
|
|
105
|
-
label: "Created at",
|
|
106
|
-
type: "date",
|
|
107
|
-
},
|
|
108
|
-
];
|
|
173
|
+
export default App;
|
|
109
174
|
```
|
|
110
175
|
|
|
111
|
-
- `key` : A unique identifier provided to each columns/field.
|
|
112
|
-
- `group`: The label of the group, if the field is associated with a group.
|
|
113
|
-
- `node`: The column in DB table corresponding to the field.
|
|
114
|
-
- `label` The label to be shown just above the field in Pane.
|
|
115
|
-
- `suffixComponent` The component to be shown at the end of the respective Block
|
|
116
|
-
in filters Bar.
|
|
117
|
-
- `preprocessor` The function to be used to preprocess the value before applying
|
|
118
|
-
the filter.
|
|
119
|
-
- `type`: The nature/type of the field needed in pane.
|
|
120
|
-
- The supported types are `text`, `number`, `decimal`, `date`, `single_date`,
|
|
121
|
-
`time`, `single_time`, `single_option`, `multi_option` and `boolean`
|
|
122
|
-
- `model`: If the node provided is **not** directly refering to the column
|
|
123
|
-
within the table being queried for the filtered results, then we need to
|
|
124
|
-
provide the **model** corresponding to the target table. - For example: We are
|
|
125
|
-
adding a filter field for querying on `users` table to list all users with
|
|
126
|
-
address containing the a certain word. Say the addresses are stored in
|
|
127
|
-
**another table `addresses`**. Then the node will be `address.line_1,line_2`.
|
|
128
|
-
In such cases we need to pass this extra prop like `model: "Address"`.
|
|
129
|
-
- Then whole object for the field might look like this
|
|
130
|
-
```js
|
|
131
|
-
{
|
|
132
|
-
key: "address",
|
|
133
|
-
label: "Address",
|
|
134
|
-
node: "address.line_1,line_2",
|
|
135
|
-
model: "Address",
|
|
136
|
-
type: "text"
|
|
137
|
-
}
|
|
138
|
-
```
|
|
139
|
-
- `values`: The list of label-value pair to be shown in dropdown, if the `type`
|
|
140
|
-
provided is `single_option` or `multi_option`.
|
|
141
|
-
- `showRuleSelector` : Boolean value, which determines whether to show a rule
|
|
142
|
-
selector above the `text` , `number` and `decimal` type fields. `false` by
|
|
143
|
-
default.
|
|
144
|
-
- `hidden`: Boolean value, which determines to show or hide field from filter
|
|
145
|
-
pane. `false ` by default.
|
|
146
|
-
- `defaultValue`: The default value that should appear as chosen one in the
|
|
147
|
-
filter fields.
|
|
148
|
-
- `defaultType`: The type of the input that should be used in the Filters pane.
|
|
149
|
-
- `isClearable`: Boolean value which specifies whether the field can be cleared
|
|
150
|
-
or not.
|
|
151
176
|
|
|
152
|
-
|
|
153
|
-
(`node`) to a DB >table column.
|
|
154
|
-
- For example, consider a field in filter pane called `Group by`. We cannot
|
|
155
|
-
provide a `node` to associate it with a column in DB table. Still it can
|
|
156
|
-
provide an important value which can be used for the computation as if by
|
|
157
|
-
telling a means by which the records can be grouped after filtering.
|
|
158
|
-
- Fields without a `node`, among the ones passed as value to the `column` prop
|
|
159
|
-
of `Filters` are >considered as selectors.
|
|
177
|
+
#### 3. `Segments` ([source code](https://github.com/bigbinary/neeto-filters-nano/blob/472fc52c3358a822bdb7d1a9d6fe7eed6335247a/app/javascript/src/components/Segments/index.jsx))
|
|
160
178
|
|
|
161
|
-
|
|
162
|
-
{
|
|
163
|
-
key: "groupBy",
|
|
164
|
-
label: "Group by",
|
|
165
|
-
type: "single_option",
|
|
166
|
-
values: [
|
|
167
|
-
{
|
|
168
|
-
label: "Team",
|
|
169
|
-
value: "team"
|
|
170
|
-
},
|
|
171
|
-
{
|
|
172
|
-
label: "Location",
|
|
173
|
-
value: "location"
|
|
174
|
-
}
|
|
175
|
-
],
|
|
176
|
-
}
|
|
177
|
-
```
|
|
179
|
+
**Props**
|
|
178
180
|
|
|
179
|
-
|
|
180
|
-
`
|
|
181
|
-
|
|
181
|
+
- `columns`: The list of columns/fields that needs to be represented in the filters pane.
|
|
182
|
+
- `entity`: The entity associated with the segments.
|
|
183
|
+
- `setIsPaneOpen`: To trigger the isOpen state of the filters pane.
|
|
184
|
+
- `defaultSegmentName`: The name of segment which results all entities without applying any filter. Default name is "All results".
|
|
182
185
|
|
|
183
|
-
|
|
186
|
+
The "columns" prop must be same as that passed to the `Filters` component.
|
|
184
187
|
|
|
185
|
-
|
|
188
|
+
**Usage**
|
|
189
|
+
```jsx
|
|
190
|
+
import React, { useMemo, useState } from "react";
|
|
186
191
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
2. **onChange**: To specify the callback function that is triggered whenever a
|
|
190
|
-
filter is applied or cleared. This function will get the updated filters as
|
|
191
|
-
argument.
|
|
192
|
-
3. **setIsPaneOpen**: To trigger the isOpen state.
|
|
193
|
-
4. **className**: To specify classes to the Bar component.
|
|
194
|
-
5. **keyword**: To specify the props related to searching.
|
|
195
|
-
6. **onSelectorsChange**: To specify the callback function that is triggered
|
|
196
|
-
whenever a selector value is changed. This function will get the updated
|
|
197
|
-
selectors as argument.
|
|
198
|
-
7. **childrenKeys** The list of keys which has to be cleared from url during
|
|
199
|
-
clear filters operation.
|
|
200
|
-
8. **entity**: The entity associated with the filters.
|
|
201
|
-
9. **defaultSegmentName**: The name of segment which results all entities
|
|
202
|
-
without applying any filter. Default name is "All results".
|
|
192
|
+
import MenuBar from "neetomolecules/MenuBar";
|
|
193
|
+
import SubHeader from "neetomolecules/SubHeader";
|
|
203
194
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
passed to the component.
|
|
195
|
+
import { Segments, buildFilterColumns } from "neetoFilters";
|
|
196
|
+
import useUsers from "hooks/useUsers";
|
|
207
197
|
|
|
208
|
-
|
|
198
|
+
const App = () => {
|
|
199
|
+
const { usersData } = useUsers();
|
|
200
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
201
|
+
const [showMenuBar, setShowMenuBar] = useState(false);
|
|
202
|
+
const [fields, setFields] = useState([]);
|
|
209
203
|
|
|
210
|
-
|
|
204
|
+
const filterColumns = useMemo(
|
|
205
|
+
() =>
|
|
206
|
+
buildFilterColumns({
|
|
207
|
+
names: usersData.names,
|
|
208
|
+
emails: usersData.emails,
|
|
209
|
+
fields,
|
|
210
|
+
}),
|
|
211
|
+
[usersData.users, fields]
|
|
212
|
+
);
|
|
211
213
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
214
|
+
return (
|
|
215
|
+
<MenuBar showMenu={showMenuBar}>
|
|
216
|
+
<Segments
|
|
217
|
+
columns={filterColumns}
|
|
218
|
+
entity="User"
|
|
219
|
+
setIsFilterPaneOpen={setIsOpen}
|
|
220
|
+
/>
|
|
221
|
+
</MenuBar>
|
|
218
222
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
+
);
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
export default App;
|
|
227
|
+
```
|
|
223
228
|
|
|
224
|
-
|
|
229
|
+
### Funtions
|
|
230
|
+
#### 1. `buildFiltersFromURL` ([source code](https://github.com/bigbinary/neeto-filters-nano/blob/472fc52c3358a822bdb7d1a9d6fe7eed6335247a/app/javascript/src/components/utils.js#L403-#L406))
|
|
225
231
|
|
|
226
232
|
- This function takes a list as argument.
|
|
227
233
|
- This list should contains all the filter columns/fields and the value passed
|
|
228
234
|
to `keyword` prop of `Filters` and `Bar`.
|
|
229
235
|
- It builds the filter payload from the URL search params. This function should
|
|
230
236
|
be called for initializing the `filters` state.
|
|
237
|
+
- Usage in [neetoTrail](https://github.com/bigbinary/neeto-trail-web/blob/91b58802bbb5f9520d2d2f9a621b6a31358d49aa/app/javascript/src/hooks/common/useFilter.js#L22).
|
|
231
238
|
|
|
232
239
|
```js
|
|
233
240
|
const [filters, setFilters] = useState(() =>
|
|
@@ -235,7 +242,7 @@ const [filters, setFilters] = useState(() =>
|
|
|
235
242
|
);
|
|
236
243
|
```
|
|
237
244
|
|
|
238
|
-
####
|
|
245
|
+
#### 2. `buildSelectorsFromURL` ([source code](https://github.com/bigbinary/neeto-filters-nano/blob/472fc52c3358a822bdb7d1a9d6fe7eed6335247a/app/javascript/src/components/utils.js#L408-L423))
|
|
239
246
|
|
|
240
247
|
- By `selectors` we mean the filter fields which doesn't have any relation
|
|
241
248
|
(`node`) to a DB table column.
|
|
@@ -251,6 +258,7 @@ const [filters, setFilters] = useState(() =>
|
|
|
251
258
|
should be called for initializing the `selectors` state.
|
|
252
259
|
- `selectors` will be an object with keys same as provided in filter fields and
|
|
253
260
|
selected value as its value.
|
|
261
|
+
- Usage in [neetoMonitor](https://github.com/bigbinary/neeto-monitor-web/blob/f892ccdb9c72db8ae4b9bba5fee135c45968a750/app/javascript/src/hooks/common/useFilter.js#L27-L29).
|
|
254
262
|
|
|
255
263
|
```js
|
|
256
264
|
const [selectors, setSelectors] = useState(() =>
|
|
@@ -258,7 +266,7 @@ const [selectors, setSelectors] = useState(() =>
|
|
|
258
266
|
);
|
|
259
267
|
```
|
|
260
268
|
|
|
261
|
-
####
|
|
269
|
+
#### 3. `buildFilterColumnsFromFields` ([source code](https://github.com/bigbinary/neeto-filters-nano/blob/472fc52c3358a822bdb7d1a9d6fe7eed6335247a/app/javascript/src/components/utils.js#L550-#L579))
|
|
262
270
|
|
|
263
271
|
The `buildFilterColumnsFromFields` function is used to generate an array of
|
|
264
272
|
filter columns based on the provided fields (often referred as custom fields)
|
|
@@ -273,6 +281,7 @@ and selected field names.
|
|
|
273
281
|
to show the rule selector for each filter or not. It is `false` by default.
|
|
274
282
|
- `groupName` (string, optional): A name to be given to the group of filters
|
|
275
283
|
built from fields.
|
|
284
|
+
- Usage in [neetoTestify](https://github.com/bigbinary/neeto-testify-web/blob/1de65b93c9455a88511c5c261b474bd23d9af8e2/app/javascript/src/utils/index.js#L131).
|
|
276
285
|
|
|
277
286
|
```js
|
|
278
287
|
const fields = [
|
|
@@ -292,83 +301,12 @@ const fields = [
|
|
|
292
301
|
const selectedFields = ["name", "age"];
|
|
293
302
|
|
|
294
303
|
const filterColumns = buildFilterColumnsFromFields({ fields, selectedFields });
|
|
295
|
-
```
|
|
296
|
-
|
|
297
|
-
## neeto-filters-engine
|
|
298
|
-
|
|
299
|
-
neeto_filters is a Ruby gem that manages filters across neeto products. It
|
|
300
|
-
allows the users to filter entities with respect to its columns, associated
|
|
301
|
-
columns, or custom attributes. It is best used along with the
|
|
302
|
-
[neeto-filters-frontend](https://github.com/bigbinary/neeto-filters-frontend)
|
|
303
|
-
npm package.
|
|
304
|
-
|
|
305
|
-
### Installation
|
|
306
|
-
|
|
307
|
-
1. Add the following line to your application's Gemfile:
|
|
308
|
-
|
|
309
|
-
```zsh
|
|
310
|
-
gem "neeto-filters-engine", git: "https://github.com/bigbinary/neeto-filters-engine", branch: "stable"
|
|
311
|
-
```
|
|
312
|
-
|
|
313
|
-
2. Execute the following command:
|
|
314
|
-
|
|
315
|
-
```zsh
|
|
316
|
-
bundle install
|
|
317
|
-
```
|
|
318
|
-
|
|
319
|
-
3. Add the following line to `config/routes.rb` file to mount the engine at
|
|
320
|
-
`/neeto_filters` route.
|
|
321
|
-
|
|
322
|
-
```ruby
|
|
323
|
-
mount NeetoFiltersEngine::Engine, at: "/neeto_filters"
|
|
324
|
-
```
|
|
325
|
-
|
|
326
|
-
4. Add the following line to `models/organization.rb` file.
|
|
327
304
|
|
|
328
|
-
```ruby
|
|
329
|
-
has_many :segments, class_name: "NeetoFiltersEngine::Segment", dependent: :destroy
|
|
330
305
|
```
|
|
306
|
+
## Basic Usage
|
|
331
307
|
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
segments.
|
|
335
|
-
|
|
336
|
-
```zsh
|
|
337
|
-
rails g neeto_filters_engine:install
|
|
338
|
-
```
|
|
339
|
-
|
|
340
|
-
#### Verify that the installation is successful.
|
|
341
|
-
|
|
342
|
-
- Assume that there is a `users` table with the `User` model associated with it.
|
|
343
|
-
It a `email` column of type `string` or `text`.
|
|
344
|
-
- Open Rails console and add the following lines:
|
|
345
|
-
|
|
346
|
-
```ruby
|
|
347
|
-
filters = [
|
|
348
|
-
{
|
|
349
|
-
"conditions": [
|
|
350
|
-
{
|
|
351
|
-
"node": "email",
|
|
352
|
-
"label": "Email Address",
|
|
353
|
-
"type": "text",
|
|
354
|
-
"rule": "contains",
|
|
355
|
-
"value": "example",
|
|
356
|
-
"conditions_join_type": "AND"
|
|
357
|
-
},
|
|
358
|
-
],
|
|
359
|
-
"group_join_type": "OR"
|
|
360
|
-
},
|
|
361
|
-
]
|
|
362
|
-
|
|
363
|
-
User.all.apply_neeto_filters(filters)
|
|
364
|
-
```
|
|
365
|
-
|
|
366
|
-
- If the above lines returns zero or more users, the installation is successful.
|
|
367
|
-
|
|
368
|
-
### Usage
|
|
369
|
-
|
|
370
|
-
Here is an example of how to use the `neeto-filters-engine` gem assuming that
|
|
371
|
-
the `users` table has been created.
|
|
308
|
+
Here is an example of how to use the `neeto-filters-engine` gem assuming that the
|
|
309
|
+
`users` table has been created.
|
|
372
310
|
|
|
373
311
|
```rb
|
|
374
312
|
class HomeController < ApplicationController
|
|
@@ -387,9 +325,7 @@ class HomeController < ApplicationController
|
|
|
387
325
|
end
|
|
388
326
|
```
|
|
389
327
|
|
|
390
|
-
Note: If you wish to use `select()` method after calling
|
|
391
|
-
`apply_neeto_filters()`, please note to use `reselect()` since neeto-filters
|
|
392
|
-
itself performs a 'select' operation internally.
|
|
328
|
+
Note: If you wish to use `select()` method after calling `apply_neeto_filters()`, please note to use `reselect()` since neeto-filters itself performs a 'select' operation internally.
|
|
393
329
|
|
|
394
330
|
Here, the param `filters` is a hash with the following structure, where each
|
|
395
331
|
`node` corresponds to a column in the `users` table.
|
|
@@ -437,9 +373,9 @@ The gem filters the users based on the conditions in the `filters` param. In
|
|
|
437
373
|
this case, all the users whose email address contains `bigbinary` in the
|
|
438
374
|
`Asia/Kolkata` timezone or whose age is greater than 18 will be filtered.
|
|
439
375
|
|
|
440
|
-
|
|
376
|
+
## How It Works
|
|
441
377
|
|
|
442
|
-
|
|
378
|
+
### Base Types
|
|
443
379
|
|
|
444
380
|
- Base Types refers to the columns that are directly present in the table on
|
|
445
381
|
which the `apply_neeto_filters` method is called.
|
|
@@ -447,34 +383,34 @@ this case, all the users whose email address contains `bigbinary` in the
|
|
|
447
383
|
|
|
448
384
|
https://vimeo.com/724478910/e349e361bd
|
|
449
385
|
|
|
450
|
-
|
|
386
|
+
### Custom Types
|
|
451
387
|
|
|
452
388
|
- Some projects will have custom attributes to the tables that will be added or
|
|
453
|
-
updated dynamically. `NeetoFiltersEngine` can handle these attributes by
|
|
454
|
-
|
|
389
|
+
updated dynamically. `NeetoFiltersEngine` can handle these attributes by passing the
|
|
390
|
+
proper filters to the `apply_neeto_filters` method.
|
|
455
391
|
- The implementation of custom attributes is different for different projects.
|
|
456
392
|
`NeetoFiltersEngine` is built in the same way as `neetoCRM`. If the custom
|
|
457
393
|
attributes feature needs to be added to a project where the custom attributes
|
|
458
394
|
implementation is different, you need to override the
|
|
459
|
-
`NeetoFiltersEngine::Custom::BaseSearchService` class specifiying the proper
|
|
460
|
-
|
|
395
|
+
`NeetoFiltersEngine::Custom::BaseSearchService` class specifiying the proper join
|
|
396
|
+
operations.
|
|
461
397
|
- Refer to the below video for an overview of the same.
|
|
462
398
|
|
|
463
399
|
https://vimeo.com/724489868/94dfc6cd43
|
|
464
400
|
|
|
465
|
-
|
|
401
|
+
### Associated Types
|
|
466
402
|
|
|
467
403
|
- Associated types refer to the the columns that are not directly present in the
|
|
468
404
|
table on which the `apply_neeto_filters` method is applied. Instead these will
|
|
469
405
|
be present in another table to which the first table has a foreign key to. For
|
|
470
406
|
instance, the `deals` table can have an association with the `companies` table
|
|
471
|
-
and the company name can be displayed in the UI. `NeetoFiltersEngine` can be
|
|
472
|
-
|
|
407
|
+
and the company name can be displayed in the UI. `NeetoFiltersEngine` can be used to
|
|
408
|
+
filter these columns by properly specifying the filters.
|
|
473
409
|
- Refer to te below video for an overview of the same.
|
|
474
410
|
|
|
475
411
|
https://vimeo.com/724484259/f305257f37
|
|
476
412
|
|
|
477
|
-
|
|
413
|
+
### Adding a new type
|
|
478
414
|
|
|
479
415
|
- `NeetoFiltersEngine` provides the following types: `text`, `number`,
|
|
480
416
|
`single_option`, `multi_option`, `date`, `time`, `datetime`, `date_range`, and
|
|
@@ -489,17 +425,13 @@ this case, all the users whose email address contains `bigbinary` in the
|
|
|
489
425
|
|
|
490
426
|
https://vimeo.com/724499299/09e2231780
|
|
491
427
|
|
|
492
|
-
|
|
428
|
+
### Working with Dates
|
|
493
429
|
|
|
494
430
|
- Working with dates is tricky due to the involvement of timezones.
|
|
495
431
|
- Refer to the below video for a quick overview of the same.
|
|
496
432
|
|
|
497
433
|
https://vimeo.com/724495909/034668f738
|
|
498
434
|
|
|
499
|
-
## Integrations
|
|
500
435
|
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
| neeto-chat-web | /admin/contacts |
|
|
504
|
-
| neeto-crm-web | /deals, /contacts, /companies, /tasks, /mails |
|
|
505
|
-
| neeto-cal-web | /meetings, /scheduled-meetings |
|
|
436
|
+
# Instructions for Publishing
|
|
437
|
+
Consult the [building and releasing packages](https://neeto-engineering.neetokb.com/articles/building-and-releasing-packages) guide for details on how to publish.
|
package/dist/index.cjs.js
CHANGED
|
@@ -3294,7 +3294,7 @@ var Pane = function Pane(_ref) {
|
|
|
3294
3294
|
}, isSearchable && /*#__PURE__*/React__default["default"].createElement(Search__default["default"], {
|
|
3295
3295
|
"data-cy": "neeto-filters-column-search",
|
|
3296
3296
|
placeholder: t("neetoFilters.messages.searchResources", {
|
|
3297
|
-
resources: t("neetoFilters.common.filters")
|
|
3297
|
+
resources: t("neetoFilters.common.filters")
|
|
3298
3298
|
}),
|
|
3299
3299
|
onSearch: function onSearch(value) {
|
|
3300
3300
|
return setSearchTerm(value);
|
|
@@ -3326,6 +3326,7 @@ var Pane = function Pane(_ref) {
|
|
|
3326
3326
|
return /*#__PURE__*/React__default["default"].createElement(Item, {
|
|
3327
3327
|
column: column,
|
|
3328
3328
|
filters: filters,
|
|
3329
|
+
onClose: onClose,
|
|
3329
3330
|
autoFocus: column.key === isOpen,
|
|
3330
3331
|
key: column.key,
|
|
3331
3332
|
onChange: handleChange
|
|
@@ -3334,7 +3335,7 @@ var Pane = function Pane(_ref) {
|
|
|
3334
3335
|
})), ramda.isEmpty(ungroupedColumns) && ramda.isEmpty(groupedColumns) && /*#__PURE__*/React__default["default"].createElement(neetoui.Typography, {
|
|
3335
3336
|
style: "body2"
|
|
3336
3337
|
}, t("neetoFilters.messages.noResourcesFound", {
|
|
3337
|
-
resources: t("neetoFilters.common.columns")
|
|
3338
|
+
resources: t("neetoFilters.common.columns")
|
|
3338
3339
|
})), children), /*#__PURE__*/React__default["default"].createElement(Slider.Footer, {
|
|
3339
3340
|
className: "neeto-filters-pane-filter__footer"
|
|
3340
3341
|
}, /*#__PURE__*/React__default["default"].createElement("div", null, /*#__PURE__*/React__default["default"].createElement(neetoui.Button, {
|