├── .gitattributes
├── .gitignore
├── LICENSE.txt
├── README.md
├── dashboard.png
├── new-visualization1.png
├── new-visualization2.png
└── vis_type_custom_form_filter_accounts
├── config.ts
├── kibana.json
├── package.json
└── public
├── _custom_form_filter_accounts_vis.scss
├── custom_form_filter_accounts_options.tsx
├── custom_form_filter_accounts_vis.tsx
├── custom_form_filter_accounts_vis_controller.tsx
├── custom_form_filter_icon.js
├── fetch_data.tsx
├── filter_helper.ts
├── index.scss
├── index.ts
├── plugin.ts
└── types.ts
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /releases
2 | /vis_type_custom_form_filter_accounts/target
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 |
2 | Apache License
3 | Version 2.0, January 2004
4 | http://www.apache.org/licenses/
5 |
6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7 |
8 | 1. Definitions.
9 |
10 | "License" shall mean the terms and conditions for use, reproduction,
11 | and distribution as defined by Sections 1 through 9 of this document.
12 |
13 | "Licensor" shall mean the copyright owner or entity authorized by
14 | the copyright owner that is granting the License.
15 |
16 | "Legal Entity" shall mean the union of the acting entity and all
17 | other entities that control, are controlled by, or are under common
18 | control with that entity. For the purposes of this definition,
19 | "control" means (i) the power, direct or indirect, to cause the
20 | direction or management of such entity, whether by contract or
21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 | outstanding shares, or (iii) beneficial ownership of such entity.
23 |
24 | "You" (or "Your") shall mean an individual or Legal Entity
25 | exercising permissions granted by this License.
26 |
27 | "Source" form shall mean the preferred form for making modifications,
28 | including but not limited to software source code, documentation
29 | source, and configuration files.
30 |
31 | "Object" form shall mean any form resulting from mechanical
32 | transformation or translation of a Source form, including but
33 | not limited to compiled object code, generated documentation,
34 | and conversions to other media types.
35 |
36 | "Work" shall mean the work of authorship, whether in Source or
37 | Object form, made available under the License, as indicated by a
38 | copyright notice that is included in or attached to the work
39 | (an example is provided in the Appendix below).
40 |
41 | "Derivative Works" shall mean any work, whether in Source or Object
42 | form, that is based on (or derived from) the Work and for which the
43 | editorial revisions, annotations, elaborations, or other modifications
44 | represent, as a whole, an original work of authorship. For the purposes
45 | of this License, Derivative Works shall not include works that remain
46 | separable from, or merely link (or bind by name) to the interfaces of,
47 | the Work and Derivative Works thereof.
48 |
49 | "Contribution" shall mean any work of authorship, including
50 | the original version of the Work and any modifications or additions
51 | to that Work or Derivative Works thereof, that is intentionally
52 | submitted to Licensor for inclusion in the Work by the copyright owner
53 | or by an individual or Legal Entity authorized to submit on behalf of
54 | the copyright owner. For the purposes of this definition, "submitted"
55 | means any form of electronic, verbal, or written communication sent
56 | to the Licensor or its representatives, including but not limited to
57 | communication on electronic mailing lists, source code control systems,
58 | and issue tracking systems that are managed by, or on behalf of, the
59 | Licensor for the purpose of discussing and improving the Work, but
60 | excluding communication that is conspicuously marked or otherwise
61 | designated in writing by the copyright owner as "Not a Contribution."
62 |
63 | "Contributor" shall mean Licensor and any individual or Legal Entity
64 | on behalf of whom a Contribution has been received by Licensor and
65 | subsequently incorporated within the Work.
66 |
67 | 2. Grant of Copyright License. Subject to the terms and conditions of
68 | this License, each Contributor hereby grants to You a perpetual,
69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 | copyright license to reproduce, prepare Derivative Works of,
71 | publicly display, publicly perform, sublicense, and distribute the
72 | Work and such Derivative Works in Source or Object form.
73 |
74 | 3. Grant of Patent License. Subject to the terms and conditions of
75 | this License, each Contributor hereby grants to You a perpetual,
76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 | (except as stated in this section) patent license to make, have made,
78 | use, offer to sell, sell, import, and otherwise transfer the Work,
79 | where such license applies only to those patent claims licensable
80 | by such Contributor that are necessarily infringed by their
81 | Contribution(s) alone or by combination of their Contribution(s)
82 | with the Work to which such Contribution(s) was submitted. If You
83 | institute patent litigation against any entity (including a
84 | cross-claim or counterclaim in a lawsuit) alleging that the Work
85 | or a Contribution incorporated within the Work constitutes direct
86 | or contributory patent infringement, then any patent licenses
87 | granted to You under this License for that Work shall terminate
88 | as of the date such litigation is filed.
89 |
90 | 4. Redistribution. You may reproduce and distribute copies of the
91 | Work or Derivative Works thereof in any medium, with or without
92 | modifications, and in Source or Object form, provided that You
93 | meet the following conditions:
94 |
95 | (a) You must give any other recipients of the Work or
96 | Derivative Works a copy of this License; and
97 |
98 | (b) You must cause any modified files to carry prominent notices
99 | stating that You changed the files; and
100 |
101 | (c) You must retain, in the Source form of any Derivative Works
102 | that You distribute, all copyright, patent, trademark, and
103 | attribution notices from the Source form of the Work,
104 | excluding those notices that do not pertain to any part of
105 | the Derivative Works; and
106 |
107 | (d) If the Work includes a "NOTICE" text file as part of its
108 | distribution, then any Derivative Works that You distribute must
109 | include a readable copy of the attribution notices contained
110 | within such NOTICE file, excluding those notices that do not
111 | pertain to any part of the Derivative Works, in at least one
112 | of the following places: within a NOTICE text file distributed
113 | as part of the Derivative Works; within the Source form or
114 | documentation, if provided along with the Derivative Works; or,
115 | within a display generated by the Derivative Works, if and
116 | wherever such third-party notices normally appear. The contents
117 | of the NOTICE file are for informational purposes only and
118 | do not modify the License. You may add Your own attribution
119 | notices within Derivative Works that You distribute, alongside
120 | or as an addendum to the NOTICE text from the Work, provided
121 | that such additional attribution notices cannot be construed
122 | as modifying the License.
123 |
124 | You may add Your own copyright statement to Your modifications and
125 | may provide additional or different license terms and conditions
126 | for use, reproduction, or distribution of Your modifications, or
127 | for any such Derivative Works as a whole, provided Your use,
128 | reproduction, and distribution of the Work otherwise complies with
129 | the conditions stated in this License.
130 |
131 | 5. Submission of Contributions. Unless You explicitly state otherwise,
132 | any Contribution intentionally submitted for inclusion in the Work
133 | by You to the Licensor shall be under the terms and conditions of
134 | this License, without any additional terms or conditions.
135 | Notwithstanding the above, nothing herein shall supersede or modify
136 | the terms of any separate license agreement you may have executed
137 | with Licensor regarding such Contributions.
138 |
139 | 6. Trademarks. This License does not grant permission to use the trade
140 | names, trademarks, service marks, or product names of the Licensor,
141 | except as required for reasonable and customary use in describing the
142 | origin of the Work and reproducing the content of the NOTICE file.
143 |
144 | 7. Disclaimer of Warranty. Unless required by applicable law or
145 | agreed to in writing, Licensor provides the Work (and each
146 | Contributor provides its Contributions) on an "AS IS" BASIS,
147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 | implied, including, without limitation, any warranties or conditions
149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 | PARTICULAR PURPOSE. You are solely responsible for determining the
151 | appropriateness of using or redistributing the Work and assume any
152 | risks associated with Your exercise of permissions under this License.
153 |
154 | 8. Limitation of Liability. In no event and under no legal theory,
155 | whether in tort (including negligence), contract, or otherwise,
156 | unless required by applicable law (such as deliberate and grossly
157 | negligent acts) or agreed to in writing, shall any Contributor be
158 | liable to You for damages, including any direct, indirect, special,
159 | incidental, or consequential damages of any character arising as a
160 | result of this License or out of the use or inability to use the
161 | Work (including but not limited to damages for loss of goodwill,
162 | work stoppage, computer failure or malfunction, or any and all
163 | other commercial damages or losses), even if such Contributor
164 | has been advised of the possibility of such damages.
165 |
166 | 9. Accepting Warranty or Additional Liability. While redistributing
167 | the Work or Derivative Works thereof, You may choose to offer,
168 | and charge a fee for, acceptance of support, warranty, indemnity,
169 | or other liability obligations and/or rights consistent with this
170 | License. However, in accepting such obligations, You may act only
171 | on Your own behalf and on Your sole responsibility, not on behalf
172 | of any other Contributor, and only if You agree to indemnify,
173 | defend, and hold each Contributor harmless for any liability
174 | incurred by, or claims asserted against, such Contributor by reason
175 | of your accepting any such warranty or additional liability.
176 |
177 | END OF TERMS AND CONDITIONS
178 |
179 | APPENDIX: How to apply the Apache License to your work.
180 |
181 | To apply the Apache License to your work, attach the following
182 | boilerplate notice, with the fields enclosed by brackets "[]"
183 | replaced with your own identifying information. (Don't include
184 | the brackets!) The text should be enclosed in the appropriate
185 | comment syntax for the file format. We also recommend that a
186 | file or class name and description of purpose be included on the
187 | same "printed page" as the copyright notice for easier
188 | identification within third-party archives.
189 |
190 | Copyright [yyyy] [name of copyright owner]
191 |
192 | Licensed under the Apache License, Version 2.0 (the "License");
193 | you may not use this file except in compliance with the License.
194 | You may obtain a copy of the License at
195 |
196 | http://www.apache.org/licenses/LICENSE-2.0
197 |
198 | Unless required by applicable law or agreed to in writing, software
199 | distributed under the License is distributed on an "AS IS" BASIS,
200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201 | See the License for the specific language governing permissions and
202 | limitations under the License.
203 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Kibana Plugin - Custom Form Filter Visualization
2 |
3 | This project is a simple tutorial for Kibana new comers trying to develop their own vizualisation plugin. The actual usecase of this plugin is to create a custom data input form, where fields are used to filter data used by other visualizations in the dashboard.
4 |
5 | This plugin is a demo based on the accounts data which can be downloaded from Elastic web site [here](https://download.elastic.co/demos/kibana/gettingstarted/accounts.zip). To work, the index pattern for bank data shall be called `bank*` as it is hard coded in `custom_form_filter_accounts_vis_controller.tsx`.
6 |
7 | As plugin architecture is being under heavy redesign in 7.x and documentation is rather obscure, I did my best to create something simple that works. The code is also basic, I am a JavaScript beginner!
8 |
9 | This repository is for Kibana **v7.8 (up) plugin New Platform (NP)** while [this repository](https://github.com/guyplusplus/Kibana-Plugin-Custom-Form-Filter-Visualization-Legacy) is for **v7.6.2 'legacy' architecture**.
10 |
11 | This plugin is adapted from the [vis_type_markdown](https://github.com/elastic/kibana/tree/7.8/src/plugins/vis_type_markdown) plugin.
12 |
13 | **WARNING: this plugin does not work for Kibana 7.13 up. I am not maintaining the code for the moment. Plugin structure and APIs are constantly evolving (changing) and documentation is scarce.**
14 |
15 | ## Sample Screenshots
16 |
17 | Few screen shots which makes it very easy to understand.
18 |
19 | 
20 |
21 | 
22 |
23 | 
24 |
25 | ## Creating a development environment from scratch on Ubuntu
26 |
27 | 1. Install curl and JRE
28 |
29 | ```shell
30 | $ sudo apt install curl
31 | $ sudo apt install openjdk-11-jre-headless
32 | ```
33 |
34 | 2. Install latest Kibana and ElasticSearch via apt
35 |
36 | ```shell
37 | $ wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add -
38 | $ echo "deb https://artifacts.elastic.co/packages/7.x/apt stable main" | sudo tee /etc/apt/sources.list.d/elastic.list
39 | $ sudo apt update
40 | $ sudo apt install elasticsearch
41 | $ sudo apt install kibana
42 | ```
43 |
44 | For testing purpose, it may be required to install a specific (not latest) version of Kibana or ElasticSearch.
45 |
46 | ```shell
47 | $ sudo apt install kibana [for latest version]
48 | $ sudo apt install kibana=7.8.0 [OR for a specific version]
49 | ```
50 |
51 | 3. Adjust listening IP address of Kibana if network access is required
52 |
53 | ```shell
54 | $ sudo vi /etc/kibana/kibana.yml
55 | server.host: "192.168.1.77" [update with correct IP value]
56 | ```
57 |
58 | 4. Start ElasticSearch, possibly upload the accounts test data
59 |
60 | ```shell
61 | $ sudo systemctl start elasticsearch
62 | $ curl -X GET "localhost:9200"
63 | $ curl -H 'Content-Type: application/x-ndjson' -XPOST 'localhost:9200/bank/account/_bulk?pretty' --data-binary @accounts.json [optional]
64 | ```
65 |
66 | 5. Now to create a Kibana development environment, download nvm, git client and yarn
67 |
68 | ```shell
69 | $ curl https://raw.githubusercontent.com/creationix/nvm/v0.25.0/install.sh | bash [then open a new terminal]
70 | $ nvm install 10.21.0
71 | $ sudo apt install git
72 | $ curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
73 | $ echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
74 | $ sudo apt update
75 | $ sudo apt install yarn
76 | ```
77 |
78 | 6. Download Kibana source code. After download, `kibana` is the top directory. Then select the target version by selecting a tag or a branch (v7.6.2, v7.8.0, v7.8, etc.)
79 |
80 | ```shell
81 | $ git clone https://github.com/elastic/kibana.git
82 | $ cd kibana
83 | $ git checkout v7.8.0
84 | ```
85 |
86 | 7. Copy the source code of this plugin with modified name inside the `kibana/plugins` directory
87 |
88 | 8. Start Kibana in development mode, ensuring only OSS (Open Source Software) features are used. This step may take few minutes for the first compilation
89 |
90 | ```shell
91 | $ cd kibana
92 | $ nvm use 10.21.0 [or expected version. nvm install n.n.n may be required if version is missing]
93 | $ yarn kbn bootstrap
94 | $ yarn start --oss
95 | ```
96 |
97 | 9. Kernel values adjustment for large number of file monitoring may be required
98 |
99 | ```shell
100 | $ echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf
101 | $ sudo sysctl -p
102 | ```
103 |
104 | 10. If you have a problem to start a higher version of Kibana than ElasticSearch, with the error message during development`[error][savedobjects-service] This version of Kibana (v8.0.0) is incompatible with the following Elasticsearch nodes in your cluster: v7.8.0 @ 127.0.0.1:9200 (127.0.0.1)`, add this line in `config/kibana.yml` config file. As a side note when upgrading from v7.6.2 to v7.8 branch I had to delete all indexes `curl -XDELETE localhost:9200/*`
105 |
106 | ```
107 | elasticsearch.ignoreVersionMismatch: true
108 | ```
109 |
110 | 11. When it is time to upgrade the Kibana development environment, start for a clean environment, get the latest changes from github, and switch to the new tag or release. The `kibana/plugins` directory remains untouched accross these steps. You may delete the `target` folder in each plugin folder.
111 |
112 | ```shell
113 | $ cd kibana
114 | $ git reset --hard
115 | $ git fetch
116 | $ git checkout v7.8.1
117 | ```
118 |
119 | ## Creating the actual form (step 7) for your own usecase
120 |
121 | The current plugin name is based on the accounts test data. Simply perform a search replace in filenames and in the source code, respecting letter capitalization.
122 |
123 | The form itself is contained in the [controller file](https://github.com/guyplusplus/Kibana-Plugin-Custom-Form-Filter-Visualization/blob/master/vis_type_custom_form_filter_accounts/public/custom_form_filter_accounts_vis_controller.tsx) file. An [option tab](https://github.com/guyplusplus/Kibana-Plugin-Custom-Form-Filter-Visualization/blob/master/vis_type_custom_form_filter_accounts/public/custom_form_filter_accounts_options.tsx) is also possible, actually one or more.
124 |
125 | The form code looks like this and is very simple to modify, based on EUI React components.
126 | * [EUI Documentation](https://elastic.github.io/eui/#/)
127 | * [EUI GitHub repository](https://github.com/elastic/eui)
128 |
129 | ```xml
130 |
131 |
132 | this.onFormChange(e)} value={this.state.age} />
133 |
134 |
135 | this.onFormChange(e)} value={this.state.minimumBalance} />
136 |
137 |
138 |
State
139 |
148 |
149 | Apply filter
150 | Delete filter
151 | Clear form
152 | Time: today
153 |
154 | ```
155 |
156 | I use [Microsoft Code](https://code.visualstudio.com/) to edit code and [Google Chrome](https://www.google.com/chrome/) to debug.
157 |
158 | ## Packaging the plugin as a zip file
159 |
160 | Build the zip file with the `plugin_helpers.js` script
161 |
162 | ```
163 | $ cd kibana/plugins/vis_type_custom_form_filter_accounts
164 | $ node ../../scripts/plugin_helpers.js build
165 | ? What version of Kibana are you building for? 7.10.0
166 | info deleting the build and target directories
167 | info running @kbn/optimizer
168 | │ info initialized, 0 bundles cached
169 | │ info starting worker [1 bundle]
170 | │ succ 1 bundles compiled successfully after 45 sec
171 | info copying source into the build and converting with babel
172 | info compressing plugin into [visTypeCustomFormFilterAccounts-7.10.0.zip]
173 | $
174 | ```
175 |
176 | ## Installing the plugin
177 |
178 | The plugin can then be installed like this for an apt installed Kibana.
179 |
180 | ```shell
181 | $ cd /usr/share/kibana
182 | $ sudo -u kibana ./bin/kibana-plugin install file:///home/john/downloads/vis_type_custom_form_filter_accounts_7.9.0_1.0.2.zip
183 | $ sudo -u kibana ./bin/kibana-plugin install https://github.com/guyplusplus/Kibana-Plugin-Custom-Form-Filter-Visualization/releases/download/7.9.0-1.0.2/vis_type_custom_form_filter_accounts_7.9.0_1.0.2.zip
184 | ```
185 |
186 | Deleting then installing the plugin often fails for me. I fix it by running this command.
187 |
188 | ```shell
189 | $ cd /usr/share/kibana
190 | $ sudo -u kibana ./bin/kibana-plugin remove visTypeCustomFormFilterAccounts
191 | Removing visTypeCustomFormFilterAccounts...
192 | Plugin removal complete
193 | $ sudo rm -rf /usr/share/kibana/optimize/bundles
194 | $
195 | ```
196 |
197 | ## Project TODO List
198 |
199 | - [X] Create form content (i.e. dropdown, slider) with actual data
200 | - [X] Sample code to modify time filter
201 | - [ ] Create a script to replace 'accounts' in filenames and file content
202 | - [ ] Add internationalization example
203 | - [ ] Create test script
204 | - [X] Create own plugin icon
205 | - [ ] Improve fetchData (actually Array) with a more reusable and paramerizable API
206 |
207 |
208 |
--------------------------------------------------------------------------------
/dashboard.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/guyplusplus/Kibana-Plugin-Custom-Form-Filter-Visualization/4a3e2b08026867e222885f8983e366d6a3e3d8c9/dashboard.png
--------------------------------------------------------------------------------
/new-visualization1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/guyplusplus/Kibana-Plugin-Custom-Form-Filter-Visualization/4a3e2b08026867e222885f8983e366d6a3e3d8c9/new-visualization1.png
--------------------------------------------------------------------------------
/new-visualization2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/guyplusplus/Kibana-Plugin-Custom-Form-Filter-Visualization/4a3e2b08026867e222885f8983e366d6a3e3d8c9/new-visualization2.png
--------------------------------------------------------------------------------
/vis_type_custom_form_filter_accounts/config.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to Elasticsearch B.V. under one or more contributor
3 | * license agreements. See the NOTICE file distributed with
4 | * this work for additional information regarding copyright
5 | * ownership. Elasticsearch B.V. licenses this file to you under
6 | * the Apache License, Version 2.0 (the "License"); you may
7 | * not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing,
13 | * software distributed under the License is distributed on an
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | * KIND, either express or implied. See the License for the
16 | * specific language governing permissions and limitations
17 | * under the License.
18 | */
19 |
20 | import { schema, TypeOf } from '@kbn/config-schema';
21 |
22 | export const configSchema = schema.object({
23 | enabled: schema.boolean({ defaultValue: true }),
24 | });
25 |
26 | export type ConfigSchema = TypeOf;
27 |
--------------------------------------------------------------------------------
/vis_type_custom_form_filter_accounts/kibana.json:
--------------------------------------------------------------------------------
1 | {
2 | "id": "visTypeCustomFormFilterAccounts",
3 | "version": "kibana",
4 | "ui": true,
5 | "server": false,
6 | "requiredPlugins": ["kibanaReact", "kibanaUtils", "expressions", "visualizations", "data", "visDefaultEditor"]
7 | }
8 |
--------------------------------------------------------------------------------
/vis_type_custom_form_filter_accounts/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vis_type_custom_form_filter_accounts",
3 | "version": "1.0.3",
4 | "private": true,
5 | "license": "Apache-2.0",
6 | "scripts": {
7 | "build": "yarn plugin-helpers build",
8 | "plugin-helpers": "node ../../scripts/plugin_helpers",
9 | "kbn": "node ../../scripts/kbn"
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/vis_type_custom_form_filter_accounts/public/_custom_form_filter_accounts_vis.scss:
--------------------------------------------------------------------------------
1 | .cffVis {
2 | padding: $euiSizeS;
3 | width: 100%;
4 | }
5 |
--------------------------------------------------------------------------------
/vis_type_custom_form_filter_accounts/public/custom_form_filter_accounts_options.tsx:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to Elasticsearch B.V. under one or more contributor
3 | * license agreements. See the NOTICE file distributed with
4 | * this work for additional information regarding copyright
5 | * ownership. Elasticsearch B.V. licenses this file to you under
6 | * the Apache License, Version 2.0 (the "License"); you may
7 | * not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing,
13 | * software distributed under the License is distributed on an
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | * KIND, either express or implied. See the License for the
16 | * specific language governing permissions and limitations
17 | * under the License.
18 | */
19 |
20 | import React, { useCallback } from 'react';
21 | import {
22 | EuiFieldNumber,
23 | EuiFormRow
24 | } from '@elastic/eui';
25 | import { VisOptionsProps } from '../../../src/plugins/vis_default_editor/public';
26 | import { CustomFormFilterAccountsVisParams } from './types';
27 |
28 |
29 | function CustomFormFilterAccountsOptions({ stateParams, setValue }: VisOptionsProps) {
30 |
31 | const onCustomFormFilterAccountsUpdate = useCallback(
32 | (value: CustomFormFilterAccountsVisParams['maximumBalance']) => setValue('maximumBalance', value),
33 | [setValue]
34 | );
35 |
36 | return (
37 |
38 | onCustomFormFilterAccountsUpdate(Number(value))}
41 | step={1000}
42 | />
43 |
44 | );
45 | }
46 |
47 | export { CustomFormFilterAccountsOptions };
--------------------------------------------------------------------------------
/vis_type_custom_form_filter_accounts/public/custom_form_filter_accounts_vis.tsx:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to Elasticsearch B.V. under one or more contributor
3 | * license agreements. See the NOTICE file distributed with
4 | * this work for additional information regarding copyright
5 | * ownership. Elasticsearch B.V. licenses this file to you under
6 | * the Apache License, Version 2.0 (the "License"); you may
7 | * not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing,
13 | * software distributed under the License is distributed on an
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | * KIND, either express or implied. See the License for the
16 | * specific language governing permissions and limitations
17 | * under the License.
18 | */
19 |
20 | import React from 'react';
21 | import { KibanaContextProvider } from '../../../src/plugins/kibana_react/public';
22 | import { DefaultEditorSize } from '../../../src/plugins/vis_default_editor/public';
23 | import { DataPublicPluginSetup } from '../../../src/plugins/data/public';
24 | import { ExprVis, VisParams } from '../../../src/plugins/visualizations/public';
25 | import { CustomFormFilterAccountsVisWrapper } from './custom_form_filter_accounts_vis_controller';
26 | import { CustomFormFilterAccountsOptions } from './custom_form_filter_accounts_options';
27 | import { CustomFormFilterAccountsVisDependencies } from './plugin';
28 | import { icon } from './custom_form_filter_icon';
29 |
30 | export interface CustomFormFilterAccountsVisComponentProp {
31 | vis: ExprVis;
32 | data: DataPublicPluginSetup;
33 | visParams: VisParams;
34 | }
35 |
36 | export function getCustomFormFilterAccountsVisDefinition(dependencies: CustomFormFilterAccountsVisDependencies) {
37 |
38 | return {
39 | name: 'customFormFilterAccounts',
40 | title: 'Form - Accounts',
41 | isAccessible: true,
42 | icon: icon,
43 | description: 'This sample custom visualization plugin contains a simple UI to adjust filter for accounts test data',
44 | visConfig: {
45 | defaults: {
46 | filterCounter: 0, //0=no action -1=delete all filters,1=first time to add filters with clicking 'Apply filter', then 2 onward each time this button is click
47 | age: 20,
48 | minimumBalance: null,
49 | maximumBalance: 100000,
50 | },
51 | component: (props: CustomFormFilterAccountsVisComponentProp) => (
52 |
53 |
54 |
55 | ),
56 | },
57 | editorConfig: {
58 | optionTabs: [
59 | {
60 | name: 'options',
61 | title: 'Options',
62 | editor: CustomFormFilterAccountsOptions,
63 | },
64 | ],
65 | enableAutoApply: false,
66 | defaultSize: DefaultEditorSize.LARGE,
67 | },
68 | options: {
69 | showIndexSelection: false,
70 | showTimePicker: true,
71 | showFilterBar: true,
72 | },
73 | requestHandler: 'none',
74 | responseHandler: 'none',
75 | };
76 | }
--------------------------------------------------------------------------------
/vis_type_custom_form_filter_accounts/public/custom_form_filter_accounts_vis_controller.tsx:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to Elasticsearch B.V. under one or more contributor
3 | * license agreements. See the NOTICE file distributed with
4 | * this work for additional information regarding copyright
5 | * ownership. Elasticsearch B.V. licenses this file to you under
6 | * the Apache License, Version 2.0 (the "License"); you may
7 | * not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing,
13 | * software distributed under the License is distributed on an
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | * KIND, either express or implied. See the License for the
16 | * specific language governing permissions and limitations
17 | * under the License.
18 | */
19 |
20 | import React from 'react';
21 | import {
22 | EuiButton,
23 | EuiForm,
24 | EuiFormRow,
25 | EuiFieldText,
26 | EuiSpacer,
27 | EuiText,
28 | EuiComboBox,
29 | } from '@elastic/eui';
30 | import { useKibana } from '../../../src/plugins/kibana_react/public';
31 | import { CustomFormFilterAccountsVisDependencies } from './plugin';
32 | import { CustomFormFilterAccountsVisParams } from './types';
33 | import { removeFiltersByControlledBy, stringToInt, stringToFloat } from './filter_helper';
34 | import { fetchData } from './fetch_data';
35 |
36 | const filterControlledBy = 'accountsVis';
37 |
38 | interface CustomFormFilterAccountsVisComponentProps extends CustomFormFilterAccountsVisParams {
39 | renderComplete: () => {};
40 | }
41 |
42 | interface AccountFormState {
43 | age: string,
44 | minimumBalance: string,
45 | countryStates: any,
46 | countryStateSelected: any
47 | }
48 |
49 | /**
50 | * The CustomFormFilterAccountsVisComponent renders the form.
51 | */
52 | class CustomFormFilterAccountsVisComponent extends React.Component {
53 |
54 | asyncInitStated : boolean = false;
55 | isLoading : boolean = true;
56 | state : AccountFormState;
57 |
58 | /**
59 | * Will be called after the first render when the component is present in the DOM.
60 | *
61 | * We call renderComplete here, to signal, that we are done with rendering.
62 | */
63 | componentDidMount() {
64 | this.props.renderComplete();
65 | }
66 |
67 | /**
68 | * Will be called after the component has been updated and the changes has been
69 | * flushed into the DOM.
70 | *
71 | * We will use this to signal that we are done rendering by calling the
72 | * renderComplete property.
73 | */
74 | componentDidUpdate() {
75 | this.props.renderComplete();
76 | }
77 |
78 | constructor(props: CustomFormFilterAccountsVisComponentProps) {
79 | super(props);
80 |
81 | removeFiltersByControlledBy(this.props.filterManager, filterControlledBy);
82 | const initialCountryStates = [{label: '-- All --', value: 0}];
83 | this.state = {
84 | age: "",
85 | minimumBalance: "",
86 | countryStates: initialCountryStates,
87 | countryStateSelected: [initialCountryStates[0]],
88 | };
89 | if(props.age != null)
90 | this.state.age = String(props.age);
91 | if(props.minimumBalance != null)
92 | this.state.minimumBalance = String(props.minimumBalance);
93 | }
94 |
95 | async initControls() {
96 | if(this.asyncInitStated)
97 | return;
98 | this.asyncInitStated = true;
99 | let statesArray = null;
100 | try {
101 | statesArray = await fetchData(this.props.coreSetup, "bank*", "state.keyword");
102 | statesArray.sort();
103 | }
104 | catch(error) {
105 | statesArray = null;
106 | }
107 | if(!statesArray)
108 | statesArray = [];
109 | statesArray.unshift('-- All --');
110 | let countryStates = [];
111 | for(let i = 0; i {
121 | removeFiltersByControlledBy(this.props.filterManager, filterControlledBy);
122 |
123 | const age = stringToInt(this.state.age);
124 | if(age != null) {
125 | const ageFilter = {
126 | meta: {
127 | controlledBy: filterControlledBy,
128 | alias: 'Age: ' + age,
129 | disabled: false,
130 | negate: false,
131 | },
132 | query: {
133 | match_phrase: {
134 | age: String(age)
135 | }
136 | }
137 | };
138 | this.props.filterManager.addFilters(ageFilter);
139 | }
140 |
141 | const minimumBalance = stringToFloat(this.state.minimumBalance);
142 | if(minimumBalance != null) {
143 | const minimumBalanceFilter = {
144 | meta: {
145 | controlledBy: filterControlledBy,
146 | alias: 'Min. Bal.: ' + minimumBalance,
147 | disabled: false,
148 | negate: false,
149 | },
150 | "range": {
151 | "balance": {
152 | "gte": minimumBalance,
153 | "lt": this.props.maximumBalance,
154 | }
155 | }
156 | };
157 | this.props.filterManager.addFilters(minimumBalanceFilter);
158 | }
159 |
160 | if(this.state.countryStateSelected[0].value != 0) {
161 | const stateFilter = {
162 | meta: {
163 | controlledBy: filterControlledBy,
164 | alias: 'State: ' + this.state.countryStateSelected[0].label,
165 | disabled: false,
166 | negate: false,
167 | },
168 | query: {
169 | match_phrase: {
170 | state: this.state.countryStateSelected[0].label
171 | }
172 | }
173 | };
174 | this.props.filterManager.addFilters(stateFilter);
175 | }
176 | }
177 |
178 | onClickButtonDeleteFilter = () => {
179 | removeFiltersByControlledBy(this.props.filterManager, filterControlledBy);
180 | };
181 |
182 | onClickButtonClearForm = () => {
183 | this.state.age = "";
184 | this.state.minimumBalance = "";
185 | this.state.countryStateSelected = [this.state.countryStates[0]];
186 | removeFiltersByControlledBy(this.props.filterManager, filterControlledBy);
187 | this.forceUpdate();
188 | };
189 |
190 | onClickButtonToday = () => {
191 | this.props.timefilter.setTime(
192 | {from: 'now/d', to: 'now/d'}
193 | );
194 | };
195 |
196 | onFormChange = (event) => {
197 | const target = event.target;
198 | const valueStr = target.value;
199 | const name = target.name;
200 | //there is no validation in this sample code to prevent illegal typing
201 | this.setState({
202 | [name]: valueStr
203 | });
204 | };
205 |
206 | onCountryStateChange = selectedOptions => {
207 | this.setState({
208 | ["countryStateSelected"]: selectedOptions
209 | });
210 | };
211 |
212 | /**
213 | * Render the actual HTML.
214 | */
215 | render() {
216 | this.initControls();
217 | const minimumBalanceHelpText = `Input account minimum balance (Maximum is ${this.props.maximumBalance})`;
218 | return (
219 |