Skip to content

Commit

Permalink
feat: Improve styling of the charts as well as the (#43)
Browse files Browse the repository at this point in the history
## Before

<img width="1629" alt="Screenshot 2024-04-28 at 16 25 23"
src="https://github.com/flxdot/carlos/assets/35657654/d341cde2-6b3d-4d9d-94a1-e24ca717d716">

## After

<img width="1549" alt="Screenshot 2024-04-28 at 16 02 52"
src="https://github.com/flxdot/carlos/assets/35657654/aef766f5-a27f-466b-9148-1dde7017b794">
  • Loading branch information
flxdot authored Apr 28, 2024
1 parent a71dd89 commit 7bcc5d5
Show file tree
Hide file tree
Showing 21 changed files with 1,782 additions and 536 deletions.
5 changes: 5 additions & 0 deletions .github/workflows/test-services-frontend.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,11 @@ jobs:
working-directory: services/frontend
run: yarn lint

- name: Unittest services/frontend
if: ${{ !cancelled() }}
working-directory: services/frontend
run: yarn test:unit

- name: build workspace
if: ${{ !cancelled() }}
working-directory: .
Expand Down
12 changes: 12 additions & 0 deletions .run/frontend _ test_unit_watch.run.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="frontend &gt; test:unit:watch" type="js.build_tools.npm">
<package-json value="$PROJECT_DIR$/services/frontend/package.json" />
<command value="run" />
<scripts>
<script value="test:unit:watch" />
</scripts>
<node-interpreter value="project" />
<envs />
<method v="2" />
</configuration>
</component>
31 changes: 31 additions & 0 deletions branding/carlos.css
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,37 @@ define the Carlos theme.
--carlos-accent-color: #afe06c;

--carlos-bg-color: #1f2128;
--carlos-bg-text--dark: #64748b;

--carlos-danger-color: #ef4444;

/* Palette ONE */
--carlos-palette1-sycamore: #a4833a;
--carlos-palette1-firefly: #133b34;
--carlos-palette1-charlotte: #acf9ea;
--carlos-palette1-nutmeg: #792c29;

/* palette two */
--carlos-palette2-cream: #f4fec1;
--carlos-palette2-mindaro: #d9f9a5;
--carlos-palette2-citron: #d2d68d;
--carlos-palette2-cinerous: #81726a;
--carlos-palette2-wenge: #68534d;

/* palette three */
--carlos-palette3-mindaro: #cbe896;
--carlos-palette3-ash-grey: #aac0aa;
--carlos-palette3-peach-yellow: #fcdfa6;
--carlos-palette3-beaver: #a18276;
--carlos-palette3-fawn: #f4b886;

/* palette ten */
--carlos-palette-ten: #f9c74f;

/* palette jet */
--carlos-palette-jet1: #366dea;
--carlos-palette-jet2: #7dcce1;
--carlos-palette-jet3: #bccf71;
--carlos-palette-jet4: #f0ce47;
--carlos-palette-jet5: #ab3124;
}
4 changes: 4 additions & 0 deletions services/frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
"dev": "vite",
"build": "vue-tsc && vite build",
"preview": "vite preview",
"test:unit": "vitest run",
"test:unit:watch": "vitest watch",
"tsc": "vue-tsc",
"lint": "yarn lint:js && yarn lint:css",
"lint:fix": "yarn lint:js:fix && yarn lint:css:fix",
Expand All @@ -22,6 +24,7 @@
"axios-jwt": "^4.0.2",
"chart.js": "^4.4.2",
"chartjs-adapter-dayjs-4": "^1.0.4",
"colorjs.io": "^0.5.0",
"dayjs": "^1.11.10",
"markdown-it": "^14.1.0",
"path": "^0.12.7",
Expand Down Expand Up @@ -53,6 +56,7 @@
"vite": "^5.2.0",
"vite-raw-plugin": "^1.0.2",
"vite-svg-loader": "^5.1.0",
"vitest": "^1.5.2",
"vue-i18n": "^9.11.0",
"vue-tsc": "^2.0.6"
}
Expand Down
116 changes: 116 additions & 0 deletions services/frontend/src/components/charts/chart-analog.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
<template>
<chart-base-line
:chart-data="chartData"
:y-axes="yAxes"
:height="props.height"
:show-x-ticks="props.showXTicks"
/>
</template>

<script setup lang="ts">
import {
defineProps,
withDefaults,
computed,
ref,
} from 'vue';
import ChartBaseLine from '@/components/charts/chart-base-line.vue';
import {
TAxisLimit,
TLineAxisProps,
TLineChartData,
} from '@/components/charts/chart-types.ts';
import {
chartJsGradient,
getSuitableLimit,
buildAxis,
} from '@/components/charts/chart-utils.ts';
import {
colorToColorStop, DiscreteGradientDefinition,
GradientCache, GradientDefinition,
} from '@/components/charts/gradients.ts';
import {
tempEmojis,
} from '@/utils/value-render.ts';
import {
LineWidth,
} from '@/components/charts/constants.ts';
import {
DeepPartial,
} from '@/utils/types.ts';
import {
ITimeseries, toChartJsData,
} from '@/components/charts/timeseries.ts';
interface IChartAnalogProps {
timeseries: ITimeseries;
limits: TAxisLimit;
ticks: number[];
color: string | GradientDefinition | DiscreteGradientDefinition;
height?: string;
tickStepSize?: number;
showXTicks?: boolean;
}
const props = withDefaults(defineProps<IChartAnalogProps>(), {
height: '10rem',
tickStepSize: 5,
showXTicks: true,
});
const lineGradient = ref<GradientCache>({
chartWidth: undefined,
chartHeight: undefined,
gradient: undefined,
});
const LineBgGradient = ref<GradientCache>({
chartWidth: undefined,
chartHeight: undefined,
gradient: undefined,
});
const actualLimits = computed<TAxisLimit>(
() => getSuitableLimit(props.limits, props.timeseries.values, props.tickStepSize),
);
const chartData = computed<DeepPartial<TLineChartData>>(() => {
let gradient: GradientDefinition | DiscreteGradientDefinition;
if (typeof props.color === 'string') {
gradient = colorToColorStop(props.color);
} else {
gradient = props.color;
}
const borderColor = chartJsGradient(lineGradient.value, gradient, actualLimits.value);
const backgroundColor = chartJsGradient(LineBgGradient.value, gradient, actualLimits.value, true);
return {
datasets: [
{
label: 'Temperature',
data: toChartJsData(props.timeseries),
borderWidth: LineWidth,
borderColor,
backgroundColor,
fill: true,
pointStyle: false,
yAxisID: props.timeseries.displayName,
// The tension helps to smooth the line in case of oversampling
tension: 0.1,
},
],
} as DeepPartial<TLineChartData>;
});
const yAxes = computed<TLineAxisProps>(() => {
return {
[props.timeseries.displayName]: buildAxis(
'right',
props.timeseries,
actualLimits.value,
props.ticks,
tempEmojis,
),
} as TLineAxisProps;
});
</script>
102 changes: 88 additions & 14 deletions services/frontend/src/components/charts/chart-base-line.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
type="line"
:data="chartData"
:options="chartOptions"
:plugins="[crosshair]"
:style="{ height: props.height || '20rem' }"
/>
</template>
Expand All @@ -12,9 +13,13 @@ import Chart from 'primevue/chart';
import {
computed,
ref,
withDefaults,
defineProps,
} from 'vue';
import {
ChartOptions,
Scale,
} from 'chart.js';
import {
deepUnion,
Expand All @@ -27,18 +32,50 @@ import {
import {
DeepPartial,
} from '@/utils/types.ts';
import {
chartJsGradient,
} from '@/components/charts/chart-utils.ts';
import {
GradientCache,
xTicksGradient,
} from '@/components/charts/gradients.ts';
import crosshair from '@/components/charts/crosshair.ts';
interface IChartBaseLineProps {
chartData: DeepPartial<TLineChartData>;
yAxes: TLineAxisProps;
height?: string;
showXTicks?: boolean;
}
const props = withDefaults(
defineProps<IChartBaseLineProps>(),
{
height: '10rem',
showXTicks: true,
},
);
const props = defineProps<{
chartData: DeepPartial<TLineChartData>,
yAxes: TLineAxisProps,
height?: string,
}>();
const ticksGradient = ref<GradientCache>({
chartWidth: undefined,
chartHeight: undefined,
gradient: undefined,
});
const chartData = computed<DeepPartial<TLineChartData>>(() => props.chartData);
const chartOptions = computed<DeepPartial<ChartOptions>>(() => {
const documentStyle = getComputedStyle(document.documentElement);
const textColorSecondary = documentStyle.getPropertyValue('--text-color-secondary');
const surfaceBorder = documentStyle.getPropertyValue('--surface-border');
const color = documentStyle.getPropertyValue('--carlos-bg-text--dark');
// const surfaceBorder = documentStyle.getPropertyValue('--surface-border');
const tickColor = chartJsGradient(
ticksGradient.value,
xTicksGradient,
[
0,
1,
],
);
const xAxis: TTimeAxisProps = {
x: {
Expand All @@ -48,26 +85,49 @@ const chartOptions = computed<DeepPartial<ChartOptions>>(() => {
unit: 'day',
},
ticks: {
color: textColorSecondary,
display: props.showXTicks,
color,
},
border: {
display: false,
color,
},
grid: {
color: surfaceBorder,
display: true,
drawOnChartArea: true,
drawTicks: true,
color: tickColor,
tickColor,
},
},
};
// explicitly set the color of the ticks and grid lines if not set in the props
const yAxis: TLineAxisProps = {};
Object.keys(props.yAxes).forEach((key, index) => {
Object.keys(props.yAxes).forEach((key) => {
const yAxisOverwrite: TLineAxisProps[string] = {
title: {
color: textColorSecondary,
display: true,
color,
},
ticks: {
color: textColorSecondary,
display: true,
color,
},
border: {
display: false,
color,
},
grid: {
drawOnChartArea: index === 0,
color: surfaceBorder,
display: false,
drawOnChartArea: true,
drawTicks: true,
color,
tickColor: color,
},
afterFit: (scale: Scale) => {
// This line ensures that all Y axis have the same width and
// therefore all charts are synchronized
scale.width = 60; // eslint-disable-line no-param-reassign
},
};
Expand All @@ -81,7 +141,21 @@ const chartOptions = computed<DeepPartial<ChartOptions>>(() => {
animation: {
duration: 0,
},
layout: {
padding: 0,
},
interaction: {
mode: 'x',
intersect: false,
},
hover: {
mode: 'x',
intersect: false,
},
plugins: {
tooltip: {
enabled: false,
},
legend: {
display: false,
},
Expand Down
Loading

0 comments on commit 7bcc5d5

Please sign in to comment.