Skip to content

Commit

Permalink
Migrate to react (#67)
Browse files Browse the repository at this point in the history
* add new plugin template with create-plugin

* implement ConfigEditor

* use config props in the datasource

* fix wrong value for tenantOrgId

* make Input required

* add Bitmovin logo

* implements the testDatasource method

* add useEffect to automatically set the url

* adds comment for useEffect

* improves ErrorMessage

* implements the query method with DataFrame transformation

* extracts data transforming into own functions and improves code readability

* extracts data transformation of table data and simple time series data into own functions

* improves java doc and comments

* adds unit tests for dataUtils and adds error and edge case handling

* changes query parameter

* trigger tests on every branch push

* Revert "trigger tests on every branch push"

This reverts commit c03c5b2.

* implements PR feedback

* lint

* extract groupedTimeSeriesTimestamps with zip instead of map to align code

* simplify QueryInterval type and move it to intervalUtils file

* delete unused QueriIntervals

* Feat/AN-4043 setup ci on every push (#62)

* trigger ci pipeline on every push

* move github folder to root folder

* Run go to grafana folder action as first action

* add default working directory

* add directory to uses option

* try sparse-checkout option

* try path option

* try path option for node setup

* add default working-directory

* use sparse-checkout with cone-mode false

* use sparse-checkout with cone-mode false

* adds github ref

* list repository structure

* add default repository

* delete list structure

* add go to folder

* delete go to folder

* add cache dependency path

* update docker-compose.yaml

* Add TODOs

* fixes is_compatible workflow

* deletes partial repo checkout

* deletes partial repo checkout

* fix linting

* Feat/AN-4041 implement license and interval selection (#64)

* implements license fetching and interval selection

* add tests for intervalUtils

* fix ceiling of timestamp for DAY interval

* add tests

* fix linting

* delete unnecessary export of enum

* rename MyQuery to BitmovinAnalyticsDataQuery

* add AnalyticsLicenseType

* Feat/AN-4106 implement aggregation selection (#65)

* implements license fetching and interval selection

* add tests for intervalUtils

* fix ceiling of timestamp for DAY interval

* add tests

* fix linting

* delete unnecessary export of enum

* implement metric selection

* Feat/AN-4107 implement dimension selection (#66)

* implement dimension selection

* fix linting errors

* add metric support

* add metric to query and check for null instead of undefined

* fix merge commit

* Feat/AN-4110 implement group by selection (#68)

* implements license fetching and interval selection

* add tests for intervalUtils

* fix ceiling of timestamp for DAY interval

* add tests

* fix linting

* delete unnecessary export of enum

* implement metric selection

* implement dimension selection

* fix linting errors

* add metric support

* add metric to query and check for null instead of undefined

* implements groupBy selection

* fix linting

* implements reordering of GroupBys and fixes position of Add Button

* make props readonly

* Feat/AN-4112 implement order by selection (#69)

* implements license fetching and interval selection

* add tests for intervalUtils

* fix ceiling of timestamp for DAY interval

* add tests

* fix linting

* delete unnecessary export of enum

* implement metric selection

* implement dimension selection

* fix linting errors

* add metric support

* add metric to query and check for null instead of undefined

* implements groupBy selection

* fix linting

* implements reordering of GroupBys and fixes position of Add Button

* make props readonly

* implements order By selection

* splits orderBy state into two seperate states to fix rendering and renames variables

* lint

* Feat/AN-4111 implement filter selection (#70)

* add queryFilter type and renames AnalyticsDataQuery and AnalyticsRequestQuery type

* implements filter selection

* implements labels for filter selection fields

* corrects wrong label for add order by and filter selection

* corrects wrong label for delete tooltip

* add AddFilter button and Filter validation

* lint

* do not set value if value isEmpty for GroupBy and OrderBy Input

* fix deleteFilterInput to use the converted values instead of rawValues

* deletes reordering of FilterInputs

* refactors FilterRow to use one Filter object as local state

* add tests for filterUtils

* implement PR Feedback

* Feat/AN-4118 implement limit selection (#71)

* add limit selection

* add radix parameter for parseInt function

* lint

* Feat/AN-4121 implement aliasby selection (#72)

* implement alias By selection

* rename onChange Methods to handle...

* add Default values for query editor (#73)

* move and rename typings

* improve code readability

* Feat/AN-4135 pass query parameters to components (#74)

* make GroupByRow controlled

* make OrderByRow controlled

* make FilterByRow controlled

* make simple selection controlled

* fix groupBy types

* fix interval default value bug

* rename filterRow prop

* delete TODOs

* split useEffect and useMemo for isMetricSelected

* lint

* refactor FilterRow and QueryEditor to hold UI related Row data as local state

* implement PR feedback

* add unit tests for mapQueryFilterValueToRawFilterValue

* Feat/AN-4127 update readme (#75)

* make GroupByRow controlled

* make OrderByRow controlled

* make FilterByRow controlled

* make simple selection controlled

* fix groupBy types

* fix interval default value bug

* rename filterRow prop

* delete TODOs

* split useEffect and useMemo for isMetricSelected

* lint

* update Readme

* delete TODOS and add example_dashboard

* reorders sections

* set defaultValue and not value top be able to change the limit and alisBy field

* Add Warning QueryResultMetaNotice to data frame produced by datasource.ts, when rowCount is higher/equal 200

* feature/AN-3212/AN-4161_change-the-add-filter-icon-in-query-editor (#77)

* Rewrite FilterInput.tsx to QueryFilterInput.tsx

- remove label arg from util convertFilterForAds, convertFilter, because we dont need that dep there

* - remove obsolete `disable` prop

* add Tooltips for QueryFilterInputSelects

---------

Co-authored-by: MGJamJam <myriam.gantner@gmail.com>

* Replace enums with const array of string (aggregations, metrics, query (ad) attributes, query filter operators) (#79)

* Feat/AN-4128 make new data query compatible with old example dashboard json (#78)

* adapt license, metric, dimension, filter and alias to work with old query type

* add migration for filters and table/timeseries options

* lint

* lint

* add type predicates for OldBitmovinAnalyticsDataQuery

* implement percentile input

* renames percentile to percentileValue

* separates metric, query aggregations and query attributes

* change metric values to lower case

* makes filter, dimension, metric and limit compatible with old JSON

* rename QueryFilter types

* Feat/AN-4160 update example dashboard (#80)

* delete filtering of attributes for already used attributes and add error_code to null filter

* update example_dashboard

* delete files related to angular plugin

* move files to root folder and delete subfolder

* add dist folder

* change gitignore to exclude dist folder

* add dist folder to eslint ignore pattern

* Fix/AN-4193 fix missing tenant id request header (#81)

* add tenant orf id to request header

* implement PR feedback

* fmt

* make plugin compatible with grafana v10.2.0

* make plugin compatible with grafana v10.1.0

* rename adAnalytics to isAdAnalytics

* update License

* update License

* filter incomplete Queries

* update changelog

* delete datasource details in example_dashboard

* update plugin description and README

---------

Co-authored-by: Peter Petraník <peter.petranik@bitmovin.com>
  • Loading branch information
MGJamJam and Svarozic authored Jul 4, 2024
1 parent e55b87c commit c9e4308
Show file tree
Hide file tree
Showing 148 changed files with 15,454 additions and 12,498 deletions.
3 changes: 3 additions & 0 deletions .config/.cprc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"version": "4.3.0"
}
25 changes: 25 additions & 0 deletions .config/.eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* ⚠️⚠️⚠️ THIS FILE WAS SCAFFOLDED BY `@grafana/create-plugin`. DO NOT EDIT THIS FILE DIRECTLY. ⚠️⚠️⚠️
*
* In order to extend the configuration follow the steps in
* https://grafana.com/developers/plugin-tools/create-a-plugin/extend-a-plugin/extend-configurations#extend-the-eslint-config
*/
{
"extends": ["@grafana/eslint-config"],
"root": true,
"rules": {
"react/prop-types": "off"
},
"overrides": [
{
"plugins": ["deprecation"],
"files": ["src/**/*.{ts,tsx}"],
"rules": {
"deprecation/deprecation": "warn"
},
"parserOptions": {
"project": "./tsconfig.json"
}
}
]
}
16 changes: 16 additions & 0 deletions .config/.prettierrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*
* ⚠️⚠️⚠️ THIS FILE WAS SCAFFOLDED BY `@grafana/create-plugin`. DO NOT EDIT THIS FILE DIRECTLY. ⚠️⚠️⚠️
*
* In order to extend the configuration follow the steps in .config/README.md
*/

module.exports = {
endOfLine: 'auto',
printWidth: 120,
trailingComma: 'es5',
semi: true,
jsxSingleQuote: false,
singleQuote: true,
useTabs: false,
tabWidth: 2,
};
47 changes: 47 additions & 0 deletions .config/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
ARG grafana_version=latest
ARG grafana_image=grafana-enterprise

FROM grafana/${grafana_image}:${grafana_version}


# Make it as simple as possible to access the grafana instance for development purposes
# Do NOT enable these settings in a public facing / production grafana instance
ENV GF_AUTH_ANONYMOUS_ORG_ROLE "Admin"
ENV GF_AUTH_ANONYMOUS_ENABLED "true"
ENV GF_AUTH_BASIC_ENABLED "false"
# Set development mode so plugins can be loaded without the need to sign
ENV GF_DEFAULT_APP_MODE "development"


LABEL maintainer="Grafana Labs <hello@grafana.com>"

ENV GF_PATHS_HOME="/usr/share/grafana"
WORKDIR $GF_PATHS_HOME

USER root


# Installing supervisor and inotify-tools
RUN if grep -i -q alpine /etc/issue; then \
apk add supervisor inotify-tools git; \
elif grep -i -q ubuntu /etc/issue; then \
DEBIAN_FRONTEND=noninteractive && \
apt-get update && \
apt-get install -y supervisor inotify-tools git && \
rm -rf /var/lib/apt/lists/*; \
else \
echo 'ERROR: Unsupported base image' && /bin/false; \
fi

COPY supervisord/supervisord.conf /etc/supervisor.d/supervisord.ini
COPY supervisord/supervisord.conf /etc/supervisor/conf.d/supervisord.conf



# Inject livereload script into grafana index.html
RUN sed -i 's|</body>|<script src="http://localhost:35729/livereload.js"></script></body>|g' /usr/share/grafana/public/views/index.html


COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
164 changes: 164 additions & 0 deletions .config/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
# Default build configuration by Grafana

**This is an auto-generated directory and is not intended to be changed! ⚠️**

The `.config/` directory holds basic configuration for the different tools
that are used to develop, test and build the project. In order to make it updates easier we ask you to
not edit files in this folder to extend configuration.

## How to extend the basic configs?

Bear in mind that you are doing it at your own risk, and that extending any of the basic configuration can lead
to issues around working with the project.

### Extending the ESLint config

Edit the `.eslintrc` file in the project root in order to extend the ESLint configuration.

**Example:**

```json
{
"extends": "./.config/.eslintrc",
"rules": {
"react/prop-types": "off"
}
}
```

---

### Extending the Prettier config

Edit the `.prettierrc.js` file in the project root in order to extend the Prettier configuration.

**Example:**

```javascript
module.exports = {
// Prettier configuration provided by Grafana scaffolding
...require('./.config/.prettierrc.js'),

semi: false,
};
```

---

### Extending the Jest config

There are two configuration in the project root that belong to Jest: `jest-setup.js` and `jest.config.js`.

**`jest-setup.js`:** A file that is run before each test file in the suite is executed. We are using it to
set up the Jest DOM for the testing library and to apply some polyfills. ([link to Jest docs](https://jestjs.io/docs/configuration#setupfilesafterenv-array))

**`jest.config.js`:** The main Jest configuration file that extends the Grafana recommended setup. ([link to Jest docs](https://jestjs.io/docs/configuration))

#### ESM errors with Jest

A common issue with the current jest config involves importing an npm package that only offers an ESM build. These packages cause jest to error with `SyntaxError: Cannot use import statement outside a module`. To work around this, we provide a list of known packages to pass to the `[transformIgnorePatterns](https://jestjs.io/docs/configuration#transformignorepatterns-arraystring)` jest configuration property. If need be, this can be extended in the following way:

```javascript
process.env.TZ = 'UTC';
const { grafanaESModules, nodeModulesToTransform } = require('./config/jest/utils');

module.exports = {
// Jest configuration provided by Grafana
...require('./.config/jest.config'),
// Inform jest to only transform specific node_module packages.
transformIgnorePatterns: [nodeModulesToTransform([...grafanaESModules, 'packageName'])],
};
```

---

### Extending the TypeScript config

Edit the `tsconfig.json` file in the project root in order to extend the TypeScript configuration.

**Example:**

```json
{
"extends": "./.config/tsconfig.json",
"compilerOptions": {
"preserveConstEnums": true
}
}
```

---

### Extending the Webpack config

Follow these steps to extend the basic Webpack configuration that lives under `.config/`:

#### 1. Create a new Webpack configuration file

Create a new config file that is going to extend the basic one provided by Grafana.
It can live in the project root, e.g. `webpack.config.ts`.

#### 2. Merge the basic config provided by Grafana and your custom setup

We are going to use [`webpack-merge`](https://github.com/survivejs/webpack-merge) for this.

```typescript
// webpack.config.ts
import type { Configuration } from 'webpack';
import { merge } from 'webpack-merge';
import grafanaConfig from './.config/webpack/webpack.config';

const config = async (env): Promise<Configuration> => {
const baseConfig = await grafanaConfig(env);

return merge(baseConfig, {
// Add custom config here...
output: {
asyncChunks: true,
},
});
};

export default config;
```

#### 3. Update the `package.json` to use the new Webpack config

We need to update the `scripts` in the `package.json` to use the extended Webpack configuration.

**Update for `build`:**

```diff
-"build": "webpack -c ./.config/webpack/webpack.config.ts --env production",
+"build": "webpack -c ./webpack.config.ts --env production",
```

**Update for `dev`:**

```diff
-"dev": "webpack -w -c ./.config/webpack/webpack.config.ts --env development",
+"dev": "webpack -w -c ./webpack.config.ts --env development",
```

### Configure grafana image to use when running docker

By default, `grafana-enterprise` will be used as the docker image for all docker related commands. If you want to override this behavior, simply alter the `docker-compose.yaml` by adding the following build arg `grafana_image`.

**Example:**

```yaml
version: '3.7'

services:
grafana:
container_name: 'myorg-basic-app'
build:
context: ./.config
args:
grafana_version: ${GRAFANA_VERSION:-9.1.2}
grafana_image: ${GRAFANA_IMAGE:-grafana}
```
In this example, we assign the environment variable `GRAFANA_IMAGE` to the build arg `grafana_image` with a default value of `grafana`. This will allow you to set the value while running the docker-compose commands, which might be convenient in some scenarios.

---
10 changes: 10 additions & 0 deletions .config/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/bin/sh

if grep -i -q alpine /etc/issue; then
exec /usr/bin/supervisord -c /etc/supervisord.conf
elif grep -i -q ubuntu /etc/issue; then
exec /usr/bin/supervisord -c /etc/supervisor/supervisord.conf
else
echo 'ERROR: Unsupported base image'
exit 1
fi
25 changes: 25 additions & 0 deletions .config/jest-setup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* ⚠️⚠️⚠️ THIS FILE WAS SCAFFOLDED BY `@grafana/create-plugin`. DO NOT EDIT THIS FILE DIRECTLY. ⚠️⚠️⚠️
*
* In order to extend the configuration follow the steps in
* https://grafana.com/developers/plugin-tools/create-a-plugin/extend-a-plugin/extend-configurations#extend-the-jest-config
*/

import '@testing-library/jest-dom';

// https://jestjs.io/docs/manual-mocks#mocking-methods-which-are-not-implemented-in-jsdom
Object.defineProperty(global, 'matchMedia', {
writable: true,
value: jest.fn().mockImplementation((query) => ({
matches: false,
media: query,
onchange: null,
addListener: jest.fn(), // deprecated
removeListener: jest.fn(), // deprecated
addEventListener: jest.fn(),
removeEventListener: jest.fn(),
dispatchEvent: jest.fn(),
})),
});

HTMLCanvasElement.prototype.getContext = () => {};
43 changes: 43 additions & 0 deletions .config/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* ⚠️⚠️⚠️ THIS FILE WAS SCAFFOLDED BY `@grafana/create-plugin`. DO NOT EDIT THIS FILE DIRECTLY. ⚠️⚠️⚠️
*
* In order to extend the configuration follow the steps in
* https://grafana.com/developers/plugin-tools/create-a-plugin/extend-a-plugin/extend-configurations#extend-the-jest-config
*/

const path = require('path');
const { grafanaESModules, nodeModulesToTransform } = require('./jest/utils');

module.exports = {
moduleNameMapper: {
'\\.(css|scss|sass)$': 'identity-obj-proxy',
'react-inlinesvg': path.resolve(__dirname, 'jest', 'mocks', 'react-inlinesvg.tsx'),
},
modulePaths: ['<rootDir>/src'],
setupFilesAfterEnv: ['<rootDir>/jest-setup.js'],
testEnvironment: 'jest-environment-jsdom',
testMatch: [
'<rootDir>/src/**/__tests__/**/*.{js,jsx,ts,tsx}',
'<rootDir>/src/**/*.{spec,test,jest}.{js,jsx,ts,tsx}',
'<rootDir>/src/**/*.{spec,test,jest}.{js,jsx,ts,tsx}',
],
transform: {
'^.+\\.(t|j)sx?$': [
'@swc/jest',
{
sourceMaps: 'inline',
jsc: {
parser: {
syntax: 'typescript',
tsx: true,
decorators: false,
dynamicImport: true,
},
},
},
],
},
// Jest will throw `Cannot use import statement outside module` if it tries to load an
// ES module without it being transformed first. ./config/README.md#esm-errors-with-jest
transformIgnorePatterns: [nodeModulesToTransform(grafanaESModules)],
};
25 changes: 25 additions & 0 deletions .config/jest/mocks/react-inlinesvg.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Due to the grafana/ui Icon component making fetch requests to
// `/public/img/icon/<icon_name>.svg` we need to mock react-inlinesvg to prevent
// the failed fetch requests from displaying errors in console.

import React from 'react';

type Callback = (...args: any[]) => void;

export interface StorageItem {
content: string;
queue: Callback[];
status: string;
}

export const cacheStore: { [key: string]: StorageItem } = Object.create(null);

const SVG_FILE_NAME_REGEX = /(.+)\/(.+)\.svg$/;

const InlineSVG = ({ src }: { src: string }) => {
// testId will be the file name without extension (e.g. `public/img/icons/angle-double-down.svg` -> `angle-double-down`)
const testId = src.replace(SVG_FILE_NAME_REGEX, '$2');
return <svg xmlns="http://www.w3.org/2000/svg" data-testid={testId} viewBox="0 0 24 24" />;
};

export default InlineSVG;
31 changes: 31 additions & 0 deletions .config/jest/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* ⚠️⚠️⚠️ THIS FILE WAS SCAFFOLDED BY `@grafana/create-plugin`. DO NOT EDIT THIS FILE DIRECTLY. ⚠️⚠️⚠️
*
* In order to extend the configuration follow the steps in .config/README.md
*/

/*
* This utility function is useful in combination with jest `transformIgnorePatterns` config
* to transform specific packages (e.g.ES modules) in a projects node_modules folder.
*/
const nodeModulesToTransform = (moduleNames) => `node_modules\/(?!.*(${moduleNames.join('|')})\/.*)`;

// Array of known nested grafana package dependencies that only bundle an ESM version
const grafanaESModules = [
'.pnpm', // Support using pnpm symlinked packages
'@grafana/schema',
'd3',
'd3-color',
'd3-force',
'd3-interpolate',
'd3-scale-chromatic',
'ol',
'react-colorful',
'rxjs',
'uuid',
];

module.exports = {
nodeModulesToTransform,
grafanaESModules,
};
Loading

0 comments on commit c9e4308

Please sign in to comment.