Add JSDoc documentation and file headers to all source files

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-06 18:55:36 +08:00
parent 3b7b6ae859
commit 7fec6cb63f
199 changed files with 2764 additions and 503 deletions

View File

@@ -30,6 +30,16 @@
</template>
<script setup>
// The Lucia project.
// Copyright 2024-2026 DSP, inc. All rights reserved.
// Authors:
// cindy.chang@dsp.im (Cindy Chang), 2024/5/30
// imacat.yang@dsp.im (imacat), 2023/9/23
/**
* @module components/AccountMenu/AcctMenu Dropdown account menu
* with links to account management, my account, and logout.
*/
import { computed, onMounted, ref } from 'vue';
import { storeToRefs } from 'pinia';
import i18next from '@/i18n/i18n';
@@ -58,6 +68,7 @@ const loginUserData = ref(null);
const currentViewingUserDetail = computed(() => acctMgmtStore.currentViewingUser.detail);
const isAdmin = ref(false);
/** Fetches user data and determines if the current user is an admin. */
const getIsAdminValue = async () => {
await loginStore.getUserData();
loginUserData.value = loginStore.userData;
@@ -65,6 +76,7 @@ const getIsAdminValue = async () => {
isAdmin.value = acctMgmtStore.currentViewingUser.is_admin;
};
/** Navigates to the My Account page. */
const onBtnMyAccountClick = async () => {
acctMgmtStore.closeAcctMenu();
await acctMgmtStore.getAllUserAccounts(); // in case we haven't fetched yet
@@ -72,6 +84,7 @@ const onBtnMyAccountClick = async () => {
await router.push('/my-account');
};
/** Registers a click listener to close the menu when clicking outside. */
const clickOtherPlacesThenCloseMenu = () => {
const acctMgmtButton = document.getElementById('acct_mgmt_button');
const acctMgmtMenu = document.getElementById('account_menu');
@@ -83,11 +96,13 @@ const clickOtherPlacesThenCloseMenu = () => {
});
};
/** Navigates to the Account Admin page. */
const onBtnAcctMgmtClick = () => {
router.push({name: 'AcctAdmin'});
acctMgmtStore.closeAcctMenu();
};
/** Handles logout with unsaved-changes confirmation for Map and Conformance pages. */
const onLogoutBtnClick = () => {
if ((route.name === 'Map' || route.name === 'CheckMap') && tempFilterId.value) {
// 傳給 Map通知 Sidebar 要關閉。

View File

@@ -10,6 +10,16 @@
</template>
<script setup>
// The Lucia project.
// Copyright 2024-2026 DSP, inc. All rights reserved.
// Authors:
// cindy.chang@dsp.im (Cindy Chang), 2024/5/30
// imacat.yang@dsp.im (imacat), 2023/9/23
/**
* @module components/AccountMenu/SearchBar Search input bar for
* filtering accounts, emits search query on click or Enter key.
*/
import { ref } from 'vue';
import i18next from '@/i18n/i18n.js';
@@ -17,11 +27,19 @@ const emit = defineEmits(['on-search-account-button-click']);
const inputQuery = ref("");
/**
* Emits the search query when the search icon is clicked.
* @param {Event} event - The click event.
*/
const onSearchClick = (event) => {
event.preventDefault();
emit('on-search-account-button-click', inputQuery.value);
};
/**
* Emits the search query when Enter key is pressed.
* @param {KeyboardEvent} event - The keypress event.
*/
const handleKeyPressOfSearch = (event) => {
if (event.key === 'Enter') {
emit('on-search-account-button-click', inputQuery.value);

View File

@@ -13,6 +13,16 @@
</template>
<script setup>
// The Lucia project.
// Copyright 2024-2026 DSP, inc. All rights reserved.
// Authors:
// cindy.chang@dsp.im (Cindy Chang), 2024/5/30
// imacat.yang@dsp.im (imacat), 2023/9/23
/**
* @module components/Badge Status badge component that displays
* an activated/deactivated state with colored background.
*/
defineProps({
isActivated: {
type: Boolean,

View File

@@ -16,6 +16,16 @@
</template>
<script setup>
// The Lucia project.
// Copyright 2024-2026 DSP, inc. All rights reserved.
// Authors:
// cindy.chang@dsp.im (Cindy Chang), 2024/5/30
// imacat.yang@dsp.im (imacat), 2023/9/23
/**
* @module components/Button Outlined button component with
* press-state ring effect.
*/
import { ref } from 'vue';
defineProps({

View File

@@ -17,6 +17,16 @@
</template>
<script setup>
// The Lucia project.
// Copyright 2024-2026 DSP, inc. All rights reserved.
// Authors:
// cindy.chang@dsp.im (Cindy Chang), 2024/5/30
// imacat.yang@dsp.im (imacat), 2023/9/23
/**
* @module components/ButtonFilled Filled button component with
* solid background and press-state ring effect.
*/
import { ref } from 'vue';
defineProps({

View File

@@ -147,6 +147,17 @@
</Sidebar>
</template>
<script setup>
// The Lucia project.
// Copyright 2024-2026 DSP, inc. All rights reserved.
// Authors:
// chiayin.kuo@dsp.im (chiayin), 2023/1/31
// imacat.yang@dsp.im (imacat), 2023/9/23
/**
* @module components/Compare/SidebarStates Summary sidebar for
* the Compare view showing side-by-side statistics (cases,
* traces, activities, timeframes, durations) of two files.
*/
import { ref, onMounted } from 'vue';
import { useRoute } from 'vue-router';
import { useCompareStore } from '@/stores/compare';
@@ -175,9 +186,9 @@ const primaryStatData = ref(null);
const secondaryStatData = ref(null);
/**
* Number to percentage
* @param {number} val 原始數字
* @returns {string} 轉換完成的百分比字串
* Converts a ratio (01) to a percentage number (0100), capped at 100.
* @param {number} val - The ratio value to convert.
* @returns {number} The percentage value.
*/
const getPercentLabel = (val) => {
if((val * 100).toFixed(1) >= 100) return 100;
@@ -185,10 +196,10 @@ const getPercentLabel = (val) => {
};
/**
* setting stats data
* @param { object } data fetch API stats data
* @param { string } fileName file Name
* @returns { object } primaryStatData | secondaryStatData回傳 primaryStatData 或 secondaryStatData
* Transforms raw API stats into display-ready stat data.
* @param {Object} data - The raw stats from the API.
* @param {string} fileName - The file name to display.
* @returns {Object} The formatted stat data object.
*/
const getStatData = (data, fileName) => {
return {
@@ -224,9 +235,7 @@ const getStatData = (data, fileName) => {
}
};
/**
* Behavior when show
*/
/** Populates progress bar values when the sidebar is shown. */
const show = () => {
primaryValueCases.value = primaryStatData.value.cases.ratio;
primaryValueTraces.value = primaryStatData.value.traces.ratio;
@@ -238,9 +247,7 @@ const show = () => {
secondaryValueTasks.value = secondaryStatData.value.tasks.ratio;
};
/**
* Behavior when hidden
*/
/** Resets all progress bar values to zero when the sidebar is hidden. */
const hide = () => {
primaryValueCases.value = 0;
primaryValueTraces.value = 0;

View File

@@ -192,6 +192,18 @@
</section>
</template>
<script setup>
// The Lucia project.
// Copyright 2023-2026 DSP, inc. All rights reserved.
// Authors:
// chiayin.kuo@dsp.im (chiayin), 2023/1/31
// cindy.chang@dsp.im (Cindy Chang), 2024/5/30
// imacat.yang@dsp.im (imacat), 2023/9/23
/**
* @module components/Discover/Conformance/ConformanceResults
* Conformance checking results panel displaying rule
* check outcomes in a data table with status indicators.
*/
import { ref, watch } from 'vue';
import { storeToRefs } from 'pinia';
import { useConformanceStore } from '@/stores/conformance';
@@ -274,8 +286,8 @@ const tooltip = ref({
/**
* set progress bar width
* @param {number} value 百分比數字
* @returns {string} 樣式的寬度設定
* @param {number} value - The percentage value.
* @returns {string} The CSS width style string.
*/
const progressWidth = (value) => {
return `width:${value}%;`
@@ -283,8 +295,8 @@ const progressWidth = (value) => {
/**
* Number to percentage
* @param {number} val 原始數字
* @returns {string} 轉換完成的百分比字串
* @param {number} val - The raw ratio value.
* @returns {string} The formatted percentage string.
*/
const getPercentLabel = (val) => {
if((val * 100).toFixed(1) >= 100) return 100;
@@ -293,7 +305,7 @@ const getPercentLabel = (val) => {
/**
* Convert seconds to days
* @param {number} sec 秒數
* @param {number} sec - The number of seconds.
* @returns {number} day
*/
const convertSecToDay = (sec) => {
@@ -302,7 +314,7 @@ const convertSecToDay = (sec) => {
/**
* Open Issues Modal.
* @param {number} no trace 編號
* @param {number} no - The trace number.
*/
const openMore = async (no) => {
// async await 解決非同步資料延遲傳遞導致未讀取到而出錯的問題
@@ -315,7 +327,7 @@ const openMore = async (no) => {
/**
* Open Loop Modal.
* @param {number} no trace 編號
* @param {number} no - The trace number.
*/
const openLoopMore = async (no) => {
// async await 解決非同步資料延遲傳遞導致未讀取到而出錯的問題
@@ -328,7 +340,7 @@ const openLoopMore = async (no) => {
/**
* set conformance report data
* @param {object} data new watch's value 監聽到後端傳來的報告 data
* @param {object} data - The report data received from the backend.
*/
const setConformanceTempReportData = (newData) => {
const total = getNumberLabel(Object.values(newData.counts).reduce((acc, val) => acc + val, 0));

View File

@@ -122,6 +122,19 @@
</template>
<script setup>
// The Lucia project.
// Copyright 2023-2026 DSP, inc. All rights reserved.
// Authors:
// chiayin.kuo@dsp.im (chiayin), 2023/1/31
// imacat.yang@dsp.im (imacat), 2023/9/23
// cindy.chang@dsp.im (Cindy Chang), 2024/5/30
/**
* @module components/Discover/Conformance/ConformanceSidebar
* Main sidebar for conformance checking with rule
* configuration, activity selection, and submit/reset
* actions.
*/
import { ref, computed, watch, onBeforeUnmount } from 'vue';
import { storeToRefs } from 'pinia';
import { useToast } from 'vue-toast-notification';
@@ -622,14 +635,14 @@ watch(conformanceTempReportData, (newValue) => {
// methods
/**
* get min total seconds
* @param {Number} e 最小值總秒數
* @param {number} e - The minimum total seconds.
*/
function minTotalSeconds(e) {
selectTimeRangeMin.value = e;
}
/**
* get min total seconds
* @param {Number} e 最大值總秒數
* @param {number} e - The maximum total seconds.
*/
function maxTotalSeconds(e) {
selectTimeRangeMax.value = e;
@@ -715,7 +728,7 @@ function isSubmitReset() {
isSubmitTimeCfmCtEteSE.value = { base: {}, rule: {}};
}
/**
* 清空選單的行為
* Clears all form selections and resets the sidebar state.
*/
function reset() {
// Results page Cover Plate(遮罩為 ture)
@@ -733,7 +746,7 @@ function reset() {
isShowBarOpen.value = true;
}
/**
* 設定 Start & End Data 連動資料
* Sets linked Start & End data for activity selection.
* @param {string} start task
* @param {string} end task
* @returns {object}
@@ -758,7 +771,7 @@ function setSubmitShowDataByStartEnd(start, end) {
}
}
/**
* Apply button 發送選項,取得 Check Id.
* Submits the selected options via the Apply button and retrieves the Check ID.
*/
async function submitConformance() {
let dataToSave;
@@ -810,6 +823,9 @@ async function submitConformance() {
$toast.success(i18next.t("Conformance.RuleApplied"));
}
/** Builds the data payload for the 'Have activity' rule.
* @returns {object} The rule data to submit.
*/
function getHaveActivityData() {
const dataToSave = {
type: 'contains-tasks',
@@ -820,6 +836,9 @@ function getHaveActivityData() {
return dataToSave;
}
/** Builds the data payload for the 'Activity sequence' rule.
* @returns {object} The rule data to submit.
*/
function getActivitySequenceData() {
let dataToSave;
switch (selectedActivitySequence.value) {
@@ -843,6 +862,9 @@ function getActivitySequenceData() {
return dataToSave;
}
/** Builds the data payload for sequence sub-rules.
* @returns {object} The rule data to submit.
*/
function getSequenceData() {
let dataToSave;
switch (selectedMode.value) {
@@ -872,6 +894,9 @@ function getSequenceData() {
return dataToSave;
}
/** Builds the data payload for the 'Activity duration' rule.
* @returns {object} The rule data to submit.
*/
function getActivityDurationData() {
const dataToSave = {
type: 'task-duration',
@@ -885,6 +910,9 @@ function getActivityDurationData() {
return dataToSave;
}
/** Builds the data payload for the 'Processing time' rule.
* @returns {object} The rule data to submit.
*/
function getProcessingTimeData() {
let dataToSave;
switch (selectedProcessScope.value) {
@@ -898,6 +926,9 @@ function getProcessingTimeData() {
return dataToSave;
}
/** Builds end-to-end processing time rule data.
* @returns {object} The rule data to submit.
*/
function getEndToEndProcessingTimeData() {
let dataToSave;
switch (selectedActSeqMore.value) {
@@ -952,6 +983,9 @@ function getEndToEndProcessingTimeData() {
return dataToSave;
}
/** Builds partial processing time rule data.
* @returns {object} The rule data to submit.
*/
function getPartialProcessingTimeData() {
let dataToSave;
switch (selectedActSeqFromTo.value) {
@@ -997,6 +1031,9 @@ function getPartialProcessingTimeData() {
return dataToSave;
}
/** Builds the data payload for the 'Waiting time' rule.
* @returns {object} The rule data to submit.
*/
function getWaitingTimeData() {
let dataToSave;
switch (selectedProcessScope.value) {
@@ -1010,6 +1047,9 @@ function getWaitingTimeData() {
return dataToSave;
}
/** Builds end-to-end waiting time rule data.
* @returns {object} The rule data to submit.
*/
function getEndToEndWaitingTimeData() {
let dataToSave;
switch (selectedActSeqMore.value) {
@@ -1064,6 +1104,9 @@ function getEndToEndWaitingTimeData() {
return dataToSave;
}
/** Builds partial waiting time rule data.
* @returns {object} The rule data to submit.
*/
function getPartialWaitingTimeData() {
let dataToSave;
switch (selectedActSeqFromTo.value) {
@@ -1109,6 +1152,9 @@ function getPartialWaitingTimeData() {
return dataToSave;
}
/** Builds the data payload for the 'Cycle time' rule.
* @returns {object} The rule data to submit.
*/
function getCycleTimeData() {
let dataToSave;
switch (selectedActSeqMore.value) {
@@ -1164,7 +1210,7 @@ function getCycleTimeData() {
}
/**
* 設置根據類別的任務選擇邏輯
* Sets up category-based task selection logic.
*/
function setTaskByCategoryOnRadioEmitting() {
emitter.on('actRadioData', (data) => {
@@ -1201,6 +1247,10 @@ function setTaskByCategoryOnRadioEmitting() {
});
}
/**
* Handles start task selection for activity sequence.
* @param {string} task - The selected task.
*/
function handleCfmSeqStart(task) {
if (isStartSelected.value && task !== selectCfmSeqStart.value) {
selectCfmSeqEnd.value = null;
@@ -1208,6 +1258,10 @@ function handleCfmSeqStart(task) {
selectCfmSeqStart.value = task;
}
/**
* Handles end task selection for activity sequence.
* @param {string} task - The selected task.
*/
function handleCfmSeqEnd(task) {
if (isEndSelected.value && task !== selectCfmSeqEnd.value) {
selectCfmSeqStart.value = null;
@@ -1215,64 +1269,109 @@ function handleCfmSeqEnd(task) {
selectCfmSeqEnd.value = task;
}
/**
* Sets a simple task selection on a ref field.
* @param {object} field - The ref to set.
* @param {string} task - The selected task.
*/
function handleSimpleSelection(field, task) {
selectFieldRefs[field].value = task;
}
/**
* Handles start task for end-to-end processing time.
* @param {string} task - The selected task.
*/
function handleCfmPtEteSEStart(task) {
if (isStartSelected.value && task !== selectCfmPtEteSEStart.value) {
selectCfmPtEteSEEnd.value = null;
}
selectCfmPtEteSEStart.value = task;
}
/**
* Handles end task for end-to-end processing time.
* @param {string} task - The selected task.
*/
function handleCfmPtEteSEEnd(task) {
if (isEndSelected.value && task !== selectCfmPtEteSEEnd.value) {
selectCfmPtEteSEStart.value = null;
}
selectCfmPtEteSEEnd.value = task;
}
/**
* Handles start task for partial processing time.
* @param {string} task - The selected task.
*/
function handleCfmPtPSEStart(task) {
if (isStartSelected.value && task !== selectCfmPtPSEStart.value) {
selectCfmPtPSEEnd.value = null;
}
selectCfmPtPSEStart.value = task;
}
/**
* Handles end task for partial processing time.
* @param {string} task - The selected task.
*/
function handleCfmPtPSEEnd(task) {
if (isEndSelected.value && task !== selectCfmPtPSEEnd.value) {
selectCfmPtPSEStart.value = null;
}
selectCfmPtPSEEnd.value = task;
}
/**
* Handles start task for end-to-end waiting time.
* @param {string} task - The selected task.
*/
function handleCfmWtEteSEStart(task) {
if (isStartSelected.value && task !== selectCfmWtEteSEStart.value) {
selectCfmWtEteSEEnd.value = null;
}
selectCfmWtEteSEStart.value = task;
}
/**
* Handles end task for end-to-end waiting time.
* @param {string} task - The selected task.
*/
function handleCfmWtEteSEEnd(task) {
if (isEndSelected.value && task !== selectCfmWtEteSEEnd.value) {
selectCfmWtEteSEStart.value = null;
}
selectCfmWtEteSEEnd.value = task;
}
/**
* Handles start task for partial waiting time.
* @param {string} task - The selected task.
*/
function handleCfmWtPSEStart(task) {
if (isStartSelected.value && task !== selectCfmWtPSEStart.value) {
selectCfmWtPSEEnd.value = null;
}
selectCfmWtPSEStart.value = task;
}
/**
* Handles end task for partial waiting time.
* @param {string} task - The selected task.
*/
function handleCfmWtPSEEnd(task) {
if (isEndSelected.value && task !== selectCfmWtPSEEnd.value) {
selectCfmWtPSEStart.value = null;
}
selectCfmWtPSEEnd.value = task;
}
/**
* Handles start task for end-to-end cycle time.
* @param {string} task - The selected task.
*/
function handleCfmCtEteSEStart(task) {
if (isStartSelected.value && task !== selectCfmCtEteSEStart.value) {
selectCfmCtEteSEEnd.value = null;
}
selectCfmCtEteSEStart.value = task;
}
/**
* Handles end task for end-to-end cycle time.
* @param {string} task - The selected task.
*/
function handleCfmCtEteSEEnd(task) {
if (isEndSelected.value && task !== selectCfmCtEteSEEnd.value) {
selectCfmCtEteSEStart.value = null;
@@ -1280,6 +1379,7 @@ function handleCfmCtEteSEEnd(task) {
selectCfmCtEteSEEnd.value = task;
}
/** Sets task data when the list sequence emits a change. */
function setTaskByCategoryOnListSeqEmitting(){
emitter.on('getListSequence', (data) => {
switch (data.category) {
@@ -1295,15 +1395,21 @@ function setTaskByCategoryOnListSeqEmitting(){
});
}
/** Checks if the 'Have activity' rule has valid selections.
* @returns {boolean} Whether the button should be disabled.
*/
function checkHaveActivity() {
return !(selectConformanceTask.value?.length);
}
/** Checks if the 'Activity duration' rule has valid selections.
* @returns {boolean} Whether the button should be disabled.
*/
function checkActivityDuration() {
return !selectDurationData.value?.length;
}
/**
* 檢查活動序列的邏輯
* @returns {boolean} 是否禁用按鈕
* Checks the activity sequence logic.
* @returns {boolean} Whether the button should be disabled.
*/
function checkActivitySequence() {
switch (selectedActivitySequence.value) {
@@ -1316,15 +1422,18 @@ function checkActivitySequence() {
}
}
/**
* 檢查 Start & End 活動序列
* @param {string} start 活動開始
* @param {string} end 活動結束
* @returns {boolean} 是否禁用按鈕
* Checks the Start & End activity sequence.
* @param {string} start - The start activity.
* @param {string} end - The end activity.
* @returns {boolean} Whether the button should be disabled.
*/
function checkStartAndEndSequence(start, end) {
return !(start && end);
}
/** Checks if the 'Processing time' rule has valid selections.
* @returns {boolean} Whether the button should be disabled.
*/
function checkProcessingTime() {
let disabled = true;
switch (selectedProcessScope.value) {
@@ -1339,6 +1448,9 @@ function checkProcessingTime() {
}
return disabled;
}
/** Checks end-to-end scope selections.
* @returns {boolean} Whether the button should be disabled.
*/
function checkEndToEnd() {
let disabled = true;
switch (selectedActSeqMore.value) {
@@ -1362,6 +1474,9 @@ function checkEndToEnd() {
}
return disabled;
}
/** Checks partial scope selections.
* @returns {boolean} Whether the button should be disabled.
*/
function checkPartial() {
let disabled = true;
switch (selectedActSeqFromTo.value) {

View File

@@ -10,6 +10,16 @@
</div>
</template>
<script setup>
// The Lucia project.
// Copyright 2023-2026 DSP, inc. All rights reserved.
// Authors:
// chiayin.kuo@dsp.im (chiayin), 2023/1/31
// imacat.yang@dsp.im (imacat), 2023/9/23
/**
* @module components/Discover/Conformance/ConformanceSidebar/ActList
* Checkbox-based activity list for conformance checking input.
*/
import { ref, watch } from 'vue';
import { sortNumEngZhtw } from '@/module/sortNumEngZhtw.js';
import emitter from '@/utils/emitter';
@@ -27,9 +37,7 @@ watch(() => props.select, (newValue) => {
actList.value = newValue;
});
/**
* 將選取的 Activities 傳出去
*/
/** Emits the selected activities list via the event bus. */
function actListData() {
emitter.emit('actListData', actList.value);
}

View File

@@ -10,6 +10,18 @@
</div>
</template>
<script setup>
// The Lucia project.
// Copyright 2023-2026 DSP, inc. All rights reserved.
// Authors:
// chiayin.kuo@dsp.im (chiayin), 2023/1/31
// cindy.chang@dsp.im (Cindy Chang), 2024/5/30
// imacat.yang@dsp.im (imacat), 2023/9/23
/**
* @module components/Discover/Conformance/ConformanceSidebar/ActRadio
* Radio-button activity selector for conformance checking
* start/end activity input.
*/
import { ref, computed, watch } from 'vue';
import { useConformanceInputStore } from "@/stores/conformanceInput";
import { sortNumEngZhtw } from '@/module/sortNumEngZhtw.js';
@@ -37,9 +49,7 @@ const inputActivityRadioData = computed(() => ({
task: selectedRadio.value,
}));
/**
* 將選取的 Activity 傳出去
*/
/** Emits the selected activity via event bus and updates the store. */
function actRadioData() {
localSelect.value = null;
emitter.emit('actRadioData', inputActivityRadioData.value);
@@ -47,6 +57,7 @@ function actRadioData() {
conformanceInputStore.setActivityRadioStartEndData(inputActivityRadioData.value.task);
}
/** Sets the global activity radio data state in the conformance input store. */
function setGlobalActivityRadioDataState() {
//this.title: value might be "From" or "To"
conformanceInputStore.setActivityRadioStartEndData(inputActivityRadioData.value.task, props.title);

View File

@@ -42,6 +42,18 @@
</div>
</template>
<script setup>
// The Lucia project.
// Copyright 2023-2026 DSP, inc. All rights reserved.
// Authors:
// chiayin.kuo@dsp.im (chiayin), 2023/1/31
// cindy.chang@dsp.im (Cindy Chang), 2024/5/30
// imacat.yang@dsp.im (imacat), 2023/9/23
/**
* @module components/Discover/Conformance/ConformanceSidebar/ActSeqDrag
* Drag-and-drop activity sequence builder for
* conformance rule configuration.
*/
import { ref, computed } from 'vue';
import { sortNumEngZhtw } from '@/module/sortNumEngZhtw.js';
import emitter from '@/utils/emitter';

View File

@@ -51,6 +51,17 @@
</section>
</template>
<script setup>
// The Lucia project.
// Copyright 2023-2026 DSP, inc. All rights reserved.
// Authors:
// chiayin.kuo@dsp.im (chiayin), 2023/1/31
// imacat.yang@dsp.im (imacat), 2023/9/23
/**
* @module components/Discover/Conformance/ConformanceSidebar/ConformanceRadioGroup
* Radio button groups for conformance rule type, activity
* sequence, mode, and process scope selection.
*/
import { storeToRefs } from 'pinia';
import { useConformanceStore } from '@/stores/conformance';
import emitter from '@/utils/emitter';
@@ -92,9 +103,7 @@ const actSeqFromTo = [
{id: 3, name: 'From & To'},
];
/**
* 切換 Rule Type 的選項時的行為
*/
/** Resets dependent selections when the rule type radio changes. */
function changeRadio() {
selectedActivitySequence.value = 'Start & End';
selectedMode.value = 'Directly follows';
@@ -103,27 +112,19 @@ function changeRadio() {
selectedActSeqFromTo.value = 'From';
emitter.emit('isRadioChange', true); // Radio 切換時,資料要清空
}
/**
* 切換 Activity sequence 的選項時的行為
*/
/** Emits event when the activity sequence radio changes. */
function changeRadioSeq() {
emitter.emit('isRadioSeqChange',true);
}
/**
* 切換 Processing time 的選項時的行為
*/
/** Emits event when the process scope radio changes. */
function changeRadioProcessScope() {
emitter.emit('isRadioProcessScopeChange', true);
}
/**
* 切換 Process Scope 的選項時的行為
*/
/** Emits event when the extended activity sequence radio changes. */
function changeRadioActSeqMore() {
emitter.emit('isRadioActSeqMoreChange', true);
}
/**
* 切換 Activity Sequence 的選項時的行為
*/
/** Emits event when the from/to activity sequence radio changes. */
function changeRadioActSeqFromTo() {
emitter.emit('isRadioActSeqFromToChange', true);
}

View File

@@ -29,6 +29,18 @@
</div>
</template>
<script setup>
// The Lucia project.
// Copyright 2023-2026 DSP, inc. All rights reserved.
// Authors:
// chiayin.kuo@dsp.im (chiayin), 2023/1/31
// cindy.chang@dsp.im (Cindy Chang), 2024/5/30
// imacat.yang@dsp.im (imacat), 2023/9/23
/**
* @module components/Discover/Conformance/ConformanceSidebar/ConformanceSelectResult
* Conformance result list with selectable items and
* scrollable display of check results.
*/
import { reactive, computed } from 'vue';
import { storeToRefs } from 'pinia';
import { useConformanceStore } from '@/stores/conformance';

View File

@@ -98,6 +98,18 @@
</section>
</template>
<script setup>
// The Lucia project.
// Copyright 2023-2026 DSP, inc. All rights reserved.
// Authors:
// chiayin.kuo@dsp.im (chiayin), 2023/1/31
// cindy.chang@dsp.im (Cindy Chang), 2024/5/30
// imacat.yang@dsp.im (imacat), 2023/9/23
/**
* @module components/Discover/Conformance/ConformanceSidebar/ConformanceShowBar
* Horizontal bar chart component displaying conformance
* check result statistics.
*/
import { ref, computed, watch } from 'vue';
import { storeToRefs } from 'pinia';
import { useLoadingStore } from '@/stores/loading';
@@ -239,10 +251,9 @@ watch(() => props.isSubmitShowDataCt, (newValue) => {
});
/**
* 設定 start and end 的 Radio Data
* @param {object} data cfmSeqStart | cfmSeqEnd | cfmPtEteSE | cfmPtPSE | cfmWtEteSE | cfmWtPSE | cfmCtEteSE
* 傳入以上任一後端接到的 Activities 列表 Data。
* @param {string} category 'start' | 'end',傳入 'start' 或 'end'。
* Sets the start and end radio data.
* @param {object} data - Activities list data from the backend (cfmSeqStart, cfmSeqEnd, cfmPtEteSE, etc.).
* @param {string} category - 'start' or 'end'.
* @returns {array}
*/
function setTaskData(data, category) {
@@ -251,11 +262,10 @@ function setTaskData(data, category) {
return newData;
}
/**
* 重新設定連動的 start and end 的 Radio Data
* @param {object} data cfmPtEteSE | cfmPtPSE | cfmWtEteSE | cfmWtPSE | cfmCtEteSE
* 傳入以上任一後端接到的 Activities 列表 Data。
* @param {string} category 'start' | 'end',傳入 'start' 或 'end'。
* @param {string} task 已選擇的 Activity task
* Resets the linked start and end radio data.
* @param {object} data - Activities list data from the backend (cfmPtEteSE, cfmPtPSE, etc.).
* @param {string} category - 'start' or 'end'.
* @param {string} task - The selected activity task.
* @returns {array}
*/
function setStartAndEndData(data, category, taskVal) {
@@ -270,10 +280,10 @@ function setStartAndEndData(data, category, taskVal) {
return newData;
}
/**
* 重新設定 Activity sequence 連動的 start and end 的 Radio Data
* @param {object} data cfmSeqStart | cfmSeqEnd,傳入以上任一後端接到的 Activities 列表 Data。
* @param {string} category 'sources' | 'sinks',傳入 'sources' 或 'sinks'
* @param {string} task 已選擇的 Activity task
* Resets the activity sequence linked start and end radio data.
* @param {object} data - Activities list data from the backend (cfmSeqStart or cfmSeqEnd).
* @param {string} category - 'sources' or 'sinks'.
* @param {string} task - The selected activity task.
* @returns {array}
*/
function setSeqStartAndEndData(data, category, taskVal) {
@@ -283,7 +293,7 @@ function setSeqStartAndEndData(data, category, taskVal) {
}
/**
* select start list's task
* @param {event} e 觸發 input 的詳細事件
* @param {Event} e - The input event.
*/
function selectStart(e) {
taskStart.value = e;
@@ -300,7 +310,7 @@ function selectStart(e) {
}
/**
* select End list's task
* @param {event} e 觸發 input 的詳細事件
* @param {Event} e - The input event.
*/
function selectEnd(e) {
taskEnd.value = e;
@@ -326,8 +336,8 @@ function reset() {
taskEnd.value = null;
}
/**
* Radio 切換時,Start & End Data 連動改變
* @param {boolean} data true | false傳入 true 或 false
* Updates linked Start & End data when radio selection changes.
* @param {boolean} data - Whether data should be restored from submission state.
*/
function setResetData(data) {
if(data) {

View File

@@ -68,6 +68,18 @@
</div>
</template>
<script setup>
// The Lucia project.
// Copyright 2023-2026 DSP, inc. All rights reserved.
// Authors:
// chiayin.kuo@dsp.im (chiayin), 2023/1/31
// cindy.chang@dsp.im (Cindy Chang), 2024/5/30
// imacat.yang@dsp.im (imacat), 2023/9/23
/**
* @module components/Discover/Conformance/ConformanceSidebar/ConformanceTimeRange
* Time range picker for conformance time-based rule
* configuration with calendar inputs.
*/
import { reactive } from 'vue';
import { storeToRefs } from 'pinia';
import { useConformanceStore } from '@/stores/conformance';
@@ -149,22 +161,22 @@ const storeRefs = {
/**
* get min total seconds
* @param {Number} e 最小值總秒數
* @param {number} e - The minimum total seconds.
*/
function minTotalSeconds(e) {
emit('min-total-seconds', e);
}
/**
* get min total seconds
* @param {Number} e 最大值總秒數
* @param {number} e - The maximum total seconds.
*/
function maxTotalSeconds(e) {
emit('max-total-seconds', e);
}
/**
* get Time Range(duration)
* @param {array} data API dataActivity 列表
* @param {string} category 'act' | 'single' | 'double',傳入以上任一值。
* @param {Array} data - Activity list data from the API.
* @param {string} category - 'act', 'single', or 'double'.
* @param {string} task select Radio task or start
* @param {string} taskTwo end
* @returns {object} {min:12, max:345}

View File

@@ -9,5 +9,16 @@
</ul>
</template>
<script setup>
// The Lucia project.
// Copyright 2023-2026 DSP, inc. All rights reserved.
// Authors:
// chiayin.kuo@dsp.im (chiayin), 2023/1/31
// imacat.yang@dsp.im (imacat), 2023/9/23
/**
* @module components/Discover/Conformance/ConformanceSidebar/ResultArrow
* Conformance result display with arrow icons showing activity
* sequences.
*/
defineProps(['data', 'select']);
</script>

View File

@@ -9,6 +9,17 @@
</ul>
</template>
<script setup>
// The Lucia project.
// Copyright 2023-2026 DSP, inc. All rights reserved.
// Authors:
// chiayin.kuo@dsp.im (chiayin), 2023/1/31
// imacat.yang@dsp.im (imacat), 2023/9/23
/**
* @module components/Discover/Conformance/ConformanceSidebar/ResultCheck
* Conformance result display with check-circle icons showing
* matched activities.
*/
import { ref, watch } from 'vue';
import emitter from '@/utils/emitter';

View File

@@ -8,6 +8,17 @@
</ul>
</template>
<script setup>
// The Lucia project.
// Copyright 2023-2026 DSP, inc. All rights reserved.
// Authors:
// chiayin.kuo@dsp.im (chiayin), 2023/1/31
// imacat.yang@dsp.im (imacat), 2023/9/23
/**
* @module components/Discover/Conformance/ConformanceSidebar/ResultDot
* Conformance result display with dot icons showing category
* and task pairs.
*/
import { ref, watch } from 'vue';
import emitter from '@/utils/emitter';

View File

@@ -10,6 +10,18 @@
</div>
</template>
<script setup>
// The Lucia project.
// Copyright 2023-2026 DSP, inc. All rights reserved.
// Authors:
// chiayin.kuo@dsp.im (chiayin), 2023/1/31
// cindy.chang@dsp.im (Cindy Chang), 2024/5/30
// imacat.yang@dsp.im (imacat), 2023/9/23
/**
* @module components/Discover/Conformance/ConformanceSidebar/TimeRangeDuration
* Time range duration picker with min/max duration inputs
* for conformance time-based rules.
*/
import { ref, watch } from 'vue';
import Durationjs from '@/components/durationjs.vue';
@@ -28,9 +40,7 @@ const updateMin = ref(null);
const durationMin = ref(null);
const durationMax = ref(null);
/**
* set props values
*/
/** Deep-copies timeData min/max values to the Vue component boundaries. */
function setTimeValue() {
// 深拷貝原始 timeData 的內容
minVuemin.value = JSON.parse(JSON.stringify(timeData.value.min));
@@ -40,8 +50,8 @@ function setTimeValue() {
}
/**
* get min total seconds
* @param {Number} e 元件傳來的最小值總秒數
* Handles the minimum duration total seconds update.
* @param {number} e - The total seconds from the min duration component.
*/
function minTotalSeconds(e) {
timeRangeMin.value = e;
@@ -50,8 +60,8 @@ function minTotalSeconds(e) {
}
/**
* get min total seconds
* @param {Number} e 元件傳來的最大值總秒數
* Handles the maximum duration total seconds update.
* @param {number} e - The total seconds from the max duration component.
*/
function maxTotalSeconds(e) {
timeRangeMax.value = e;

View File

@@ -62,6 +62,18 @@
</Dialog>
</template>
<script setup>
// The Lucia project.
// Copyright 2023-2026 DSP, inc. All rights reserved.
// Authors:
// chiayin.kuo@dsp.im (chiayin), 2023/1/31
// cindy.chang@dsp.im (Cindy Chang), 2024/5/30
// imacat.yang@dsp.im (imacat), 2023/9/23
/**
* @module components/Discover/Conformance/MoreModal
* Modal dialog showing detailed conformance check
* results with expandable activity sequences.
*/
import { ref, computed, watch, nextTick, useTemplateRef } from 'vue';
import { storeToRefs } from 'pinia';
import { useConformanceStore } from '@/stores/conformance';
@@ -169,8 +181,8 @@ watch(infinite404, (newValue) => {
// methods
/**
* Number to percentage
* @param {number} val 原始數字
* @returns {string} 轉換完成的百分比字串
* @param {number} val - The raw ratio value.
* @returns {string} The formatted percentage string.
*/
function getPercentLabel(val){
if((val * 100).toFixed(1) >= 100) return 100;
@@ -178,8 +190,8 @@ function getPercentLabel(val){
}
/**
* set progress bar width
* @param {number} value 百分比數字
* @returns {string} 樣式的寬度設定
* @param {number} value - The percentage value.
* @returns {string} The CSS width style string.
*/
function progressWidth(value){
return `width:${value}%;`
@@ -201,7 +213,7 @@ async function switchCaseData(id) {
showTraceId.value = id; // 放 getDetail 為了 case table 載入完再切換 showTraceId
}
/**
* trace element nodes 資料彙整
* Assembles the trace element nodes data for Cytoscape rendering.
*/
function setNodesData(){
// 避免每次渲染都重複累加
@@ -224,7 +236,7 @@ function setNodesData(){
};
}
/**
* trace edge line 資料彙整
* Assembles the trace edge line data for Cytoscape rendering.
*/
function setEdgesData(){
processMap.value.edges = [];
@@ -256,7 +268,7 @@ function createCy(){
});
}
/**
* 無限滾動: 載入數據
* Infinite scroll: loads more data.
*/
async function fetchData() {
try {
@@ -270,8 +282,8 @@ async function fetchData() {
}
}
/**
* 無限滾動: 監聽 scroll 有沒有滾到底部
* @param {element} event 監聽時回傳的事件
* Infinite scroll: listens for scroll reaching the bottom.
* @param {Event} event - The scroll event.
*/
function handleScroll(event) {
if(maxItems.value || infiniteData.value.length < 20 || infiniteFinish.value === false) return;

View File

@@ -58,6 +58,16 @@
</div>
</template>
<script setup>
// The Lucia project.
// Copyright 2023-2026 DSP, inc. All rights reserved.
// Authors:
// chiayin.kuo@dsp.im (chiayin), 2023/1/31
/**
* @module components/Discover/Map/Filter/ActAndSeq Activity list
* with drag-and-drop sequence builder for creating filter
* rules.
*/
import { ref, computed, watch } from 'vue';
import { sortNumEngZhtwForFilter } from '@/module/sortNumEngZhtw.js';
@@ -100,33 +110,31 @@ watch(() => props.filterTaskData, (newval) => {
});
/**
* double click Activity List
* @param {number} index data item index
* @param {object} element data item
* Moves an activity from the list to the sequence on double-click.
* @param {number} index - The item index in the activity list.
* @param {Object} element - The activity data object.
*/
function moveActItem(index, element) {
listSequence.value.push(element);
}
/**
* double click Sequence List
* @param {number} index data item index
* @param {object} element data item
* Removes an activity from the sequence on double-click.
* @param {number} index - The item index in the sequence.
* @param {Object} element - The activity data object.
*/
function moveSeqItem(index, element) {
listSequence.value.splice(index, 1);
}
/**
* get listSequence
*/
/** Emits the current sequence list to the parent component. */
function getComponentData() {
emit('update:listSeq', listSequence.value);
}
/**
* Element dragging started
* @param {event} evt input 傳入的事件
* Handles drag start: hides original element and last arrow.
* @param {Event} evt - The drag start event.
*/
function onStart(evt) {
const lastChild = evt.to.lastChild.lastChild;
@@ -140,8 +148,8 @@ function onStart(evt) {
}
/**
* Element dragging ended
* @param {event} evt input 傳入的事件
* Handles drag end: restores element visibility.
* @param {Event} evt - The drag end event.
*/
function onEnd(evt) {
// 顯示拖曳元素

View File

@@ -29,6 +29,15 @@
</div>
</template>
<script setup>
// The Lucia project.
// Copyright 2023-2026 DSP, inc. All rights reserved.
// Authors:
// chiayin.kuo@dsp.im (chiayin), 2023/1/31
/**
* @module components/Discover/Map/Filter/ActOcc Activity
* occurrences filter table with single-row radio selection.
*/
import { ref, watch } from 'vue';
const props = defineProps({
@@ -60,8 +69,8 @@ watch(() => props.tableSelect, (newval) => {
});
/**
* 將選取的 row 傳到父層
* @param {event} e input 傳入的事件
* Emits the selected row to the parent component.
* @param {Event} e - The row selection event.
*/
function onRowSelect(e) {
emit('on-row-select', e);

View File

@@ -40,6 +40,16 @@
</template>
<script setup>
// The Lucia project.
// Copyright 2023-2026 DSP, inc. All rights reserved.
// Authors:
// chiayin.kuo@dsp.im (chiayin), 2023/1/31
/**
* @module components/Discover/Map/Filter/ActOccCase Activity
* occurrences and cases filter table with multi-row checkbox
* selection.
*/
import { ref, watch } from 'vue';
const props = defineProps(['tableTitle', 'tableData', 'tableSelect', 'progressWidth']);
@@ -53,23 +63,19 @@ watch(() => props.tableSelect, (newval) => {
select.value = newval;
});
/**
* 選擇 Row 的行為
*/
/** Emits the current selection when a row is selected. */
function onRowSelect() {
emit('on-row-select', select.value);
}
/**
* 取消選取 Row 的行為
*/
/** Emits the current selection when a row is unselected. */
function onRowUnselect() {
emit('on-row-select', select.value);
}
/**
* 全選 Row 的行為
* @param {event} e input 傳入的事件
* Handles select-all rows action.
* @param {Event} e - The select-all event with data property.
*/
function onRowSelectAll(e) {
select.value = e.data;
@@ -77,8 +83,8 @@ function onRowSelectAll(e) {
}
/**
* 取消全選 Row 的行為
* @param {event} e input 傳入的事件
* Handles unselect-all rows action.
* @param {Event} e - The unselect-all event.
*/
function onRowUnelectAll(e) {
select.value = null;

View File

@@ -120,6 +120,18 @@
</section>
</template>
<script setup>
// The Lucia project.
// Copyright 2023-2026 DSP, inc. All rights reserved.
// Authors:
// chiayin.kuo@dsp.im (chiayin), 2023/1/31
// cindy.chang@dsp.im (Cindy Chang), 2024/5/30
// imacat.yang@dsp.im (imacat), 2023/9/23
/**
* @module components/Discover/Map/Filter/Attributes
* Case attribute filter with dynamic form fields
* for filtering by attribute values.
*/
import { ref, computed, onMounted, onBeforeUnmount } from 'vue';
import { storeToRefs } from 'pinia';
import { useAllMapDataStore } from '@/stores/allMapData';
@@ -313,7 +325,7 @@ const labelsData = computed(() => {
});
/**
* 選取類別型 table 的選項
* Selects an option in the categorical table.
*/
function onRowSelect() {
const type = selectedAttName.value.type;
@@ -325,7 +337,7 @@ function onRowSelect() {
}
/**
* 取消類別型 table 的選項
* Deselects an option in the categorical table.
*/
function onRowUnselect() {
const type = selectedAttName.value.type;
@@ -337,8 +349,8 @@ function onRowUnselect() {
}
/**
* 選取類別型 table 的全選項
* @param {event} e input 傳入的事件
* Selects all options in the categorical table.
* @param {Event} e - The input event.
*/
function onRowSelectAll(e) {
selectedAttRange.value = e.data;
@@ -351,7 +363,7 @@ function onRowSelectAll(e) {
}
/**
* 取消類別型 table 的全選項
* Deselects all options in the categorical table.
*/
function onRowUnelectAll() {
selectedAttRange.value = null;
@@ -364,8 +376,8 @@ function onRowUnelectAll() {
}
/**
* 切換 Attribute Name Radio
* @param {event} e input 傳入的事件
* Switches the attribute name radio selection.
* @param {Event} e - The input event.
*/
function switchAttNameRadio(e) {
selectedAttRange.value = null;
@@ -416,8 +428,8 @@ function switchAttNameRadio(e) {
/**
* set progress bar width
* @param {number} value 百分比數字
* @returns {string} 樣式的寬度設定
* @param {number} value - The percentage value.
* @returns {string} The CSS width style string.
*/
function progressWidth(value){
return `width:${value}%;`
@@ -425,8 +437,8 @@ function progressWidth(value){
/**
* Number to percentage
* @param {number} val 原始數字
* @returns {string} 轉換完成的百分比字串
* @param {number} val - The raw ratio value.
* @returns {string} The formatted percentage string.
*/
function getPercentLabel(val){
if((val * 100).toFixed(1) >= 100) return `100%`;
@@ -434,8 +446,8 @@ function getPercentLabel(val){
}
/**
* 調整遮罩大小
* @param {object} chart 取得 chart.js 資料
* Adjusts the overlay mask size.
* @param {object} chart - The Chart.js instance data.
*/
function resizeMask(chart) {
const from = (selectArea.value[0] * 0.01) / (selectRange.value * 0.01);
@@ -445,8 +457,8 @@ function resizeMask(chart) {
}
/**
* 調整左邊遮罩大小
* @param {object} chart 取得 chart.js 資料
* Adjusts the left overlay mask size.
* @param {object} chart - The Chart.js instance data.
*/
function resizeLeftMask(chart, from) {
const canvas = document.querySelector('#chartCanvasId canvas');
@@ -458,8 +470,8 @@ function resizeLeftMask(chart, from) {
}
/**
* 調整右邊遮罩大小
* @param {object} chart 取得 chart.js 資料
* Adjusts the right overlay mask size.
* @param {object} chart - The Chart.js instance data.
*/
function resizeRightMask(chart, to) {
const canvas = document.querySelector('#chartCanvasId canvas');
@@ -471,7 +483,7 @@ function resizeRightMask(chart, to) {
}
/**
* create chart
* Creates and renders the Chart.js line chart for attribute data.
*/
function createChart() {
const vData = valueData.value;
@@ -632,7 +644,7 @@ function createChart() {
}
/**
* 滑塊改變的時候
* Handles slider value changes.
* @param {array} e [1, 100]
*/
function changeSelectArea(e) {
@@ -665,8 +677,8 @@ function changeSelectArea(e) {
}
/**
* 選取開始或結束時間時,要改變滑塊跟圖表
* @param {object} e Tue Jan 25 2022 00:00:00 GMT+0800 (台北標準時間) | Blur Event
* Updates the slider and chart when a start or end time is selected.
* @param {object} e - The date object or blur event.
* @param {string} direction start or end
*/
function sliderValueRange(e, direction) {

View File

@@ -39,6 +39,16 @@
</template>
<script setup>
// The Lucia project.
// Copyright 2023-2026 DSP, inc. All rights reserved.
// Authors:
// chiayin.kuo@dsp.im (chiayin), 2023/1/31
/**
* @module components/Discover/Map/Filter/Funnel Filter funnel
* panel showing applied filter rules with toggle, delete, and
* apply-all actions.
*/
import { storeToRefs } from 'pinia';
import { useToast } from 'vue-toast-notification';
import { useLoadingStore } from '@/stores/loading';
@@ -54,8 +64,9 @@ const { isLoading } = storeToRefs(loadingStore);
const { hasResultRule, temporaryData, postRuleData, ruleData, isRuleData, tempFilterId } = storeToRefs(allMapDataStore);
/**
* @param {boolean} e ture | false可選 ture 或 false
* @param {numble} index rule's index
* Toggles a filter rule on or off.
* @param {boolean} e - Whether the rule is enabled.
* @param {number} index - The rule index.
*/
function isRule(e, index){
const rule = isRuleData.value[index];
@@ -66,8 +77,8 @@ function isRule(e, index){
}
/**
* header:Funnel 刪除全部的 Funnel
* @param {numble|string} index rule's index 或 全部
* Deletes a single filter rule or all rules.
* @param {number|string} index - The rule index, or 'all' to delete all.
*/
async function deleteRule(index) {
if(index === 'all') {
@@ -91,9 +102,7 @@ async function deleteRule(index) {
}
}
/**
* header:Funnel 發送暫存的選取資料
*/
/** Submits all enabled filter rules and refreshes the map data. */
async function submitAll() {
postRuleData.value = temporaryData.value.filter(item => item !== 0); // 取得 submit 的資料,有 toggle button 的話,找出並刪除陣列中為 0 的項目
if(!postRuleData.value?.length) return $toast.error('Not selected');

View File

@@ -31,6 +31,16 @@
</div>
</template>
<script setup>
// The Lucia project.
// Copyright 2023-2026 DSP, inc. All rights reserved.
// Authors:
// chiayin.kuo@dsp.im (chiayin), 2023/1/31
/**
* @module components/Discover/Map/Filter/Timeframes
* Timeframe filter with date range pickers and
* duration range selectors.
*/
import { ref, computed, watch, onMounted } from 'vue';
import { storeToRefs } from 'pinia';
import { useAllMapDataStore } from '@/stores/allMapData';
@@ -151,8 +161,8 @@ watch(selectTimeFrame, (newValue, oldValue) => {
});
/**
* 調整遮罩大小
* @param {object} chartInstance 取得 chart.js 資料
* Adjusts the overlay mask size.
* @param {object} chartInstance - The Chart.js instance.
*/
function resizeMask(chartInstance) {
const from = (selectArea.value[0] * 0.01) / (selectRange.value * 0.01);
@@ -164,8 +174,8 @@ function resizeMask(chartInstance) {
}
/**
* 調整左邊遮罩大小
* @param {object} chartInstance 取得 chart.js 資料
* Adjusts the left overlay mask size.
* @param {object} chartInstance - The Chart.js instance.
*/
function resizeLeftMask(chartInstance, from) {
const canvas = document.getElementById("chartCanvasId");
@@ -177,8 +187,8 @@ function resizeLeftMask(chartInstance, from) {
}
/**
* 調整右邊遮罩大小
* @param {object} chartInstance 取得 chart.js 資料
* Adjusts the right overlay mask size.
* @param {object} chartInstance - The Chart.js instance.
*/
function resizeRightMask(chartInstance, to) {
const canvas = document.getElementById("chartCanvasId");
@@ -190,7 +200,7 @@ function resizeRightMask(chartInstance, to) {
}
/**
* create chart
* Creates and renders the Chart.js area chart for timeframe data.
*/
function createChart() {
const max = filterTimeframe.value.y_axis.max * 1.1;
@@ -289,7 +299,7 @@ function createChart() {
}
/**
* 滑塊改變的時候
* Handles slider value changes.
* @param {array} e [1, 100]
*/
function changeSelectArea(e) {
@@ -310,8 +320,8 @@ function changeSelectArea(e) {
}
/**
* 選取開始或結束時間時,要改變滑塊跟圖表
* @param {object} e Tue Jan 25 2022 00:00:00 GMT+0800 (台北標準時間)
* Updates the slider and chart when a start or end time is selected.
* @param {object} e - The selected date object.
* @param {string} direction start or end
*/
function sliderTimeRange(e, direction) {

View File

@@ -69,6 +69,16 @@
</template>
<script setup>
// The Lucia project.
// Copyright 2023-2026 DSP, inc. All rights reserved.
// Authors:
// chiayin.kuo@dsp.im (chiayin), 2023/1/31
/**
* @module components/Discover/Map/Filter/Trace
* Trace filter with trace selection table and
* trace detail display.
*/
import { ref, computed, watch, onMounted } from 'vue';
import { storeToRefs } from 'pinia';
import { useAllMapDataStore } from '@/stores/allMapData';
@@ -238,8 +248,8 @@ function barOptions(){
/**
* Number to percentage
* @param {number} val 原始數字
* @returns {string} 轉換完成的百分比字串
* @param {number} val - The raw ratio value.
* @returns {string} The formatted percentage string.
*/
function getPercentLabel(val){
if((val * 100).toFixed(1) >= 100) return 100;
@@ -248,8 +258,8 @@ function getPercentLabel(val){
/**
* set progress bar width
* @param {number} value 百分比數字
* @returns {string} 樣式的寬度設定
* @param {number} value - The percentage value.
* @returns {string} The CSS width style string.
*/
function progressWidth(value){
return `width:${value}%;`
@@ -258,7 +268,7 @@ function progressWidth(value){
/**
* switch case data
* @param {number} id case id
* @param {number} count 所有的 case 數量
* @param {number} count - The total number of cases.
*/
async function switchCaseData(id, count) {
// 點同一筆 id 不要有動作
@@ -275,7 +285,7 @@ async function switchCaseData(id, count) {
}
/**
* trace element nodes 資料彙整
* Assembles the trace element nodes data for Cytoscape rendering.
*/
function setNodesData(){
// 避免每次渲染都重複累加
@@ -297,7 +307,7 @@ function setNodesData(){
}
/**
* trace edge line 資料彙整
* Assembles the trace edge line data for Cytoscape rendering.
*/
function setEdgesData(){
processMap.value.edges = [];
@@ -327,8 +337,8 @@ function createCy(){
}
/**
* 無限滾動: 監聽 scroll 有沒有滾到底部
* @param {element} event 滾動傳入的事件
* Infinite scroll: listens for scroll reaching the bottom.
* @param {Event} event - The scroll event.
*/
function handleScroll(event) {
if(infinitMaxItems.value || baseCases.value.length < 20 || infiniteFinish.value === false) return;
@@ -340,7 +350,7 @@ function handleScroll(event) {
}
/**
* 無限滾動: 滾到底後,要載入數據
* Infinite scroll: loads more data when the bottom is reached.
*/
async function fetchData() {
try {

View File

@@ -97,6 +97,17 @@
</template>
<script setup>
// The Lucia project.
// Copyright 2023-2026 DSP, inc. All rights reserved.
// Authors:
// chiayin.kuo@dsp.im (chiayin), 2023/1/31
/**
* @module components/Discover/Map/SidebarFilter
* Filter sidebar for the Map view with tabbed panels
* for activity, timeframe, attribute, and trace
* filters.
*/
import { ref, reactive, computed } from 'vue';
import { storeToRefs } from 'pinia';
import { useToast } from 'vue-toast-notification';
@@ -227,6 +238,7 @@ const isDisabledButton = computed(() => {
/**
* Change Radio Filter Type
*/
/** Checks if the apply button should be disabled based on filter type. */
function radioFilterType() {
reset();
}
@@ -234,6 +246,7 @@ function radioFilterType() {
/**
* Change Radio Act Seq
*/
/** Checks if the apply button should be disabled for activity sequence. */
function radioActSeq() {
reset();
}
@@ -241,6 +254,7 @@ function radioActSeq() {
/**
* Change Radio Start And End
*/
/** Checks if the apply button should be disabled for start & end filter. */
function radioStartAndEnd() {
reset();
}
@@ -254,8 +268,8 @@ function switchTab(newTab) {
/**
* Number to percentage
* @param {number} val 原始數字
* @returns {string} 轉換完成的百分比字串
* @param {number} val - The raw ratio value.
* @returns {string} The formatted percentage string.
*/
function getPercentLabel(val){
if((val * 100).toFixed(1) >= 100) return `100%`;
@@ -264,8 +278,8 @@ function getPercentLabel(val){
/**
* set progress bar width
* @param {number} value 百分比數字
* @returns {string} 樣式的寬度設定
* @param {number} value - The percentage value.
* @returns {string} The CSS width style string.
*/
function progressWidth(value){
return `width:${value}%;`
@@ -293,7 +307,7 @@ function setHaveAct(data){
// 調整 filterStartData / filterEndData / filterStartToEndData / filterEndToStartData 的內容
/**
* @param {array} array filterStartToEnd / filterEndToStart,可傳入以上任一。
* @param {Array} array - filterStartToEnd or filterEndToStart data array.
*/
function setActData(array) {
const list = [];
@@ -376,7 +390,7 @@ function endRow(e) {
// 重新設定連動的 filterStartToEndData / filterEndToStartData 內容
/**
* @param {array} eventData Start or End List
* @param {object} rowDataVal 所選擇的 row's data
* @param {object} rowDataVal - The selected row's data.
* @param {string} event sinks / sources
*/
function setStartAndEndData(eventData, rowDataVal, event){
@@ -398,6 +412,11 @@ function setStartAndEndData(eventData, rowDataVal, event){
/**
* @param {object} e task's object
*/
/**
* Creates a display rule object from filter event data.
* @param {object} e - The filter rule data.
* @returns {object} The display rule with type, label, and toggle.
*/
function setRule(e) {
let label, type;
const includeStr = e.is_exclude? "exclude" : "include";
@@ -449,7 +468,7 @@ function setRule(e) {
}
/**
* @param {boolean} message true | false 清空選項,可選以上任一。
* @param {boolean} message - Whether to show the success toast message.
*/
function reset(message) {
// Sequence
@@ -480,7 +499,7 @@ function reset(message) {
}
/**
* header:Filter 發送選取的資料
* Submits the selected filter data to the backend.
*/
async function submit() {
isLoading.value = true;
@@ -520,10 +539,16 @@ async function submit() {
/**
* create map
*/
/** Triggers the submit-all event to create the map. */
function sumbitAll() {
emit('submit-all');
}
/**
* Checks if the sequence filter selection is valid.
* @param {Array} sele - The current selection values.
* @returns {boolean} Whether the button should be disabled.
*/
function handleSequenceSelection(sele) {
const secondSelection = sele[1];
@@ -539,6 +564,11 @@ function handleSequenceSelection(sele) {
}
}
/**
* Checks if the start & end sub-selection is valid.
* @param {string} option - 'Start', 'End', or 'Start & End'.
* @returns {boolean} Whether the button should be disabled.
*/
function handleStartEndSelection(option) {
switch (option) {
case 'Start':
@@ -552,6 +582,11 @@ function handleStartEndSelection(option) {
}
}
/**
* Checks if the attribute filter selection is valid.
* @param {string} type - The attribute type.
* @returns {boolean} Whether the button should be disabled.
*/
function handleAttributesSelection(type) {
switch (type) {
case 'string':
@@ -567,14 +602,25 @@ function handleAttributesSelection(type) {
}
}
/** Checks if the trace filter selection is valid.
* @returns {boolean} Whether the button should be disabled.
*/
function handleTraceSelection() {
return selectTraceArea.value[0] === selectTraceArea.value[1];
}
/** Checks if the timeframes filter selection is valid.
* @returns {boolean} Whether the button should be disabled.
*/
function handleTimeframesSelection() {
return selectTimeFrame.value.length === 0;
}
/**
* Gets the display label for a task filter rule.
* @param {object} e - The filter rule data.
* @returns {string} The formatted label.
*/
function getTaskLabel(e) {
switch (e.type) {
case "contains-task":
@@ -589,6 +635,11 @@ function getTaskLabel(e) {
}
}
/**
* Gets the display label for an attribute filter rule.
* @param {object} e - The filter rule data.
* @returns {string} The formatted label.
*/
function getAttributeLabel(e) {
switch (e.type) {
case 'string-attr':
@@ -603,6 +654,13 @@ function getAttributeLabel(e) {
}
}
/**
* Builds filter data from the current selections.
* @param {Array} sele - The current selection values.
* @param {boolean} isExclude - Whether this is an exclude filter.
* @param {object} containmentMap - Containment type mapping.
* @returns {object|Array} The filter data to submit.
*/
function getFilterData(sele, isExclude, containmentMap) {
switch (sele[0]) {
case 'Sequence':
@@ -623,6 +681,12 @@ function getFilterData(sele, isExclude, containmentMap) {
}
}
/**
* Builds sequence filter data.
* @param {Array} sele - The current selection values.
* @param {boolean} isExclude - Whether this is an exclude filter.
* @returns {object} The sequence filter data.
*/
function getSequenceData(sele, isExclude) {
switch (sele[1]) {
case 'Have activity(s)':
@@ -644,6 +708,12 @@ function getSequenceData(sele, isExclude) {
}
}
/**
* Builds start & end filter data.
* @param {Array} sele - The current selection values.
* @param {boolean} isExclude - Whether this is an exclude filter.
* @returns {object} The start & end filter data.
*/
function getStartEndData(sele, isExclude) {
switch (sele[2]) {
case 'Start':
@@ -670,6 +740,11 @@ function getStartEndData(sele, isExclude) {
}
}
/**
* Builds attributes filter data.
* @param {boolean} isExclude - Whether this is an exclude filter.
* @returns {object} The attributes filter data.
*/
function getAttributesData(isExclude) {
const attrTypeMap = {
'string': 'string-attr',
@@ -704,6 +779,11 @@ function getAttributesData(isExclude) {
}
}
/**
* Builds trace filter data.
* @param {boolean} isExclude - Whether this is an exclude filter.
* @returns {object} The trace filter data.
*/
function getTraceData(isExclude) {
const lowerIndex = filterTraceViewRef.value.selectArea[0];
const upperIndex = filterTraceViewRef.value.selectArea[1] - 1;
@@ -715,6 +795,10 @@ function getTraceData(isExclude) {
};
}
/**
* Updates the rules list with newly submitted filter data.
* @param {Array} postData - The submitted filter data.
*/
function updateRules(postData) {
if (!temporaryData.value?.length) {
temporaryData.value.push(...postData);
@@ -727,6 +811,11 @@ function updateRules(postData) {
}
}
/**
* Returns a promise that resolves after the given delay.
* @param {number} ms - The delay in milliseconds.
* @returns {Promise} Resolves after the delay.
*/
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}

View File

@@ -242,6 +242,17 @@
</template>
<script setup>
// The Lucia project.
// Copyright 2023-2026 DSP, inc. All rights reserved.
// Authors:
// chiayin.kuo@dsp.im (chiayin), 2023/1/31
/**
* @module components/Discover/Map/SidebarState
* Summary statistics sidebar for the Map view
* displaying cases, traces, activities, timeframe,
* and case duration.
*/
import { computed, ref } from 'vue';
import { usePageAdminStore } from '@/stores/pageAdmin';
import { useMapPathStore } from '@/stores/mapPathStore';
@@ -282,17 +293,26 @@ const valueTraces = ref(0);
const valueTaskInstances = ref(0);
const valueTasks = ref(0);
/**
* Handles click on an active trace to highlight it.
* @param {number} clickedActiveTraceIndex - The clicked trace index.
*/
function onActiveTraceClick(clickedActiveTraceIndex) {
mapPathStore.clearAllHighlight();
activeTrace.value = clickedActiveTraceIndex;
mapPathStore.highlightClickedPath(clickedActiveTraceIndex, clickedPathListIndex.value);
}
/**
* Handles click on a path option to highlight it.
* @param {number} clickedPath - The clicked path index.
*/
function onPathOptionClick(clickedPath) {
clickedPathListIndex.value = clickedPath;
mapPathStore.highlightClickedPath(activeTrace.value, clickedPath);
}
/** Resets the trace highlight to default. */
function onResetTraceBtnClick() {
if(isBPMNOn.value) {
return;
@@ -326,8 +346,8 @@ function moment(time){
/**
* Number to percentage
* @param {number} val 原始數字
* @returns {string} 轉換完成的百分比字串
* @param {number} val - The raw ratio value.
* @returns {string} The formatted percentage string.
*/
function getPercentLabel(val){
if((val * 100).toFixed(1) >= 100) return `100%`;

View File

@@ -60,6 +60,16 @@
</Sidebar>
</template>
<script setup>
// The Lucia project.
// Copyright 2023-2026 DSP, inc. All rights reserved.
// Authors:
// chiayin.kuo@dsp.im (chiayin), 2023/1/31
/**
* @module components/Discover/Map/SidebarTraces
* Traces sidebar showing path insights with
* clickable trace lists for highlighting on the map.
*/
import { ref, computed, watch } from 'vue';
import { storeToRefs } from 'pinia';
import { useLoadingStore } from '@/stores/loading';
@@ -150,8 +160,8 @@ watch(infiniteFirstCases, (newValue) => {
/**
* Number to percentage
* @param {number} val 原始數字
* @returns {string} 轉換完成的百分比字串
* @param {number} val - The raw ratio value.
* @returns {string} The formatted percentage string.
*/
function getPercentLabel(val){
if((val * 100).toFixed(1) >= 100) return `100%`;
@@ -160,8 +170,8 @@ function getPercentLabel(val){
/**
* set progress bar width
* @param {number} value 百分比數字
* @returns {string} 樣式的寬度設定
* @param {number} value - The percentage value.
* @returns {string} The CSS width style string.
*/
function progressWidth(value){
return `width:${value}%;`
@@ -170,7 +180,7 @@ function progressWidth(value){
/**
* switch case data
* @param {number} id case id
* @param {number} count case 數量
* @param {number} count - The total number of cases.
*/
async function switchCaseData(id, count) {
// 點同一筆 id 不要有動作
@@ -184,7 +194,7 @@ async function switchCaseData(id, count) {
}
/**
* trace element nodes 資料彙整
* Assembles the trace element nodes data for Cytoscape rendering.
*/
function setNodesData(){
// 避免每次渲染都重複累加
@@ -206,7 +216,7 @@ function setNodesData(){
}
/**
* trace edge line 資料彙整
* Assembles the trace edge line data for Cytoscape rendering.
*/
function setEdgesData(){
processMap.value.edges = [];
@@ -250,8 +260,8 @@ async function show() {
}
/**
* 無限滾動: 監聽 scroll 有沒有滾到底部
* @param {element} event 滾動傳入的事件
* Infinite scroll: listens for scroll reaching the bottom.
* @param {Event} event - The scroll event.
*/
function handleScroll(event) {
if(infinitMaxItems.value || props.cases.length < 20 || infiniteFinish.value === false) return;
@@ -263,7 +273,7 @@ function handleScroll(event) {
}
/**
* 無限滾動: 滾到底後,要載入數據
* Infinite scroll: loads more data when the bottom is reached.
*/
async function fetchData() {
try {

View File

@@ -70,6 +70,16 @@
</template>
<script setup>
// The Lucia project.
// Copyright 2023-2026 DSP, inc. All rights reserved.
// Authors:
// chiayin.kuo@dsp.im (chiayin), 2023/1/31
/**
* @module components/Discover/Map/SidebarView Visualization
* settings sidebar for map view type (process/BPMN), curve
* style, direction, and data layer selection.
*/
import { ref, onMounted } from 'vue';
import { storeToRefs } from 'pinia';
import { useMapPathStore } from '@/stores/mapPathStore';
@@ -117,8 +127,8 @@ const selectedDuration = ref('');
const rank = ref('LR'); // 直向 TB | 橫向 LR
/**
* switch map type
* @param {string} type 'processMap' | 'bpmn',可傳入以上任一。
* Switches the map type and emits the change event.
* @param {string} type - 'processMap' or 'bpmn'.
*/
function switchMapType(type) {
mapType.value = type;
@@ -126,8 +136,8 @@ function switchMapType(type) {
}
/**
* switch curve style
* @param {string} style 直角 'unbundled-bezier' | 'taxi',可傳入以上任一。
* Switches the curve style and emits the change event.
* @param {string} style - 'unbundled-bezier' (curved) or 'taxi' (elbow).
*/
function switchCurveStyles(style) {
curveStyle.value = style;
@@ -135,8 +145,8 @@ function switchCurveStyles(style) {
}
/**
* switch rank
* @param {string} rank 直向 'TB' | 橫向 'LR',可傳入以上任一。
* Switches the graph layout direction and emits the change event.
* @param {string} rankValue - 'TB' (vertical) or 'LR' (horizontal).
*/
function switchRank(rankValue) {
rank.value = rankValue;
@@ -144,9 +154,9 @@ function switchRank(rankValue) {
}
/**
* switch Data Layoer Type or Option.
* @param {string} e 切換時傳入的選項
* @param {string} type 'freq' | 'duration',可傳入以上任一。
* Switches the data layer type (frequency or duration) and option.
* @param {Event} e - The change event from the radio or select.
* @param {string} type - 'freq' or 'duration'.
*/
function switchDataLayerType(e, type) {
let value = '';
@@ -169,11 +179,13 @@ function switchDataLayerType(e, type) {
emit('switch-data-layer-type', dataLayerType.value, dataLayerOption.value);
}
/** Switches to Process Map view. */
function onProcessMapClick() {
mapPathStore.setIsBPMNOn(false);
switchMapType('processMap');
}
/** Switches to BPMN Model view. */
function onBPMNClick() {
mapPathStore.setIsBPMNOn(true);
switchMapType('bpmn');

View File

@@ -79,6 +79,16 @@
</template>
<script setup>
// The Lucia project.
// Copyright 2024-2026 DSP, inc. All rights reserved.
// Authors:
// chiayin.kuo@dsp.im (chiayin), 2023/1/31
/**
* @module components/Discover/StatusBar Collapsible status bar
* showing dataset statistics (cases, traces, activities,
* timeframe, case duration) for the Discover page.
*/
import { ref, onMounted, } from 'vue';
import { useRoute } from 'vue-router';
import { storeToRefs } from 'pinia';
@@ -95,18 +105,16 @@ const isPanel = ref(false);
const statData = ref(null);
/**
* Number to percentage
* @param {number} val 原始數字
* @returns {string} 轉換完成的百分比字串
* Converts a ratio (01) to a percentage number (0100), capped at 100.
* @param {number} val - The ratio value to convert.
* @returns {number} The percentage value.
*/
function getPercentLabel(val){
if((val * 100).toFixed(1) >= 100) return 100;
else return parseFloat((val * 100).toFixed(1));
}
/**
* setting stats data
*/
/** Transforms raw stats into display-ready format with localized numbers and time labels. */
function getStatData() {
statData.value = {
cases: {

View File

@@ -15,6 +15,17 @@
</Dialog>
</template>
<script setup>
// The Lucia project.
// Copyright 2023-2026 DSP, inc. All rights reserved.
// Authors:
// chiayin.kuo@dsp.im (chiayin), 2023/1/31
// cindy.chang@dsp.im (Cindy Chang), 2024/5/30
// imacat.yang@dsp.im (imacat), 2023/9/23
/**
* @module components/File/UploadModal File upload modal dialog
* with drag-and-drop support for CSV files (max 90 MB).
*/
import { onBeforeUnmount, } from 'vue';
import { storeToRefs } from 'pinia';
import IconUploarding from '../icons/IconUploarding.vue';
@@ -30,8 +41,8 @@ const { uploadFileName } = storeToRefs(filesStore);
const contentClass = 'h-full';
/**
* 上傳的行為
* @param {event} event input 傳入的事件
* Handles CSV file upload: validates size, sends to API, extracts filename.
* @param {Event} event - The file input change event.
*/
async function upload(event) {
const fileInput = document.getElementById('uploadFiles');

View File

@@ -20,6 +20,17 @@
</template>
<script setup>
// The Lucia project.
// Copyright 2023-2026 DSP, inc. All rights reserved.
// Authors:
// chiayin.kuo@dsp.im (chiayin), 2023/1/31
// cindy.chang@dsp.im (Cindy Chang), 2024/5/30
// imacat.yang@dsp.im (imacat), 2023/9/23
/**
* @module components/Header Application header with DSP logo and
* user account menu toggle button.
*/
import { ref, onMounted, } from 'vue';
import { useRoute } from 'vue-router';
import { storeToRefs, } from 'pinia';
@@ -49,7 +60,8 @@ const toggleIsAcctMenuOpen = () => {
};
/**
* 登出的行為
* Handles logout with unsaved-changes confirmation for Map
* and Conformance pages.
*/
function logOutButton() {
if ((route.name === 'Map' || route.name === 'CheckMap') && tempFilterId.value) {

View File

@@ -1,3 +1,7 @@
<!-- The Lucia project.
Copyright 2023-2026 DSP, inc. All rights reserved.
Authors:
chiayin.kuo@dsp.im (chiayin), 2023/1/31 -->
<template>
<div class="w-full h-full fixed inset-0 m-auto flex justify-center items-center bg-gradient-to-tr from-neutral-500/50 to-neutral-900/50 z-[9999]">
<span class="loader block"></span>

View File

@@ -45,6 +45,18 @@
</nav>
</template>
<script setup>
// The Lucia project.
// Copyright 2023-2026 DSP, inc. All rights reserved.
// Authors:
// chiayin.kuo@dsp.im (chiayin), 2023/1/31
// cindy.chang@dsp.im (Cindy Chang), 2024/5/30
// imacat.yang@dsp.im (imacat), 2023/9/23
/**
* @module components/Navbar Navigation bar with breadcrumb-style
* page tabs, import button for Files, and save button for
* Map/Conformance pages.
*/
import { ref, computed, watch, onMounted, } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { storeToRefs, } from 'pinia';
@@ -123,8 +135,8 @@ watch(filterName, (newVal) => {
});
/**
* switch navbar item
* @param {event} event 選取 Navbar 選項後傳入的值
* Handles navigation when a navbar tab is clicked.
* @param {Event} event - The click event from the nav item.
*/
function onNavItemBtnClick(event) {
let type;
@@ -185,8 +197,8 @@ function onNavItemBtnClick(event) {
}
/**
* Based on the route.name, decide the navViewName.
* @returns {string} the string of navigation name to return
* Determines the navbar view name and active page from the current route.
* @returns {string} The navigation item name to highlight.
*/
function getNavViewName() {
@@ -244,9 +256,7 @@ function getNavViewName() {
return valueToSet;
}
/**
* Save button' modal
*/
/** Opens the save modal for Map or Conformance pages. */
async function saveModal() {
// 協助判斷 MAP, CONFORMANCE 儲存有「送出」或「取消」。
// 傳給 Map通知 Sidebar 要關閉。
@@ -268,15 +278,14 @@ async function saveModal() {
}
}
/**
* Set nav item button background color in case the variable is an empty string
*/
/** Sets nav item button background color when the active page is empty. */
function handleNavItemBtn() {
if(activePageComputedByRoute.value === "") {
setActivePageComputedByRoute(route.matched[route.matched.length - 1].name);
}
}
/** Saves or creates a filter for the Map page. */
async function handleMapSave() {
if (createFilterId.value) {
await allMapDataStore.updateFilter();
@@ -292,6 +301,7 @@ async function handleMapSave() {
}
}
/** Saves a filter from the Check Map page. */
async function handleCheckMapSave() {
const isSaved = await saveFilter(allMapDataStore.addFilterId);
if (isSaved) {
@@ -300,6 +310,7 @@ async function handleCheckMapSave() {
}
}
/** Saves or updates conformance check data. */
async function handleConformanceSave() {
if (conformanceFilterCreateCheckId.value || conformanceLogCreateCheckId.value) {
await conformanceStore.updateConformance();

View File

@@ -17,6 +17,17 @@
</template>
<script setup>
// The Lucia project.
// Copyright 2023-2026 DSP, inc. All rights reserved.
// Authors:
// chiayin.kuo@dsp.im (chiayin), 2023/1/31
// cindy.chang@dsp.im (Cindy Chang), 2024/5/30
// imacat.yang@dsp.im (imacat), 2023/9/23
/**
* @module components/Search Search bar component with activity
* search input, settings icon, and search icon button.
*/
import IconSearch from '@/components/icons/IconSearch.vue';
import IconSetting from '@/components/icons/IconSetting.vue';
</script>

View File

@@ -40,6 +40,18 @@
</template>
<script setup>
// The Lucia project.
// Copyright 2023-2026 DSP, inc. All rights reserved.
// Authors:
// chiayin.kuo@dsp.im (chiayin), 2023/1/31
// cindy.chang@dsp.im (Cindy Chang), 2024/5/30
// imacat.yang@dsp.im (imacat), 2023/9/23
/**
* @module components/durationjs
* Duration input component with day/hour/minute/second
* fields and bounded min/max validation.
*/
import { ref, computed, watch, onMounted } from 'vue';
import emitter from '@/utils/emitter';
@@ -137,15 +149,24 @@ const inputTimeFields = computed(() => {
return paddedTimeFields;
});
/** Closes the time selection dropdown. */
function onClose() {
openTimeSelect.value = false;
}
/**
* Selects all text in the focused input field.
* @param {FocusEvent} event - The focus event.
*/
function onFocus(event) {
lastInput.value = event.target;
lastInput.value.select();
}
/**
* Validates and updates the duration value when an input changes.
* @param {Event} event - The change event from a duration input.
*/
function onChange(event) {
const baseInputValue = event.target.value;
let decoratedInputValue;
@@ -184,6 +205,10 @@ function onChange(event) {
calculateTotalSeconds();
}
/**
* Handles arrow key up/down to increment/decrement duration values.
* @param {KeyboardEvent} event - The keyup event.
*/
function onKeyUp(event) {
event.target.value = event.target.value.replace(/\D/g, '');
if (event.keyCode === 38 || event.keyCode === 40) {
@@ -191,6 +216,12 @@ function onKeyUp(event) {
};
}
/**
* Increments or decrements a duration unit value with carry-over.
* @param {HTMLInputElement} input - The input element to update.
* @param {boolean} goUp - True to increment, false to decrement.
* @param {boolean} [selectIt=false] - Whether to select the input text after.
*/
function actionUpDown(input, goUp, selectIt = false) {
const tUnit = input.dataset.tunit;
let newVal = getNewValue(input);
@@ -259,6 +290,11 @@ function updateInputValue(input, newVal, tUnit) {
}
}
/**
* Converts total seconds to day/hour/minute/second components.
* @param {number} totalSec - The total seconds to convert.
* @param {string} [size] - 'max' or 'min' to set boundary days.
*/
function secondToDate(totalSec, size) {
totalSec = parseInt(totalSec);
if(!isNaN(totalSec)) {
@@ -276,6 +312,7 @@ function secondToDate(totalSec, size) {
};
}
/** Calculates total seconds from all duration units and emits the result. */
function calculateTotalSeconds() {
let total = 0;
@@ -299,6 +336,7 @@ function calculateTotalSeconds() {
emit('total-seconds', total);
}
/** Initializes the duration display based on min/max boundaries and preset value. */
async function createData() {
const size = props.size;

View File

@@ -1,3 +1,7 @@
<!-- The Lucia project.
Copyright 2023-2026 DSP, inc. All rights reserved.
Authors:
chiayin.kuo@dsp.im (chiayin), 2023/1/31 -->
<template>
<svg
width="124"

View File

@@ -9,6 +9,16 @@
</template>
<script setup>
// The Lucia project.
// Copyright 2024-2026 DSP, inc. All rights reserved.
// Authors:
// cindy.chang@dsp.im (Cindy Chang), 2024/5/30
// imacat.yang@dsp.im (imacat), 2023/9/23
/**
* @module components/icons/IconChecked Checkbox icon component
* that toggles between checked and unchecked states.
*/
import ImgCheckboxBlueFrame from "@/assets/icon-blue-checkbox.svg";
import ImgCheckboxCheckedMark from "@/assets/icon-checkbox-checked.svg";
import ImgCheckboxGrayFrame from "@/assets/icon-checkbox-empty.svg";

View File

@@ -1,3 +1,7 @@
<!-- The Lucia project.
Copyright 2023-2026 DSP, inc. All rights reserved.
Authors:
chiayin.kuo@dsp.im (chiayin), 2023/1/31 -->
<template>
<svg width="32" height="32" viewBox="0 0 32 32" fill="black" xmlns="http://www.w3.org/2000/svg">
<path d="M28.8571 31H3.14286C2.57471 30.9994 2.03 30.7735 1.62825 30.3717C1.22651 29.97 1.00057 29.4253 1 28.8571V3.14286C1.00057 2.57471 1.22651 2.03 1.62825 1.62825C2.03 1.22651 2.57471 1.00057 3.14286 1H28.8571C29.4253 1.00057 29.97 1.22651 30.3717 1.62825C30.7735 2.03 30.9994 2.57471 31 3.14286V28.8571C30.9994 29.4253 30.7735 29.97 30.3717 30.3717C29.97 30.7735 29.4253 30.9994 28.8571 31ZM3.14286 3.14286V28.8571H28.8571V3.14286H3.14286Z"/>

View File

@@ -1,3 +1,7 @@
<!-- The Lucia project.
Copyright 2023-2026 DSP, inc. All rights reserved.
Authors:
chiayin.kuo@dsp.im (chiayin), 2023/1/31 -->
<template>
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.0529 3.24373C4.9174 3.10198 4.73177 3.01893 4.53578 3.01238C4.33979 3.00583 4.14903 3.07631 4.00437 3.20871C3.85971 3.34111 3.77266 3.5249 3.76187 3.7207C3.75108 3.9165 3.81741 4.10874 3.94665 4.25624L5.74665 6.23436C2.34352 8.32498 0.881025 11.55 0.8154 11.7C0.773866 11.7962 0.752441 11.8999 0.752441 12.0047C0.752441 12.1095 0.773866 12.2132 0.8154 12.3094C0.843525 12.375 1.6404 14.1375 3.4029 15.9094C5.75602 18.2531 8.7279 19.5 11.9998 19.5C13.6807 19.5067 15.3444 19.1618 16.8842 18.4875L18.9467 20.7562C19.0169 20.833 19.1023 20.8943 19.1976 20.9363C19.2928 20.9783 19.3957 21 19.4998 21C19.6869 20.9982 19.8669 20.9282 20.006 20.8031C20.0797 20.7373 20.1396 20.6574 20.1819 20.5681C20.2243 20.4789 20.2484 20.382 20.2528 20.2833C20.2571 20.1846 20.2417 20.086 20.2074 19.9933C20.173 19.9007 20.1205 19.8158 20.0529 19.7437L5.0529 3.24373ZM9.48727 10.3594L13.3966 14.6531C12.9666 14.8818 12.4868 15.0009 11.9998 15C11.4591 15.0001 10.9284 14.8542 10.4639 14.5775C9.99933 14.3009 9.61819 13.9038 9.36076 13.4283C9.10334 12.9528 8.97919 12.4166 9.00146 11.8764C9.02373 11.3362 9.19159 10.812 9.48727 10.3594V10.3594ZM11.9998 18C9.11228 18 6.5904 16.95 4.50915 14.8781C3.64691 14.0329 2.91685 13.0626 2.34352 12C2.78415 11.175 4.19978 8.85936 6.7779 7.36873L8.4654 9.22499C7.81494 10.0615 7.48054 11.1007 7.52112 12.1596C7.5617 13.2185 7.97465 14.2291 8.68723 15.0134C9.39981 15.7976 10.3663 16.3053 11.4164 16.4469C12.4666 16.5885 13.533 16.355 14.4279 15.7875L15.806 17.3062C14.5911 17.771 13.3005 18.0063 11.9998 18V18ZM23.1842 12.3094C23.1467 12.3937 22.1998 14.4937 20.0529 16.4156C19.9152 16.5359 19.7388 16.6025 19.556 16.6031C19.4509 16.6044 19.3467 16.5823 19.2511 16.5385C19.1555 16.4948 19.0707 16.4304 19.0029 16.35C18.937 16.2767 18.8862 16.1912 18.8534 16.0983C18.8205 16.0055 18.8063 15.907 18.8116 15.8086C18.8168 15.7103 18.8413 15.6139 18.8838 15.525C18.9263 15.4361 18.9859 15.3565 19.0592 15.2906C20.107 14.3507 20.9854 13.2376 21.656 12C21.0811 10.9356 20.3513 9.96244 19.4904 9.11248C17.4091 7.04998 14.8873 5.99999 11.9998 5.99999C11.3903 5.99753 10.7818 6.04772 10.181 6.14998C9.98493 6.17994 9.78489 6.13197 9.62371 6.01634C9.46252 5.90071 9.35299 5.72659 9.31852 5.53124C9.30244 5.43397 9.30569 5.33448 9.32809 5.23847C9.35049 5.14246 9.3916 5.0518 9.44907 4.9717C9.50654 4.89159 9.57924 4.8236 9.66301 4.77161C9.74678 4.71963 9.83998 4.68467 9.93727 4.66873C10.6189 4.55517 11.3088 4.49873 11.9998 4.49998C15.2717 4.49998 18.2435 5.74686 20.5966 8.09061C22.3591 9.86249 23.156 11.625 23.1842 11.7C23.2257 11.7962 23.2471 11.8999 23.2471 12.0047C23.2471 12.1095 23.2257 12.2132 23.1842 12.3094V12.3094ZM12.5623 9.05624C12.465 9.03777 12.3723 9.00032 12.2896 8.94604C12.2068 8.89176 12.1355 8.82171 12.0798 8.73987C11.9672 8.57461 11.925 8.37141 11.9623 8.17498C11.9996 7.97856 12.1134 7.80499 12.2786 7.69247C12.4439 7.57995 12.6471 7.53769 12.8435 7.57499C13.7999 7.76202 14.6703 8.25257 15.3257 8.97375C15.981 9.69494 16.3862 10.6083 16.481 11.5781C16.4993 11.7757 16.4385 11.9725 16.312 12.1254C16.1855 12.2782 16.0035 12.3747 15.806 12.3937H15.731C15.5455 12.3945 15.3664 12.3255 15.2292 12.2005C15.0921 12.0755 15.0068 11.9036 14.9904 11.7187C14.9257 11.0729 14.6546 10.4651 14.2172 9.98546C13.7798 9.50585 13.1995 9.18 12.5623 9.05624V9.05624Z" fill="#C4C4C4"/>

View File

@@ -1,3 +1,7 @@
<!-- The Lucia project.
Copyright 2023-2026 DSP, inc. All rights reserved.
Authors:
chiayin.kuo@dsp.im (chiayin), 2023/1/31 -->
<template>
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M23.1842 11.7C23.1561 11.625 22.3592 9.8625 20.5967 8.09063C18.2436 5.74688 15.2717 4.5 11.9998 4.5C8.72793 4.5 5.75606 5.74688 3.40293 8.09063C1.64043 9.8625 0.843558 11.625 0.815433 11.7C0.773576 11.7945 0.751953 11.8967 0.751953 12C0.751953 12.1033 0.773576 12.2055 0.815433 12.3C0.843558 12.375 1.64043 14.1375 3.40293 15.9094C5.75606 18.2531 8.72793 19.5 11.9998 19.5C15.2717 19.5 18.2436 18.2531 20.5967 15.9094C22.3592 14.1375 23.1561 12.375 23.1842 12.3C23.226 12.2055 23.2477 12.1033 23.2477 12C23.2477 11.8967 23.226 11.7945 23.1842 11.7ZM11.9998 18C9.11231 18 6.59043 16.95 4.50918 14.8781C3.64906 14.031 2.91925 13.0611 2.34356 12C2.91847 10.9356 3.64831 9.96245 4.50918 9.1125C6.59043 7.05 9.11231 6 11.9998 6C14.8873 6 17.4092 7.05 19.4904 9.1125C20.3513 9.96245 21.0811 10.9356 21.6561 12C20.9811 13.2656 18.0373 18 11.9998 18ZM11.9998 7.5C11.1098 7.5 10.2398 7.76392 9.49974 8.25839C8.75972 8.75285 8.18295 9.45566 7.84235 10.2779C7.50176 11.1002 7.41264 12.005 7.58628 12.8779C7.75991 13.7508 8.18849 14.5526 8.81783 15.182C9.44716 15.8113 10.249 16.2399 11.1219 16.4135C11.9948 16.5872 12.8996 16.4981 13.7219 16.1575C14.5442 15.8169 15.247 15.2401 15.7414 14.5001C16.2359 13.76 16.4998 12.89 16.4998 12C16.4998 10.8065 16.0257 9.66193 15.1818 8.81802C14.3379 7.97411 13.1933 7.5 11.9998 7.5ZM11.9998 15C11.4065 15 10.8264 14.8241 10.3331 14.4944C9.83975 14.1648 9.45523 13.6962 9.22817 13.1481C9.00111 12.5999 8.9417 11.9967 9.05745 11.4147C9.17321 10.8328 9.45893 10.2982 9.87849 9.87868C10.298 9.45912 10.8326 9.1734 11.4145 9.05764C11.9965 8.94189 12.5997 9.0013 13.1479 9.22836C13.696 9.45542 14.1646 9.83994 14.4942 10.3333C14.8239 10.8266 14.9998 11.4067 14.9998 12C14.9973 12.7949 14.6805 13.5565 14.1184 14.1186C13.5563 14.6807 12.7947 14.9975 11.9998 15Z" fill="#0099FF"/>

View File

@@ -1,3 +1,7 @@
<!-- The Lucia project.
Copyright 2023-2026 DSP, inc. All rights reserved.
Authors:
chiayin.kuo@dsp.im (chiayin), 2023/1/31 -->
<template>
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_2381_1348)">

View File

@@ -1,3 +1,7 @@
<!-- The Lucia project.
Copyright 2023-2026 DSP, inc. All rights reserved.
Authors:
chiayin.kuo@dsp.im (chiayin), 2023/1/31 -->
<template>
<svg width="24" height="24" viewBox="0 0 24 24" fill="#86909C" xmlns="http://www.w3.org/2000/svg">
<path d="M1.5 3.58929C1.5 3.03517 1.72012 2.50375 2.11194 2.11194C2.50375 1.72012 3.03517 1.5 3.58929 1.5H7.76786C8.32197 1.5 8.85339 1.72012 9.24521 2.11194C9.63702 2.50375 9.85714 3.03517 9.85714 3.58929V7.76786C9.85714 8.32197 9.63702 8.85339 9.24521 9.24521C8.85339 9.63702 8.32197 9.85714 7.76786 9.85714H3.58929C3.03517 9.85714 2.50375 9.63702 2.11194 9.24521C1.72012 8.85339 1.5 8.32197 1.5 7.76786V3.58929ZM3.58929 2.89286C3.40458 2.89286 3.22744 2.96623 3.09684 3.09684C2.96623 3.22744 2.89286 3.40458 2.89286 3.58929V7.76786C2.89286 7.95256 2.96623 8.1297 3.09684 8.26031C3.22744 8.39091 3.40458 8.46429 3.58929 8.46429H7.76786C7.95256 8.46429 8.1297 8.39091 8.26031 8.26031C8.39091 8.1297 8.46429 7.95256 8.46429 7.76786V3.58929C8.46429 3.40458 8.39091 3.22744 8.26031 3.09684C8.1297 2.96623 7.95256 2.89286 7.76786 2.89286H3.58929ZM12.6429 3.58929C12.6429 3.03517 12.863 2.50375 13.2548 2.11194C13.6466 1.72012 14.178 1.5 14.7321 1.5H18.9107C19.4648 1.5 19.9962 1.72012 20.3881 2.11194C20.7799 2.50375 21 3.03517 21 3.58929V7.76786C21 8.32197 20.7799 8.85339 20.3881 9.24521C19.9962 9.63702 19.4648 9.85714 18.9107 9.85714H14.7321C14.178 9.85714 13.6466 9.63702 13.2548 9.24521C12.863 8.85339 12.6429 8.32197 12.6429 7.76786V3.58929ZM14.7321 2.89286C14.5474 2.89286 14.3703 2.96623 14.2397 3.09684C14.1091 3.22744 14.0357 3.40458 14.0357 3.58929V7.76786C14.0357 7.95256 14.1091 8.1297 14.2397 8.26031C14.3703 8.39091 14.5474 8.46429 14.7321 8.46429H18.9107C19.0954 8.46429 19.2726 8.39091 19.4032 8.26031C19.5338 8.1297 19.6071 7.95256 19.6071 7.76786V3.58929C19.6071 3.40458 19.5338 3.22744 19.4032 3.09684C19.2726 2.96623 19.0954 2.89286 18.9107 2.89286H14.7321ZM1.5 14.7321C1.5 14.178 1.72012 13.6466 2.11194 13.2548C2.50375 12.863 3.03517 12.6429 3.58929 12.6429H7.76786C8.32197 12.6429 8.85339 12.863 9.24521 13.2548C9.63702 13.6466 9.85714 14.178 9.85714 14.7321V18.9107C9.85714 19.4648 9.63702 19.9962 9.24521 20.3881C8.85339 20.7799 8.32197 21 7.76786 21H3.58929C3.03517 21 2.50375 20.7799 2.11194 20.3881C1.72012 19.9962 1.5 19.4648 1.5 18.9107V14.7321ZM3.58929 14.0357C3.40458 14.0357 3.22744 14.1091 3.09684 14.2397C2.96623 14.3703 2.89286 14.5474 2.89286 14.7321V18.9107C2.89286 19.0954 2.96623 19.2726 3.09684 19.4032C3.22744 19.5338 3.40458 19.6071 3.58929 19.6071H7.76786C7.95256 19.6071 8.1297 19.5338 8.26031 19.4032C8.39091 19.2726 8.46429 19.0954 8.46429 18.9107V14.7321C8.46429 14.5474 8.39091 14.3703 8.26031 14.2397C8.1297 14.1091 7.95256 14.0357 7.76786 14.0357H3.58929ZM12.6429 14.7321C12.6429 14.178 12.863 13.6466 13.2548 13.2548C13.6466 12.863 14.178 12.6429 14.7321 12.6429H18.9107C19.4648 12.6429 19.9962 12.863 20.3881 13.2548C20.7799 13.6466 21 14.178 21 14.7321V18.9107C21 19.4648 20.7799 19.9962 20.3881 20.3881C19.9962 20.7799 19.4648 21 18.9107 21H14.7321C14.178 21 13.6466 20.7799 13.2548 20.3881C12.863 19.9962 12.6429 19.4648 12.6429 18.9107V14.7321ZM14.7321 14.0357C14.5474 14.0357 14.3703 14.1091 14.2397 14.2397C14.1091 14.3703 14.0357 14.5474 14.0357 14.7321V18.9107C14.0357 19.0954 14.1091 19.2726 14.2397 19.4032C14.3703 19.5338 14.5474 19.6071 14.7321 19.6071H18.9107C19.0954 19.6071 19.2726 19.5338 19.4032 19.4032C19.5338 19.2726 19.6071 19.0954 19.6071 18.9107V14.7321C19.6071 14.5474 19.5338 14.3703 19.4032 14.2397C19.2726 14.1091 19.0954 14.0357 18.9107 14.0357H14.7321Z" />

View File

@@ -1,3 +1,7 @@
<!-- The Lucia project.
Copyright 2023-2026 DSP, inc. All rights reserved.
Authors:
chiayin.kuo@dsp.im (chiayin), 2023/1/31 -->
<template>
<svg width="24" height="24" viewBox="0 0 24 24" fill="#86909C" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.75 18C3.75 17.8011 3.82902 17.6103 3.96967 17.4697C4.11032 17.329 4.30109 17.25 4.5 17.25H19.5C19.6989 17.25 19.8897 17.329 20.0303 17.4697C20.171 17.6103 20.25 17.8011 20.25 18C20.25 18.1989 20.171 18.3897 20.0303 18.5303C19.8897 18.671 19.6989 18.75 19.5 18.75H4.5C4.30109 18.75 4.11032 18.671 3.96967 18.5303C3.82902 18.3897 3.75 18.1989 3.75 18ZM3.75 12C3.75 11.8011 3.82902 11.6103 3.96967 11.4697C4.11032 11.329 4.30109 11.25 4.5 11.25H19.5C19.6989 11.25 19.8897 11.329 20.0303 11.4697C20.171 11.6103 20.25 11.8011 20.25 12C20.25 12.1989 20.171 12.3897 20.0303 12.5303C19.8897 12.671 19.6989 12.75 19.5 12.75H4.5C4.30109 12.75 4.11032 12.671 3.96967 12.5303C3.82902 12.3897 3.75 12.1989 3.75 12ZM3.75 6C3.75 5.80109 3.82902 5.61032 3.96967 5.46967C4.11032 5.32902 4.30109 5.25 4.5 5.25H19.5C19.6989 5.25 19.8897 5.32902 20.0303 5.46967C20.171 5.61032 20.25 5.80109 20.25 6C20.25 6.19891 20.171 6.38968 20.0303 6.53033C19.8897 6.67098 19.6989 6.75 19.5 6.75H4.5C4.30109 6.75 4.11032 6.67098 3.96967 6.53033C3.82902 6.38968 3.75 6.19891 3.75 6Z" />

View File

@@ -1,3 +1,7 @@
<!-- The Lucia project.
Copyright 2023-2026 DSP, inc. All rights reserved.
Authors:
chiayin.kuo@dsp.im (chiayin), 2023/1/31 -->
<template>
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12 11.75C11.3713 11.7524 10.7643 11.9805 10.2895 12.3926C9.81465 12.8048 9.50353 13.3736 9.41271 13.9958C9.32189 14.6179 9.45738 15.252 9.79456 15.7827C10.1317 16.3134 10.6482 16.7054 11.25 16.8875V18.5C11.25 18.6989 11.329 18.8897 11.4697 19.0303C11.6103 19.171 11.8011 19.25 12 19.25C12.1989 19.25 12.3897 19.171 12.5303 19.0303C12.671 18.8897 12.75 18.6989 12.75 18.5V16.8875C13.3518 16.7054 13.8683 16.3134 14.2054 15.7827C14.5426 15.252 14.6781 14.6179 14.5873 13.9958C14.4965 13.3736 14.1854 12.8048 13.7105 12.3926C13.2357 11.9805 12.6287 11.7524 12 11.75ZM12 15.5C11.7775 15.5 11.56 15.434 11.375 15.3104C11.19 15.1868 11.0458 15.0111 10.9606 14.8055C10.8755 14.6 10.8532 14.3738 10.8966 14.1555C10.94 13.9373 11.0472 13.7368 11.2045 13.5795C11.3618 13.4222 11.5623 13.315 11.7805 13.2716C11.9988 13.2282 12.225 13.2505 12.4305 13.3356C12.6361 13.4208 12.8118 13.565 12.9354 13.75C13.059 13.935 13.125 14.1525 13.125 14.375C13.125 14.6734 13.0065 14.9595 12.7955 15.1705C12.5845 15.3815 12.2984 15.5 12 15.5ZM19.5 8.75H16.125V6.125C16.125 5.03098 15.6904 3.98177 14.9168 3.20818C14.1432 2.4346 13.094 2 12 2C10.906 2 9.85677 2.4346 9.08318 3.20818C8.3096 3.98177 7.875 5.03098 7.875 6.125V8.75H4.5C4.10218 8.75 3.72064 8.90804 3.43934 9.18934C3.15804 9.47064 3 9.85218 3 10.25V20.75C3 21.1478 3.15804 21.5294 3.43934 21.8107C3.72064 22.092 4.10218 22.25 4.5 22.25H19.5C19.8978 22.25 20.2794 22.092 20.5607 21.8107C20.842 21.5294 21 21.1478 21 20.75V10.25C21 9.85218 20.842 9.47064 20.5607 9.18934C20.2794 8.90804 19.8978 8.75 19.5 8.75ZM9.375 6.125C9.375 5.42881 9.65156 4.76113 10.1438 4.26884C10.6361 3.77656 11.3038 3.5 12 3.5C12.6962 3.5 13.3639 3.77656 13.8562 4.26884C14.3484 4.76113 14.625 5.42881 14.625 6.125V8.75H9.375V6.125ZM19.5 20.75H4.5V10.25H19.5V20.75Z" fill="#1A1A1A"/>

View File

@@ -1,3 +1,7 @@
<!-- The Lucia project.
Copyright 2023-2026 DSP, inc. All rights reserved.
Authors:
chiayin.kuo@dsp.im (chiayin), 2023/1/31 -->
<template>
<svg width="40" height="40" viewBox="0 0 40 40" fill="black" xmlns="http://www.w3.org/2000/svg" id="iconMember">
<circle cx="20" cy="20" r="20" fill="white"/>

View File

@@ -1,3 +1,7 @@
<!-- The Lucia project.
Copyright 2023-2026 DSP, inc. All rights reserved.
Authors:
chiayin.kuo@dsp.im (chiayin), 2023/1/31 -->
<template>
<svg width="16" height="16" viewBox="3 0 20 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<g filter="url(#filter0_d_4086_5522)">

View File

@@ -1,3 +1,7 @@
<!-- The Lucia project.
Copyright 2023-2026 DSP, inc. All rights reserved.
Authors:
chiayin.kuo@dsp.im (chiayin), 2023/1/31 -->
<template>
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10 16H22V18H10V16ZM10 10H22V12H10V10Z" fill="#191C21"/>

View File

@@ -1,3 +1,7 @@
<!-- The Lucia project.
Copyright 2023-2026 DSP, inc. All rights reserved.
Authors:
chiayin.kuo@dsp.im (chiayin), 2023/1/31 -->
<template>
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10.5 19C15.1944 19 19 15.1944 19 10.5C19 5.80558 15.1944 2 10.5 2C5.80558 2 2 5.80558 2 10.5C2 15.1944 5.80558 19 10.5 19Z" stroke="#4E5969" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>

View File

@@ -1,3 +1,7 @@
<!-- The Lucia project.
Copyright 2023-2026 DSP, inc. All rights reserved.
Authors:
chiayin.kuo@dsp.im (chiayin), 2023/1/31 -->
<template>
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M22.5 6H19.425C19.05 4.275 17.55 3 15.75 3C13.95 3 12.45 4.275 12.075 6H1.5V7.5H12.075C12.45 9.225 13.95 10.5 15.75 10.5C17.55 10.5 19.05 9.225 19.425 7.5H22.5V6ZM15.75 9C14.475 9 13.5 8.025 13.5 6.75C13.5 5.475 14.475 4.5 15.75 4.5C17.025 4.5 18 5.475 18 6.75C18 8.025 17.025 9 15.75 9ZM1.5 18H4.575C4.95 19.725 6.45 21 8.25 21C10.05 21 11.55 19.725 11.925 18H22.5V16.5H11.925C11.55 14.775 10.05 13.5 8.25 13.5C6.45 13.5 4.95 14.775 4.575 16.5H1.5V18ZM8.25 15C9.525 15 10.5 15.975 10.5 17.25C10.5 18.525 9.525 19.5 8.25 19.5C6.975 19.5 6 18.525 6 17.25C6 15.975 6.975 15 8.25 15Z" fill="#64748B"/>

View File

@@ -1,3 +1,7 @@
<!-- The Lucia project.
Copyright 2023-2026 DSP, inc. All rights reserved.
Authors:
chiayin.kuo@dsp.im (chiayin), 2023/1/31 -->
<template>
<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64" fill="none">
<g clip-path="url(#clip0_2395_2657)">

View File

@@ -1,3 +1,7 @@
<!-- The Lucia project.
Copyright 2023-2026 DSP, inc. All rights reserved.
Authors:
chiayin.kuo@dsp.im (chiayin), 2023/1/31 -->
<template>
<svg width="16" height="16" viewBox="0 0 16 16" fill="black" xmlns="http://www.w3.org/2000/svg">
<path d="M7.9999 16C7.71657 16 7.47924 15.904 7.2879 15.712C7.0959 15.5207 6.9999 15.2833 6.9999 15V3.82499L2.1249 8.69999C1.9249 8.89999 1.68724 8.99999 1.4119 8.99999C1.13724 8.99999 0.899902 8.89999 0.699902 8.69999C0.499902 8.49999 0.399902 8.26665 0.399902 7.99999C0.399902 7.73332 0.499902 7.49999 0.699902 7.29999L7.2999 0.699987C7.3999 0.599987 7.50824 0.528988 7.6249 0.486988C7.74157 0.445654 7.86657 0.424988 7.9999 0.424988C8.13324 0.424988 8.26257 0.445654 8.3879 0.486988C8.51257 0.528988 8.61657 0.599987 8.6999 0.699987L15.2999 7.29999C15.4999 7.49999 15.5999 7.73332 15.5999 7.99999C15.5999 8.26665 15.4999 8.49999 15.2999 8.69999C15.0999 8.89999 14.8622 8.99999 14.5869 8.99999C14.3122 8.99999 14.0749 8.89999 13.8749 8.69999L8.9999 3.82499V15C8.9999 15.2833 8.90424 15.5207 8.7129 15.712C8.5209 15.904 8.28324 16 7.9999 16Z"/>

View File

@@ -1,3 +1,7 @@
<!-- The Lucia project.
Copyright 2023-2026 DSP, inc. All rights reserved.
Authors:
chiayin.kuo@dsp.im (chiayin), 2023/1/31 -->
<template>
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M9.78488 2.03878C9.62343 1.72766 9.37026 1.46508 9.05455 1.28129C8.73885 1.09751 8.37345 1 8.00047 1C7.62748 1 7.26209 1.09751 6.94638 1.28129C6.63068 1.46508 6.37751 1.72766 6.21605 2.03878L0.521086 12.4048C-0.160262 13.6423 0.70072 15.2857 2.3048 15.2857H13.6954C15.3002 15.2857 16.1598 13.643 15.4799 12.4048L9.78488 2.03878ZM8.00047 5.54628C8.18657 5.54628 8.36505 5.61468 8.49664 5.73645C8.62824 5.85822 8.70216 6.02337 8.70216 6.19557V9.44205C8.70216 9.61425 8.62824 9.77941 8.49664 9.90117C8.36505 10.0229 8.18657 10.0913 8.00047 10.0913C7.81437 10.0913 7.63589 10.0229 7.50429 9.90117C7.3727 9.77941 7.29877 9.61425 7.29877 9.44205V6.19557C7.29877 6.02337 7.3727 5.85822 7.50429 5.73645C7.63589 5.61468 7.81437 5.54628 8.00047 5.54628ZM8.00047 11.0653C8.18657 11.0653 8.36505 11.1337 8.49664 11.2555C8.62824 11.3772 8.70216 11.5424 8.70216 11.7146V12.0392C8.70216 12.2114 8.62824 12.3766 8.49664 12.4984C8.36505 12.6201 8.18657 12.6885 8.00047 12.6885C7.81437 12.6885 7.63589 12.6201 7.50429 12.4984C7.3727 12.3766 7.29877 12.2114 7.29877 12.0392V11.7146C7.29877 11.5424 7.3727 11.3772 7.50429 11.2555C7.63589 11.1337 7.81437 11.0653 8.00047 11.0653Z" fill="#FF3366"/>

View File

@@ -1,3 +1,7 @@
<!-- The Lucia project.
Copyright 2023-2026 DSP, inc. All rights reserved.
Authors:
chiayin.kuo@dsp.im (chiayin), 2023/1/31 -->
<template>
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M16 9.33333C22.6274 9.33333 28 8.13943 28 6.66667C28 5.19391 22.6274 4 16 4C9.37258 4 4 5.19391 4 6.66667C4 8.13943 9.37258 9.33333 16 9.33333Z" stroke="#191C21" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>