Skip to content

Commit

Permalink
initial version
Browse files Browse the repository at this point in the history
  • Loading branch information
ylasri committed Aug 20, 2020
1 parent 444ef90 commit 7defd98
Show file tree
Hide file tree
Showing 25 changed files with 63,703 additions and 2 deletions.
12 changes: 12 additions & 0 deletions .kibana-plugin-helpers.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"buildSourcePatterns": [
"package.json",
"yarn.lock",
"tsconfig.json",
"{public,server,common,translations,target}/**/*",
"kibana.json",
".i18nrc.json",
"config.ts",
"README.md"
]
}
17 changes: 15 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,15 @@
# kibana_cohort
Custom Cohort Visualization based on Kibana NP
## Description

From [Wikipedia](https://en.wikipedia.org/wiki/Cohort_analysis):

> Cohort analysis is a subset of behavioral analytics that takes the data from a given dataset (e.g. an eCommerce platform, web application, or online game) and rather than looking at all users as one unit, it breaks them into related groups for analysis. These related groups, or cohorts, usually share common characteristics or experiences within a defined time-span. Cohort analysis allows a company to “see patterns clearly across the life-cycle of a customer (or user), rather than slicing across all customers blindly without accounting for the natural cycle that a customer undergoes.
## Usage

- The **total** metric is the value that determine y-axis. Can be either a count or a sum. It also possible to use the percentual as y value just marking the option `Show percetual values`.
- The **cohort date** bucket is the date used to draw the chart lines. Each bucket is a line in this chart. It should be a date histogram.
- The **cohort period** bucket is the "cohort" itself that determine the x-axis. It should be a numeric histogram.

## Install

In Progress
83 changes: 83 additions & 0 deletions README_VizDev.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# Developing Visualizations

[Source](https://kobelb.github.io/kibana-rbac-docs/development-visualize-index.html)

Kibana Visualizations are the easiest way to add additional functionality to Kibana. This part of documentation is split into two parts. The first part tells you all you need to know on how to embed existing Kibana Visualizations in your plugin. The second step explains how to create your own custom visualization.

## Visualization Factory

Use the `VisualizationsSetup` to create a new visualization. The creation-methods create a new visualization tied to the underlying rendering technology.

```ts
public setup(
{ visualizations }: MyPluginSetupDependencies
) {
visualizations.createBaseVisualization(.createBaseVisualization({
name: 'my_new_vis',
title: 'My New Vis',
icon: 'my_icon',
description: 'Cool new chart',
category: CATEGORY.OTHER
...
}););
}
```

The list of common parameters:

- name: unique visualization name, only lowercase letters and underscore
- title: title of your visualization as displayed in kibana
- icon: the icon class to use (font awesome)
- image: instead of icon you can provide svg image (imported)
- description: description of your visualization as shown in kibana
- category: the category your visualization falls into (one of ui/vis/vis_category values)
- visConfig: object holding visualization parameters
- visConfig.defaults: object holding default visualization configuration
- visualization: A constructor function for a Visualization.
- requestHandler: <string> one of the available request handlers or a <function> for a custom request handler
- responseHandler: <string> one of the available response handlers or a <function> for a custom response handler
- editor: <string> one of the available editors or Editor class for custom one
- editorConfig: object holding editor parameters
- options.showTimePicker: <bool> show or hide time picker (defaults to true)
- options.showQueryBar: <bool> show or hide query bar (defaults to true)
- options.showFilterBar: <bool> show or hide filter bar (defaults to true)
- options.showIndexSelection: <bool> show or hide index selection (defaults to true)
- stage: <string> Set this to "experimental" or "labs" to mark your visualization as experimental. Labs visualizations can also be disabled from the advanced settings. (defaults to "production")
- feedbackMessage: <string> You can provide a message (which can contain HTML), that will be appended to the experimental notification in visualize, if your visualization is experimental or in lab mode.

Each of the factories have some of the custom parameters, which will be described below.

# Base Visualization Type

The base visualization type does not make any assumptions about the rendering technology you are going to use and works with pure JavaScript. It is the visualization type we recommend to use.

You need to provide a type with a constructor function, a render method which will be called every time options or data change, and a destroy method which will be called to cleanup.

The render function receives the data object and status object which tells what actually changed. Render function needs to return a promise, which should be resolved once the visualization is done rendering.

The status object provides information about changes since the previous render call. Due to performance reasons you need to opt-in for each status change, that you want to be informed about by Kibana. This is done by using the requiresUpdateStatus key in your visualization registration object. You pass it an array, that contains all the status updates you want to receive. By default none of it will be calculated.

The following snippet shows explain all available status updates. You should only activate those changes, that you actually use in your render method.

# React Visualization Type
React visualization type assumes you are using React as your rendering technology. Just pass in a React component to visConfig.template.

The visualization will receive `vis`, `visParams`, `config` and `visData` as props. It also has a `renderComplete` property, which needs to be called once the rendering has completed.

```ts
import { MyReactVizComponent } from './my_react_component';
public setup(
{ visualizations }: MyPluginSetupDependencies
) {
visualizations.createBaseVisualization(.createBaseVisualization({
name: 'my_new_vis',
title: 'My New Vis',
icon: 'my_icon',
description: 'Cool new chart',
category: CATEGORY.OTHER,
visConfig: {
template: MyReactVizComponent
}
}););
}
```
26 changes: 26 additions & 0 deletions config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import { schema, TypeOf } from '@kbn/config-schema';

export const configSchema = schema.object({
enabled: schema.boolean({ defaultValue: true }),
});

export type ConfigSchema = TypeOf<typeof configSchema>;
8 changes: 8 additions & 0 deletions kibana.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"id": "kibanaCohort",
"version": "0.0.1",
"kibanaVersion": "kibana",
"ui": true,
"server": true,
"requiredPlugins": ["expressions", "visualizations", "data", "charts", "kibanaUtils", "kibanaReact"]
}
42 changes: 42 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"name": "kibana_cohort",
"version": "0.0.1",
"description": "Cohort Analysis",
"private": true,
"author": "Yassine LASRI <yassine.lasri@synapticiel.co>",
"license": "MIT",
"contributors": [],
"kibana": {
"version": "kibana",
"templateVersion": "1.0.0"
},
"repository": {
"type": "git",
"url": "https://github.com/synapticielfactory/kibana_cohort.git"
},
"keywords": [
"cohort",
"kibana",
"plugin",
"visualization",
"churn",
"retention"
],
"homepage": "https://github.com/synapticielfactory/kibana_cohort",
"bugs": {
"url": "https://github.com/synapticielfactory/kibana_cohort/issues"
},
"scripts": {
"preinstall": "node ../../preinstall_check",
"kbn": "node ../../scripts/kbn",
"es": "node ../../scripts/es",
"lint": "eslint .",
"start": "plugin-helpers start",
"test:server": "plugin-helpers test:server",
"test:browser": "plugin-helpers test:browser",
"build": "plugin-helpers build"
},
"devDependencies": {
"@kbn/plugin-helpers": "link:../../packages/kbn-plugin-helpers"
}
}
81 changes: 81 additions & 0 deletions public/cohort_vis_options.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import React, { useCallback, Fragment } from 'react';
import { EuiCheckbox, EuiFlexItem, EuiIconTip, EuiFlexGroup } from '@elastic/eui';
import { VisOptionsProps } from '../../../src/plugins/vis_default_editor/public';
import { CohortVisParams } from './types';

function CohortOptionsParams({ stateParams, setValue }: VisOptionsProps<CohortVisParams>) {
const onChangePercentual = useCallback(
(value: CohortVisParams['percentual']) => setValue('percentual', value),
[setValue]
);

const onChangeInverse = useCallback(
(value: CohortVisParams['inverse']) => setValue('inverse', value),
[setValue]
);

const onChangeCumulative = useCallback(
(value: CohortVisParams['cumulative']) => setValue('cumulative', value),
[setValue]
);

const onChangeTable = useCallback((value: CohortVisParams['table']) => setValue('table', value), [
setValue,
]);
return (
<Fragment>
<EuiFlexGroup alignItems="center" gutterSize="s" responsive={false}>
<EuiFlexItem grow={false}>
<EuiCheckbox
id="percentual"
label="Show percentual values"
checked={stateParams.percentual}
onChange={({ target: { checked } }) => onChangePercentual(Boolean(checked))}
/>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiIconTip content="Show % values" position="right" />
</EuiFlexItem>
</EuiFlexGroup>
<EuiCheckbox
id="inverse"
label="Show inverse values"
checked={stateParams.inverse}
onChange={({ target: { checked } }) => onChangeInverse(Boolean(checked))}
/>
<EuiCheckbox
id="cumulative"
label="Show cumulative values"
checked={stateParams.cumulative}
onChange={({ target: { checked } }) => onChangeCumulative(Boolean(checked))}
/>
<EuiCheckbox
id="table"
label="Show values as table"
checked={stateParams.table}
onChange={({ target: { checked } }) => onChangeTable(Boolean(checked))}
/>
</Fragment>
);
}

export { CohortOptionsParams };
106 changes: 106 additions & 0 deletions public/cohort_vis_type.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import React from 'react';
import { KibanaContextProvider } from '../../../src/plugins/kibana_react/public';
import { CohortVisComponentWraper } from './components/cohort_visualization';
import { CohortOptionsParams } from './cohort_vis_options';
import { Schemas } from '../../../src/plugins/vis_default_editor/public';
import { AggGroupNames } from '../../../src/plugins/data/public';
import { CohortPluginSetupDependencies } from './plugin';
import { CohortVisComponentProp } from './types';

export function getCohortVisDefinition(deps: CohortPluginSetupDependencies) {
return {
name: 'cohort',
title: 'Cohort',
icon: 'wrench',
description: 'Cohort Analysis Visualization',
visConfig: {
defaults: {
percentual: true, // Show percentual values
inverse: false, // Show inverse values
cumulative: false, // Show cumulative values
table: true, // Show values as table
mapColors: 'heatmap', // Show heatmap colors
},
// Main component controller to render the Viz
component: (props: CohortVisComponentProp) => (
<KibanaContextProvider services={{ ...deps }}>
<CohortVisComponentWraper {...props} />
</KibanaContextProvider>
),
},
editorConfig: {
optionsTemplate: CohortOptionsParams,
// Data Schema for Metrics & Buckets
schemas: new Schemas([
{
group: AggGroupNames.Metrics,
name: 'metric',
title: 'Metrics',
max: 1, // Remove this if you require more metrics
min: 1,
aggFilter: ['count', 'sum', 'avg', 'cardinality'],
defaults: [{ type: 'count', schema: 'metric' }],
},
{
group: AggGroupNames.Buckets,
name: 'cohort_date',
title: 'Cohort Date',
min: 1,
max: 1,
aggFilter: ['date_histogram', 'terms'],
defaults: [
{
type: 'date_histogram',
schema: 'cohort_date',
params: {
interval: 'M',
orderBy: '_term',
},
},
],
},
{
group: AggGroupNames.Buckets,
name: 'cohort_period',
title: 'Cohort Period',
min: 1,
max: 1,
aggFilter: ['histogram'],
defaults: [
{
type: 'histogram',
schema: 'cohort_period',
params: {
interval: 30,
},
},
],
},
]),
},
stage: 'experimental',
requestHandler: 'courier',
responseHandler: 'none',
hierarchicalData: true,
enableAutoApply: true,
};
}
Loading

0 comments on commit 7defd98

Please sign in to comment.