Giter VIP home page Giter VIP logo

dashkit's Introduction

@gravity-ui/dashkit · npm package CI storybook

DashKit

A dashboard grid rendering library.

Installation

npm i @gravity-ui/dashkit @gravity-ui/uikit

Description

The library is used to line up widgets in a grid, resize them, add new ones, and delete them. The widget is a react component. For example, text, graphics, and images.

New widgets are added via a plugin system.

Plugins

Plugins are required to create custom widgets.

Props

interface DashKitProps {
  config: Config;
  editMode: boolean;
  onItemEdit: ({id}: {id: string}) => void;
  onChange: (data: {config: Config; itemsStateAndParams: ItemsStateAndParams}) => void;
  onDrop: (dropProps: ItemDropProps) => void;
  defaultGlobalParams: GlobalParams;
  globalParams: GlobalParams;
  itemsStateAndParams: ItemsStateAndParams;
  settings: SettingsProps;
  context: ContextProps;
  overlayControls?: Record<string, OverlayControlItem[]>;
  noOverlay?: boolean;
  focusable?: boolean;
  draggableHandleClassName?: string;
}
  • config: сonfig.
  • editMode: Whether edit mode is enabled.
  • onItemEdit: Called when you click to edit a widget.
  • onChange: Called when config or itemsStateAndParams are changed.
  • onDrop: Called when item dropped from ActionPanel using (#DashKitDnDWrapper)
  • defaultGlobalParams, globalParams: Parameters that affect all widgets. In DataLens, defaultGlobalParams are global parameters set in the dashboard settings. globalParams are globals parameters that can be set in the url.
  • itemsStateAndParams: itemsStateAndParams.
  • settings: DashKit settings.
  • context: Object that will be propped up on all widgets.
  • overlayControls: Object that overrides widget controls at the time of editing. If not transmitted, basic controls will be displayed.
  • noOverlay: If true, overlay and controls are not displayed while editing.
  • focusable: If true, grid items will be focusable.
  • draggableHandleClassName : СSS class name of the element that makes the widget draggable.

Usage

DashKit configuration

Before using DashKit as a react component, it must be configured.

  • set language

    import {configure, Lang} from '@gravity-ui/uikit';
    
    configure({lang: Lang.En});
  • DashKit.setSettings

    Used for global DashKit settings (such as margins between widgets, default widget sizes and widget overlay menu)

    import {DashKit} from '@gravity-ui/dashkit';
    
    DashKit.setSettings({
      gridLayout: {margin: [8, 8]},
      isMobile: true,
      // menu: [] as Array<MenuItem>,
    });
  • DashKit.registerPlugins

    Registering and configuring plugins

    import {DashKit} from '@gravity-ui/dashkit';
    import {pluginTitle, pluginText} from '@gravity-ui/dashkit';
    
    DashKit.registerPlugins(
      pluginTitle,
      pluginText.setSettings({
        apiHandler({text}) {
          return api.getMarkdown(text);
        },
      }),
    );
    
    DashKit.registerPlugins({
      type: 'custom',
      defaultLayout: {
        w: 10,
        h: 8,
      },
      renderer: function CustomPlugin() {
        return <div>Custom widget with custom controls</div>;
      },
    });

Config

export interface Config {
  salt: string; // to form a unique id
  counter: number; // to form a unique id, only increases
  items: ConfigItem[]; //  initial widget states
  layout: ConfigLayout[]; // widget position on the grid https://github.com/react-grid-layout
  aliases: ConfigAliases; // aliases for parameters see #Params
  connections: ConfigConnection[]; // links between widgets see #Params
}

Config example:

import {DashKitProps} from '@gravity-ui/dashkit';

const config: DashKitProps['config'] = {
  salt: '0.46703554571365613',
  counter: 4,
  items: [
    {
      id: 'tT',
      data: {
        size: 'm',
        text: 'Caption',
        showInTOC: true,
      },
      type: 'title',
      namespace: 'default',
      orderId: 1,
    },
    {
      id: 'Ea',
      data: {
        text: 'mode _editActive',
        _editActive: true,
      },
      type: 'text',
      namespace: 'default',
    },
    {
      id: 'zR',
      data: {
        text: '### Text',
      },
      type: 'text',
      namespace: 'default',
      orderId: 0,
    },
    {
      id: 'Dk',
      data: {
        foo: 'bar',
      },
      type: 'custom',
      namespace: 'default',
      orderId: 5,
    },
  ],
  layout: [
    {
      h: 2,
      i: 'tT',
      w: 36,
      x: 0,
      y: 0,
    },
    {
      h: 6,
      i: 'Ea',
      w: 12,
      x: 0,
      y: 2,
    },
    {
      h: 6,
      i: 'zR',
      w: 12,
      x: 12,
      y: 2,
    },
    {
      h: 4,
      i: 'Dk',
      w: 8,
      x: 0,
      y: 8,
    },
  ],
  aliases: {},
  connections: [],
};

Add a new item to the config:

const newLayout = updateLayout: [
  {
    h: 6,
    i: 'Ea',
    w: 12,
    x: 0,
    y: 6,
  },
  {
    h: 4,
    i: 'Dk',
    w: 8,
    x: 0,
    y: 12,
  },
];

const newConfig = DashKit.setItem({
  item: {
    data: {
      text: `Some text`,
    },
    namespace: 'default',
    type: 'text',
    // Optional. If new item needed to be inserted in current layout with predefined dimensions
    layout: { // Current item inseterted before 'Ea'
      h: 6,
      w: 12,
      x: 0,
      y: 2,
    },,
  },
  config: config,
  options: {
    // Optional. New layout values for existing items when new element is dropped from ActionPanel
    updateLayout: newLayout,
  },
});

Change an existing item in the config:

const newConfig = DashKit.setItem({
  item: {
    id: 'tT', // item.id
    data: {
      size: 'm',
      text: `New caption`,
    },
    namespace: 'default',
    type: 'title',
  },
  config: config,
});

Delete an item from the config:

import {DashKitProps} from '@gravity-ui/dashkit';

const oldItemsStateAndParams: DashKitProps['itemsStateAndParams'] = {};

const {config: newConfig, itemsStateAndParams} = DashKit.removeItem({
  id: 'tT', // item.id
  config: config,
  itemsStateAndParams: this.state.itemsStateAndParams,
});

Params

type Params = Record<string, string | string[]>;

DashKit generates parameters according to the default parameters for widgets, links, and aliases. These parameters are required for the ChartKit library.

Generation order:

  1. defaultGlobalParams
  2. Default widget parameters item.default
  3. globalParams
  4. Parameters from itemsStateAndParams according to the queue.

itemsStateAndParams

Object that stores widget parameters and states as well as a parameter change queue. It has a __meta__ field for storing queue and meta information.

interface StateAndParamsMeta = {
    __meta__: {
        queue: {id: string}[]; // queue
        version: number; // current version itemsStateAndParams
    };
}

And also widget states and parameters:

interface ItemsStateAndParamsBase {
  [itemId: string]: {
    state?: Record<string, any>;
    params?: Params;
  };
}
type ItemsStateAndParams = StateAndParamsMeta & ItemsStateAndParamsBase;

Menu

You can specify custom DashKit widget overlay menu in edit mode

type MenuItem = {
  id: string; // uniq id
  title?: string; // string title
  icon?: ReactNode; // node of icon
  iconSize?: number | string; // icon size in px as number or as string with units
  handler?: (item: ConfigItem) => void; // custom item action handler
  visible?: (item: ConfigItem) => boolean; // optional visibility handler for filtering menu items
  className?: string; // custom class property
};

// use array of menu items in settings
DashKit.setSettings({menu: [] as Array<MenuItem>});

Draggable items from ActionPanel

DashKitDnDWrapper

interface DashKitDnDWrapperProps {
  dragImageSrc?: string;
  onDragStart?: (dragProps: ItemDragProps) => void;
  onDragEnd?: () => void;
}
  • dragImageSrc: Drag image preview, by default used transparent 1px png base64
  • onDragStart: Callback called when element is dragged from ActionPanel
  • onDragEnd: Callback called when element dropped or drag canceled
type ItemDragProps = {
    type: string; // Plugin type
    layout?: { // Optional. Layout item size for preview and init
        w?: number;
        h?: number;
    };
    extra?: any; // Custom user context
};
type ItemDropProps = {
    commit: () => void; // Callback should be called after all config operations are made
    dragProps: ItemDragProps; // Item drag props
    itemLayout: ConfigLayout; // Calculated item layout dimensions
    newLayout: ConfigLayout[]; // New layout after element is dropped
};

Example:

const menuItems = [
  {
    id: 'chart',
    icon: <Icon data={ChartColumn} />,
    title: 'Chart',
    qa: 'chart',
    dragProps: { // ItemDragProps
        type: 'custom', // Registered plugin type
    },
  }
]

const onDrop = (dropProps: ItemDropProps) => {
  // ... add element to your config
  dropProps.commit();
}

<DashKitDnDWrapper>
  <DashKit editMode={true} config={config} onChange={onChange} onDrop={onDrop} />
  <ActionPanel items={menuItems} />
</DashKitDnDWrapper>

CSS API

Name Description
Action panel variables
--dashkit-action-panel-color Background color
--dashkit-action-panel-border-color Border color
--dashkit-action-panel-border-radius Border radius
Action panel item variables
--dashkit-action-panel-item-color Backgroud color
--dashkit-action-panel-item-text-color Text color
--dashkit-action-panel-item-color-hover Hover backgroud color
--dashkit-action-panel-item-text-color-hover Hover text color
Overlay variables
--dashkit-overlay-border-color Border color
--dashkit-overlay-color Background color
--dashkit-overlay-opacity Opacity
Grid item variables
--dashkit-grid-item-edit-opacity Opacity
--dashkit-grid-item-border-radius Border radius
Placeholder variables
--dashkit-placeholder-color Background color
--dashkit-placeholder-opacity Opacity

Usage example

.custom-theme-wrapper {
  --dashkit-grid-item-edit-opacit: 1;
  --dashkit-overlay-color: var(--g-color-base-float);
  --dashkit-overlay-border-color: var(--g-color-base-float);
  --dashkit-overlay-opacity: 0.5;

  --dashkit-action-panel-border-color: var(--g-color-line-info);
  --dashkit-action-panel-color: var(--g-color-base-float-accent);
  --dashkit-action-panel-border-radius: var(--g-border-radius-xxl);
}
// ....

const CustomThemeWrapper = (props: {
  dashkitProps: DashkitProps;
  actionPanelProps: ActionPanelProps;
}) => {
  return (
    <div className="custom-theme-wrapper">
      <Dashkit {...props.dashkitProps} />
      <ActionPanel {...props.actionPanelProps} />
    </div>
  );
};

Development

Build & watch

  • Build dependencies npm ci
  • Build a project npm run build
  • Build storybook npm run start

By default, storybook runs on http://localhost:7120/. New changes from a project aren't always picked up when storybook is running, so it's better to rebuild a project manually and restart storybook.

Example of an nginx config for development on a dev machine

server {
    server_name dashkit.username.ru;

    include common/ssl;

    access_log /home/username/logs/common.access.log;
    error_log /home/username/logs/common.error.log;

    root /home/username/projects/dashkit;

    location / {
        try_files $uri @node;
    }

    location @node {
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_pass http://127.0.0.1:7120;
        proxy_redirect off;
    }
}

dashkit's People

Contributors

artemluchin avatar astandrik avatar catakot avatar flops avatar goshander avatar gravity-ui-bot avatar ierehon1905 avatar imechoim avatar jhoncool avatar korvin89 avatar kseniya57 avatar marginy605 avatar mournfulcoroner avatar pavel-klimov avatar ref256 avatar yc-ui-bot avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

dashkit's Issues

Prop for hiding settings button in edit mode

Context menu button in Editing mode doesn't have a border radius on the left part of the button when hovered over

Mac OS 14.4.1 (23E224)
Yandex Browser 24.1.5.827 (64-bit) | Safari 17.4.1 (19618.1.15.11.14)

image

Crash when rendering with unregistered layout plugin

Non informative error with global crash all dashkit

useCalcLayout.js:6 Uncaught TypeError: Cannot read properties of undefined (reading 'defaultLayout')
    at useCalcLayout.js:6:1
    at Array.map (<anonymous>)
    at onUpdatePropsConfig (useCalcLayout.js:4:1)
    at useCalcPropsLayout (useCalcLayout.js:11:1)
    at DashKitView.js:17:1
    at renderWithHooks (react-dom.development.js:14985:1)
    at updateForwardRef (react-dom.development.js:17044:1)
    at beginWork (react-dom.development.js:19098:1)
    at HTMLUnknownElement.callCallback (react-dom.development.js:3945:1)
    at Object.invokeGuardedCallbackDev (react-dom.development.js:3994:1)

image

Code link

Update @yandex-cloud/i18n package version

Hi, the @yandex-cloud/i18n api is not out of 0.x.x yet so npm semver resolution does not pay attention to hats ^, so I was wondering if I could help you to migrate to new @yandex-cloud/i18n version 0.6.0

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.