Map Attributes: type 'string' layout done.
This commit is contained in:
@@ -1,12 +1,14 @@
|
|||||||
<template>
|
<template>
|
||||||
<section class="h-full">
|
<section class="h-full">
|
||||||
<p class="h2 ml-1 mb-2">Activity Select</p>
|
<p class="h2 ml-1 mb-2">Activity Select</p>
|
||||||
<!-- selectedAttName: {{ selectedAttName }} -->
|
<!-- selectedAttName: {{ selectedAttName }} <br>
|
||||||
<!-- selectedAttRange: {{ selectedAttRange }} -->
|
selectedAttRange: {{ selectedAttRange }} <br>
|
||||||
|
attRangeData: {{ attRangeData }} -->
|
||||||
|
|
||||||
<div class="flex flex-row justify-between items-start gap-4 w-full h-[calc(100%_-_48px)]">
|
<div class="flex flex-row justify-between items-start gap-4 w-full h-[calc(100%_-_48px)]">
|
||||||
<!-- Attribute Name -->
|
<!-- Attribute Name -->
|
||||||
<div class="basis-1/3 bg-neutral-10 border border-neutral-300 rounded-xl px-4 pb-4 w-full h-full relative text-sm">
|
<div class="basis-1/3 bg-neutral-10 border border-neutral-300 rounded-xl px-4 pb-4 w-full h-full relative text-sm">
|
||||||
<p class="h2 border-b border-500 my-2">Attribute Name (13)</p>
|
<p class="h2 border-b border-500 my-2">Attribute Name ({{ attTotal }})</p>
|
||||||
<div class="overflow-y-auto overflow-x-auto scrollbar -mx-2 h-[calc(100%_-_56px)]">
|
<div class="overflow-y-auto overflow-x-auto scrollbar -mx-2 h-[calc(100%_-_56px)]">
|
||||||
<DataTable v-model:selection="selectedAttName" :value="filterAttrs" dataKey="key" breakpoint="0" :tableClass="tableClass">
|
<DataTable v-model:selection="selectedAttName" :value="filterAttrs" dataKey="key" breakpoint="0" :tableClass="tableClass">
|
||||||
<Column selectionMode="single" :headerClass="headerModeClass" :bodyClass="bodyModeClass"></Column>
|
<Column selectionMode="single" :headerClass="headerModeClass" :bodyClass="bodyModeClass"></Column>
|
||||||
@@ -17,41 +19,42 @@
|
|||||||
<!-- Range Selection -->
|
<!-- Range Selection -->
|
||||||
<div class="basis-2/3 bg-neutral-10 border border-neutral-300 rounded-xl px-4 w-full h-full">
|
<div class="basis-2/3 bg-neutral-10 border border-neutral-300 rounded-xl px-4 w-full h-full">
|
||||||
<div class="flex justify-between items-center my-2 flex-wrap">
|
<div class="flex justify-between items-center my-2 flex-wrap">
|
||||||
<p class="h2">Range Selection</p>
|
<p class="h2">Range Selection {{ attRangeTotal }}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="overflow-y-auto overflow-x-auto scrollbar -mx-2 h-[calc(100%_-_70px)]">
|
<div class="overflow-y-auto overflow-x-auto scrollbar -mx-2 h-[calc(100%_-_70px)]">
|
||||||
|
<!-- type: boolean -->
|
||||||
<div v-if="selectedAttName?.type === 'boolean'">
|
<div v-if="selectedAttName?.type === 'boolean'">
|
||||||
<DataTable v-model:selection="selectedAttRange" :value="attRangeData" dataKey="id" breakpoint="0" :tableClass="tableClass" @row-select="onRowSelect">
|
<DataTable v-model:selection="selectedAttRange" :value="attRangeData" dataKey="id" breakpoint="0" :tableClass="tableClass" @row-select="onRowSelect">
|
||||||
<Column selectionMode="single" :headerClass="headerModeClass" :bodyClass="bodyModeClass"></Column>
|
<Column selectionMode="single" :headerClass="headerModeClass" :bodyClass="bodyModeClass"></Column>
|
||||||
<Column field="label" header="Activity" :headerClass="headerClass" :bodyClass="bodyClass"></Column>
|
<Column field="label" header="Activity" :headerClass="headerClass" :bodyClass="bodyClass"></Column>
|
||||||
</DataTable>
|
</DataTable>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- type: string -->
|
||||||
<div v-else-if="selectedAttName?.type === 'string'">
|
<div v-else-if="selectedAttName?.type === 'string'">
|
||||||
string
|
<DataTable v-model:selection="selectedAttRange" :value="attRangeData" dataKey="id" breakpoint="0" tableClass="w-full !border-separate !border-spacing-x-2 !table-auto text-sm" @row-select="onRowSelect">
|
||||||
|
<ColumnGroup type="header">
|
||||||
|
<Row>
|
||||||
|
<Column selectionMode="multiple" :headerClass="headerModeClass"></Column>
|
||||||
|
<Column field="value" header="Value" :headerClass="headerClass" sortable />
|
||||||
|
<Column field="freq" header="Occurrences" :headerClass="headerClass" sortable :colspan="3" />
|
||||||
|
</Row>
|
||||||
|
</ColumnGroup>
|
||||||
|
<Column selectionMode="multiple" :bodyClass="bodyModeClass"></Column>
|
||||||
|
<Column field="value" header="Activity" :bodyClass="bodyClass"></Column>
|
||||||
|
<Column header="進度條" bodyClass="!py-2 !border-0 min-w-[96px]">
|
||||||
|
<template #body="slotProps">
|
||||||
|
<div class="h-4 w-full bg-neutral-300 rounded-sm overflow-hidden">
|
||||||
|
<div class="h-full bg-primary" :style="progressWidth(slotProps.data.occ_progress_bar)"></div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</Column>
|
||||||
|
<Column field="occ_value" header="Occurrences" bodyClass="!text-right !py-2 !border-0"></Column>
|
||||||
|
<Column field="occ_ratio" header="Occurrence Ratio" bodyClass="!text-right !py-2 !border-0"></Column>
|
||||||
|
</DataTable>
|
||||||
</div>
|
</div>
|
||||||
<div v-else>
|
<div v-else>
|
||||||
other
|
other
|
||||||
</div>
|
</div>
|
||||||
<!-- <DataTable v-model:selection="selectedAttRange" :value="attRangeData" dataKey="label" breakpoint="0" tableClass="w-full !border-separate !border-spacing-x-2 !table-auto text-sm" @row-select="onRowSelect">
|
|
||||||
<ColumnGroup type="header">
|
|
||||||
<Row>
|
|
||||||
<Column selectionMode="single" headerClass="w-8 !p-2 !bg-neutral-10 !border-neutral-500 sticky top-0 left-0 z-10 bg-neutral-10"></Column>
|
|
||||||
<Column field="label" header="Activity" headerClass="!bg-neutral-10 !border-neutral-500 !py-2 sticky top-0 left-0 z-10 bg-neutral-10" sortable />
|
|
||||||
<Column field="occurrences_base" header="Occurrences" headerClass="!bg-neutral-10 !border-neutral-500 !py-2 sticky top-0 left-0 z-10 bg-neutral-10" sortable :colspan="3" />
|
|
||||||
</Row>
|
|
||||||
</ColumnGroup>
|
|
||||||
<Column selectionMode="single" bodyClass="!p-2 !border-0"></Column>
|
|
||||||
<Column field="label" header="Activity" bodyClass="break-words !py-2 !border-0"></Column>
|
|
||||||
<Column header="進度條" bodyClass="!py-2 !border-0 min-w-[96px]">
|
|
||||||
<template #body="slotProps">
|
|
||||||
<div class="h-4 w-full bg-neutral-300 rounded-sm overflow-hidden">
|
|
||||||
<div class="h-full bg-primary" :style="progressWidth(slotProps.data.occ_value)"></div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</Column>
|
|
||||||
<Column field="occurrences" header="Occurrences" bodyClass="!text-right !py-2 !border-0"></Column>
|
|
||||||
<Column field="occurrence_ratio" header="Occurrence Ratio" bodyClass="!text-right !py-2 !border-0"></Column>
|
|
||||||
</DataTable> -->
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -77,14 +80,24 @@ export default {
|
|||||||
headerClass: '!bg-neutral-10 !border-neutral-500 !py-2 sticky top-0 left-0 z-10 bg-neutral-10',
|
headerClass: '!bg-neutral-10 !border-neutral-500 !py-2 sticky top-0 left-0 z-10 bg-neutral-10',
|
||||||
bodyModeClass: '!p-2 !border-0',
|
bodyModeClass: '!p-2 !border-0',
|
||||||
bodyClass: 'break-words !py-2 !border-0',
|
bodyClass: 'break-words !py-2 !border-0',
|
||||||
|
valueTypes: ['int', 'float', 'date'],
|
||||||
|
classTypes: ['boolean', 'string'],
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
attTotal: function() {
|
||||||
|
return this.filterAttrs.length;
|
||||||
|
},
|
||||||
|
attRangeTotal: function() {
|
||||||
|
const type = this.selectedAttName?.type;
|
||||||
|
|
||||||
|
return !this.classTypes.includes(type) ? null
|
||||||
|
: this.attRangeData ? `(${this.attRangeData.length})`
|
||||||
|
: null;
|
||||||
|
},
|
||||||
attRangeData: function() {
|
attRangeData: function() {
|
||||||
let data = [];
|
let data = [];
|
||||||
const type = this.selectedAttName.type;
|
const type = this.selectedAttName?.type;
|
||||||
const valueTypes = ['int', 'float', 'date'];
|
|
||||||
const classTypes = ['boolean', 'string'];
|
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'boolean':
|
case 'boolean':
|
||||||
@@ -92,20 +105,37 @@ export default {
|
|||||||
{
|
{
|
||||||
id: 1,
|
id: 1,
|
||||||
key: this.selectedAttName.key,
|
key: this.selectedAttName.key,
|
||||||
type: 'boolean',
|
type: type,
|
||||||
value: true,
|
value: true,
|
||||||
label: 'Yes'
|
label: 'Yes'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 2,
|
id: 2,
|
||||||
key: this.selectedAttName.key,
|
key: this.selectedAttName.key,
|
||||||
type: 'boolean',
|
type: type,
|
||||||
value: false,
|
value: false,
|
||||||
label: 'No'
|
label: 'No'
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
return data;
|
return data;
|
||||||
|
case 'string':
|
||||||
|
let sum = this.selectedAttName.options.map(item => item.freq).reduce((acc, cur) => acc + cur, 0);
|
||||||
|
data = this.selectedAttName.options.map((item, index) => {
|
||||||
|
let result;
|
||||||
|
let ratio = item.freq / sum;
|
||||||
|
result = {
|
||||||
|
id: index + 1,
|
||||||
|
key: this.selectedAttName.key,
|
||||||
|
type: type,
|
||||||
|
value: item.value,
|
||||||
|
occ_progress_bar: ratio * 100,
|
||||||
|
occ_value: item.freq.toLocaleString('en-US'),
|
||||||
|
occ_ratio: this.getPercentLabel(ratio),
|
||||||
|
freq: item.freq
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
})
|
||||||
|
return data.sort((x, y) => y.freq - x.freq);
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -131,6 +161,15 @@ export default {
|
|||||||
progressWidth(value){
|
progressWidth(value){
|
||||||
return `width:${value}%;`
|
return `width:${value}%;`
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* Number to percentage
|
||||||
|
* @param {number} val
|
||||||
|
* @returns {string} 轉換完成的百分比字串
|
||||||
|
*/
|
||||||
|
getPercentLabel(val){
|
||||||
|
if((val * 100).toFixed(1) >= 100) return `100%`;
|
||||||
|
else return `${(val * 100).toFixed(1)}%`;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
Reference in New Issue
Block a user