Skip to content

Commit e6cf8d6

Browse files
committed
charts progress
1 parent 101889b commit e6cf8d6

File tree

14 files changed

+261
-128
lines changed

14 files changed

+261
-128
lines changed

Changelog.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1515
### Fixed
1616
- show hook is now called as it was when user edits the page
1717
- fixed showRow in ShowTable.vue
18+
- if not ab le to connect postgres, don't crash the app
19+
20+
### Improved
21+
- reduce stdout output from AdminForths
22+
23+
### Added
24+
- AFCL Chart components
1825

1926
## [v1.5.8]
2027

adminforth/documentation/docs/tutorial/03-Customization/13-standardPagesTuning.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
## Fields Grouping
77

88

9-
In some cases, you may want to organize data fields into specific groups for better structure and clarity. For example, you could create a "Main Info" group to include columns like title, description, country, and apartment_image. Another group, "Characteristics," could hold attributes such as price, square_meter, number_of_rooms, property_type, and listed. Any values without a specified group will be categorized under "Other.
9+
In some cases, you may want to organize data fields into specific groups for better structure and clarity. For example, you could create a "Main Info" group to include columns like title, description, country, and apartment_image. Another group, "Characteristics," could hold attributes such as price, square_meter, number_of_rooms, and listed. Any values without a specified group will be categorized under "Other.
1010

1111
```typescript title="./resources/apartments.ts"
1212
export default {
@@ -28,7 +28,7 @@ export default {
2828
//diff-add
2929
groupName: 'Characteristics',
3030
//diff-add
31-
columns: ['price', 'square_meter', 'number_of_rooms', "property_type", "listed"]
31+
columns: ['price', 'square_meter', 'number_of_rooms', "listed"]
3232
//diff-add
3333
}
3434
//diff-add
@@ -60,7 +60,7 @@ export default {
6060
//diff-add
6161
groupName: 'Characteristics',
6262
//diff-add
63-
columns: ['description', 'country', 'price', 'square_meter', 'number_of_rooms', "property_type", "listed"]
63+
columns: ['description', 'country', 'price', 'square_meter', 'number_of_rooms', "listed"]
6464
//diff-add
6565
}
6666
//diff-add

adminforth/package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

adminforth/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "adminforth",
3-
"version": "1.5.9-next.2",
3+
"version": "1.5.9-next.4",
44
"description": "OpenSource Vue3 powered forth-generation admin panel",
55
"main": "dist/index.js",
66
"module": "dist/index.js",
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Changelog
2+
3+
All notable changes to this project will be documented in this file.
4+
5+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7+
8+
## [1.0.26]
9+
10+
### Fixed
11+
12+
- Modify Resource Config did not support allowedActions, now it does
13+
- Modify Resource Config did not support bulkActions, now it does

adminforth/plugins/foreign-inline-list/package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

adminforth/plugins/foreign-inline-list/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@adminforth/foreign-inline-list",
3-
"version": "1.0.25",
3+
"version": "1.0.26",
44
"description": "AdminForth plugin for adding list of children items to the parent item show page",
55
"main": "dist/index.js",
66
"types": "dist/index.d.ts",

adminforth/spa/src/afcl/AreaChart.vue

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
<script setup lang="ts">
66
import ApexCharts, { type ApexOptions } from 'apexcharts';
7-
import { ref, type Ref, watch, computed } from 'vue';
7+
import { ref, type Ref, watch, computed, onUnmounted } from 'vue';
88
99
const chart: Ref<HTMLDivElement | null> = ref(null);
1010
@@ -60,9 +60,10 @@ const optionsBase = {
6060
show: false,
6161
strokeDashArray: 4,
6262
padding: {
63-
left: 2,
64-
right: 2,
65-
top: 0
63+
left: 3,
64+
right: 3,
65+
top: 3,
66+
bottom: 3
6667
},
6768
},
6869
series: [],
@@ -131,16 +132,24 @@ const options = computed(() => {
131132
return options;
132133
});
133134
134-
let apexChart: ApexCharts;
135+
let apexChart: ApexCharts | null = null;
135136
136-
watch(() => options.value, (value) => {
137+
watch(() => [options.value, chart.value], (value) => {
138+
if (!value || !chart.value) {
139+
return;
140+
}
137141
if (apexChart) {
138-
apexChart.updateOptions(value);
142+
apexChart.updateOptions(options.value);
139143
} else {
140-
console.log('chart.value', value);
141-
apexChart = new ApexCharts(chart.value, value);
144+
apexChart = new ApexCharts(chart.value, options.value);
142145
apexChart.render();
143146
}
144147
});
145148
149+
onUnmounted(() => {
150+
if (apexChart) {
151+
apexChart.destroy();
152+
}
153+
});
154+
146155
</script>

adminforth/spa/src/afcl/BarChart.vue

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
<script setup lang="ts">
66
import ApexCharts, { type ApexOptions } from 'apexcharts';
7-
import { ref, type Ref, watch, computed } from 'vue';
7+
import { ref, type Ref, watch, computed, onUnmounted } from 'vue';
88
99
const chart: Ref<HTMLDivElement | null> = ref(null);
1010
@@ -43,7 +43,7 @@ const optionsBase = {
4343
horizontal: false,
4444
columnWidth: "80%",
4545
borderRadiusApplication: "end",
46-
borderRadius: 5,
46+
borderRadius: 8,
4747
dataLabels: {
4848
position: "top",
4949
},
@@ -95,8 +95,10 @@ const optionsBase = {
9595
show: false,
9696
strokeDashArray: 4,
9797
padding: {
98-
left: 2,
99-
right: 2,
98+
left: 3, // 3 seams to be a safe value, otherwise labels overlap somewhy
99+
right: 3,
100+
top: 3,
101+
bottom: 3,
100102
// top: -20
101103
},
102104
},
@@ -142,16 +144,23 @@ const options = computed(() => {
142144
return options;
143145
});
144146
145-
let apexChart: ApexCharts;
147+
let apexChart: ApexCharts | null = null;
146148
147-
watch(() => options.value, (value) => {
149+
watch(() => [options.value, chart.value], (value) => {
150+
if (!value || !chart.value) {
151+
return;
152+
}
148153
if (apexChart) {
149-
apexChart.updateOptions(value);
154+
apexChart.updateOptions(options.value);
150155
} else {
151-
console.log('chart.value', value);
152-
apexChart = new ApexCharts(chart.value, value);
156+
apexChart = new ApexCharts(chart.value, options.value);
153157
apexChart.render();
154158
}
155159
});
156160
161+
onUnmounted(() => {
162+
if (apexChart) {
163+
apexChart.destroy();
164+
}
165+
});
157166
</script>
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
<template>
2+
<div ref="chart"></div>
3+
</template>
4+
5+
<script setup lang="ts">
6+
import ApexCharts, { type ApexOptions } from 'apexcharts';
7+
import { ref, type Ref, watch, computed, onUnmounted } from 'vue';
8+
9+
const chart: Ref<HTMLDivElement | null> = ref(null);
10+
11+
const props = defineProps<{
12+
data: {
13+
x: string,
14+
[key: string]: any,
15+
}[],
16+
series: {
17+
name: string,
18+
fieldName: string,
19+
color: string,
20+
}[],
21+
options: ApexOptions,
22+
}>();
23+
24+
25+
26+
const optionsBase = {
27+
chart: {
28+
sparkline: {
29+
enabled: false,
30+
},
31+
type: "bar",
32+
width: "100%",
33+
height: 150,
34+
toolbar: {
35+
show: false,
36+
}
37+
},
38+
fill: {
39+
opacity: 1,
40+
},
41+
plotOptions: {
42+
bar: {
43+
horizontal: false,
44+
columnWidth: "80%",
45+
borderRadiusApplication: "end",
46+
borderRadius: 8,
47+
dataLabels: {
48+
position: "top",
49+
},
50+
},
51+
},
52+
legend: {
53+
show: false,
54+
position: "bottom",
55+
},
56+
dataLabels: {
57+
enabled: false,
58+
},
59+
tooltip: {
60+
shared: true,
61+
intersect: false,
62+
formatter: function (value) {
63+
return value
64+
},
65+
},
66+
xaxis: {
67+
labels: {
68+
show: false,
69+
style: {
70+
fontFamily: "Inter, sans-serif",
71+
cssClass: 'text-xs font-normal fill-gray-500 dark:fill-gray-400'
72+
},
73+
formatter: function (value) {
74+
return value
75+
}
76+
},
77+
categories: [],
78+
axisTicks: {
79+
show: false,
80+
},
81+
axisBorder: {
82+
show: false,
83+
},
84+
},
85+
yaxis: {
86+
labels: {
87+
show: false,
88+
style: {
89+
fontFamily: "Inter, sans-serif",
90+
cssClass: 'text-xs font-normal fill-gray-500 dark:fill-gray-400'
91+
}
92+
}
93+
},
94+
grid: {
95+
show: false,
96+
strokeDashArray: 4,
97+
padding: {
98+
left: 2,
99+
right: 2,
100+
// top: -20
101+
},
102+
},
103+
};
104+
105+
const options = computed(() => {
106+
if (props.data?.length > 0) {
107+
props.series.forEach((s) => {
108+
if (props.data[0][s.fieldName] === undefined) {
109+
throw new Error(`Field ${s.fieldName} not found even in first data point ${JSON.stringify(props.data[0])}, something is wrong`);
110+
}
111+
});
112+
}
113+
const options = {
114+
...optionsBase,
115+
116+
// shade and gradient take from first series
117+
series: props.series.map((s) => ({
118+
data: props.data?.map((item) => item[s.fieldName]) ?? [],
119+
...s,
120+
})),
121+
xaxis: {
122+
...optionsBase.xaxis,
123+
categories: props.data?.map((item) => item.x) ?? [],
124+
},
125+
};
126+
127+
// for each of ...props.options merge on lowest level. so if { chart: {height : 2} }, it should not replace chart level, only height level
128+
function mergeOptions(options: any, newOptions: any) {
129+
for (const key in newOptions) {
130+
if (typeof newOptions[key] === 'object') {
131+
if (!options[key]) {
132+
options[key] = {};
133+
}
134+
mergeOptions(options[key], newOptions[key]);
135+
} else {
136+
options[key] = newOptions[key];
137+
}
138+
}
139+
}
140+
mergeOptions(options, props.options);
141+
142+
return options;
143+
});
144+
145+
let apexChart: ApexCharts | null = null;
146+
147+
watch(() => [options.value, chart.value], (value) => {
148+
if (!value || !chart.value) {
149+
return;
150+
}
151+
if (apexChart) {
152+
apexChart.updateOptions(options.value);
153+
} else {
154+
apexChart = new ApexCharts(chart.value, options.value);
155+
apexChart.render();
156+
}
157+
});
158+
159+
onUnmounted(() => {
160+
if (apexChart) {
161+
apexChart.destroy();
162+
}
163+
});
164+
</script>

0 commit comments

Comments
 (0)