From 191a985affa60f5919440a6f995fb897ec0fccfa Mon Sep 17 00:00:00 2001 From: Zalenski Egor <63463140+zalenskiSofteq@users.noreply.github.com> Date: Wed, 17 Nov 2021 20:25:57 +0300 Subject: [PATCH 1/4] updates --- LICENSE | 2 +- README.md | 171 ++++------------ docs/plugins/development.md | 182 ++++++++++++++++++ docs/plugins/installation.md | 30 +++ docs/plugins/introduction.md | 9 + electron-builder.json | 1 + redisinsight/api/README.md | 63 ++++++ .../src/exceptions/global-exception.filter.ts | 27 +++ redisinsight/api/src/main.ts | 3 +- redisinsight/main.dev.ts | 39 +++- redisinsight/splash.html | 106 ++++++++++ .../cli-search/CliSearchFilter/constants.ts | 12 ++ redisinsight/ui/src/constants/commands.ts | 3 + .../packages/clients-list-example/README.md | 34 ++++ .../clients-list-example/src/main.tsx | 1 + .../enablement-area/enablement-area.json | 18 ++ .../document-capabilities/introduction.html | 12 +- .../document-capabilities/learn-more.html | 56 ++++++ .../working-with-hashes.html | 2 +- .../working-with-json.html | 169 ++++++++++++++++ .../multiple-tags-or-search.txt | 2 +- .../combined-search-with-and.txt | 19 ++ .../combined-search-with-geo-filter.txt | 19 ++ .../combined-search-with-or.txt | 19 ++ .../working-with-json/create-json-index.txt | 24 +++ .../working-with-json/crud-create.txt | 11 ++ .../working-with-json/crud-delete.txt | 9 + .../working-with-json/crud-read.txt | 5 + .../working-with-json/crud-update.txt | 5 + .../working-with-json/exact-text-search.txt | 19 ++ .../field-specific-text-search.txt | 20 ++ .../working-with-json/fuzzy-text-search.txt | 19 ++ .../group-and-sort-by-aggregation.txt | 25 +++ .../working-with-json/index-info.txt | 5 + .../working-with-json/list-all-indexes.txt | 3 + .../multiple-tags-and-search.txt | 19 ++ .../multiple-tags-or-search.txt | 19 ++ .../working-with-json/numeric-range-query.txt | 21 ++ .../working-with-json/tag-search.txt | 19 ++ .../TableInfoResult/TableInfoResult.tsx | 1 + .../components/TableResult/TableResult.tsx | 1 + .../components/list-details/ListDetails.tsx | 16 +- .../components/Group/styles.scss | 4 + .../components/InternalLink/InternalLink.tsx | 1 + .../components/InternalLink/styles.scss | 3 + .../components/wb-view/WBView/WBView.tsx | 10 +- .../wb-view/WBView/styles.module.scss | 17 +- redisinsight/ui/src/slices/keys.ts | 8 +- redisinsight/ui/src/slices/list.ts | 2 +- redisinsight/ui/src/utils/commands.ts | 30 +-- .../ui/src/utils/tests/commands.spec.ts | 6 + tests/e2e/package.json | 2 + 52 files changed, 1148 insertions(+), 175 deletions(-) create mode 100644 docs/plugins/development.md create mode 100644 docs/plugins/installation.md create mode 100644 docs/plugins/introduction.md create mode 100644 redisinsight/api/README.md create mode 100644 redisinsight/api/src/exceptions/global-exception.filter.ts create mode 100644 redisinsight/splash.html create mode 100644 redisinsight/ui/src/packages/clients-list-example/README.md create mode 100644 redisinsight/ui/src/packages/enablement-area/guides/document-capabilities/learn-more.html create mode 100644 redisinsight/ui/src/packages/enablement-area/guides/document-capabilities/working-with-json.html create mode 100644 redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/combined-search-with-and.txt create mode 100644 redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/combined-search-with-geo-filter.txt create mode 100644 redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/combined-search-with-or.txt create mode 100644 redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/create-json-index.txt create mode 100644 redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/crud-create.txt create mode 100644 redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/crud-delete.txt create mode 100644 redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/crud-read.txt create mode 100644 redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/crud-update.txt create mode 100644 redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/exact-text-search.txt create mode 100644 redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/field-specific-text-search.txt create mode 100644 redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/fuzzy-text-search.txt create mode 100644 redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/group-and-sort-by-aggregation.txt create mode 100644 redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/index-info.txt create mode 100644 redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/list-all-indexes.txt create mode 100644 redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/multiple-tags-and-search.txt create mode 100644 redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/multiple-tags-or-search.txt create mode 100644 redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/numeric-range-query.txt create mode 100644 redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/tag-search.txt create mode 100644 redisinsight/ui/src/pages/workbench/components/enablament-area/EnablementArea/components/InternalLink/styles.scss diff --git a/LICENSE b/LICENSE index ea3921393f..7ad9b79ae5 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ - Server Side Public License +Server Side Public License VERSION 1, OCTOBER 16, 2018 Copyright © 2018 MongoDB, Inc. diff --git a/README.md b/README.md index e29400c3ee..b923b92783 100644 --- a/README.md +++ b/README.md @@ -6,32 +6,35 @@ Awesome Redis GUI written in Electron, NodeJS and React ## Directory Structure -- `redisinsight/ui` - Contains the frontend code -- `redisinsight/api` - Contains the backend code +- `redisinsight/ui` - Contains the frontend code. +- `redisinsight/api` - Contains the backend code. +- `docs` - Contains the documentation. - `scripts` - Build scripts and other build-related files - `configs` - Webpack configuration files and other build-related files -- `tests` - Contains the e2e +- `tests` - Contains the e2e and integration tests. -## Prerequisites +## Development Workflow -Make sure you have installed following packages: -* [Node](https://nodejs.org/en/download/) >=14.x and <16 -* [yarn](https://www.npmjs.com/package/yarn) >=1.21.3 - -## Installation - -Before development or build you have to install required dependencies +### Installation ```bash $ yarn install $ yarn --cwd redisinsight/api/ ``` -## Development +### Packaging the desktop app -There are 2 ways to develop: +After you have installed all dependencies you can package the app. +Run `yarn package:prod` to package app for the local platform: -### Developing using electron app +```bash +# Production +$ yarn package:prod +``` + +And packaged installer will be in the folder _release_ + +### Running the desktop app After you have installed all dependencies you can now run the app. Run `yarn start` to start an electron application that will watch and build for you. @@ -41,51 +44,32 @@ Run `yarn start` to start an electron application that will watch and build for $ yarn start ``` -### Developing using web +### Running frontend part of the app -#### Running backend part of the app - -Run `yarn --cwd redisinsight/api/ start:dev` to start a local API at `localhost:5000`. +After you have installed all dependencies you can now run the app. +Run `yarn start:web` to start a local server that will watch and build for you. ```bash # Development -$ yarn --cwd redisinsight/api/ start:dev +$ yarn start:web ``` -While the API is running, open your browser and navigate to http://localhost:5000/api/docs. You should see the Swagger UI. - -#### Running frontend part of the app +### Running backend part of the app -Run `yarn start:web` to start a local server for UI. +After you have installed all dependencies run `yarn --cwd redisinsight/api/ start:dev` to start a local API at `localhost:5000`. ```bash # Development -$ yarn start:web +$ yarn --cwd redisinsight/api/ start:dev ``` -Web interface will be available at http://localhost:8080 - -Now servers will watch for changes and automatically build for you - -## Build - -### Packaging the desktop app - -#### Building statics for enablement area and default plugins - -Run `yarn build:statics` or `yarn build:statics:win` for Windows - -After you have installed all dependencies you can package the app. -Run `yarn package:prod` to package app for the local platform: +While the API is running, open your browser and navigate to http://localhost:5000/api/docs. You should see the Swagger UI. -```bash -# Production -$ yarn package:prod -``` +### Building frontend part of the app -And packaged installer will be in the folder _./release_ +Run `yarn build:web` to build fronted to `/redisinsight/ui/dist/`. -### Create docker image +## Docker There are 2 different docker images available @@ -111,10 +95,10 @@ Example: ``` ```bash - docker run -p 5000:5000 -d --cap-add ipc_lock redisinsight + docker run -p 5006:5000 -d --cap-add ipc_lock redisinsight ``` -Then api docs and main ui should be available on http://localhost:5000/api/docs and http://localhost:5000 +Then api docs and main ui should be available on http://localhost/api/docs and http://localhost #### Build Docker with API only @@ -129,98 +113,25 @@ Example: ``` ```bash - docker run -p 5000:5000 -d --cap-add ipc_lock api.redisinsight + docker run -p 5006:5000 -d --cap-add ipc_lock api.redisinsight ``` -Then api docs and main ui should be available on http://localhost:5000/api/docs +Then api docs and main ui should be available on http://localhost/api/docs -## Tests +## Plugins documentation -### Running frontend tests +* [Introduction](docs/plugins/introduction.md) +* [Installation and Usage](docs/plugins/installation.md) +* [Plugin Development](docs/plugins/development.md) -#### Run UI unit tests +## Continuous Integration -```bash - yarn test -``` - -### Running backend tests - -#### Run backend unit tests - -```bash - # Plain tests - yarn --cwd redisinsight/api test - - # Tests with coverage - yarn --cwd redisinsight/api test:cov -``` - -### Run backend integration tests (using local server) - -```bash - # Plain tests - yarn --cwd redisinsight/api test:api - - # Tests with coverage - yarn --cwd redisinsight/api test:api:cov -``` - -> **_NOTE_**: Using `yarn test:api*` scripts you should have redis server up and running. -By default tests will look on `localhost:6379` without any auth -To customize tests configs you should run test with proper environment variables - -Example: - -If you have redis server running on a different host or port `somehost:7777` with default user pass `somepass` - -You should run test commands with such environment variables +## Related Repositories -```bash - # Plain tests - TEST_REDIS_HOST=somehost \ - TEST_REDIS_PORT=7777 \ - TEST_REDIS_PASSWORD-somepass \ - yarn --cwd redisinsight/api test:api -``` - -You can find all possible environment variable available in the [constants.ts](redisinsight/api/test/helpers/constants.ts) file - -### Run backend integration tests (using docker) - -Here you should not care about tests and local redis database configuration - -We will spin up server inside docker container and run tests over it - -```bash - # run this this command - ./redisinsight/api/test/test-runs/start-test-run.sh -r oss-st-6 -``` -- -r - is the Redis Test Environment name - -We are supporting several test environments to run tests on various Redis databases: -- **oss-st-5** - _OSS Standalone v5_ -- **oss-st-5-pass** - _OSS Standalone v5 with admin pass required_ -- **oss-st-6** - _OSS Standalone v6 and all modules_ -- **oss-st-6-tls** - _OSS Standalone v6 with TLS enabled_ -- **oss-st-6-tls-auth** - _OSS Standalone v6 with TLS auth required_ -- **oss-clu** - _OSS Cluster_ -- **oss-clu-tls** - _OSS Cluster with TLS enabled_ -- **oss-sent** - _OSS Sentinel_ -- **re-st** - _Redis Enterprise with Standalone inside_ -- **re-clu** - _Redis Enterprise with Cluster inside_ - - -### Running E2E tests - -Install E2E tests deps - -```bash - yarn --cwd tests/e2e -``` +## Running e2e tests in root tests/e2e -Run E2E tests +- To run E2E tests run command: ```bash - yarn --cwd tests/e2e test:chrome + yarn test-chrome ``` diff --git a/docs/plugins/development.md b/docs/plugins/development.md new file mode 100644 index 0000000000..dcb6024e33 --- /dev/null +++ b/docs/plugins/development.md @@ -0,0 +1,182 @@ +# Plugin development + +This document describes the guides to develop your own plugin for the RedisInsight Workbench. + +## How it works + +Plugin visualization in the Workbench is rendered using Iframe to encapsulate plugin scripts and styles, described in +the main plugin script and the stylesheet (if it has been specified in the `package.json`), +iframe includes basic styles as well. + +## Plugin structure + +Each plugin should have a unique name with all its files [loaded](installation.md) to +a separate folder inside the default `plugins` folder. + +> Default plugins are located inside the application. + +### Files +`package.json` should be located in the root folder of your plugins, all other files can be included into a subfolder. + +* **pluginName/package.json** *(required)* - Manifest of the plugin +* **pluginName/{anyName}.js** *(required)* - Core script of the plugin +* **pluginName/{anyName}.css** *(optional)* - File with styles for the plugin visualizations +* **pluginName/{anyFileOrFolder}** *(optional)* - Specify any other file or folder inside the plugin folder +to use by the core module script. *For example*: pluginName/images/image.png. + +## `package.json` structure + +This is the required manifest to use the plugin. `package.json` file should include +the following **required** fields: + + + + + + + + + + + + + + +
namePlugin name. It is recommended to use the folder name as the plugin name in the package.json.
mainRelative path to the core script of the plugin. Example: "./dist/index.js"
visualizations + Array of visualizations (objects) to visualize the results in the Workbench. +

+ Required fields in visualizations: +
    +
  • id - visualization id
  • +
  • name - visualization name to display in the Workbench
  • +
  • activationMethod - name of the exported function to call when +this visualization is selected in the Workbench
  • +
  • + matchCommands - array of commands to use the visualization for. Supports regex string. + Example: ["CLIENT LIST", "FT.*"] +
  • +
+
+ +You can specify the path to a css file in the `styles` field. If specified, +this file will be included inside the iframe plugin. + +Simple example of the `package.json` file with required and optional fields: + +```json +{ + "author": { + "name": "Redis Ltd.", + "email": "support@redis.com", + "url": "https://redis.com/redis-enterprise/redis-insight" + }, + "description": "Show client list as table", + "styles": "./dist/styles.css", + "main": "./dist/index.js", + "name": "client-list", + "version": "0.0.1", + "scripts": {}, + "visualizations": [ + { + "id": "clients-list", + "name": "Table", + "activationMethod": "renderClientsList", + "matchCommands": [ + "CLIENT LIST" + ], + "description": "Example of client list plugin", + "default": true + } + ], + "devDependencies": {}, + "dependencies": {} +} +``` + +## Core script of the plugin + +This is the required script with defined visualization methods. +The core script contains function and its export (functions - for multiple visualizations), +which is run after the relevant visualization is selected in the Workbench. + +The following function receives props of the executed commands: +```typescript +interface Props { + command: string; // executed command + data: string; // result of the executed command + status: 'success' | 'fail'; // response status of the executed command +} + +const renderVisualization = (props: Props) => { + // Do your magic +} + +export default { renderVisualization } +``` + +Each plugin iframe has basic styles of RedisInsight application, including fonts and color schemes. + +It is recommended to use the React & [Elastic UI library](https://elastic.github.io/eui/#/) for +consistency with plugin visualisations and the entire application. + +Find the example of the plugin here. + +* [Client List Plugin README](../../redisinsight/ui/src/packages/clients-list-example/README.md) +* [Client List Plugin dir](../../redisinsight/ui/src/packages/clients-list-example/) + +### Available parameters + +Additional information provided to the plugin iframe is included in the `window.state` +inside of the plugin script. + +```javascript +const { config, modules } = window.state +const { baseUrl } = config + +// modules - the list of modules of the current database +// baseUrl - url for your plugin folder - can be used to include your assets +``` + +### Plugin rendering +To render the plugin visualization, the iframe with basic html is generated which is +then populated with relevant scripts and styles. To render the html data, use existing +DOM Element `#app` or create your own DOM Elements. +Rendered iframe also includes `theme_DARK` or `theme_LIGHT` className on `body` to indicate the application theme used. + +_Javascript Example:_ +```javascript +const renderVisualization = (props) => { + const { command, data } = props; + document.getElementById('app') + .innerHTML = ` +

Executed command:

+

${command}

+

Result of the command

+

${data}

+ ` +} + +export default { renderVisualization } +``` + +_React Example:_ +```javascript +import { render } from 'react-dom' +import App from './App' + +const renderVisualization = (props) => { + const { command, status, data = '' } = props + render( + , + document.getElementById('app') + ) +} + +// This is a required action - export the main function for execution of the visualization +export default { renderVisualization } +``` + + +## Plugins communication +> **_Future updates:_** +Support of communication with the main application via a third-party library - _redisinsight-plugin-sdk_. diff --git a/docs/plugins/installation.md b/docs/plugins/installation.md new file mode 100644 index 0000000000..cff18847f4 --- /dev/null +++ b/docs/plugins/installation.md @@ -0,0 +1,30 @@ +# Plugin installation & Usage + +This document describes the guides to add `plugins` for the Workbench to RedisInsight. + +## Installation guide + +**Note**: While adding new plugins for Workbench, use files only from trusted +authors to avoid automatic execution of malicious code. + +1. Download the plugin for the Workbench. +2. Open the `plugins` folder with the following path + * For MacOs: `/.redisinsight-v2.0/plugins` + * For Windows: `C:\Users\{Username}\.redisinsight-v2.0\plugins` + * For Linux: `/.redisinsight-v2.0/plugins` +3. Add the folder with plugin to the `plugins` folder + +To see the uploaded plugin visualizations in the command results, reload the Workbench +page and run Redis command relevant for this visualization. + + +## Usage + +The plugin may contain different visualizations for any Redis commands. +Below you can find a guide to see command results in the uploaded plugin visualization: + +1. Open RedisInsight +2. Open a database added +3. Open the Workbench +4. Run the Redis command relevant for the plugin visualization +5. Select the plugin visualization to display results in (if this visualization has not been set by default) diff --git a/docs/plugins/introduction.md b/docs/plugins/introduction.md new file mode 100644 index 0000000000..d585af2ab1 --- /dev/null +++ b/docs/plugins/introduction.md @@ -0,0 +1,9 @@ +# Introduction to plugins for the Workbench + +Plugins allow the customization of visualizations for Redis commands executed +in the Workbench inside the RedisInsight. + +## Wiki + +* [Installation and Usage](installation.md) +* [Plugin Development](development.md) diff --git a/electron-builder.json b/electron-builder.json index b7b893e969..9c046951c8 100644 --- a/electron-builder.json +++ b/electron-builder.json @@ -6,6 +6,7 @@ "dist/", "node_modules/", "index.html", + "splash.html", "main.prod.js", "main.prod.js.map", "package.json" diff --git a/redisinsight/api/README.md b/redisinsight/api/README.md new file mode 100644 index 0000000000..e3e09c1b52 --- /dev/null +++ b/redisinsight/api/README.md @@ -0,0 +1,63 @@ +# RedisInsight API + +## Description +RedisInsight provides an intuitive and efficient GUI for Redis, allowing you to interact with your databases and manage your data—with built-in support for most popular Redis modules. It provides tools to analyze the memory, profile the performance of your database usage, and guide you toward better Redis usage. + +## Prerequisites + +Make sure you have installed following packages: +* [Node](https://nodejs.org/en/download/) >= 8.0 +* [npm](https://www.npmjs.com/get-npm) >= 5 + +## Dependencies used +* [NestJS](https://nestjs.com/) + +## Getting started + +### Installation + +```bash +$ yarn install +``` + +### Running the app + +```bash +# development +$ yarn start + +# watch mode +$ yarn start:dev + +# production mode +$ yarn start:prod +``` + +### Formatting + +Formatting required before submitting pull request. + +Prints the filenames of files that are different from Prettier formatting +```bash +$ yarn format +``` +### Swagger OpenApi + +The [OpenAPI](https://swagger.io/specification/) specification is a language-agnostic definition format used +to describe RESTful APIs. + +While the application is running, open your browser and navigate to `http://localhost[:]/api/docs`. +You should see the Swagger UI. + +### Test + +```bash +# unit tests +$ yarn test + +# e2e tests +$ yarn test:e2e + +# test coverage +$ yarn test:cov +``` diff --git a/redisinsight/api/src/exceptions/global-exception.filter.ts b/redisinsight/api/src/exceptions/global-exception.filter.ts new file mode 100644 index 0000000000..d43974372b --- /dev/null +++ b/redisinsight/api/src/exceptions/global-exception.filter.ts @@ -0,0 +1,27 @@ +import { BaseExceptionFilter } from '@nestjs/core'; +import { ArgumentsHost, Logger } from '@nestjs/common'; +import { Request, Response } from 'express'; + +export class GlobalExceptionFilter extends BaseExceptionFilter { + private staticServerLogger = new Logger('StaticServerLogger'); + + catch(exception: Error, host: ArgumentsHost) { + const ctx = host.switchToHttp(); + const request = ctx.getRequest(); + + if (/^\/(?:plugins|static)\//i.test(request.url)) { + const response = ctx.getResponse(); + const statusCode = exception['statusCode'] || 500; + const message = `Error when trying to fetch ${request.url}`; + + this.staticServerLogger.error(message, { ...exception } as any); + return response.status(statusCode) + .json({ + statusCode, + message, + }); + } + + return super.catch(exception, host); + } +} diff --git a/redisinsight/api/src/main.ts b/redisinsight/api/src/main.ts index ce34af83e2..13a9fa7893 100644 --- a/redisinsight/api/src/main.ts +++ b/redisinsight/api/src/main.ts @@ -3,6 +3,7 @@ import { SwaggerModule } from '@nestjs/swagger'; import { NestApplicationOptions } from '@nestjs/common'; import * as bodyParser from 'body-parser'; import { WinstonModule } from 'nest-winston'; +import { GlobalExceptionFilter } from 'src/exceptions/global-exception.filter'; import { AppModule } from './app.module'; import SWAGGER_CONFIG from '../config/swagger'; import LOGGER_CONFIG from '../config/logger'; @@ -22,7 +23,7 @@ export default async function bootstrap() { } const app = await NestFactory.create(AppModule, options); - + app.useGlobalFilters(new GlobalExceptionFilter(app.getHttpAdapter())); app.use(bodyParser.json({ limit: '512mb' })); app.use(bodyParser.urlencoded({ limit: '512mb', extended: true })); app.enableCors(); diff --git a/redisinsight/main.dev.ts b/redisinsight/main.dev.ts index 96cc4c6103..108625e1a5 100644 --- a/redisinsight/main.dev.ts +++ b/redisinsight/main.dev.ts @@ -94,7 +94,7 @@ export const getDisplayAppInTrayValue = (): boolean => { /** * Backend part... */ -const port = 5000; +const port = 5001; const launchApiServer = async () => { try { const detectPortConst = await detectPort(port); @@ -134,19 +134,35 @@ const bootstrap = async () => { export const windows = new Set(); -export const createWindow = async () => { +const titleSplash = 'splash'; +export const createSplashScreen = async () => { + const splash = new BrowserWindow({ + width: 500, + height: 200, + transparent: true, + frame: false, + resizable: false, + alwaysOnTop: true, + title: titleSplash, + }); + + splash.loadURL(`file://${__dirname}/splash.html`); + + return splash; +}; + +export const createWindow = async (splash: BrowserWindow | null) => { const RESOURCES_PATH = app.isPackaged ? path.join(process.resourcesPath, 'resources') : path.join(__dirname, '../resources'); - const getAssetPath = (...paths: string[]): string => { - return path.join(RESOURCES_PATH, ...paths); - }; + const getAssetPath = (...paths: string[]): string => path.join(RESOURCES_PATH, ...paths); let x; let y; const currentWindow = BrowserWindow.getFocusedWindow(); - if (currentWindow) { + + if (currentWindow && currentWindow?.getTitle() !== titleSplash) { const [currentWindowX, currentWindowY] = currentWindow.getPosition(); x = currentWindowX + 24; y = currentWindowY + 24; @@ -188,8 +204,9 @@ export const createWindow = async () => { if (process.env.START_MINIMIZED) { newWindow.minimize(); } else { - newWindow.show(); - newWindow.focus(); + newWindow?.show(); + newWindow?.focus(); + splash?.close(); } }); @@ -293,7 +310,11 @@ app.on('continue-activity-error', (event, type, error) => { } }); -app.whenReady().then(bootstrap).then(createWindow).catch(console.log); +app.whenReady() + .then(bootstrap) + .then(createSplashScreen) + .then(createWindow) + .catch(console.log); app.on('activate', () => { // On macOS it's common to re-create a window in the app when the diff --git a/redisinsight/splash.html b/redisinsight/splash.html new file mode 100644 index 0000000000..5763e7345a --- /dev/null +++ b/redisinsight/splash.html @@ -0,0 +1,106 @@ + + + + + + +
+
+ + + RedisInsight 2.0.2-preview © 2021 Redis Ltd. +
+
+ + + diff --git a/redisinsight/ui/src/components/cli/components/cli-search/CliSearchFilter/constants.ts b/redisinsight/ui/src/components/cli/components/cli-search/CliSearchFilter/constants.ts index 46e177974b..25dd61a1e3 100644 --- a/redisinsight/ui/src/components/cli/components/cli-search/CliSearchFilter/constants.ts +++ b/redisinsight/ui/src/components/cli/components/cli-search/CliSearchFilter/constants.ts @@ -69,4 +69,16 @@ export const FILTER_GROUP_TYPE_OPTIONS = [ text: 'JSON', value: CommandGroup.JSON, }, + { + text: 'TimeSeries', + value: CommandGroup.TimeSeries, + }, + { + text: 'Graph', + value: CommandGroup.Graph, + }, + { + text: 'AI', + value: CommandGroup.AI, + }, ] diff --git a/redisinsight/ui/src/constants/commands.ts b/redisinsight/ui/src/constants/commands.ts index 531cf7aee9..b67dfd9c6b 100644 --- a/redisinsight/ui/src/constants/commands.ts +++ b/redisinsight/ui/src/constants/commands.ts @@ -56,6 +56,9 @@ export enum CommandGroup { String = 'string', Search = 'search', JSON = 'json', + TimeSeries = 'timeseries', + Graph = 'graph', + AI = 'ai' } export enum CommandRediSearch { diff --git a/redisinsight/ui/src/packages/clients-list-example/README.md b/redisinsight/ui/src/packages/clients-list-example/README.md new file mode 100644 index 0000000000..40443ad0a0 --- /dev/null +++ b/redisinsight/ui/src/packages/clients-list-example/README.md @@ -0,0 +1,34 @@ +# Example of the plugin for the “Client List” command + +The example has been created using React, TypeScript, and [Elastic UI](https://elastic.github.io/eui/#/). +[Parcel](https://parceljs.org/) is used to build the plugin. + +## Running locally + +The following commands will install dependencies and start the server to run the plugin locally: +``` +yarn +yarn start +``` +These commands will install dependencies and start the server. + +_Note_: Base styles are included to `index.html` from the repository. + +This command will generate the `vendor` folder with styles and fonts of the core app. Add this folder +inside the folder for your plugin and include appropriate styles to the `index.html` file. + +``` +yarn build:statics - for Linux or MacOs +yarn build:statics:win - for Windows +``` + +## Build plugin + +The following commands will build plugins to be used in RedisInsight: +``` +yarn +yarn build +``` + +[Add](../../../../../docs/plugins/installation.md) the package.json file and the +`dist` folder to the folder with your plugin, which should be located in the `plugins` folder. diff --git a/redisinsight/ui/src/packages/clients-list-example/src/main.tsx b/redisinsight/ui/src/packages/clients-list-example/src/main.tsx index ff97fb6f3e..51359287e9 100644 --- a/redisinsight/ui/src/packages/clients-list-example/src/main.tsx +++ b/redisinsight/ui/src/packages/clients-list-example/src/main.tsx @@ -20,4 +20,5 @@ if (process.env.NODE_ENV === 'development') { renderClientsList({ command: '', data: response, status: 'success' }) } +// This is a required action - export the main function for execution of the visualization export default { renderClientsList } diff --git a/redisinsight/ui/src/packages/enablement-area/enablement-area.json b/redisinsight/ui/src/packages/enablement-area/enablement-area.json index 2c00feb4e3..c4582ef82e 100644 --- a/redisinsight/ui/src/packages/enablement-area/enablement-area.json +++ b/redisinsight/ui/src/packages/enablement-area/enablement-area.json @@ -33,6 +33,24 @@ "backTitle": "Document Capabilities", "path": "/static/workbench/guides/document-capabilities/working-with-hashes.html" } + }, + { + "type": "internal-link", + "id": "working-with-json", + "label": "Working with JSON", + "args": { + "backTitle": "Document Capabilities", + "path": "/static/workbench/guides/document-capabilities/working-with-json.html" + } + }, + { + "type": "internal-link", + "id": "learn-more", + "label": "Learn More", + "args": { + "backTitle": "Document Capabilities", + "path": "/static/workbench/guides/document-capabilities/learn-more.html" + } } ] } diff --git a/redisinsight/ui/src/packages/enablement-area/guides/document-capabilities/introduction.html b/redisinsight/ui/src/packages/enablement-area/guides/document-capabilities/introduction.html index 5f58e7011d..e573784324 100644 --- a/redisinsight/ui/src/packages/enablement-area/guides/document-capabilities/introduction.html +++ b/redisinsight/ui/src/packages/enablement-area/guides/document-capabilities/introduction.html @@ -3,8 +3,8 @@
In Redis, you can model documents using:
@@ -24,7 +24,7 @@
  • Supports atomic CRUD operations
  • -

    Full-text search and querying is supported for both Hashes and JSON via a secondary index.

    +

    Full-text search and querying is supported for both Hashes and JSON via a secondary index.

    A number of data types are available for indexing:
      @@ -32,7 +32,7 @@
    • Numeric range index
    • Tag index supporting multiple values
    • Geo index
    • -
    • Vector index
    • +
    • Vector index (upcoming)
    @@ -58,10 +58,10 @@

    PRE-REQUISITES

    Follow these instructions to set up the RedisJSON and RediSearch modules on Redis OSS.

    - For working with Hashes you will need Redis >=6, RediSearch >=2.0. + For working with Hashes you will need Redis >=6, RediSearch >=2.0.

    - For working with JSON you will need Redis >=6, RediSearch >=2.2 and RedisJSON >=2.0. + For working with JSON you will need Redis >=6, RediSearch >=2.2 and RedisJSON >=2.0.

    You could also create a free and ready to use instance on Redis Cloud. diff --git a/redisinsight/ui/src/packages/enablement-area/guides/document-capabilities/learn-more.html b/redisinsight/ui/src/packages/enablement-area/guides/document-capabilities/learn-more.html new file mode 100644 index 0000000000..3f527f58da --- /dev/null +++ b/redisinsight/ui/src/packages/enablement-area/guides/document-capabilities/learn-more.html @@ -0,0 +1,56 @@ + diff --git a/redisinsight/ui/src/packages/enablement-area/guides/document-capabilities/working-with-hashes.html b/redisinsight/ui/src/packages/enablement-area/guides/document-capabilities/working-with-hashes.html index 60c908492c..e82cb95d3c 100644 --- a/redisinsight/ui/src/packages/enablement-area/guides/document-capabilities/working-with-hashes.html +++ b/redisinsight/ui/src/packages/enablement-area/guides/document-capabilities/working-with-hashes.html @@ -1,6 +1,6 @@
    -

    ! Click on the button, see the command and the comments in the Workbench editor, and then run it.

    +

    Click on the button, see the command and the comments in the Workbench editor, and then run it.

    1. diff --git a/redisinsight/ui/src/packages/enablement-area/guides/document-capabilities/working-with-json.html b/redisinsight/ui/src/packages/enablement-area/guides/document-capabilities/working-with-json.html new file mode 100644 index 0000000000..3d23498dbc --- /dev/null +++ b/redisinsight/ui/src/packages/enablement-area/guides/document-capabilities/working-with-json.html @@ -0,0 +1,169 @@ +
      +
      +

      Click on the button, see the command and the comments in the Workbench editor, and then run it.

      +
        +
      1. + + CRUD operations +
        + +
        +
        + +
        +
        + +
        +
        + +
        +
        +
      2. +
      3. + + Secondary Index +
        + +
        +
        + +
        +
        + +
        +
        +
      4. +
      5. + + Search and Querying Basics +
        + +
        +
        + +
        +
        + +
        +
        + +
        +
        + +
        +
        + +
        +
        + +
        +
        + +
        +
        + +
        +
        + +
        +
        + +
        +
        +
      6. +
      +
      + +
      diff --git a/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-hashes/multiple-tags-or-search.txt b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-hashes/multiple-tags-or-search.txt index 942c0a627a..4644cc619f 100644 --- a/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-hashes/multiple-tags-or-search.txt +++ b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-hashes/multiple-tags-or-search.txt @@ -1,4 +1,4 @@ -​​// Perform a search for documents that have one of multiple tags (OR condition) +// Perform a search for documents that have one of multiple tags (OR condition) FT.SEARCH "permits" "@work_type:{construction|design}" diff --git a/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/combined-search-with-and.txt b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/combined-search-with-and.txt new file mode 100644 index 0000000000..e72baa6c0e --- /dev/null +++ b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/combined-search-with-and.txt @@ -0,0 +1,19 @@ +// Perform a combined search on two fields (AND): query for intersection of both search terms, a text search and a tag match + +FT.SEARCH "schools" "@description:girls @status:{closed}" + +// See the "schools" index schema for reference + +// FT.CREATE schools +// on JSON +// PREFIX 1 "school:" +// SCHEMA +// $.name AS name TEXT NOSTEM SORTABLE +// $.description AS description TEXT +// $.school_type AS school_type TAG SEPARATOR ";" +// $.class AS class TAG +// $.address.street AS address TEXT NOSTEM +// $.address.city AS city TAG +// $.pupils AS pupils NUMERIC SORTABLE +// $.location AS location GEO +// $.status_log.[-1] as status TAG diff --git a/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/combined-search-with-geo-filter.txt b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/combined-search-with-geo-filter.txt new file mode 100644 index 0000000000..83ec2b9109 --- /dev/null +++ b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/combined-search-with-geo-filter.txt @@ -0,0 +1,19 @@ +// Perform a fuzzy text search and filter on location in a radius distance of 10 miles + +FT.SEARCH "schools" "%%gill%%" GEOFILTER location 51.11 0.45 10 mi + +// See the "schools" index schema for reference + +// FT.CREATE schools +// on JSON +// PREFIX 1 "school:" +// SCHEMA +// $.name AS name TEXT NOSTEM SORTABLE +// $.description AS description TEXT +// $.school_type AS school_type TAG SEPARATOR ";" +// $.class AS class TAG +// $.address.street AS address TEXT NOSTEM +// $.address.city AS city TAG +// $.pupils AS pupils NUMERIC SORTABLE +// $.location AS location GEO +// $.status_log.[-1] as status TAG diff --git a/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/combined-search-with-or.txt b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/combined-search-with-or.txt new file mode 100644 index 0000000000..fa28f448e0 --- /dev/null +++ b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/combined-search-with-or.txt @@ -0,0 +1,19 @@ +// Perform a combined search on two fields (OR): query for union of both search terms. The brackets are important. + +FT.SEARCH "schools" "(@city:{Oxford})|(@description:girls)" + +// See the "schools" index schema for reference + +// FT.CREATE schools +// on JSON +// PREFIX 1 "school:" +// SCHEMA +// $.name AS name TEXT NOSTEM SORTABLE +// $.description AS description TEXT +// $.school_type AS school_type TAG SEPARATOR ";" +// $.class AS class TAG +// $.address.street AS address TEXT NOSTEM +// $.address.city AS city TAG +// $.pupils AS pupils NUMERIC SORTABLE +// $.location AS location GEO +// $.status_log.[-1] as status TAG diff --git a/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/create-json-index.txt b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/create-json-index.txt new file mode 100644 index 0000000000..aa4972fce4 --- /dev/null +++ b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/create-json-index.txt @@ -0,0 +1,24 @@ +// It is possible to index either every hash or every JSON document in the keyspace or configure indexing only for a subset of the same data type documents described by a prefix. + +// RedisJSON supports JSONPath, so we can easily access and index nested properties and array elements. +// Note that you cannot index values that contain JSON objects or JSON arrays. To be indexed, a JSONPath expression must return a single scalar value (string or number). If the JSONPath expression returns an object or an array, it will be ignored. + +// JSON Strings can only be indexed as TEXT, TAG and GEO (using the right syntax). +// JSON numbers can only be indexed as NUMERIC. +// Boolean and NULL values are ignored. + +// Command to create an index on JSON keys that are prefixed with "school:" + +FT.CREATE schools // Index name + on JSON // Indicates the type of data to index + PREFIX 1 "school:" // Tells the index which keys it should index + SCHEMA + $.name AS name TEXT NOSTEM SORTABLE // Will be indexed as a TEXT field. Will permit sorting during query. Stemming is disabled - which is ideal for proper names. + $.description AS description TEXT + $.school_type AS school_type TAG SEPARATOR ";" // For tag fields, a separator indicates how the text contained in the field is to be split into individual tags + $.class AS class TAG // Will be indexed as a tag. Will allow exact-match queries. + $.address.street AS address TEXT NOSTEM // '$.address.street' field will be indexed as TEXT and can be referred as 'street' due to the '... AS fieldname ...' construct. + $.address.city AS city TAG + $.pupils AS pupils NUMERIC SORTABLE // Will be indexed as a numeric field. Will permit sorting during query + $.location AS location GEO // Will be indexed as GEO. Will allow geographic range queries + $.status_log.[-1] as status TAG // Will index the last element of the array as "status" diff --git a/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/crud-create.txt b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/crud-create.txt new file mode 100644 index 0000000000..5904384541 --- /dev/null +++ b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/crud-create.txt @@ -0,0 +1,11 @@ +// Let's add four documents as JSON to the index. Note the format of the key names. +// Each document represents a school. + +JSON.SET school:1 . '{"name":"Hall School", "description":"Independent primary school for boys aged 5 to 11","school_type":"single;boys","class":"independent", "address":{"city":"London", "street":"Manor Street"}, "pupils":342, "location":"51.445417, -0.258352", "status_log":["new", "operating"]}' + +JSON.SET school:2 . '{"name":"Garden School", "description":"State school for boys and girls aged 5 to 18","school_type":"mixed;boys;girls","class":"state", "address":{"city":"London", "street":"Gordon Street"}, "pupils":1452, "location":"51.402926, -0.321523", "status_log":["new", "operating"]}' + +JSON.SET school:3 . '{"name":"Gillford School", "description":"Independent school for girls aged 5 to 18","school_type":"single;girls","class":"private", "address":{"city":"Goudhurst", "street":"Goudhurst"}, "pupils":721, "location":"51.112685, 0.451076", "status_log":["new", "operating", "closed"]}' + +JSON.SET school:4 . '{"name":"Old Boys School", "description":"Independent school for boys aged 5 to 18","school_type":"single;boys","class":"independent", "address":{"city":"Oxford", "street":"Trident Street"}, "pupils":1200, "location":"51.781756, -1.123196", "status_log":["new", "operating"]}' + diff --git a/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/crud-delete.txt b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/crud-delete.txt new file mode 100644 index 0000000000..68970feb23 --- /dev/null +++ b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/crud-delete.txt @@ -0,0 +1,9 @@ +JSON.GET school:1 $.pupils // Read the pupils field before deletion + +JSON.DEL school:1 $.pupils // Delete only the pupils field from the document + +JSON.GET school:1 // Read the whole document to confirm the construction_value field has been deleted + +JSON.DEL school:1 // Delete the entire document + +JSON.GET school:1 // Confirm the entire document has been deleted diff --git a/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/crud-read.txt b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/crud-read.txt new file mode 100644 index 0000000000..9af0845a6c --- /dev/null +++ b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/crud-read.txt @@ -0,0 +1,5 @@ +JSON.GET school:1 // Read the whole document + +// RedisJSON supports JSONPath, so we can easily access nested properties using $. construct + +JSON.GET school:1 $.description // Read only the field description diff --git a/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/crud-update.txt b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/crud-update.txt new file mode 100644 index 0000000000..b9cb1e0f19 --- /dev/null +++ b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/crud-update.txt @@ -0,0 +1,5 @@ +JSON.GET school:1 $.pupils // Read the pupils field before the update + +JSON.SET school:1 $.pupils 430 // Update the pupils field + +JSON.GET school:1 $.pupils // Read the pupils field after the update diff --git a/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/exact-text-search.txt b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/exact-text-search.txt new file mode 100644 index 0000000000..64d41fabeb --- /dev/null +++ b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/exact-text-search.txt @@ -0,0 +1,19 @@ +// Perform a text search on all text fields: query for documents inside which the word 'girls' occurs + +FT.SEARCH "schools" "girls" + +// See the "schools" index schema for reference + +// FT.CREATE schools +// on JSON +// PREFIX 1 "school:" +// SCHEMA +// $.name AS name TEXT NOSTEM SORTABLE +// $.description AS description TEXT +// $.school_type AS school_type TAG SEPARATOR ";" +// $.class AS class TAG +// $.address.street AS address TEXT NOSTEM +// $.address.city AS city TAG +// $.pupils AS pupils NUMERIC SORTABLE +// $.location AS location GEO +// $.status_log.[-1] as status TAG diff --git a/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/field-specific-text-search.txt b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/field-specific-text-search.txt new file mode 100644 index 0000000000..a30dae9d82 --- /dev/null +++ b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/field-specific-text-search.txt @@ -0,0 +1,20 @@ +// Perform a text search on a specific field: query for documents which have a field 'name' inside which the word 'old' occurs +// To reference a field, use @ construct + +FT.SEARCH "schools" "@name:old" + +// See the "schools" index schema for reference + +// FT.CREATE schools +// on JSON +// PREFIX 1 "school:" +// SCHEMA +// $.name AS name TEXT NOSTEM SORTABLE +// $.description AS description TEXT +// $.school_type AS school_type TAG SEPARATOR ";" +// $.class AS class TAG +// $.address.street AS address TEXT NOSTEM +// $.address.city AS city TAG +// $.pupils AS pupils NUMERIC SORTABLE +// $.location AS location GEO +// $.status_log.[-1] as status TAG diff --git a/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/fuzzy-text-search.txt b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/fuzzy-text-search.txt new file mode 100644 index 0000000000..5b3b140140 --- /dev/null +++ b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/fuzzy-text-search.txt @@ -0,0 +1,19 @@ +// Perform a Fuzzy text search on all text fields: query for documents with words similar to 'gill'. The number of % indicates the allowed Levenshtein distance. So the query would also match on 'girl' because 'gill' and 'girl' have a distance of two. + +FT.SEARCH "schools" "%%gill%%" + +// See the "schools" index schema for reference + +// FT.CREATE schools +// on JSON +// PREFIX 1 "school:" +// SCHEMA +// $.name AS name TEXT NOSTEM SORTABLE +// $.description AS description TEXT +// $.school_type AS school_type TAG SEPARATOR ";" +// $.class AS class TAG +// $.address.street AS address TEXT NOSTEM +// $.address.city AS city TAG +// $.pupils AS pupils NUMERIC SORTABLE +// $.location AS location GEO +// $.status_log.[-1] as status TAG diff --git a/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/group-and-sort-by-aggregation.txt b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/group-and-sort-by-aggregation.txt new file mode 100644 index 0000000000..80cbfa4f90 --- /dev/null +++ b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/group-and-sort-by-aggregation.txt @@ -0,0 +1,25 @@ +// Aggregations are a way to process the results of a search query, group, sort and transform them - and extract analytic insights from them. +// Aggregations are represented as the following data processing pipeline: +// Filter -> Group (Reduce) -> Apply -> Sort -> Apply + +// Perform a Group By & Sort By aggregation of your documents: display the number of permits by city and then sort the city alphabetically + +FT.AGGREGATE "schools" "*" + GROUPBY 1 @city REDUCE COUNT 0 AS nb_of_schools + SORTBY 2 @city Asc + +// See the "schools" index schema for reference + +// FT.CREATE schools +// on JSON +// PREFIX 1 "school:" +// SCHEMA +// $.name AS name TEXT NOSTEM SORTABLE +// $.description AS description TEXT +// $.school_type AS school_type TAG SEPARATOR ";" +// $.class AS class TAG +// $.address.street AS address TEXT NOSTEM +// $.address.city AS city TAG +// $.pupils AS pupils NUMERIC SORTABLE +// $.location AS location GEO +// $.status_log.[-1] as status TAG diff --git a/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/index-info.txt b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/index-info.txt new file mode 100644 index 0000000000..40ab37462a --- /dev/null +++ b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/index-info.txt @@ -0,0 +1,5 @@ +// Command to display information about a particular index. +// In this case display the information about the newly created "schools" index + +FT.INFO "schools" + diff --git a/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/list-all-indexes.txt b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/list-all-indexes.txt new file mode 100644 index 0000000000..01a7b83a5b --- /dev/null +++ b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/list-all-indexes.txt @@ -0,0 +1,3 @@ +// Command to return the list of all existing indexes + +FT._LIST diff --git a/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/multiple-tags-and-search.txt b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/multiple-tags-and-search.txt new file mode 100644 index 0000000000..f95fbbb128 --- /dev/null +++ b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/multiple-tags-and-search.txt @@ -0,0 +1,19 @@ +// Perform a search for documents that all of the tags (AND condition) + +FT.SEARCH "schools" "@school_type:{single} @school_type:{girls}" + +// See the "schools" index schema for reference + +// FT.CREATE schools +// on JSON +// PREFIX 1 "school:" +// SCHEMA +// $.name AS name TEXT NOSTEM SORTABLE +// $.description AS description TEXT +// $.school_type AS school_type TAG SEPARATOR ";" +// $.class AS class TAG +// $.address.street AS address TEXT NOSTEM +// $.address.city AS city TAG +// $.pupils AS pupils NUMERIC SORTABLE +// $.location AS location GEO +// $.status_log.[-1] as status TAG diff --git a/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/multiple-tags-or-search.txt b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/multiple-tags-or-search.txt new file mode 100644 index 0000000000..2713ed5863 --- /dev/null +++ b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/multiple-tags-or-search.txt @@ -0,0 +1,19 @@ +// Perform a search for documents that have one of multiple tags (OR condition) + +FT.SEARCH "schools" "@school_type:{single|girls}" + +// See the "schools" index schema for reference + +// FT.CREATE schools +// on JSON +// PREFIX 1 "school:" +// SCHEMA +// $.name AS name TEXT NOSTEM SORTABLE +// $.description AS description TEXT +// $.school_type AS school_type TAG SEPARATOR ";" +// $.class AS class TAG +// $.address.street AS address TEXT NOSTEM +// $.address.city AS city TAG +// $.pupils AS pupils NUMERIC SORTABLE +// $.location AS location GEO +// $.status_log.[-1] as status TAG diff --git a/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/numeric-range-query.txt b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/numeric-range-query.txt new file mode 100644 index 0000000000..91dfb9725d --- /dev/null +++ b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/numeric-range-query.txt @@ -0,0 +1,21 @@ +// Perform a numeric range query: query for every document that has a 'pupils' value between 0 and 1000 +// For numerical ranges, square brackets are inclusive of the listed values + +FT.SEARCH "schools" "@pupils:[0,1000]" + + +// See the "schools" index schema for reference + +// FT.CREATE schools +// on JSON +// PREFIX 1 "school:" +// SCHEMA +// $.name AS name TEXT NOSTEM SORTABLE +// $.description AS description TEXT +// $.school_type AS school_type TAG SEPARATOR ";" +// $.class AS class TAG +// $.address.street AS address TEXT NOSTEM +// $.address.city AS city TAG +// $.pupils AS pupils NUMERIC SORTABLE +// $.location AS location GEO +// $.status_log.[-1] as status TAG diff --git a/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/tag-search.txt b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/tag-search.txt new file mode 100644 index 0000000000..bb1abaf392 --- /dev/null +++ b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/tag-search.txt @@ -0,0 +1,19 @@ +// Perform a tag search: query for documents which have the city field set to "London". Note that we use curly braces around the tag. + +FT.SEARCH "schools" "@city:{Oxford}" + +// See the "schools" index schema for reference + +// FT.CREATE schools +// on JSON +// PREFIX 1 "school:" +// SCHEMA +// $.name AS name TEXT NOSTEM SORTABLE +// $.description AS description TEXT +// $.school_type AS school_type TAG SEPARATOR ";" +// $.class AS class TAG +// $.address.street AS address TEXT NOSTEM +// $.address.city AS city TAG +// $.pupils AS pupils NUMERIC SORTABLE +// $.location AS location GEO +// diff --git a/redisinsight/ui/src/packages/redisearch/src/components/TableInfoResult/TableInfoResult.tsx b/redisinsight/ui/src/packages/redisearch/src/components/TableInfoResult/TableInfoResult.tsx index 42a9086bd0..57d956852d 100644 --- a/redisinsight/ui/src/packages/redisearch/src/components/TableInfoResult/TableInfoResult.tsx +++ b/redisinsight/ui/src/packages/redisearch/src/components/TableInfoResult/TableInfoResult.tsx @@ -120,6 +120,7 @@ const TableInfoResult = React.memo((props: Props) => { className={cx('inMemoryTableDefault', 'tableInfo', { tableWithPagination: result?.length > 10, })} + responsive={false} data-testid={`query-table-result-${query}`} /> {Footer()} diff --git a/redisinsight/ui/src/packages/redisearch/src/components/TableResult/TableResult.tsx b/redisinsight/ui/src/packages/redisearch/src/components/TableResult/TableResult.tsx index b497a0adfa..1d115634d0 100644 --- a/redisinsight/ui/src/packages/redisearch/src/components/TableResult/TableResult.tsx +++ b/redisinsight/ui/src/packages/redisearch/src/components/TableResult/TableResult.tsx @@ -117,6 +117,7 @@ const TableResult = React.memo((props: Props) => { tableWithPagination: result?.length > 10, } )} + responsive={false} data-testid={`query-table-result-${query}`} /> )} diff --git a/redisinsight/ui/src/pages/browser/components/list-details/ListDetails.tsx b/redisinsight/ui/src/pages/browser/components/list-details/ListDetails.tsx index e6a4ab0c01..7f216c5cc2 100644 --- a/redisinsight/ui/src/pages/browser/components/list-details/ListDetails.tsx +++ b/redisinsight/ui/src/pages/browser/components/list-details/ListDetails.tsx @@ -2,7 +2,7 @@ import { EuiButtonIcon, EuiText, EuiToolTip } from '@elastic/eui' import React, { useEffect, useState } from 'react' import { useDispatch, useSelector } from 'react-redux' import cx from 'classnames' -import { isNull } from 'lodash' +import { isEqual, isNull } from 'lodash' import { SCAN_COUNT_DEFAULT } from 'uiSrc/constants/api' import { @@ -66,10 +66,16 @@ const ListDetails = (props: Props) => { }, [loadedElements]) const handleEditElement = (index = 0, editing: boolean) => { - const elems = [...elements] - elems[index].editing = editing - - setElements(elems) + const newElemsState = elements.map((item) => { + if (item.index === index) { + return { ...item, editing } + } + return item + }) + + if (!isEqual(elements, newElemsState)) { + setElements(newElemsState) + } } const handleApplyEditElement = (index = 0, element: string) => { diff --git a/redisinsight/ui/src/pages/workbench/components/enablament-area/EnablementArea/components/Group/styles.scss b/redisinsight/ui/src/pages/workbench/components/enablament-area/EnablementArea/components/Group/styles.scss index 1172ecc8c5..466d660140 100644 --- a/redisinsight/ui/src/pages/workbench/components/enablament-area/EnablementArea/components/Group/styles.scss +++ b/redisinsight/ui/src/pages/workbench/components/enablament-area/EnablementArea/components/Group/styles.scss @@ -34,6 +34,10 @@ .euiListGroupItem { button { padding: 3px 8px; + line-height: 24px; + } + .euiListGroupItem__label { + line-height: 20px; } } } diff --git a/redisinsight/ui/src/pages/workbench/components/enablament-area/EnablementArea/components/InternalLink/InternalLink.tsx b/redisinsight/ui/src/pages/workbench/components/enablament-area/EnablementArea/components/InternalLink/InternalLink.tsx index 06f32ca0dd..328c24dad4 100644 --- a/redisinsight/ui/src/pages/workbench/components/enablament-area/EnablementArea/components/InternalLink/InternalLink.tsx +++ b/redisinsight/ui/src/pages/workbench/components/enablament-area/EnablementArea/components/InternalLink/InternalLink.tsx @@ -4,6 +4,7 @@ import cx from 'classnames' import EnablementAreaContext from 'uiSrc/pages/workbench/contexts/enablementAreaContext' import styles from './styles.module.scss' +import './styles.scss' export interface Props { testId: string, diff --git a/redisinsight/ui/src/pages/workbench/components/enablament-area/EnablementArea/components/InternalLink/styles.scss b/redisinsight/ui/src/pages/workbench/components/enablament-area/EnablementArea/components/InternalLink/styles.scss new file mode 100644 index 0000000000..f1b7d39490 --- /dev/null +++ b/redisinsight/ui/src/pages/workbench/components/enablament-area/EnablementArea/components/InternalLink/styles.scss @@ -0,0 +1,3 @@ +.euiListGroupItem--xSmall .euiListGroupItem__label { + line-height: 12px; +} diff --git a/redisinsight/ui/src/pages/workbench/components/wb-view/WBView/WBView.tsx b/redisinsight/ui/src/pages/workbench/components/wb-view/WBView/WBView.tsx index b70b04bc16..504d61728c 100644 --- a/redisinsight/ui/src/pages/workbench/components/wb-view/WBView/WBView.tsx +++ b/redisinsight/ui/src/pages/workbench/components/wb-view/WBView/WBView.tsx @@ -79,7 +79,7 @@ const WBView = (props: Props) => { { isCollapsed.current = !isCollapsed.current }} @@ -92,11 +92,12 @@ const WBView = (props: Props) => { data-test-subj="resize-btn-preselects-area" /> {(EuiResizablePanel, EuiResizableButton) => ( @@ -106,6 +107,7 @@ const WBView = (props: Props) => { minSize="140px" paddingSize="none" scrollable={false} + className={styles.queryPanel} initialSize={vertical[verticalPanelIds.firstPanelId] ?? 20} style={{ minHeight: '140px' }} > @@ -129,7 +131,9 @@ const WBView = (props: Props) => { paddingSize="none" scrollable={false} initialSize={vertical[verticalPanelIds.secondPanelId] ?? 80} - className={styles.queryResults} + className={cx(styles.queryResults, styles.queryResultsPanel)} + // Fix scroll on low height - 140px (queryPanel) + style={{ maxHeight: 'calc(100% - 140px)' }} > { - state.data.elements[payload.index] = payload.element + state.data.elements[state.data.elements.length === 1 ? 0 : payload.index] = payload.element }, insertListElements: (state) => { state.loading = true diff --git a/redisinsight/ui/src/utils/commands.ts b/redisinsight/ui/src/utils/commands.ts index 1053257a98..0a9006af89 100644 --- a/redisinsight/ui/src/utils/commands.ts +++ b/redisinsight/ui/src/utils/commands.ts @@ -49,26 +49,30 @@ export const generateArgsNames = ( isEmpty ) +const getExternalCommandFormat = (commandName = '') => + commandName + .replace(/\s+/g, '_') + .replace(/[.]+/g, '') + .toLowerCase() + export const getDocUrlForCommand = ( commandName: string, commandGroup: CommandGroup | string = CommandGroup.Generic ): string => { - let commandPage = '' + let command = getExternalCommandFormat(commandName) switch (commandGroup) { case CommandGroup.Search: - commandPage = commandName - .replace(/\s+/g, '_') - .replace(/[.]+/g, '') - .toLowerCase() - return `https://oss.redis.com/redisearch/Commands/#${commandPage}` + return `https://oss.redis.com/redisearch/Commands/#${command}` case CommandGroup.JSON: - commandPage = commandName - .replace(/\s+/g, '_') - .replace(/[.]+/g, '') - .toLowerCase() - return `https://oss.redis.com/redisjson/commands/#${commandPage}` + return `https://oss.redis.com/redisjson/commands/#${command}` + case CommandGroup.TimeSeries: + return `https://oss.redis.com/redistimeseries/commands/#${command}` + case CommandGroup.Graph: + return `https://oss.redis.com/redisgraph/commands/#${command}` + case CommandGroup.AI: + return `https://oss.redis.com/redisai/commands/#${command}` default: - commandPage = commandName.replace(/\s+/g, '-').toLowerCase() - return `https://redis.io/commands/${commandPage}` + command = commandName.replace(/\s+/g, '-').toLowerCase() + return `https://redis.io/commands/${command}` } } diff --git a/redisinsight/ui/src/utils/tests/commands.spec.ts b/redisinsight/ui/src/utils/tests/commands.spec.ts index 06671e18f4..4ae9286224 100644 --- a/redisinsight/ui/src/utils/tests/commands.spec.ts +++ b/redisinsight/ui/src/utils/tests/commands.spec.ts @@ -192,6 +192,12 @@ const getDocUrlForCommandTests: any[] = [ ['JSON.GET', CommandGroup.JSON, 'https://oss.redis.com/redisjson/commands/#jsonget'], ['FT.CREATE', CommandGroup.Search, 'https://oss.redis.com/redisearch/Commands/#ftcreate'], ['FT.ALTER SCHEMA ADD', CommandGroup.Search, 'https://oss.redis.com/redisearch/Commands/#ftalter_schema_add'], + ['TS.ADD', CommandGroup.TimeSeries, 'https://oss.redis.com/redistimeseries/commands/#tsadd'], + ['TS.CREATE', CommandGroup.TimeSeries, 'https://oss.redis.com/redistimeseries/commands/#tscreate'], + ['GRAPH.EXPLAIN', CommandGroup.Graph, 'https://oss.redis.com/redisgraph/commands/#graphexplain'], + ['GRAPH.QUERY', CommandGroup.Graph, 'https://oss.redis.com/redisgraph/commands/#graphquery'], + ['AI.MODELRUN', CommandGroup.AI, 'https://oss.redis.com/redisai/commands/#aimodelrun'], + ['AI.SCRIPTDEL', CommandGroup.AI, 'https://oss.redis.com/redisai/commands/#aiscriptdel'], ['NON EXIST COMMAND', 'non-exist', 'https://redis.io/commands/non-exist-command'], ] diff --git a/tests/e2e/package.json b/tests/e2e/package.json index 6cba7ae7d5..b8ab6b5e88 100644 --- a/tests/e2e/package.json +++ b/tests/e2e/package.json @@ -7,6 +7,8 @@ "test:live": "testcafe --live chrome ", "start:api": "cross-env SERVER_STATIC_CONTENT=true yarn --cwd ../../redisinsight/api start:prod", "build:api": "yarn --cwd ../../redisinsight/api build:prod", + "build:statics": "yarn --cwd ../../ build:statics", + "build:statics:win": "yarn --cwd ../../ build:statics:win", "build:web": "yarn --cwd ../../ build:web", "redis:last": "docker run --name redis-last-version -p 7777:6379 -d redislabs/redismod", "start:app": "cross-env SERVER_STATIC_CONTENT=true yarn start:api", From 134817fb94d504ca6b0946ddd94e4fdee8c81876 Mon Sep 17 00:00:00 2001 From: Zalenski Egor <63463140+zalenskiSofteq@users.noreply.github.com> Date: Wed, 17 Nov 2021 20:38:50 +0300 Subject: [PATCH 2/4] updates --- README.md | 7 + docs/plugins/development.md | 182 ++++++++++++++++++ docs/plugins/installation.md | 30 +++ docs/plugins/introduction.md | 9 + electron-builder.json | 1 + .../src/exceptions/global-exception.filter.ts | 27 +++ redisinsight/api/src/main.ts | 3 +- redisinsight/main.dev.ts | 39 +++- redisinsight/splash.html | 106 ++++++++++ .../cli-search/CliSearchFilter/constants.ts | 12 ++ redisinsight/ui/src/constants/commands.ts | 3 + .../packages/clients-list-example/README.md | 34 ++++ .../clients-list-example/src/main.tsx | 1 + .../enablement-area/enablement-area.json | 18 ++ .../document-capabilities/introduction.html | 12 +- .../document-capabilities/learn-more.html | 56 ++++++ .../working-with-hashes.html | 2 +- .../working-with-json.html | 169 ++++++++++++++++ .../multiple-tags-or-search.txt | 2 +- .../combined-search-with-and.txt | 19 ++ .../combined-search-with-geo-filter.txt | 19 ++ .../combined-search-with-or.txt | 19 ++ .../working-with-json/create-json-index.txt | 24 +++ .../working-with-json/crud-create.txt | 11 ++ .../working-with-json/crud-delete.txt | 9 + .../working-with-json/crud-read.txt | 5 + .../working-with-json/crud-update.txt | 5 + .../working-with-json/exact-text-search.txt | 19 ++ .../field-specific-text-search.txt | 20 ++ .../working-with-json/fuzzy-text-search.txt | 19 ++ .../group-and-sort-by-aggregation.txt | 25 +++ .../working-with-json/index-info.txt | 5 + .../working-with-json/list-all-indexes.txt | 3 + .../multiple-tags-and-search.txt | 19 ++ .../multiple-tags-or-search.txt | 19 ++ .../working-with-json/numeric-range-query.txt | 21 ++ .../working-with-json/tag-search.txt | 19 ++ .../TableInfoResult/TableInfoResult.tsx | 1 + .../components/TableResult/TableResult.tsx | 1 + .../components/list-details/ListDetails.tsx | 16 +- .../components/Group/styles.scss | 4 + .../components/InternalLink/InternalLink.tsx | 1 + .../components/InternalLink/styles.scss | 3 + .../components/wb-view/WBView/WBView.tsx | 10 +- .../wb-view/WBView/styles.module.scss | 17 +- redisinsight/ui/src/slices/keys.ts | 8 +- redisinsight/ui/src/slices/list.ts | 2 +- redisinsight/ui/src/utils/commands.ts | 30 +-- .../ui/src/utils/tests/commands.spec.ts | 6 + tests/e2e/package.json | 2 + 50 files changed, 1050 insertions(+), 44 deletions(-) create mode 100644 docs/plugins/development.md create mode 100644 docs/plugins/installation.md create mode 100644 docs/plugins/introduction.md create mode 100644 redisinsight/api/src/exceptions/global-exception.filter.ts create mode 100644 redisinsight/splash.html create mode 100644 redisinsight/ui/src/packages/clients-list-example/README.md create mode 100644 redisinsight/ui/src/packages/enablement-area/guides/document-capabilities/learn-more.html create mode 100644 redisinsight/ui/src/packages/enablement-area/guides/document-capabilities/working-with-json.html create mode 100644 redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/combined-search-with-and.txt create mode 100644 redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/combined-search-with-geo-filter.txt create mode 100644 redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/combined-search-with-or.txt create mode 100644 redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/create-json-index.txt create mode 100644 redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/crud-create.txt create mode 100644 redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/crud-delete.txt create mode 100644 redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/crud-read.txt create mode 100644 redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/crud-update.txt create mode 100644 redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/exact-text-search.txt create mode 100644 redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/field-specific-text-search.txt create mode 100644 redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/fuzzy-text-search.txt create mode 100644 redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/group-and-sort-by-aggregation.txt create mode 100644 redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/index-info.txt create mode 100644 redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/list-all-indexes.txt create mode 100644 redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/multiple-tags-and-search.txt create mode 100644 redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/multiple-tags-or-search.txt create mode 100644 redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/numeric-range-query.txt create mode 100644 redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/tag-search.txt create mode 100644 redisinsight/ui/src/pages/workbench/components/enablament-area/EnablementArea/components/InternalLink/styles.scss diff --git a/README.md b/README.md index e29400c3ee..96d99a6d4b 100644 --- a/README.md +++ b/README.md @@ -8,10 +8,17 @@ Awesome Redis GUI written in Electron, NodeJS and React - `redisinsight/ui` - Contains the frontend code - `redisinsight/api` - Contains the backend code +- `docs` - Contains the documentation - `scripts` - Build scripts and other build-related files - `configs` - Webpack configuration files and other build-related files - `tests` - Contains the e2e +## Plugins documentation + +* [Introduction](docs/plugins/introduction.md) +* [Installation and Usage](docs/plugins/installation.md) +* [Plugin Development](docs/plugins/development.md) + ## Prerequisites Make sure you have installed following packages: diff --git a/docs/plugins/development.md b/docs/plugins/development.md new file mode 100644 index 0000000000..dcb6024e33 --- /dev/null +++ b/docs/plugins/development.md @@ -0,0 +1,182 @@ +# Plugin development + +This document describes the guides to develop your own plugin for the RedisInsight Workbench. + +## How it works + +Plugin visualization in the Workbench is rendered using Iframe to encapsulate plugin scripts and styles, described in +the main plugin script and the stylesheet (if it has been specified in the `package.json`), +iframe includes basic styles as well. + +## Plugin structure + +Each plugin should have a unique name with all its files [loaded](installation.md) to +a separate folder inside the default `plugins` folder. + +> Default plugins are located inside the application. + +### Files +`package.json` should be located in the root folder of your plugins, all other files can be included into a subfolder. + +* **pluginName/package.json** *(required)* - Manifest of the plugin +* **pluginName/{anyName}.js** *(required)* - Core script of the plugin +* **pluginName/{anyName}.css** *(optional)* - File with styles for the plugin visualizations +* **pluginName/{anyFileOrFolder}** *(optional)* - Specify any other file or folder inside the plugin folder +to use by the core module script. *For example*: pluginName/images/image.png. + +## `package.json` structure + +This is the required manifest to use the plugin. `package.json` file should include +the following **required** fields: + + + + + + + + + + + + + + +
      namePlugin name. It is recommended to use the folder name as the plugin name in the package.json.
      mainRelative path to the core script of the plugin. Example: "./dist/index.js"
      visualizations + Array of visualizations (objects) to visualize the results in the Workbench. +

      + Required fields in visualizations: +
        +
      • id - visualization id
      • +
      • name - visualization name to display in the Workbench
      • +
      • activationMethod - name of the exported function to call when +this visualization is selected in the Workbench
      • +
      • + matchCommands - array of commands to use the visualization for. Supports regex string. + Example: ["CLIENT LIST", "FT.*"] +
      • +
      +
      + +You can specify the path to a css file in the `styles` field. If specified, +this file will be included inside the iframe plugin. + +Simple example of the `package.json` file with required and optional fields: + +```json +{ + "author": { + "name": "Redis Ltd.", + "email": "support@redis.com", + "url": "https://redis.com/redis-enterprise/redis-insight" + }, + "description": "Show client list as table", + "styles": "./dist/styles.css", + "main": "./dist/index.js", + "name": "client-list", + "version": "0.0.1", + "scripts": {}, + "visualizations": [ + { + "id": "clients-list", + "name": "Table", + "activationMethod": "renderClientsList", + "matchCommands": [ + "CLIENT LIST" + ], + "description": "Example of client list plugin", + "default": true + } + ], + "devDependencies": {}, + "dependencies": {} +} +``` + +## Core script of the plugin + +This is the required script with defined visualization methods. +The core script contains function and its export (functions - for multiple visualizations), +which is run after the relevant visualization is selected in the Workbench. + +The following function receives props of the executed commands: +```typescript +interface Props { + command: string; // executed command + data: string; // result of the executed command + status: 'success' | 'fail'; // response status of the executed command +} + +const renderVisualization = (props: Props) => { + // Do your magic +} + +export default { renderVisualization } +``` + +Each plugin iframe has basic styles of RedisInsight application, including fonts and color schemes. + +It is recommended to use the React & [Elastic UI library](https://elastic.github.io/eui/#/) for +consistency with plugin visualisations and the entire application. + +Find the example of the plugin here. + +* [Client List Plugin README](../../redisinsight/ui/src/packages/clients-list-example/README.md) +* [Client List Plugin dir](../../redisinsight/ui/src/packages/clients-list-example/) + +### Available parameters + +Additional information provided to the plugin iframe is included in the `window.state` +inside of the plugin script. + +```javascript +const { config, modules } = window.state +const { baseUrl } = config + +// modules - the list of modules of the current database +// baseUrl - url for your plugin folder - can be used to include your assets +``` + +### Plugin rendering +To render the plugin visualization, the iframe with basic html is generated which is +then populated with relevant scripts and styles. To render the html data, use existing +DOM Element `#app` or create your own DOM Elements. +Rendered iframe also includes `theme_DARK` or `theme_LIGHT` className on `body` to indicate the application theme used. + +_Javascript Example:_ +```javascript +const renderVisualization = (props) => { + const { command, data } = props; + document.getElementById('app') + .innerHTML = ` +

      Executed command:

      +

      ${command}

      +

      Result of the command

      +

      ${data}

      + ` +} + +export default { renderVisualization } +``` + +_React Example:_ +```javascript +import { render } from 'react-dom' +import App from './App' + +const renderVisualization = (props) => { + const { command, status, data = '' } = props + render( + , + document.getElementById('app') + ) +} + +// This is a required action - export the main function for execution of the visualization +export default { renderVisualization } +``` + + +## Plugins communication +> **_Future updates:_** +Support of communication with the main application via a third-party library - _redisinsight-plugin-sdk_. diff --git a/docs/plugins/installation.md b/docs/plugins/installation.md new file mode 100644 index 0000000000..cff18847f4 --- /dev/null +++ b/docs/plugins/installation.md @@ -0,0 +1,30 @@ +# Plugin installation & Usage + +This document describes the guides to add `plugins` for the Workbench to RedisInsight. + +## Installation guide + +**Note**: While adding new plugins for Workbench, use files only from trusted +authors to avoid automatic execution of malicious code. + +1. Download the plugin for the Workbench. +2. Open the `plugins` folder with the following path + * For MacOs: `/.redisinsight-v2.0/plugins` + * For Windows: `C:\Users\{Username}\.redisinsight-v2.0\plugins` + * For Linux: `/.redisinsight-v2.0/plugins` +3. Add the folder with plugin to the `plugins` folder + +To see the uploaded plugin visualizations in the command results, reload the Workbench +page and run Redis command relevant for this visualization. + + +## Usage + +The plugin may contain different visualizations for any Redis commands. +Below you can find a guide to see command results in the uploaded plugin visualization: + +1. Open RedisInsight +2. Open a database added +3. Open the Workbench +4. Run the Redis command relevant for the plugin visualization +5. Select the plugin visualization to display results in (if this visualization has not been set by default) diff --git a/docs/plugins/introduction.md b/docs/plugins/introduction.md new file mode 100644 index 0000000000..d585af2ab1 --- /dev/null +++ b/docs/plugins/introduction.md @@ -0,0 +1,9 @@ +# Introduction to plugins for the Workbench + +Plugins allow the customization of visualizations for Redis commands executed +in the Workbench inside the RedisInsight. + +## Wiki + +* [Installation and Usage](installation.md) +* [Plugin Development](development.md) diff --git a/electron-builder.json b/electron-builder.json index b7b893e969..9c046951c8 100644 --- a/electron-builder.json +++ b/electron-builder.json @@ -6,6 +6,7 @@ "dist/", "node_modules/", "index.html", + "splash.html", "main.prod.js", "main.prod.js.map", "package.json" diff --git a/redisinsight/api/src/exceptions/global-exception.filter.ts b/redisinsight/api/src/exceptions/global-exception.filter.ts new file mode 100644 index 0000000000..d43974372b --- /dev/null +++ b/redisinsight/api/src/exceptions/global-exception.filter.ts @@ -0,0 +1,27 @@ +import { BaseExceptionFilter } from '@nestjs/core'; +import { ArgumentsHost, Logger } from '@nestjs/common'; +import { Request, Response } from 'express'; + +export class GlobalExceptionFilter extends BaseExceptionFilter { + private staticServerLogger = new Logger('StaticServerLogger'); + + catch(exception: Error, host: ArgumentsHost) { + const ctx = host.switchToHttp(); + const request = ctx.getRequest(); + + if (/^\/(?:plugins|static)\//i.test(request.url)) { + const response = ctx.getResponse(); + const statusCode = exception['statusCode'] || 500; + const message = `Error when trying to fetch ${request.url}`; + + this.staticServerLogger.error(message, { ...exception } as any); + return response.status(statusCode) + .json({ + statusCode, + message, + }); + } + + return super.catch(exception, host); + } +} diff --git a/redisinsight/api/src/main.ts b/redisinsight/api/src/main.ts index ce34af83e2..13a9fa7893 100644 --- a/redisinsight/api/src/main.ts +++ b/redisinsight/api/src/main.ts @@ -3,6 +3,7 @@ import { SwaggerModule } from '@nestjs/swagger'; import { NestApplicationOptions } from '@nestjs/common'; import * as bodyParser from 'body-parser'; import { WinstonModule } from 'nest-winston'; +import { GlobalExceptionFilter } from 'src/exceptions/global-exception.filter'; import { AppModule } from './app.module'; import SWAGGER_CONFIG from '../config/swagger'; import LOGGER_CONFIG from '../config/logger'; @@ -22,7 +23,7 @@ export default async function bootstrap() { } const app = await NestFactory.create(AppModule, options); - + app.useGlobalFilters(new GlobalExceptionFilter(app.getHttpAdapter())); app.use(bodyParser.json({ limit: '512mb' })); app.use(bodyParser.urlencoded({ limit: '512mb', extended: true })); app.enableCors(); diff --git a/redisinsight/main.dev.ts b/redisinsight/main.dev.ts index 96cc4c6103..108625e1a5 100644 --- a/redisinsight/main.dev.ts +++ b/redisinsight/main.dev.ts @@ -94,7 +94,7 @@ export const getDisplayAppInTrayValue = (): boolean => { /** * Backend part... */ -const port = 5000; +const port = 5001; const launchApiServer = async () => { try { const detectPortConst = await detectPort(port); @@ -134,19 +134,35 @@ const bootstrap = async () => { export const windows = new Set(); -export const createWindow = async () => { +const titleSplash = 'splash'; +export const createSplashScreen = async () => { + const splash = new BrowserWindow({ + width: 500, + height: 200, + transparent: true, + frame: false, + resizable: false, + alwaysOnTop: true, + title: titleSplash, + }); + + splash.loadURL(`file://${__dirname}/splash.html`); + + return splash; +}; + +export const createWindow = async (splash: BrowserWindow | null) => { const RESOURCES_PATH = app.isPackaged ? path.join(process.resourcesPath, 'resources') : path.join(__dirname, '../resources'); - const getAssetPath = (...paths: string[]): string => { - return path.join(RESOURCES_PATH, ...paths); - }; + const getAssetPath = (...paths: string[]): string => path.join(RESOURCES_PATH, ...paths); let x; let y; const currentWindow = BrowserWindow.getFocusedWindow(); - if (currentWindow) { + + if (currentWindow && currentWindow?.getTitle() !== titleSplash) { const [currentWindowX, currentWindowY] = currentWindow.getPosition(); x = currentWindowX + 24; y = currentWindowY + 24; @@ -188,8 +204,9 @@ export const createWindow = async () => { if (process.env.START_MINIMIZED) { newWindow.minimize(); } else { - newWindow.show(); - newWindow.focus(); + newWindow?.show(); + newWindow?.focus(); + splash?.close(); } }); @@ -293,7 +310,11 @@ app.on('continue-activity-error', (event, type, error) => { } }); -app.whenReady().then(bootstrap).then(createWindow).catch(console.log); +app.whenReady() + .then(bootstrap) + .then(createSplashScreen) + .then(createWindow) + .catch(console.log); app.on('activate', () => { // On macOS it's common to re-create a window in the app when the diff --git a/redisinsight/splash.html b/redisinsight/splash.html new file mode 100644 index 0000000000..5763e7345a --- /dev/null +++ b/redisinsight/splash.html @@ -0,0 +1,106 @@ + + + + + + +
      +
      + + + RedisInsight 2.0.2-preview © 2021 Redis Ltd. +
      +
      + + + diff --git a/redisinsight/ui/src/components/cli/components/cli-search/CliSearchFilter/constants.ts b/redisinsight/ui/src/components/cli/components/cli-search/CliSearchFilter/constants.ts index 46e177974b..25dd61a1e3 100644 --- a/redisinsight/ui/src/components/cli/components/cli-search/CliSearchFilter/constants.ts +++ b/redisinsight/ui/src/components/cli/components/cli-search/CliSearchFilter/constants.ts @@ -69,4 +69,16 @@ export const FILTER_GROUP_TYPE_OPTIONS = [ text: 'JSON', value: CommandGroup.JSON, }, + { + text: 'TimeSeries', + value: CommandGroup.TimeSeries, + }, + { + text: 'Graph', + value: CommandGroup.Graph, + }, + { + text: 'AI', + value: CommandGroup.AI, + }, ] diff --git a/redisinsight/ui/src/constants/commands.ts b/redisinsight/ui/src/constants/commands.ts index 531cf7aee9..b67dfd9c6b 100644 --- a/redisinsight/ui/src/constants/commands.ts +++ b/redisinsight/ui/src/constants/commands.ts @@ -56,6 +56,9 @@ export enum CommandGroup { String = 'string', Search = 'search', JSON = 'json', + TimeSeries = 'timeseries', + Graph = 'graph', + AI = 'ai' } export enum CommandRediSearch { diff --git a/redisinsight/ui/src/packages/clients-list-example/README.md b/redisinsight/ui/src/packages/clients-list-example/README.md new file mode 100644 index 0000000000..40443ad0a0 --- /dev/null +++ b/redisinsight/ui/src/packages/clients-list-example/README.md @@ -0,0 +1,34 @@ +# Example of the plugin for the “Client List” command + +The example has been created using React, TypeScript, and [Elastic UI](https://elastic.github.io/eui/#/). +[Parcel](https://parceljs.org/) is used to build the plugin. + +## Running locally + +The following commands will install dependencies and start the server to run the plugin locally: +``` +yarn +yarn start +``` +These commands will install dependencies and start the server. + +_Note_: Base styles are included to `index.html` from the repository. + +This command will generate the `vendor` folder with styles and fonts of the core app. Add this folder +inside the folder for your plugin and include appropriate styles to the `index.html` file. + +``` +yarn build:statics - for Linux or MacOs +yarn build:statics:win - for Windows +``` + +## Build plugin + +The following commands will build plugins to be used in RedisInsight: +``` +yarn +yarn build +``` + +[Add](../../../../../docs/plugins/installation.md) the package.json file and the +`dist` folder to the folder with your plugin, which should be located in the `plugins` folder. diff --git a/redisinsight/ui/src/packages/clients-list-example/src/main.tsx b/redisinsight/ui/src/packages/clients-list-example/src/main.tsx index ff97fb6f3e..51359287e9 100644 --- a/redisinsight/ui/src/packages/clients-list-example/src/main.tsx +++ b/redisinsight/ui/src/packages/clients-list-example/src/main.tsx @@ -20,4 +20,5 @@ if (process.env.NODE_ENV === 'development') { renderClientsList({ command: '', data: response, status: 'success' }) } +// This is a required action - export the main function for execution of the visualization export default { renderClientsList } diff --git a/redisinsight/ui/src/packages/enablement-area/enablement-area.json b/redisinsight/ui/src/packages/enablement-area/enablement-area.json index 2c00feb4e3..c4582ef82e 100644 --- a/redisinsight/ui/src/packages/enablement-area/enablement-area.json +++ b/redisinsight/ui/src/packages/enablement-area/enablement-area.json @@ -33,6 +33,24 @@ "backTitle": "Document Capabilities", "path": "/static/workbench/guides/document-capabilities/working-with-hashes.html" } + }, + { + "type": "internal-link", + "id": "working-with-json", + "label": "Working with JSON", + "args": { + "backTitle": "Document Capabilities", + "path": "/static/workbench/guides/document-capabilities/working-with-json.html" + } + }, + { + "type": "internal-link", + "id": "learn-more", + "label": "Learn More", + "args": { + "backTitle": "Document Capabilities", + "path": "/static/workbench/guides/document-capabilities/learn-more.html" + } } ] } diff --git a/redisinsight/ui/src/packages/enablement-area/guides/document-capabilities/introduction.html b/redisinsight/ui/src/packages/enablement-area/guides/document-capabilities/introduction.html index 5f58e7011d..e573784324 100644 --- a/redisinsight/ui/src/packages/enablement-area/guides/document-capabilities/introduction.html +++ b/redisinsight/ui/src/packages/enablement-area/guides/document-capabilities/introduction.html @@ -3,8 +3,8 @@
      In Redis, you can model documents using:
      @@ -24,7 +24,7 @@
    2. Supports atomic CRUD operations
    -

    Full-text search and querying is supported for both Hashes and JSON via a secondary index.

    +

    Full-text search and querying is supported for both Hashes and JSON via a secondary index.

    A number of data types are available for indexing:
      @@ -32,7 +32,7 @@
    • Numeric range index
    • Tag index supporting multiple values
    • Geo index
    • -
    • Vector index
    • +
    • Vector index (upcoming)
    @@ -58,10 +58,10 @@

    PRE-REQUISITES

    Follow these instructions to set up the RedisJSON and RediSearch modules on Redis OSS.

    - For working with Hashes you will need Redis >=6, RediSearch >=2.0. + For working with Hashes you will need Redis >=6, RediSearch >=2.0.

    - For working with JSON you will need Redis >=6, RediSearch >=2.2 and RedisJSON >=2.0. + For working with JSON you will need Redis >=6, RediSearch >=2.2 and RedisJSON >=2.0.

    You could also create a free and ready to use instance on Redis Cloud. diff --git a/redisinsight/ui/src/packages/enablement-area/guides/document-capabilities/learn-more.html b/redisinsight/ui/src/packages/enablement-area/guides/document-capabilities/learn-more.html new file mode 100644 index 0000000000..3f527f58da --- /dev/null +++ b/redisinsight/ui/src/packages/enablement-area/guides/document-capabilities/learn-more.html @@ -0,0 +1,56 @@ + diff --git a/redisinsight/ui/src/packages/enablement-area/guides/document-capabilities/working-with-hashes.html b/redisinsight/ui/src/packages/enablement-area/guides/document-capabilities/working-with-hashes.html index 60c908492c..e82cb95d3c 100644 --- a/redisinsight/ui/src/packages/enablement-area/guides/document-capabilities/working-with-hashes.html +++ b/redisinsight/ui/src/packages/enablement-area/guides/document-capabilities/working-with-hashes.html @@ -1,6 +1,6 @@
    -

    ! Click on the button, see the command and the comments in the Workbench editor, and then run it.

    +

    Click on the button, see the command and the comments in the Workbench editor, and then run it.

    1. diff --git a/redisinsight/ui/src/packages/enablement-area/guides/document-capabilities/working-with-json.html b/redisinsight/ui/src/packages/enablement-area/guides/document-capabilities/working-with-json.html new file mode 100644 index 0000000000..3d23498dbc --- /dev/null +++ b/redisinsight/ui/src/packages/enablement-area/guides/document-capabilities/working-with-json.html @@ -0,0 +1,169 @@ +
      +
      +

      Click on the button, see the command and the comments in the Workbench editor, and then run it.

      +
        +
      1. + + CRUD operations +
        + +
        +
        + +
        +
        + +
        +
        + +
        +
        +
      2. +
      3. + + Secondary Index +
        + +
        +
        + +
        +
        + +
        +
        +
      4. +
      5. + + Search and Querying Basics +
        + +
        +
        + +
        +
        + +
        +
        + +
        +
        + +
        +
        + +
        +
        + +
        +
        + +
        +
        + +
        +
        + +
        +
        + +
        +
        +
      6. +
      +
      + +
      diff --git a/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-hashes/multiple-tags-or-search.txt b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-hashes/multiple-tags-or-search.txt index 942c0a627a..4644cc619f 100644 --- a/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-hashes/multiple-tags-or-search.txt +++ b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-hashes/multiple-tags-or-search.txt @@ -1,4 +1,4 @@ -​​// Perform a search for documents that have one of multiple tags (OR condition) +// Perform a search for documents that have one of multiple tags (OR condition) FT.SEARCH "permits" "@work_type:{construction|design}" diff --git a/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/combined-search-with-and.txt b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/combined-search-with-and.txt new file mode 100644 index 0000000000..e72baa6c0e --- /dev/null +++ b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/combined-search-with-and.txt @@ -0,0 +1,19 @@ +// Perform a combined search on two fields (AND): query for intersection of both search terms, a text search and a tag match + +FT.SEARCH "schools" "@description:girls @status:{closed}" + +// See the "schools" index schema for reference + +// FT.CREATE schools +// on JSON +// PREFIX 1 "school:" +// SCHEMA +// $.name AS name TEXT NOSTEM SORTABLE +// $.description AS description TEXT +// $.school_type AS school_type TAG SEPARATOR ";" +// $.class AS class TAG +// $.address.street AS address TEXT NOSTEM +// $.address.city AS city TAG +// $.pupils AS pupils NUMERIC SORTABLE +// $.location AS location GEO +// $.status_log.[-1] as status TAG diff --git a/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/combined-search-with-geo-filter.txt b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/combined-search-with-geo-filter.txt new file mode 100644 index 0000000000..83ec2b9109 --- /dev/null +++ b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/combined-search-with-geo-filter.txt @@ -0,0 +1,19 @@ +// Perform a fuzzy text search and filter on location in a radius distance of 10 miles + +FT.SEARCH "schools" "%%gill%%" GEOFILTER location 51.11 0.45 10 mi + +// See the "schools" index schema for reference + +// FT.CREATE schools +// on JSON +// PREFIX 1 "school:" +// SCHEMA +// $.name AS name TEXT NOSTEM SORTABLE +// $.description AS description TEXT +// $.school_type AS school_type TAG SEPARATOR ";" +// $.class AS class TAG +// $.address.street AS address TEXT NOSTEM +// $.address.city AS city TAG +// $.pupils AS pupils NUMERIC SORTABLE +// $.location AS location GEO +// $.status_log.[-1] as status TAG diff --git a/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/combined-search-with-or.txt b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/combined-search-with-or.txt new file mode 100644 index 0000000000..fa28f448e0 --- /dev/null +++ b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/combined-search-with-or.txt @@ -0,0 +1,19 @@ +// Perform a combined search on two fields (OR): query for union of both search terms. The brackets are important. + +FT.SEARCH "schools" "(@city:{Oxford})|(@description:girls)" + +// See the "schools" index schema for reference + +// FT.CREATE schools +// on JSON +// PREFIX 1 "school:" +// SCHEMA +// $.name AS name TEXT NOSTEM SORTABLE +// $.description AS description TEXT +// $.school_type AS school_type TAG SEPARATOR ";" +// $.class AS class TAG +// $.address.street AS address TEXT NOSTEM +// $.address.city AS city TAG +// $.pupils AS pupils NUMERIC SORTABLE +// $.location AS location GEO +// $.status_log.[-1] as status TAG diff --git a/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/create-json-index.txt b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/create-json-index.txt new file mode 100644 index 0000000000..aa4972fce4 --- /dev/null +++ b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/create-json-index.txt @@ -0,0 +1,24 @@ +// It is possible to index either every hash or every JSON document in the keyspace or configure indexing only for a subset of the same data type documents described by a prefix. + +// RedisJSON supports JSONPath, so we can easily access and index nested properties and array elements. +// Note that you cannot index values that contain JSON objects or JSON arrays. To be indexed, a JSONPath expression must return a single scalar value (string or number). If the JSONPath expression returns an object or an array, it will be ignored. + +// JSON Strings can only be indexed as TEXT, TAG and GEO (using the right syntax). +// JSON numbers can only be indexed as NUMERIC. +// Boolean and NULL values are ignored. + +// Command to create an index on JSON keys that are prefixed with "school:" + +FT.CREATE schools // Index name + on JSON // Indicates the type of data to index + PREFIX 1 "school:" // Tells the index which keys it should index + SCHEMA + $.name AS name TEXT NOSTEM SORTABLE // Will be indexed as a TEXT field. Will permit sorting during query. Stemming is disabled - which is ideal for proper names. + $.description AS description TEXT + $.school_type AS school_type TAG SEPARATOR ";" // For tag fields, a separator indicates how the text contained in the field is to be split into individual tags + $.class AS class TAG // Will be indexed as a tag. Will allow exact-match queries. + $.address.street AS address TEXT NOSTEM // '$.address.street' field will be indexed as TEXT and can be referred as 'street' due to the '... AS fieldname ...' construct. + $.address.city AS city TAG + $.pupils AS pupils NUMERIC SORTABLE // Will be indexed as a numeric field. Will permit sorting during query + $.location AS location GEO // Will be indexed as GEO. Will allow geographic range queries + $.status_log.[-1] as status TAG // Will index the last element of the array as "status" diff --git a/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/crud-create.txt b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/crud-create.txt new file mode 100644 index 0000000000..5904384541 --- /dev/null +++ b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/crud-create.txt @@ -0,0 +1,11 @@ +// Let's add four documents as JSON to the index. Note the format of the key names. +// Each document represents a school. + +JSON.SET school:1 . '{"name":"Hall School", "description":"Independent primary school for boys aged 5 to 11","school_type":"single;boys","class":"independent", "address":{"city":"London", "street":"Manor Street"}, "pupils":342, "location":"51.445417, -0.258352", "status_log":["new", "operating"]}' + +JSON.SET school:2 . '{"name":"Garden School", "description":"State school for boys and girls aged 5 to 18","school_type":"mixed;boys;girls","class":"state", "address":{"city":"London", "street":"Gordon Street"}, "pupils":1452, "location":"51.402926, -0.321523", "status_log":["new", "operating"]}' + +JSON.SET school:3 . '{"name":"Gillford School", "description":"Independent school for girls aged 5 to 18","school_type":"single;girls","class":"private", "address":{"city":"Goudhurst", "street":"Goudhurst"}, "pupils":721, "location":"51.112685, 0.451076", "status_log":["new", "operating", "closed"]}' + +JSON.SET school:4 . '{"name":"Old Boys School", "description":"Independent school for boys aged 5 to 18","school_type":"single;boys","class":"independent", "address":{"city":"Oxford", "street":"Trident Street"}, "pupils":1200, "location":"51.781756, -1.123196", "status_log":["new", "operating"]}' + diff --git a/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/crud-delete.txt b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/crud-delete.txt new file mode 100644 index 0000000000..68970feb23 --- /dev/null +++ b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/crud-delete.txt @@ -0,0 +1,9 @@ +JSON.GET school:1 $.pupils // Read the pupils field before deletion + +JSON.DEL school:1 $.pupils // Delete only the pupils field from the document + +JSON.GET school:1 // Read the whole document to confirm the construction_value field has been deleted + +JSON.DEL school:1 // Delete the entire document + +JSON.GET school:1 // Confirm the entire document has been deleted diff --git a/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/crud-read.txt b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/crud-read.txt new file mode 100644 index 0000000000..9af0845a6c --- /dev/null +++ b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/crud-read.txt @@ -0,0 +1,5 @@ +JSON.GET school:1 // Read the whole document + +// RedisJSON supports JSONPath, so we can easily access nested properties using $. construct + +JSON.GET school:1 $.description // Read only the field description diff --git a/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/crud-update.txt b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/crud-update.txt new file mode 100644 index 0000000000..b9cb1e0f19 --- /dev/null +++ b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/crud-update.txt @@ -0,0 +1,5 @@ +JSON.GET school:1 $.pupils // Read the pupils field before the update + +JSON.SET school:1 $.pupils 430 // Update the pupils field + +JSON.GET school:1 $.pupils // Read the pupils field after the update diff --git a/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/exact-text-search.txt b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/exact-text-search.txt new file mode 100644 index 0000000000..64d41fabeb --- /dev/null +++ b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/exact-text-search.txt @@ -0,0 +1,19 @@ +// Perform a text search on all text fields: query for documents inside which the word 'girls' occurs + +FT.SEARCH "schools" "girls" + +// See the "schools" index schema for reference + +// FT.CREATE schools +// on JSON +// PREFIX 1 "school:" +// SCHEMA +// $.name AS name TEXT NOSTEM SORTABLE +// $.description AS description TEXT +// $.school_type AS school_type TAG SEPARATOR ";" +// $.class AS class TAG +// $.address.street AS address TEXT NOSTEM +// $.address.city AS city TAG +// $.pupils AS pupils NUMERIC SORTABLE +// $.location AS location GEO +// $.status_log.[-1] as status TAG diff --git a/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/field-specific-text-search.txt b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/field-specific-text-search.txt new file mode 100644 index 0000000000..a30dae9d82 --- /dev/null +++ b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/field-specific-text-search.txt @@ -0,0 +1,20 @@ +// Perform a text search on a specific field: query for documents which have a field 'name' inside which the word 'old' occurs +// To reference a field, use @ construct + +FT.SEARCH "schools" "@name:old" + +// See the "schools" index schema for reference + +// FT.CREATE schools +// on JSON +// PREFIX 1 "school:" +// SCHEMA +// $.name AS name TEXT NOSTEM SORTABLE +// $.description AS description TEXT +// $.school_type AS school_type TAG SEPARATOR ";" +// $.class AS class TAG +// $.address.street AS address TEXT NOSTEM +// $.address.city AS city TAG +// $.pupils AS pupils NUMERIC SORTABLE +// $.location AS location GEO +// $.status_log.[-1] as status TAG diff --git a/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/fuzzy-text-search.txt b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/fuzzy-text-search.txt new file mode 100644 index 0000000000..5b3b140140 --- /dev/null +++ b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/fuzzy-text-search.txt @@ -0,0 +1,19 @@ +// Perform a Fuzzy text search on all text fields: query for documents with words similar to 'gill'. The number of % indicates the allowed Levenshtein distance. So the query would also match on 'girl' because 'gill' and 'girl' have a distance of two. + +FT.SEARCH "schools" "%%gill%%" + +// See the "schools" index schema for reference + +// FT.CREATE schools +// on JSON +// PREFIX 1 "school:" +// SCHEMA +// $.name AS name TEXT NOSTEM SORTABLE +// $.description AS description TEXT +// $.school_type AS school_type TAG SEPARATOR ";" +// $.class AS class TAG +// $.address.street AS address TEXT NOSTEM +// $.address.city AS city TAG +// $.pupils AS pupils NUMERIC SORTABLE +// $.location AS location GEO +// $.status_log.[-1] as status TAG diff --git a/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/group-and-sort-by-aggregation.txt b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/group-and-sort-by-aggregation.txt new file mode 100644 index 0000000000..80cbfa4f90 --- /dev/null +++ b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/group-and-sort-by-aggregation.txt @@ -0,0 +1,25 @@ +// Aggregations are a way to process the results of a search query, group, sort and transform them - and extract analytic insights from them. +// Aggregations are represented as the following data processing pipeline: +// Filter -> Group (Reduce) -> Apply -> Sort -> Apply + +// Perform a Group By & Sort By aggregation of your documents: display the number of permits by city and then sort the city alphabetically + +FT.AGGREGATE "schools" "*" + GROUPBY 1 @city REDUCE COUNT 0 AS nb_of_schools + SORTBY 2 @city Asc + +// See the "schools" index schema for reference + +// FT.CREATE schools +// on JSON +// PREFIX 1 "school:" +// SCHEMA +// $.name AS name TEXT NOSTEM SORTABLE +// $.description AS description TEXT +// $.school_type AS school_type TAG SEPARATOR ";" +// $.class AS class TAG +// $.address.street AS address TEXT NOSTEM +// $.address.city AS city TAG +// $.pupils AS pupils NUMERIC SORTABLE +// $.location AS location GEO +// $.status_log.[-1] as status TAG diff --git a/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/index-info.txt b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/index-info.txt new file mode 100644 index 0000000000..40ab37462a --- /dev/null +++ b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/index-info.txt @@ -0,0 +1,5 @@ +// Command to display information about a particular index. +// In this case display the information about the newly created "schools" index + +FT.INFO "schools" + diff --git a/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/list-all-indexes.txt b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/list-all-indexes.txt new file mode 100644 index 0000000000..01a7b83a5b --- /dev/null +++ b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/list-all-indexes.txt @@ -0,0 +1,3 @@ +// Command to return the list of all existing indexes + +FT._LIST diff --git a/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/multiple-tags-and-search.txt b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/multiple-tags-and-search.txt new file mode 100644 index 0000000000..f95fbbb128 --- /dev/null +++ b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/multiple-tags-and-search.txt @@ -0,0 +1,19 @@ +// Perform a search for documents that all of the tags (AND condition) + +FT.SEARCH "schools" "@school_type:{single} @school_type:{girls}" + +// See the "schools" index schema for reference + +// FT.CREATE schools +// on JSON +// PREFIX 1 "school:" +// SCHEMA +// $.name AS name TEXT NOSTEM SORTABLE +// $.description AS description TEXT +// $.school_type AS school_type TAG SEPARATOR ";" +// $.class AS class TAG +// $.address.street AS address TEXT NOSTEM +// $.address.city AS city TAG +// $.pupils AS pupils NUMERIC SORTABLE +// $.location AS location GEO +// $.status_log.[-1] as status TAG diff --git a/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/multiple-tags-or-search.txt b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/multiple-tags-or-search.txt new file mode 100644 index 0000000000..2713ed5863 --- /dev/null +++ b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/multiple-tags-or-search.txt @@ -0,0 +1,19 @@ +// Perform a search for documents that have one of multiple tags (OR condition) + +FT.SEARCH "schools" "@school_type:{single|girls}" + +// See the "schools" index schema for reference + +// FT.CREATE schools +// on JSON +// PREFIX 1 "school:" +// SCHEMA +// $.name AS name TEXT NOSTEM SORTABLE +// $.description AS description TEXT +// $.school_type AS school_type TAG SEPARATOR ";" +// $.class AS class TAG +// $.address.street AS address TEXT NOSTEM +// $.address.city AS city TAG +// $.pupils AS pupils NUMERIC SORTABLE +// $.location AS location GEO +// $.status_log.[-1] as status TAG diff --git a/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/numeric-range-query.txt b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/numeric-range-query.txt new file mode 100644 index 0000000000..91dfb9725d --- /dev/null +++ b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/numeric-range-query.txt @@ -0,0 +1,21 @@ +// Perform a numeric range query: query for every document that has a 'pupils' value between 0 and 1000 +// For numerical ranges, square brackets are inclusive of the listed values + +FT.SEARCH "schools" "@pupils:[0,1000]" + + +// See the "schools" index schema for reference + +// FT.CREATE schools +// on JSON +// PREFIX 1 "school:" +// SCHEMA +// $.name AS name TEXT NOSTEM SORTABLE +// $.description AS description TEXT +// $.school_type AS school_type TAG SEPARATOR ";" +// $.class AS class TAG +// $.address.street AS address TEXT NOSTEM +// $.address.city AS city TAG +// $.pupils AS pupils NUMERIC SORTABLE +// $.location AS location GEO +// $.status_log.[-1] as status TAG diff --git a/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/tag-search.txt b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/tag-search.txt new file mode 100644 index 0000000000..bb1abaf392 --- /dev/null +++ b/redisinsight/ui/src/packages/enablement-area/scripts/document-capabilities/working-with-json/tag-search.txt @@ -0,0 +1,19 @@ +// Perform a tag search: query for documents which have the city field set to "London". Note that we use curly braces around the tag. + +FT.SEARCH "schools" "@city:{Oxford}" + +// See the "schools" index schema for reference + +// FT.CREATE schools +// on JSON +// PREFIX 1 "school:" +// SCHEMA +// $.name AS name TEXT NOSTEM SORTABLE +// $.description AS description TEXT +// $.school_type AS school_type TAG SEPARATOR ";" +// $.class AS class TAG +// $.address.street AS address TEXT NOSTEM +// $.address.city AS city TAG +// $.pupils AS pupils NUMERIC SORTABLE +// $.location AS location GEO +// diff --git a/redisinsight/ui/src/packages/redisearch/src/components/TableInfoResult/TableInfoResult.tsx b/redisinsight/ui/src/packages/redisearch/src/components/TableInfoResult/TableInfoResult.tsx index 42a9086bd0..57d956852d 100644 --- a/redisinsight/ui/src/packages/redisearch/src/components/TableInfoResult/TableInfoResult.tsx +++ b/redisinsight/ui/src/packages/redisearch/src/components/TableInfoResult/TableInfoResult.tsx @@ -120,6 +120,7 @@ const TableInfoResult = React.memo((props: Props) => { className={cx('inMemoryTableDefault', 'tableInfo', { tableWithPagination: result?.length > 10, })} + responsive={false} data-testid={`query-table-result-${query}`} /> {Footer()} diff --git a/redisinsight/ui/src/packages/redisearch/src/components/TableResult/TableResult.tsx b/redisinsight/ui/src/packages/redisearch/src/components/TableResult/TableResult.tsx index b497a0adfa..1d115634d0 100644 --- a/redisinsight/ui/src/packages/redisearch/src/components/TableResult/TableResult.tsx +++ b/redisinsight/ui/src/packages/redisearch/src/components/TableResult/TableResult.tsx @@ -117,6 +117,7 @@ const TableResult = React.memo((props: Props) => { tableWithPagination: result?.length > 10, } )} + responsive={false} data-testid={`query-table-result-${query}`} /> )} diff --git a/redisinsight/ui/src/pages/browser/components/list-details/ListDetails.tsx b/redisinsight/ui/src/pages/browser/components/list-details/ListDetails.tsx index e6a4ab0c01..7f216c5cc2 100644 --- a/redisinsight/ui/src/pages/browser/components/list-details/ListDetails.tsx +++ b/redisinsight/ui/src/pages/browser/components/list-details/ListDetails.tsx @@ -2,7 +2,7 @@ import { EuiButtonIcon, EuiText, EuiToolTip } from '@elastic/eui' import React, { useEffect, useState } from 'react' import { useDispatch, useSelector } from 'react-redux' import cx from 'classnames' -import { isNull } from 'lodash' +import { isEqual, isNull } from 'lodash' import { SCAN_COUNT_DEFAULT } from 'uiSrc/constants/api' import { @@ -66,10 +66,16 @@ const ListDetails = (props: Props) => { }, [loadedElements]) const handleEditElement = (index = 0, editing: boolean) => { - const elems = [...elements] - elems[index].editing = editing - - setElements(elems) + const newElemsState = elements.map((item) => { + if (item.index === index) { + return { ...item, editing } + } + return item + }) + + if (!isEqual(elements, newElemsState)) { + setElements(newElemsState) + } } const handleApplyEditElement = (index = 0, element: string) => { diff --git a/redisinsight/ui/src/pages/workbench/components/enablament-area/EnablementArea/components/Group/styles.scss b/redisinsight/ui/src/pages/workbench/components/enablament-area/EnablementArea/components/Group/styles.scss index 1172ecc8c5..466d660140 100644 --- a/redisinsight/ui/src/pages/workbench/components/enablament-area/EnablementArea/components/Group/styles.scss +++ b/redisinsight/ui/src/pages/workbench/components/enablament-area/EnablementArea/components/Group/styles.scss @@ -34,6 +34,10 @@ .euiListGroupItem { button { padding: 3px 8px; + line-height: 24px; + } + .euiListGroupItem__label { + line-height: 20px; } } } diff --git a/redisinsight/ui/src/pages/workbench/components/enablament-area/EnablementArea/components/InternalLink/InternalLink.tsx b/redisinsight/ui/src/pages/workbench/components/enablament-area/EnablementArea/components/InternalLink/InternalLink.tsx index 06f32ca0dd..328c24dad4 100644 --- a/redisinsight/ui/src/pages/workbench/components/enablament-area/EnablementArea/components/InternalLink/InternalLink.tsx +++ b/redisinsight/ui/src/pages/workbench/components/enablament-area/EnablementArea/components/InternalLink/InternalLink.tsx @@ -4,6 +4,7 @@ import cx from 'classnames' import EnablementAreaContext from 'uiSrc/pages/workbench/contexts/enablementAreaContext' import styles from './styles.module.scss' +import './styles.scss' export interface Props { testId: string, diff --git a/redisinsight/ui/src/pages/workbench/components/enablament-area/EnablementArea/components/InternalLink/styles.scss b/redisinsight/ui/src/pages/workbench/components/enablament-area/EnablementArea/components/InternalLink/styles.scss new file mode 100644 index 0000000000..f1b7d39490 --- /dev/null +++ b/redisinsight/ui/src/pages/workbench/components/enablament-area/EnablementArea/components/InternalLink/styles.scss @@ -0,0 +1,3 @@ +.euiListGroupItem--xSmall .euiListGroupItem__label { + line-height: 12px; +} diff --git a/redisinsight/ui/src/pages/workbench/components/wb-view/WBView/WBView.tsx b/redisinsight/ui/src/pages/workbench/components/wb-view/WBView/WBView.tsx index b70b04bc16..504d61728c 100644 --- a/redisinsight/ui/src/pages/workbench/components/wb-view/WBView/WBView.tsx +++ b/redisinsight/ui/src/pages/workbench/components/wb-view/WBView/WBView.tsx @@ -79,7 +79,7 @@ const WBView = (props: Props) => { { isCollapsed.current = !isCollapsed.current }} @@ -92,11 +92,12 @@ const WBView = (props: Props) => { data-test-subj="resize-btn-preselects-area" /> {(EuiResizablePanel, EuiResizableButton) => ( @@ -106,6 +107,7 @@ const WBView = (props: Props) => { minSize="140px" paddingSize="none" scrollable={false} + className={styles.queryPanel} initialSize={vertical[verticalPanelIds.firstPanelId] ?? 20} style={{ minHeight: '140px' }} > @@ -129,7 +131,9 @@ const WBView = (props: Props) => { paddingSize="none" scrollable={false} initialSize={vertical[verticalPanelIds.secondPanelId] ?? 80} - className={styles.queryResults} + className={cx(styles.queryResults, styles.queryResultsPanel)} + // Fix scroll on low height - 140px (queryPanel) + style={{ maxHeight: 'calc(100% - 140px)' }} > { - state.data.elements[payload.index] = payload.element + state.data.elements[state.data.elements.length === 1 ? 0 : payload.index] = payload.element }, insertListElements: (state) => { state.loading = true diff --git a/redisinsight/ui/src/utils/commands.ts b/redisinsight/ui/src/utils/commands.ts index 1053257a98..0a9006af89 100644 --- a/redisinsight/ui/src/utils/commands.ts +++ b/redisinsight/ui/src/utils/commands.ts @@ -49,26 +49,30 @@ export const generateArgsNames = ( isEmpty ) +const getExternalCommandFormat = (commandName = '') => + commandName + .replace(/\s+/g, '_') + .replace(/[.]+/g, '') + .toLowerCase() + export const getDocUrlForCommand = ( commandName: string, commandGroup: CommandGroup | string = CommandGroup.Generic ): string => { - let commandPage = '' + let command = getExternalCommandFormat(commandName) switch (commandGroup) { case CommandGroup.Search: - commandPage = commandName - .replace(/\s+/g, '_') - .replace(/[.]+/g, '') - .toLowerCase() - return `https://oss.redis.com/redisearch/Commands/#${commandPage}` + return `https://oss.redis.com/redisearch/Commands/#${command}` case CommandGroup.JSON: - commandPage = commandName - .replace(/\s+/g, '_') - .replace(/[.]+/g, '') - .toLowerCase() - return `https://oss.redis.com/redisjson/commands/#${commandPage}` + return `https://oss.redis.com/redisjson/commands/#${command}` + case CommandGroup.TimeSeries: + return `https://oss.redis.com/redistimeseries/commands/#${command}` + case CommandGroup.Graph: + return `https://oss.redis.com/redisgraph/commands/#${command}` + case CommandGroup.AI: + return `https://oss.redis.com/redisai/commands/#${command}` default: - commandPage = commandName.replace(/\s+/g, '-').toLowerCase() - return `https://redis.io/commands/${commandPage}` + command = commandName.replace(/\s+/g, '-').toLowerCase() + return `https://redis.io/commands/${command}` } } diff --git a/redisinsight/ui/src/utils/tests/commands.spec.ts b/redisinsight/ui/src/utils/tests/commands.spec.ts index 06671e18f4..4ae9286224 100644 --- a/redisinsight/ui/src/utils/tests/commands.spec.ts +++ b/redisinsight/ui/src/utils/tests/commands.spec.ts @@ -192,6 +192,12 @@ const getDocUrlForCommandTests: any[] = [ ['JSON.GET', CommandGroup.JSON, 'https://oss.redis.com/redisjson/commands/#jsonget'], ['FT.CREATE', CommandGroup.Search, 'https://oss.redis.com/redisearch/Commands/#ftcreate'], ['FT.ALTER SCHEMA ADD', CommandGroup.Search, 'https://oss.redis.com/redisearch/Commands/#ftalter_schema_add'], + ['TS.ADD', CommandGroup.TimeSeries, 'https://oss.redis.com/redistimeseries/commands/#tsadd'], + ['TS.CREATE', CommandGroup.TimeSeries, 'https://oss.redis.com/redistimeseries/commands/#tscreate'], + ['GRAPH.EXPLAIN', CommandGroup.Graph, 'https://oss.redis.com/redisgraph/commands/#graphexplain'], + ['GRAPH.QUERY', CommandGroup.Graph, 'https://oss.redis.com/redisgraph/commands/#graphquery'], + ['AI.MODELRUN', CommandGroup.AI, 'https://oss.redis.com/redisai/commands/#aimodelrun'], + ['AI.SCRIPTDEL', CommandGroup.AI, 'https://oss.redis.com/redisai/commands/#aiscriptdel'], ['NON EXIST COMMAND', 'non-exist', 'https://redis.io/commands/non-exist-command'], ] diff --git a/tests/e2e/package.json b/tests/e2e/package.json index 6cba7ae7d5..b8ab6b5e88 100644 --- a/tests/e2e/package.json +++ b/tests/e2e/package.json @@ -7,6 +7,8 @@ "test:live": "testcafe --live chrome ", "start:api": "cross-env SERVER_STATIC_CONTENT=true yarn --cwd ../../redisinsight/api start:prod", "build:api": "yarn --cwd ../../redisinsight/api build:prod", + "build:statics": "yarn --cwd ../../ build:statics", + "build:statics:win": "yarn --cwd ../../ build:statics:win", "build:web": "yarn --cwd ../../ build:web", "redis:last": "docker run --name redis-last-version -p 7777:6379 -d redislabs/redismod", "start:app": "cross-env SERVER_STATIC_CONTENT=true yarn start:api", From 50822e0db8f3971f27ba180802d691e944862067 Mon Sep 17 00:00:00 2001 From: Zalenski Egor <63463140+zalenskiSofteq@users.noreply.github.com> Date: Wed, 17 Nov 2021 20:42:05 +0300 Subject: [PATCH 3/4] Update padding LICENSE --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index 7ad9b79ae5..ea3921393f 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Server Side Public License + Server Side Public License VERSION 1, OCTOBER 16, 2018 Copyright © 2018 MongoDB, Inc. From 3198084a81aadaf1f5d1748eacc4d5d99dba94af Mon Sep 17 00:00:00 2001 From: Zalenski Egor <63463140+zalenskiSofteq@users.noreply.github.com> Date: Wed, 17 Nov 2021 20:43:41 +0300 Subject: [PATCH 4/4] delete README for api --- redisinsight/api/README.md | 63 -------------------------------------- 1 file changed, 63 deletions(-) delete mode 100644 redisinsight/api/README.md diff --git a/redisinsight/api/README.md b/redisinsight/api/README.md deleted file mode 100644 index e3e09c1b52..0000000000 --- a/redisinsight/api/README.md +++ /dev/null @@ -1,63 +0,0 @@ -# RedisInsight API - -## Description -RedisInsight provides an intuitive and efficient GUI for Redis, allowing you to interact with your databases and manage your data—with built-in support for most popular Redis modules. It provides tools to analyze the memory, profile the performance of your database usage, and guide you toward better Redis usage. - -## Prerequisites - -Make sure you have installed following packages: -* [Node](https://nodejs.org/en/download/) >= 8.0 -* [npm](https://www.npmjs.com/get-npm) >= 5 - -## Dependencies used -* [NestJS](https://nestjs.com/) - -## Getting started - -### Installation - -```bash -$ yarn install -``` - -### Running the app - -```bash -# development -$ yarn start - -# watch mode -$ yarn start:dev - -# production mode -$ yarn start:prod -``` - -### Formatting - -Formatting required before submitting pull request. - -Prints the filenames of files that are different from Prettier formatting -```bash -$ yarn format -``` -### Swagger OpenApi - -The [OpenAPI](https://swagger.io/specification/) specification is a language-agnostic definition format used -to describe RESTful APIs. - -While the application is running, open your browser and navigate to `http://localhost[:]/api/docs`. -You should see the Swagger UI. - -### Test - -```bash -# unit tests -$ yarn test - -# e2e tests -$ yarn test:e2e - -# test coverage -$ yarn test:cov -```