Skip to content

Commit cec41cb

Browse files
committed
wip
1 parent f1f4cf4 commit cec41cb

File tree

9 files changed

+95
-59
lines changed

9 files changed

+95
-59
lines changed

demo/app/Sharp/Dashboard/DemoDashboard.php

Lines changed: 15 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -31,19 +31,13 @@
3131

3232
class DemoDashboard extends SharpDashboard
3333
{
34-
private static array $colors = [
35-
'#2a9d90',
36-
'#e76e50',
37-
'#274754',
38-
'#e8c468',
39-
'#f4a462',
40-
// '#3B82F6',
41-
// '#064E3B',
42-
// '#EC4899',
43-
// '#78350F',
44-
// '#9CA3AF',
34+
const array COLORS = [
35+
'oklch(0.809 0.105 251.813)',
36+
'oklch(0.623 0.214 259.815)',
37+
'oklch(0.546 0.245 262.881)',
38+
'oklch(0.488 0.243 264.376)',
39+
'oklch(0.424 0.199 265.638)',
4540
];
46-
private static int $colorsIndex = 0;
4741

4842
protected function buildWidgets(WidgetsContainer $widgetsContainer): void
4943
{
@@ -52,7 +46,7 @@ protected function buildWidgets(WidgetsContainer $widgetsContainer): void
5246
SharpBarGraphWidget::make('authors_bar')
5347
->setTitle('Posts by author')
5448
->setShowLegend(false)
55-
->setHorizontal(),
49+
// ->setHorizontal(),
5650
)
5751
->addWidget(
5852
SharpPieGraphWidget::make('categories_pie')
@@ -62,10 +56,10 @@ protected function buildWidgets(WidgetsContainer $widgetsContainer): void
6256
SharpLineGraphWidget::make('visits_line')
6357
->setTitle('Visits')
6458
->setHeight(200)
65-
->setShowLegend()
66-
// ->setDisplayHorizontalAxisAsTimeline()
67-
// ->setMinimal()
68-
->setCurvedLines(),
59+
// ->setShowLegend()
60+
->setDisplayHorizontalAxisAsTimeline()
61+
->setMinimal()
62+
->setFilled(),
6963
)
7064
->addWidget(
7165
SharpFigureWidget::make('draft_panel')
@@ -185,13 +179,13 @@ protected function setLineGraphDataSet(): void
185179
'visits_line',
186180
SharpGraphWidgetDataSet::make($visits)
187181
->setLabel('Visits')
188-
->setColor(static::nextColor()),
182+
->setColor(static::COLORS[0]),
189183
)
190184
->addGraphDataSet(
191185
'visits_line',
192186
SharpGraphWidgetDataSet::make($visits->map(fn ($value) => (int) ($value / (rand(20, 40) / 10))))
193187
->setLabel('New')
194-
->setColor(static::nextColor()),
188+
->setColor(static::COLORS[1]),
195189
);
196190
}
197191

@@ -213,7 +207,7 @@ protected function setBarsGraphDataSet(): void
213207
$this->addGraphDataSet(
214208
'authors_bar',
215209
SharpGraphWidgetDataSet::make($data)
216-
->setColor(static::nextColor()),
210+
->setColor(static::COLORS[1]),
217211
);
218212
}
219213

@@ -235,7 +229,7 @@ protected function setPieGraphDataSet(): void
235229
'categories_pie',
236230
SharpGraphWidgetDataSet::make([$category->posts_count])
237231
->setLabel($category->name)
238-
->setColor(static::nextColor()),
232+
->setColor(static::COLORS[$i % count(static::COLORS)]),
239233
);
240234
});
241235
}
@@ -285,15 +279,6 @@ protected function setCustomPanelDataSet(): void
285279
}
286280
}
287281

288-
private static function nextColor(): string
289-
{
290-
if (static::$colorsIndex >= count(static::$colors)) {
291-
static::$colorsIndex = 0;
292-
}
293-
294-
return static::$colors[static::$colorsIndex++];
295-
}
296-
297282
protected function getStartDate(): Carbon
298283
{
299284
return $this->queryParams->filterFor(PeriodRequiredFilter::class)->getStart();

resources/js/components/ui/chart/utils.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ export function componentToString<P>(config: MaybeRef<ChartConfig>, component: C
3030
// https://unovis.dev/docs/auxiliary/Crosshair#component-props
3131
return (_data: any, x: number | Date) => {
3232
const data = "data" in _data ? _data.data : _data
33-
const serializedKey = `${id}-${serializeKey(data)}`
33+
const normalizedX = typeof x === "number" ? Math.round(x) : x.getTime()
34+
const serializedKey = `${id}-${normalizedX}-${serializeKey(data)}`
3435
const cachedContent = cache.get(serializedKey)
3536
if (cachedContent)
3637
return cachedContent

resources/js/dashboard/components/widgets/graph/Bar.vue

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,14 @@
3535
<VisAxis
3636
v-bind="{
3737
type: props.widget.options?.horizontal ? 'x' : 'y',
38+
domainLine: false,
3839
} as AxisConfigInterface<Datum>"
3940
/>
4041
<VisAxis
4142
v-bind="{
4243
type: props.widget.options?.horizontal ? 'y' : 'x',
4344
gridLine: false,
45+
domainLine: false,
4446
// tickValues: props.value?.labels.map((_, i) => i),
4547
numTicks: props.value?.labels.length - 1,
4648
tickFormat: tickFormat,

resources/js/dashboard/components/widgets/graph/Line.vue

Lines changed: 53 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,64 @@
11
<script setup lang="ts">
22
import { GraphWidgetData } from "@/types";
33
import { DashboardWidgetProps } from "@/dashboard/types";
4-
import { VisXYContainer, VisAxis, VisLine, VisTooltip, VisCrosshair, VisScatter } from "@unovis/vue";
4+
import { VisXYContainer, VisAxis, VisLine, VisTooltip, VisCrosshair, VisScatter, VisArea } from "@unovis/vue";
55
import {
66
AxisConfigInterface, BulletLegendConfigInterface,
77
CrosshairConfigInterface,
88
CurveType,
99
LineConfigInterface, ScatterConfigInterface, XYContainerConfigInterface,
10-
Scale, TextAlign, FitMode, Scatter,
10+
Scale, TextAlign, FitMode, Scatter, AreaConfigInterface,
1111
} from "@unovis/ts";
1212
import { Datum, useXYChart } from "@/dashboard/components/widgets/graph/useXYChart";
1313
import { ChartContainer, ChartLegendContent, ChartTooltip, ChartCrosshair } from "@/components/ui/chart";
14+
import { computed } from "vue";
1415
1516
const props = defineProps<DashboardWidgetProps<GraphWidgetData>>();
1617
18+
// props.value.datasets = props.value?.datasets.toReversed();
19+
1720
const { data, x, y, color, tooltipTemplate, xScale, xTickValues, tickFormat, chartConfig } = useXYChart(props);
1821
1922
// const rotate = computed(() => props.value?.labels?.length >= 10);
23+
const svgDefs = computed(() => props.value?.datasets.map((dataset, i) => `
24+
<linearGradient id="fill-${i}" x1="0" y1="0" x2="0" y2="1">
25+
<stop
26+
offset="5%"
27+
stop-color="${dataset.color}"
28+
stop-opacity="0.8"
29+
/>
30+
<stop
31+
offset="95%"
32+
stop-color="${dataset.color}"
33+
stop-opacity="0.1"
34+
/>
35+
</linearGradient>
36+
`).join(''));
2037
</script>
2138

2239
<template>
2340
<ChartContainer class="flex flex-col" :config="chartConfig">
24-
<VisXYContainer class="flex-1 min-h-0" v-bind="{
25-
xScale,
26-
components: props.value?.datasets.map(dataset => new Scatter({
27-
size: 5, x: x, y: y, color: color
28-
})),
29-
} as XYContainerConfigInterface<Datum>" :data="data">
41+
<VisXYContainer class="flex-1 min-h-0"
42+
v-bind="{
43+
xScale: xScale,
44+
svgDefs: svgDefs,
45+
} as XYContainerConfigInterface<Datum>"
46+
:data="data"
47+
>
3048
<template v-if="!props.widget.minimal">
3149
<VisAxis
3250
v-bind="{
3351
type: 'x',
3452
tickFormat: tickFormat,
3553
tickValues: xTickValues,
36-
// minMaxTicksOnly: true
37-
// tickValues: props.value?.labels.length < 5 ? props.value?.labels.map((_, i) => x(null, i)) as number[] : undefined,
38-
// numTicks: props.value?.labels.length < 10 ? props.value?.labels.length - 1 : undefined,
39-
// tickTextAlign: rotate ? TextAlign.Left : TextAlign.Center,
40-
// tickTextFitMode: rotate ? FitMode.Wrap : FitMode.Trim,
41-
// tickTextAngle: rotate ? 45 : undefined,
42-
// tickTextWidth: rotate ? 100 : undefined,
54+
gridLine: false,
55+
domainLine: false,
4356
} as AxisConfigInterface<Datum>"
4457
/>
45-
<VisAxis v-bind="{ type: 'y' } as AxisConfigInterface<Datum>" />
58+
<VisAxis v-bind="{
59+
type: 'y',
60+
domainLine: false,
61+
} as AxisConfigInterface<Datum>" />
4662
</template>
4763

4864
<VisLine
@@ -55,6 +71,20 @@
5571
} as LineConfigInterface<Datum>"
5672
/>
5773

74+
<template v-if="props.widget.options.filled">
75+
<template v-for="(dataset, i) in props.value?.datasets.toReversed()">
76+
<VisArea
77+
v-bind="{
78+
x: x,
79+
y: (d) => d[i],
80+
color: () => `url(#fill-${i})`,
81+
opacity: 0.6,
82+
curveType: props.widget.options.curved ? CurveType.MonotoneX : CurveType.Linear,
83+
} as AreaConfigInterface<Datum>"
84+
/>
85+
</template>
86+
</template>
87+
5888
<ChartCrosshair
5989
v-bind="{
6090
color: color,
@@ -64,14 +94,13 @@
6494
/>
6595
<ChartTooltip />
6696

67-
<template v-if="props.value?.labels.length < 40">
68-
<template v-for="dataset in props.value?.datasets">
69-
<VisScatter
70-
v-bind="{ size: 4, x: x, y: y, strokeColor: color, color: 'var(--background)' } as ScatterConfigInterface<Datum>"
71-
/>
72-
</template>
73-
</template>
74-
97+
<!-- <template v-if="props.value?.labels.length < 40">-->
98+
<!-- <template v-for="dataset in props.value?.datasets">-->
99+
<!-- <VisScatter-->
100+
<!-- v-bind="{ size: 4, x: x, y: y, strokeColor: color, color: 'var(&#45;&#45;background)' } as ScatterConfigInterface<Datum>"-->
101+
<!-- />-->
102+
<!-- </template>-->
103+
<!-- </template>-->
75104
</VisXYContainer>
76105
<template v-if="props.widget.showLegend && !props.widget.minimal">
77106
<ChartLegendContent />

resources/js/dashboard/components/widgets/graph/Pie.vue

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<script setup lang="ts">
2-
import { computed, useTemplateRef } from "vue";
2+
import { computed, useAttrs, useTemplateRef } from "vue";
33
import { GraphWidgetData } from "@/types";
44
import { DashboardWidgetProps } from "@/dashboard/types";
55
import { VisSingleContainer, VisDonut, VisTooltip, VisBulletLegend } from "@unovis/vue";
@@ -30,6 +30,8 @@
3030
console.log(v, ...args);
3131
return v;
3232
}
33+
const attrs = useAttrs();
34+
console.log(attrs);
3335
</script>
3436

3537
<template>
@@ -42,7 +44,8 @@
4244
value: d => d.value,
4345
color: d => d.color,
4446
// arcWidth: 47,
45-
arcWidth: log(Math.round(Math.min(width, height) * .15), width, height),
47+
arcWidth: width ? log(Math.round(Math.min(width, height) * .15), width, height) : 20,
48+
showBackground: false,
4649
attributes: {
4750
// [Donut.selectors.segment]: {
4851
// 'class'() {

resources/js/dashboard/components/widgets/graph/useXYChart.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,13 @@ export function useXYChart(props: DashboardWidgetProps<GraphWidgetData>) {
5656
Object.fromEntries(props.value?.datasets.map((dataset, i) => [i, ({ label: dataset.label, color: dataset.color })]))
5757
);
5858

59-
const tooltipTemplate = componentToString(chartConfig, ChartTooltipContent);
59+
const tooltipTemplate = componentToString(chartConfig, ChartTooltipContent, {
60+
labelFormatter: (x) => {
61+
return props.widget.dateLabels
62+
? new Intl.DateTimeFormat(undefined, { day: '2-digit', month: 'short' }).format(timeScale ? x : new Date(props.value.labels[Math.round(x as number)]))
63+
: props.value.labels[Math.round(x as number)];
64+
}
65+
});
6066

6167
const tickFormat: AxisConfigInterface<number[]>['tickFormat'] = (tick, i) => {
6268
if(props.widget.dateLabels) {

resources/js/types/generated.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -661,7 +661,7 @@ export type GraphWidgetData = {
661661
ratioY: number | null;
662662
height: number | null;
663663
dateLabels: boolean;
664-
options: { curved: boolean; horizontal: boolean };
664+
options: { curved: boolean; horizontal: boolean; filled: boolean };
665665
};
666666
export type GraphWidgetDisplay = "bar" | "line" | "pie";
667667
export type IconData = {

src/Dashboard/Widgets/SharpLineGraphWidget.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ class SharpLineGraphWidget extends SharpGraphWidget
66
{
77
protected bool $curvedLines = true;
88
protected bool $displayHorizontalAxisAsTimeline = false;
9+
protected bool $filled = false;
910

1011
public static function make(string $key): SharpLineGraphWidget
1112
{
@@ -22,6 +23,13 @@ public function setCurvedLines(bool $curvedLines = true): self
2223
return $this;
2324
}
2425

26+
public function setFilled(bool $filled = true): self
27+
{
28+
$this->filled = $filled;
29+
30+
return $this;
31+
}
32+
2533
public function setDisplayHorizontalAxisAsTimeline(bool $displayAsTimeline = true): self
2634
{
2735
$this->displayHorizontalAxisAsTimeline = $displayAsTimeline;
@@ -36,6 +44,7 @@ public function toArray(): array
3644
'dateLabels' => $this->displayHorizontalAxisAsTimeline,
3745
'options' => [
3846
'curved' => $this->curvedLines,
47+
'filled' => $this->filled,
3948
],
4049
],
4150
);

src/Data/Dashboard/Widgets/GraphWidgetData.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ public function __construct(
3737
#[TypeScriptType([
3838
'curved' => 'boolean',
3939
'horizontal' => 'boolean',
40+
'filled' => 'boolean',
4041
])]
4142
public ?array $options = null,
4243
) {}

0 commit comments

Comments
 (0)