Skip to content

Commit

Permalink
feat: add Display Series Label field (cloudforet-io#4495)
Browse files Browse the repository at this point in the history
* chore: fix minor in PSlider

Signed-off-by: yuda <[email protected]>

* chore: update language

Signed-off-by: yuda <[email protected]>

* feat: add `Display Series Label` field

Signed-off-by: yuda <[email protected]>

* chore: fix minor

Signed-off-by: yuda <[email protected]>

* fix: fix ordering bug in widgets

Signed-off-by: yuda <[email protected]>

---------

Signed-off-by: yuda <[email protected]>
  • Loading branch information
yuda110 authored Aug 8, 2024
1 parent c0abbf2 commit b363830
Show file tree
Hide file tree
Showing 15 changed files with 316 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import comparison from '@/common/modules/widgets/_widget-fields/WidgetFieldCompa
import dataField from '@/common/modules/widgets/_widget-fields/WidgetFieldDataField.vue';
import dateFormat from '@/common/modules/widgets/_widget-fields/WidgetFieldDateFormat.vue';
import displayAnnotation from '@/common/modules/widgets/_widget-fields/WidgetFieldDisplayAnnotation.vue';
import displaySeriesLabel from '@/common/modules/widgets/_widget-fields/WidgetFieldDisplaySeriesLabel.vue';
import formatRules from '@/common/modules/widgets/_widget-fields/WidgetFieldFormatRules.vue';
import granularity from '@/common/modules/widgets/_widget-fields/WidgetFieldGranularity.vue';
import groupBy from '@/common/modules/widgets/_widget-fields/WidgetFieldGroupBy.vue';
Expand Down Expand Up @@ -54,4 +55,5 @@ export const WIDGET_FIELD_COMPONENTS: Record<Partial<WidgetFieldName>, Component
dateFormat,
numberFormat,
displayAnnotation,
displaySeriesLabel,
};
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,6 @@ onMounted(() => {
.left {
flex-shrink: 0;
width: 10rem;
}
.compare-with {
Expand All @@ -274,7 +273,6 @@ onMounted(() => {
.left {
@apply flex gap-3;
flex-shrink: 0;
width: 10rem;
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
<script setup lang="ts">
import {
computed, onMounted, reactive, watch,
} from 'vue';
import {
PFieldGroup, PSelectDropdown, PFieldTitle, PToggleButton, PSlider,
} from '@cloudforet/mirinae';
import type { SelectDropdownMenuItem } from '@cloudforet/mirinae/types/inputs/dropdown/select-dropdown/type';
import { i18n } from '@/translations';
import { useProxyValue } from '@/common/composables/proxy-state';
import type {
WidgetFieldComponentProps,
WidgetFieldComponentEmit,
} from '@/common/modules/widgets/types/widget-field-type';
import type {
DisplaySeriesLabelValue,
} from '@/common/modules/widgets/types/widget-field-value-type';
const ROTATE_MIN = -90;
const ROTATE_MAX = 90;
const emit = defineEmits<WidgetFieldComponentEmit<DisplaySeriesLabelValue>>();
const props = defineProps<WidgetFieldComponentProps<undefined, DisplaySeriesLabelValue>>();
const state = reactive({
proxyValue: useProxyValue<DisplaySeriesLabelValue|undefined>('value', props, emit),
menuItems: computed<SelectDropdownMenuItem[]>(() => [
{ name: 'center', label: 'Center' },
{ name: 'left', label: 'Left' },
{ name: 'right', label: 'Right' },
]),
isRotateValid: computed<boolean>(() => {
if (!state.proxyValue?.toggleValue) return true;
if (state.proxyValue?.rotate === undefined) return false;
if (state.proxyValue.rotate < ROTATE_MIN || state.proxyValue.rotate > ROTATE_MAX) return false;
return true;
}),
rotateInvalidText: computed(() => {
if (!state.proxyValue?.toggleValue) return '';
if (state.proxyValue?.rotate === undefined) return '';
if (state.proxyValue.rotate < ROTATE_MIN) return i18n.t('COMMON.WIDGETS.DISPLAY_SERIES_LABEL.ROTATE_MIN_INVALID_TEXT');
if (state.proxyValue.rotate > ROTATE_MAX) return i18n.t('COMMON.WIDGETS.DISPLAY_SERIES_LABEL.ROTATE_MAX_INVALID_TEXT');
return '';
}),
isAllValid: computed(() => state.isRotateValid),
});
/* Util */
/* Event */
const handleUpdateToggle = (value: boolean) => {
if (!value) {
state.proxyValue = undefined;
return;
}
state.proxyValue = {
toggleValue: value,
position: 'center',
rotate: 0,
};
};
const handleSelectMenuItem = (selected: string) => {
state.proxyValue = {
...state.proxyValue,
position: selected,
};
};
const handleUpdateRotate = (value: number) => {
state.proxyValue = {
...state.proxyValue,
rotate: value,
};
};
/* Watcher */
watch(() => state.isAllValid, (_isAllValid) => {
emit('update:is-valid', _isAllValid);
}, { immediate: true });
onMounted(() => {
if (!props.value) {
state.proxyValue = undefined;
return;
}
state.proxyValue = {
toggleValue: props.value?.toggleValue ?? false,
position: props.value?.position ?? 'center',
rotate: props.value?.rotate ?? 0,
};
});
</script>

<template>
<div class="widget-field-display-series-label">
<div class="field-header">
<p-field-title>{{ $t('COMMON.WIDGETS.DISPLAY_SERIES_LABEL.DISPLAY_SERIES_LABEL') }}</p-field-title>
<p-toggle-button :value="state.proxyValue?.toggleValue"
@update:value="handleUpdateToggle"
/>
</div>
<div v-if="state.proxyValue?.toggleValue"
class="contents"
>
<p-field-group :label="$t('COMMON.WIDGETS.DISPLAY_SERIES_LABEL.POSITION')"
style-type="secondary"
>
<p-select-dropdown class="w-full"
use-fixed-menu-style
reset-selection-on-menu-close
:menu="state.menuItems"
:selected="state.proxyValue?.position"
@select="handleSelectMenuItem"
/>
</p-field-group>
<p-field-group :label="$t('COMMON.WIDGETS.DISPLAY_SERIES_LABEL.ROTATE')"
style-type="secondary"
:invalid="!state.isRotateValid"
:invalid-text="state.rotateInvalidText"
>
<p-slider :value="state.proxyValue?.rotate"
:min="-90"
:max="90"
show-input
@update:value="handleUpdateRotate"
/>
</p-field-group>
</div>
</div>
</template>

<style lang="postcss" scoped>
.widget-field-display-series-label {
.field-header {
@apply flex items-center gap-1 justify-between;
}
.contents {
display: flex;
flex-direction: column;
gap: 0.25rem;
margin-top: 0.5rem;
/* custom design-system component - p-field-group */
:deep(.p-field-group) {
.p-text-input {
width: 4rem;
}
}
}
}
</style>
Original file line number Diff line number Diff line change
Expand Up @@ -192,8 +192,9 @@ const getLineByData = (rawData: Data) => {
// slice lineByData by lineByCount
const _slicedByLineBy: any[] = [];
rawData.results?.forEach((d) => {
const _slicedData = orderBy(d[state.dataField], 'value', 'desc').slice(0, state.lineByCount);
const _etcData = d[state.dataField]?.slice(state.lineByCount).reduce((acc, v) => {
const _orderedData = orderBy(d[state.dataField], 'value', 'desc') ?? [];
const _slicedData = _orderedData.slice(0, state.lineByCount);
const _etcData = _orderedData.slice(state.lineByCount).reduce((acc, v) => {
acc[state.lineByField] = 'etc';
acc.value += v.value || 0;
return acc;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,6 @@ const state = reactive({
},
xAxis: {
type: 'category',
boundaryGap: false,
data: state.xAxisData,
axisLabel: {
formatter: (val) => {
Expand Down Expand Up @@ -193,8 +192,9 @@ const getLineByData = (rawData: Data) => {
// slice lineByData by lineByCount
const _slicedByLineBy: any[] = [];
rawData.results?.forEach((d) => {
const _slicedData = orderBy(d[state.dataField], 'value', 'desc').slice(0, state.lineByCount);
const _etcData = d[state.dataField]?.slice(state.lineByCount).reduce((acc, v) => {
const _orderedData = orderBy(d[state.dataField], 'value', 'desc') ?? [];
const _slicedData = _orderedData.slice(0, state.lineByCount);
const _etcData = _orderedData.slice(state.lineByCount).reduce((acc, v) => {
acc[state.lineByField] = 'etc';
acc.value += v.value || 0;
return acc;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -194,8 +194,9 @@ const drawChart = (rawData?: Data|null) => {
// slice stackByData by stackByCount
const _slicedByStackBy: any[] = [];
rawData.results?.forEach((d) => {
const _slicedData = orderBy(d[state.dataField], 'value', 'desc').slice(0, state.stackByCount);
const _etcData = d[state.dataField]?.slice(state.stackByCount).reduce((acc, v) => {
const _orderedData = orderBy(d[state.dataField], 'value', 'desc');
const _slicedData = _orderedData.slice(0, state.stackByCount);
const _etcData = _orderedData?.slice(state.stackByCount).reduce((acc, v) => {
acc[state.stackByField] = 'etc';
acc.value += v.value || 0;
return acc;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -193,8 +193,9 @@ const drawChart = (rawData?: Data|null) => {
// slice stackByData by stackByCount
const _slicedByStackBy: any[] = [];
rawData.results?.forEach((d) => {
const _slicedData = orderBy(d[state.dataField], 'value', 'desc').slice(0, state.stackByCount);
const _etcData = d[state.dataField]?.slice(state.stackByCount).reduce((acc, v) => {
const _orderedData = orderBy(d[state.dataField], 'value', 'desc') ?? [];
const _slicedData = _orderedData.slice(0, state.stackByCount);
const _etcData = _orderedData.slice(state.stackByCount).reduce((acc, v) => {
acc[state.stackByField] = 'etc';
acc.value += v.value || 0;
return acc;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,9 +145,9 @@ const fetchWidget = async (): Promise<Data|APIErrorToast|undefined> => {
};
const drawChart = (rawData: Data|null) => {
if (isEmpty(rawData)) return;
const _sortedData = orderBy(rawData.results, [state.dataField], ['desc']);
const _slicedData = _sortedData.slice(0, state.categoryByCount);
const _etcValue = _sortedData.slice(state.categoryByCount).reduce((acc, v) => acc + v[state.dataField], 0);
const _orderedData = orderBy(rawData.results, [state.dataField], ['desc']);
const _slicedData = _orderedData.slice(0, state.categoryByCount);
const _etcValue = _orderedData.slice(state.categoryByCount).reduce((acc, v) => acc + v[state.dataField], 0);
const _etcData = _etcValue ? {
[state.categoryByField]: 'etc',
[state.dataField]: _etcValue,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,8 @@ export type WidgetFieldName = 'dataField' | 'tableDataField' | 'xAxis' | 'yAxis'
| 'progressBar'
| 'formatRules'
| 'granularity' | 'colorSchema' | 'pieChartType'
| 'widgetHeader' | 'dateFormat' | 'numberFormat' | 'displayAnnotation';
| 'widgetHeader' | 'dateFormat' | 'numberFormat'
| 'displayAnnotation' | 'displaySeriesLabel';

export interface WidgetFieldComponentProps<FieldOptions, FieldValue = any> {
dataTable?: PublicDataTableModel|PrivateDataTableModel;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,14 @@ export interface DisplayAnnotationValue {
annotation?: string;
}

export interface DisplaySeriesLabelValue {
toggleValue: boolean;
position?: 'left' | 'center' | 'right';
rotate?: number;
}

export type WidgetFieldValues = string | string[] | number | boolean | ComparisonValue[] | ProgressBarValue | FormatRulesValue[]
| LineByValue | StackByValue | CategoryByValue | GroupByValue
| XAxisValue | YAxisValue | TableDataFieldValue | IconValue | TotalValue | ColorSchemaValue
| WidgetHeaderValue | DateFormatValue | NumberFormatValue | DisplayAnnotationValue;
| WidgetHeaderValue | DateFormatValue | NumberFormatValue
| DisplayAnnotationValue | DisplaySeriesLabelValue;
110 changes: 110 additions & 0 deletions packages/language-pack/console-translation-2.8.babel
Original file line number Diff line number Diff line change
Expand Up @@ -26759,6 +26759,116 @@
</concept_node>
</children>
</folder_node>
<folder_node>
<name>DISPLAY_SERIES_LABEL</name>
<children>
<concept_node>
<name>DISPLAY_SERIES_LABEL</name>
<definition_loaded>false</definition_loaded>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>ja-JP</language>
<approved>false</approved>
</translation>
<translation>
<language>ko-KR</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>POSITION</name>
<definition_loaded>false</definition_loaded>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>ja-JP</language>
<approved>false</approved>
</translation>
<translation>
<language>ko-KR</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>ROTATE</name>
<definition_loaded>false</definition_loaded>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>ja-JP</language>
<approved>false</approved>
</translation>
<translation>
<language>ko-KR</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>ROTATE_MAX_INVALID_TEXT</name>
<definition_loaded>false</definition_loaded>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>ja-JP</language>
<approved>false</approved>
</translation>
<translation>
<language>ko-KR</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>ROTATE_MIN_INVALID_TEXT</name>
<definition_loaded>false</definition_loaded>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>ja-JP</language>
<approved>false</approved>
</translation>
<translation>
<language>ko-KR</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
</children>
</folder_node>
<concept_node>
<name>DONE</name>
<definition_loaded>false</definition_loaded>
Expand Down
Loading

0 comments on commit b363830

Please sign in to comment.