GrDashboardItemSettings

Package: @feugene/granularity-dashboardcompanionGroup: misc

Machine-translated from the Russian original, not yet reviewed. Read the original

When to take it

  • the widget has something to configure — a period, a source, an alert threshold: the window gives them a place without making the application assemble a dialog anew on every dashboard;
  • the size is set with a number rather than with a gesture — from the keyboard the resize corner requires counting the presses, and here the width and the height are entered directly;
  • the widget cannot be stretched with the mouse — a narrow screen, touch input, resizable removed on its neighbours: the fields remain the only way to change the size;
  • a refusal has to be visible — “there is no room on the grid” is shown by the window in place rather than by closing over something not done.

When to take something else

NeedTake
A window of your own with a header and a footer of your ownGrDialog
Ask “are you sure?” before a destructive actionGrConfirmDialog
Product buttons right in the header of a widgetGrDashboardItem
A form from a backend schemaGrSchemaForm

The button is opened by the widget, the window is drawn by the package

The gear lives in GrDashboardItem under the showSettings prop and appears in the same place as #editActions: in the header if there is one, and in the panel over the content if there is not. Unlike #actions, it does not switch the header on — otherwise entering the edit mode would shift the content by its height.

A press emits settings on the widget and itemSettings on the grid. The second is needed so that the application listens in one place rather than subscribing to every widget separately.

The size is committed by the grid rather than by the window

The width and the height travel into the layout through the context of the grid — with its compaction, its preventCollision and its check of static. The window deliberately has no arithmetic of its own: were it to compute the size itself, two layouts would appear on the dashboard, diverging at the very first collision.

Hence the bounds of the fields as well. The upper limit of the width is neither the number of columns nor maxW, but the smaller of them and cols - x: a widget grows to the right and will not go past the right edge. A field offering twelve columns to a widget standing in the eighth would silently give away four.

Applying with a button rather than live

Changing the size moves the neighbours, and a live preview would require a snapshot of the layout and a rollback on Esc. One press of “Apply” is therefore one commit, and “Cancel” leaves no traces: the draft is typed anew on every opening.

Outside a grid the window works without the size

The context of GrDashboard is the only source both of the widget and of the number of columns. If the window stands outside, itemId equals null or the grid is in the view mode, the size block is simply absent while the application’s slot keeps working. The hideSize prop removes it even where there is a grid: sometimes the application computes the size itself.

Limits

The window does not edit the title of the widget, its static or the minW/maxW bounds. The first deliberately does not enter the layout — having travelled into the storage, it would go stale at the first change of language; the rest are declared by the markup of the widget, and an editor for them would introduce a second truth about the same thing.

Install

npm i @feugene/granularity-dashboard

Import

import { GrDashboardItemSettings } from '@feugene/granularity-dashboard/components/GrDashboardItemSettings'

API

The API for this component has not been generated yet: the showcase generator only covers the core so far. Until it does, the reference lives in the package documentation.

Examples 1

Basic

Basic
<script setup lang="ts">
import { ref } from 'vue'
import type { GrDashboardResponsiveLayout } from '@feugene/granularity-dashboard'

/**
 * Настройки виджета: размер в ячейках даёт пакет, период — приложение.
 *
 * Кнопку-шестерёнку рисует сам виджет (`show-settings`), окно приложение
 * открывает по `item-settings` от сетки — так подписка одна на всю сетку, а не
 * по одной на каждый виджет.
 */
const layout = ref<GrDashboardResponsiveLayout>({
  lg: [
    { id: 'revenue', x: 0, y: 0, w: 6, h: 2 },
    { id: 'orders', x: 6, y: 0, w: 6, h: 2, minW: 3 },
  ],
})

const titles: Record<string, string> = { revenue: 'Выручка', orders: 'Заказы' }
const periods = [
  { value: 'week', label: 'Неделя' },
  { value: 'month', label: 'Месяц' },
  { value: 'quarter', label: 'Квартал' },
]

const period = ref<Record<string, string>>({ revenue: 'month', orders: 'week' })
const draft = ref('month')

const open = ref(false)
const editing = ref<string | null>(null)

function openSettings(id: string): void {
  editing.value = id
  draft.value = period.value[id] ?? 'month'
  open.value = true
}

function apply(id: string): void {
  period.value = { ...period.value, [id]: draft.value }
}

const breakpoints = { lg: 680, md: 520, sm: 400, xs: 0 }
const cols = { lg: 12, md: 8, sm: 4, xs: 2 }
</script>

<template>
  <GrDashboard
    v-model:layout="layout"
    mode="edit"
    :breakpoints="breakpoints"
    :cols="cols"
    :row-height="72"
    aria-label="Настройки виджета"
    @item-settings="openSettings"
  >
    <GrDashboardItem
      v-for="item in layout.lg"
      :key="item.id"
      :item-id="item.id"
      :title="titles[item.id]"
      show-settings
      overflow="hidden"
    >
      <p class="text-[var(--gr-muted-fg)]">
        Период: {{ periods.find(entry => entry.value === period[item.id])?.label }}
      </p>
    </GrDashboardItem>

    <GrDashboardItemSettings v-model="open" :item-id="editing" @apply="apply">
      <GrFormField label="Период">
        <GrSelect v-model="draft" :options="periods" />
      </GrFormField>
    </GrDashboardItemSettings>
  </GrDashboard>
</template>

Component documentationAll components