Merge branch 'develop'
Some checks failed
Spell Check / Spell Check with Typos (push) Failing after 10s
Some checks failed
Spell Check / Spell Check with Typos (push) Failing after 10s
This commit is contained in:
commit
96fc372bf2
16 changed files with 490 additions and 128 deletions
|
|
@ -1,8 +1,4 @@
|
|||
name: Gitea Action
|
||||
|
||||
run-name: Build ${{ github.actor }}
|
||||
|
||||
# Intended for local gitea instance only.
|
||||
name: Deploy Local
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
|
@ -37,22 +33,14 @@ jobs:
|
|||
platforms: linux/amd64
|
||||
tags: ${{ env.CONTAINER_IMAGE_NAME }}
|
||||
push: true
|
||||
- name: Remote Deploy Development
|
||||
- name: Remote Deploy
|
||||
uses: appleboy/ssh-action@v1.2.1
|
||||
with:
|
||||
host: ${{ vars.SSH_DEVELOPMENT_HOST }}
|
||||
port: ${{ vars.SSH_DEVELOPMENT_PORT }}
|
||||
username: ${{ secrets.SSH_DEVELOPMENT_USER }}
|
||||
password: ${{ secrets.SSH_DEVELOPMENT_PASSWORD }}
|
||||
script: eval "${{ secrets.SSH_DEVELOPMENT_DEPLOY_CMD }}" & wait
|
||||
- name: Remote Deploy Test
|
||||
uses: appleboy/ssh-action@v1.2.1
|
||||
with:
|
||||
host: ${{ vars.SSH_TEST_HOST }}
|
||||
port: ${{ vars.SSH_TEST_PORT }}
|
||||
username: ${{ secrets.SSH_TEST_USER }}
|
||||
password: ${{ secrets.SSH_TEST_PASSWORD }}
|
||||
script: eval "${{ secrets.SSH_TEST_DEPLOY_CMD }}" & wait
|
||||
host: ${{ vars.SSH_DEPLOY_HOST }}
|
||||
port: ${{ vars.SSH_DEPLOY_PORT }}
|
||||
username: ${{ secrets.SSH_DEPLOY_USER }}
|
||||
password: ${{ secrets.SSH_DEPLOY_PASSWORD }}
|
||||
script: eval "${{ secrets.SSH_DEPLOY_CMD }}"
|
||||
- name: Notify Discord Success
|
||||
if: success()
|
||||
run: |
|
||||
21
.forgejo/workflows/spellcheck.yaml
Normal file
21
.forgejo/workflows/spellcheck.yaml
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
name: Spell Check
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
env:
|
||||
CLICOLOR: 1
|
||||
|
||||
jobs:
|
||||
spelling:
|
||||
name: Spell Check with Typos
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Actions Repository
|
||||
uses: actions/checkout@v4
|
||||
- name: Spell Check Repo
|
||||
uses: crate-ci/typos@v1.29.9
|
||||
with:
|
||||
files: ./src
|
||||
31
.github/workflows/local-build-dev.yaml
vendored
31
.github/workflows/local-build-dev.yaml
vendored
|
|
@ -1,31 +0,0 @@
|
|||
name: local-build-dev
|
||||
|
||||
# Intended for local network use.
|
||||
# Remote access is possible if the host has a public IP address.
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
REGISTRY: ${{ vars.DOCKER_REGISTRY }}
|
||||
|
||||
jobs:
|
||||
local-build-dev:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Setup Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
with:
|
||||
config-inline: |
|
||||
[registry."${{ env.REGISTRY }}"]
|
||||
http = true
|
||||
insecure = true
|
||||
- name: Build and Push Docker Image
|
||||
uses: docker/build-push-action@v3
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64
|
||||
push: true
|
||||
tags: ${{ env.REGISTRY }}/jws/jws-frontend:dev
|
||||
allow: security.insecure
|
||||
2
.typos.toml
Normal file
2
.typos.toml
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
[default]
|
||||
extend-ignore-re = ["(?Rm)^.*(#|//)\\s*spellchecker:disable-line$"]
|
||||
|
|
@ -45,6 +45,8 @@ type ExclusiveProps = {
|
|||
type: 'service' | 'product';
|
||||
grid?: boolean;
|
||||
disabledWorkerId?: string[];
|
||||
disabledProductFields?: (typeof columnsProduct)[number]['name'][];
|
||||
disabledServiceFields?: (typeof columnsService)[number]['name'][];
|
||||
rows: Product[];
|
||||
};
|
||||
|
||||
|
|
@ -56,6 +58,13 @@ const columnsProduct = [
|
|||
field: (_) => '#check',
|
||||
},
|
||||
|
||||
{
|
||||
name: 'order',
|
||||
align: 'center',
|
||||
label: 'general.order',
|
||||
field: (e: Product & { _index: number }) => e._index + 1,
|
||||
},
|
||||
|
||||
{
|
||||
name: '#productName',
|
||||
align: 'left',
|
||||
|
|
@ -76,7 +85,7 @@ const columnsProduct = [
|
|||
label: 'productService.product.priceInformation',
|
||||
field: (v: Product) => v,
|
||||
},
|
||||
] satisfies QTableColumn[];
|
||||
] as const satisfies QTableColumn[];
|
||||
|
||||
const columnsService = [
|
||||
{
|
||||
|
|
@ -85,6 +94,12 @@ const columnsService = [
|
|||
label: '',
|
||||
field: (_) => '#check',
|
||||
},
|
||||
{
|
||||
name: 'order',
|
||||
align: 'center',
|
||||
label: 'general.order',
|
||||
field: (e: Service & { _index: number }) => e._index + 1,
|
||||
},
|
||||
|
||||
{
|
||||
name: '#serviceName',
|
||||
|
|
@ -110,7 +125,7 @@ const columnsService = [
|
|||
label: 'general.createdAt',
|
||||
field: (v: Service) => dateFormatJS({ date: v.createdAt }),
|
||||
},
|
||||
] satisfies QTableColumn[];
|
||||
] as const satisfies QTableColumn[];
|
||||
|
||||
const props = defineProps<ExclusiveProps>();
|
||||
|
||||
|
|
@ -165,7 +180,18 @@ function selectedIndex(item: any) {
|
|||
:props="props"
|
||||
>
|
||||
<q-th
|
||||
v-for="col in type === 'product' ? columnsProduct : columnsService"
|
||||
v-for="col in type === 'product'
|
||||
? columnsProduct.filter((v) =>
|
||||
disabledProductFields
|
||||
? !disabledProductFields.includes(v.name)
|
||||
: true,
|
||||
)
|
||||
: columnsService.filter((v) =>
|
||||
disabledServiceFields
|
||||
? !disabledServiceFields.includes(v.name)
|
||||
: true,
|
||||
)"
|
||||
:auto-width="col.name === '#check'"
|
||||
:key="col.name"
|
||||
:props="props"
|
||||
>
|
||||
|
|
@ -209,7 +235,17 @@ function selectedIndex(item: any) {
|
|||
class="text-center"
|
||||
>
|
||||
<q-td
|
||||
v-for="col in type === 'product' ? columnsProduct : columnsService"
|
||||
v-for="col in type === 'product'
|
||||
? columnsProduct.filter((v) =>
|
||||
disabledProductFields
|
||||
? !disabledProductFields.includes(v.name)
|
||||
: true,
|
||||
)
|
||||
: columnsService.filter((v) =>
|
||||
disabledServiceFields
|
||||
? !disabledServiceFields.includes(v.name)
|
||||
: true,
|
||||
)"
|
||||
:align="col.align"
|
||||
:key="col.name"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ export default {
|
|||
confirm: 'Confirm',
|
||||
login: 'Login',
|
||||
logout: 'Logout',
|
||||
manage: 'Manage',
|
||||
manage: 'Manage {text}',
|
||||
theme: 'Theme',
|
||||
light: 'Light',
|
||||
dark: 'Dark',
|
||||
|
|
@ -915,6 +915,10 @@ export default {
|
|||
|
||||
salesRepresentative: 'Sales Representative',
|
||||
ref: 'Reference',
|
||||
action: {
|
||||
title: 'Action',
|
||||
configure: 'Configure',
|
||||
},
|
||||
status: {
|
||||
work: {
|
||||
Pending: 'Await for order',
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ export default {
|
|||
confirm: 'ยืนยัน',
|
||||
login: 'เข้าสู่ระบบ',
|
||||
logout: 'ออกจากระบบ',
|
||||
manage: 'จัดการ',
|
||||
manage: 'จัดการ{text}',
|
||||
theme: 'ธีม',
|
||||
light: 'สว่าง',
|
||||
dark: 'มืด',
|
||||
|
|
@ -904,6 +904,10 @@ export default {
|
|||
noWorkflowTemplate: 'คุณไม่ได้เลือกแม่แบบขั้นตอนการทำงาน',
|
||||
salesRepresentative: 'พนักงานขาย',
|
||||
ref: 'อ้างอิง',
|
||||
action: {
|
||||
title: 'จัดการ',
|
||||
configure: 'กำหนดค่า',
|
||||
},
|
||||
status: {
|
||||
work: {
|
||||
Pending: 'รอสั่งงาน',
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ const responsibleUserId = defineModel<string>('responsibleUserId', {
|
|||
defineProps<{
|
||||
readonly?: boolean;
|
||||
districtId?: string;
|
||||
cost?: boolean;
|
||||
}>();
|
||||
|
||||
watch(responsibleUserLocal, (lhs, rhs) => {
|
||||
|
|
|
|||
229
src/pages/08_request-list/RequestAction.vue
Normal file
229
src/pages/08_request-list/RequestAction.vue
Normal file
|
|
@ -0,0 +1,229 @@
|
|||
<script setup lang="ts">
|
||||
import { reactive, ref } from 'vue';
|
||||
import { RequestWork } from 'src/stores/request-list';
|
||||
import { DialogContainer, DialogHeader } from 'src/components/dialog';
|
||||
import {
|
||||
BackButton,
|
||||
CancelButton,
|
||||
MainButton,
|
||||
SaveButton,
|
||||
} from 'src/components/button';
|
||||
import TableProductAndService from 'src/components/shared/table/TableProductAndService.vue';
|
||||
import { Product } from 'src/stores/product-service/types';
|
||||
import FormResponsibleUser from './FormResponsibleUser.vue';
|
||||
import FormGroupHead from './FormGroupHead.vue';
|
||||
|
||||
defineProps<{
|
||||
work: RequestWork[];
|
||||
responsibleDistrictId: string;
|
||||
}>();
|
||||
|
||||
defineEmits<{
|
||||
(
|
||||
e: 'submit',
|
||||
data: {
|
||||
form: { responsibleUserLocal: boolean; responsibleUserId: string };
|
||||
selected: { _work: RequestWork }[];
|
||||
},
|
||||
): void;
|
||||
}>();
|
||||
|
||||
enum Step {
|
||||
Product = 1,
|
||||
Configure = 2,
|
||||
}
|
||||
|
||||
const open = defineModel<boolean>('selected', { default: false });
|
||||
const step = ref<Step>(Step.Product);
|
||||
const selected = ref<{ _work: RequestWork }[]>([]);
|
||||
const form = reactive({
|
||||
responsibleUserLocal: false,
|
||||
responsibleUserId: '',
|
||||
});
|
||||
|
||||
function reset() {
|
||||
step.value = Step.Product;
|
||||
selected.value = [];
|
||||
}
|
||||
|
||||
function prev() {
|
||||
step.value = Step.Product;
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<DialogContainer v-model="open" :onOpen="reset">
|
||||
<template #header>
|
||||
<DialogHeader :title="$t('requestList.action.title')" />
|
||||
</template>
|
||||
|
||||
<div class="surface-0 q-pa-md">
|
||||
<div class="stepper-wrapper">
|
||||
<div class="stepper">
|
||||
<template
|
||||
v-for="(label, i) in [
|
||||
$t('menu.product'),
|
||||
$t('requestList.action.configure'),
|
||||
]"
|
||||
:key="i"
|
||||
>
|
||||
<span class="step" :class="{ ['step__active']: step > i }">
|
||||
<span class="step-outer"><span class="step-inner" /></span>
|
||||
<span class="step-label">{{ label }}</span>
|
||||
</span>
|
||||
<span
|
||||
class="step-connector"
|
||||
:class="{ ['step-connector__active']: step > i + 1 }"
|
||||
/>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="surface-1 q-pa-md col">
|
||||
<TableProductAndService
|
||||
v-if="step === Step.Product"
|
||||
type="product"
|
||||
v-model:selected="selected"
|
||||
:disabled-product-fields="[
|
||||
'#priceInformation',
|
||||
'productProcessingTime',
|
||||
]"
|
||||
:rows="
|
||||
(work?.map((v) => ({
|
||||
...v.productService.product,
|
||||
type: 'product',
|
||||
_work: v,
|
||||
})) || []) as unknown as Product[]
|
||||
"
|
||||
/>
|
||||
|
||||
<template v-if="step === Step.Configure">
|
||||
<q-expansion-item
|
||||
dense
|
||||
class="overflow-hidden bordered full-width"
|
||||
switch-toggle-side
|
||||
style="border-radius: var(--radius-2)"
|
||||
expand-icon="mdi-chevron-down-circle"
|
||||
header-class="surface-1 q-py-sm text-medium text-body1"
|
||||
default-opened
|
||||
>
|
||||
<template #header>
|
||||
<span>
|
||||
{{ $t('requestList.employeeMessenger') }}
|
||||
</span>
|
||||
</template>
|
||||
<FormGroupHead>
|
||||
{{
|
||||
$t('general.select', { msg: $t('requestList.employeeMessenger') })
|
||||
}}
|
||||
</FormGroupHead>
|
||||
|
||||
<FormResponsibleUser
|
||||
:district-id="responsibleDistrictId"
|
||||
v-model:responsible-user-id="form.responsibleUserId"
|
||||
v-model:responsible-user-local="form.responsibleUserLocal"
|
||||
/>
|
||||
</q-expansion-item>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<template #footer>
|
||||
<div class="q-gutter-x-xs q-ml-auto">
|
||||
<CancelButton
|
||||
v-if="step === Step.Product"
|
||||
id="btn-cancel"
|
||||
outlined
|
||||
@click="
|
||||
reset();
|
||||
open = false;
|
||||
"
|
||||
/>
|
||||
<BackButton
|
||||
v-if="step === Step.Configure"
|
||||
id="btn-back"
|
||||
outlined
|
||||
@click="prev"
|
||||
/>
|
||||
<MainButton
|
||||
icon="mdi-check"
|
||||
color="207 96% 32%"
|
||||
solid
|
||||
id="btn-next"
|
||||
v-if="step === Step.Product"
|
||||
@click="step = Step.Configure"
|
||||
>
|
||||
{{ $t('general.next') }}
|
||||
</MainButton>
|
||||
<SaveButton
|
||||
v-if="step === Step.Configure"
|
||||
id="btn-save"
|
||||
solid
|
||||
@click="$emit('submit', { form, selected })"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</DialogContainer>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.stepper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-bottom: 1.5rem;
|
||||
margin-inline: 25%;
|
||||
|
||||
& > .step {
|
||||
--__color: var(--gray-5);
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
gap: 0.25rem;
|
||||
|
||||
&.step__active {
|
||||
--__color: var(--brand-1);
|
||||
}
|
||||
|
||||
& > .step-label {
|
||||
position: absolute;
|
||||
font-weight: 600;
|
||||
color: var(--__color);
|
||||
white-space: nowrap;
|
||||
top: 2rem;
|
||||
}
|
||||
|
||||
& > .step-outer {
|
||||
display: inline-flex;
|
||||
border: 2px solid var(--__color);
|
||||
border-radius: 50%;
|
||||
width: 1.5rem;
|
||||
height: 1.5rem;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
& > .step-inner {
|
||||
display: inline-block;
|
||||
border-radius: 50%;
|
||||
background-color: var(--__color);
|
||||
width: 0.7rem;
|
||||
height: 0.7rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
& > .step-connector {
|
||||
display: block;
|
||||
border-bottom: 2px solid var(--gray-5);
|
||||
flex-grow: 1;
|
||||
|
||||
&.step-connector__active {
|
||||
border-color: var(--brand-1);
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -11,9 +11,10 @@ import PropertiesExpansion from './PropertiesExpansion.vue';
|
|||
import FormGroupHead from './FormGroupHead.vue';
|
||||
import AvatarGroup from 'src/components/shared/AvatarGroup.vue';
|
||||
import { StateButton } from 'components/button';
|
||||
import { CancelButton } from 'components/button';
|
||||
import { CancelButton, MainButton } from 'components/button';
|
||||
import DutyExpansion from './DutyExpansion.vue';
|
||||
import MessengerExpansion from './MessengerExpansion.vue';
|
||||
import RequestAction from './RequestAction.vue';
|
||||
|
||||
// NOTE: Store
|
||||
import {
|
||||
|
|
@ -68,9 +69,41 @@ const statusFile = ref<Attributes>({
|
|||
const refDocumentExpansion = ref<InstanceType<typeof DocumentExpansion>[]>([]);
|
||||
const data = ref<RequestData>();
|
||||
const flow = ref<WorkflowTemplate>();
|
||||
const productsList = computed(() =>
|
||||
workList.value
|
||||
?.filter((v) =>
|
||||
v.productService.work?.attributes.workflowStep?.[
|
||||
pageState.currentStep - 1
|
||||
]?.productsId.includes(v.productService.productId),
|
||||
)
|
||||
.map((v) => {
|
||||
const _props =
|
||||
v.productService.work?.attributes?.workflowStep[
|
||||
pageState.currentStep - 1
|
||||
]?.attributes?.properties;
|
||||
return Object.assign(v, {
|
||||
_documentExpansion: _props.some(
|
||||
(v: PropVariant) => v.fieldName === 'documentCheck',
|
||||
),
|
||||
_formExpansion: _props.some(
|
||||
(v: PropVariant) => v.fieldName === 'designForm',
|
||||
),
|
||||
_dutyExpansion: _props.some((v: PropVariant) => v.fieldName === 'duty'),
|
||||
_messengerExpansion: _props.some(
|
||||
(v: PropVariant) => v.fieldName === 'messenger',
|
||||
),
|
||||
});
|
||||
})
|
||||
.sort(
|
||||
(lhs, rhs) =>
|
||||
lhs.productService.installmentNo - rhs.productService.installmentNo,
|
||||
),
|
||||
);
|
||||
|
||||
const pageState = reactive({
|
||||
hideMetaData: false,
|
||||
currentStep: 1,
|
||||
requestActionDialog: false,
|
||||
});
|
||||
|
||||
// NOTE: Function
|
||||
|
|
@ -342,6 +375,31 @@ function closeTab() {
|
|||
cancel: () => {},
|
||||
});
|
||||
}
|
||||
|
||||
function openRequestAction() {
|
||||
pageState.requestActionDialog = true;
|
||||
}
|
||||
|
||||
async function submitRequestAction(data: {
|
||||
form: { responsibleUserLocal: boolean; responsibleUserId: string };
|
||||
selected: { _work: RequestWork }[];
|
||||
}) {
|
||||
const requestWorksId = data.selected.map((s) => s._work.id);
|
||||
|
||||
const res = await requestListStore.actionRequestWork(
|
||||
route.params['requestListId'] as string,
|
||||
pageState.currentStep,
|
||||
requestWorksId.map((v) => ({
|
||||
responsibleUserId: data.form.responsibleUserId,
|
||||
responsibleUserLocal: data.form.responsibleUserLocal,
|
||||
requestWorkId: v!,
|
||||
})),
|
||||
);
|
||||
if (res) {
|
||||
await getData();
|
||||
pageState.requestActionDialog = false;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<div class="column surface-0 fullscreen" v-if="data">
|
||||
|
|
@ -671,40 +729,7 @@ function closeTab() {
|
|||
</transition>
|
||||
</article>
|
||||
<!-- product -->
|
||||
<template
|
||||
v-for="(value, index) in workList
|
||||
?.filter((v) =>
|
||||
v.productService.work?.attributes.workflowStep?.[
|
||||
pageState.currentStep - 1
|
||||
]?.productsId.includes(v.productService.productId),
|
||||
)
|
||||
.map((v) => {
|
||||
const _props =
|
||||
v.productService.work?.attributes?.workflowStep[
|
||||
pageState.currentStep - 1
|
||||
]?.attributes?.properties;
|
||||
return Object.assign(v, {
|
||||
_documentExpansion: _props.some(
|
||||
(v: PropVariant) => v.fieldName === 'documentCheck',
|
||||
),
|
||||
_formExpansion: _props.some(
|
||||
(v: PropVariant) => v.fieldName === 'designForm',
|
||||
),
|
||||
_dutyExpansion: _props.some(
|
||||
(v: PropVariant) => v.fieldName === 'duty',
|
||||
),
|
||||
_messengerExpansion: _props.some(
|
||||
(v: PropVariant) => v.fieldName === 'messenger',
|
||||
),
|
||||
});
|
||||
})
|
||||
.sort(
|
||||
(lhs, rhs) =>
|
||||
lhs.productService.installmentNo -
|
||||
rhs.productService.installmentNo,
|
||||
)"
|
||||
:key="value"
|
||||
>
|
||||
<template v-for="(value, index) in productsList" :key="value">
|
||||
<ProductExpansion
|
||||
:cancel="data.requestDataStatus === RequestDataStatus.Canceled"
|
||||
:readonly="
|
||||
|
|
@ -873,13 +898,34 @@ function closeTab() {
|
|||
</main>
|
||||
|
||||
<!-- SEC: Footer -->
|
||||
<footer class="surface-1 q-pa-md full-width text-right">
|
||||
<footer
|
||||
class="surface-1 q-pa-md full-width row justify-end"
|
||||
style="gap: var(--size-2)"
|
||||
>
|
||||
<CancelButton
|
||||
outlined
|
||||
@click="closeTab()"
|
||||
:label="$t('dialog.action.close')"
|
||||
outlined
|
||||
/>
|
||||
<MainButton
|
||||
v-if="productsList.some((v) => v._messengerExpansion)"
|
||||
solid
|
||||
icon="mdi-account-outline"
|
||||
color="207 96% 32%"
|
||||
@click="openRequestAction"
|
||||
>
|
||||
{{
|
||||
$t('general.manage', { text: $t('requestList.employeeMessenger') })
|
||||
}}
|
||||
</MainButton>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
<RequestAction
|
||||
v-model="pageState.requestActionDialog"
|
||||
:work="workList"
|
||||
:responsible-district-id="data?.quotation.customerBranch.districtId || ''"
|
||||
@submit="submitRequestAction"
|
||||
/>
|
||||
</template>
|
||||
<style scoped></style>
|
||||
|
|
|
|||
|
|
@ -113,7 +113,8 @@ function handleCheckAll() {
|
|||
validate
|
||||
? status === TaskStatus.Success ||
|
||||
status === TaskStatus.Complete ||
|
||||
status === TaskStatus.Redo
|
||||
status === TaskStatus.Redo ||
|
||||
status === TaskStatus.Restart
|
||||
: status === TaskStatus.Failed ||
|
||||
status === TaskStatus.Success ||
|
||||
status === TaskStatus.Complete ||
|
||||
|
|
@ -196,6 +197,7 @@ function handleCheck(
|
|||
row.taskStatus === TaskStatus.Success ||
|
||||
row.taskStatus === TaskStatus.Complete ||
|
||||
row.taskStatus === TaskStatus.Redo ||
|
||||
row.taskStatus === TaskStatus.Restart ||
|
||||
(selectedEmployee.value.length > 0 &&
|
||||
selectedEmployee.value.some((v) => v._template?.id !== row._template?.id))
|
||||
) {
|
||||
|
|
@ -311,7 +313,7 @@ function disableCheckAll() {
|
|||
class=""
|
||||
>
|
||||
<q-menu :offset="[0, 4]">
|
||||
<q-list v-if="validate">
|
||||
<q-list v-if="validate" dense>
|
||||
<q-item
|
||||
v-if="
|
||||
!selectedEmployee.some(
|
||||
|
|
@ -355,6 +357,25 @@ function disableCheckAll() {
|
|||
></q-icon>
|
||||
{{ $t(`taskOrder.status.Redo`) }}
|
||||
</q-item>
|
||||
<q-item
|
||||
clickable
|
||||
v-close-popup
|
||||
class="items-center"
|
||||
@click="
|
||||
$emit('changeAllStatus', {
|
||||
data: selectedEmployee,
|
||||
status: TaskStatus.Restart,
|
||||
})
|
||||
"
|
||||
>
|
||||
<q-icon
|
||||
style="color: hsl(var(--negative-bg))"
|
||||
name="mdi-file-remove-outline"
|
||||
class="q-pr-sm"
|
||||
size="xs"
|
||||
></q-icon>
|
||||
{{ $t(`taskOrder.status.Restart`) }}
|
||||
</q-item>
|
||||
</q-list>
|
||||
<q-list v-if="!validate" dense>
|
||||
<q-item
|
||||
|
|
@ -445,6 +466,7 @@ function disableCheckAll() {
|
|||
props.row.taskStatus === TaskStatus.Success ||
|
||||
props.row.taskStatus === TaskStatus.Complete ||
|
||||
props.row.taskStatus === TaskStatus.Redo ||
|
||||
props.row.taskStatus === TaskStatus.Restart ||
|
||||
(selectedEmployee.length > 0 &&
|
||||
selectedEmployee.some(
|
||||
(v) => v._template?.id !== props.row._template?.id,
|
||||
|
|
|
|||
|
|
@ -41,7 +41,8 @@ function inactiveCheck() {
|
|||
currStatus.value?.value === TaskStatus.Redo ||
|
||||
currStatus.value?.value === TaskStatus.Success ||
|
||||
currStatus.value?.value === TaskStatus.Complete ||
|
||||
currStatus.value?.value === TaskStatus.Canceled
|
||||
currStatus.value?.value === TaskStatus.Canceled ||
|
||||
currStatus.value?.value === TaskStatus.Restart
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -227,6 +227,7 @@ const messengerListGroup = computed(() =>
|
|||
});
|
||||
|
||||
if (indexUser === -1) {
|
||||
// If user does not exist in acc, create a new entry
|
||||
acc.push({
|
||||
responsibleUser: task.responsibleUser,
|
||||
list: [
|
||||
|
|
@ -236,27 +237,38 @@ const messengerListGroup = computed(() =>
|
|||
},
|
||||
],
|
||||
});
|
||||
if (selectedEmployee.value.length < acc.length) {
|
||||
selectedEmployee.value.push([[]]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const userEntry = acc[indexUser];
|
||||
|
||||
if (indexUser !== -1) {
|
||||
const indexProduct = acc[indexUser].list.findIndex(
|
||||
// Find product in user's list
|
||||
const indexProduct = userEntry.list.findIndex(
|
||||
(v) => v.product.id === task.requestWork.productService.product.id,
|
||||
);
|
||||
|
||||
if (indexProduct === -1) {
|
||||
acc[indexUser].list.push({
|
||||
// If product does not exist in user's list, add it
|
||||
userEntry.list.push({
|
||||
product: task.requestWork.productService.product,
|
||||
list: [record],
|
||||
});
|
||||
}
|
||||
|
||||
if (indexProduct !== -1) {
|
||||
acc[indexUser].list[indexProduct].list.push(record);
|
||||
} else {
|
||||
// Append task to the correct product's list
|
||||
userEntry.list[indexProduct].list.push(record);
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure `selectedEmployee.value` grows dynamically
|
||||
while (selectedEmployee.value.length < acc.length) {
|
||||
selectedEmployee.value.push([]);
|
||||
}
|
||||
|
||||
acc.forEach((accItem, index) => {
|
||||
const length = accItem.list.length;
|
||||
|
||||
while (selectedEmployee.value[index].length < length) {
|
||||
selectedEmployee.value[index].push([]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return acc;
|
||||
|
|
@ -1106,15 +1118,21 @@ watch(
|
|||
step-on
|
||||
:checkbox-on="
|
||||
view === TaskOrderStatus.Validate &&
|
||||
fullTaskOrder?.userTask.find(
|
||||
(fullTaskOrder?.userTask.find(
|
||||
(l) => l.userId === v.responsibleUser.id,
|
||||
)?.userTaskStatus === UserTaskStatus.Submit
|
||||
)?.userTaskStatus === UserTaskStatus.Submit ||
|
||||
fullTaskOrder?.userTask.find(
|
||||
(l) => l.userId === v.responsibleUser.id,
|
||||
)?.userTaskStatus === UserTaskStatus.Restart)
|
||||
"
|
||||
:check-all="
|
||||
view === TaskOrderStatus.Validate &&
|
||||
(view === TaskOrderStatus.Validate &&
|
||||
fullTaskOrder?.userTask.find(
|
||||
(l) => l.userId === v.responsibleUser.id,
|
||||
)?.userTaskStatus === UserTaskStatus.Submit) ||
|
||||
fullTaskOrder?.userTask.find(
|
||||
(l) => l.userId === v.responsibleUser.id,
|
||||
)?.userTaskStatus === UserTaskStatus.Submit
|
||||
)?.userTaskStatus === UserTaskStatus.Restart
|
||||
"
|
||||
:rows="sortList(list)"
|
||||
@change-all-status="
|
||||
|
|
|
|||
|
|
@ -853,6 +853,21 @@ onMounted(async () => {
|
|||
:label="$t('dialog.action.close')"
|
||||
outlined
|
||||
/>
|
||||
<SaveButton
|
||||
v-if="pageState.mode === 'edit'"
|
||||
:disabled="taskListGroup.length === 0"
|
||||
@click="(e) => refForm?.submit(e)"
|
||||
solid
|
||||
/>
|
||||
<EditButton
|
||||
v-if="
|
||||
pageState.mode === 'info' &&
|
||||
creditNoteData?.creditNoteStatus === CreditNoteStatus.Waiting
|
||||
"
|
||||
class="no-print"
|
||||
@click="pageState.mode = 'edit'"
|
||||
solid
|
||||
/>
|
||||
<SaveButton
|
||||
v-if="
|
||||
!creditNoteData ||
|
||||
|
|
@ -869,21 +884,6 @@ onMounted(async () => {
|
|||
icon="mdi-account-multiple-check-outline"
|
||||
solid
|
||||
/>
|
||||
<SaveButton
|
||||
v-if="pageState.mode === 'edit'"
|
||||
:disabled="taskListGroup.length === 0"
|
||||
@click="(e) => refForm?.submit(e)"
|
||||
solid
|
||||
/>
|
||||
<EditButton
|
||||
v-if="
|
||||
pageState.mode === 'info' &&
|
||||
creditNoteData?.creditNoteStatus === CreditNoteStatus.Waiting
|
||||
"
|
||||
class="no-print"
|
||||
@click="pageState.mode = 'edit'"
|
||||
solid
|
||||
/>
|
||||
</nav>
|
||||
</footer>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1296,7 +1296,10 @@ async function submitAccepted() {
|
|||
id="btn-close"
|
||||
@click="closeTab()"
|
||||
:label="$t('dialog.action.close')"
|
||||
v-if="pageState.mode === 'info' && closeAble()"
|
||||
v-if="
|
||||
(pageState.mode === 'info' || pageState.mode === 'create') &&
|
||||
closeAble()
|
||||
"
|
||||
/>
|
||||
|
||||
<div class="row q-gutter-x-sm q-ml-xs">
|
||||
|
|
|
|||
|
|
@ -276,6 +276,24 @@ export const useRequestList = defineStore('request-list', () => {
|
|||
return false;
|
||||
}
|
||||
|
||||
async function actionRequestWork(
|
||||
requestDataId: string,
|
||||
step: number,
|
||||
body: (Omit<Step, 'step'> & {
|
||||
requestWorkId: string;
|
||||
})[],
|
||||
successAll?: boolean,
|
||||
) {
|
||||
const res = await api.put<Step[]>(
|
||||
`/request-data/${requestDataId}/request-work/step-status/${step}`,
|
||||
body,
|
||||
{ params: { successAll } },
|
||||
);
|
||||
|
||||
if (res.status < 400) return res.data;
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
data,
|
||||
page,
|
||||
|
|
@ -296,6 +314,8 @@ export const useRequestList = defineStore('request-list', () => {
|
|||
editStatusRequestWork,
|
||||
|
||||
cancelRequest,
|
||||
|
||||
actionRequestWork,
|
||||
};
|
||||
});
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue