dashboard

basic-dashboard

Kết hợp resource chart và insight bằng dashboard builder để tạo dashboard cơ bản

Thẻ: basic

Loading...
import { createVBI, VBIChartBuilder, VBIInsightBuilder, VBIDashboardBuilder } from '@visactor/vbi'
import { JsonRender } from '@components'
import { useEffect, useState } from 'react'

export default () => {
  const [result, setResult] = useState<any>(null)
  const [error, setError] = useState<string | null>(null)

  useEffect(() => {
    try {
      const LocalVBI = createVBI()
      const resources = {
        charts: {
          salesChart: LocalVBI.chart.create({
              "connectorId": "demoSupermarket",
              "chartType": "bar",
              "dimensions": [
                {
                  "field": "province",
                  "alias": "Tỉnh"
                }
              ],
              "measures": [
                {
                  "field": "sales",
                  "alias": "Doanh số",
                  "encoding": "xAxis",
                  "aggregate": {
                    "func": "sum"
                  }
                }
              ],
              "whereFilter": {
                "id": "root",
                "op": "and",
                "conditions": []
              },
              "havingFilter": {
                "id": "root",
                "op": "and",
                "conditions": []
              },
              "theme": "light",
              "locale": "vi-VN",
              "version": 1
            }),
        },
        insights: {
          salesInsight: LocalVBI.insight.create({
              "content": "Doanh số khu vực Hoa Đông đang dẫn đầu. Nên tiếp tục theo dõi các khách hàng trọng điểm.",
              "version": 0
            }),
        },
      }
      const builder = LocalVBI.dashboard.create({
          "widgets": [],
          "breakpoints": {
            "xxl": 1600,
            "xl": 1200,
            "lg": 996,
            "md": 768,
            "sm": 480,
            "xs": 0
          },
          "layout": {
            "xxl": [],
            "xl": [],
            "lg": [],
            "md": [],
            "sm": [],
            "xs": []
          },
          "meta": {
            "title": "Dashboard doanh số",
            "theme": "light"
          },
          "version": 0
        })
      const applyBuilder = (builder: VBIDashboardBuilder, resources: any) => {
  builder.chart.add(chart => {
    chart
      .setChartId(resources.charts.salesChart)
      .setTitle('Xu hướng doanh số')
      .setDescription('Tổng hợp doanh số theo tỉnh')
      .setLayouts({
        lg: { x: 0, y: 0, w: 8, h: 6 },
        md: { x: 0, y: 0, w: 6, h: 5 }
      })
  })

  builder.insight.add(insight => {
    insight
      .setInsightId(resources.insights.salesInsight)
      .setTitle('Insight chính')
      .setLayouts({
        lg: { x: 8, y: 0, w: 4, h: 6 },
        md: { x: 0, y: 5, w: 6, h: 3 }
      })
  })
}
      applyBuilder(builder, resources)
      setResult(builder.build())
    } catch (err) {
      setError(err instanceof Error ? err.message : String(err))
    }
  }, [])

  if (error) return <JsonRender value={{ error }} />
  if (!result) return <div>Loading...</div>

  return <JsonRender value={result} />
}

responsive-dashboard-layout

Kết hợp nhiều resource chart và insight, rồi thiết lập layout dashboard responsive cho các breakpoint khác nhau

Thẻ: layout responsive resources

Loading...
import { createVBI, VBIChartBuilder, VBIInsightBuilder, VBIDashboardBuilder } from '@visactor/vbi'
import { JsonRender } from '@components'
import { useEffect, useState } from 'react'

export default () => {
  const [result, setResult] = useState<any>(null)
  const [error, setError] = useState<string | null>(null)

  useEffect(() => {
    try {
      const LocalVBI = createVBI()
      const resources = {
        charts: {
          salesChart: LocalVBI.chart.create({
              "connectorId": "demoSupermarket",
              "chartType": "bar",
              "dimensions": [
                {
                  "field": "province",
                  "alias": "Tỉnh"
                }
              ],
              "measures": [
                {
                  "field": "sales",
                  "alias": "Doanh số",
                  "encoding": "xAxis",
                  "aggregate": {
                    "func": "sum"
                  }
                }
              ],
              "whereFilter": {
                "id": "root",
                "op": "and",
                "conditions": []
              },
              "havingFilter": {
                "id": "root",
                "op": "and",
                "conditions": []
              },
              "theme": "light",
              "locale": "vi-VN",
              "version": 1
            }),
          profitChart: LocalVBI.chart.create({
              "connectorId": "demoSupermarket",
              "chartType": "line",
              "dimensions": [
                {
                  "field": "order_date",
                  "alias": "Tháng đặt hàng",
                  "aggregate": {
                    "func": "toMonth"
                  }
                }
              ],
              "measures": [
                {
                  "field": "profit",
                  "alias": "Lợi nhuận",
                  "encoding": "yAxis",
                  "aggregate": {
                    "func": "sum"
                  }
                }
              ],
              "whereFilter": {
                "id": "root",
                "op": "and",
                "conditions": []
              },
              "havingFilter": {
                "id": "root",
                "op": "and",
                "conditions": []
              },
              "theme": "light",
              "locale": "vi-VN",
              "version": 1
            }),
        },
        insights: {
          opsInsight: LocalVBI.insight.create({
              "content": "Cần quan sát kết hợp xu hướng doanh số và lợi nhuận. Các tháng có lợi nhuận thấp nên được phân tích sâu hơn theo cấu trúc danh mục.",
              "version": 0
            }),
        },
      }
      const builder = LocalVBI.dashboard.create({
          "widgets": [],
          "breakpoints": {
            "xxl": 1600,
            "xl": 1200,
            "lg": 996,
            "md": 768,
            "sm": 480,
            "xs": 0
          },
          "layout": {
            "xxl": [],
            "xl": [],
            "lg": [],
            "md": [],
            "sm": [],
            "xs": []
          },
          "meta": {
            "title": "Dashboard vận hành",
            "theme": "dark"
          },
          "version": 0
        })
      const applyBuilder = (builder: VBIDashboardBuilder, resources: any) => {
  builder.chart.add(chart => {
    chart
      .setChartId(resources.charts.salesChart)
      .setTitle('Doanh số khu vực')
      .setDescription('Tổng hợp doanh số theo tỉnh')
      .setLayouts({
        lg: { x: 0, y: 0, w: 7, h: 5 },
        md: { x: 0, y: 0, w: 6, h: 4 },
        sm: { x: 0, y: 0, w: 4, h: 4 }
      })
  })

  builder.chart.add(chart => {
    chart
      .setChartId(resources.charts.profitChart)
      .setTitle('Xu hướng lợi nhuận')
      .setDescription('Tổng hợp lợi nhuận theo tháng')
      .setLayouts({
        lg: { x: 7, y: 0, w: 5, h: 5 },
        md: { x: 0, y: 4, w: 6, h: 4 },
        sm: { x: 0, y: 4, w: 4, h: 4 }
      })
  })

  builder.insight.add(insight => {
    insight
      .setInsightId(resources.insights.opsInsight)
      .setTitle('Insight vận hành')
      .setDescription('Giải thích liên hệ giữa doanh số và lợi nhuận')
      .setLayouts({
        lg: { x: 0, y: 5, w: 12, h: 3 },
        md: { x: 0, y: 8, w: 6, h: 3 },
        sm: { x: 0, y: 8, w: 4, h: 3 }
      })
  })
}
      applyBuilder(builder, resources)
      setResult(builder.build())
    } catch (err) {
      setError(err instanceof Error ? err.message : String(err))
    }
  }, [])

  if (error) return <JsonRender value={{ error }} />
  if (!result) return <div>Loading...</div>

  return <JsonRender value={result} />
}

update-and-remove-dashboard-widgets

Thêm nhiều dashboard widget, sau đó cập nhật layout và xóa chart tạm thời

Thẻ: layout mutation

Loading...
import { createVBI, VBIChartBuilder, VBIInsightBuilder, VBIDashboardBuilder } from '@visactor/vbi'
import { JsonRender } from '@components'
import { useEffect, useState } from 'react'

export default () => {
  const [result, setResult] = useState<any>(null)
  const [error, setError] = useState<string | null>(null)

  useEffect(() => {
    try {
      const LocalVBI = createVBI()
      const resources = {
        charts: {
        },
        insights: {
        },
      }
      const builder = LocalVBI.dashboard.create({
          "widgets": [],
          "breakpoints": {
            "xxl": 1600,
            "xl": 1200,
            "lg": 996,
            "md": 768,
            "sm": 480,
            "xs": 0
          },
          "layout": {
            "xxl": [],
            "xl": [],
            "lg": [],
            "md": [],
            "sm": [],
            "xs": []
          },
          "meta": {
            "title": "",
            "theme": "light"
          },
          "version": 0
        })
      const applyBuilder = (builder: VBIDashboardBuilder, _resources: any) => {
  builder.chart.add(chart => {
    chart.setTitle('Chart tạm thời').setLayouts({ lg: { x: 0, y: 0, w: 6, h: 4 } })
  })
  builder.insight.add(insight => {
    insight.setTitle('Insight được giữ lại').setLayouts({ lg: { x: 6, y: 0, w: 6, h: 4 } })
  })

  const [chartWidget] = builder.chart.toJSON()
  const [insightWidget] = builder.insight.toJSON()

  builder.chart.update(chartWidget.id, chart => {
    chart
      .setDescription('Xóa sau khi cập nhật')
      .setLayouts({ lg: { x: 0, y: 1, w: 5, h: 3 } })
  })
  builder.insight.update(insightWidget.id, insight => {
    insight.setDescription('Mô tả insight được giữ lại trong dashboard')
  })
  builder.chart.remove(chartWidget.id)
}
      applyBuilder(builder, resources)
      setResult(builder.build())
    } catch (err) {
      setError(err instanceof Error ? err.message : String(err))
    }
  }, [])

  if (error) return <JsonRender value={{ error }} />
  if (!result) return <div>Loading...</div>

  return <JsonRender value={result} />
}