├── tools
├── index.ts
├── workspace-plugin
│ ├── src
│ │ ├── executors
│ │ │ └── is-published
│ │ │ │ ├── schema.d.ts
│ │ │ │ └── schema.json
│ │ └── generators
│ │ │ └── viz-component
│ │ │ ├── files
│ │ │ ├── type.ts__tmpl__
│ │ │ ├── viz-__dashedName__.tsx__tmpl__
│ │ │ └── translation.ts__tmpl__
│ │ │ └── schema.json
│ ├── package.json
│ ├── executors.json
│ ├── generators.json
│ ├── tsconfig.lib.json
│ ├── tsconfig.json
│ ├── tsconfig.spec.json
│ ├── jest.config.ts
│ └── .eslintrc.json
├── tsconfig.plugin.json
└── tsconfig.tools.json
├── .dockerignore
├── .eslintignore
├── dashboard
├── src
│ ├── shared
│ ├── model
│ │ ├── utils
│ │ │ └── index.ts
│ │ ├── meta-model
│ │ │ ├── context
│ │ │ │ └── index.ts
│ │ │ ├── dashboard
│ │ │ │ ├── index.ts
│ │ │ │ └── content
│ │ │ │ │ ├── mock-context
│ │ │ │ │ └── index.ts
│ │ │ │ │ ├── sql-snippet
│ │ │ │ │ └── index.ts
│ │ │ │ │ ├── layout
│ │ │ │ │ └── index.ts
│ │ │ │ │ ├── view
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── widgets
│ │ │ │ │ │ └── index.ts
│ │ │ │ │ └── types.ts
│ │ │ │ │ ├── filter
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── widgets
│ │ │ │ │ │ └── index.ts
│ │ │ │ │ └── types.ts
│ │ │ │ │ ├── query
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── types.ts
│ │ │ │ │ ├── panel
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── style
│ │ │ │ │ │ └── index.ts
│ │ │ │ │ └── index.ts
│ │ │ ├── datasources
│ │ │ │ ├── index.ts
│ │ │ │ └── datasource.ts
│ │ │ ├── global-sql-snippets
│ │ │ │ ├── index.ts
│ │ │ │ └── global-sql-snippet.ts
│ │ │ └── index.ts
│ │ ├── render-model
│ │ │ ├── index.ts
│ │ │ └── dashboard
│ │ │ │ ├── index.ts
│ │ │ │ └── content
│ │ │ │ ├── layouts
│ │ │ │ └── index.ts
│ │ │ │ ├── filters
│ │ │ │ ├── types.ts
│ │ │ │ └── index.ts
│ │ │ │ ├── views
│ │ │ │ └── index.ts
│ │ │ │ ├── panels
│ │ │ │ └── index.ts
│ │ │ │ ├── queries
│ │ │ │ └── index.ts
│ │ │ │ ├── sql-snippets
│ │ │ │ ├── index.ts
│ │ │ │ ├── types.ts
│ │ │ │ └── utils.ts
│ │ │ │ └── index.ts
│ │ └── index.ts
│ ├── vite-env.d.ts
│ ├── types
│ │ ├── filter.ts
│ │ ├── index.ts
│ │ └── utils.ts
│ ├── dashboard-editor
│ │ ├── model
│ │ │ ├── layouts
│ │ │ │ └── index.ts
│ │ │ ├── datasources
│ │ │ │ ├── db-info
│ │ │ │ │ └── index.ts
│ │ │ │ ├── mm-info
│ │ │ │ │ └── index.ts
│ │ │ │ └── datasource.ts
│ │ │ ├── panels
│ │ │ │ └── index.ts
│ │ │ ├── queries
│ │ │ │ └── index.ts
│ │ │ └── index.ts
│ │ ├── index.ts
│ │ └── ui
│ │ │ ├── settings
│ │ │ ├── content
│ │ │ │ ├── edit-panel
│ │ │ │ │ └── variable-config
│ │ │ │ │ │ └── index.ts
│ │ │ │ ├── edit-query
│ │ │ │ │ └── merico-metric-query-editor-form
│ │ │ │ │ │ ├── query-tabs
│ │ │ │ │ │ ├── index.ts
│ │ │ │ │ │ └── edit-metric-query
│ │ │ │ │ │ │ ├── index.ts
│ │ │ │ │ │ │ ├── dimension-selector
│ │ │ │ │ │ │ ├── index.ts
│ │ │ │ │ │ │ └── dimension-icon
│ │ │ │ │ │ │ │ └── index.ts
│ │ │ │ │ │ │ └── table-styles.ts
│ │ │ │ │ │ ├── preview-data
│ │ │ │ │ │ └── index.ts
│ │ │ │ │ │ ├── preview-query-and-vars
│ │ │ │ │ │ └── index.ts
│ │ │ │ │ │ └── merico-icons
│ │ │ │ │ │ ├── types.ts
│ │ │ │ │ │ └── index.ts
│ │ │ │ ├── view-query-vars
│ │ │ │ │ └── index.tsx
│ │ │ │ ├── db-explorer-modal
│ │ │ │ │ └── db-explorer
│ │ │ │ │ │ ├── full-space-loading.tsx
│ │ │ │ │ │ └── structure
│ │ │ │ │ │ └── tooltip-value.tsx
│ │ │ │ └── edit-view
│ │ │ │ │ └── edit-view-form
│ │ │ │ │ └── config-fields
│ │ │ │ │ ├── modal
│ │ │ │ │ └── modal-title-editor
│ │ │ │ │ │ └── types.ts
│ │ │ │ │ └── index.tsx
│ │ │ └── navbar
│ │ │ │ └── nav-links.module.css
│ │ │ ├── header
│ │ │ ├── spotlight
│ │ │ │ └── index.ts
│ │ │ └── index.tsx
│ │ │ └── index.ts
│ ├── interactions
│ │ ├── trigger
│ │ │ └── index.ts
│ │ ├── hooks
│ │ │ ├── index.ts
│ │ │ ├── use-current-interaction-manager.ts
│ │ │ └── use-watch-triggers.ts
│ │ ├── operation
│ │ │ └── index.ts
│ │ ├── components
│ │ │ └── index.ts
│ │ ├── index.ts
│ │ └── interactions-viewer
│ │ │ ├── node-with-interactions
│ │ │ ├── index.css
│ │ │ └── types.ts
│ │ │ └── data
│ │ │ └── types.ts
│ ├── utils
│ │ ├── rich-text
│ │ │ └── index.ts
│ │ ├── template
│ │ │ ├── editor
│ │ │ │ ├── index.ts
│ │ │ │ ├── utils.ts
│ │ │ │ └── template-input.tsx
│ │ │ ├── render
│ │ │ │ └── index.ts
│ │ │ ├── index.ts
│ │ │ └── types.ts
│ │ ├── usage.ts
│ │ ├── mantine.ts
│ │ ├── shallow-to-js.ts
│ │ ├── color-feed.ts
│ │ ├── color-mapping.ts
│ │ ├── diff-json.ts
│ │ ├── index.ts
│ │ └── dashboard-state.ts
│ ├── components
│ │ ├── filter
│ │ │ ├── filter-select
│ │ │ │ └── editor
│ │ │ │ │ └── index.ts
│ │ │ ├── filter-merico-date-range
│ │ │ │ └── widget
│ │ │ │ │ └── calendar
│ │ │ │ │ └── index.ts
│ │ │ ├── filter-tree
│ │ │ │ ├── filter-tree-select
│ │ │ │ │ ├── editor
│ │ │ │ │ │ └── index.ts
│ │ │ │ │ ├── render
│ │ │ │ │ │ └── index.ts
│ │ │ │ │ └── index.ts
│ │ │ │ ├── filter-tree-single-select
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── editor
│ │ │ │ │ │ └── index.ts
│ │ │ │ │ └── render
│ │ │ │ │ │ └── index.ts
│ │ │ │ ├── index.ts
│ │ │ │ └── common
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── types.ts
│ │ │ │ │ └── query-data-to-tree.ts
│ │ │ ├── filter-settings
│ │ │ │ ├── types.ts
│ │ │ │ └── filter-settings.css
│ │ │ ├── use-update-filter-preview-values.ts
│ │ │ ├── error-message-or-not-found.tsx
│ │ │ └── filter-date-range
│ │ │ │ └── widget
│ │ │ │ └── hints.tsx
│ │ ├── plugins
│ │ │ ├── common-echarts-fields
│ │ │ │ ├── tooltip-metric
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── types.ts
│ │ │ │ ├── stats-around-viz
│ │ │ │ │ └── index.ts
│ │ │ │ ├── axis-label-rotate
│ │ │ │ │ └── index.ts
│ │ │ │ ├── regression-line
│ │ │ │ │ └── index.ts
│ │ │ │ ├── x-axis-position
│ │ │ │ │ ├── types.ts
│ │ │ │ │ └── index.ts
│ │ │ │ ├── y-axis-position
│ │ │ │ │ ├── types.ts
│ │ │ │ │ └── index.ts
│ │ │ │ ├── line-type
│ │ │ │ │ ├── types.ts
│ │ │ │ │ └── index.ts
│ │ │ │ ├── orientation
│ │ │ │ │ ├── types.ts
│ │ │ │ │ └── index.ts
│ │ │ │ ├── name-text-align
│ │ │ │ │ ├── types.ts
│ │ │ │ │ └── index.ts
│ │ │ │ ├── series-unit
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── types.ts
│ │ │ │ ├── symbol-size
│ │ │ │ │ └── index.ts
│ │ │ │ ├── line-area-style
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── types.ts
│ │ │ │ ├── series-order
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── types.ts
│ │ │ │ ├── label-position
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── types.ts
│ │ │ │ ├── visual-map
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── visual-map-editor
│ │ │ │ │ │ └── types.ts
│ │ │ │ ├── number-or-dynamic-value
│ │ │ │ │ └── index.ts
│ │ │ │ ├── axis-label-overflow
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── types.ts
│ │ │ │ └── x-axis-label-formatter
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── types.ts
│ │ │ ├── viz-components
│ │ │ │ ├── merico-stats
│ │ │ │ │ ├── migrators
│ │ │ │ │ │ ├── index.ts
│ │ │ │ │ │ └── v2.ts
│ │ │ │ │ └── triggers
│ │ │ │ │ │ └── index.ts
│ │ │ │ ├── stats
│ │ │ │ │ ├── triggers
│ │ │ │ │ │ └── index.ts
│ │ │ │ │ ├── type.ts
│ │ │ │ │ └── translation.ts
│ │ │ │ ├── pie-chart
│ │ │ │ │ ├── editors
│ │ │ │ │ │ ├── index.ts
│ │ │ │ │ │ └── pie-color-map-editor
│ │ │ │ │ │ │ ├── index.ts
│ │ │ │ │ │ │ └── palette.ts
│ │ │ │ │ ├── triggers
│ │ │ │ │ │ └── index.ts
│ │ │ │ │ └── option
│ │ │ │ │ │ ├── types.ts
│ │ │ │ │ │ └── index.ts
│ │ │ │ ├── button
│ │ │ │ │ ├── triggers
│ │ │ │ │ │ └── index.ts
│ │ │ │ │ └── translation.ts
│ │ │ │ ├── rich-text
│ │ │ │ │ ├── triggers
│ │ │ │ │ │ └── index.ts
│ │ │ │ │ └── type.ts
│ │ │ │ ├── cartesian
│ │ │ │ │ ├── option
│ │ │ │ │ │ ├── series
│ │ │ │ │ │ │ └── types.ts
│ │ │ │ │ │ └── utils
│ │ │ │ │ │ │ ├── types.ts
│ │ │ │ │ │ │ └── variables.ts
│ │ │ │ │ ├── triggers
│ │ │ │ │ │ └── index.ts
│ │ │ │ │ └── editors
│ │ │ │ │ │ ├── echarts-zooming-field
│ │ │ │ │ │ └── types.ts
│ │ │ │ │ │ └── tooltip
│ │ │ │ │ │ └── index.tsx
│ │ │ │ ├── heatmap
│ │ │ │ │ ├── triggers
│ │ │ │ │ │ └── index.ts
│ │ │ │ │ ├── option
│ │ │ │ │ │ ├── grid.ts
│ │ │ │ │ │ └── series.ts
│ │ │ │ │ └── editors
│ │ │ │ │ │ └── tooltip
│ │ │ │ │ │ └── index.tsx
│ │ │ │ ├── merico-linear-gauge
│ │ │ │ │ ├── render
│ │ │ │ │ │ └── index.ts
│ │ │ │ │ └── editor
│ │ │ │ │ │ ├── index.ts
│ │ │ │ │ │ └── sections-editor
│ │ │ │ │ │ ├── index.ts
│ │ │ │ │ │ └── palette.ts
│ │ │ │ ├── merico-panel-groups
│ │ │ │ │ ├── render
│ │ │ │ │ │ └── index.ts
│ │ │ │ │ ├── editor
│ │ │ │ │ │ └── index.ts
│ │ │ │ │ └── type.ts
│ │ │ │ ├── table
│ │ │ │ │ ├── triggers
│ │ │ │ │ │ └── index.ts
│ │ │ │ │ └── utils.ts
│ │ │ │ ├── boxplot-chart
│ │ │ │ │ ├── triggers
│ │ │ │ │ │ └── index.ts
│ │ │ │ │ ├── option
│ │ │ │ │ │ ├── series
│ │ │ │ │ │ │ └── custom
│ │ │ │ │ │ │ │ ├── index.ts
│ │ │ │ │ │ │ │ └── utils.ts
│ │ │ │ │ │ ├── type.ts
│ │ │ │ │ │ ├── common.ts
│ │ │ │ │ │ └── grid.ts
│ │ │ │ │ └── editors
│ │ │ │ │ │ └── tooltip
│ │ │ │ │ │ └── index.tsx
│ │ │ │ ├── merico-heatmap
│ │ │ │ │ ├── triggers
│ │ │ │ │ │ └── index.ts
│ │ │ │ │ ├── render
│ │ │ │ │ │ └── option
│ │ │ │ │ │ │ ├── grid.ts
│ │ │ │ │ │ │ └── series.ts
│ │ │ │ │ └── editors
│ │ │ │ │ │ └── tooltip
│ │ │ │ │ │ └── index.tsx
│ │ │ │ ├── pareto-chart
│ │ │ │ │ ├── triggers
│ │ │ │ │ │ └── index.ts
│ │ │ │ │ └── option
│ │ │ │ │ │ └── types.ts
│ │ │ │ ├── horizontal-bar-chart
│ │ │ │ │ ├── option
│ │ │ │ │ │ ├── series
│ │ │ │ │ │ │ └── types.ts
│ │ │ │ │ │ └── utils
│ │ │ │ │ │ │ ├── types.ts
│ │ │ │ │ │ │ └── variables.ts
│ │ │ │ │ └── triggers
│ │ │ │ │ │ └── index.ts
│ │ │ │ ├── calendar-heatmap
│ │ │ │ │ ├── triggers
│ │ │ │ │ │ └── index.ts
│ │ │ │ │ ├── option
│ │ │ │ │ │ └── legend.ts
│ │ │ │ │ └── editors
│ │ │ │ │ │ └── tooltip
│ │ │ │ │ │ └── index.tsx
│ │ │ │ ├── regression-chart
│ │ │ │ │ └── render
│ │ │ │ │ │ ├── toolbox
│ │ │ │ │ │ ├── choose-data-keys
│ │ │ │ │ │ │ └── index.ts
│ │ │ │ │ │ └── data-key-selector
│ │ │ │ │ │ │ └── index.ts
│ │ │ │ │ │ └── use-data-key.ts
│ │ │ │ ├── scatter-chart
│ │ │ │ │ ├── triggers
│ │ │ │ │ │ └── index.ts
│ │ │ │ │ └── option
│ │ │ │ │ │ ├── legend.ts
│ │ │ │ │ │ ├── dataset.ts
│ │ │ │ │ │ └── grid.ts
│ │ │ │ ├── viz-dashboard-state
│ │ │ │ │ ├── render
│ │ │ │ │ │ └── item
│ │ │ │ │ │ │ ├── selection-table.module.css
│ │ │ │ │ │ │ └── context-state.tsx
│ │ │ │ │ └── type.ts
│ │ │ │ ├── merico-estimation-chart
│ │ │ │ │ ├── option
│ │ │ │ │ │ └── series
│ │ │ │ │ │ │ └── utils.ts
│ │ │ │ │ ├── toolbox
│ │ │ │ │ │ └── index.tsx
│ │ │ │ │ └── translation.ts
│ │ │ │ ├── viz-merico-gqm
│ │ │ │ │ ├── type.ts
│ │ │ │ │ └── translation.ts
│ │ │ │ ├── radar-chart
│ │ │ │ │ └── option
│ │ │ │ │ │ ├── formatter.ts
│ │ │ │ │ │ └── series.label.ts
│ │ │ │ ├── bar-3d-chart
│ │ │ │ │ └── translation.ts
│ │ │ │ ├── funnel
│ │ │ │ │ └── option
│ │ │ │ │ │ └── index.ts
│ │ │ │ ├── sunburst
│ │ │ │ │ └── option
│ │ │ │ │ │ └── types.ts
│ │ │ │ └── text
│ │ │ │ │ ├── translation.ts
│ │ │ │ │ └── type.ts
│ │ │ ├── editor-components
│ │ │ │ ├── field-array-tabs
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── types.ts
│ │ │ │ ├── color-type
│ │ │ │ │ ├── type.ts
│ │ │ │ │ └── index.ts
│ │ │ │ ├── flex
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── type.ts
│ │ │ │ └── index.ts
│ │ │ ├── color-manager
│ │ │ │ ├── index.ts
│ │ │ │ ├── type.ts
│ │ │ │ └── color-manager.ts
│ │ │ ├── plugin-data-migrator
│ │ │ │ └── index.ts
│ │ │ ├── hooks
│ │ │ │ ├── index.ts
│ │ │ │ ├── use-tab-state.ts
│ │ │ │ ├── use-row-data-map.ts
│ │ │ │ ├── use-channel-event.ts
│ │ │ │ └── use-current-viz-instance.ts
│ │ │ ├── panel-addon
│ │ │ │ └── index.ts
│ │ │ ├── viz-manager
│ │ │ │ ├── index.ts
│ │ │ │ └── types.ts
│ │ │ ├── colors
│ │ │ │ ├── sequential-color.ts
│ │ │ │ └── diverging-color.ts
│ │ │ ├── message-channels.spec.ts
│ │ │ ├── index.ts
│ │ │ ├── message-channels.ts
│ │ │ └── test-utils.tsx
│ │ ├── view
│ │ │ ├── index.ts
│ │ │ ├── view-component
│ │ │ │ └── utils
│ │ │ │ │ └── index.ts
│ │ │ └── layout
│ │ │ │ ├── index.ts
│ │ │ │ └── index.css
│ │ ├── panel
│ │ │ ├── index.tsx
│ │ │ ├── panel-editor
│ │ │ │ └── dropdown-menu-items
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── dropdown-menu-items.tsx
│ │ │ ├── settings
│ │ │ │ └── common
│ │ │ │ │ └── variable-selector
│ │ │ │ │ └── index.ts
│ │ │ ├── panel-render
│ │ │ │ ├── full-screen-render
│ │ │ │ │ └── index.ts
│ │ │ │ ├── viz
│ │ │ │ │ ├── viz.css
│ │ │ │ │ └── index.ts
│ │ │ │ ├── index.ts
│ │ │ │ └── dropdown-menu-items
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── refresh.tsx
│ │ │ │ │ ├── download-data.tsx
│ │ │ │ │ ├── download-schema.tsx
│ │ │ │ │ └── dropdown-menu-items.tsx
│ │ │ ├── utils.ts
│ │ │ └── index.css
│ │ └── widgets
│ │ │ ├── rich-text-editor
│ │ │ ├── color-picker-control
│ │ │ │ └── index.ts
│ │ │ ├── line-height-mark
│ │ │ │ └── index.ts
│ │ │ ├── color-mapping-mark
│ │ │ │ └── index.ts
│ │ │ ├── dynamic-color-mark
│ │ │ │ └── index.ts
│ │ │ └── index.ts
│ │ │ ├── function-editor
│ │ │ ├── index.ts
│ │ │ └── types.ts
│ │ │ ├── color-picker-popover
│ │ │ └── index.ts
│ │ │ └── index.ts
│ ├── i18n
│ │ ├── index.ts
│ │ └── i18next-context.tsx
│ ├── dashboard-render
│ │ ├── index.ts
│ │ └── model
│ │ │ └── index.ts
│ ├── test
│ │ ├── setup.ts
│ │ └── test-utils.ts
│ ├── emotion.d.ts
│ ├── styles
│ │ ├── default-echarts-options
│ │ │ ├── index.ts
│ │ │ ├── tooltip.ts
│ │ │ ├── y-axis.ts
│ │ │ └── x-axis.ts
│ │ └── action-icon-group-style.ts
│ ├── global.d.ts
│ └── contexts
│ │ ├── render-content-model-context.ts
│ │ ├── customize-screenshot-context.ts
│ │ ├── index.ts
│ │ ├── dashboard-action-context.ts
│ │ ├── dashboard-theme-context.ts
│ │ ├── layout-state-context.ts
│ │ ├── additional-panel-menu-items.ts
│ │ └── dates-provider.tsx
├── tsconfig.test.json
├── cypress
│ ├── fixtures
│ │ └── example.json
│ └── support
│ │ └── component-index.html
├── tsconfig.node.json
├── tsconfig.cypress.json
├── .gitignore
└── index.html
├── website
├── src
│ ├── frames
│ │ ├── admin
│ │ │ ├── index.css
│ │ │ └── navbar
│ │ │ │ └── index.tsx
│ │ ├── app
│ │ │ ├── index.css
│ │ │ └── navbar-toggler.tsx
│ │ ├── socket-client-frame
│ │ │ ├── types.ts
│ │ │ └── socket-context.ts
│ │ └── dashboard-editor-frame
│ │ │ └── index.tsx
│ ├── contexts
│ │ └── index.ts
│ ├── global.d.ts
│ ├── api-caller
│ │ ├── status.typs.ts
│ │ ├── types.ts
│ │ ├── custom-function.types.ts
│ │ ├── dashboard.typed.ts
│ │ ├── dashboard.transform.ts
│ │ ├── status.ts
│ │ ├── custom-function.ts
│ │ ├── dashboard-content-changelog.types.ts
│ │ └── api-key.ts
│ ├── components
│ │ ├── readonly-monaco-editor
│ │ │ └── index.css
│ │ ├── account-type-icon.tsx
│ │ ├── load-favicon.tsx
│ │ └── logo
│ │ │ └── index.tsx
│ ├── types
│ │ └── dayjs-locale.d.ts
│ ├── pages
│ │ ├── dashboard-editor-page
│ │ │ ├── content-rebase-warning
│ │ │ │ └── rebase-editor
│ │ │ │ │ └── index.ts
│ │ │ ├── index.css
│ │ │ └── more-dashboard-info
│ │ │ │ ├── types.ts
│ │ │ │ ├── whos-editing
│ │ │ │ └── types.ts
│ │ │ │ ├── dashboard-changlog-modal
│ │ │ │ └── changelog-modal-trigger.tsx
│ │ │ │ ├── use-modal-states.ts
│ │ │ │ └── dashboard-header-menu-items.tsx
│ │ ├── dashboard-render-page
│ │ │ ├── content.css
│ │ │ ├── placeholder.tsx
│ │ │ └── index.tsx
│ │ ├── status-page
│ │ │ └── index.tsx
│ │ ├── account-page
│ │ │ └── index.tsx
│ │ ├── api-key-page
│ │ │ └── index.tsx
│ │ ├── data-source-page
│ │ │ └── index.tsx
│ │ └── sql-snippet-page
│ │ │ └── index.tsx
│ ├── emotion.d.ts
│ ├── utils
│ │ ├── dashboard-json-type-def.ts
│ │ └── configure-monaco-editor
│ │ │ └── index.ts
│ ├── vite-env.d.ts
│ └── index.css
├── .env.sample
├── README.md
├── tsconfig.node.json
├── cypress
│ ├── fixtures
│ │ └── example.json
│ └── support
│ │ └── component-index.html
├── tsconfig.cypress.json
├── .gitignore
├── index.html
└── cypress.config.ts
├── settings-form
├── README.md
├── src
│ ├── shared
│ ├── i18n
│ │ ├── index.ts
│ │ ├── i18next-context.tsx
│ │ └── i18n.ts
│ ├── vite-env.d.ts
│ ├── api-caller
│ │ ├── types.ts
│ │ ├── role.typed.ts
│ │ ├── api-key.typed.ts
│ │ ├── role.ts
│ │ ├── index.ts
│ │ └── account.typed.ts
│ ├── api-key
│ │ ├── index.tsx
│ │ └── styles.ts
│ ├── components
│ │ ├── index.ts
│ │ └── submit-form-button.tsx
│ ├── datasource
│ │ ├── index.tsx
│ │ ├── edit-data-source
│ │ │ └── types.ts
│ │ ├── add-data-source
│ │ │ └── types.ts
│ │ └── styles.ts
│ ├── sql_snippet
│ │ ├── index.tsx
│ │ └── styles.ts
│ ├── account
│ │ ├── index.tsx
│ │ └── styles.ts
│ ├── emotion.d.ts
│ ├── global.d.ts
│ └── utils
│ │ └── load-monaco-editor.ts
├── tsconfig.node.json
├── .gitignore
├── index.html
├── project.json
└── tsconfig.json
├── shared
├── src
│ ├── index.ts
│ └── api-client
│ │ └── index.ts
├── README.md
├── tsconfig.lib.json
├── project.json
├── .eslintrc.json
└── tsconfig.json
├── api
├── test-teardown-globals.js
├── src
│ ├── cli
│ │ └── clearCache.ts
│ ├── preset
│ │ ├── sql_snippets
│ │ │ ├── config.example.json
│ │ │ └── README.md
│ │ ├── custom_functions
│ │ │ ├── README.md
│ │ │ └── config.example.js
│ │ └── data_sources
│ │ │ └── README.md
│ ├── dashboard_migration
│ │ └── handlers
│ │ │ ├── 2.0.0.ts
│ │ │ ├── 2.1.0.ts
│ │ │ ├── 4.5.1.ts
│ │ │ ├── 4.5.0.ts
│ │ │ ├── 4.5.2.ts
│ │ │ ├── 4.5.3.ts
│ │ │ ├── 6.7.0.ts
│ │ │ ├── 5.9.1.ts
│ │ │ ├── 4.10.0.ts
│ │ │ ├── 5.9.2.ts
│ │ │ ├── 11.0.0.ts
│ │ │ ├── 4.14.1.ts
│ │ │ └── 9.11.0.ts
│ ├── api_models
│ │ └── cache.ts
│ ├── models
│ │ ├── dashboard_changelog.ts
│ │ ├── dashboard_content_changelog.ts
│ │ ├── role.ts
│ │ ├── sql_snippet.ts
│ │ ├── custom_function.ts
│ │ ├── base.ts
│ │ ├── job.ts
│ │ ├── dashboard_content.ts
│ │ ├── config.ts
│ │ └── dashboard_permission.ts
│ ├── plugins
│ │ └── index.js
│ ├── data_sources
│ │ ├── migrations
│ │ │ ├── 1660005273691-add-extension-citext.ts
│ │ │ └── 1675750180197-add-group-column-to-dashboard-table.ts
│ │ └── dashboard.ts
│ ├── middleware
│ │ ├── ensureAuthEnabled.ts
│ │ ├── localization.ts
│ │ └── permission.ts
│ └── utils
│ │ ├── logger.ts
│ │ └── constants.ts
├── tests
│ ├── e2e
│ │ ├── constants.ts
│ │ ├── tsconfig.json
│ │ ├── jest.mock.ts
│ │ └── 00_init_db.test.ts
│ ├── unit
│ │ ├── jest.setup.ts
│ │ └── tsconfig.json
│ └── integration
│ │ ├── tsconfig.json
│ │ ├── 00_seed.test.ts
│ │ └── jest.util.ts
├── tsconfig.json
├── swagger
│ └── assets
│ │ ├── favicon-16x16.png
│ │ └── favicon-32x32.png
├── tsconfig.dist.json
├── test.sequencer.js
├── jest-u.config.js
├── jest-i.config.js
├── jest.config.js
├── project.json
├── jest-e2e.config.js
└── base.json
├── .yarn
└── versions
│ ├── 34a1b820.yml
│ ├── 3fa39196.yml
│ ├── e4a2d889.yml
│ └── b2f619d3.yml
├── .prettierignore
├── jest.preset.js
├── .husky
└── pre-commit
├── Dockerfile-website
├── .prettierrc.js
├── .yarnrc.yml
├── jest.config.ts
├── .eslintrc.json
├── .vscode
└── settings.json
├── CHANGELOG.md
├── .github
└── renovate.json
└── Dockerfile-api
/tools/index.ts:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.dockerignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
--------------------------------------------------------------------------------
/dashboard/src/shared:
--------------------------------------------------------------------------------
1 | ../../shared/src
--------------------------------------------------------------------------------
/website/src/frames/admin/index.css:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/settings-form/README.md:
--------------------------------------------------------------------------------
1 | # Settings Form
2 |
--------------------------------------------------------------------------------
/settings-form/src/shared:
--------------------------------------------------------------------------------
1 | ../../shared/src
--------------------------------------------------------------------------------
/shared/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './api-client';
2 |
--------------------------------------------------------------------------------
/dashboard/src/model/utils/index.ts:
--------------------------------------------------------------------------------
1 | export * from './draft';
2 |
--------------------------------------------------------------------------------
/settings-form/src/i18n/index.ts:
--------------------------------------------------------------------------------
1 | export * from './i18n';
2 |
--------------------------------------------------------------------------------
/dashboard/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/settings-form/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/website/src/contexts/index.ts:
--------------------------------------------------------------------------------
1 | export * from './language-context';
2 |
--------------------------------------------------------------------------------
/dashboard/src/model/meta-model/context/index.ts:
--------------------------------------------------------------------------------
1 | export * from './context';
2 |
--------------------------------------------------------------------------------
/dashboard/src/model/render-model/index.ts:
--------------------------------------------------------------------------------
1 | export * from './dashboard';
2 |
--------------------------------------------------------------------------------
/dashboard/src/model/meta-model/dashboard/index.ts:
--------------------------------------------------------------------------------
1 | export * from './content';
2 |
--------------------------------------------------------------------------------
/dashboard/src/model/render-model/dashboard/index.ts:
--------------------------------------------------------------------------------
1 | export * from './content';
2 |
--------------------------------------------------------------------------------
/dashboard/src/types/filter.ts:
--------------------------------------------------------------------------------
1 | export { DashboardFilterType } from '~/model';
2 |
--------------------------------------------------------------------------------
/api/test-teardown-globals.js:
--------------------------------------------------------------------------------
1 | module.exports = () => {
2 | process.exit(0);
3 | };
4 |
--------------------------------------------------------------------------------
/dashboard/src/dashboard-editor/model/layouts/index.ts:
--------------------------------------------------------------------------------
1 | export * from './layouts';
2 |
--------------------------------------------------------------------------------
/dashboard/src/interactions/trigger/index.ts:
--------------------------------------------------------------------------------
1 | export * from './trigger-manager-impl';
2 |
--------------------------------------------------------------------------------
/dashboard/src/utils/rich-text/index.ts:
--------------------------------------------------------------------------------
1 | export * from './parse-rich-text-content';
2 |
--------------------------------------------------------------------------------
/website/.env.sample:
--------------------------------------------------------------------------------
1 | VITE_API_BASE_URL=http://localhost:31200/
2 | VITE_WEBSITE_BASE_URL=/
--------------------------------------------------------------------------------
/dashboard/src/components/filter/filter-select/editor/index.ts:
--------------------------------------------------------------------------------
1 | export * from './editor';
2 |
--------------------------------------------------------------------------------
/shared/README.md:
--------------------------------------------------------------------------------
1 | # shared
2 |
3 | This library was generated with [Nx](https://nx.dev).
4 |
--------------------------------------------------------------------------------
/.yarn/versions/34a1b820.yml:
--------------------------------------------------------------------------------
1 | undecided:
2 | - "@devtable/root"
3 | - "@devtable/dashboard"
4 |
--------------------------------------------------------------------------------
/.yarn/versions/3fa39196.yml:
--------------------------------------------------------------------------------
1 | undecided:
2 | - "@devtable/root"
3 | - "@devtable/dashboard"
4 |
--------------------------------------------------------------------------------
/.yarn/versions/e4a2d889.yml:
--------------------------------------------------------------------------------
1 | undecided:
2 | - "@devtable/root"
3 | - "@devtable/dashboard"
4 |
--------------------------------------------------------------------------------
/api/src/cli/clearCache.ts:
--------------------------------------------------------------------------------
1 | import { clearCache } from '../utils/cache';
2 |
3 | clearCache();
4 |
--------------------------------------------------------------------------------
/api/tests/e2e/constants.ts:
--------------------------------------------------------------------------------
1 | export const notFoundId = '3e7acce4-b8cd-4c01-b009-d2ea33a07258';
2 |
--------------------------------------------------------------------------------
/dashboard/src/dashboard-editor/model/datasources/db-info/index.ts:
--------------------------------------------------------------------------------
1 | export * from './db-info';
2 |
--------------------------------------------------------------------------------
/dashboard/src/i18n/index.ts:
--------------------------------------------------------------------------------
1 | export * from './i18n';
2 | export * from './i18next-context';
3 |
--------------------------------------------------------------------------------
/dashboard/src/model/render-model/dashboard/content/layouts/index.ts:
--------------------------------------------------------------------------------
1 | export * from './layouts';
2 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/common-echarts-fields/tooltip-metric/index.ts:
--------------------------------------------------------------------------------
1 | export * from './types';
2 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/merico-stats/migrators/index.ts:
--------------------------------------------------------------------------------
1 | export * from './v2';
2 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/stats/triggers/index.ts:
--------------------------------------------------------------------------------
1 | export * from './click-stats';
2 |
--------------------------------------------------------------------------------
/dashboard/src/components/view/index.ts:
--------------------------------------------------------------------------------
1 | export * from './view-editor';
2 | export * from './view-render';
3 |
--------------------------------------------------------------------------------
/dashboard/src/dashboard-editor/index.ts:
--------------------------------------------------------------------------------
1 | export * from './dashboard-editor';
2 | export * from './model';
3 |
--------------------------------------------------------------------------------
/dashboard/src/dashboard-render/index.ts:
--------------------------------------------------------------------------------
1 | export * from './dashboard-render';
2 | export * from './model';
3 |
--------------------------------------------------------------------------------
/dashboard/src/model/meta-model/dashboard/content/mock-context/index.ts:
--------------------------------------------------------------------------------
1 | export * from './mock-context';
2 |
--------------------------------------------------------------------------------
/dashboard/src/model/meta-model/dashboard/content/sql-snippet/index.ts:
--------------------------------------------------------------------------------
1 | export * from './sql-snippet';
2 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | .yarn/*
2 | **/*/dist
3 | api/swagger
4 | *.json
5 | *.html
6 | /.nx/cache
7 | /.nx/workspace-data
--------------------------------------------------------------------------------
/dashboard/src/components/filter/filter-merico-date-range/widget/calendar/index.ts:
--------------------------------------------------------------------------------
1 | export * from './calendar';
2 |
--------------------------------------------------------------------------------
/dashboard/src/components/panel/index.tsx:
--------------------------------------------------------------------------------
1 | export * from './panel-editor';
2 | export * from './panel-render';
3 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/pie-chart/editors/index.ts:
--------------------------------------------------------------------------------
1 | export * from './radius-slider';
2 |
--------------------------------------------------------------------------------
/dashboard/src/components/view/view-component/utils/index.ts:
--------------------------------------------------------------------------------
1 | export * from './use-download-div-screenshot';
2 |
--------------------------------------------------------------------------------
/dashboard/src/dashboard-editor/model/panels/index.ts:
--------------------------------------------------------------------------------
1 | export * from './panel';
2 | export * from './panels';
3 |
--------------------------------------------------------------------------------
/dashboard/src/dashboard-editor/model/queries/index.ts:
--------------------------------------------------------------------------------
1 | export * from './query';
2 | export * from './queries';
3 |
--------------------------------------------------------------------------------
/dashboard/src/utils/template/editor/index.ts:
--------------------------------------------------------------------------------
1 | export * from './template-input';
2 | export * from './utils';
3 |
--------------------------------------------------------------------------------
/api/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./base",
3 | "exclude": ["node_modules", "build", "_build", "tests"]
4 | }
5 |
--------------------------------------------------------------------------------
/dashboard/src/components/panel/panel-editor/dropdown-menu-items/index.ts:
--------------------------------------------------------------------------------
1 | export * from './dropdown-menu-items';
2 |
--------------------------------------------------------------------------------
/dashboard/src/components/panel/settings/common/variable-selector/index.ts:
--------------------------------------------------------------------------------
1 | export * from './variable-selector';
2 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/editor-components/field-array-tabs/index.ts:
--------------------------------------------------------------------------------
1 | export * from './field-array-tabs';
2 |
--------------------------------------------------------------------------------
/dashboard/src/components/view/layout/index.ts:
--------------------------------------------------------------------------------
1 | export * from './edit-layout';
2 | export * from './render-layout';
3 |
--------------------------------------------------------------------------------
/dashboard/src/utils/template/render/index.ts:
--------------------------------------------------------------------------------
1 | export * from './render-jsx';
2 | export * from './render-string';
3 |
--------------------------------------------------------------------------------
/jest.preset.js:
--------------------------------------------------------------------------------
1 | const nxPreset = require('@nx/jest/preset').default;
2 |
3 | module.exports = { ...nxPreset };
4 |
--------------------------------------------------------------------------------
/website/src/global.d.ts:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
2 | type $TSFixMe = any;
3 |
--------------------------------------------------------------------------------
/.husky/pre-commit:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 | . "$(dirname -- "$0")/_/husky.sh"
3 |
4 | yarn exec nx format --uncommitted
5 |
--------------------------------------------------------------------------------
/api/tests/unit/jest.setup.ts:
--------------------------------------------------------------------------------
1 | module.exports = async (globalConfig) => {
2 | process.env.ENABLE_AUTH = '1';
3 | };
4 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/color-manager/index.ts:
--------------------------------------------------------------------------------
1 | export * from './color-manager';
2 | export * from './impl';
3 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/common-echarts-fields/stats-around-viz/index.ts:
--------------------------------------------------------------------------------
1 | export * from './stats-around-viz';
2 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/button/triggers/index.ts:
--------------------------------------------------------------------------------
1 | export { ClickButton } from './click-button';
2 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/merico-stats/triggers/index.ts:
--------------------------------------------------------------------------------
1 | export * from './click-merico-stats';
2 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/rich-text/triggers/index.ts:
--------------------------------------------------------------------------------
1 | export * from './click-rich-text-block';
2 |
--------------------------------------------------------------------------------
/dashboard/src/components/widgets/rich-text-editor/color-picker-control/index.ts:
--------------------------------------------------------------------------------
1 | export * from './color-picker-control';
2 |
--------------------------------------------------------------------------------
/dashboard/src/model/meta-model/datasources/index.ts:
--------------------------------------------------------------------------------
1 | export * from './datasources';
2 | export * from './datasource';
3 |
--------------------------------------------------------------------------------
/dashboard/src/model/render-model/dashboard/content/filters/types.ts:
--------------------------------------------------------------------------------
1 | export type FilterValuesType = Record;
2 |
--------------------------------------------------------------------------------
/dashboard/src/model/render-model/dashboard/content/views/index.ts:
--------------------------------------------------------------------------------
1 | export * from './view';
2 | export * from './views';
3 |
--------------------------------------------------------------------------------
/website/src/api-caller/status.typs.ts:
--------------------------------------------------------------------------------
1 | export type VersionResp = {
2 | semver: string;
3 | version: string;
4 | };
5 |
--------------------------------------------------------------------------------
/Dockerfile-website:
--------------------------------------------------------------------------------
1 | FROM nginx
2 |
3 | COPY ./website/dist /usr/share/nginx/html
4 |
5 | CMD exec nginx -g 'daemon off;'
6 |
--------------------------------------------------------------------------------
/api/swagger/assets/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/merico-dev/table/HEAD/api/swagger/assets/favicon-16x16.png
--------------------------------------------------------------------------------
/api/swagger/assets/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/merico-dev/table/HEAD/api/swagger/assets/favicon-32x32.png
--------------------------------------------------------------------------------
/dashboard/src/components/filter/filter-tree/filter-tree-select/editor/index.ts:
--------------------------------------------------------------------------------
1 | export * from './filter-tree-select-editor';
2 |
--------------------------------------------------------------------------------
/dashboard/src/components/filter/filter-tree/filter-tree-select/render/index.ts:
--------------------------------------------------------------------------------
1 | export * from './filter-tree-select-render';
2 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/common-echarts-fields/axis-label-rotate/index.ts:
--------------------------------------------------------------------------------
1 | export * from './axis-label-rotate-input';
2 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/cartesian/option/series/types.ts:
--------------------------------------------------------------------------------
1 | export type DataTemplateType = [string, 0];
2 |
--------------------------------------------------------------------------------
/dashboard/src/components/widgets/function-editor/index.ts:
--------------------------------------------------------------------------------
1 | export * from './function-editor';
2 | export * from './types';
3 |
--------------------------------------------------------------------------------
/dashboard/src/dashboard-editor/ui/settings/content/edit-panel/variable-config/index.ts:
--------------------------------------------------------------------------------
1 | export * from './variables-editor';
2 |
--------------------------------------------------------------------------------
/dashboard/src/model/index.ts:
--------------------------------------------------------------------------------
1 | export * from './meta-model';
2 | export * from './render-model';
3 | export * from './utils';
4 |
--------------------------------------------------------------------------------
/dashboard/src/model/render-model/dashboard/content/filters/index.ts:
--------------------------------------------------------------------------------
1 | export * from './filters';
2 | export * from './types';
3 |
--------------------------------------------------------------------------------
/.yarn/versions/b2f619d3.yml:
--------------------------------------------------------------------------------
1 | undecided:
2 | - "@devtable/root"
3 | - "@devtable/settings-form"
4 | - "@devtable/website"
5 |
--------------------------------------------------------------------------------
/api/src/preset/sql_snippets/config.example.json:
--------------------------------------------------------------------------------
1 | {
2 | "snippet1": "test snippet 1",
3 | "snippet2": "test snippet 2"
4 | }
5 |
--------------------------------------------------------------------------------
/dashboard/src/components/filter/filter-tree/filter-tree-select/index.ts:
--------------------------------------------------------------------------------
1 | export * from './editor';
2 | export * from './render';
3 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/cartesian/triggers/index.ts:
--------------------------------------------------------------------------------
1 | export { ClickEchartSeries } from './click-echart';
2 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/heatmap/triggers/index.ts:
--------------------------------------------------------------------------------
1 | export { ClickHeatBlock } from './click-heat-block';
2 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/merico-linear-gauge/render/index.ts:
--------------------------------------------------------------------------------
1 | export * from './viz-merico-linear-gauge';
2 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/merico-panel-groups/render/index.ts:
--------------------------------------------------------------------------------
1 | export * from './viz-merico-panel-groups';
2 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/pie-chart/triggers/index.ts:
--------------------------------------------------------------------------------
1 | export { ClickPieChart } from './click-pie-chart';
2 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/table/triggers/index.ts:
--------------------------------------------------------------------------------
1 | export { ClickCellContent } from './click-cell-content';
2 |
--------------------------------------------------------------------------------
/dashboard/src/model/meta-model/dashboard/content/layout/index.ts:
--------------------------------------------------------------------------------
1 | export * from './layout-item';
2 | export * from './layout-set';
3 |
--------------------------------------------------------------------------------
/dashboard/src/components/filter/filter-tree/filter-tree-single-select/index.ts:
--------------------------------------------------------------------------------
1 | export * from './editor';
2 | export * from './render';
3 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/common-echarts-fields/regression-line/index.ts:
--------------------------------------------------------------------------------
1 | export * from './option';
2 | export * from './types';
3 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/common-echarts-fields/x-axis-position/types.ts:
--------------------------------------------------------------------------------
1 | export type EChartsXAxisPosition = 'top' | 'bottom';
2 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/common-echarts-fields/y-axis-position/types.ts:
--------------------------------------------------------------------------------
1 | export type EChartsYAxisPosition = 'left' | 'right';
2 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/editor-components/color-type/type.ts:
--------------------------------------------------------------------------------
1 | export type ColorType = 'static' | 'interpolation' | 'none';
2 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/boxplot-chart/triggers/index.ts:
--------------------------------------------------------------------------------
1 | export { ClickBoxplotSeries } from './click-boxplot';
2 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/merico-heatmap/triggers/index.ts:
--------------------------------------------------------------------------------
1 | export { ClickHeatBlock } from './click-heat-block';
2 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/merico-linear-gauge/editor/index.ts:
--------------------------------------------------------------------------------
1 | export * from './viz-merico-linear-gauge-editor';
2 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/merico-linear-gauge/editor/sections-editor/index.ts:
--------------------------------------------------------------------------------
1 | export * from './sections-editor';
2 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/merico-panel-groups/editor/index.ts:
--------------------------------------------------------------------------------
1 | export * from './viz-merico-panel-groups-editor';
2 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/pareto-chart/triggers/index.ts:
--------------------------------------------------------------------------------
1 | export { ClickParetoSeries } from './click-pareto';
2 |
--------------------------------------------------------------------------------
/dashboard/src/interactions/hooks/index.ts:
--------------------------------------------------------------------------------
1 | export * from './use-watch-triggers';
2 | export * from './use-current-interaction-manager';
3 |
--------------------------------------------------------------------------------
/dashboard/src/test/setup.ts:
--------------------------------------------------------------------------------
1 | import '@testing-library/jest-dom';
2 | import { vi } from 'vitest';
3 | global.jest = vi as $TSFixMe;
4 |
--------------------------------------------------------------------------------
/dashboard/src/components/filter/filter-tree/filter-tree-single-select/editor/index.ts:
--------------------------------------------------------------------------------
1 | export * from './filter-tree-single-select-editor';
2 |
--------------------------------------------------------------------------------
/dashboard/src/components/filter/filter-tree/filter-tree-single-select/render/index.ts:
--------------------------------------------------------------------------------
1 | export * from './filter-tree-single-select-render';
2 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/common-echarts-fields/line-type/types.ts:
--------------------------------------------------------------------------------
1 | export type IEChartsLineType = 'solid' | 'dashed' | 'dotted';
2 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/common-echarts-fields/orientation/types.ts:
--------------------------------------------------------------------------------
1 | export type ChartingOrientation = 'horizontal' | 'vertical';
2 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/editor-components/color-type/index.ts:
--------------------------------------------------------------------------------
1 | export * from './color-type-selector';
2 | export * from './type';
3 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/horizontal-bar-chart/option/series/types.ts:
--------------------------------------------------------------------------------
1 | export type DataTemplateType = [string, 0];
2 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/horizontal-bar-chart/triggers/index.ts:
--------------------------------------------------------------------------------
1 | export * from './click-horizontal-bar-chart-series';
2 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/pie-chart/editors/pie-color-map-editor/index.ts:
--------------------------------------------------------------------------------
1 | export * from './pie-color-map-editor';
2 |
--------------------------------------------------------------------------------
/dashboard/src/dashboard-editor/ui/header/spotlight/index.ts:
--------------------------------------------------------------------------------
1 | export * from './editor-spotlight';
2 | export * from './spotlight-control';
3 |
--------------------------------------------------------------------------------
/tools/workspace-plugin/src/executors/is-published/schema.d.ts:
--------------------------------------------------------------------------------
1 | export interface IsPublishedExecutorSchema {
2 | packageJson: string;
3 | }
4 |
--------------------------------------------------------------------------------
/website/src/api-caller/types.ts:
--------------------------------------------------------------------------------
1 | export type PaginationResponse = {
2 | total: number;
3 | offset: number;
4 | data: T[];
5 | };
6 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/common-echarts-fields/line-type/index.ts:
--------------------------------------------------------------------------------
1 | export * from './line-type-selector';
2 | export * from './types';
3 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/common-echarts-fields/name-text-align/types.ts:
--------------------------------------------------------------------------------
1 | export type EChartsNameTextAlign = 'left' | 'center' | 'right';
2 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/common-echarts-fields/orientation/index.ts:
--------------------------------------------------------------------------------
1 | export * from './orientation-selector';
2 | export * from './types';
3 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/common-echarts-fields/series-unit/index.ts:
--------------------------------------------------------------------------------
1 | export * from './series-unit-field';
2 | export * from './types';
3 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/common-echarts-fields/symbol-size/index.ts:
--------------------------------------------------------------------------------
1 | export * from './symbol-size-selector';
2 | export * from './types';
3 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/calendar-heatmap/triggers/index.ts:
--------------------------------------------------------------------------------
1 | export { ClickCalendarDate } from './click-calendar-date';
2 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/regression-chart/render/toolbox/choose-data-keys/index.ts:
--------------------------------------------------------------------------------
1 | export * from './choose-data-keys';
2 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/regression-chart/render/toolbox/data-key-selector/index.ts:
--------------------------------------------------------------------------------
1 | export * from './data-key-selector';
2 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/scatter-chart/triggers/index.ts:
--------------------------------------------------------------------------------
1 | export { ClickScatterChartSeries } from './click-scatter-chart';
2 |
--------------------------------------------------------------------------------
/dashboard/src/dashboard-editor/ui/settings/content/edit-query/merico-metric-query-editor-form/query-tabs/index.ts:
--------------------------------------------------------------------------------
1 | export * from './query-tabs';
2 |
--------------------------------------------------------------------------------
/dashboard/src/interactions/operation/index.ts:
--------------------------------------------------------------------------------
1 | export * from './operations';
2 | export { OperationManager } from './operation-manager-impl';
3 |
--------------------------------------------------------------------------------
/dashboard/src/model/meta-model/global-sql-snippets/index.ts:
--------------------------------------------------------------------------------
1 | export * from './global-sql-snippet';
2 | export * from './global-sql-snippets';
3 |
--------------------------------------------------------------------------------
/dashboard/src/types/index.ts:
--------------------------------------------------------------------------------
1 | export * from './dashboard';
2 | export * from './filter';
3 | export type { AnyObject, Ready } from './utils';
4 |
--------------------------------------------------------------------------------
/settings-form/src/api-caller/types.ts:
--------------------------------------------------------------------------------
1 | export type PaginationResponse = {
2 | total: number;
3 | offset: number;
4 | data: T[];
5 | };
6 |
--------------------------------------------------------------------------------
/settings-form/src/api-key/index.tsx:
--------------------------------------------------------------------------------
1 | export * from './add-api-key';
2 | export * from './api-key-list';
3 | export * from './delete-api-key';
4 |
--------------------------------------------------------------------------------
/.prettierrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | printWidth: 120,
3 | singleQuote: true,
4 | trailingComma: 'all',
5 | jsxSingleQuote: false,
6 | };
7 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/common-echarts-fields/line-area-style/index.ts:
--------------------------------------------------------------------------------
1 | export * from './line-area-style-field';
2 | export * from './types';
3 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/common-echarts-fields/series-order/index.ts:
--------------------------------------------------------------------------------
1 | export * from './series-order-selector';
2 | export * from './types';
3 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/plugin-data-migrator/index.ts:
--------------------------------------------------------------------------------
1 | export * from './plugin-data-migrator';
2 | export * from './version-based-migrator';
3 |
--------------------------------------------------------------------------------
/dashboard/src/dashboard-editor/ui/settings/content/edit-query/merico-metric-query-editor-form/preview-data/index.ts:
--------------------------------------------------------------------------------
1 | export * from './preview-data';
2 |
--------------------------------------------------------------------------------
/dashboard/src/model/meta-model/dashboard/content/view/index.ts:
--------------------------------------------------------------------------------
1 | export * from './view';
2 | export * from './widgets';
3 | export * from './types';
4 |
--------------------------------------------------------------------------------
/settings-form/src/api-caller/role.typed.ts:
--------------------------------------------------------------------------------
1 | export interface IRole {
2 | id: string;
3 | description: string;
4 | permissions: string[];
5 | }
6 |
--------------------------------------------------------------------------------
/website/src/components/readonly-monaco-editor/index.css:
--------------------------------------------------------------------------------
1 | .website-readonly-monaco-editor {
2 | border-radius: 0px;
3 | overflow: hidden;
4 | }
5 |
--------------------------------------------------------------------------------
/website/src/types/dayjs-locale.d.ts:
--------------------------------------------------------------------------------
1 | declare module 'dayjs/locale/*' {
2 | const locale: Record;
3 | export default locale;
4 | }
5 |
--------------------------------------------------------------------------------
/.yarnrc.yml:
--------------------------------------------------------------------------------
1 | compressionLevel: mixed
2 |
3 | enableGlobalCache: false
4 |
5 | nodeLinker: node-modules
6 |
7 | yarnPath: .yarn/releases/yarn-4.12.0.cjs
8 |
--------------------------------------------------------------------------------
/dashboard/src/components/panel/panel-render/full-screen-render/index.ts:
--------------------------------------------------------------------------------
1 | export * from './full-screen-panel';
2 | export * from './use-panel-full-screen';
3 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/common-echarts-fields/label-position/index.ts:
--------------------------------------------------------------------------------
1 | export * from './label-position-selector';
2 | export * from './types';
3 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/common-echarts-fields/name-text-align/index.ts:
--------------------------------------------------------------------------------
1 | export * from './name-text-align-selector';
2 | export * from './types';
3 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/common-echarts-fields/x-axis-position/index.ts:
--------------------------------------------------------------------------------
1 | export * from './x-axis-position-selector';
2 | export * from './types';
3 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/common-echarts-fields/y-axis-position/index.ts:
--------------------------------------------------------------------------------
1 | export * from './y-axis-position-selector';
2 | export * from './types';
3 |
--------------------------------------------------------------------------------
/dashboard/src/model/meta-model/dashboard/content/filter/index.ts:
--------------------------------------------------------------------------------
1 | export * from './filter';
2 | export * from './types';
3 | export * from './widgets';
4 |
--------------------------------------------------------------------------------
/dashboard/src/model/render-model/dashboard/content/panels/index.ts:
--------------------------------------------------------------------------------
1 | export * from './panel';
2 | export * from './panels';
3 | export * from './types';
4 |
--------------------------------------------------------------------------------
/dashboard/src/utils/template/index.ts:
--------------------------------------------------------------------------------
1 | export * from './editor';
2 | export * from './render';
3 | export * from './types';
4 | export * from './utils';
5 |
--------------------------------------------------------------------------------
/settings-form/src/components/index.ts:
--------------------------------------------------------------------------------
1 | export * from './minimal-mocaco-editor';
2 | export * from './submit-form-button';
3 | export * from './with-entry';
4 |
--------------------------------------------------------------------------------
/dashboard/src/model/meta-model/dashboard/content/view/widgets/index.ts:
--------------------------------------------------------------------------------
1 | export * from './division';
2 | export * from './modal';
3 | export * from './tabs';
4 |
--------------------------------------------------------------------------------
/dashboard/src/model/render-model/dashboard/content/queries/index.ts:
--------------------------------------------------------------------------------
1 | export * from './queries';
2 | export * from './query';
3 | export * from './mute-query';
4 |
--------------------------------------------------------------------------------
/jest.config.ts:
--------------------------------------------------------------------------------
1 | import { getJestProjectsAsync } from '@nx/jest';
2 |
3 | export default async () => ({
4 | projects: await getJestProjectsAsync(),
5 | });
6 |
--------------------------------------------------------------------------------
/settings-form/src/datasource/index.tsx:
--------------------------------------------------------------------------------
1 | export * from './add-data-source';
2 | export * from './data-source-list';
3 | export * from './delete-data-source';
4 |
--------------------------------------------------------------------------------
/website/README.md:
--------------------------------------------------------------------------------
1 | # Dashboard Demo
2 |
3 | ## Development
4 |
5 | ```bash
6 | $ nx dev website
7 | ```
8 |
9 | see `package.json` for more scripts
10 |
--------------------------------------------------------------------------------
/dashboard/src/dashboard-render/model/index.ts:
--------------------------------------------------------------------------------
1 | export * from './dashboard';
2 | export * from './content';
3 | export { type IContentRenderModel } from './types';
4 |
--------------------------------------------------------------------------------
/dashboard/src/model/meta-model/dashboard/content/query/index.ts:
--------------------------------------------------------------------------------
1 | export * from './query';
2 | export * from './types';
3 | export * from './merico-metric-query';
4 |
--------------------------------------------------------------------------------
/dashboard/src/components/filter/filter-tree/index.ts:
--------------------------------------------------------------------------------
1 | export * from './filter-tree-select';
2 | export * from './filter-tree-single-select';
3 | export * from './common';
4 |
--------------------------------------------------------------------------------
/dashboard/src/components/panel/panel-render/viz/viz.css:
--------------------------------------------------------------------------------
1 | .viz-root {
2 | width: 100%;
3 | overflow: auto;
4 | flex-grow: 1;
5 | background-color: white;
6 | }
7 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/common-echarts-fields/visual-map/index.ts:
--------------------------------------------------------------------------------
1 | export * from './visual-map-editor';
2 | export * from './types';
3 | export * from './utils';
4 |
--------------------------------------------------------------------------------
/dashboard/src/dashboard-editor/ui/settings/content/edit-query/merico-metric-query-editor-form/preview-query-and-vars/index.ts:
--------------------------------------------------------------------------------
1 | export * from './preview-query-and-vars';
2 |
--------------------------------------------------------------------------------
/dashboard/src/dashboard-editor/ui/settings/content/edit-query/merico-metric-query-editor-form/query-tabs/edit-metric-query/index.ts:
--------------------------------------------------------------------------------
1 | export * from './edit-metric-query';
2 |
--------------------------------------------------------------------------------
/dashboard/src/model/meta-model/dashboard/content/view/types.ts:
--------------------------------------------------------------------------------
1 | export enum EViewComponentType {
2 | Division = 'div',
3 | Modal = 'modal',
4 | Tabs = 'tabs',
5 | }
6 |
--------------------------------------------------------------------------------
/shared/src/api-client/index.ts:
--------------------------------------------------------------------------------
1 | export * from './types';
2 | export * from './utils';
3 | export * from './default-api-client';
4 | export * from './facade-api-client';
5 |
--------------------------------------------------------------------------------
/dashboard/src/components/panel/panel-render/viz/index.ts:
--------------------------------------------------------------------------------
1 | export * from './viz';
2 | export * from './panel-error-or-state-message';
3 | export * from './panel-viz-section';
4 |
--------------------------------------------------------------------------------
/dashboard/src/dashboard-editor/ui/index.ts:
--------------------------------------------------------------------------------
1 | export * from './header';
2 | export * from './navbar';
3 | export * from './settings';
4 | export * from './header/spotlight';
5 |
--------------------------------------------------------------------------------
/api/src/preset/sql_snippets/README.md:
--------------------------------------------------------------------------------
1 | To add preset sql snippets, make a copy of config.example.json and rename it to config.json.
2 | Modify the file according to the examples.
3 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/boxplot-chart/option/series/custom/index.ts:
--------------------------------------------------------------------------------
1 | export * from './box';
2 | export * from './scatter';
3 | export * from './outliers';
4 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/boxplot-chart/option/type.ts:
--------------------------------------------------------------------------------
1 | export type SeriesNames = {
2 | Box: string;
3 | Scatter: string;
4 | Outlier: string;
5 | };
6 |
--------------------------------------------------------------------------------
/dashboard/src/model/meta-model/index.ts:
--------------------------------------------------------------------------------
1 | export * from './dashboard';
2 | export * from './datasources';
3 | export * from './global-sql-snippets';
4 | export * from './context';
5 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/editor-components/flex/index.ts:
--------------------------------------------------------------------------------
1 | export * from './justify-content-selector';
2 | export * from './align-items-selector';
3 | export * from './type';
4 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/hooks/index.ts:
--------------------------------------------------------------------------------
1 | export * from './use-channel-event';
2 | export * from './use-storage-data';
3 | export * from './use-handle-chart-render-finished';
4 |
--------------------------------------------------------------------------------
/dashboard/src/components/widgets/rich-text-editor/line-height-mark/index.ts:
--------------------------------------------------------------------------------
1 | export * from './line-height-mark';
2 | export * from './line-height-control';
3 | export * from './utils';
4 |
--------------------------------------------------------------------------------
/website/src/pages/dashboard-editor-page/content-rebase-warning/rebase-editor/index.ts:
--------------------------------------------------------------------------------
1 | export * from './rebase-dashboard-config-modal';
2 | export { diffNodes } from './diff-nodes';
3 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/pareto-chart/option/types.ts:
--------------------------------------------------------------------------------
1 | export type TLineDataItem = [string | number, number];
2 | export type BarData = [string | number, number][];
3 |
--------------------------------------------------------------------------------
/dashboard/src/components/widgets/rich-text-editor/color-mapping-mark/index.ts:
--------------------------------------------------------------------------------
1 | export * from './color-mapping-mark';
2 | export * from './color-mapping-control';
3 | export * from './utils';
4 |
--------------------------------------------------------------------------------
/dashboard/src/components/widgets/rich-text-editor/dynamic-color-mark/index.ts:
--------------------------------------------------------------------------------
1 | export * from './dynamic-color-mark';
2 | export * from './dynamic-color-control';
3 | export * from './utils';
4 |
--------------------------------------------------------------------------------
/dashboard/src/dashboard-editor/ui/settings/content/edit-query/merico-metric-query-editor-form/query-tabs/edit-metric-query/dimension-selector/index.ts:
--------------------------------------------------------------------------------
1 | export * from './dimension-selector';
2 |
--------------------------------------------------------------------------------
/settings-form/src/api-caller/api-key.typed.ts:
--------------------------------------------------------------------------------
1 | export interface IAPIKey {
2 | id: string;
3 | name: string;
4 | role_id: string;
5 | app_id: string;
6 | app_secret: string;
7 | }
8 |
--------------------------------------------------------------------------------
/dashboard/src/components/filter/filter-settings/types.ts:
--------------------------------------------------------------------------------
1 | import { FilterMetaInstance } from '~/model';
2 |
3 | export interface IFilterSettingsForm {
4 | filters: FilterMetaInstance[];
5 | }
6 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/common-echarts-fields/number-or-dynamic-value/index.ts:
--------------------------------------------------------------------------------
1 | export * from './field';
2 | export * from './get-number-or-dynamic-value';
3 | export * from './types';
4 |
--------------------------------------------------------------------------------
/dashboard/src/interactions/components/index.ts:
--------------------------------------------------------------------------------
1 | export { InteractionSettingsPanel } from './interaction-settings';
2 | export { VariableList, type IVariableListProps } from './variable-list';
3 |
--------------------------------------------------------------------------------
/dashboard/src/dashboard-editor/ui/settings/content/edit-query/merico-metric-query-editor-form/query-tabs/edit-metric-query/dimension-selector/dimension-icon/index.ts:
--------------------------------------------------------------------------------
1 | export * from './dimension-icon';
2 |
--------------------------------------------------------------------------------
/dashboard/src/model/render-model/dashboard/content/sql-snippets/index.ts:
--------------------------------------------------------------------------------
1 | export * from './sql-snippet';
2 | export * from './sql-snippets';
3 | export * from './types';
4 | export * from './utils';
5 |
--------------------------------------------------------------------------------
/settings-form/src/sql_snippet/index.tsx:
--------------------------------------------------------------------------------
1 | export * from './add-sql_snippet';
2 | export * from './update-sql_snippet';
3 | export * from './sql_snippet-list';
4 | export * from './delete-sql_snippet';
5 |
--------------------------------------------------------------------------------
/website/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "composite": true,
4 | "module": "esnext",
5 | "moduleResolution": "node"
6 | },
7 | "include": ["vite.config.ts"]
8 | }
9 |
--------------------------------------------------------------------------------
/api/src/preset/custom_functions/README.md:
--------------------------------------------------------------------------------
1 | To add preset custom functions, make a copy of config.example.js and rename it to config.js.
2 | It is advised to use arrow functions for function definitions.
3 |
--------------------------------------------------------------------------------
/dashboard/src/components/panel/utils.ts:
--------------------------------------------------------------------------------
1 | export function doesVizRequiresData(type: string) {
2 | const vizTypes = ['richText', 'button', 'vizDashboardState'];
3 | return !vizTypes.includes(type);
4 | }
5 |
--------------------------------------------------------------------------------
/dashboard/src/dashboard-editor/model/datasources/mm-info/index.ts:
--------------------------------------------------------------------------------
1 | export * from './mm-info';
2 | export * from './metric-detail';
3 | export * from './metric-detail.types';
4 | export * from './metrics';
5 |
--------------------------------------------------------------------------------
/dashboard/src/interactions/index.ts:
--------------------------------------------------------------------------------
1 | export * from './hooks';
2 | export * from './components';
3 | export * from './operation';
4 | export * from './trigger';
5 | export * from './interaction-manager';
6 |
--------------------------------------------------------------------------------
/settings-form/src/datasource/edit-data-source/types.ts:
--------------------------------------------------------------------------------
1 | import { TDataSourceConfig } from '../../api-caller/datasource.typed';
2 |
3 | export interface IFormValues {
4 | config: TDataSourceConfig;
5 | }
6 |
--------------------------------------------------------------------------------
/website/src/pages/dashboard-render-page/content.css:
--------------------------------------------------------------------------------
1 | .dashboard-page-content {
2 | display: flex;
3 | flex-direction: column;
4 | flex-wrap: nowrap;
5 | height: 100%;
6 | overflow: hidden;
7 | }
8 |
--------------------------------------------------------------------------------
/dashboard/src/components/panel/index.css:
--------------------------------------------------------------------------------
1 | .panel-root {
2 | height: 100%;
3 | width: 100%;
4 | max-width: 100%;
5 | background: transparent;
6 | border-radius: 4px;
7 | position: relative;
8 | }
9 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/panel-addon/index.ts:
--------------------------------------------------------------------------------
1 | export * from './panel-addon-manager';
2 | export { PanelAddonProvider, usePanelAddonSlot } from '~/components/panel/panel-render/panel-addon-context';
3 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/rich-text/type.ts:
--------------------------------------------------------------------------------
1 | export interface IRichTextConf {
2 | content: '';
3 | }
4 |
5 | export const DEFAULT_CONFIG: IRichTextConf = {
6 | content: '',
7 | };
8 |
--------------------------------------------------------------------------------
/dashboard/src/model/meta-model/dashboard/content/panel/index.ts:
--------------------------------------------------------------------------------
1 | export * from './panel';
2 | export * from './viz';
3 | export * from './style';
4 | export * from './title';
5 | export * from './variable';
6 |
--------------------------------------------------------------------------------
/dashboard/tsconfig.test.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "include": ["src", "**/*.spec.ts"],
4 | "exclude": [],
5 | "compilerOptions": {
6 | "types": ["vitest/globals"]
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/tools/workspace-plugin/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "workspace-plugin",
3 | "version": "0.0.1",
4 | "type": "commonjs",
5 | "generators": "./generators.json",
6 | "executors": "./executors.json"
7 | }
8 |
--------------------------------------------------------------------------------
/website/cypress/fixtures/example.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Using fixtures to represent data",
3 | "email": "hello@cypress.io",
4 | "body": "Fixtures are a great way to mock data for responses to routes"
5 | }
6 |
--------------------------------------------------------------------------------
/dashboard/cypress/fixtures/example.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Using fixtures to represent data",
3 | "email": "hello@cypress.io",
4 | "body": "Fixtures are a great way to mock data for responses to routes"
5 | }
6 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/common-echarts-fields/visual-map/visual-map-editor/types.ts:
--------------------------------------------------------------------------------
1 | import { VisualMap } from '../types';
2 |
3 | export type VisualMapPartialForm = {
4 | visualMap: VisualMap;
5 | };
6 |
--------------------------------------------------------------------------------
/settings-form/src/account/index.tsx:
--------------------------------------------------------------------------------
1 | export * from './add-account';
2 | export * from './account-list';
3 | export * from './delete-account';
4 | export * from './login';
5 | export type { IStyles } from './styles';
6 |
--------------------------------------------------------------------------------
/website/src/pages/dashboard-editor-page/index.css:
--------------------------------------------------------------------------------
1 | .load-and-render-dashboard-editor {
2 | display: flex;
3 | flex-direction: column;
4 | flex-wrap: nowrap;
5 | height: 100%;
6 | overflow: hidden;
7 | }
8 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/viz-dashboard-state/render/item/selection-table.module.css:
--------------------------------------------------------------------------------
1 | .table {
2 | font-size: 12px !important;
3 | }
4 | .table th,
5 | .table td {
6 | padding: 5px 10px;
7 | }
8 |
--------------------------------------------------------------------------------
/dashboard/src/components/widgets/color-picker-popover/index.ts:
--------------------------------------------------------------------------------
1 | export * from './color-input';
2 | export * from './color-picker-popover';
3 | export * from './utils';
4 | export * from './color-picker-popover-for-viz';
5 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/color-manager/type.ts:
--------------------------------------------------------------------------------
1 | export interface IValueMapper {
2 | /**
3 | * Maps any number to a number between 0 and 100
4 | * @param from
5 | */
6 | mapValue(from: number): number;
7 | }
8 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/common-echarts-fields/axis-label-overflow/index.ts:
--------------------------------------------------------------------------------
1 | export * from './axis-label-overflow-field';
2 | export * from './types';
3 | export * from './overflow-field';
4 | export * from './overflow-option';
5 |
--------------------------------------------------------------------------------
/api/src/preset/data_sources/README.md:
--------------------------------------------------------------------------------
1 | To add preset datasources, make a copy of config.example.json and rename it to config.json.
2 | The configuration for each type follows the same rules as using the frontend to configure datasources.
3 |
--------------------------------------------------------------------------------
/dashboard/src/components/filter/filter-tree/common/index.ts:
--------------------------------------------------------------------------------
1 | export * from './expected-structure';
2 | export * from './query-data-to-tree';
3 | export * from './switcher-icon';
4 | export * from './tree-icon';
5 | export * from './types';
6 |
--------------------------------------------------------------------------------
/dashboard/src/components/panel/panel-render/index.ts:
--------------------------------------------------------------------------------
1 | export * from './panel-render';
2 | export * from './viz';
3 | export * from './full-screen-render';
4 | export * from './description-popover';
5 | export * from './client-panel-render';
6 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/boxplot-chart/option/common.ts:
--------------------------------------------------------------------------------
1 | import { IBoxplotDataItem } from '../type';
2 |
3 | export const BOXPLOT_DATA_ITEM_KEYS: Array = ['max', 'q3', 'median', 'q1', 'min'];
4 |
--------------------------------------------------------------------------------
/dashboard/src/dashboard-editor/ui/settings/content/edit-query/merico-metric-query-editor-form/merico-icons/types.ts:
--------------------------------------------------------------------------------
1 | export type MericoIconProps = {
2 | width: number | string;
3 | height: number | string;
4 | color?: string;
5 | };
6 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/editor-components/flex/type.ts:
--------------------------------------------------------------------------------
1 | export type JustifyContent = 'center' | 'left' | 'right' | 'space-between' | 'space-around' | 'space-evenly';
2 | export type AlignItems = 'start' | 'center' | 'end' | 'stretch';
3 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/pie-chart/option/types.ts:
--------------------------------------------------------------------------------
1 | export type TDataItem = {
2 | name: string;
3 | value: number;
4 | color?: string;
5 | ratio: number;
6 | percentage: string;
7 | items?: TDataItem[];
8 | };
9 |
--------------------------------------------------------------------------------
/dashboard/src/model/render-model/dashboard/content/index.ts:
--------------------------------------------------------------------------------
1 | export * from './views';
2 | export * from './panels';
3 | export * from './filters';
4 | export * from './queries';
5 | export * from './layouts';
6 | export * from './sql-snippets';
7 |
--------------------------------------------------------------------------------
/tools/workspace-plugin/src/generators/viz-component/files/type.ts__tmpl__:
--------------------------------------------------------------------------------
1 | export interface I<%= pascalcase(name) %>Conf {
2 | hello: string;
3 | }
4 |
5 | export const DEFAULT_CONFIG: I<%= pascalcase(name) %>Conf = {
6 | hello: 'world'
7 | };
8 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/common-echarts-fields/x-axis-label-formatter/index.ts:
--------------------------------------------------------------------------------
1 | export * from './function-editor';
2 | export * from './get-echarts-x-axis-tick-label';
3 | export * from './x-axis-label-formatter-field';
4 | export * from './types';
5 |
--------------------------------------------------------------------------------
/dashboard/src/model/meta-model/dashboard/content/query/types.ts:
--------------------------------------------------------------------------------
1 | export enum DataSourceType {
2 | Postgresql = 'postgresql',
3 | MySQL = 'mysql',
4 | HTTP = 'http',
5 | Transform = 'transform',
6 | MericoMetricSystem = 'merico_metric_system',
7 | }
8 |
--------------------------------------------------------------------------------
/dashboard/src/dashboard-editor/model/index.ts:
--------------------------------------------------------------------------------
1 | export * from './filters';
2 | export * from './queries';
3 | export * from './sql-snippets';
4 | export * from './dashboard';
5 | export * from './views';
6 | export * from './panels';
7 | export * from './content';
8 |
--------------------------------------------------------------------------------
/dashboard/src/dashboard-editor/ui/settings/content/edit-query/merico-metric-query-editor-form/merico-icons/index.ts:
--------------------------------------------------------------------------------
1 | export * from './external-link';
2 | export * from './play';
3 | export * from './copy';
4 | export * from './delete';
5 | export * from './more';
6 |
--------------------------------------------------------------------------------
/dashboard/src/dashboard-editor/ui/settings/content/edit-query/merico-metric-query-editor-form/query-tabs/edit-metric-query/table-styles.ts:
--------------------------------------------------------------------------------
1 | export const MetricTableStyles = {
2 | tbody: {
3 | td: {
4 | fontFamily: 'monospace',
5 | },
6 | },
7 | };
8 |
--------------------------------------------------------------------------------
/api/tests/e2e/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../base",
3 | "compilerOptions": {
4 | "baseUrl": ".",
5 | "paths": {
6 | "~/*": ["../../src/*"]
7 | },
8 | "types": ["node", "jest"],
9 | "strictNullChecks": false
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/settings-form/src/datasource/add-data-source/types.ts:
--------------------------------------------------------------------------------
1 | import { DataSourceType, TDataSourceConfig } from '../../api-caller/datasource.typed';
2 |
3 | export interface IFormValues {
4 | type: DataSourceType;
5 | key: string;
6 | config: TDataSourceConfig;
7 | }
8 |
--------------------------------------------------------------------------------
/api/tests/unit/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../base",
3 | "compilerOptions": {
4 | "baseUrl": ".",
5 | "paths": {
6 | "~/*": ["../../src/*"]
7 | },
8 | "types": ["node", "jest"],
9 | "strictNullChecks": false
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/dashboard/src/model/render-model/dashboard/content/sql-snippets/types.ts:
--------------------------------------------------------------------------------
1 | import { Instance } from 'mobx-state-tree';
2 | import { SQLSnippetsRenderModel } from './sql-snippets';
3 |
4 | export type SQLSnippetsRenderModelInstance = Instance;
5 |
--------------------------------------------------------------------------------
/api/tests/e2e/jest.mock.ts:
--------------------------------------------------------------------------------
1 | import { NextFunction, Request, Response } from 'express';
2 |
3 | jest.mock('~/middleware/validation', () => ({
4 | validate: () => (req: Request, res: Response, next: NextFunction) => next(),
5 | validateClass: (type, data) => data,
6 | }));
7 |
--------------------------------------------------------------------------------
/api/tests/integration/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../base",
3 | "compilerOptions": {
4 | "baseUrl": ".",
5 | "paths": {
6 | "~/*": ["../../src/*"]
7 | },
8 | "types": ["node", "jest"],
9 | "strictNullChecks": false
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/common-echarts-fields/tooltip-metric/types.ts:
--------------------------------------------------------------------------------
1 | import { SeriesUnitType } from '../series-unit';
2 |
3 | export interface IEchartsTooltipMetric {
4 | id: string;
5 | data_key: TDataKey;
6 | name: string;
7 | unit: SeriesUnitType;
8 | }
9 |
--------------------------------------------------------------------------------
/website/src/pages/status-page/index.tsx:
--------------------------------------------------------------------------------
1 | import { Box } from '@mantine/core';
2 | import { StatusTable } from './table';
3 |
4 | export function StatusPage() {
5 | return (
6 |
7 |
8 |
9 | );
10 | }
11 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/scatter-chart/option/legend.ts:
--------------------------------------------------------------------------------
1 | export function getLegend() {
2 | const ret: Record = {
3 | show: false,
4 | bottom: 0,
5 | left: 'center',
6 | type: 'scroll',
7 | };
8 | return ret;
9 | }
10 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/viz-dashboard-state/type.ts:
--------------------------------------------------------------------------------
1 | export interface IVizDashboardStateConf {
2 | all: boolean;
3 | keys: string[];
4 | }
5 |
6 | export const DEFAULT_CONFIG: IVizDashboardStateConf = {
7 | all: true,
8 | keys: [],
9 | };
10 |
--------------------------------------------------------------------------------
/dashboard/src/components/widgets/rich-text-editor/index.ts:
--------------------------------------------------------------------------------
1 | export * from './custom-rich-text-editor';
2 | export * from './dynamic-color-mark';
3 | export * from './font-size-extension';
4 | export * from './readonly-rich-text-editor';
5 | export * from './rich-text-editor-modal';
6 |
--------------------------------------------------------------------------------
/dashboard/src/emotion.d.ts:
--------------------------------------------------------------------------------
1 | import '@mantine/core';
2 |
3 | import type { EmotionStyles, EmotionSx } from '@mantine/emotion';
4 |
5 | declare module '@mantine/core' {
6 | export interface BoxProps {
7 | sx?: EmotionSx;
8 | styles?: EmotionStyles;
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/dashboard/src/styles/default-echarts-options/index.ts:
--------------------------------------------------------------------------------
1 | import * as xAxis from './x-axis';
2 | import * as yAxis from './y-axis';
3 | import * as tooltip from './tooltip';
4 |
5 | export const defaultEchartsOptions = {
6 | ...xAxis,
7 | ...yAxis,
8 | ...tooltip,
9 | };
10 |
--------------------------------------------------------------------------------
/website/src/api-caller/custom-function.types.ts:
--------------------------------------------------------------------------------
1 | export type TCustomFunctionDefinition = () => Record;
2 | export type TCustomFunctionDto = {
3 | id: string;
4 | is_preset: boolean;
5 | definition: string;
6 | create_time: string;
7 | update_time: string;
8 | };
9 |
--------------------------------------------------------------------------------
/website/src/emotion.d.ts:
--------------------------------------------------------------------------------
1 | import '@mantine/core';
2 |
3 | import type { EmotionStyles, EmotionSx } from '@mantine/emotion';
4 |
5 | declare module '@mantine/core' {
6 | export interface BoxProps {
7 | sx?: EmotionSx;
8 | styles?: EmotionStyles;
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/settings-form/src/emotion.d.ts:
--------------------------------------------------------------------------------
1 | import '@mantine/core';
2 |
3 | import type { EmotionStyles, EmotionSx } from '@mantine/emotion';
4 |
5 | declare module '@mantine/core' {
6 | export interface BoxProps {
7 | sx?: EmotionSx;
8 | styles?: EmotionStyles;
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/website/src/pages/dashboard-editor-page/more-dashboard-info/types.ts:
--------------------------------------------------------------------------------
1 | export type TModalState = {
2 | opened: boolean;
3 | open: () => void;
4 | close: () => void;
5 | };
6 |
7 | export type TModalStates = {
8 | changelog: TModalState;
9 | version: TModalState;
10 | };
11 |
--------------------------------------------------------------------------------
/website/src/api-caller/dashboard.typed.ts:
--------------------------------------------------------------------------------
1 | export type TDashboardMetaInfo = {
2 | id: string;
3 | name: string;
4 | group: string;
5 | content_id: string | null;
6 | create_time: string;
7 | update_time: string;
8 | is_removed: boolean;
9 | is_preset?: boolean;
10 | };
11 |
--------------------------------------------------------------------------------
/dashboard/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "composite": true,
4 | "module": "esnext",
5 | "moduleResolution": "node",
6 | "resolveJsonModule": true
7 | },
8 | "include": ["vite.config.ts", "package.json","./rollup-plugin-write-version-file.ts"]
9 | }
10 |
--------------------------------------------------------------------------------
/dashboard/src/components/panel/panel-render/dropdown-menu-items/index.ts:
--------------------------------------------------------------------------------
1 | export * from './download-data';
2 | export * from './download-screenshot';
3 | export * from './download-schema';
4 | export * from './enter-fullscreen';
5 | export * from './refresh';
6 | export * from './dropdown-menu-items';
7 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-manager/index.ts:
--------------------------------------------------------------------------------
1 | export { VizManager } from './impl';
2 | export type { IVizManager, IPanelInfo } from './types';
3 | export { VizConfigComponent, VizViewComponent } from './components';
4 | export type { IViewPanelInfo, IViewComponentProps } from './components';
5 |
--------------------------------------------------------------------------------
/dashboard/src/global.d.ts:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
2 | type $TSFixMe = any;
3 |
4 | type TFunctionString = string;
5 |
6 | type TPanelData = Record;
7 | type TQueryData = Record[];
8 | type TDataKey = string; // queryID.columnKey
9 |
--------------------------------------------------------------------------------
/settings-form/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "composite": true,
4 | "module": "esnext",
5 | "moduleResolution": "node",
6 | "resolveJsonModule": true
7 | },
8 | "include": ["vite.config.ts", "package.json", "./rollup-plugin-write-version-file.ts"]
9 | }
10 |
--------------------------------------------------------------------------------
/tools/tsconfig.plugin.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "rootDir": "./",
4 | "outDir": "./dist/nx-plugin",
5 | "module": "commonjs",
6 | "target": "ES2019",
7 | "sourceMap": false,
8 | "skipLibCheck": true
9 | },
10 | "exclude": ["node_modules", "dist"]
11 | }
12 |
--------------------------------------------------------------------------------
/tools/tsconfig.tools.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "rootDir": "./",
4 | "outDir": "./dist/generators",
5 | "module": "commonjs",
6 | "target": "ES2019",
7 | "sourceMap": false,
8 | "skipLibCheck": true
9 | },
10 | "exclude": ["node_modules", "dist"]
11 | }
12 |
--------------------------------------------------------------------------------
/tools/workspace-plugin/executors.json:
--------------------------------------------------------------------------------
1 | {
2 | "executors": {
3 | "is-published": {
4 | "implementation": "./src/executors/is-published/executor",
5 | "schema": "./src/executors/is-published/schema.json",
6 | "description": "is-published executor"
7 | }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/tools/workspace-plugin/generators.json:
--------------------------------------------------------------------------------
1 | {
2 | "generators": {
3 | "viz-component": {
4 | "implementation": "./src/generators/viz-component",
5 | "schema": "./src/generators/viz-component/schema.json",
6 | "description": "Generator viz-component"
7 | }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/common-echarts-fields/series-order/types.ts:
--------------------------------------------------------------------------------
1 | export type SeriesOrder = {
2 | key: 'name' | 'value' | '';
3 | order: 'asc' | 'desc';
4 | };
5 | export const getDefaultSeriesOrder = () =>
6 | ({
7 | key: '',
8 | order: 'desc',
9 | } as SeriesOrder);
10 |
--------------------------------------------------------------------------------
/settings-form/src/api-caller/role.ts:
--------------------------------------------------------------------------------
1 | import { APIClient } from './request';
2 | import { IRole } from './role.typed';
3 |
4 | export const role = {
5 | list: async (): Promise => {
6 | const res: IRole[] = await APIClient.get()('/role/list', {}, {});
7 | return res;
8 | },
9 | };
10 |
--------------------------------------------------------------------------------
/api/src/dashboard_migration/handlers/2.0.0.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * from before-versioning state to 2.0.0
3 | * @param schema
4 | * @returns schema with version set to 2.0.0
5 | */
6 | export function main(schema: Record) {
7 | return {
8 | ...schema,
9 | version: '2.0.0',
10 | };
11 | }
12 |
--------------------------------------------------------------------------------
/shared/tsconfig.lib.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../dist/out-tsc",
5 | "declaration": true,
6 | "types": ["node"]
7 | },
8 | "include": ["src/**/*.ts"],
9 | "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"]
10 | }
11 |
--------------------------------------------------------------------------------
/website/src/frames/app/index.css:
--------------------------------------------------------------------------------
1 | .App {
2 | padding: 1em;
3 | }
4 |
5 | .website-app .mantine-AppShell-main::-webkit-scrollbar {
6 | width: 0 !important;
7 | height: 0 !important;
8 | }
9 | .website-app .mantine-AppShell-main {
10 | overflow: -moz-scrollbars-none;
11 | -ms-overflow-style: none;
12 | }
13 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/cartesian/option/utils/types.ts:
--------------------------------------------------------------------------------
1 | export type TEchartsSeriesType = 'line' | 'bar' | 'scatter';
2 |
3 | export interface IEchartsSeriesItem {
4 | name: string;
5 | color?: string;
6 | type: TEchartsSeriesType;
7 | hide_in_legend: boolean;
8 | yAxisIndex: number;
9 | }
10 |
--------------------------------------------------------------------------------
/dashboard/src/styles/default-echarts-options/tooltip.ts:
--------------------------------------------------------------------------------
1 | import _ from 'lodash';
2 | import { AnyObject } from '~/types';
3 |
4 | export const tooltip = {
5 | confine: true,
6 | appendToBody: true,
7 | };
8 |
9 | export function getTooltip(option: AnyObject) {
10 | return _.defaultsDeep({}, option, tooltip);
11 | }
12 |
--------------------------------------------------------------------------------
/website/src/utils/dashboard-json-type-def.ts:
--------------------------------------------------------------------------------
1 | export const DashboardJSONTypeDef = {
2 | type: 'object',
3 | properties: {
4 | views: { type: 'array' },
5 | panels: { type: 'array' },
6 | filters: { type: 'array' },
7 | definition: { type: 'object' },
8 | version: { type: 'string' },
9 | },
10 | };
11 |
--------------------------------------------------------------------------------
/api/src/dashboard_migration/handlers/2.1.0.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * from before-versioning state to 2.0.0
3 | * @param schema
4 | * @returns schema with version set to 2.0.0
5 | */
6 | export function main(schema: Record) {
7 | return {
8 | filters: [],
9 | ...schema,
10 | version: '2.1.0',
11 | };
12 | }
13 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/hooks/use-tab-state.ts:
--------------------------------------------------------------------------------
1 | import { useEffect, useState } from 'react';
2 |
3 | export function useTabState(initialTab: string | null) {
4 | const [tab, setTab] = useState(initialTab);
5 | useEffect(() => {
6 | setTab(initialTab);
7 | }, [initialTab]);
8 | return { tab, setTab };
9 | }
10 |
--------------------------------------------------------------------------------
/tools/workspace-plugin/tsconfig.lib.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../../dist/out-tsc",
5 | "declaration": true,
6 | "types": ["node"]
7 | },
8 | "include": ["src/**/*.ts"],
9 | "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"]
10 | }
11 |
--------------------------------------------------------------------------------
/dashboard/src/model/meta-model/global-sql-snippets/global-sql-snippet.ts:
--------------------------------------------------------------------------------
1 | import { types } from 'mobx-state-tree';
2 |
3 | export const GlobalSQLSnippetMeta = types.model({
4 | id: types.string,
5 | content: types.string,
6 | create_time: types.string,
7 | update_time: types.string,
8 | is_preset: types.boolean,
9 | });
10 |
--------------------------------------------------------------------------------
/settings-form/src/global.d.ts:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line @typescript-eslint/no-explicit-any
2 | type $TSFixMe = any;
3 |
4 | interface ISettingsFormConfig {
5 | basename: string;
6 | apiBaseURL: string;
7 | app_id?: string;
8 | app_secret?: string;
9 | monacoPath: string;
10 | }
11 |
12 | type TFunctionString = string;
13 |
--------------------------------------------------------------------------------
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["plugin:@typescript-eslint/recommended"],
3 | "parser": "@typescript-eslint/parser",
4 | "plugins": ["@typescript-eslint"],
5 | "root": true,
6 | "overrides": [
7 | {
8 | "files": "*.json",
9 | "parser": "jsonc-eslint-parser",
10 | "rules": {}
11 | }
12 | ]
13 | }
14 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/table/utils.ts:
--------------------------------------------------------------------------------
1 | import { ColumnAlignType } from './type';
2 |
3 | type JustifyType = 'flex-start' | 'center' | 'flex-end';
4 |
5 | export const AlignmentToFlexJustify: Record = {
6 | left: 'flex-start',
7 | center: 'center',
8 | right: 'flex-end',
9 | };
10 |
--------------------------------------------------------------------------------
/dashboard/src/model/meta-model/dashboard/content/index.ts:
--------------------------------------------------------------------------------
1 | export * from './mock-context';
2 | export * from './panel';
3 | export * from './query';
4 | export * from './layout';
5 | export * from './sql-snippet';
6 | export * from './filter';
7 | export * from './view';
8 | export * from './types';
9 | export * from './initial-content';
10 |
--------------------------------------------------------------------------------
/api/src/preset/custom_functions/config.example.js:
--------------------------------------------------------------------------------
1 | const example_custom_function1 = () => {
2 | console.log('this is an example custom function 1');
3 | };
4 |
5 | const example_custom_function2 = () => {
6 | console.log('this is an example custom function 2');
7 | };
8 |
9 | export { example_custom_function1, example_custom_function2 };
10 |
--------------------------------------------------------------------------------
/dashboard/src/model/meta-model/dashboard/content/filter/widgets/index.ts:
--------------------------------------------------------------------------------
1 | export * from './checkbox';
2 | export * from './date-range';
3 | export * from './multi-select';
4 | export * from './select';
5 | export * from './text-input';
6 | export * from './tree-select';
7 | export * from './tree-single-select';
8 | export * from './merico-date-range';
9 |
--------------------------------------------------------------------------------
/dashboard/src/utils/usage.ts:
--------------------------------------------------------------------------------
1 | export const UsageRegs = {
2 | sqlSnippet: /(?<=sql_snippets\.)([^\?}.]+)/gm,
3 | context: /(?<=context\.)([^\?}.]+)/gm,
4 | filter: /(?<=filters\.)([^\?}.]+)/gm,
5 | };
6 |
7 | export type DependencyInfo = {
8 | type: 'sql_snippet' | 'context' | 'filter';
9 | key: string;
10 | valid: boolean;
11 | };
12 |
--------------------------------------------------------------------------------
/website/tsconfig.cypress.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "include": ["src", "cypress"],
4 | "exclude": ["**/*.spec.ts"],
5 | "compilerOptions": {
6 | "types": ["cypress", "@testing-library/cypress", "chai"],
7 | "paths": {
8 | "@cy/*": ["./cypress/*"],
9 | "~/*": ["./src/*"]
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/merico-estimation-chart/option/series/utils.ts:
--------------------------------------------------------------------------------
1 | export function getIndicatorColorStyle(color: string) {
2 | const ret = [`background-color: ${color}`];
3 | if (color === 'rgba(255, 255, 255, 1)') {
4 | ret.push('box-shadow: 0px 0px 1px 0px rgba(0,0,0,.5)');
5 | }
6 | return ret.join(';');
7 | }
8 |
--------------------------------------------------------------------------------
/dashboard/src/contexts/render-content-model-context.ts:
--------------------------------------------------------------------------------
1 | import { IContentRenderModel } from '../dashboard-render';
2 | import { useContentModelContext } from './content-model-context';
3 |
4 | export const useRenderContentModelContext = () => useContentModelContext();
5 |
6 | // use a separate file to allow tsc generate proper types
7 |
--------------------------------------------------------------------------------
/dashboard/tsconfig.cypress.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "include": ["src", "cypress"],
4 | "exclude": ["**/*.spec.ts"],
5 | "compilerOptions": {
6 | "types": ["cypress", "@testing-library/cypress", "chai"],
7 | "paths": {
8 | "@cy/*": ["./cypress/*"],
9 | "~/*": ["./src/*"]
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/shared/project.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "shared",
3 | "$schema": "../node_modules/nx/schemas/project-schema.json",
4 | "sourceRoot": "shared/src",
5 | "projectType": "library",
6 | "targets": {
7 | "lint": {
8 | "executor": "@nx/eslint:lint",
9 | "outputs": ["{options.outputFile}"]
10 | }
11 | },
12 | "tags": []
13 | }
14 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/horizontal-bar-chart/option/utils/types.ts:
--------------------------------------------------------------------------------
1 | export type TEchartsSeriesType = 'bar' | 'scatter';
2 |
3 | export interface IEchartsSeriesItem {
4 | name: string;
5 | color?: string;
6 | type: TEchartsSeriesType;
7 | hide_in_legend: boolean;
8 | xAxisIndex: number;
9 | yAxisIndex: number;
10 | }
11 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/viz-merico-gqm/type.ts:
--------------------------------------------------------------------------------
1 | export interface IMericoGQMConf {
2 | expertSystemURL: string;
3 | path: string;
4 | goal: string;
5 | question: string;
6 | }
7 |
8 | export const DEFAULT_CONFIG: IMericoGQMConf = {
9 | expertSystemURL: '',
10 | path: '',
11 | goal: '',
12 | question: '',
13 | };
14 |
--------------------------------------------------------------------------------
/dashboard/src/utils/mantine.ts:
--------------------------------------------------------------------------------
1 | import { ComboboxItem } from '@mantine/core';
2 |
3 | type SelectChangeHandler = (v: T, option: ComboboxItem) => void;
4 | export const getSelectChangeHandler = (func: SelectChangeHandler) => {
5 | return (v: string | null, option: ComboboxItem) => {
6 | v !== null && func(v as T, option);
7 | };
8 | };
9 |
--------------------------------------------------------------------------------
/tools/workspace-plugin/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.base.json",
3 | "compilerOptions": {
4 | "module": "commonjs"
5 | },
6 | "files": [],
7 | "include": [],
8 | "references": [
9 | {
10 | "path": "./tsconfig.lib.json"
11 | },
12 | {
13 | "path": "./tsconfig.spec.json"
14 | }
15 | ]
16 | }
17 |
--------------------------------------------------------------------------------
/dashboard/src/types/utils.ts:
--------------------------------------------------------------------------------
1 | export type AnyObject = Record;
2 | export type Ready = T & { [P in TK]-?: NonNullable };
3 |
4 | export const typeAssert = {
5 | // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-empty-function
6 | shouldExtends(): void {},
7 | };
8 |
--------------------------------------------------------------------------------
/dashboard/src/utils/shallow-to-js.ts:
--------------------------------------------------------------------------------
1 | import { toJS } from 'mobx';
2 | import { cloneDeepWith } from 'lodash';
3 |
4 | export const shallowToJS = (obj: T): T => {
5 | return cloneDeepWith(obj, (value, key) => {
6 | if (key === undefined) {
7 | return;
8 | }
9 | if (value) {
10 | return toJS(value);
11 | }
12 | });
13 | };
14 |
--------------------------------------------------------------------------------
/website/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | interface ImportMetaEnv {
4 | readonly VITE_API_BASE_URL: string;
5 | readonly VITE_WEBSITE_BASE_URL: string;
6 | readonly VITE_WEBSITE_ROUTER_MIDDLEWARE_KEY: string;
7 | // more env variables...
8 | }
9 |
10 | interface ImportMeta {
11 | readonly env: ImportMetaEnv;
12 | }
13 |
--------------------------------------------------------------------------------
/tools/workspace-plugin/tsconfig.spec.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../../dist/out-tsc",
5 | "module": "commonjs",
6 | "types": ["jest", "node"]
7 | },
8 | "include": [
9 | "jest.config.ts",
10 | "src/**/*.test.ts",
11 | "src/**/*.spec.ts",
12 | "src/**/*.d.ts"
13 | ]
14 | }
15 |
--------------------------------------------------------------------------------
/api/src/api_models/cache.ts:
--------------------------------------------------------------------------------
1 | import { ApiModel, ApiModelProperty } from 'swagger-express-ts';
2 |
3 | @ApiModel({
4 | description: 'Cache clear request object',
5 | name: 'CacheClearRequest',
6 | })
7 | export class CacheClearRequest {
8 | @ApiModelProperty({
9 | description: 'Content id',
10 | required: true,
11 | })
12 | content_id: string;
13 | }
14 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/calendar-heatmap/option/legend.ts:
--------------------------------------------------------------------------------
1 | export function getLegend(oneYearMode: boolean, years: string[]) {
2 | return {
3 | show: !oneYearMode,
4 | selectedMode: 'single',
5 | top: 5,
6 | right: 5,
7 | data: years.map((name) => ({
8 | name,
9 | icon: 'circle',
10 | })),
11 | };
12 | }
13 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/regression-chart/render/use-data-key.ts:
--------------------------------------------------------------------------------
1 | import { useState } from 'react';
2 |
3 | export const useDataKey = (initialKey: TDataKey) => {
4 | const [value, set] = useState(initialKey);
5 | return {
6 | value,
7 | set,
8 | };
9 | };
10 |
11 | export type UseDataKeyReturn = ReturnType;
12 |
--------------------------------------------------------------------------------
/dashboard/src/interactions/interactions-viewer/node-with-interactions/index.css:
--------------------------------------------------------------------------------
1 | .react-flow__node-interaction {
2 | padding: 10px;
3 | border-radius: 3px;
4 | width: 150px;
5 | font-size: 12px;
6 | color: #222;
7 | text-align: center;
8 | border-width: 1px;
9 | border-style: solid;
10 | border-color: #1a192b;
11 | background-color: white;
12 | }
13 |
--------------------------------------------------------------------------------
/api/tsconfig.dist.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "baseUrl": ".",
4 | "paths": {
5 | "~/*": ["dist/*", "src/*"],
6 | "express": ["node_modules/express/lib/express"]
7 | }
8 | },
9 | "exclude": ["node_modules", "build", "_build"],
10 | "rules": {
11 | "no-unused-expression": true,
12 | "no-floating-promises": true
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/dashboard/src/components/widgets/index.ts:
--------------------------------------------------------------------------------
1 | export * from './about-function-utils';
2 | export * from './custom-selector-item';
3 | export * from './function-editor';
4 | export * from './inline-function-input';
5 | export * from './minimal-monaco-editor';
6 | export * from './modal-function-editor';
7 | export * from './rich-text-editor';
8 | export * from './color-picker-popover';
9 |
--------------------------------------------------------------------------------
/dashboard/src/contexts/customize-screenshot-context.ts:
--------------------------------------------------------------------------------
1 | import { noop } from 'lodash';
2 | import React from 'react';
3 |
4 | export interface ICustomizeScreenshotContext {
5 | onScreenshot: (canvas: HTMLCanvasElement) => void;
6 | }
7 |
8 | export const CustomizeScreenshotContext = React.createContext({
9 | onScreenshot: noop,
10 | });
11 |
--------------------------------------------------------------------------------
/settings-form/src/api-caller/index.ts:
--------------------------------------------------------------------------------
1 | import { account } from './account';
2 | import { api_key } from './api-key';
3 | import { datasource } from './datasource';
4 | import { role } from './role';
5 | import { sql_snippet } from './sql_snippet';
6 |
7 | export const APICaller = {
8 | datasource,
9 | account,
10 | role,
11 | api_key,
12 | sql_snippet,
13 | };
14 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "prettier.configPath": ".prettierrc.js",
3 | "prettier.prettierPath": "./node_modules/prettier",
4 | "editor.defaultFormatter": "esbenp.prettier-vscode",
5 | "[typescriptreact]": {
6 | "editor.defaultFormatter": "esbenp.prettier-vscode"
7 | },
8 | "eslint.validate": [
9 | "json"
10 | ],
11 | "git-blame.gitWebUrl": ""
12 | }
13 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/common-echarts-fields/series-unit/types.ts:
--------------------------------------------------------------------------------
1 | export interface SeriesUnitType {
2 | text: string;
3 | show_in_tooltip: boolean;
4 | show_in_legend: boolean;
5 | }
6 |
7 | export function getDefaultSeriesUnit(): SeriesUnitType {
8 | return {
9 | text: '',
10 | show_in_tooltip: false,
11 | show_in_legend: false,
12 | };
13 | }
14 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/editor-components/index.ts:
--------------------------------------------------------------------------------
1 | export * from './viz-config-banner';
2 | export * from './horizontal-align-selector';
3 | export * from './vertical-align-selector';
4 | export * from './color-interpolation-select';
5 | export * from './color-mapping-editor';
6 | export * from './color-type';
7 | export * from './flex';
8 | export * from './field-array-tabs';
9 |
--------------------------------------------------------------------------------
/settings-form/src/account/styles.ts:
--------------------------------------------------------------------------------
1 | import { MantineSize } from '@mantine/core';
2 |
3 | export interface IStyles {
4 | size: MantineSize;
5 | spacing: MantineSize;
6 | button: {
7 | size: MantineSize;
8 | };
9 | }
10 |
11 | export const defaultStyles: IStyles = {
12 | size: 'sm',
13 | spacing: 'md',
14 | button: {
15 | size: 'xs',
16 | },
17 | };
18 |
--------------------------------------------------------------------------------
/settings-form/src/api-key/styles.ts:
--------------------------------------------------------------------------------
1 | import { MantineSize } from '@mantine/core';
2 |
3 | export interface IStyles {
4 | size: MantineSize;
5 | spacing: MantineSize;
6 | button: {
7 | size: MantineSize;
8 | };
9 | }
10 |
11 | export const defaultStyles: IStyles = {
12 | size: 'sm',
13 | spacing: 'md',
14 | button: {
15 | size: 'xs',
16 | },
17 | };
18 |
--------------------------------------------------------------------------------
/settings-form/src/datasource/styles.ts:
--------------------------------------------------------------------------------
1 | import { MantineSize } from '@mantine/core';
2 |
3 | export interface IStyles {
4 | size: MantineSize;
5 | spacing: MantineSize;
6 | button: {
7 | size: MantineSize;
8 | };
9 | }
10 |
11 | export const defaultStyles: IStyles = {
12 | size: 'sm',
13 | spacing: 'md',
14 | button: {
15 | size: 'xs',
16 | },
17 | };
18 |
--------------------------------------------------------------------------------
/settings-form/src/sql_snippet/styles.ts:
--------------------------------------------------------------------------------
1 | import { MantineSize } from '@mantine/core';
2 |
3 | export interface IStyles {
4 | size: MantineSize;
5 | spacing: MantineSize;
6 | button: {
7 | size: MantineSize;
8 | };
9 | }
10 |
11 | export const defaultStyles: IStyles = {
12 | size: 'sm',
13 | spacing: 'md',
14 | button: {
15 | size: 'xs',
16 | },
17 | };
18 |
--------------------------------------------------------------------------------
/website/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | *.local
14 |
15 | # Editor directories and files
16 | .vscode/*
17 | !.vscode/extensions.json
18 | .idea
19 | .DS_Store
20 | *.suo
21 | *.ntvs*
22 | *.njsproj
23 | *.sln
24 | *.sw?
25 |
--------------------------------------------------------------------------------
/website/src/api-caller/dashboard.transform.ts:
--------------------------------------------------------------------------------
1 | import { IDashboard } from '@devtable/dashboard';
2 | import { TDashboardMetaInfo } from './dashboard.typed';
3 |
4 | export function normalizeDBDashboard({ id, name, group, content_id }: TDashboardMetaInfo): IDashboard {
5 | return {
6 | id,
7 | name,
8 | group,
9 | content_id,
10 | } as IDashboard;
11 | }
12 |
--------------------------------------------------------------------------------
/website/src/pages/dashboard-render-page/placeholder.tsx:
--------------------------------------------------------------------------------
1 | import { Center } from '@mantine/core';
2 |
3 | export function PleaseChooseADashboard() {
4 | return Please choose a dashboard to proceed;
5 | }
6 |
7 | export function DashboardIsEmpty() {
8 | return This dashboard is empty;
9 | }
10 |
--------------------------------------------------------------------------------
/website/cypress/support/component-index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Components App
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/api/src/models/dashboard_changelog.ts:
--------------------------------------------------------------------------------
1 | import { Entity, Column } from 'typeorm';
2 | import { BaseModel } from './base';
3 |
4 | @Entity()
5 | export default class DashboardChangelog extends BaseModel {
6 | @Column('uuid', {
7 | name: 'dashboard_id',
8 | comment: '报表ID',
9 | })
10 | dashboard_id: string;
11 |
12 | @Column('text', { name: 'diff' })
13 | diff: string;
14 | }
15 |
--------------------------------------------------------------------------------
/api/tests/integration/00_seed.test.ts:
--------------------------------------------------------------------------------
1 | import { seed } from './seed/seed';
2 | import { connectionHook } from './jest.util';
3 | import { RoleService } from '~/services/role.service';
4 |
5 | describe('System Init', () => {
6 | connectionHook();
7 |
8 | it('seed', async () => {
9 | await seed();
10 | await RoleService.ensureFixedRolePermissions();
11 | }, 120000);
12 | });
13 |
--------------------------------------------------------------------------------
/dashboard/cypress/support/component-index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Components App
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/dashboard/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | *.local
14 | stats.html
15 |
16 | # Editor directories and files
17 | .vscode/*
18 | !.vscode/extensions.json
19 | .idea
20 | .DS_Store
21 | *.suo
22 | *.ntvs*
23 | *.njsproj
24 | *.sln
25 | *.sw?
26 |
--------------------------------------------------------------------------------
/dashboard/src/components/filter/filter-settings/filter-settings.css:
--------------------------------------------------------------------------------
1 | .filter-settings-tabs {
2 | width: 100%;
3 | height: 100%;
4 | }
5 | .filter-settings-tabs .mantine-Tabs-panel {
6 | height: calc(100% - 25px);
7 | }
8 | .filter-settings-tabs .mantine-Tabs-tabsListWrapper {
9 | flex: 0;
10 | }
11 | .filter-settings-tabs .mantine-Tabs-body {
12 | flex: 1;
13 | overflow: auto;
14 | }
15 |
--------------------------------------------------------------------------------
/tools/workspace-plugin/jest.config.ts:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | export default {
3 | displayName: 'tools/workspace-plugin',
4 | preset: '../../jest.preset.js',
5 | transform: {
6 | '^.+\\.[tj]s$': ['ts-jest', { tsconfig: '/tsconfig.spec.json' }],
7 | },
8 | moduleFileExtensions: ['ts', 'js', 'html'],
9 | coverageDirectory: '../../coverage/tools/workspace-plugin',
10 | };
11 |
--------------------------------------------------------------------------------
/dashboard/src/components/filter/filter-tree/common/types.ts:
--------------------------------------------------------------------------------
1 | export interface ITreeDataQueryOption {
2 | label: string;
3 | value: string;
4 | parent_value: string;
5 | description?: string;
6 | }
7 |
8 | export interface ITreeDataRenderItem {
9 | label: string | JSX.Element;
10 | value: string;
11 | parent_value: string;
12 | description?: string;
13 | filterBasis: string;
14 | }
15 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/colors/sequential-color.ts:
--------------------------------------------------------------------------------
1 | import chroma from 'chroma-js';
2 | import { IColorInterpolation } from '~/types/plugin';
3 |
4 | export const createSequentialColorPalette = (colors: string[]): IColorInterpolation['getColor'] => {
5 | const fn = chroma.bezier(colors);
6 | return function (value: number): string {
7 | return fn(value / 100).hex();
8 | };
9 | };
10 |
--------------------------------------------------------------------------------
/settings-form/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | *.local
14 | stats.html
15 |
16 | # Editor directories and files
17 | .vscode/*
18 | !.vscode/extensions.json
19 | .idea
20 | .DS_Store
21 | *.suo
22 | *.ntvs*
23 | *.njsproj
24 | *.sln
25 | *.sw?
26 |
--------------------------------------------------------------------------------
/shared/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["../.eslintrc.json"],
3 | "ignorePatterns": ["!**/*"],
4 | "overrides": [
5 | {
6 | "files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
7 | "rules": {}
8 | },
9 | {
10 | "files": ["*.ts", "*.tsx"],
11 | "rules": {}
12 | },
13 | {
14 | "files": ["*.js", "*.jsx"],
15 | "rules": {}
16 | }
17 | ]
18 | }
19 |
--------------------------------------------------------------------------------
/website/src/api-caller/status.ts:
--------------------------------------------------------------------------------
1 | import { get } from './request';
2 | import { VersionResp } from './status.typs';
3 |
4 | export const StatusAPI = {
5 | /**
6 | * get api version
7 | */
8 | version: async (signal?: AbortSignal): Promise => {
9 | const res = await get(signal)('/version', {});
10 | return res;
11 | },
12 | };
13 |
14 | export const status = StatusAPI;
15 |
--------------------------------------------------------------------------------
/api/src/plugins/index.js:
--------------------------------------------------------------------------------
1 | import path from 'path';
2 | import fs from 'fs-extra';
3 |
4 | export const sqlRewriter = (
5 | fs.existsSync(path.resolve(__dirname, './sqlrewriter.js'))
6 | ? require(path.resolve(__dirname, './sqlrewriter.js'))
7 | : {
8 | default: async (sql, env) => {
9 | return {
10 | sql,
11 | };
12 | },
13 | }
14 | ).default;
15 |
--------------------------------------------------------------------------------
/api/test.sequencer.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line @typescript-eslint/no-var-requires
2 | const Sequencer = require('@jest/test-sequencer').default;
3 |
4 | class CustomSequencer extends Sequencer {
5 | sort(tests) {
6 | const copyTests = Array.from(tests);
7 | return copyTests.sort((testA, testB) => (testA.path > testB.path ? 1 : -1));
8 | }
9 | }
10 |
11 | module.exports = CustomSequencer;
12 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/stats/type.ts:
--------------------------------------------------------------------------------
1 | import { VerticalAlign } from '../../editor-components';
2 |
3 | export interface IVizStatsConf {
4 | content: string;
5 | vertical_align: VerticalAlign;
6 | }
7 | export const DEFAULT_CONFIG: IVizStatsConf = {
8 | content: 'Use double curly brackets to wrap js code: {{ new Date().getTime() }}',
9 | vertical_align: 'center',
10 | };
11 |
--------------------------------------------------------------------------------
/website/src/pages/dashboard-render-page/index.tsx:
--------------------------------------------------------------------------------
1 | import { useParams } from 'react-router-dom';
2 | import { DashboardPageContent } from './content';
3 | import { PleaseChooseADashboard } from './placeholder';
4 |
5 | export function DashboardRenderPage() {
6 | const { id } = useParams();
7 | if (!id) {
8 | return ;
9 | }
10 | return ;
11 | }
12 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/hooks/use-row-data-map.ts:
--------------------------------------------------------------------------------
1 | import _ from 'lodash';
2 | import { useMemo } from 'react';
3 | import { parseDataKey } from '~/utils';
4 |
5 | export function useRowDataMap(data: TPanelData, dataKey: TDataKey) {
6 | return useMemo(() => {
7 | const { queryID, columnKey } = parseDataKey(dataKey);
8 | return _.keyBy(data[queryID], columnKey);
9 | }, [data, dataKey]);
10 | }
11 |
--------------------------------------------------------------------------------
/dashboard/src/dashboard-editor/ui/settings/content/view-query-vars/index.tsx:
--------------------------------------------------------------------------------
1 | import { Stack } from '@mantine/core';
2 | import { observer } from 'mobx-react-lite';
3 | import { QueryVariablesGuide } from './query-variables-guide';
4 |
5 | export const ViewQueryVars = observer(() => {
6 | return (
7 |
8 |
9 |
10 | );
11 | });
12 |
--------------------------------------------------------------------------------
/dashboard/src/components/widgets/function-editor/types.ts:
--------------------------------------------------------------------------------
1 | // [ startLine, startColumn, endLine, endColumn ]
2 | export type MonacoEditorRestrictionRange = [number, number, number, number];
3 |
4 | export type MonacoEditorRestriction = {
5 | range: MonacoEditorRestrictionRange;
6 | label?: string;
7 | allowMultiline?: boolean;
8 | validate?: (currentlyTypedValue: any, newRange: any, info: any) => boolean;
9 | };
10 |
--------------------------------------------------------------------------------
/api/src/models/dashboard_content_changelog.ts:
--------------------------------------------------------------------------------
1 | import { Entity, Column } from 'typeorm';
2 | import { BaseModel } from './base';
3 |
4 | @Entity()
5 | export default class DashboardContentChangelog extends BaseModel {
6 | @Column('uuid', {
7 | name: 'dashboard_content_id',
8 | comment: '报表内容ID',
9 | })
10 | dashboard_content_id: string;
11 |
12 | @Column('text', { name: 'diff' })
13 | diff: string;
14 | }
15 |
--------------------------------------------------------------------------------
/dashboard/src/contexts/index.ts:
--------------------------------------------------------------------------------
1 | export * from './dashboard-context';
2 | export * from './dashboard-theme-context';
3 | export * from './content-model-context';
4 | export * from './layout-state-context';
5 | export * from './panel-context';
6 | export * from './full-screen-panel-context';
7 | export * from './dates-provider';
8 | export * from './render-content-model-context';
9 | export * from './additional-panel-menu-items';
10 |
--------------------------------------------------------------------------------
/dashboard/src/dashboard-editor/ui/settings/content/db-explorer-modal/db-explorer/full-space-loading.tsx:
--------------------------------------------------------------------------------
1 | import { Box, LoadingOverlay } from '@mantine/core';
2 |
3 | export const FullSpaceLoading = ({ visible }: { visible: boolean }) => {
4 | return (
5 |
6 |
7 |
8 | );
9 | };
10 |
--------------------------------------------------------------------------------
/dashboard/src/i18n/i18next-context.tsx:
--------------------------------------------------------------------------------
1 | import { ReactNode, useEffect } from 'react';
2 | import { I18nextProvider } from 'react-i18next';
3 | import i18n from './i18n';
4 |
5 | export function I18nextContextProvider({ lang, children }: { lang: string; children: ReactNode }) {
6 | useEffect(() => {
7 | i18n.changeLanguage(lang);
8 | }, [lang]);
9 |
10 | return {children};
11 | }
12 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/hooks/use-channel-event.ts:
--------------------------------------------------------------------------------
1 | import { ListenerFn, EventEmitter2 } from 'eventemitter2';
2 | import { useEffect } from 'react';
3 |
4 | export function useChannelEvent(channel: EventEmitter2, event: string, listener: ListenerFn) {
5 | useEffect(() => {
6 | channel.on(event, listener);
7 | return () => {
8 | channel.off(event, listener);
9 | };
10 | }, [channel, event, listener]);
11 | }
12 |
--------------------------------------------------------------------------------
/settings-form/src/i18n/i18next-context.tsx:
--------------------------------------------------------------------------------
1 | import { ReactNode, useEffect } from 'react';
2 | import { I18nextProvider } from 'react-i18next';
3 | import i18n from './i18n';
4 |
5 | export function I18nextContextProvider({ lang, children }: { lang: string; children: ReactNode }) {
6 | useEffect(() => {
7 | i18n.changeLanguage(lang);
8 | }, [lang]);
9 |
10 | return {children};
11 | }
12 |
--------------------------------------------------------------------------------
/api/src/dashboard_migration/handlers/4.5.1.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * migrate to v4.5.1
3 | * Changes: add name to view
4 | * @param schema
5 | * @returns schema with version set to 4.5.1
6 | */
7 | export function main({ filters, views, ...rest }: Record) {
8 | return {
9 | filters,
10 | views: views.map((v) => ({
11 | ...v,
12 | name: v.id,
13 | })),
14 | ...rest,
15 | version: '4.5.1',
16 | };
17 | }
18 |
--------------------------------------------------------------------------------
/dashboard/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | @devtable/dashboard
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/editor-components/field-array-tabs/types.ts:
--------------------------------------------------------------------------------
1 | import { ReactNode } from 'react';
2 | import { ArrayPath, FieldArrayWithId, FieldValues, Path, PathValue } from 'react-hook-form';
3 |
4 | export type ControlledField = FieldArrayWithId, 'id'> & PathValue>;
5 | export type FieldArrayTabsChildren = ({ field, index }: { field: FieldItem; index: number }) => ReactNode;
6 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/merico-panel-groups/type.ts:
--------------------------------------------------------------------------------
1 | export type MericoPanelGroupItem = {
2 | name: string;
3 | comment: string;
4 | panelIDs: string[];
5 | };
6 |
7 | export type VizMericoPanelGroupsConf = {
8 | groups: MericoPanelGroupItem[];
9 | };
10 |
11 | export const getDefaultConfig = () => {
12 | const config: VizMericoPanelGroupsConf = {
13 | groups: [],
14 | };
15 | return config;
16 | };
17 |
--------------------------------------------------------------------------------
/dashboard/src/dashboard-editor/ui/settings/content/edit-view/edit-view-form/config-fields/modal/modal-title-editor/types.ts:
--------------------------------------------------------------------------------
1 | export interface ICustomModalTitle {
2 | enabled: boolean;
3 | func_content: string;
4 | }
5 |
6 | export const DEFAULT_CUSTOM_MODAL_TITLE = {
7 | enabled: false,
8 | func_content: ['function text({ filters, context}) {', ' // your code goes here', ' return "text"', '}'].join(
9 | '\n',
10 | ),
11 | };
12 |
--------------------------------------------------------------------------------
/dashboard/src/components/filter/filter-tree/common/query-data-to-tree.ts:
--------------------------------------------------------------------------------
1 | import { arrayToTree } from 'performant-array-to-tree';
2 | import { ITreeDataRenderItem } from './types';
3 |
4 | export function queryDataToTree(queryData: ITreeDataRenderItem[]) {
5 | const tree = arrayToTree(queryData, {
6 | id: 'value',
7 | parentId: 'parent_value',
8 | childrenField: 'children',
9 | dataField: null,
10 | });
11 | return tree;
12 | }
13 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/boxplot-chart/option/series/custom/utils.ts:
--------------------------------------------------------------------------------
1 | import { CustomSeriesRenderItemAPI } from 'echarts';
2 |
3 | export const BOX_WIDTH = [10, 40];
4 |
5 | export function getLayout(api: CustomSeriesRenderItemAPI) {
6 | // Leftside for scatter
7 | // Rightside for box
8 | return api.barLayout({
9 | barMinWidth: BOX_WIDTH[0],
10 | barMaxWidth: BOX_WIDTH[1],
11 | count: 2,
12 | });
13 | }
14 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/viz-dashboard-state/render/item/context-state.tsx:
--------------------------------------------------------------------------------
1 | import { TDashboardStateItem } from '~/model';
2 | import { ItemBadge } from './item-badge';
3 |
4 | export const ContextState = ({ item }: { item: TDashboardStateItem }) => {
5 | if (item.type !== 'context') {
6 | return null;
7 | }
8 |
9 | return ;
10 | };
11 |
--------------------------------------------------------------------------------
/settings-form/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | @devtable/settings-form
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/website/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | @devtable
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/dashboard/src/contexts/dashboard-action-context.ts:
--------------------------------------------------------------------------------
1 | import _ from 'lodash';
2 | import React from 'react';
3 |
4 | export interface IDashboardActionContext {
5 | viewPanelInFullScreen: (id: string) => void;
6 | inFullScreen: boolean;
7 | }
8 |
9 | const initialContext = {
10 | viewPanelInFullScreen: _.noop,
11 | inFullScreen: false,
12 | };
13 |
14 | export const DashboardActionContext = React.createContext(initialContext);
15 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ## 15.58.9 (2025-12-09)
2 |
3 | ### 🚀 Features
4 |
5 | - **rich-text-editor:** Add line height control ([e1ab982d7](https://github.com/merico-dev/table/commit/e1ab982d7))
6 |
7 | ### ❤️ Thank You
8 |
9 | - ZeekoZhu
10 |
11 | ## v15.58.9 (2025-12-09)
12 |
13 | ### 🚀 Features
14 |
15 | - **rich-text-editor:** Add line height control ([e1ab982d7](https://github.com/merico-dev/table/commit/e1ab982d7))
16 |
17 | ### ❤️ Thank You
18 |
19 | - ZeekoZhu
--------------------------------------------------------------------------------
/api/tests/e2e/00_init_db.test.ts:
--------------------------------------------------------------------------------
1 | import { connectionHook } from './jest.util';
2 | import { dashboardDataSource } from '~/data_sources/dashboard';
3 | import { RoleService } from '~/services/role.service';
4 |
5 | describe('System Init', () => {
6 | connectionHook();
7 |
8 | it('migrate', async () => {
9 | await dashboardDataSource.runMigrations({ transaction: 'none' });
10 | await RoleService.ensureFixedRolePermissions();
11 | }, 120000);
12 | });
13 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/common-echarts-fields/x-axis-label-formatter/types.ts:
--------------------------------------------------------------------------------
1 | export interface IXAxisLabelFormatter {
2 | enabled: boolean;
3 | func_content: string;
4 | }
5 |
6 | export function getDefaultXAxisLabelFormatter(): IXAxisLabelFormatter {
7 | return {
8 | enabled: false,
9 | func_content: ['function label(value, index) {', ' // your code goes here', ' // return value', '}'].join(
10 | '\n',
11 | ),
12 | };
13 | }
14 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-manager/types.ts:
--------------------------------------------------------------------------------
1 | import { IDashboardPanel } from '~/types';
2 | import { VizComponent, VizInstance } from '~/types/plugin';
3 |
4 | export type IPanelInfo = Omit;
5 |
6 | export interface IVizManager {
7 | readonly availableVizList: VizComponent[];
8 |
9 | resolveComponent(type: string): VizComponent;
10 |
11 | getOrCreateInstance(panel: IPanelInfo): VizInstance;
12 | }
13 |
--------------------------------------------------------------------------------
/website/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans',
4 | 'Droid Sans', 'Helvetica Neue', sans-serif;
5 | -webkit-font-smoothing: antialiased;
6 | -moz-osx-font-smoothing: grayscale;
7 | }
8 |
9 | * {
10 | box-sizing: border-box;
11 | }
12 |
13 | code {
14 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace;
15 | }
16 |
--------------------------------------------------------------------------------
/api/src/dashboard_migration/handlers/4.5.0.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * migrate to v4.5.0
3 | * @param schema
4 | * @returns schema with version set to 4.5.0
5 | */
6 | export function main({ filters, panels, ...rest }: Record) {
7 | return {
8 | filters,
9 | views: [
10 | {
11 | id: 'Main',
12 | type: 'div',
13 | config: {},
14 | panels,
15 | },
16 | ],
17 | ...rest,
18 | version: '4.5.0',
19 | };
20 | }
21 |
--------------------------------------------------------------------------------
/api/src/dashboard_migration/handlers/4.5.2.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * migrate to v4.5.2
3 | * Changes: add visibleInViewsIDs to filter
4 | * @param schema
5 | * @returns schema with version set to 4.5.2
6 | */
7 | export function main({ filters, views, ...rest }: Record) {
8 | return {
9 | filters: filters.map((f) => ({
10 | ...f,
11 | visibleInViewsIDs: 'Main',
12 | })),
13 | views,
14 | ...rest,
15 | version: '4.5.2',
16 | };
17 | }
18 |
--------------------------------------------------------------------------------
/api/src/dashboard_migration/handlers/4.5.3.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * migrate to v4.5.3
3 | * Changes: fix mistyped visibleInViewsIDs
4 | * @param schema
5 | * @returns schema with version set to 4.5.3
6 | */
7 | export function main({ filters, views, ...rest }: Record) {
8 | return {
9 | filters: filters.map((f) => ({
10 | ...f,
11 | visibleInViewsIDs: ['Main'],
12 | })),
13 | views,
14 | ...rest,
15 | version: '4.5.3',
16 | };
17 | }
18 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/scatter-chart/option/dataset.ts:
--------------------------------------------------------------------------------
1 | import { parseDataKey } from '~/utils';
2 | import { IScatterChartConf } from '../type';
3 |
4 | export function getDataset(conf: IScatterChartConf, data: TPanelData) {
5 | if (!conf.x_axis.data_key) {
6 | return [];
7 | }
8 | const x = parseDataKey(conf.x_axis.data_key);
9 | const source = data[x.queryID];
10 | return [
11 | {
12 | source,
13 | },
14 | ];
15 | }
16 |
--------------------------------------------------------------------------------
/website/src/pages/dashboard-editor-page/more-dashboard-info/whos-editing/types.ts:
--------------------------------------------------------------------------------
1 | export type PresenceType = {
2 | [key: string]: {
3 | // [id:type]: { type, name, count }
4 | type: string;
5 | name: string;
6 | count: number;
7 | };
8 | };
9 |
10 | export type PresenceDataItemType = 'APIKEY' | 'ACCOUNT';
11 |
12 | export type PresenceDataItem = {
13 | id: string;
14 | type: PresenceDataItemType;
15 | name: string;
16 | count: number;
17 | };
18 |
--------------------------------------------------------------------------------
/api/src/dashboard_migration/handlers/6.7.0.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Changes: add name to query, init name with id
3 | * @param schema
4 | * @returns new schema
5 | */
6 | export function main({ definition, ...rest }: Record) {
7 | return {
8 | definition: {
9 | ...definition,
10 | queries: definition.queries.map((q) => ({
11 | ...q,
12 | name: q.id,
13 | })),
14 | },
15 | ...rest,
16 | version: '6.7.0',
17 | };
18 | }
19 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/radar-chart/option/formatter.ts:
--------------------------------------------------------------------------------
1 | import { TNumberFormat, formatNumber } from '~/utils';
2 |
3 | export function getFormatter(formatter: TNumberFormat) {
4 | if (!formatter) {
5 | return (value: number) => value;
6 | }
7 | return (value: number) => {
8 | try {
9 | return formatNumber(value, formatter);
10 | } catch (error) {
11 | console.error(error);
12 | return value;
13 | }
14 | };
15 | }
16 |
--------------------------------------------------------------------------------
/tools/workspace-plugin/src/executors/is-published/schema.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://json-schema.org/schema",
3 | "version": 2,
4 | "title": "IsPublished executor",
5 | "description": "Check if a package version is published on npm and fail if it is",
6 | "type": "object",
7 | "properties": {
8 | "packageJson": {
9 | "type": "string",
10 | "description": "Path to the package.json file"
11 | }
12 | },
13 | "required": ["packageJson"]
14 | }
15 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/heatmap/option/grid.ts:
--------------------------------------------------------------------------------
1 | import { IHeatmapConf } from '../type';
2 |
3 | export function getGrid(conf: IHeatmapConf) {
4 | let bottom = 0;
5 | if (conf.x_axis.name) {
6 | bottom += 20;
7 | }
8 |
9 | return {
10 | show: true,
11 | top: 45,
12 | left: 5,
13 | right: 5,
14 | bottom,
15 | containLabel: true,
16 | borderColor: 'none',
17 | backgroundColor: '#E7E7E9',
18 | z: 1,
19 | };
20 | }
21 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/merico-stats/migrators/v2.ts:
--------------------------------------------------------------------------------
1 | import { TMericoStatsConf, TMericoStatsMetric } from '../type';
2 |
3 | export function v2(legacyConf: any): TMericoStatsConf {
4 | const { metrics, ...rest } = legacyConf;
5 | return {
6 | ...rest,
7 | metrics: metrics.map((m: TMericoStatsMetric) => ({
8 | ...m,
9 | postfix: m.postfix ?? {
10 | type: 'text',
11 | value: '',
12 | },
13 | })),
14 | };
15 | }
16 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/pie-chart/option/index.ts:
--------------------------------------------------------------------------------
1 | import { IPieChartConf } from '../type';
2 | import { getDataset } from './dataset';
3 | import { getSeries } from './series';
4 | import { getTooltip } from './tooltip';
5 |
6 | export function getOption(conf: IPieChartConf, data: TPanelData, width: number) {
7 | return {
8 | dataset: getDataset(conf, data),
9 | tooltip: getTooltip(conf),
10 | series: getSeries(conf, data, width),
11 | };
12 | }
13 |
--------------------------------------------------------------------------------
/dashboard/src/contexts/dashboard-theme-context.ts:
--------------------------------------------------------------------------------
1 | import React, { ReactNode } from 'react';
2 | import { RenderSearchButtonProps } from '..';
3 |
4 | const DashboardThemeContext = React.createContext<{
5 | renderSearchButton?: (props: RenderSearchButtonProps) => ReactNode;
6 | }>({});
7 |
8 | export const DashboardThemeContextProvider = DashboardThemeContext.Provider;
9 |
10 | export function useDashboardThemeContext() {
11 | return React.useContext(DashboardThemeContext);
12 | }
13 |
--------------------------------------------------------------------------------
/tools/workspace-plugin/src/generators/viz-component/files/viz-__dashedName__.tsx__tmpl__:
--------------------------------------------------------------------------------
1 | import { VizViewProps } from '~/types/plugin';
2 | import { useStorageData } from '~/components/plugins';
3 | import { DEFAULT_CONFIG, I<%= pascalcase(name) %>Conf } from './type';
4 |
5 | export function Viz<%= pascalcase(name) %>({ context }: VizViewProps) {
6 | const { value: conf } = useStorageDataConf>(context.instanceData, 'config');
7 | return Hello World
;
8 | }
9 |
--------------------------------------------------------------------------------
/website/src/pages/account-page/index.tsx:
--------------------------------------------------------------------------------
1 | import { AccountList } from '@devtable/settings-form';
2 | import { Box } from '@mantine/core';
3 | import { SettingsFormConfig } from '../../utils/config';
4 | import { useLanguageContext } from '../../contexts';
5 |
6 | export function AccountsPage() {
7 | const { lang } = useLanguageContext();
8 | return (
9 |
10 |
11 |
12 | );
13 | }
14 |
--------------------------------------------------------------------------------
/website/src/pages/api-key-page/index.tsx:
--------------------------------------------------------------------------------
1 | import { APIKeyList } from '@devtable/settings-form';
2 | import { Box } from '@mantine/core';
3 | import { SettingsFormConfig } from '../../utils/config';
4 | import { useLanguageContext } from '../../contexts';
5 |
6 | export function APIKeyPage() {
7 | const { lang } = useLanguageContext();
8 | return (
9 |
10 |
11 |
12 | );
13 | }
14 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/merico-heatmap/render/option/grid.ts:
--------------------------------------------------------------------------------
1 | import { TMericoHeatmapConf } from '../../type';
2 |
3 | export function getGrid(conf: TMericoHeatmapConf) {
4 | let bottom = 0;
5 | if (conf.x_axis.name) {
6 | bottom += 20;
7 | }
8 |
9 | return {
10 | top: 45,
11 | left: 5,
12 | right: 5,
13 | bottom,
14 | containLabel: true,
15 | borderColor: 'none',
16 | backgroundColor: '#E7E7E9',
17 | z: 1,
18 | };
19 | }
20 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/viz-merico-gqm/translation.ts:
--------------------------------------------------------------------------------
1 | import { TranslationPatch } from '~/types/plugin';
2 |
3 | const en = {
4 | merico_gqm: {
5 | viz_name: 'Merico GQM',
6 | },
7 | };
8 |
9 | const zh = {
10 | merico_gqm: {
11 | viz_name: '思码逸GQM组件',
12 | },
13 | };
14 |
15 | export const translation: TranslationPatch = [
16 | {
17 | lang: 'en',
18 | resources: en,
19 | },
20 | {
21 | lang: 'zh',
22 | resources: zh,
23 | },
24 | ];
25 |
--------------------------------------------------------------------------------
/dashboard/src/utils/color-feed.ts:
--------------------------------------------------------------------------------
1 | import { ChartTheme } from '~/styles/register-themes';
2 | export function* getColorFeed(paletteKey: keyof typeof ChartTheme.graphics): Generator {
3 | const theme = ChartTheme.graphics[paletteKey];
4 | if (!theme) {
5 | throw new Error('Invalid palette key provided');
6 | }
7 |
8 | const palette = Object.values(theme);
9 |
10 | let i = 0;
11 | while (true) {
12 | yield palette[i % palette.length];
13 | i++;
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/dashboard/src/utils/color-mapping.ts:
--------------------------------------------------------------------------------
1 | import { interpolate } from 'popmotion';
2 |
3 | export interface InterpolateColorOption {
4 | valueRange: number[];
5 | colorRange: string[];
6 | }
7 | export class InterpolateColor {
8 | mapper: (v: number) => string;
9 |
10 | constructor({ valueRange, colorRange }: InterpolateColorOption) {
11 | this.mapper = interpolate(valueRange, colorRange);
12 | }
13 |
14 | getColor(value: number) {
15 | return this.mapper(value);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/website/src/components/account-type-icon.tsx:
--------------------------------------------------------------------------------
1 | import { ActionIcon } from '@mantine/core';
2 | import { IconApi, IconUser } from '@tabler/icons-react';
3 |
4 | export const AccountTypeIcon = ({ type }: { type: 'ACCOUNT' | 'APIKEY' | null }) => {
5 | if (!type) {
6 | return null;
7 | }
8 | return (
9 |
10 | {type === 'APIKEY' ? : }
11 |
12 | );
13 | };
14 |
--------------------------------------------------------------------------------
/dashboard/src/components/filter/use-update-filter-preview-values.ts:
--------------------------------------------------------------------------------
1 | import { useEffect } from 'react';
2 | import { useEditContentModelContext } from '~/contexts';
3 |
4 | export function useUpdateFilterPreviewValues(formValue: any) {
5 | const content = useEditContentModelContext();
6 |
7 | useEffect(() => {
8 | // this form is not a controlled component,
9 | // so we need to manually update the model
10 | content.filters.updatePreviewValues?.(formValue);
11 | }, [formValue]);
12 | }
13 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/bar-3d-chart/translation.ts:
--------------------------------------------------------------------------------
1 | import { TranslationPatch } from '~/types/plugin';
2 |
3 | const en = {
4 | bar_chart_3d: {
5 | viz_name: 'Bar Chart(3D)',
6 | },
7 | };
8 |
9 | const zh = {
10 | bar_chart_3d: {
11 | viz_name: '柱图(3D)',
12 | },
13 | };
14 |
15 | export const translation: TranslationPatch = [
16 | {
17 | lang: 'en',
18 | resources: en,
19 | },
20 | {
21 | lang: 'zh',
22 | resources: zh,
23 | },
24 | ];
25 |
--------------------------------------------------------------------------------
/website/src/frames/admin/navbar/index.tsx:
--------------------------------------------------------------------------------
1 | import { AppShell } from '@mantine/core';
2 | import { AdminPageLinks } from './admin-page-links';
3 | import { AdminSystemNavActions } from './admin-system-nav-actions';
4 |
5 | export function AdminNavbar() {
6 | return (
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | );
15 | }
16 |
--------------------------------------------------------------------------------
/website/src/frames/socket-client-frame/types.ts:
--------------------------------------------------------------------------------
1 | // FIXME(leto): import from api/src/utils/websocket.ts
2 | export enum SERVER_CHANNELS {
3 | DASHBOARD = 'DASHBOARD',
4 | DASHBOARD_EDIT_PRESENCE = 'DASHBOARD_EDIT_PRESENCE',
5 | }
6 |
7 | // FIXME(leto): import from api/src/utils/websocket.ts
8 | export enum CLIENT_CHANNELS {
9 | DASHBOARD_GET_EDIT_PRESENCE = 'DASHBOARD_GET_EDIT_PRESENCE',
10 | DASHBOARD_START_EDIT = 'DASHBOARD_START_EDIT',
11 | DASHBOARD_END_EDIT = 'DASHBOARD_END_EDIT',
12 | }
13 |
--------------------------------------------------------------------------------
/website/src/pages/data-source-page/index.tsx:
--------------------------------------------------------------------------------
1 | import { DataSourceList } from '@devtable/settings-form';
2 | import { Box } from '@mantine/core';
3 | import { SettingsFormConfig } from '../../utils/config';
4 | import { useLanguageContext } from '../../contexts';
5 |
6 | export function DataSourcePage() {
7 | const { lang } = useLanguageContext();
8 | return (
9 |
10 |
11 |
12 | );
13 | }
14 |
--------------------------------------------------------------------------------
/website/src/pages/sql-snippet-page/index.tsx:
--------------------------------------------------------------------------------
1 | import { SQLSnippetList } from '@devtable/settings-form';
2 | import { Box } from '@mantine/core';
3 | import { SettingsFormConfig } from '../../utils/config';
4 | import { useLanguageContext } from '../../contexts';
5 |
6 | export function SQLSnippetPage() {
7 | const { lang } = useLanguageContext();
8 | return (
9 |
10 |
11 |
12 | );
13 | }
14 |
--------------------------------------------------------------------------------
/api/src/dashboard_migration/handlers/5.9.1.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Changes: add _name to filter.config to avoid incorrect type inference
3 | * @param schema
4 | * @returns new schema
5 | */
6 | export function main({ filters, views, ...rest }: Record) {
7 | return {
8 | filters: filters.map((f) => ({
9 | ...f,
10 | config: {
11 | _name: f.type,
12 | ...f.config,
13 | },
14 | })),
15 | views,
16 | ...rest,
17 | version: '5.9.1',
18 | };
19 | }
20 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/boxplot-chart/option/grid.ts:
--------------------------------------------------------------------------------
1 | import { IBoxplotChartConf } from '../type';
2 |
3 | export function getGrid(conf: IBoxplotChartConf) {
4 | const grid = {
5 | top: 35,
6 | left: 20,
7 | right: 15,
8 | bottom: 25,
9 | containLabel: true,
10 | };
11 |
12 | if (conf.legend.orient === 'vertical') {
13 | grid.right = 80;
14 | }
15 | if (conf.dataZoom.x_axis_slider) {
16 | grid.top = 50;
17 | }
18 |
19 | return grid;
20 | }
21 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/merico-estimation-chart/toolbox/index.tsx:
--------------------------------------------------------------------------------
1 | import { Group } from '@mantine/core';
2 | import { BasisMetricSelector, IBasisMetricSelector } from './basis-metric-selector';
3 | import { MetricsDescription } from './metric-description';
4 |
5 | export function Toolbox(props: IBasisMetricSelector) {
6 | return (
7 |
8 |
9 |
10 |
11 | );
12 | }
13 |
--------------------------------------------------------------------------------
/api/src/data_sources/migrations/1660005273691-add-extension-citext.ts:
--------------------------------------------------------------------------------
1 | import { MigrationInterface, QueryRunner } from 'typeorm';
2 |
3 | export class addExtensionCitext1660005273691 implements MigrationInterface {
4 | public async up(queryRunner: QueryRunner): Promise {
5 | await queryRunner.query(`CREATE EXTENSION IF NOT EXISTS citext`);
6 | }
7 |
8 | public async down(queryRunner: QueryRunner): Promise {
9 | await queryRunner.query(`DROP EXTENSION IF EXISTS citext`);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/api/src/models/role.ts:
--------------------------------------------------------------------------------
1 | import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm';
2 |
3 | @Entity()
4 | export default class Role {
5 | @PrimaryGeneratedColumn('identity', {
6 | name: 'id',
7 | comment: '实体id',
8 | })
9 | id: string;
10 |
11 | @Column('text', {
12 | nullable: false,
13 | name: 'description',
14 | })
15 | description: string;
16 |
17 | @Column('jsonb', {
18 | nullable: false,
19 | name: 'permissions',
20 | })
21 | permissions: string[];
22 | }
23 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/heatmap/editors/tooltip/index.tsx:
--------------------------------------------------------------------------------
1 | import { Control, UseFormWatch } from 'react-hook-form';
2 | import { IHeatmapConf } from '../../type';
3 | import { TooltipMetricsField } from './metrics';
4 |
5 | interface ITooltipField {
6 | control: Control;
7 | watch: UseFormWatch;
8 | }
9 | export function TooltipField({ control, watch }: ITooltipField) {
10 | return ;
11 | }
12 |
--------------------------------------------------------------------------------
/settings-form/src/api-caller/account.typed.ts:
--------------------------------------------------------------------------------
1 | export interface IAccount {
2 | id: string;
3 | name: string;
4 | email: string;
5 | role_id: string;
6 | create_time: string;
7 | update_time: string;
8 | }
9 |
10 | export interface IEditAccountPayload {
11 | id: string;
12 | name: string;
13 | email: string;
14 | role_id: string;
15 | reset_password: boolean;
16 | new_password?: string;
17 | }
18 |
19 | export interface ILoginResp {
20 | account: IAccount;
21 | token: string;
22 | }
23 |
--------------------------------------------------------------------------------
/shared/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig.base.json",
3 | "compilerOptions": {
4 | "module": "commonjs",
5 | "forceConsistentCasingInFileNames": true,
6 | "strict": true,
7 | "noImplicitOverride": true,
8 | "noPropertyAccessFromIndexSignature": true,
9 | "noImplicitReturns": true,
10 | "noFallthroughCasesInSwitch": true
11 | },
12 | "files": [],
13 | "include": [],
14 | "references": [
15 | {
16 | "path": "./tsconfig.lib.json"
17 | }
18 | ]
19 | }
20 |
--------------------------------------------------------------------------------
/api/src/middleware/ensureAuthEnabled.ts:
--------------------------------------------------------------------------------
1 | import * as express from 'express';
2 | import { AUTH_ENABLED } from '../utils/constants';
3 | import { ApiError, AUTH_NOT_ENABLED } from '../utils/errors';
4 | import { translate } from '../utils/i18n';
5 |
6 | export default function ensureAuthEnabled(req: express.Request, res: express.Response, next: express.NextFunction) {
7 | if (!AUTH_ENABLED) {
8 | throw new ApiError(AUTH_NOT_ENABLED, { message: translate('AUTH_NOT_ENABLED', req.locale) });
9 | }
10 | next();
11 | }
12 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/message-channels.spec.ts:
--------------------------------------------------------------------------------
1 | import { IMessageChannels } from '~/types/plugin';
2 | import { MessageChannels } from './message-channels';
3 |
4 | describe('message channels', () => {
5 | let channels: IMessageChannels;
6 | beforeEach(() => {
7 | channels = new MessageChannels();
8 | });
9 | test('can get channel', () => {
10 | const alice = channels.getChannel('alice');
11 | const alice2 = channels.getChannel('alice');
12 | expect(alice).toBe(alice2);
13 | });
14 | });
15 |
--------------------------------------------------------------------------------
/website/src/components/load-favicon.tsx:
--------------------------------------------------------------------------------
1 | import { useRequest } from 'ahooks';
2 | import { Helmet } from 'react-helmet-async';
3 | import { ConfigAPI } from '../api-caller/config';
4 |
5 | export const LoadFavicon = () => {
6 | const { data } = useRequest(ConfigAPI.getWebsiteSettings);
7 | if (!data?.WEBSITE_FAVICON_URL) {
8 | return null;
9 | }
10 | return (
11 |
12 |
13 |
14 | );
15 | };
16 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/funnel/option/index.ts:
--------------------------------------------------------------------------------
1 | import { AnyObject } from '~/types';
2 | import { IFunnelConf } from '../type';
3 | import { getSeries } from './series';
4 | import { getTooltip } from './tooltip';
5 |
6 | export function getOption(conf: IFunnelConf, data: TPanelData) {
7 | return {
8 | grid: {
9 | top: 0,
10 | left: 0,
11 | right: 0,
12 | bottom: 0,
13 | },
14 | tooltip: getTooltip(conf, data),
15 | series: getSeries(conf, data),
16 | };
17 | }
18 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/radar-chart/option/series.label.ts:
--------------------------------------------------------------------------------
1 | import { IRadarChartConf } from '../type';
2 | import { getFormatter } from './formatter';
3 |
4 | export function getSeriesLabel(conf: IRadarChartConf) {
5 | return {
6 | show: conf.label.enabled,
7 | formatter: ({ dimensionIndex, value }: { dimensionIndex: number; value: number }) => {
8 | const formatter = getFormatter(conf.dimensions[dimensionIndex].formatter);
9 | return formatter(value);
10 | },
11 | };
12 | }
13 |
--------------------------------------------------------------------------------
/api/jest-u.config.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line @typescript-eslint/no-var-requires
2 | const defaultConfig = require('./jest.config');
3 |
4 | module.exports = {
5 | ...defaultConfig,
6 | coverageDirectory: './coverage-u/',
7 | globalSetup: '/tests/unit/jest.setup.ts',
8 | testRegex: '(/tests/unit/.*(test|spec|unit))\\.(jsx?|tsx?)$',
9 | roots: ['/tests/unit/'],
10 | maxWorkers: 1,
11 | globals: {
12 | 'ts-jest': {
13 | tsconfig: 'tests/unit/tsconfig.json',
14 | },
15 | },
16 | };
17 |
--------------------------------------------------------------------------------
/dashboard/src/styles/default-echarts-options/y-axis.ts:
--------------------------------------------------------------------------------
1 | import _ from 'lodash';
2 | import { AnyObject } from '~/types';
3 |
4 | export const yAxis = {
5 | axisTick: {
6 | show: false,
7 | },
8 | axisLine: {
9 | show: false,
10 | lineStyle: {
11 | width: 3,
12 | },
13 | },
14 | splitLine: {
15 | show: true,
16 | lineStyle: {
17 | type: 'dashed',
18 | },
19 | },
20 | };
21 |
22 | export function getYAxis(option: AnyObject) {
23 | return _.defaultsDeep({}, option, yAxis);
24 | }
25 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/merico-heatmap/editors/tooltip/index.tsx:
--------------------------------------------------------------------------------
1 | import { Control, UseFormWatch } from 'react-hook-form';
2 | import { TMericoHeatmapConf } from '../../type';
3 | import { TooltipMetricsField } from './metrics';
4 |
5 | interface ITooltipField {
6 | control: Control;
7 | watch: UseFormWatch;
8 | }
9 | export function TooltipField({ control, watch }: ITooltipField) {
10 | return ;
11 | }
12 |
--------------------------------------------------------------------------------
/website/src/pages/dashboard-editor-page/more-dashboard-info/dashboard-changlog-modal/changelog-modal-trigger.tsx:
--------------------------------------------------------------------------------
1 | import { Menu } from '@mantine/core';
2 | import { IconHistory } from '@tabler/icons-react';
3 | import { TModalState } from '../types';
4 |
5 | interface IProps {
6 | state: TModalState;
7 | }
8 | export const DashboardChangelogModalTrigger = ({ state }: IProps) => {
9 | return (
10 | }>
11 | Changelog
12 |
13 | );
14 | };
15 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/calendar-heatmap/editors/tooltip/index.tsx:
--------------------------------------------------------------------------------
1 | import { Control, UseFormWatch } from 'react-hook-form';
2 | import { ICalendarHeatmapConf } from '../../type';
3 | import { TooltipMetricsField } from './metrics';
4 |
5 | interface ITooltipField {
6 | control: Control;
7 | watch: UseFormWatch;
8 | }
9 | export function TooltipField({ control, watch }: ITooltipField) {
10 | return ;
11 | }
12 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/scatter-chart/option/grid.ts:
--------------------------------------------------------------------------------
1 | import { IScatterChartConf } from '../type';
2 |
3 | export function getGrid(conf: IScatterChartConf) {
4 | const hasYAxisName = conf.y_axes.some((y) => !!y.name);
5 | let top = 15;
6 | if (hasYAxisName) {
7 | top += 20;
8 | }
9 | if (conf.dataZoom.x_axis_slider) {
10 | top += 20;
11 | }
12 |
13 | let bottom = 5;
14 | if (conf.x_axis.name) {
15 | bottom += 15;
16 | }
17 |
18 | return {
19 | top,
20 | bottom,
21 | };
22 | }
23 |
--------------------------------------------------------------------------------
/dashboard/src/utils/diff-json.ts:
--------------------------------------------------------------------------------
1 | import _ from 'lodash';
2 | import { AnyObject } from '..';
3 |
4 | function printChanges(a: any, b: any) {
5 | if (_.isEqual(a, b)) {
6 | return;
7 | }
8 | if (Array.isArray(a) && Array.isArray(b)) {
9 | a.forEach((_a, i) => {
10 | printChanges(_a, b[i]);
11 | });
12 | return;
13 | }
14 | console.log(a, b);
15 | }
16 |
17 | export function printJSONChanges(a: AnyObject, b: AnyObject) {
18 | Object.keys(a).forEach((k) => {
19 | printChanges(a[k], b[k]);
20 | });
21 | }
22 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/common-echarts-fields/label-position/types.ts:
--------------------------------------------------------------------------------
1 | export type IEchartsLabelPosition =
2 | | 'top'
3 | | 'left'
4 | | 'right'
5 | | 'bottom'
6 | | 'inside'
7 | | 'insideLeft'
8 | | 'insideRight'
9 | | 'insideTop'
10 | | 'insideBottom'
11 | | 'insideTopLeft'
12 | | 'insideBottomLeft'
13 | | 'insideTopRight'
14 | | 'insideBottomRight'
15 | | 'outside';
16 |
17 | export type LabelPositionOptionType = {
18 | label: string;
19 | value: IEchartsLabelPosition;
20 | disabled?: boolean;
21 | };
22 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/index.ts:
--------------------------------------------------------------------------------
1 | export * from './viz-manager';
2 | export * from './plugin-context';
3 | export * from './plugin-data-migrator';
4 | export * from './hooks';
5 | export * from './color-manager';
6 | export { onVizRendered, notifyVizRendered } from './viz-components/viz-instance-api';
7 | export { ServiceLocator, Token } from './service/service-locator';
8 | export { useServiceLocator } from './service/service-locator/use-service-locator';
9 | export type { IServiceLocator, IDisposable } from './service/service-locator';
10 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/merico-estimation-chart/translation.ts:
--------------------------------------------------------------------------------
1 | import { TranslationPatch } from '~/types/plugin';
2 |
3 | const en = {
4 | merico_estimation_chart: {
5 | viz_name: 'Merico Estimation Chart',
6 | },
7 | };
8 |
9 | const zh = {
10 | merico_estimation_chart: {
11 | viz_name: '思码逸估算分析图',
12 | },
13 | };
14 |
15 | export const translation: TranslationPatch = [
16 | {
17 | lang: 'en',
18 | resources: en,
19 | },
20 | {
21 | lang: 'zh',
22 | resources: zh,
23 | },
24 | ];
25 |
--------------------------------------------------------------------------------
/settings-form/project.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "settings-form",
3 | "$schema": "../node_modules/nx/schemas/project-schema.json",
4 | "projectType": "library",
5 | "targets": {
6 | "check": {
7 | "executor": "nx:run-commands",
8 | "options": {
9 | "command": "echo noop, build runs type-checking automatically"
10 | }
11 | },
12 | "dev": {
13 | "executor": "nx:run-script",
14 | "options": {
15 | "script": "dev-build"
16 | },
17 | "dependsOn": ["^build"]
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/website/src/components/logo/index.tsx:
--------------------------------------------------------------------------------
1 | import { useRequest } from 'ahooks';
2 | import { ConfigAPI } from '../../api-caller/config';
3 | import { LogoLink } from './logo-link';
4 | import { Box } from '@mantine/core';
5 |
6 | export const Logo = ({ height }: { height: string | number }) => {
7 | const { data } = useRequest(ConfigAPI.getWebsiteSettings);
8 | if (!data) {
9 | return null;
10 | }
11 |
12 | return (
13 |
14 |
15 |
16 | );
17 | };
18 |
--------------------------------------------------------------------------------
/website/src/frames/app/navbar-toggler.tsx:
--------------------------------------------------------------------------------
1 | import { ActionIcon, Tooltip } from '@mantine/core';
2 | import { IconLayoutSidebar } from '@tabler/icons-react';
3 |
4 | export const NavbarToggler = ({ collapsed, expand }: { collapsed: boolean; expand: () => void }) => {
5 | if (!collapsed) {
6 | return null;
7 | }
8 | return (
9 |
10 |
11 |
12 |
13 |
14 | );
15 | };
16 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/pie-chart/editors/pie-color-map-editor/palette.ts:
--------------------------------------------------------------------------------
1 | import _ from 'lodash';
2 | import { ChartTheme } from '~/styles/register-themes';
3 |
4 | export type PieChartPaletteOption = {
5 | name: string;
6 | colors: string[];
7 | };
8 | export const PieChartPalettes = Object.entries(
9 | _.pick(ChartTheme.graphics, ['compared', 'level', 'depth', 'multiple']),
10 | ).map(([name, record]) => {
11 | return {
12 | name,
13 | colors: Object.values(record),
14 | } as PieChartPaletteOption;
15 | });
16 |
--------------------------------------------------------------------------------
/dashboard/src/contexts/layout-state-context.ts:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export interface ILayoutStateContext {
4 | inEditMode: boolean;
5 | }
6 |
7 | const initialContext = {
8 | inEditMode: false,
9 | };
10 |
11 | export const LayoutStateContext = React.createContext(initialContext);
12 |
13 | export function useLayoutStateContext() {
14 | const ctx = React.useContext(LayoutStateContext);
15 | if (!ctx) {
16 | throw new Error('Please use LayoutStateContext.Provider');
17 | }
18 | return ctx;
19 | }
20 |
--------------------------------------------------------------------------------
/tools/workspace-plugin/src/generators/viz-component/files/translation.ts__tmpl__:
--------------------------------------------------------------------------------
1 | import { TranslationPatch } from '~/types/plugin';
2 |
3 | const en = {
4 | <%= camelcase(name) %>: {
5 | viz_name: '<%= pascalcase(name) %>',
6 | },
7 | };
8 |
9 | const zh = {
10 | <%= camelcase(name) %>: {
11 | viz_name: '<%= pascalcase(name) %>',
12 | },
13 | };
14 |
15 | export const translation: TranslationPatch = [
16 | {
17 | lang: 'en',
18 | resources: en,
19 | },
20 | {
21 | lang: 'zh',
22 | resources: zh,
23 | },
24 | ];
25 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/merico-linear-gauge/editor/sections-editor/palette.ts:
--------------------------------------------------------------------------------
1 | import _ from 'lodash';
2 | import { ChartTheme } from '~/styles/register-themes';
3 |
4 | export type PieChartPaletteOption = {
5 | name: string;
6 | colors: string[];
7 | };
8 | export const PieChartPalettes = Object.entries(
9 | _.pick(ChartTheme.graphics, ['compared', 'level', 'depth', 'multiple']),
10 | ).map(([name, record]) => {
11 | return {
12 | name,
13 | colors: Object.values(record),
14 | } as PieChartPaletteOption;
15 | });
16 |
--------------------------------------------------------------------------------
/api/src/models/sql_snippet.ts:
--------------------------------------------------------------------------------
1 | import { Entity, Column, PrimaryColumn } from 'typeorm';
2 | import { BaseModel } from './base';
3 |
4 | @Entity()
5 | export default class SqlSnippet extends BaseModel {
6 | @PrimaryColumn('character varying', {
7 | nullable: false,
8 | name: 'id',
9 | })
10 | id: string;
11 |
12 | @Column('text', {
13 | nullable: false,
14 | name: 'content',
15 | })
16 | content: string;
17 |
18 | @Column('boolean', {
19 | default: false,
20 | name: 'is_preset',
21 | })
22 | is_preset: boolean;
23 | }
24 |
--------------------------------------------------------------------------------
/api/src/utils/logger.ts:
--------------------------------------------------------------------------------
1 | import * as logger from 'npmlog';
2 |
3 | export const enum LOG_LEVELS {
4 | INFO = 'info',
5 | WARN = 'warn',
6 | ERROR = 'error',
7 | }
8 |
9 | export enum LOG_LABELS {
10 | SERVER = 'SERVER',
11 | DASHBOARD_SCHEMA = 'DASHBOARD_SCHEMA',
12 | API = 'API',
13 | SERVICE = 'SERVICE',
14 | AXIOS = 'AXIOS',
15 | WEBSOCKET = 'WEBSOCKET',
16 | QUERY_MISMATCH = 'QUERY_MISMATCH',
17 | }
18 |
19 | export default function log(level: LOG_LEVELS, label: LOG_LABELS, message: any) {
20 | logger[level](label, message);
21 | }
22 |
--------------------------------------------------------------------------------
/dashboard/src/utils/template/editor/utils.ts:
--------------------------------------------------------------------------------
1 | import { randomId } from '@mantine/hooks';
2 | import { defaultNumberFormat } from '~/utils';
3 | import { ITemplateVariable } from '../types';
4 |
5 | export function getANewVariable() {
6 | return {
7 | name: randomId(),
8 | size: '20px',
9 | weight: 'bold',
10 | color: {
11 | type: 'static',
12 | staticColor: 'blue',
13 | },
14 | data_field: '',
15 | aggregation: { type: 'none', config: {} },
16 | formatter: defaultNumberFormat,
17 | } as ITemplateVariable;
18 | }
19 |
--------------------------------------------------------------------------------
/tools/workspace-plugin/src/generators/viz-component/schema.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://json-schema.org/schema",
3 | "cli": "nx",
4 | "$id": "viz-component",
5 | "type": "object",
6 | "properties": {
7 | "name": {
8 | "type": "string",
9 | "description": "component name",
10 | "$default": {
11 | "$source": "argv",
12 | "index": 0
13 | }
14 | },
15 | "path": {
16 | "type": "string",
17 | "description": "path to the generated files"
18 | }
19 | },
20 | "required": ["name"]
21 | }
22 |
--------------------------------------------------------------------------------
/api/src/data_sources/dashboard.ts:
--------------------------------------------------------------------------------
1 | import path from 'path';
2 | import { DataSource } from 'typeorm';
3 |
4 | // eslint-disable-next-line @typescript-eslint/no-var-requires
5 | require('dotenv').config({ path: path.join(__dirname, '../../.env') });
6 |
7 | export const dashboardDataSource = new DataSource({
8 | type: 'postgres',
9 | url: process.env.PG_URL,
10 | migrationsTableName: 'schema_migrations',
11 | migrations: ['src/data_sources/migrations/*.ts', 'dist/data_sources/migrations/*.js'],
12 | entities: ['src/models/*.ts', 'dist/models/*.js'],
13 | });
14 |
--------------------------------------------------------------------------------
/dashboard/src/styles/default-echarts-options/x-axis.ts:
--------------------------------------------------------------------------------
1 | import _ from 'lodash';
2 | import { AnyObject } from '~/types';
3 |
4 | export const xAxis = {
5 | axisTick: {
6 | show: true,
7 | alignWithLabel: true,
8 | lineStyle: {
9 | width: 2,
10 | },
11 | },
12 | axisLine: {
13 | show: true,
14 | lineStyle: {
15 | width: 3,
16 | },
17 | },
18 | splitLine: {
19 | show: false,
20 | },
21 | z: 3,
22 | };
23 |
24 | export function getXAxis(option: AnyObject) {
25 | return _.defaultsDeep({}, option, xAxis);
26 | }
27 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/cartesian/option/utils/variables.ts:
--------------------------------------------------------------------------------
1 | import { AnyObject } from '~/types';
2 | import { formatAggregatedValue, getAggregatedValue, ITemplateVariable } from '~/utils';
3 |
4 | export function getVariableValueMap(data: TPanelData, variables: ITemplateVariable[]) {
5 | const ret: Record = {};
6 |
7 | variables.map((variable) => {
8 | const value = getAggregatedValue(variable, data);
9 | ret[variable.name] = formatAggregatedValue(variable, value);
10 | });
11 |
12 | return ret;
13 | }
14 |
--------------------------------------------------------------------------------
/dashboard/src/utils/index.ts:
--------------------------------------------------------------------------------
1 | export * from './template';
2 | export * from './aggregation';
3 | export * from './color-feed';
4 | export * from './color-mapping';
5 | export * from './dashboard-state';
6 | export * from './data';
7 | export * from './diff-json';
8 | export * from './error-boundary';
9 | export * from './function-utils';
10 | export * from './http-query';
11 | export * from './number';
12 | export * from './register-echarts';
13 | export * from './shallow-to-js';
14 | export * from './sql';
15 | export * from './usage';
16 | export * from './rich-text';
17 |
--------------------------------------------------------------------------------
/api/src/models/custom_function.ts:
--------------------------------------------------------------------------------
1 | import { Entity, Column, PrimaryColumn } from 'typeorm';
2 | import { BaseModel } from './base';
3 |
4 | @Entity()
5 | export default class CustomFunction extends BaseModel {
6 | @PrimaryColumn('character varying', {
7 | nullable: false,
8 | name: 'id',
9 | })
10 | id: string;
11 |
12 | @Column('text', {
13 | nullable: false,
14 | name: 'definition',
15 | })
16 | definition: string;
17 |
18 | @Column('boolean', {
19 | default: false,
20 | name: 'is_preset',
21 | })
22 | is_preset: boolean;
23 | }
24 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/colors/diverging-color.ts:
--------------------------------------------------------------------------------
1 | import chroma from 'chroma-js';
2 | import { IColorInterpolation } from '~/types/plugin';
3 |
4 | export const createDivergingColorPalette = (left: string[], right: string[]): IColorInterpolation['getColor'] => {
5 | const leftColor = chroma.bezier(left);
6 | const rightColor = chroma.bezier(right);
7 | return function (value: number): string {
8 | if (value < 50) {
9 | return leftColor((value * 2) / 100).hex();
10 | }
11 | return rightColor(((value - 50) * 2) / 100).hex();
12 | };
13 | };
14 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/sunburst/option/types.ts:
--------------------------------------------------------------------------------
1 | import { SunburstItemType } from '../type';
2 |
3 | export type TreeItemIn = {
4 | id: string;
5 | parent_id: string | null;
6 | } & SunburstItemType;
7 |
8 | export type TreeItemOut = TreeItemIn & {
9 | children: TreeItemOut[];
10 | };
11 |
12 | export interface IEchartsSunburstLabelFormatter {
13 | treePathInfo: {
14 | name: string;
15 | dataIndex: number;
16 | value: number;
17 | }[];
18 | name: string;
19 | value: number;
20 | marker: string;
21 | color: string;
22 | }
23 |
--------------------------------------------------------------------------------
/dashboard/src/interactions/hooks/use-current-interaction-manager.ts:
--------------------------------------------------------------------------------
1 | import { IVizManager, tokens } from '~/components/plugins';
2 | import { IVizInteractionManager, VizInstance } from '~/types/plugin';
3 | import { useServiceLocator } from '~/components/plugins/service/service-locator/use-service-locator';
4 |
5 | export const useCurrentInteractionManager = ({}: {
6 | vizManager: IVizManager;
7 | instance: VizInstance;
8 | }): IVizInteractionManager => {
9 | const sl = useServiceLocator();
10 | return sl.getRequired(tokens.instanceScope.interactionManager);
11 | };
12 |
--------------------------------------------------------------------------------
/api/src/dashboard_migration/handlers/4.10.0.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Changes: introduce panel.style & panel.style.border
3 | * @param schema
4 | * @returns new schema
5 | */
6 | export function main({ views, ...rest }: Record) {
7 | return {
8 | views: views.map((v) => ({
9 | ...v,
10 | panels: v.panels.map((p) => ({
11 | ...p,
12 | style: {
13 | border: {
14 | enabled: !!p.style?.border?.enabled,
15 | },
16 | },
17 | })),
18 | })),
19 | ...rest,
20 | version: '4.10.0',
21 | };
22 | }
23 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/cartesian/editors/echarts-zooming-field/types.ts:
--------------------------------------------------------------------------------
1 | import _ from 'lodash';
2 |
3 | export type TEchartsDataZoomConfig = {
4 | x_axis_scroll: boolean;
5 | y_axis_scroll: boolean;
6 | x_axis_slider: boolean;
7 | y_axis_slider: boolean;
8 | };
9 |
10 | export const DEFAULT_DATA_ZOOM_CONFIG = {
11 | x_axis_scroll: false,
12 | y_axis_scroll: false,
13 | x_axis_slider: false,
14 | y_axis_slider: false,
15 | };
16 |
17 | export function getDefaultDataZoomConfig() {
18 | return _.cloneDeep(DEFAULT_DATA_ZOOM_CONFIG);
19 | }
20 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/horizontal-bar-chart/option/utils/variables.ts:
--------------------------------------------------------------------------------
1 | import { AnyObject } from '~/types';
2 | import { formatAggregatedValue, getAggregatedValue, ITemplateVariable } from '~/utils';
3 |
4 | export function getVariableValueMap(data: TPanelData, variables: ITemplateVariable[]) {
5 | const ret: Record = {};
6 |
7 | variables.map((variable) => {
8 | const value = getAggregatedValue(variable, data);
9 | ret[variable.name] = formatAggregatedValue(variable, value);
10 | });
11 |
12 | return ret;
13 | }
14 |
--------------------------------------------------------------------------------
/website/src/pages/dashboard-editor-page/more-dashboard-info/use-modal-states.ts:
--------------------------------------------------------------------------------
1 | import { useDisclosure } from '@mantine/hooks';
2 | import { TModalState, TModalStates } from './types';
3 |
4 | function useModalState(): TModalState {
5 | const [opened, { open, close }] = useDisclosure(false);
6 | return {
7 | opened,
8 | open,
9 | close,
10 | };
11 | }
12 |
13 | export function useModalStates(): TModalStates {
14 | const changelog = useModalState();
15 | const version = useModalState();
16 | return {
17 | changelog,
18 | version,
19 | };
20 | }
21 |
--------------------------------------------------------------------------------
/website/src/utils/configure-monaco-editor/index.ts:
--------------------------------------------------------------------------------
1 | import { loader } from '@monaco-editor/react';
2 | import { MonacoPath } from '../config';
3 | import { configureSQLLanguage } from './configure-sql-language';
4 | import { configureDiffLanguage } from './custom-diff-language';
5 |
6 | const cleanURL = (str: string) => {
7 | return str.replace(/([^:])(\/\/+)/g, '$1/');
8 | };
9 | const path = cleanURL(MonacoPath);
10 | loader.config({ paths: { vs: path } });
11 | loader.init().then((monaco) => {
12 | configureDiffLanguage(monaco);
13 | configureSQLLanguage(monaco);
14 | });
15 |
--------------------------------------------------------------------------------
/dashboard/src/utils/dashboard-state.ts:
--------------------------------------------------------------------------------
1 | import { TDashboardStateValues, TPayloadForSQL } from '~/model';
2 |
3 | export function getEmptyDashboardStateValues(): TDashboardStateValues {
4 | return {
5 | filters: {},
6 | context: {},
7 | };
8 | }
9 |
10 | export function payloadToDashboardStateValues(payload: TPayloadForSQL) {
11 | const empty = getEmptyDashboardStateValues();
12 | if (!payload) {
13 | return getEmptyDashboardStateValues();
14 | }
15 | const { filters = empty.filters, context = empty.context } = payload;
16 | return { filters, context };
17 | }
18 |
--------------------------------------------------------------------------------
/dashboard/src/utils/template/editor/template-input.tsx:
--------------------------------------------------------------------------------
1 | import { TextInput, TextInputProps } from '@mantine/core';
2 | import { ChangeEventHandler, forwardRef } from 'react';
3 |
4 | interface ITemplateInput extends Omit {
5 | value: string;
6 | onChange: ChangeEventHandler;
7 | }
8 |
9 | export const TemplateInput = forwardRef(function TemplateInput(
10 | { value, onChange, ...rest }: ITemplateInput,
11 | ref: $TSFixMe,
12 | ) {
13 | return ;
14 | });
15 |
--------------------------------------------------------------------------------
/tools/workspace-plugin/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["../../.eslintrc.json"],
3 | "ignorePatterns": ["!**/*"],
4 | "overrides": [
5 | {
6 | "files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
7 | "rules": {}
8 | },
9 | {
10 | "files": ["*.ts", "*.tsx"],
11 | "rules": {}
12 | },
13 | {
14 | "files": ["*.js", "*.jsx"],
15 | "rules": {}
16 | },
17 | {
18 | "files": ["./package.json", "./generators.json", "./executors.json"],
19 | "parser": "jsonc-eslint-parser",
20 | "rules": {}
21 | }
22 | ]
23 | }
24 |
--------------------------------------------------------------------------------
/api/src/utils/constants.ts:
--------------------------------------------------------------------------------
1 | export const SALT_ROUNDS = 12;
2 | export const SECRET_KEY = process.env.SECRET_KEY;
3 | export const TOKEN_VALIDITY = 7 * 24 * 3600;
4 | export const AUTH_ENABLED = process.env.ENABLE_AUTH !== '0';
5 | export const DATABASE_CONNECTION_TIMEOUT_MS = parseInt(process.env.DATABASE_CONNECTION_TIMEOUT_MS ?? '30000');
6 | export const DATABASE_POOL_SIZE = parseInt(process.env.DATABASE_POOL_SIZE ?? '10');
7 | export const DEFAULT_LANGUAGE = 'en';
8 | export const CACHE_RETAIN_TIME = '86400';
9 | export const QUERY_PARSING_ENABLED = process.env.ENABLE_QUERY_PARSER === '1';
10 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/hooks/use-current-viz-instance.ts:
--------------------------------------------------------------------------------
1 | import { useCreation } from 'ahooks';
2 | import { useContext } from 'react';
3 | import { IPanelInfo, PluginContext } from '~/components/plugins';
4 | import { useRenderPanelContext } from '~/contexts';
5 |
6 | export const useCurrentVizInstance = () => {
7 | const { panel } = useRenderPanelContext();
8 | const { vizManager } = useContext(PluginContext);
9 | const panelInfo: IPanelInfo = panel.json;
10 |
11 | return useCreation(() => vizManager.getOrCreateInstance(panelInfo), [vizManager, panel.viz.type]);
12 | };
13 |
--------------------------------------------------------------------------------
/dashboard/src/dashboard-editor/ui/settings/content/db-explorer-modal/db-explorer/structure/tooltip-value.tsx:
--------------------------------------------------------------------------------
1 | import { ActionIcon, Tooltip } from '@mantine/core';
2 | import { IconInfoCircle } from '@tabler/icons-react';
3 |
4 | export const TooltipValue = ({ value }: { value: string }) => {
5 | if (value === null || value === '') {
6 | return null;
7 | }
8 | return (
9 |
10 |
11 |
12 |
13 |
14 | );
15 | };
16 |
--------------------------------------------------------------------------------
/.github/renovate.json:
--------------------------------------------------------------------------------
1 | {
2 | "packageRules": [
3 | {
4 | "matchPackagePatterns": ["^@tiptap/"],
5 | "groupName": "tiptap packages"
6 | },
7 | {
8 | "matchPackagePatterns": ["^@mantine/"],
9 | "groupName": "mantine packages"
10 | },
11 | {
12 | "matchPackagePatterns": ["^@nrwl/"],
13 | "groupName": "Nrwl packages"
14 | },
15 | {
16 | "matchPackagePatterns": ["^prosemirror"],
17 | "enabled": false
18 | },
19 | {
20 | "matchPackagePatterns": ["^@types/"],
21 | "automerge": true
22 | }
23 | ]
24 | }
25 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/button/translation.ts:
--------------------------------------------------------------------------------
1 | import { TranslationPatch } from '~/types/plugin';
2 |
3 | const en = {
4 | button: {
5 | viz_name: 'Button',
6 | click: {
7 | label: 'Click this button',
8 | },
9 | },
10 | };
11 |
12 | const zh = {
13 | button: {
14 | viz_name: '按钮',
15 | click: {
16 | label: '点击此按钮',
17 | },
18 | },
19 | };
20 |
21 | export const translation: TranslationPatch = [
22 | {
23 | lang: 'en',
24 | resources: en,
25 | },
26 | {
27 | lang: 'zh',
28 | resources: zh,
29 | },
30 | ];
31 |
--------------------------------------------------------------------------------
/dashboard/src/components/view/layout/index.css:
--------------------------------------------------------------------------------
1 | .dashboard-layout {
2 | margin: 5px;
3 | }
4 | .react-grid-item {
5 | padding: 0;
6 | }
7 | .react-grid-item.react-grid-placeholder {
8 | background: black !important;
9 | opacity: 0.3 !important;
10 | }
11 | .panel-grid-item {
12 | padding: 5px;
13 | min-height: 38px;
14 | }
15 | .remove-panel {
16 | position: absolute;
17 | right: 2px;
18 | top: 0;
19 | cursor: pointer;
20 | }
21 | .code-textarea textarea {
22 | font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, Liberation Mono, Courier New, monospace;
23 | }
24 |
--------------------------------------------------------------------------------
/api/src/models/base.ts:
--------------------------------------------------------------------------------
1 | import { Column, PrimaryGeneratedColumn } from 'typeorm';
2 |
3 | export class BaseModel {
4 | @PrimaryGeneratedColumn('uuid', {
5 | name: 'id',
6 | comment: '实体id',
7 | })
8 | id: string;
9 |
10 | @Column('timestamp with time zone', {
11 | nullable: false,
12 | default: () => 'CURRENT_TIMESTAMP',
13 | name: 'create_time',
14 | })
15 | create_time: Date;
16 |
17 | @Column('timestamp with time zone', {
18 | nullable: false,
19 | default: () => 'CURRENT_TIMESTAMP',
20 | name: 'update_time',
21 | })
22 | update_time: Date;
23 | }
24 |
--------------------------------------------------------------------------------
/api/tests/integration/jest.util.ts:
--------------------------------------------------------------------------------
1 | import { dashboardDataSource } from '~/data_sources/dashboard';
2 |
3 | export function connectionHook(): void {
4 | beforeAll(async () => {
5 | dashboardDataSource.setOptions({ url: process.env.INTEGRATION_TEST_PG_URL! });
6 | await dashboardDataSource.initialize();
7 | });
8 | afterAll(async () => {
9 | await dashboardDataSource.destroy();
10 | });
11 | }
12 |
13 | function timeout(ms: number) {
14 | return new Promise((resolve) => setTimeout(resolve, ms));
15 | }
16 | export async function sleep(ms: number) {
17 | await timeout(ms);
18 | }
19 |
--------------------------------------------------------------------------------
/api/src/middleware/localization.ts:
--------------------------------------------------------------------------------
1 | import * as express from 'express';
2 | import { ConfigService } from '../services/config.service';
3 | import { DEFAULT_LANGUAGE } from '../utils/constants';
4 |
5 | export default async function localization(req: express.Request, res: express.Response, next: express.NextFunction) {
6 | if (req.headers['accept-language'] === undefined && req.body.auth) {
7 | const configService = new ConfigService();
8 | const langConfig = await configService.get('lang', req.body.auth);
9 | req.locale = langConfig.value ?? DEFAULT_LANGUAGE;
10 | }
11 | next();
12 | }
13 |
--------------------------------------------------------------------------------
/api/src/middleware/permission.ts:
--------------------------------------------------------------------------------
1 | import * as express from 'express';
2 | import { Account } from '../api_models/account';
3 | import { ApiKey } from '../api_models/api';
4 | import { CHECK_PERMISSION, RoleService } from '../services/role.service';
5 |
6 | export default function permission(requiredPermission: CHECK_PERMISSION) {
7 | return (req: express.Request, res: express.Response, next: express.NextFunction) => {
8 | const auth: Account | ApiKey | undefined = req.body.auth;
9 | RoleService.checkPermission(requiredPermission, req.locale, auth?.permissions);
10 | next();
11 | };
12 | }
13 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/color-manager/color-manager.ts:
--------------------------------------------------------------------------------
1 | import { IColorInterpolation, IColorPaletteItem, ISingleColor } from '~/types/plugin';
2 |
3 | export interface IColorManager {
4 | getStaticColors(): ISingleColor[];
5 | getColorInterpolations(): IColorInterpolation[];
6 |
7 | register(paletteItem: T): void;
8 |
9 | decodeStaticColor(key: string): ISingleColor | undefined;
10 |
11 | encodeColor(color: IColorPaletteItem): string;
12 | decodeInterpolation(key: string): IColorInterpolation | undefined;
13 |
14 | // todo: color interpolation
15 | }
16 |
--------------------------------------------------------------------------------
/dashboard/src/model/render-model/dashboard/content/sql-snippets/utils.ts:
--------------------------------------------------------------------------------
1 | import { TPayloadForSQLSnippet } from '~/model';
2 | import { AnyObject } from '~/types';
3 | import { formatSQL } from '~/utils';
4 |
5 | export function formatSQLSnippet(list: AnyObject[], idKey: string, valueKey: string, params: TPayloadForSQLSnippet) {
6 | return list.reduce((ret, curr) => {
7 | try {
8 | ret[curr[idKey]] = formatSQL(curr[valueKey], params);
9 | } catch (error) {
10 | ret[curr[idKey]] = (error as any).message;
11 | }
12 | return ret;
13 | }, {} as Record);
14 | }
15 |
--------------------------------------------------------------------------------
/settings-form/src/i18n/i18n.ts:
--------------------------------------------------------------------------------
1 | import { createInstance } from 'i18next';
2 | import { initReactI18next } from 'react-i18next';
3 | import LanguageDetector from 'i18next-browser-languagedetector';
4 | import 'intl-pluralrules';
5 | import { en } from './en';
6 | import { zh } from './zh';
7 |
8 | const i18n = createInstance({
9 | debug: false,
10 | fallbackLng: 'en',
11 | interpolation: {
12 | escapeValue: false,
13 | },
14 | resources: {
15 | en,
16 | zh,
17 | },
18 | })
19 | .use(LanguageDetector)
20 | .use(initReactI18next);
21 |
22 | i18n.init();
23 | export default i18n;
24 |
--------------------------------------------------------------------------------
/api/jest-i.config.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line @typescript-eslint/no-var-requires
2 | const defaultConfig = require('./jest.config');
3 |
4 | module.exports = {
5 | ...defaultConfig,
6 | coverageDirectory: './coverage-i/',
7 | globalSetup: '/tests/integration/jest.setup.ts',
8 | testRegex: '(/tests/integration/.*(test|spec|integration))\\.(jsx?|tsx?)$',
9 | roots: ['/tests/integration/'],
10 | testSequencer: './test.sequencer.js',
11 | maxWorkers: 1,
12 | globals: {
13 | 'ts-jest': {
14 | tsconfig: 'tests/integration/tsconfig.json',
15 | },
16 | },
17 | };
18 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/stats/translation.ts:
--------------------------------------------------------------------------------
1 | import { TranslationPatch } from '~/types/plugin';
2 |
3 | const en = {
4 | stats: {
5 | viz_name: 'Stats',
6 | click_stats: {
7 | trigger: 'Click stats text',
8 | },
9 | },
10 | };
11 |
12 | const zh = {
13 | stats: {
14 | viz_name: '数据指标',
15 | click_stats: {
16 | trigger: '点击文字',
17 | },
18 | },
19 | };
20 |
21 | export const translation: TranslationPatch = [
22 | {
23 | lang: 'en',
24 | resources: en,
25 | },
26 | {
27 | lang: 'zh',
28 | resources: zh,
29 | },
30 | ];
31 |
--------------------------------------------------------------------------------
/dashboard/src/dashboard-editor/model/datasources/datasource.ts:
--------------------------------------------------------------------------------
1 | import { Instance, types } from 'mobx-state-tree';
2 | import { DataSourceMetaModel } from '~/model/meta-model/datasources';
3 | import { DBInfoModel } from './db-info';
4 | import { MMInfoModel } from './mm-info';
5 |
6 | export const DataSourceModel = types.compose(
7 | 'DataSourceModel',
8 | DataSourceMetaModel,
9 | types.model({
10 | dbInfo: types.optional(DBInfoModel, {}),
11 | mericoMetricInfo: types.optional(MMInfoModel, {}),
12 | }),
13 | );
14 |
15 | export type DataSourceModelInstance = Instance;
16 |
--------------------------------------------------------------------------------
/settings-form/src/components/submit-form-button.tsx:
--------------------------------------------------------------------------------
1 | import { Button, MantineSize } from '@mantine/core';
2 | import { IconDeviceFloppy } from '@tabler/icons-react';
3 | import { useTranslation } from 'react-i18next';
4 |
5 | type Props = {
6 | size: MantineSize;
7 | disabled?: boolean;
8 | };
9 | export function SubmitFormButton({ size, disabled }: Props) {
10 | const { t } = useTranslation();
11 | return (
12 | } size={size} disabled={disabled}>
13 | {t('common.actions.submit')}
14 |
15 | );
16 | }
17 |
--------------------------------------------------------------------------------
/Dockerfile-api:
--------------------------------------------------------------------------------
1 | FROM docker.io/node:20 as installer
2 |
3 | ENV YARN_NPM_REGISTRY_SERVER=https://registry.npmmirror.com
4 |
5 | COPY api /code/api
6 |
7 | # Javascript
8 |
9 | WORKDIR /code/api/_build
10 |
11 | ENV YARN_VERSION 3.6.1
12 | ENV YARN_IGNORE_NODE 1
13 |
14 | RUN yarn set version $YARN_VERSION
15 | RUN yarn config set nodeLinker node-modules
16 | RUN yarn install
17 |
18 | FROM node:20
19 | # fix trivy issues
20 | RUN apt update && apt upgrade -y
21 |
22 | COPY --from=installer /code/api/_build /code/api/_build
23 |
24 | WORKDIR /code/api/_build
25 | RUN yarn config set nodeLinker node-modules
26 |
--------------------------------------------------------------------------------
/api/jest.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | transform: {
3 | '^.+\\.(j|t)sx?$': ['ts-jest'],
4 | },
5 | testTimeout: 15000,
6 | moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
7 | moduleDirectories: ['node_modules'],
8 | collectCoverageFrom: ['./src/**/*.ts'],
9 | coverageReporters: ['text', 'text-summary', 'lcov', 'json'],
10 | clearMocks: true,
11 | bail: 1,
12 | moduleNameMapper: {
13 | '^~/(.*)$': '/src/$1',
14 | },
15 | roots: ['/tests/'],
16 | cacheDirectory: '/.jest_cache',
17 | globalTeardown: './test-teardown-globals.js',
18 | };
19 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/message-channels.ts:
--------------------------------------------------------------------------------
1 | import EventEmitter2 from 'eventemitter2';
2 | import { IMessageChannels } from '~/types/plugin';
3 |
4 | export class MessageChannels implements IMessageChannels {
5 | private channels = new Map();
6 | globalChannel = new EventEmitter2();
7 |
8 | getChannel(name: string): EventEmitter2 {
9 | const result = this.channels.get(name);
10 | if (result) {
11 | return result;
12 | }
13 | const channel = new EventEmitter2();
14 | this.channels.set(name, channel);
15 | return channel;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/dashboard/src/test/test-utils.ts:
--------------------------------------------------------------------------------
1 | import { cleanup, render } from '@testing-library/react';
2 | import React from 'react';
3 | import { afterEach } from 'vitest';
4 |
5 | afterEach(() => {
6 | cleanup();
7 | });
8 |
9 | const customRender = (ui: React.ReactElement, options = {}) =>
10 | render(ui, {
11 | // wrap provider(s) here if needed
12 | wrapper: ({ children }) => children,
13 | ...options,
14 | });
15 |
16 | export * from '@testing-library/react';
17 | export { default as userEvent } from '@testing-library/user-event';
18 | // override render export
19 | export { customRender as render };
20 |
--------------------------------------------------------------------------------
/website/src/api-caller/custom-function.ts:
--------------------------------------------------------------------------------
1 | import { TCustomFunctionDefinition, TCustomFunctionDto } from './custom-function.types';
2 | import { post } from './request';
3 |
4 | export const custom_function = {
5 | get: (id: string, signal?: AbortSignal) => async (): Promise => {
6 | try {
7 | const res: TCustomFunctionDto = await post(signal)('/custom_function/get', { id });
8 | const ret = new Function(`return ${res.definition}`)() as TCustomFunctionDefinition;
9 | return ret;
10 | } catch (error) {
11 | return null;
12 | }
13 | },
14 | };
15 |
--------------------------------------------------------------------------------
/website/src/api-caller/dashboard-content-changelog.types.ts:
--------------------------------------------------------------------------------
1 | import { PaginationResponse } from './types';
2 |
3 | export type DashboardContentChangelogDBType = {
4 | id: string;
5 | diff: string;
6 | create_time: string;
7 | dashboard_id: string;
8 | };
9 |
10 | export type ListDashboardContentChangelogReqType = {
11 | filter: {
12 | dashboard_content_id: { value: string; isFuzzy: false };
13 | };
14 | pagination: {
15 | page: number;
16 | pagesize: number;
17 | };
18 | };
19 |
20 | export type ListDashboardContentChangelogRespType = PaginationResponse;
21 |
--------------------------------------------------------------------------------
/dashboard/src/dashboard-editor/ui/header/index.tsx:
--------------------------------------------------------------------------------
1 | import { observer } from 'mobx-react-lite';
2 | import { IDashbaordEditorHeaderMain, MainHeader } from './main-header';
3 | import { SubHeader } from './sub-header';
4 |
5 |
6 | interface IDashboardEditorHeader extends IDashbaordEditorHeaderMain {
7 | [key: string]: any;
8 | }
9 |
10 | export const DashboardEditorHeader = observer((props: IDashboardEditorHeader) => {
11 | return (
12 | <>
13 |
14 |
15 | >
16 | );
17 | });
18 |
19 | export type { OnExitParams, OnExitCallback } from './main-header';
20 |
--------------------------------------------------------------------------------
/api/src/dashboard_migration/handlers/5.9.2.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Changes: add variables to panel config
3 | * @param schema
4 | * @returns new schema
5 | */
6 | export function main({ views, ...rest }: Record) {
7 | return {
8 | views: views.map((view: Record) => {
9 | return {
10 | panels: view.panels.map((panel: Record) => {
11 | return {
12 | variables: panel.variables || [],
13 | ...panel,
14 | };
15 | }),
16 | ...view,
17 | };
18 | }),
19 | ...rest,
20 | version: '5.9.2',
21 | };
22 | }
23 |
--------------------------------------------------------------------------------
/dashboard/src/components/filter/error-message-or-not-found.tsx:
--------------------------------------------------------------------------------
1 | import { Text } from '@mantine/core';
2 | import { useTranslation } from 'react-i18next';
3 |
4 | interface IProps {
5 | errorMessage?: string;
6 | }
7 |
8 | export const ErrorMessageOrNotFound = ({ errorMessage }: IProps) => {
9 | const { t } = useTranslation();
10 | if (errorMessage) {
11 | return (
12 |
13 | {errorMessage}
14 |
15 | );
16 | }
17 | return (
18 |
19 | {t('filter.widget.common.selector_option_empty')}
20 |
21 | );
22 | };
23 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/merico-heatmap/render/option/series.ts:
--------------------------------------------------------------------------------
1 | import { TMericoHeatmapConf } from '../../type';
2 |
3 | export function getSeries(conf: TMericoHeatmapConf, seriesData: any[]) {
4 | const { heat_block } = conf;
5 |
6 | return {
7 | type: 'heatmap',
8 | name: heat_block.name,
9 | xAxisId: 'main-x-axis',
10 | yAxisIndex: 0,
11 | datasetIndex: 0,
12 | itemStyle: {
13 | borderWidth: 0,
14 | },
15 | data: seriesData,
16 | label: heat_block.label,
17 | labelLayout: {
18 | hideOverlap: true,
19 | },
20 | z: 2,
21 | };
22 | }
23 |
--------------------------------------------------------------------------------
/website/src/pages/dashboard-editor-page/more-dashboard-info/dashboard-header-menu-items.tsx:
--------------------------------------------------------------------------------
1 | import { observer } from 'mobx-react-lite';
2 | import { TModalStates } from './types';
3 | import { DashboardChangelogModalTrigger } from './dashboard-changlog-modal/changelog-modal-trigger';
4 | import { Menu } from '@mantine/core';
5 |
6 | interface IProps {
7 | states: TModalStates;
8 | }
9 |
10 | export const DashboardHeaderMenuItems = observer(({ states }: IProps) => {
11 | return (
12 | <>
13 |
14 |
15 | >
16 | );
17 | });
18 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/boxplot-chart/editors/tooltip/index.tsx:
--------------------------------------------------------------------------------
1 | import { Stack } from '@mantine/core';
2 | import { Control, UseFormWatch } from 'react-hook-form';
3 | import { IBoxplotChartConf } from '../../type';
4 | import { TooltipMetricsField } from './metrics';
5 |
6 | interface ITooltipField {
7 | control: Control;
8 | watch: UseFormWatch;
9 | }
10 | export function TooltipField({ control, watch }: ITooltipField) {
11 | return (
12 |
13 |
14 |
15 | );
16 | }
17 |
--------------------------------------------------------------------------------
/dashboard/src/interactions/hooks/use-watch-triggers.ts:
--------------------------------------------------------------------------------
1 | import { useEffect, useState } from 'react';
2 | import { ITriggerSnapshot, IVizTriggerManager } from '~/types/plugin';
3 |
4 | export const useTriggerSnapshotList = (triggerManager: IVizTriggerManager, triggerSchemaId: string) => {
5 | const [state, setState] = useState[]>([]);
6 | useEffect(() => {
7 | return triggerManager.watchTriggerSnapshotList((list) =>
8 | setState(list.filter((it) => it.schemaRef === triggerSchemaId) as unknown as ITriggerSnapshot[]),
9 | );
10 | }, []);
11 |
12 | return state;
13 | };
14 |
--------------------------------------------------------------------------------
/api/project.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "api",
3 | "$schema": "../node_modules/nx/schemas/project-schema.json",
4 | "targets": {
5 | "build": {
6 | "executor": "nx:run-commands",
7 | "inputs": ["{projectRoot}/**/*", "!{projectRoot}/_build/**/*"],
8 | "outputs": ["{projectRoot}/_build"],
9 | "dependsOn": ["^build"],
10 | "options": {
11 | "commands": ["gulp build"],
12 | "cwd": "api"
13 | }
14 | },
15 | "dev": {
16 | "executor": "nx:run-script",
17 | "options": {
18 | "script": "dev"
19 | },
20 | "dependsOn": ["^dev"]
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/api/src/models/job.ts:
--------------------------------------------------------------------------------
1 | import { Entity, Column } from 'typeorm';
2 | import { BaseModel } from './base';
3 |
4 | @Entity()
5 | export default class Job extends BaseModel {
6 | @Column('character varying', {
7 | nullable: false,
8 | primary: false,
9 | name: 'type',
10 | })
11 | type: string;
12 |
13 | @Column('character varying', {
14 | nullable: false,
15 | primary: false,
16 | name: 'status',
17 | })
18 | status: string;
19 |
20 | @Column('jsonb', { name: 'params' })
21 | params: Record;
22 |
23 | @Column('jsonb', { name: 'result' })
24 | result: Record;
25 | }
26 |
--------------------------------------------------------------------------------
/dashboard/src/components/filter/filter-date-range/widget/hints.tsx:
--------------------------------------------------------------------------------
1 | import { Badge, Divider, Group } from '@mantine/core';
2 | import { useTranslation } from 'react-i18next';
3 |
4 | export const Hints = ({ max_days }: { max_days: number }) => {
5 | const { t } = useTranslation();
6 | if (!max_days) {
7 | return null;
8 | }
9 | return (
10 | <>
11 |
12 |
13 | {t('filter.widget.date_range.x_max_days', { max_days })}
14 |
15 |
16 |
17 | >
18 | );
19 | };
20 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/cartesian/editors/tooltip/index.tsx:
--------------------------------------------------------------------------------
1 | import { Stack } from '@mantine/core';
2 | import { Control, UseFormWatch } from 'react-hook-form';
3 | import { ICartesianChartConf } from '../../type';
4 | import { TooltipMetricsField } from './metrics';
5 |
6 | interface ITooltipField {
7 | control: Control;
8 | watch: UseFormWatch;
9 | }
10 | export function TooltipField({ control, watch }: ITooltipField) {
11 | return (
12 |
13 |
14 |
15 | );
16 | }
17 |
--------------------------------------------------------------------------------
/dashboard/src/contexts/additional-panel-menu-items.ts:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { PanelMenuItem } from '~/types';
3 |
4 | export interface IAdditionalPanelMenuItemsContext {
5 | items: PanelMenuItem[];
6 | }
7 |
8 | const initialContext = {
9 | items: [],
10 | };
11 |
12 | export const AdditionalPanelMenuItemsContext = React.createContext(initialContext);
13 | export const AdditionalPanelMenuItemsContextProvider = AdditionalPanelMenuItemsContext.Provider;
14 |
15 | export function useAdditionalPanelMenuItems() {
16 | return React.useContext(AdditionalPanelMenuItemsContext);
17 | }
18 |
--------------------------------------------------------------------------------
/api/jest-e2e.config.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line @typescript-eslint/no-var-requires
2 | const defaultConfig = require('./jest.config');
3 |
4 | module.exports = {
5 | ...defaultConfig,
6 | coverageDirectory: './coverage-e2e/',
7 | globalSetup: '/tests/e2e/jest.setup.ts',
8 | setupFilesAfterEnv: ['/tests/e2e/jest.mock.ts'],
9 | testRegex: '(/tests/e2e/.*(test|spec|e2e))\\.(jsx?|tsx?)$',
10 | roots: ['/tests/e2e/'],
11 | testSequencer: './test.sequencer.js',
12 | testTimeout: 60000,
13 | globals: {
14 | 'ts-jest': {
15 | tsconfig: 'tests/e2e/tsconfig.json',
16 | },
17 | },
18 | };
19 |
--------------------------------------------------------------------------------
/dashboard/src/components/panel/panel-render/dropdown-menu-items/refresh.tsx:
--------------------------------------------------------------------------------
1 | import { Menu } from '@mantine/core';
2 | import { IconRefresh } from '@tabler/icons-react';
3 | import { observer } from 'mobx-react-lite';
4 | import { useTranslation } from 'react-i18next';
5 | import { useRenderPanelContext } from '~/contexts';
6 |
7 | export const Refresh = observer(() => {
8 | const { t } = useTranslation();
9 | const { panel } = useRenderPanelContext();
10 | return (
11 | }>
12 | {t('common.actions.refresh')}
13 |
14 | );
15 | });
16 |
--------------------------------------------------------------------------------
/dashboard/src/interactions/interactions-viewer/data/types.ts:
--------------------------------------------------------------------------------
1 | import { CSSProperties } from 'react';
2 | import { Node } from 'reactflow';
3 | import { EViewComponentType } from '~/model';
4 |
5 | export type TFlowNode_View = Node & {
6 | _node_type: 'view-root';
7 | _view_type: EViewComponentType;
8 | _view_level: number;
9 | _sub_view_ids: string[];
10 | _tab_view_ids: string[]; // for tabs only
11 | style: CSSProperties;
12 | };
13 |
14 | export type TFlowNode_Default = Node & {
15 | _node_type: 'filter-root' | 'filter' | 'open-link-root' | 'panel';
16 | };
17 | export type TFlowNode = TFlowNode_View | TFlowNode_Default;
18 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/common-echarts-fields/line-area-style/types.ts:
--------------------------------------------------------------------------------
1 | export type EchartsLineAreaStyle = {
2 | enabled: boolean;
3 | color: string;
4 | origin: 'auto' | 'start' | 'end';
5 | shadowBlur: number;
6 | shadowColor: string;
7 | shadowOffsetX: number;
8 | shadowOffsetY: number;
9 | opacity: number;
10 | };
11 |
12 | export function getDefaultLineAreaStyle(): EchartsLineAreaStyle {
13 | return {
14 | enabled: false,
15 | color: '',
16 | origin: 'auto',
17 | shadowBlur: 0,
18 | shadowColor: '',
19 | shadowOffsetX: 0,
20 | shadowOffsetY: 0,
21 | opacity: 0.7,
22 | };
23 | }
24 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/heatmap/option/series.ts:
--------------------------------------------------------------------------------
1 | import { IHeatmapConf } from '../type';
2 |
3 | export function getSeries(conf: IHeatmapConf, seriesData: any[], borderWidth: number) {
4 | const { heat_block } = conf;
5 |
6 | return {
7 | type: 'heatmap',
8 | name: heat_block.name,
9 | xAxisId: 'main-x-axis',
10 | yAxisIndex: 0,
11 | datasetIndex: 0,
12 | itemStyle: {
13 | borderColor: 'white',
14 | borderWidth,
15 | },
16 | data: seriesData,
17 | label: heat_block.label,
18 | labelLayout: {
19 | hideOverlap: true,
20 | },
21 | z: 2,
22 | };
23 | }
24 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/text/translation.ts:
--------------------------------------------------------------------------------
1 | import { TranslationPatch } from '~/types/plugin';
2 |
3 | const en = {
4 | text: {
5 | viz_name: 'Text',
6 | content: {
7 | label: 'Text content',
8 | edit: 'Edit Content',
9 | },
10 | },
11 | };
12 |
13 | const zh = {
14 | text: {
15 | viz_name: '文本',
16 | content: {
17 | label: '文本内容',
18 | edit: '编辑文本内容',
19 | },
20 | },
21 | };
22 |
23 | export const translation: TranslationPatch = [
24 | {
25 | lang: 'en',
26 | resources: en,
27 | },
28 | {
29 | lang: 'zh',
30 | resources: zh,
31 | },
32 | ];
33 |
--------------------------------------------------------------------------------
/api/src/models/dashboard_content.ts:
--------------------------------------------------------------------------------
1 | import { Entity, Column } from 'typeorm';
2 | import { BaseModel } from './base';
3 | import { Content } from '../api_models/dashboard_content';
4 |
5 | @Entity()
6 | export default class DashboardContent extends BaseModel {
7 | @Column('uuid', {
8 | nullable: false,
9 | name: 'dashboard_id',
10 | comment: '报表ID',
11 | })
12 | dashboard_id: string;
13 |
14 | @Column('character varying', {
15 | nullable: false,
16 | name: 'name',
17 | })
18 | name: string;
19 |
20 | @Column('jsonb', {
21 | nullable: false,
22 | name: 'content',
23 | })
24 | content: Content;
25 | }
26 |
--------------------------------------------------------------------------------
/dashboard/src/interactions/interactions-viewer/node-with-interactions/types.ts:
--------------------------------------------------------------------------------
1 | import { ReactNode } from 'react';
2 |
3 | export type TInteraction =
4 | | {
5 | schemaRef: 'builtin:op:open-link';
6 | urlTemplate: string;
7 | shortURLTemplate: string;
8 | }
9 | | {
10 | schemaRef: 'builtin:op:set_filter_values';
11 | filters: { key: string; label: string }[];
12 | }
13 | | {
14 | schemaRef: 'builtin:op:clear_filter_values';
15 | filters: { key: string; label: string }[];
16 | };
17 |
18 | export type TInteractionLine = {
19 | key: string;
20 | icon: ReactNode;
21 | text: ReactNode;
22 | };
23 |
--------------------------------------------------------------------------------
/dashboard/src/model/meta-model/dashboard/content/filter/types.ts:
--------------------------------------------------------------------------------
1 | import { types } from 'mobx-state-tree';
2 |
3 | export enum DashboardFilterType {
4 | Select = 'select',
5 | MultiSelect = 'multi-select',
6 | TreeSelect = 'tree-select',
7 | TreeSingleSelect = 'tree-single-select',
8 | TextInput = 'text-input',
9 | Checkbox = 'checkbox',
10 | DateRange = 'date-range',
11 | MericoDateRange = 'merico-date-range',
12 | }
13 |
14 | export type DefaultValueMode = 'intersect' | 'reset';
15 | export const DefaultValueModeModelType = types.optional(
16 | types.enumeration(['intersect', 'reset']),
17 | 'intersect',
18 | );
19 |
--------------------------------------------------------------------------------
/dashboard/src/components/panel/panel-render/dropdown-menu-items/download-data.tsx:
--------------------------------------------------------------------------------
1 | import { Menu } from '@mantine/core';
2 | import { IconDownload } from '@tabler/icons-react';
3 | import { observer } from 'mobx-react-lite';
4 | import { useTranslation } from 'react-i18next';
5 | import { useRenderPanelContext } from '~/contexts';
6 |
7 | export const DownloadData = observer(() => {
8 | const { t } = useTranslation();
9 | const { panel } = useRenderPanelContext();
10 | return (
11 | }>
12 | {t('common.actions.download_data')}
13 |
14 | );
15 | });
16 |
--------------------------------------------------------------------------------
/dashboard/src/components/panel/panel-render/dropdown-menu-items/download-schema.tsx:
--------------------------------------------------------------------------------
1 | import { Menu } from '@mantine/core';
2 | import { IconCode } from '@tabler/icons-react';
3 | import { observer } from 'mobx-react-lite';
4 | import { useTranslation } from 'react-i18next';
5 | import { useRenderPanelContext } from '~/contexts';
6 |
7 | export const DownloadSchema = observer(() => {
8 | const { t } = useTranslation();
9 | const { panel } = useRenderPanelContext();
10 | return (
11 | }>
12 | {t('common.actions.download_schema')}
13 |
14 | );
15 | });
16 |
--------------------------------------------------------------------------------
/dashboard/src/dashboard-editor/ui/settings/content/edit-view/edit-view-form/config-fields/index.tsx:
--------------------------------------------------------------------------------
1 | import { observer } from 'mobx-react-lite';
2 | import { ViewMetaInstance } from '~/model';
3 | import { ViewDivisionConfigFields } from './config.division';
4 | import { ViewTabsConfigFields } from './config.tabs';
5 | import { ViewModalConfigFields } from './modal';
6 |
7 | export const ConfigFields = observer(({ view }: { view: ViewMetaInstance }) => {
8 | return (
9 | <>
10 |
11 |
12 |
13 | >
14 | );
15 | });
16 |
--------------------------------------------------------------------------------
/website/src/frames/dashboard-editor-frame/index.tsx:
--------------------------------------------------------------------------------
1 | import { Notifications } from '@mantine/notifications';
2 | import { Navigate, Outlet } from 'react-router-dom';
3 | import { DashboardStoreProvider } from '../app/models/dashboard-store-context';
4 | import { useAccountContext } from '../require-auth/account-context';
5 |
6 | export function DashboardEditorFrame() {
7 | const { canEdit } = useAccountContext();
8 | if (!canEdit) {
9 | return ;
10 | }
11 | return (
12 |
13 |
14 |
15 |
16 | );
17 | }
18 |
--------------------------------------------------------------------------------
/dashboard/src/utils/template/types.ts:
--------------------------------------------------------------------------------
1 | import { TNumberFormat } from '~/utils';
2 | import { AggregationType } from '../aggregation';
3 |
4 | export type ColorConfType =
5 | | {
6 | type: 'static';
7 | staticColor: string;
8 | }
9 | | {
10 | type: 'continuous';
11 | valueRange: number[];
12 | colorRange: string[];
13 | }
14 | | {
15 | type: 'piecewise'; // TODO
16 | };
17 |
18 | export interface ITemplateVariable {
19 | name: string;
20 | data_field: string;
21 | aggregation: AggregationType;
22 | formatter: TNumberFormat;
23 | color: ColorConfType;
24 | size: string;
25 | weight: string;
26 | }
27 |
--------------------------------------------------------------------------------
/website/src/api-caller/api-key.ts:
--------------------------------------------------------------------------------
1 | import { IAPIKey } from '@devtable/settings-form';
2 | import { post } from './request';
3 | import { PaginationResponse } from './types';
4 |
5 | export const api_key = {
6 | list: async (signal?: AbortSignal): Promise> => {
7 | const res = await post(signal)('/api/key/list', {
8 | filter: {
9 | search: '',
10 | },
11 | sort: [
12 | {
13 | field: 'name',
14 | order: 'ASC',
15 | },
16 | ],
17 | pagination: {
18 | page: 1,
19 | pagesize: 1000,
20 | },
21 | });
22 | return res;
23 | },
24 | };
25 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/test-utils.tsx:
--------------------------------------------------------------------------------
1 | import { VizComponent } from '~/types/plugin';
2 |
3 | export function createMockPlugin(id = 'foo', components: string[] = ['mockViz'], others: Partial = {}) {
4 | return {
5 | id: id,
6 | manifest: {
7 | color: [],
8 | viz: components.map(
9 | (name) =>
10 | ({
11 | name,
12 | configRender: () => Hello,
13 | viewRender: () => World,
14 | migrator: {} as $TSFixMe,
15 | ...others,
16 | } as VizComponent),
17 | ),
18 | },
19 | version: '1.1.1',
20 | };
21 | }
22 |
--------------------------------------------------------------------------------
/dashboard/src/dashboard-editor/ui/settings/navbar/nav-links.module.css:
--------------------------------------------------------------------------------
1 | .menu_target:global(.mantine-ActionIcon-root) {
2 | width: 40px;
3 | height: 100%;
4 | min-height: 40px;
5 | position: absolute;
6 | top: 0;
7 | right: 0;
8 | bottom: 0;
9 | border-radius: 0;
10 | }
11 |
12 | .query:global(.mantine-NavLink-root) {
13 | padding: 0;
14 | }
15 |
16 | .query :global(.mantine-NavLink-body) {
17 | padding: 9px 6px 9px 12px;
18 | }
19 | .query :global(.mantine-NavLink-label) {
20 | display: block;
21 | width: calc(100% - 40px);
22 | word-break: break-all;
23 | }
24 |
25 | .query :global(.mantine-NavLink-section) {
26 | margin-left: 0px;
27 | }
28 |
--------------------------------------------------------------------------------
/settings-form/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ESNext",
4 | "useDefineForClassFields": true,
5 | "lib": ["DOM", "DOM.Iterable", "ESNext"],
6 | "allowJs": false,
7 | "skipLibCheck": true,
8 | "esModuleInterop": false,
9 | "allowSyntheticDefaultImports": true,
10 | "strict": true,
11 | "forceConsistentCasingInFileNames": true,
12 | "module": "ESNext",
13 | "moduleResolution": "Node",
14 | "resolveJsonModule": true,
15 | "isolatedModules": true,
16 | "noEmit": true,
17 | "jsx": "react-jsx"
18 | },
19 | "include": ["src"],
20 | "references": [{ "path": "./tsconfig.node.json" }]
21 | }
22 |
--------------------------------------------------------------------------------
/api/src/data_sources/migrations/1675750180197-add-group-column-to-dashboard-table.ts:
--------------------------------------------------------------------------------
1 | import { MigrationInterface, QueryRunner } from 'typeorm';
2 |
3 | export class addGroupColumnToDashboardTable1675750180197 implements MigrationInterface {
4 | public async up(queryRunner: QueryRunner): Promise {
5 | await queryRunner.query(
6 | `ALTER TABLE dashboard
7 | ADD COLUMN "group" VARCHAR NOT NULL DEFAULT ''
8 | `,
9 | );
10 | }
11 |
12 | public async down(queryRunner: QueryRunner): Promise {
13 | await queryRunner.query(
14 | `ALTER TABLE dashboard
15 | DROP COLUMN "group"
16 | `,
17 | );
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/dashboard/src/components/panel/panel-editor/dropdown-menu-items/dropdown-menu-items.tsx:
--------------------------------------------------------------------------------
1 | import { observer } from 'mobx-react-lite';
2 |
3 | import { useRenderPanelContext } from '~/contexts/panel-context';
4 | import { ViewMetaInstance } from '~/model';
5 | import { useItems } from './use-items';
6 |
7 | type Props = {
8 | view: ViewMetaInstance;
9 | };
10 |
11 | export const PanelDropdownMenuItems = observer(({ view }: Props) => {
12 | const { getEchartsOptions, panel } = useRenderPanelContext();
13 | const items = useItems(view);
14 | return items.map((item) => item.render({ getEchartsOptions, inEditMode: true, panelID: panel.id, viewID: view.id }));
15 | });
16 |
--------------------------------------------------------------------------------
/dashboard/src/components/panel/panel-render/dropdown-menu-items/dropdown-menu-items.tsx:
--------------------------------------------------------------------------------
1 | import { observer } from 'mobx-react-lite';
2 |
3 | import { useRenderPanelContext } from '~/contexts/panel-context';
4 | import { ViewMetaInstance } from '~/model';
5 | import { useItems } from './use-items';
6 |
7 | type Props = {
8 | view: ViewMetaInstance;
9 | };
10 |
11 | export const PanelDropdownMenuItems = observer(({ view }: Props) => {
12 | const { getEchartsOptions, panel } = useRenderPanelContext();
13 | const items = useItems(view);
14 | return items.map((item) => item.render({ getEchartsOptions, inEditMode: false, panelID: panel.id, viewID: view.id }));
15 | });
16 |
--------------------------------------------------------------------------------
/api/src/dashboard_migration/handlers/11.0.0.ts:
--------------------------------------------------------------------------------
1 | function upgradeQueries(queries: Record[]) {
2 | return queries.map((p) => {
3 | const { dep_query_ids, ...rest } = p;
4 | return {
5 | ...rest,
6 | dep_query_ids: dep_query_ids ?? [],
7 | };
8 | });
9 | }
10 |
11 | /**
12 | * https://github.com/merico-dev/table/issues/1308
13 | */
14 | export function main({ definition, ...rest }: Record) {
15 | const finalQueries = upgradeQueries(definition.queries);
16 | return {
17 | ...rest,
18 | definition: {
19 | ...definition,
20 | queries: finalQueries,
21 | },
22 | version: '11.0.0',
23 | };
24 | }
25 |
--------------------------------------------------------------------------------
/api/src/dashboard_migration/handlers/4.14.1.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Changes: add default_value to filter.date_range
3 | * @param schema
4 | * @returns new schema
5 | */
6 | export function main({ filters, views, ...rest }: Record) {
7 | return {
8 | filters: filters.map((f) => {
9 | if (f.type !== 'date-range') {
10 | return f;
11 | }
12 | return {
13 | ...f,
14 | config: {
15 | ...f.config,
16 | default_value: Array.isArray(f.config.default_value) ? f.config.default_value : [null, null],
17 | },
18 | };
19 | }),
20 | views,
21 | ...rest,
22 | version: '4.14.1',
23 | };
24 | }
25 |
--------------------------------------------------------------------------------
/api/src/models/config.ts:
--------------------------------------------------------------------------------
1 | import { Entity, Column } from 'typeorm';
2 | import { BaseModel } from './base';
3 |
4 | @Entity()
5 | export default class Config extends BaseModel {
6 | @Column('character varying', {
7 | nullable: false,
8 | name: 'resource_type',
9 | })
10 | resource_type: string;
11 |
12 | @Column('character varying', {
13 | nullable: true,
14 | name: 'resource_id',
15 | })
16 | resource_id: string;
17 |
18 | @Column('character varying', {
19 | nullable: false,
20 | name: 'key',
21 | })
22 | key: string;
23 |
24 | @Column('text', {
25 | nullable: false,
26 | name: 'value',
27 | })
28 | value: string;
29 | }
30 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/common-echarts-fields/axis-label-overflow/types.ts:
--------------------------------------------------------------------------------
1 | export interface IEchartsOverflow {
2 | width: number;
3 | overflow: 'truncate' | 'break' | 'breakAll';
4 | ellipsis: '...';
5 | }
6 |
7 | export interface IAxisLabelOverflow {
8 | on_axis: IEchartsOverflow;
9 | in_tooltip: IEchartsOverflow;
10 | }
11 |
12 | export function getDefaultAxisLabelOverflow(): IAxisLabelOverflow {
13 | return {
14 | on_axis: {
15 | width: 80,
16 | overflow: 'truncate',
17 | ellipsis: '...',
18 | },
19 | in_tooltip: {
20 | width: 200,
21 | overflow: 'break',
22 | ellipsis: '...',
23 | },
24 | };
25 | }
26 |
--------------------------------------------------------------------------------
/dashboard/src/model/meta-model/dashboard/content/panel/style/index.ts:
--------------------------------------------------------------------------------
1 | import { types } from 'mobx-state-tree';
2 | import { PanelStyleBorderMeta, type IPanelStyleBorderMeta } from './border';
3 |
4 | export const PanelStyleMeta = types
5 | .model('PanelStyleMeta', {
6 | border: PanelStyleBorderMeta,
7 | })
8 | .views((self) => ({
9 | get json() {
10 | const { border } = self;
11 | return {
12 | border: border.json,
13 | };
14 | },
15 | }))
16 | .actions((self) => ({}));
17 |
18 | export interface IPanelStyleMeta {
19 | border: IPanelStyleBorderMeta;
20 | json: {
21 | border: IPanelStyleBorderMeta['json'];
22 | };
23 | }
24 |
--------------------------------------------------------------------------------
/website/src/frames/socket-client-frame/socket-context.ts:
--------------------------------------------------------------------------------
1 | import { Socket } from 'socket.io-client';
2 | import React from 'react';
3 |
4 | type SocketContextType = {
5 | socket: Socket | null;
6 | };
7 |
8 | type SocketContextOutType = {
9 | socket: Socket;
10 | };
11 |
12 | const SocketContext = React.createContext({
13 | socket: null,
14 | });
15 |
16 | export const SocketContextProvider = SocketContext.Provider;
17 |
18 | export function useSocketContext() {
19 | const c = React.useContext(SocketContext);
20 | if (!c.socket) {
21 | throw new Error('Please use SocketContextProvider');
22 | }
23 | return c as SocketContextOutType;
24 | }
25 |
--------------------------------------------------------------------------------
/api/src/models/dashboard_permission.ts:
--------------------------------------------------------------------------------
1 | import { Entity, Column } from 'typeorm';
2 | import { PermissionResource } from '../api_models/dashboard_permission';
3 | import { BaseModel } from './base';
4 |
5 | @Entity()
6 | export default class DashboardPermission extends BaseModel {
7 | @Column('uuid', {
8 | name: 'owner_id',
9 | nullable: true,
10 | })
11 | owner_id: string | null;
12 |
13 | @Column('character varying', {
14 | name: 'owner_type',
15 | nullable: true,
16 | })
17 | owner_type: 'ACCOUNT' | 'APIKEY' | null;
18 |
19 | @Column('jsonb', {
20 | name: 'access',
21 | nullable: false,
22 | })
23 | access: PermissionResource[];
24 | }
25 |
--------------------------------------------------------------------------------
/dashboard/src/model/meta-model/datasources/datasource.ts:
--------------------------------------------------------------------------------
1 | import { Instance, types } from 'mobx-state-tree';
2 | import { TDataSourceConfig } from '~/api-caller/types';
3 | import { DataSourceType } from '~/model';
4 |
5 | export const DataSourceMetaModel = types.model('DataSourceMetaModel', {
6 | id: types.string,
7 | type: types.enumeration('DataSourceType', [
8 | DataSourceType.HTTP,
9 | DataSourceType.MySQL,
10 | DataSourceType.Postgresql,
11 | DataSourceType.MericoMetricSystem,
12 | ]),
13 | key: types.string,
14 | config: types.frozen(),
15 | });
16 |
17 | export type DataSourceMetaModelInstance = Instance;
18 |
--------------------------------------------------------------------------------
/dashboard/src/contexts/dates-provider.tsx:
--------------------------------------------------------------------------------
1 | import { ReactNode, useMemo } from 'react';
2 | import { DatesProvider as MantineDatesProvider } from '@mantine/dates';
3 | import { useTranslation } from 'react-i18next';
4 |
5 | const lang2dayjsLocale = {
6 | en: 'en',
7 | zh: 'zh-cn',
8 | };
9 | export function DatesProvider({ children }: { children: ReactNode }) {
10 | const { i18n } = useTranslation();
11 | const locale = useMemo(() => {
12 | const lang = i18n.language as 'zh' | 'en';
13 | return lang2dayjsLocale[lang] ?? 'en';
14 | }, [i18n.language]);
15 |
16 | return {children};
17 | }
18 |
--------------------------------------------------------------------------------
/dashboard/src/styles/action-icon-group-style.ts:
--------------------------------------------------------------------------------
1 | export const ActionIconGroupStyle = {
2 | '> button': {
3 | '&:first-of-type': {
4 | borderTopRightRadius: 0,
5 | borderBottomRightRadius: 0,
6 | borderRightWidth: 0.5,
7 | },
8 | ':not(:first-of-type):not(:last-of-type)': {
9 | borderTopRightRadius: 0,
10 | borderBottomRightRadius: 0,
11 | borderTopLeftRadius: 0,
12 | borderBottomLeftRadius: 0,
13 | borderLeftWidth: 0.5,
14 | borderRightWidth: 0.5,
15 | },
16 | '&:last-of-type': {
17 | borderTopLeftRadius: 0,
18 | borderBottomLeftRadius: 0,
19 | borderLeftWidth: 0.5,
20 | },
21 | },
22 | };
23 |
--------------------------------------------------------------------------------
/api/base.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es2018",
4 | "allowSyntheticDefaultImports": true,
5 | "module": "commonjs",
6 | "esModuleInterop": true,
7 | "types": ["reflect-metadata", "swagger-express-ts", "node"],
8 | "downlevelIteration": true,
9 | "moduleResolution": "node",
10 | "experimentalDecorators": true,
11 | "emitDecoratorMetadata": true,
12 | "allowJs": true,
13 | "checkJs": false,
14 | "skipLibCheck": true,
15 | "noEmit": true,
16 | "resolveJsonModule": true,
17 | "strictNullChecks": true
18 | },
19 | "rules": {
20 | "no-unused-expression": true,
21 | "no-floating-promises": true
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/dashboard/src/components/plugins/viz-components/text/type.ts:
--------------------------------------------------------------------------------
1 | import { HorizontalAlign } from '../../editor-components';
2 |
3 | export const DEFAULT_TEXT_FUNC_CONTENT = [
4 | 'function text({ data, variables, filters, context}) {',
5 | ' // your code goes here',
6 | ' return "text"',
7 | '}',
8 | ].join('\n');
9 |
10 | export interface IVizTextConf {
11 | func_content: string;
12 | horizontal_align: HorizontalAlign;
13 | font_size: string;
14 | font_weight: string;
15 | }
16 |
17 | export const DEFAULT_CONFIG: IVizTextConf = {
18 | func_content: DEFAULT_TEXT_FUNC_CONTENT,
19 | horizontal_align: 'left',
20 | font_size: '14px',
21 | font_weight: 'normal',
22 | };
23 |
--------------------------------------------------------------------------------
/settings-form/src/utils/load-monaco-editor.ts:
--------------------------------------------------------------------------------
1 | import { loader } from '@monaco-editor/react';
2 | import { useEffect } from 'react';
3 |
4 | const cleanURL = (str: string) => {
5 | return str.replace(/([^:])(\/\/+)/g, '$1/');
6 | };
7 |
8 | export function useLoadMonacoEditor(monacoPath: string) {
9 | useEffect(() => {
10 | const loaded = loader.__getMonacoInstance();
11 | if (loaded) {
12 | return;
13 | }
14 |
15 | console.log('loading monaco for @devtable/settings-form');
16 | const path = cleanURL(monacoPath);
17 | loader.config({ paths: { vs: path } });
18 | loader.init().then((monaco) => console.log('monaco instance:', monaco));
19 | }, []);
20 | }
21 |
--------------------------------------------------------------------------------
/website/cypress.config.ts:
--------------------------------------------------------------------------------
1 | import { resolve } from 'path';
2 | import dts from 'vite-plugin-dts';
3 | import tsconfigPaths from 'vite-tsconfig-paths';
4 | import { defineConfig } from 'cypress';
5 |
6 | export default defineConfig({
7 | component: {
8 | devServer: {
9 | framework: 'react',
10 | bundler: 'vite',
11 | viteConfig: {
12 | plugins: [
13 | tsconfigPaths({
14 | projects: ['./tsconfig.cypress.json'],
15 | }),
16 | dts({
17 | entryRoot: resolve(__dirname, 'src'),
18 | insertTypesEntry: true,
19 | }),
20 | ],
21 | },
22 | },
23 | },
24 | video: false,
25 | });
26 |
--------------------------------------------------------------------------------
/api/src/dashboard_migration/handlers/9.11.0.ts:
--------------------------------------------------------------------------------
1 | function upgradeQueries(queries: Record[]) {
2 | return queries.map((q) => {
3 | const { react_to = [], ...rest } = q;
4 | return {
5 | ...rest,
6 | react_to,
7 | };
8 | });
9 | }
10 |
11 | /**
12 | * https://github.com/merico-dev/table/issues/980
13 | * @param schema
14 | * @returns new schema
15 | */
16 | export function main({ definition, ...rest }: Record) {
17 | const finalQueries = upgradeQueries(definition.queries);
18 | return {
19 | ...rest,
20 | definition: {
21 | ...definition,
22 | queries: finalQueries,
23 | },
24 | version: '9.11.0',
25 | };
26 | }
27 |
--------------------------------------------------------------------------------