clone code

This commit is contained in:
Kittapath 2023-06-01 12:54:58 +07:00
parent c9597d1e38
commit d57bcd1719
362 changed files with 104804 additions and 0 deletions

4
.env.production Normal file
View file

@ -0,0 +1,4 @@
VITE_COMPETITIVE_EXAM_PANEL=VITE_COMPETITIVE_EXAM_PANEL
VITE_QUALIFY_DISABLE_EMAM_PANEL=VITE_QUALIFY_DISABLE_EMAM_PANEL
VITE_QUALIFY_EXAM_PANEL=VITE_QUALIFY_EXAM_PANEL
VITE_S3CLUSTER_PUBLIC_URL=VITE_S3CLUSTER_PUBLIC_URL

21
.eslintrc.cjs Normal file
View file

@ -0,0 +1,21 @@
/* eslint-env node */
require("@rushstack/eslint-patch/modern-module-resolution");
module.exports = {
root: true,
extends: [
"plugin:vue/vue3-essential",
"eslint:recommended",
"@vue/eslint-config-typescript/recommended",
"@vue/eslint-config-prettier/recommended",
],
overrides: [
{
files: ["cypress/e2e/**/*.{cy,spec}.{js,ts,jsx,tsx}"],
extends: ["plugin:cypress/recommended"],
},
],
parserOptions: {
ecmaVersion: "latest",
},
};

39
.github/workflows/build-local.yaml vendored Normal file
View file

@ -0,0 +1,39 @@
# use for local build with act
name: build-local
run-name: build-local ${{ github.actor }}
on:
workflow_dispatch:
env:
REGISTRY: docker.frappet.com
IMAGE_NAME: demo/bma-ehr-app
jobs:
# act workflow_dispatch -W .github/workflows/build-local.yaml --input IMAGE_VER=test-v1
build-local:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
# skip Set up QEMU because it fail on act and container
- name: Gen Version
id: gen_ver
run: |
if [[ $GITHUB_REF == 'refs/tags/'* ]]; then
IMAGE_VER='${GITHUB_REF/refs\/tags\//}'
else
IMAGE_VER=${{ github.event.inputs.IMAGE_VER }}
fi
if [[ $IMAGE_VER == '' ]]; then
IMAGE_VER='test-vBeta'
fi
echo '::set-output name=image_ver::'$IMAGE_VER
- name: Test Version
run: |
echo $GITHUB_REF
echo ${{ steps.gen_ver.outputs.image_ver }}
- name: Build and load local docker image
uses: docker/build-push-action@v3
with:
context: .
platforms: linux/amd64
load: true
tags: ${{env.REGISTRY}}/${{env.IMAGE_NAME}}:${{ steps.gen_ver.outputs.image_ver }},${{env.REGISTRY}}/${{env.IMAGE_NAME}}:latest

86
.github/workflows/release.yaml vendored Normal file
View file

@ -0,0 +1,86 @@
name: release-test
run-name: release-test ${{ github.actor }}
on:
# push:
# tags:
# - 'v[0-9]+.[0-9]+.[0-9]+'
# tags-ignore:
# - '2.*'
# Allow run workflow manually from Action tab
workflow_dispatch:
env:
REGISTRY: docker.frappet.com
IMAGE_NAME: ehr/bma-ehr-app
DEPLOY_HOST: frappet.com
COMPOSE_PATH: /home/frappet/docker/bma-ehr
TOKEN_LINE: uxuK5hDzS2DsoC5piJBrWRLiz8GgY7iMZZldOWsDDF0
jobs:
# # act workflow_dispatch -W .github/workflows/release.yaml --input IMAGE_VER=test-v1 -s DOCKER_USER=sorawit -s DOCKER_PASS=P@ssword -s SSH_PASSWORD=P@ssw0rd
# release-test:
# runs-on: ubuntu-latest
# steps:
# - uses: actions/checkout@v3
# # skip Set up QEMU because it fail on act and container
# # Gen Version try to get version from tag or inut
# - name: Gen Version
# id: gen_ver
# run: |
# if [[ $GITHUB_REF == 'refs/tags/'* ]]; then
# IMAGE_VER='${GITHUB_REF/refs\/tags\//}'
# else
# IMAGE_VER=${{ github.event.inputs.IMAGE_VER }}
# fi
# if [[ $IMAGE_VER == '' ]]; then
# IMAGE_VER='test-vBeta'
# fi
# echo '::set-output name=image_ver::'$IMAGE_VER
# - name: Check Version
# run: |
# echo $GITHUB_REF
# echo ${{ steps.gen_ver.outputs.image_ver }}
# - name: Set up Docker Buildx
# uses: docker/setup-buildx-action@v2
# - name: Login in to registry
# uses: docker/login-action@v2
# with:
# registry: ${{env.REGISTRY}}
# username: ${{secrets.DOCKER_USER}}
# password: ${{secrets.DOCKER_PASS}}
# - name: Build and push docker image
# uses: docker/build-push-action@v3
# with:
# context: .
# platforms: linux/amd64
# push: true
# tags: ${{env.REGISTRY}}/${{env.IMAGE_NAME}}:${{ steps.gen_ver.outputs.image_ver }},${{env.REGISTRY}}/${{env.IMAGE_NAME}}:latest
# - name: Remote Deployment
# uses: appleboy/ssh-action@v0.1.8
# with:
# host: ${{env.DEPLOY_HOST}}
# username: frappet
# password: ${{ secrets.SSH_PASSWORD }}
# port: 22
# script: |
# cd "${{env.COMPOSE_PATH}}"
# docker-compose pull
# docker-compose up -d
# echo "${{ steps.gen_ver.outputs.image_ver }}"> success
# - uses: snow-actions/line-notify@v1.1.0
# if: success()
# with:
# access_token: ${{ env.TOKEN_LINE }}
# message: |
# -Success✅✅✅
# Image: ${{env.IMAGE_NAME}}
# Version: ${{ github.event.inputs.IMAGE_VER }}
# By: ${{secrets.DOCKER_USER}}
# - uses: snow-actions/line-notify@v1.1.0
# if: failure()
# with:
# access_token: ${{ env.TOKEN_LINE }}
# message: |
# -Failure❌❌❌
# Image: ${{env.IMAGE_NAME}}
# Version: ${{ github.event.inputs.IMAGE_VER }}
# By: ${{secrets.DOCKER_USER}}

28
.gitignore vendored Normal file
View file

@ -0,0 +1,28 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
.DS_Store
dist
dist-ssr
coverage
*.local
/cypress/videos/
/cypress/screenshots/
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

1
.prettierrc.json Normal file
View file

@ -0,0 +1 @@
{}

3
.vscode/extensions.json vendored Normal file
View file

@ -0,0 +1,3 @@
{
"recommendations": ["Vue.volar", "Vue.vscode-typescript-vue-plugin"]
}

21
Dockerfile Normal file
View file

@ -0,0 +1,21 @@
# docker build . -t docker.frappet.com/demo/fe:latest
FROM node:latest as build-stage
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY ./ .
RUN npm run build
FROM nginx as production-stage
RUN mkdir /app
COPY --from=build-stage /app/dist /app
COPY nginx.conf /etc/nginx/nginx.conf
COPY entrypoint.sh /usr/local/bin/entrypoint.sh
RUN chmod u+x /usr/local/bin/entrypoint.sh
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
CMD ["nginx", "-g", "daemon off;"]

8
cypress.config.ts Normal file
View file

@ -0,0 +1,8 @@
import { defineConfig } from 'cypress'
export default defineConfig({
e2e: {
specPattern: 'cypress/e2e/**/*.{cy,spec}.{js,jsx,ts,tsx}',
baseUrl: 'http://localhost:4173'
}
})

View file

@ -0,0 +1,8 @@
// https://docs.cypress.io/api/introduction/api.html
describe('My First Test', () => {
it('visits the app root url', () => {
cy.visit('/')
cy.contains('h1', 'You did it!')
})
})

10
cypress/e2e/tsconfig.json Normal file
View file

@ -0,0 +1,10 @@
{
"extends": "@vue/tsconfig/tsconfig.web.json",
"include": ["./**/*", "../support/**/*"],
"compilerOptions": {
"isolatedModules": false,
"target": "es5",
"lib": ["es5", "dom"],
"types": ["cypress"]
}
}

View file

@ -0,0 +1,5 @@
{
"name": "Using fixtures to represent data",
"email": "hello@cypress.io",
"body": "Fixtures are a great way to mock data for responses to routes"
}

View file

@ -0,0 +1,39 @@
/// <reference types="cypress" />
// ***********************************************
// This example commands.ts shows you how to
// create various custom commands and overwrite
// existing commands.
//
// For more comprehensive examples of custom
// commands please read more here:
// https://on.cypress.io/custom-commands
// ***********************************************
//
//
// -- This is a parent command --
// Cypress.Commands.add('login', (email, password) => { ... })
//
//
// -- This is a child command --
// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
//
//
// -- This is a dual command --
// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
//
//
// -- This will overwrite an existing command --
// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
//
// declare global {
// namespace Cypress {
// interface Chainable {
// login(email: string, password: string): Chainable<void>
// drag(subject: string, options?: Partial<TypeOptions>): Chainable<Element>
// dismiss(subject: string, options?: Partial<TypeOptions>): Chainable<Element>
// visit(originalFn: CommandOriginalFn, url: string, options: Partial<VisitOptions>): Chainable<Element>
// }
// }
// }
export {}

20
cypress/support/e2e.ts Normal file
View file

@ -0,0 +1,20 @@
// ***********************************************************
// This example support/index.js is processed and
// loaded automatically before your test files.
//
// This is a great place to put global configuration and
// behavior that modifies Cypress.
//
// You can change the location of this file or turn off
// automatically serving support files with the
// 'supportFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/configuration
// ***********************************************************
// Import commands.js using ES2015 syntax:
import './commands'
// Alternatively you can use CommonJS syntax:
// require('./commands')

19
entrypoint.sh Normal file
View file

@ -0,0 +1,19 @@
#!/bin/sh
ROOT_DIR=/app
# Replace env vars in JavaScript files
echo "Replacing env constants in JS"
for file in $ROOT_DIR/assets/app.*.js* $ROOT_DIR/js/app.*.js* $ROOT_DIR/index.html $ROOT_DIR/precache-manifest*.js;
do
echo "Processing $file ...";
sed -i 's|VITE_COMPETITIVE_EXAM_PANEL|'${VITE_COMPETITIVE_EXAM_PANEL}'|g' $file
sed -i 's|VITE_QUALIFY_DISABLE_EMAM_PANEL|'${VITE_QUALIFY_DISABLE_EMAM_PANEL}'|g' $file
sed -i 's|VITE_QUALIFY_EXAM_PANEL|'${VITE_QUALIFY_EXAM_PANEL}'|g' $file
sed -i 's|VITE_S3CLUSTER_PUBLIC_URL|'${VITE_S3CLUSTER_PUBLIC_URL}'|g' $file
done
echo "Starting Nginx"
nginx -g 'daemon off;'

1
env.d.ts vendored Normal file
View file

@ -0,0 +1 @@
/// <reference types="vite/client" />

13
index.html Normal file
View file

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="icon" href="/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ระบบทรัพยากรบุคคล</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>

30
nginx.conf Normal file
View file

@ -0,0 +1,30 @@
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name localhost;
location / {
root /app;
index index.html;
try_files $uri $uri/ /index.html;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
}

14326
package-lock.json generated Normal file

File diff suppressed because it is too large Load diff

62
package.json Normal file
View file

@ -0,0 +1,62 @@
{
"name": "ehr",
"version": "0.0.0",
"private": true,
"scripts": {
"dev": "vite",
"build": "run-p type-check build-only",
"preview": "vite preview",
"test:unit": "vitest --environment jsdom --root src/",
"test:e2e": "start-server-and-test preview :4173 'cypress run --e2e'",
"test:e2e:dev": "start-server-and-test 'vite dev --port 4173' :4173 'cypress open --e2e'",
"build-only": "vite build",
"type-check": "vue-tsc --noEmit -p tsconfig.vitest.json --composite false",
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore"
},
"dependencies": {
"@fullcalendar/core": "^6.0.1",
"@fullcalendar/daygrid": "^6.0.1",
"@fullcalendar/interaction": "^6.0.2",
"@fullcalendar/list": "^6.0.2",
"@fullcalendar/react": "^6.0.1",
"@fullcalendar/timegrid": "^6.0.2",
"@fullcalendar/vue3": "^6.0.1",
"@quasar/extras": "^1.15.8",
"@vuepic/vue-datepicker": "^3.6.3",
"bma-org-chart": "^0.0.7",
"keycloak-js": "^20.0.2",
"moment": "^2.29.4",
"pinia": "^2.0.29",
"quasar": "^2.11.1",
"structure-chart": "^0.0.9",
"vue": "^3.2.45",
"vue-router": "^4.1.6",
"vue3-datepicker": "^0.3.4"
},
"devDependencies": {
"@quasar/vite-plugin": "^1.3.0",
"@rushstack/eslint-patch": "^1.1.4",
"@types/jsdom": "^20.0.1",
"@types/node": "^18.11.12",
"@vitejs/plugin-vue": "^4.0.0",
"@vitejs/plugin-vue-jsx": "^3.0.0",
"@vue/eslint-config-prettier": "^7.0.0",
"@vue/eslint-config-typescript": "^11.0.0",
"@vue/test-utils": "^2.2.6",
"@vue/tsconfig": "^0.1.3",
"cypress": "^12.0.2",
"eslint": "^8.22.0",
"eslint-plugin-cypress": "^2.12.1",
"eslint-plugin-vue": "^9.3.0",
"jsdom": "^20.0.3",
"npm-run-all": "^4.1.5",
"prettier": "^2.7.1",
"sass": "^1.32.12",
"start-server-and-test": "^1.15.2",
"typescript": "~4.7.4",
"vite": "^4.0.0",
"vitest": "^0.25.6",
"vue-table-to-excel": "^1.0.6",
"vue-tsc": "^1.0.12"
}
}

BIN
public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 MiB

15
src/App.vue Normal file
View file

@ -0,0 +1,15 @@
<script setup lang="ts">
</script>
<template>
<div id="azay-admin-app">
<router-view v-slot="{ Component }">
<transition>
<component :is="Component" />
</transition>
</router-view>
</div>
</template>
<style scoped>
</style>

View file

@ -0,0 +1,14 @@
/**
* API Structure + Org Chart
*/
import env from "../index"
const treeRoot = `${env.API_URI}/Organization/treeroot`
const structChart = `${env.API_URI}/Organization/struct-chart/`
const orgChart = `${env.API_URI}/Organization/org-chart/`
export default {
chartGetTreeRoot: `${treeRoot}`,
chartGetStructure: (id: string) => `${structChart}${id}`,
chartGetOrg: (id: string) => `${orgChart}${id}`
}

View file

@ -0,0 +1,80 @@
/**
* api Tree
*
*/
import env from "../index";
//Dropdown เพิ่มโครงร้างหน่วยงาน
// const organizationAgency = `${env.API_URI_ORG_SERVICE}/organization-agency/`;
// const organizationGovernmentAgency = `${env.API_URI_ORG_SERVICE}/organization-government-agency/`;
// const organizationPath = `${env.API_URI}/Organization/tree`;
const organizationPath = `${env.API_URI_ORG_SERVICE}/Organization/`;
const postionMasterPath = `${env.API_URI_ORG_SERVICE}/PositionMaster`;
const organizationPosition = `${env.API_URI_ORG_SERVICE}/OrganizationPosition/`;
const report = `${env.API_URI}/report/organization/`;
export default {
getOCType: `${report}oc-type`,
getReportAccount1: (id: string) => `${report}account1/${id}`,
getReportAccount2: (id: string) => `${report}account2/${id}`,
getReportAccount3: (id: string) => `${report}account3/${id}`,
/**api /
* @param organizationType
* @returns organizationId and organizationName
*/
listOrganizationAgency: (organizationType: string) =>
`${organizationPath}type/${organizationType}`,
/**api Tree
*
*/
// treeList: `${organizationPath}`,
getTreeRoot: `${organizationPath}treeroot`,
getDraftTreeRoot: `${organizationPath}history/treeroot`,
getTreeHistory: `${organizationPath}publish-history`,
getTreeNode: (organizationId: string, keyId: string) =>
`${organizationPath}tree?organizationId=${organizationId}&keyId=${keyId}`,
getDraftTreeNode: (organizationId: string, keyId: string) =>
`${organizationPath}history/tree?organizationId=${organizationId}&keyId=${keyId}`,
addTreeDraft: `${organizationPosition}history`,
editTreeOrgDraft: (organizationId: string) =>
`${organizationPath}history/${organizationId}`,
getOrgDraft: (organizationId: string) =>
`${organizationPath}history/${organizationId}`,
// /api/v1/Organization/history?organizationPositionId=65ab2ddc-b9d2-4422-83d4-b90dd8191b6f
delTreeOrgDraft: (organizationId: string) =>
`${organizationPath}history?organizationPositionId=${organizationId}`,
getPostionMasterDraft: (showAll: boolean) =>
`${postionMasterPath}/history?showall=${showAll}`,
getPostionMaster: (showAll: boolean) =>
`${postionMasterPath}?showall=${showAll}`,
editTreePositionDraft: (organizationPositionId: string) =>
`${organizationPosition}history?organizationPositionId=${organizationPositionId}`,
// /api/v1/OrganizationPosition/history?organizationPositionId=15ec8c2b-796f-4fad-b731-667a232e723e
delTreePositionDraft: (organizationPositionId: string) =>
`${organizationPosition}history/${organizationPositionId}`,
//PUT /api/v1/OrganizationPosition/history/publish
publishOrgPoDraft: `${organizationPosition}history/publish`,
//PUT /api/v1/OrganizationPosition/history/sync
delTreeOrgPoDraft: `${organizationPosition}history/sync`,
isOrgPohasDraft: `${organizationPosition}history/has-draft`,
isOrghasDraft: `${organizationPath}history/has-draft`,
/**
* api
*/
getPositionMaster: `${postionMasterPath}/history`,
getPositionMasterId: (id: string) => `${postionMasterPath}/history/${id}`,
getPositionMasterPublish: `${postionMasterPath}/history/publish`,
getPositionMasterSync: `${postionMasterPath}/history/sync`,
getPositionMasterHistoryId: (id: string) =>
`${postionMasterPath}/history/publish/${id}`,
getPositionMasterPositionNumber: `${postionMasterPath}/position-number`,
getPositionMasterPositionNumberId: (id: string) =>
`${postionMasterPath}/position-number/${id}`,
getPositionNumberIdByOcId: (OcId: string) =>
`${postionMasterPath}/position-number/Oc/${OcId}`,
};

View file

@ -0,0 +1,6 @@
/**
* api
*/
import env from "../index";
export default {};

View file

@ -0,0 +1,6 @@
/**
* api
*/
import env from "../index";
export default {};

View file

@ -0,0 +1,6 @@
/**
* api
*/
import env from "../index";
export default {};

62
src/api/index.ts Normal file
View file

@ -0,0 +1,62 @@
/**config api */
import { ref } from "vue";
const env = ref<string>(process.env.NODE_ENV || "development");
// if (process.env.VUE_APP_TEST) {
// env = "test";
// }
const config = ref<any>({
development: {
// API_URI: "https://localhost:7006/api/v1",
API_URI: "https://bma-ehr.frappet.synology.me/api/v1",
// API_URI_ORG_SERVICE: "https://localhost:7056/api/v1", //ใช้ชั่วคราว
API_URI_ORG_SERVICE: "https://bma-ehr.frappet.synology.me/api/v1", //ใช้ชั่วคราว
// API_URI_PROFILE_SERVICE: "https://localhost:7159/api/v1",
API_URI_PROFILE_SERVICE: "https://bma-ehr.frappet.synology.me/api/v1", //ใช้ชั่วคราว
// API_CANDIDATE_URI: "https://localhost:7007/api/v1",
API_CANDIDATE_URI: "https://bma-ehr.frappet.synology.me/api/v1",
// API_REPORT_URI: "https://localhost:7187/api/v1",
API_REPORT_URI: "https://bma-ehr.frappet.synology.me/api/v1",
MEET_URI: "meet.frappet.com",
},
test: {
API_URI: "http://localhost:5010/api/v1",
API_CANDIDATE_URI: "https://localhost:7007/api/v1",
API_REPORT_URI: "https://localhost:7007/api/v1",
MEET_URI: "meet.frappet.com",
},
production: {
// API_URI: "https://localhost:5010",
API_URI: `${window.location.protocol}//${window.location.host}/api/v1`,
API_URI_ORG_SERVICE: `${window.location.protocol}//${window.location.host}/api/v1`, //ใช้ชั่วคราว
API_URI_PROFILE_SERVICE: `${window.location.protocol}//${window.location.host}/api/v1`,
API_CANDIDATE_URI: `${window.location.protocol}//${window.location.host}/api/v1`,
API_REPORT_URI: `${window.location.protocol}//${window.location.host}/api/v1`,
MEET_URI: "meet.frappet.com",
},
});
const API_URI = ref<string>(config.value[env.value].API_URI);
const API_CANDIDATE_URI = ref<string>(
config.value[env.value].API_CANDIDATE_URI
);
const API_REPORT_URI = ref<string>(config.value[env.value].API_REPORT_URI);
const API_URI_ORG_SERVICE = ref<string>(
config.value[env.value].API_URI_ORG_SERVICE
);
const MEET_URI = ref<string>(config.value[env.value].MEET_URI);
const API_URI_PROFILE_SERVICE = ref<string>(
config.value[env.value].API_URI_PROFILE_SERVICE
);
export default {
env: env.value,
config: config.value,
API_URI: API_URI.value,
API_CANDIDATE_URI: API_CANDIDATE_URI.value,
API_REPORT_URI: API_REPORT_URI.value,
API_URI_ORG_SERVICE: API_URI_ORG_SERVICE.value,
API_URI_PROFILE_SERVICE: API_URI_PROFILE_SERVICE.value,
MEET_URI: MEET_URI.value,
};

View file

@ -0,0 +1,23 @@
/**
* api
* เมนูย่อย: ปฏิทินวันหยุด
*/
import env from "../index";
const holiday = `${env.API_URI}/metadata/holiday/`;
export default {
/**
* api
*/
listHolidayHistoryAdd: (category: string) =>
`${holiday}range/add/${category}`,
listHolidayHistoryEdit: (category: string) =>
`${holiday}range/edit/${category}`,
listHolidayHistoryDelete: (category: string) =>
`${holiday}range/delete/${category}`,
listHolidayHistoryYear: (year: number) => `${holiday}${year}`,
listHolidayHistoryYearMonth: (year: number, month: number) =>
`${holiday}${year}/${month}`,
listHolidayCopy: `${holiday}copy`,
summaryHolidayHistoryYear: (year: number) => `${holiday}summary/${year}`,
};

View file

@ -0,0 +1,35 @@
/**
* api
* เมนูย่อย: ข้อมูลเครื่องราชอิสริยาภรณ์
*/
import env from "../index";
const insignia = `${env.API_URI}/metadata/insignia/`;
const insigniaType = `${env.API_URI}/metadata/insignia-type/`;
export default {
/**
* api
*/
insignia,
listInsigniaHistory: `${insignia}history`,
listInsigniaHistoryId: (id: string) => `${insignia}history/${id}`,
listInsigniaPublished: `${insignia}history/published`,
listInsigniaPublishedHistory: `${insignia}history/published-history`,
/**
* api
*/
insigniaType,
listInsigniaTypeHistory: `${insigniaType}history`,
listInsigniaTypeHistoryId: (id: string) => `${insigniaType}history/${id}`,
listInsigniaTypePublished: `${insigniaType}history/published`,
listInsigniaTypePublishedHistory: `${insigniaType}history/published-history`,
/**
* api
*/
// listInsigniaHistory: `${insignia}history`,
// listInsigniaHistoryId: (id: string) => `${insignia}history/${id}`,
// listInsigniaPublished: `${insignia}history/published`,
// listInsigniaPublishedHistory: `${insignia}history/published-history`,
};

View file

@ -0,0 +1,130 @@
/**
* api
* เมนูย่อย: ข้อมูลโครงสร้างหน่วยงาน
*/
import env from "../index"
const organization = `${env.API_URI}/metadata/organization/`
const organizationOrganization = `${env.API_URI}/metadata/organization-organization/`
const organizationShortName = `${env.API_URI}/metadata/organization-shortname/`
const organizationCode = `${env.API_URI_ORG_SERVICE}/PositionMaster/`
const organizationType = `${env.API_URI}/metadata/organization-type/`
const organizationLevel = `${env.API_URI}/metadata/organization-level/`
const organizationStatus = `${env.API_URI}/metadata/organization-status/`
const organizationAgency = `${env.API_URI}/metadata/organization-agency/`
const organizationGovernmentAgency = `${env.API_URI}/metadata/organization-government-agency/`
const organizationTelExternal = `${env.API_URI}/metadata/organization-tel-external/`
const organizationTelInternal = `${env.API_URI}/metadata/organization-tel-internal/`
const organizationFax = `${env.API_URI}/metadata/organization-fax/`
const dashbord = `${env.API_URI}/metadata/dashbord/`
export default {
/**
* api tab tab
*/
organization,
countDashbordSubHistory: (type: number) => `${dashbord}${type}`,
countDashbordHistory: `${dashbord}`,
/**
* api
*/
listOrganizationOrganizationHistory: `${organizationOrganization}history`,
listOrganizationOrganizationHistoryId: (id: string) =>
`${organizationOrganization}history/${id}`,
listOrganizationOrganizationPublished: `${organizationOrganization}history/published`,
listOrganizationOrganizationPublishedHistory: `${organizationOrganization}history/published-history`,
/**
* api
*/
organizationShortName,
listOrganizationShortNameHistory: `${organizationShortName}history`,
listOrganizationShortNameHistoryId: (id: string) =>
`${organizationShortName}history/${id}`,
listOrganizationShortNamePublished: `${organizationShortName}history/published`,
listOrganizationShortNamePublishedHistory: `${organizationShortName}history/published-history`,
organizationCode: `${organizationCode}organization-code`,
organizationGovernmentCode: (id: string) =>
`${organizationCode}government/${id}`,
organizationAgencyCode: (id: string) => `${organizationCode}agency/${id}`,
/**
* api
*/
organizationType,
listOrganizationTypeHistory: `${organizationType}history`,
listOrganizationTypeHistoryId: (id: string) =>
`${organizationType}history/${id}`,
listOrganizationTypePublished: `${organizationType}history/published`,
listOrganizationTypePublishedHistory: `${organizationType}history/published-history`,
/**
* api
*/
organizationLevel,
listOrganizationLevelHistory: `${organizationLevel}history`,
listOrganizationLevelHistoryId: (id: string) =>
`${organizationLevel}history/${id}`,
listOrganizationLevelPublished: `${organizationLevel}history/published`,
listOrganizationLevelPublishedHistory: `${organizationLevel}history/published-history`,
/**
* api
*/
organizationStatus,
listOrganizationStatusHistory: `${organizationStatus}history`,
listOrganizationStatusHistoryId: (id: string) =>
`${organizationStatus}history/${id}`,
listOrganizationStatusPublished: `${organizationStatus}history/published`,
listOrganizationStatusPublishedHistory: `${organizationStatus}history/published-history`,
/**
* api
*/
organizationAgency,
listOrganizationAgencyHistory: `${organizationAgency}history`,
listOrganizationAgencyHistoryId: (id: string) =>
`${organizationAgency}history/${id}`,
listOrganizationAgencyPublished: `${organizationAgency}history/published`,
listOrganizationAgencyPublishedHistory: `${organizationAgency}history/published-history`,
/**
* api
*/
organizationGovernmentAgency,
listOrganizationGovernmentAgencyHistory: `${organizationGovernmentAgency}history`,
listOrganizationGovernmentAgencyHistoryId: (id: string) =>
`${organizationGovernmentAgency}history/${id}`,
listOrganizationGovernmentAgencyPublished: `${organizationGovernmentAgency}history/published`,
listOrganizationGovernmentAgencyPublishedHistory: `${organizationGovernmentAgency}history/published-history`,
/**
* api
*/
organizationTelExternal,
listOrganizationTelExternalHistory: `${organizationTelExternal}history`,
listOrganizationTelExternalHistoryId: (id: string) =>
`${organizationTelExternal}history/${id}`,
listOrganizationTelExternalPublished: `${organizationTelExternal}history/published`,
listOrganizationTelExternalPublishedHistory: `${organizationTelExternal}history/published-history`,
/**
* api
*/
organizationTelInternal,
listOrganizationTelInternalHistory: `${organizationTelInternal}history`,
listOrganizationTelInternalHistoryId: (id: string) =>
`${organizationTelInternal}history/${id}`,
listOrganizationTelInternalPublished: `${organizationTelInternal}history/published`,
listOrganizationTelInternalPublishedHistory: `${organizationTelInternal}history/published-history`,
/**
* api
*/
organizationFax,
listOrganizationFaxHistory: `${organizationFax}history`,
listOrganizationFaxHistoryId: (id: string) =>
`${organizationFax}history/${id}`,
listOrganizationFaxPublished: `${organizationFax}history/published`,
listOrganizationFaxPublishedHistory: `${organizationFax}history/published-history`,
}

View file

@ -0,0 +1,108 @@
/**
* api
* เมนูย่อย: ข้อมูลเกี่ยวกับบุคคล
*/
import env from "../index";
const person = `${env.API_URI}/metadata/main/`;
const province = `${env.API_URI}/metadata/province/`;
const district = `${env.API_URI}/metadata/district/`;
const subDistrict = `${env.API_URI}/metadata/sub-district/`;
const prefix = `${env.API_URI}/metadata/prefix/`;
const bloodGroup = `${env.API_URI}/metadata/blood-group/`;
const educationLevel = `${env.API_URI}/metadata/education-level/`;
const gender = `${env.API_URI}/metadata/gender/`;
const relationship = `${env.API_URI}/metadata/relationship/`;
const religion = `${env.API_URI}/metadata/religion/`;
export default {
person: `${person}person`,
/**
* api
*/
province,
listProvinceHistory: `${province}history`,
listProvinceHistoryId: (id: string) => `${province}history/${id}`,
listProvincePublished: `${province}history/published`,
listProvincePublishedHistory: `${province}history/published-history`,
/**
* api
*/
listDistrict: (id: string) => `${district}${id}`,
listDistrictHistory: `${district}history`,
listDistrictHistoryId: (id: string | string[]) => `${district}history/${id}`,
listDistrictPublishedId: (id: string) => `${district}history/published/${id}`,
listDistrictPublishedHistory: (id: string | string[]) =>
`${district}history/published-history/${id}`,
/**
* api
*/
listSubDistrict: (id: string) => `${subDistrict}${id}`,
listSubDistrictHistory: `${subDistrict}history`,
listSubDistrictHistoryProvinceId: (
provinceId: string | string[],
district: string | string[]
) => `${subDistrict}history/${provinceId}/${district}`,
listSubDistrictHistoryId: (id: string | string[]) =>
`${subDistrict}history/${id}`,
listSubDistrictPublishedId: (id: string) =>
`${subDistrict}history/published/${id}`,
listSubDistrictPublishedHistory: (id: string | string[]) =>
`${subDistrict}history/published-history/${id}`,
/**
* api
*/
prefix,
listPrefixHistory: `${prefix}history`,
listPrefixHistoryId: (id: string) => `${prefix}history/${id}`,
listPrefixPublished: `${prefix}history/published`,
listPrefixPublishedHistory: `${prefix}history/published-history`,
/**
* api
*/
gender,
listGenderHistory: `${gender}history`,
listGenderHistoryId: (id: string) => `${gender}history/${id}`,
listGenderPublished: `${gender}history/published`,
listGenderPublishedHistory: `${gender}history/published-history`,
/**
* api
*/
relationship,
listRelationshipHistory: `${relationship}history`,
listRelationshipHistoryId: (id: string) => `${relationship}history/${id}`,
listRelationshipPublished: `${relationship}history/published`,
listRelationshipPublishedHistory: `${relationship}history/published-history`,
/**
* api
*/
bloodGroup,
listBloodGroupHistory: `${bloodGroup}history`,
listBloodGroupHistoryId: (id: string) => `${bloodGroup}history/${id}`,
listBloodGroupPublished: `${bloodGroup}history/published`,
listBloodGroupPublishedHistory: `${bloodGroup}history/published-history`,
/**
* api
*/
religion,
listReligionHistory: `${religion}history`,
listReligionHistoryId: (id: string) => `${religion}history/${id}`,
listReligionPublished: `${religion}history/published`,
listReligionPublishedHistory: `${religion}history/published-history`,
/**
* api
*/
educationLevel,
listEducationLevelHistory: `${educationLevel}history`,
listEducationLevelHistoryId: (id: string) => `${educationLevel}history/${id}`,
listEducationLevelPublished: `${educationLevel}history/published`,
listEducationLevelPublishedHistory: `${educationLevel}history/published-history`,
};

View file

@ -0,0 +1,98 @@
/**
* api
* เมนูย่อย: ข้อมูลตำแหน่งของข้าราชการกรุงเทพมหานคร
*/
import env from "../index";
const position = `${env.API_URI}/metadata/main/`;
const positionExecutiveSide = `${env.API_URI}/metadata/position-executive-side/`;
const positionLevel = `${env.API_URI}/metadata/position-level/`;
const positionPath = `${env.API_URI}/metadata/position-path/`;
const positionSide = `${env.API_URI}/metadata/position-path-side/`;
const positionType = `${env.API_URI}/metadata/position-type/`;
const positionStatus = `${env.API_URI}/metadata/position-status/`;
const positionLine = `${env.API_URI}/metadata/position-line/`;
const positionExecutive = `${env.API_URI}/metadata/position-executive/`;
export default {
position: `${position}position`,
/**
* api
*/
positionExecutiveSide,
listPositionExecutiveSideHistory: `${positionExecutiveSide}history`,
listPositionExecutiveSideHistoryId: (id: string) =>
`${positionExecutiveSide}history/${id}`,
listPositionExecutiveSidePublished: `${positionExecutiveSide}history/published`,
listPositionExecutiveSidePublishedHistory: `${positionExecutiveSide}history/published-history`,
/**
* api
*/
// listPositionHistory: `${position}history`,
// listPositionHistoryId: (id: string) => `${position}history/${id}`,
// listPositionPublished: `${position}history/published`,
/**
* api
*/
positionLevel,
listPositionLevelHistory: `${positionLevel}history`,
listPositionLevelHistoryId: (id: string) => `${positionLevel}history/${id}`,
listPositionLevelPublished: `${positionLevel}history/published`,
listPositionLevelPublishedHistory: `${positionLevel}history/published-history`,
/**
* api
*/
positionPath,
listPositionPathHistory: `${positionPath}history`,
listPositionPathHistoryId: (id: string) => `${positionPath}history/${id}`,
listPositionPathPublished: `${positionPath}history/published`,
listPositionPathPublishedHistory: `${positionPath}history/published-history`,
/**
* api /
*/
positionSide,
listPositionSideHistory: `${positionSide}history`,
listPositionSideHistoryId: (id: string) => `${positionSide}history/${id}`,
listPositionSidePublished: `${positionSide}history/published`,
listPositionSidePublishedHistory: `${positionSide}history/published-history`,
/**
* api
*/
positionType,
listPositionTypeHistory: `${positionType}history`,
listPositionTypeHistoryId: (id: string) => `${positionType}history/${id}`,
listPositionTypePublished: `${positionType}history/published`,
listPositionTypePublishedHistory: `${positionType}history/published-history`,
/**
* api
*/
positionStatus,
listPositionStatusHistory: `${positionStatus}history`,
listPositionStatusHistoryId: (id: string) => `${positionStatus}history/${id}`,
listPositionStatusPublished: `${positionStatus}history/published`,
listPositionStatusPublishedHistory: `${positionStatus}history/published-history`,
/**
* api
*/
positionLine,
listPositionLineHistory: `${positionLine}history`,
listPositionLineHistoryId: (id: string) => `${positionLine}history/${id}`,
listPositionLinePublished: `${positionLine}history/published`,
listPositionLinePublishedHistory: `${positionLine}history/published-history`,
/**
* api
*/
positionExecutive,
listPositionExecutiveHistory: `${positionExecutive}history`,
listPositionExecutiveHistoryId: (id: string) =>
`${positionExecutive}history/${id}`,
listPositionExecutivePublished: `${positionExecutive}history/published`,
listPositionExecutivePublishedHistory: `${positionExecutive}history/published-history`,
};

View file

@ -0,0 +1,67 @@
/**
* api
* เมนูย่อย: ข้อมูลตำแหน่งของลูกจ้างกรุงเทพมหานคร
*/
import env from "../index";
const positionEmployeePosition = `${env.API_URI}/metadata/position-employee-position/`;
const positionEmployeePositionSide = `${env.API_URI}/metadata/position-employee-position-side/`;
const positionEmployeeGroup = `${env.API_URI}/metadata/position-employee-group/`;
const positionEmployeeLine = `${env.API_URI}/metadata/position-employee-line/`;
const positionEmployeeLevel = `${env.API_URI}/metadata/position-employee-level/`;
const positionEmployeeStatus = `${env.API_URI}/metadata/position-employee-status/`;
export default {
/**
* api
*/
listPositionEmployeePositionHistory: `${positionEmployeePosition}history`,
listPositionEmployeePositionHistoryId: (id: string) =>
`${positionEmployeePosition}history/${id}`,
listPositionEmployeePositionPublished: `${positionEmployeePosition}history/published`,
listPositionEmployeePositionPublishedHistory: `${positionEmployeePosition}history/published-history`,
/**
* api
*/
listPositionEmployeePositionSideHistory: `${positionEmployeePositionSide}history`,
listPositionEmployeePositionSideHistoryId: (id: string) =>
`${positionEmployeePositionSide}history/${id}`,
listPositionEmployeePositionSidePublished: `${positionEmployeePositionSide}history/published`,
listPositionEmployeePositionSidePublishedHistory: `${positionEmployeePositionSide}history/published-history`,
/**
* api
*/
listPositionEmployeeGroupHistory: `${positionEmployeeGroup}history`,
listPositionEmployeeGroupHistoryId: (id: string) =>
`${positionEmployeeGroup}history/${id}`,
listPositionEmployeeGroupPublished: `${positionEmployeeGroup}history/published`,
listPositionEmployeeGroupPublishedHistory: `${positionEmployeeGroup}history/published-history`,
/**
* api
*/
listPositionEmployeeLineHistory: `${positionEmployeeLine}history`,
listPositionEmployeeLineHistoryId: (id: string) =>
`${positionEmployeeLine}history/${id}`,
listPositionEmployeeLinePublished: `${positionEmployeeLine}history/published`,
listPositionEmployeeLinePublishedHistory: `${positionEmployeeLine}history/published-history`,
/**
* api
*/
listPositionEmployeeLevelHistory: `${positionEmployeeLevel}history`,
listPositionEmployeeLevelHistoryId: (id: string) =>
`${positionEmployeeLevel}history/${id}`,
listPositionEmployeeLevelPublished: `${positionEmployeeLevel}history/published`,
listPositionEmployeeLevelPublishedHistory: `${positionEmployeeLevel}history/published-history`,
/**
* api
*/
listPositionEmployeeStatusHistory: `${positionEmployeeStatus}history`,
listPositionEmployeeStatusHistoryId: (id: string) =>
`${positionEmployeeStatus}history/${id}`,
listPositionEmployeeStatusPublished: `${positionEmployeeStatus}history/published`,
listPositionEmployeeStatusPublishedHistory: `${positionEmployeeStatus}history/published-history`,
};

View file

@ -0,0 +1,39 @@
/**
* api
*/
import env from "../index"
const disableExam = `${env.API_CANDIDATE_URI}/candidate/disable-exam/`
const diable_report = `${env.API_URI}/report/exam/`
export default {
getDisableCandidates: `${disableExam}candidate`,
saveDisableCandidates: `${disableExam}candidate`,
deleteDisableCandidates: (id: string) => `${disableExam}candidate/${id}`,
getDisableExamDetail: (id: string, examId: string) =>
`${disableExam}exam/${id}/${examId}`,
saveDisableScores: (id: string) => `${disableExam}score/${id}`,
getDisableExamResultById: (id: string) => `${disableExam}exam/${id}`,
// จัดการรอบการสอบ
saveDisablePeriod: `${disableExam}period`,
editDisablePeriod: (id: string) => `${disableExam}period/${id}`,
getDisablePeriodById: (id: string) => `${disableExam}period/${id}`,
uploadDisableCandidates: (id: string) => `${disableExam}candidate/${id}`,
getDisableImportHistory: (id: string) => `${disableExam}history/${id}`,
// รายงาน
downloadDisableExamReport: (id: string, examId: string, type: number = 2) =>
`${diable_report}certificate/${type}/${id}/${examId}`,
downloadDisableScoreReport: (id: string, examId: string) =>
`${diable_report}score/${id}/${examId}`,
exportDisableExam: (id: string) => `${disableExam}export/exam/${id}`,
exportDisablePassExam: (id: string) => `${disableExam}export/pass-exam/${id}`,
exportDisablePassResultExam: (id: string) =>
`${disableExam}export/pass/${id}`,
exportDisableCandidateList: (id: string) => `${diable_report}candidate/${id}`,
exportDisablePassExamList: (id: string) => `${diable_report}pass/${id}`,
}

View file

@ -0,0 +1,85 @@
/**
* api
*/
import env from "../index"
const candidate = `${env.API_CANDIDATE_URI}/candidate/`
const periodExam = `${env.API_CANDIDATE_URI}/candidate/period-exam/`
const exam_report = `${env.API_URI}/report/exam/`
const cms = `${env.API_CANDIDATE_URI}/cms/`
export default {
/**
* api cms
*/
cms,
cmsDeatail: `${cms}detail`,
cmsAbout: `${cms}about`,
cmsLogo: `${cms}logo`,
cmsBanner: `${cms}banner`,
cmsAgency: `${cms}agency`,
cmsGoverment: `${cms}government`,
/**
* api
*/
periodExam: `${periodExam}`,
periodExamType: (type: string) => `${periodExam}type/${type}`,
periodExamId: (examId: string) => `${periodExam}${examId}`,
periodExamDoc: (examId: string) => `${periodExam}doc/${examId}`,
periodExamImg: (examId: string) => `${periodExam}img/${examId}`,
periodExamStatus: (examId: string) => `${periodExam}status-payment/${examId}`,
countDashbordPeriodExam: (examId: string) =>
`${periodExam}dashboard/${examId}`,
candidateId: (candidateId: string) => `${candidate}${candidateId}`,
candidateInformation: (candidateId: string) =>
`${periodExam}information/${candidateId}`,
candidateAddress: (candidateId: string) =>
`${periodExam}address/${candidateId}`,
candidateFamily: (candidateId: string) =>
`${periodExam}family/${candidateId}`,
candidateOccupation: (candidateId: string) =>
`${periodExam}occupation/${candidateId}`,
candidateEducation: (candidateId: string) =>
`${periodExam}education/${candidateId}`,
candidateAdminEducation: (candidateId: string) =>
`${candidate}education/${candidateId}`,
candidateDocument: (candidateId: string) =>
`${periodExam}document/${candidateId}`,
candidateCareer: (candidateId: string) =>
`${periodExam}career/${candidateId}`,
candidateAdminCareer: (candidateId: string) =>
`${candidate}career/${candidateId}`,
candidateProfile: (candidateId: string) =>
`${candidate}profile-image/${candidateId}`,
candidateUpload: (candidateId: string) => `${candidate}upload/${candidateId}`,
candidateCheckRegister: (candidateId: string) =>
`${candidate}check-register/${candidateId}`,
candidateRejectRegister: (candidateId: string) =>
`${candidate}reject-register/${candidateId}`,
candidateCheckPayment: (candidateId: string) =>
`${candidate}check-payment/${candidateId}`,
candidate,
candidateOfPeriodExam: (status: string, examId: string) =>
`${periodExam}${status}/${examId}`,
candidateCard: (candidateId: string) => `${candidate}card/${candidateId}`,
periodExamUploadSeat: (examId: string) =>
`${periodExam}upload-seat/${examId}`,
periodExamUploadPoint: (examId: string) =>
`${periodExam}upload-point/${examId}`,
periodExamDownload: (examId: string) => `${periodExam}download/${examId}`,
periodExamDownloadDetail: (examId: string) =>
`${periodExam}download/detail/${examId}`,
periodExamDownloadDashboard: (examId: string) =>
`${periodExam}download/dashboard/${examId}`,
candidatePayment: (candidateId: string) =>
`${candidate}payment-image/${candidateId}`,
periodExamPayment: (examId: string) => `${periodExam}payment/${examId}`,
exportExamCandidateList: (id: string) => `${exam_report}candidate-exam/${id}`,
exportExamPassExamList: (id: string) => `${exam_report}pass-exam/${id}`,
}

View file

@ -0,0 +1,41 @@
/**
* api -
*/
import env from "../index"
const recruit = `${env.API_URI}/recruit/`
const recruit_report = `${env.API_URI}/report/recruit/`
export default {
getCandidates: `${recruit}candidate`,
saveCandidates: `${recruit}candidate`,
deleteCandidates: (id: string) => `${recruit}candidate/${id}`,
getExamDetail: (id: string, examId: string) => `${recruit}exam/${id}/${examId}`,
saveScores: (id: string) => `${recruit}score/${id}`,
getExamResultById: (id: string) => `${recruit}exam/${id}`,
// จัดการรอบการสอบ
savePeriod: `${recruit}period`,
editPeriod: (id: string) => `${recruit}period/${id}`,
getPeriodById: (id: string) => `${recruit}period/${id}`,
uploadCandidates: (id: string) => `${recruit}candidate/${id}`,
getImportHistory: (id: string) => `${recruit}history/${id}`,
//upload
periodRecruitDoc: (examId: string) => `${recruit}doc/${examId}`,
periodRecruitImg: (examId: string) => `${recruit}img/${examId}`,
periodDeleteDoc: (docId: string) => `${recruit}doc/${docId}`,
periodDeleteImg: (docId: string) => `${recruit}img/${docId}`,
// รายงาน
downloadExamReport: (id: string, examId: string, type: number = 2) => `${recruit_report}certificate/${type}/${id}/${examId}`,
downloadScoreReport: (id: string, examId: string) => `${recruit_report}score/${id}/${examId}`,
exportExam: (id: string) => `${recruit}export/exam/${id}`,
exportPassExam: (id: string) => `${recruit}export/pass-exam/${id}`,
exportPassResultExam: (id: string) => `${recruit}export/pass/${id}`,
exportCandidateList: (id: string) => `${recruit_report}candidate/${id}`,
exportPassExamList: (id: string) => `${recruit_report}pass/${id}`,
}

View file

@ -0,0 +1,12 @@
import env from "../index";
const report2 = `${env.API_URI_ORG_SERVICE}/report2/`;
export default {
report2Id: (id: string) => `${report2}${id}`,
report2TreeId: (organizationId: string) => `${report2}tree/${organizationId}`,
report2DoneId: (organizationId: string) => `${report2}done/${organizationId}`,
report2HistoryId: (organizationId: string) =>
`${report2}history/${organizationId}`,
report2HistoryDetailId: (historyId: string) =>
`${report2}history/detail/${historyId}`,
};

View file

@ -0,0 +1,161 @@
/**
* api -
*/
import env from "../index";
const profile = `${env.API_URI_PROFILE_SERVICE}/profile/`;
const report = `${env.API_REPORT_URI}/report/profile/`;
export default {
profileUser: `${profile}user`,
profileValidateId: (profileId: string) => `${profile}validate/${profileId}`,
profilePaperDownloadId: (id: string) => `${profile}paper/download/${id}`,
profilePaperId: (id: string) => `${profile}paper/${id}`,
profileMultiId: (id: string) => `${profile}multi-paper/${id}`,
profileMultiOId: (id: string) => `${profile}multi-paper-other/${id}`,
profileMultiKId: (id: string) => `${profile}multi-paper-kk1/${id}`,
profileHistoryselfId: (profileId: string) =>
`${profile}/historyself${profileId}`,
profileOrganiNameId: (id: string) => `${profile}organization/name/${id}`,
profileOrganiId: (id: string) => `${profile}organization/${id}`,
profileOrganiSelectId: (id: string) => `${profile}organization/select/${id}`,
profileOrganiRootId: (id: string) => `${profile}organization/root/${id}`,
profileLeaveOrganiId: (id: string) => `${profile}leave/organization/${id}`,
profileSearchNewOcId: (id: string) => `${profile}search/new/oc/${id}`,
profileSearchNewOcIdType: (id: string, type: string) =>
`${profile}search/new/oc/${id}/${type}`,
profileSearchId: (id: string) => `${profile}search/${id}`,
profileSearchOcId: (id: string) => `${profile}search/oc/${id}`,
profileSearchNewOcLeaveId: (id: string) =>
`${profile}search/new/oc/leave/${id}`,
profileSearchNewOcLeaveIdType: (id: string, type: string) =>
`${profile}search/new/oc/leave/${id}/${type}`,
profileSearchOcLeaveId: (id: string) => `${profile}search/oc/leave/${id}`,
profileSearchNewEmOcId: (id: string) =>
`${profile}search/new-employee/oc/${id}`,
profileSearchNewEmOcLeaveId: (id: string) =>
`${profile}search/new-employee/oc/leave/${id}`,
profileCoupleId: (profileId: string) => `${profile}couple/${profileId}`,
profileFatherId: (profileId: string) => `${profile}father/${profileId}`,
profileMotherId: (profileId: string) => `${profile}mother/${profileId}`,
profileAdsId: (profileId: string) => `${profile}address/current/${profileId}`,
profileAdsCurAdrsId: (profileId: string) =>
`${profile}address/currentAdrs/${profileId}`,
profileAdsRegisId: (profileId: string) =>
`${profile}address/registration/${profileId}`,
profileInsignId: (profileId: string) => `${profile}insignia/${profileId}`,
profileInsignHisId: (profileId: string) =>
`${profile}insignia/history/${profileId}`,
profileInsignInsignId: (profileId: string) =>
`${profile}insignia/insigniadiocesan/${profileId}`,
profileInsignToolList: `${profile}insignia/tool/list`,
profileChildId: (profileId: string) => `${profile}children/${profileId}`,
profileAssessmentId: (profileId: string) =>
`${profile}assessment/${profileId}`,
profileAssessmentHisId: (profileId: string) =>
`${profile}assessment/history/${profileId}`,
profileHonorId: (profileId: string) => `${profile}honor/${profileId}`,
profileHonorHisId: (profileId: string) =>
`${profile}honor/history/${profileId}`,
profileCertId: (profileId: string) => `${profile}certificate/${profileId}`,
profileCertHisId: (profileId: string) =>
`${profile}certificate/history/${profileId}`,
profileAbiliId: (profileId: string) => `${profile}ability/${profileId}`,
profileAbiliHisId: (profileId: string) =>
`${profile}ability/history/${profileId}`,
profileDutyId: (profileId: string) => `${profile}duty/${profileId}`,
profileDutyHisId: (profileId: string) =>
`${profile}duty/history/${profileId}`,
profileOtherId: (profileId: string) => `${profile}other/${profileId}`,
profileOtherHisId: (profileId: string) =>
`${profile}other/history/${profileId}`,
profileNopaidId: (profileId: string) => `${profile}nopaid/${profileId}`,
profileNopaidHisId: (profileId: string) =>
`${profile}nopaid/history/${profileId}`,
profileAvaId: (profileId: string) => `${profile}avatar/${profileId}`,
profileAvaCurId: (profileId: string) =>
`${profile}avatar/current/${profileId}`,
profileEduId: (profileId: string) => `${profile}education/${profileId}`,
profileEduHisId: (profileId: string) =>
`${profile}education/history/${profileId}`,
profileSwapEducation: `${profile}swap_education`,
profileTrainId: (profileId: string) => `${profile}training/${profileId}`,
profileTrainHisId: (profileId: string) =>
`${profile}training/history/${profileId}`,
profileDisId: (profileId: string) => `${profile}discipline/${profileId}`,
profileDisHisId: (profileId: string) =>
`${profile}discipline/history/${profileId}`,
profileSwapDiscipline: `${profile}swap_discipline`,
profileLeaveId: (profileId: string) => `${profile}leave/${profileId}`,
profileLeaveHisId: (profileId: string) =>
`${profile}leave/history/${profileId}`,
profileSalaryId: (profileId: string) => `${profile}salary/${profileId}`,
profileSalaryHisId: (profileId: string) =>
`${profile}salary/history/${profileId}`,
profileSalarySwapId: (id: string, direction: string) =>
`${profile}salary/swap/${id}/${direction}`,
profileSalaryCopyId: (profileId: string) =>
`${profile}salary-copy/${profileId}`,
profileInforId: (profileId: string) => `${profile}information/${profileId}`,
profileInforHisId: (profileId: string) =>
`${profile}information/history/${profileId}`,
profileGovId: (profileId: string) => `${profile}government/${profileId}`,
profileGovHisId: (profileId: string) =>
`${profile}government/history/${profileId}`,
profileCalGovId: (profileId: string) => `${profile}cal/gov/${profileId}`,
profileFamiId: (profileId: string) => `${profile}family/${profileId}`,
profileFamiHisId: (profileId: string) =>
`${profile}family/history/${profileId}`,
profileAdrsId: (profileId: string) => `${profile}address/${profileId}`,
profileAdrsHisId: (profileId: string) =>
`${profile}address/history/${profileId}`,
searchProfileByOcId: (OcId: string, type: string) =>
`${profile}search/new/oc/${OcId}/${type}`,
profileAvatarId: (profileId: string) => `${profile}avatar/${profileId}`,
profileAvatarHistoryId: (profileId: string) =>
`${profile}avatar/history/${profileId}`,
profileCheckId: (profileId: string) => `${profile}check/${profileId}`,
profileOrganizRoot: `${profile}organization/root`,
profileCalRetire: `${profile}cal/retire`,
profilePositionNumber: `${profile}position-number`,
organizationName: (ocId: string) => `${profile}organization/${ocId}`,
profileDeactive: (profileId: string) => `${profile}deactive/${profileId}`,
profileReactive: (profileId: string) => `${profile}reactive/${profileId}`,
profileReportId: (profileId: string) => `${report}kk1/${profileId}`,
profileKp7ShortId: (profileId: string) => `${report}kp7-short/${profileId}`,
};

83
src/app.config.ts Normal file
View file

@ -0,0 +1,83 @@
/**ใช้รวมไฟล์ย่อยๆ ของ api แต่ละไฟล์ */
/** API Metadata */
import manageOrganization from "./api/manage/api.organization";
import managePerson from "./api/manage/api.person";
import managePosition from "./api/manage/api.position";
import managePositionEmployee from "./api/manage/api.positionEmployee";
import manageInsignia from "./api/manage/api.insignia";
import manageHoliday from "./api/manage/api.holiday";
/** API Tree List */
import organizationTreeList from "./api/02_organizational/api.treelist";
/** API Structure & Org Chart */
import organizationChart from "./api/02_organizational/api.chart";
/** API periodexam List */
import periodexam from "./api/recruiting/api.period-exam";
import disableexam from "./api/recruiting/api.disable";
/** API Recruit List */
import recruit from "./api/recruiting/api.recruit";
/** API Profile List */
import profile from "./api/registry/api.profile";
/** API Report2 List */
import report2 from "./api/recruiting/api.report2";
/** API ระบบการบรรจุ แต่งตั้ง ย้าย โอน List */
import placement from "./api/05_placement/api.placement";
/** API ระบบการพ้นจากราชการ List */
import retirement from "./api/06_retirement/api.retirement";
/** API ระบบงานเครื่องราชอิสริยาภรณ์ List */
import insignia from "./api/07_insignia/api.insignia";
// environment variables
export const compettitivePanel = import.meta.env.VITE_COMPETITIVE_EXAM_PANEL;
export const qualifyDisableExamPanel = import.meta.env
.VITE_QUALIFY_DISABLE_EMAM_PANEL;
export const qualifyExamPanel = import.meta.env.VITE_QUALIFY_EXAM_PANEL;
export const s3ClusterUrl = import.meta.env.VITE_S3CLUSTER_PUBLIC_URL;
const API = {
//Metadata
...manageOrganization,
...managePerson,
...managePosition,
...managePositionEmployee,
...manageInsignia,
...manageHoliday,
//Tree List
...organizationTreeList,
...organizationChart,
//periodexam
...periodexam,
...disableexam,
// recruit
...recruit,
//profile
...profile,
//report2
...report2,
...placement,
...retirement,
...insignia,
};
export default {
API: API,
compettitivePanel,
qualifyDisableExamPanel,
qualifyExamPanel,
s3ClusterUrl,
};

BIN
src/assets/avatar_user.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

0
src/assets/base.css Normal file
View file

BIN
src/assets/ex_slip.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

BIN
src/assets/krungthai.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 KiB

BIN
src/assets/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

1
src/assets/logo.svg Normal file
View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 261.76 226.69" xmlns:v="https://vecta.io/nano"><path d="M161.096.001l-30.225 52.351L100.647.001H-.005l130.877 226.688L261.749.001z" fill="#41b883"/><path d="M161.096.001l-30.225 52.351L100.647.001H52.346l78.526 136.01L209.398.001z" fill="#34495e"/></svg>

After

Width:  |  Height:  |  Size: 308 B

35
src/assets/main.css Normal file
View file

@ -0,0 +1,35 @@
/* @import './base.css'; */
/* #app {
max-width: 1280px;
margin: 0 auto;
padding: 2rem;
font-weight: normal;
}
a,
.green {
text-decoration: none;
color: hsla(160, 100%, 37%, 1);
transition: 0.4s;
}
@media (hover: hover) {
a:hover {
background-color: hsla(160, 100%, 37%, 0.2);
}
}
@media (min-width: 1024px) {
body {
display: flex;
place-items: center;
}
#app {
display: grid;
grid-template-columns: 1fr 1fr;
padding: 0 2rem;
}
} */

View file

@ -0,0 +1,11 @@
const chartData = {
personID: "", // Unique ID เป็นเลข ID ที่อ้างอิงไปที่ตัวบุคคล
name: "-", // ขื่อบุคคล
positionName: "-", // ชื่อตำแหน่ง
positionNum: "", // เลขที่ประจำตำแหน่งในโครงสร้าง
departmentName: "", // ชื่อหน่วยงานที่สังกัด
avatar: "", // ภาพถ่าย
children: [], // บุคคลอื่น ๆ ที่อยู่ภายใต้คนนี้ มีโครงสร้างเหมือนกัน
};
export default chartData;

View file

@ -0,0 +1,272 @@
/**
* Root TreeList TreeList
* - Object
* - deptID : Unique ID // Int String
* - departmentName : ชื่อสำนัก//
* - totalPositionCount : จำนวนตำแหน่งทั้งหมดในหน่วยงาน
* - totalPositionVacant : จำนวนตำแหน่งว่างทั้งหมดในหน่วยงาน
* - Object 3
* - heads : เป็น Array Object
* - offcier : เป็น Array Object
* - children : เป็น Array Root children Object
* - Object
* - positionID : Unique ID deptID
* - positionName : ชื่อตำแหน่ง
* - positionNum : เลขที่ประจำตำแหน่ง .
* - totalPositionCount : จำนวนตำแหน่งทั้งหมด
* - totalPositionVacant : จำนวนตำแหน่งว่างทั้งหมด
*/
const chartData = { // root ของข้อมูลเป็น Object (ไม่ใช่ Array แบบ TreeList)
deptID: 1, // Unique ID ของสำนัก/ฝ่าย/กอง (ถ้ามี?)
departmentName: "สำนักงานเลขานุการผู้ว่าราชการกรุงเทพมหานคร", // ชื่อสำนัก/ฝ่าย/กอง
totalPositionCount: 75, // จำนวนตำแหน่งทั้งหมดในหน่วยงาน
totalPositionVacant: 2, // จำนวนตำแหน่งว่างทั้งหมดในหน่วยงาน
heads: [ // Array ของผู้บริหารในหน่วยงานนั้น ๆ (ผู้อำนวยการ/หัวหน้า)
{
positionID: 2, // Unique ID ของประเภทตำแหน่งนั้น (ถ้ามี?)
positionName: "ผู้อำนวยการสูง", // ชื่อตำแหน่ง
positionNum: "(หัวหน้าสำนักงาน)", // เลขที่ประจำตำแหน่ง (ถ้ามี) เช่นพวก กทข.
totalPositionCount: 1, // จำนวนตำแหน่งทั้งหมด
totalPositionVacant: 0 // จำนวนตำแหน่งว่างทั้งหมด
}
],
officer: [ // Array ของเจ้าหน้าที่ในหน่วยงาน (รายการตำแหน่งในหน่วยงานที่ขึ้นตรงกับ deptID นั้น ๆ)
],
children: [ // Array ของหน่วยงานย่อย เช่น ฝ่าย กอง
{ // โครงสร้างที่เหลือจะเหมือนกับส่วน Root ทุกอย่าง คือแต่ละหน่วยงานย่อย มี heads ไว้ระบุหัวหน้า ผู้อำนวยการ มี Officer ไว้ระบุรายการตำแหน่งในหน่วยงาน มี Children ไว้ระบุหน่วยงานย่อย
deptID: 3,
departmentName: "ฝ่ายบริหารทั่วไป",
totalPositionCount: 14,
totalPositionVacant: 0,
heads: [
{
positionID: 2,
positionName: "นักจัดการงานทั่วไป",
positionNum: "ชพ. (หัวหน้าฝ่าย)",
totalPositionCount: 1,
totalPositionVacant: 0
}
],
officer: [
{
positionID: 3,
positionName: "นักจัดการงานทั่วไป",
positionNum: "ปก./ชก",
totalPositionCount: 1,
totalPositionVacant: 0
},
{
positionID: 4,
positionName: "นักทรัพยากรบุคคล",
positionNum: "ปก./ชก.",
totalPositionCount: 1,
totalPositionVacnt: 0
},
{
positionID: 5,
positionName: "นักวิชาการเงินและบัญชี",
positionNum: "ปก./ชก.",
totalPositionCount: 2,
totalPositionVacnt: 0
},
{
positionID: 6,
positionName: "นักวิชาการพัสดุ",
positionNum: "ปก./ชก.",
totalPositionCount: 1,
totalPositionVacnt: 0
},
{
positionID: 7,
positionName: "เจ้าพนักงานการเงินและบัญชี",
positionNum: "ปง./ชง.",
totalPositionCount: 3,
totalPositionVacnt: 0
},
{
positionID: 8,
positionName: "เจ้าพนักงานพัสดุ",
positionNum: "ปง./ชง.",
totalPositionCount: 1,
totalPositionVacnt: 0
},
{
positionID: 9,
positionName: "เจ้าพนักงานธุรการ",
positionNum: "ปง./ชง.",
totalPositionCount: 4,
totalPositionVacnt: 0
}
]
},
{
deptID: 4,
departmentName: "ส่วนประสานนโยบาย",
totalPositionCount: 15,
totalPositionVacant: 0,
heads: [
{
positionID: 10,
positionName: "ผู้อำนวยการต้น",
positionNum: "(ผู้อำนวยการส่วน)",
totalPositionCount: 1,
totalPositionVacant: 0,
}
],
children: [
{
deptID: 11,
departmentName: "กลุ่มงานประชุม",
totalPositionCount: 6,
totalPositionVacant: 0,
heads: [
{
positionID: 11,
positionName: "นักจัดการงานทั่วไป",
positionNum: "ชพ. (หัวหน้ากลุ่มงาน)",
totalPositionCount: 1,
totalPositionVacant: 0,
}
],
officer: [
{
positionID: 12,
positionName: "นักจัดการงานทั่วไป",
positionNum: "ปก./ชก.",
totalPositionCount: 4,
totalPositionVacant: 0
},
{
positionID: 13,
positionName: "เจ้าพนักงานธุรการ",
positionNum: "ปง./ชง.",
totalPositionCount: 1,
totalPositionVacant: 0
}
]
},
{
deptID: 12,
departmentName: "กลุ่มงานการเมืองและประสานนโยบาย",
totalPositionCount: 8,
totalPositionVacant: 0,
heads: [
{
positionID: 14,
positionName: "นักจัดการงานทั่วไป",
positionNum: "ชพ. (หัวหน้ากลุ่มงาน)",
totalPositionCount: 1,
totalPositionVacant: 0,
}
],
officer: [
{
positionID: 15,
positionName: "นักจัดการงานทั่วไป",
positionNum: "ปก./ชก.",
totalPositionCount: 4,
totalPositionVacant: 0
},
{
positionID: 16,
positionName: "เจ้าพนักงานสถิติ",
positionNum: "ปง./ชง.",
totalPositionCount: 1,
totalPositionVacant: 0
},
{
positionID: 17,
positionName: "เจ้าพนักงานธุรการ",
positionNum: "ปง./ชง.",
totalPositionCount: 2,
totalPositionVacant: 0
}
]
}
]
},
{
deptID: 14,
departmentName: "ส่วนเรื่องราวร้องทุกข์",
totalPositionCount: 15,
totalPositionVacant: 0,
heads: [
{
positionID: 18,
positionName: "ผู้อำนวยการต้น",
positionNum: "(ผู้อำนวยการส่วน)",
totalPositionCount: 1,
totalPositionVacant: 0
}
],
children: [
{
deptID: 15,
departmentName: "กลุ่มงานรับเรื่องราวร้องทุกข์",
totalPositionCount: 7,
totalPositionVacant: 0,
heads: [
{
positionID: 19,
positionName: "นักจัดการงานทั่วไป",
positionNum: "ชพ. (หัวหน้ากลุ่มงาน)",
totalPositionCount: 1,
totalPositionVacant: 0
}
],
officer: [
{
positionID: 20,
positionName: "นักจัดการงานทั่วไป",
positionNum: "ปก./ชก.",
totalPositionCount: 4,
totalPositionVacant: 0
},
{
positionID: 21,
positionName: "เจ้าพนักงานธุรการ",
positionNum: "ปง./ชง.",
totalPositionCount: 2,
totalPositionVacant: 0
}
]
},
{
deptID: 16,
departmentName: "กลุ่มงานตรวจสอบ ติดตามและประมวลผล",
totalPositionCount: 7,
totalPositionVacant: 0,
heads: [
{
positionID: 22,
positionName: "นักจัดการงานทั่วไป",
positionNum: "ชพ. (หัวหน้ากลุ่มงาน)",
totalPositionCount: 1,
totalPositionVacant: 0
}
],
officer: [
{
positionID: 23,
positionName: "นักจัดการงานทั่วไป",
positionNum: "ปก./ชก.",
totalPositionCount: 4,
totalPositionVacant: 0
},
{
positionID: 24,
positionName: "เจ้าพนักงานธุรการ",
positionNum: "ปง./ชง.",
totalPositionCount: 2,
totalPositionVacant: 0
}
]
}
]
}
]
}
export default chartData

8321
src/assets/tree.json Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,90 @@
<template>
<q-dialog ref="dialogRef" @hide="onDialogHide" persistent>
<q-card class="q-pa-sm">
<q-card-section class="row">
<div class="q-pr-md">
<q-avatar
:icon="icon"
size="lg"
font-size="25px"
color="blue-1"
:text-color="color"
/>
</div>
<div class="col text-dark">
<span class="text-bold">{{ title }}</span>
<br />
<span>{{ message }}</span>
</div>
</q-card-section>
<q-card-actions
align="right"
class="bg-white text-teal"
v-if="onlycancel"
>
<q-btn label="ตกลง" flat color="grey-8" @click="onDialogCancel" />
<!-- <q-btn :label="textOk" :color="color" @click="onOKClick" /> -->
</q-card-actions>
<q-card-actions align="right" class="bg-white text-teal" v-else>
<q-btn label="ยกเลิก" flat color="grey-8" @click="onDialogCancel" />
<q-btn :label="textOk" :color="color" @click="onOKClick" />
</q-card-actions>
</q-card>
</q-dialog>
</template>
<script setup lang="ts">
import { useDialogPluginComponent } from "quasar";
const props = defineProps({
color: {
type: String,
default: "primary",
},
textOk: {
type: String,
default: "ตกลง",
},
title: {
type: String,
default: "หัวข้อ?",
},
message: {
type: String,
default: "ข้อความ",
},
icon: {
type: String,
default: "question_mark",
},
onlycancel: {
type: Boolean,
default: false,
},
});
defineEmits([
// REQUIRED; need to specify some events that your
// component will emit through useDialogPluginComponent()
...useDialogPluginComponent.emits,
]);
const { dialogRef, onDialogHide, onDialogOK, onDialogCancel } =
useDialogPluginComponent();
// dialogRef - Vue ref to be applied to QDialog
// onDialogHide - Function to be used as handler for @hide on QDialog
// onDialogOK - Function to call to settle dialog with "ok" outcome
// example: onDialogOK() - no payload
// example: onDialogOK({ /*...*/ }) - with payload
// onDialogCancel - Function to call to settle dialog with "cancel" outcome
// this is part of our example (so not required)
function onOKClick() {
// on OK, it is REQUIRED to
// call onDialogOK (with optional payload)
onDialogOK();
// or with payload: onDialogOK({ ... })
// ...and it will also hide the dialog automatically
}
</script>

View file

@ -0,0 +1,27 @@
<template>
<q-toolbar>
<q-toolbar-title class="text-subtitle2 text-bold">{{ tittle }}</q-toolbar-title>
<q-btn
icon="close"
unelevated
round
dense
@click="close"
style="color: #ff8080; background-color: #ffdede"
/>
</q-toolbar>
</template>
<script setup lang="ts">
import { ref, useAttrs } from "vue";
const props = defineProps({
tittle: String,
close: {
type: Function,
default: () => console.log("not function"),
},
});
const close = async () => {
props.close();
};
</script>

View file

@ -0,0 +1,16 @@
<!-- =============================== -->
<!-- Component Show No Result Found Message -->
<!-- When filtering Drodown(q-select) -->
<!-- อความทจะแสดงเวลาคนหาขอมลในดรอบดาวนไมเจอ -->
<!-- ใชหลายท จะได css เดยว -->
<!-- =============================== -->
<template>
<q-item>
<q-item-section class="text-black"> ไมพบขอมลทนหา </q-item-section>
</q-item>
</template>
<script setup lang="ts"></script>
<style lang="scss"></style>

View file

@ -0,0 +1,15 @@
<template>
<q-select v-bind="attrs">
<template v-slot:no-option>
<q-item>
<q-item-section class="text-black">
ไมพบขอมลทนหา
</q-item-section>
</q-item>
</template>
</q-select>
</template>
<script setup lang="ts">
import { ref, useAttrs, defineAsyncComponent } from "vue";
const attrs = ref<any>(useAttrs());
</script>

View file

@ -0,0 +1,204 @@
<template>
<q-dialog :model-value="modal" persistent>
<q-card style="min-width: 70vw;">
<q-form ref="myForm">
<div class="row items-center q-pa-sm">
<div class="row">
<div class="text-bold">{{ tittle }}</div>
</div>
<q-space />
<q-btn
icon="close"
unelevated
round
dense
style="color: #ff8080; background-color: #ffdede"
size="12px"
@click="close"
/>
</div>
<q-separator />
<div class="q-pa-sm">
<!-- header บน table นหา แสดงคอลมน (status nornmalData true) -->
<div class="col-12 row q-pb-sm">
<!-- <q-select
hide-bottom-space
@update:model-value="updateHistory"
outlined
dense
lazy-rules
borderless
:model-value="history"
:label="`${'วันที่'}`"
emit-value
map-options
option-label="publishedDate"
:options="optionsHistory"
option-value="id"
/> -->
<q-space />
<div class="items-center" style="display: flex">
<!-- นหาขอความใน table -->
<q-input
standout
dense
:model-value="inputfilter"
ref="filterRef"
@update:model-value="updateInput"
outlined
debounce="300"
placeholder="ค้นหา"
style="max-width: 200px"
class="q-ml-sm"
>
<template v-slot:append>
<q-icon v-if="inputfilter == ''" name="search" />
<q-icon
v-if="inputfilter !== ''"
name="clear"
class="cursor-pointer"
@click="resetFilter"
/>
</template>
</q-input>
<!-- แสดงคอลมนใน table -->
<q-select
:model-value="inputvisible"
@update:model-value="updateVisible"
:display-value="$q.lang.table.columns"
multiple
outlined
dense
:options="attrs.columns"
options-dense
option-value="name"
map-options
emit-value
style="min-width: 150px"
class="gt-xs q-ml-sm"
/>
</div>
</div>
<q-table
ref="table"
flat
bordered
class="custom-header-table"
v-bind="attrs"
virtual-scroll
:virtual-scroll-sticky-size-start="48"
dense
:pagination-label="paginationLabel"
:pagination="initialPagination"
:rows-per-page-options="[0]"
>
<template v-slot:header="props">
<q-tr :props="props">
<q-th auto-width v-if="boss == true" />
<q-th v-for="col in props.cols" :key="col.name" :props="props">
<span class="text-weight-medium">{{ col.label }}</span>
</q-th>
</q-tr>
</template>
<!-- สำหรบเรยกใช template วขางนอก -->
<template #body="props">
<slot v-bind="props" name="columns"></slot>
</template>
</q-table>
</div>
<q-separator />
</q-form>
</q-card>
</q-dialog>
</template>
<script setup lang="ts">
import { ref, useAttrs } from "vue";
import type { Pagination } from "@/modules/01_metadata/interface/index/Main";
const attrs = ref<any>(useAttrs());
const filterRef = ref<any>(null);
// const history = ref<string>("");
const initialPagination = ref<Pagination>({
// descending: false,
rowsPerPage: 0,
});
const props = defineProps({
tittle: String,
inputfilter: String,
// history: String,
inputvisible: Array,
modal: Boolean,
boss: {
type: Boolean,
defualt: false,
},
// optionsHistory: Array,
// updateHistory: {
// type: Function,
// default: () => console.log("not function"),
// },
});
const emit = defineEmits([
"update:inputfilter",
"update:inputvisible",
"update:modal",
// "update:history",
]);
const updateInput = (value: string | number | null) => {
emit("update:inputfilter", value);
};
const updateVisible = (value: []) => {
emit("update:inputvisible", value);
};
const close = () => {
emit("update:modal", false);
};
// const updateHistory = (value: string) => {
// emit("update:history", value);
// props.updateHistory();
// };
const paginationLabel = (start: string, end: string, total: string) => {
return start + "-" + end + " ใน " + total;
};
const resetFilter = () => {
// reset X
emit("update:inputfilter", "");
filterRef.value.focus();
};
</script>
<style lang="scss">
.icon-color {
color: #4154b3;
}
.custom-header-table {
max-height: 64vh;
.q-table tr:nth-child(odd) td {
background: white;
}
.q-table tr:nth-child(even) td {
background: #f8f8f8;
}
.q-table thead tr {
background: #ecebeb;
}
.q-table thead tr th {
position: sticky;
z-index: 1;
}
/* this will be the loading indicator */
.q-table thead tr:last-child th {
/* height of all previous header rows */
top: 48px;
}
.q-table thead tr:first-child th {
top: 0;
}
}
</style>

View file

@ -0,0 +1,541 @@
<template>
<div class="q-px-md q-pb-md">
<!-- header บน table นหา แสดงคอลมน มแกไข เพ เผยแพรอม ยกเล (status nornmalData false) -->
<div class="col-12 row q-py-sm" v-if="nornmalData == false">
<q-btn
v-if="!editvisible == true && publicNoBtn == false"
flat
round
:disabled="editvisible == true"
:color="editvisible == true ? 'grey-7' : 'primary'"
@click="edit"
icon="mdi-pencil-outline"
>
<q-tooltip>แกไขขอม</q-tooltip>
</q-btn>
<!-- ยกเล แสดงเม กดปมแกไข -->
<q-btn
v-else
flat
round
:disabled="editvisible == false"
:outline="editvisible == false"
:color="editvisible == false ? 'grey-7' : 'red'"
@click="cancel()"
icon="mdi-undo"
>
<q-tooltip>ยกเล</q-tooltip>
</q-btn>
<!-- <q-separator vertical /> -->
<div class="q-px-sm">
<q-btn
flat
round
:disabled="editvisible == false"
:color="editvisible == false ? 'grey-7' : 'add'"
@click="add"
icon="mdi-plus"
>
<q-tooltip>เพมขอม</q-tooltip>
</q-btn>
<!-- นทกราง แสดงเม กดปมแกไข อมลมการเปนแปลงหร งไมเผยแพรอม -->
<q-btn
flat
round
:disabled="!(editvisible == true && updateData == true)"
:color="
!(editvisible == true && updateData == true) ? 'grey-7' : 'public'
"
@click="checkSave"
v-if="saveNoDraft == false"
icon="mdi-content-save-outline"
>
<q-tooltip>นทกราง</q-tooltip>
</q-btn>
<!-- ลบบนทกราง แสดงเม นทกรางแล -->
<q-btn
flat
round
:disabled="publicData == true"
:color="publicData == true ? 'grey-7' : 'deep-orange'"
@click="DeleteModal"
icon="mdi-file-remove-outline"
v-if="publicNoBtn == false"
>
<q-tooltip>ลบบนทกราง</q-tooltip>
</q-btn>
</div>
<!-- เผยแพร -->
<q-btn
flat
round
:disabled="!(publicData == false || updateData == true)"
:color="
!(publicData == false || updateData == true) ? 'grey-7' : 'public'
"
@click="publishModal"
icon="mdi-cloud-upload-outline"
v-if="publicNoBtn == false"
>
<q-tooltip>เผยแพร</q-tooltip>
</q-btn>
<div class="items-center" style="display: flex">
<div
class="row items-center"
style="display: flex"
v-if="publicData == false && publicNoBtn == false"
>
<div class="text-public text-body2 text-weight-medium q-px-sm">
อมลยงไมเผยแพร
</div>
</div>
</div>
<q-space />
<div class="items-center" style="display: flex">
<!-- อความสถานะเผยแพร โดยใช parameter publicData เปนตวกำหนดขอความ -->
<!-- <div class="row items-center" style="display: flex" v-if="publicData == true">
<q-icon cener size="20px" name="label_important" class="icon-color" />
<div class="text-size">อมลเผยแพรแล</div>
</div> -->
<div
class="row items-center"
style="display: flex"
v-if="publicData == false && publicNoBtn == false"
>
<!-- <q-icon cener size="20px" name="label_important" color="amber" />
<div class="text-grey-7 text-body2 text-weight-medium q-px-sm">
อมลยงไมเผยแพร
</div> -->
</div>
<!-- นหาขอความใน table -->
<q-input
standout
dense
:model-value="inputfilter"
ref="filterRef"
@update:model-value="updateInput"
outlined
debounce="300"
placeholder="ค้นหา"
style="max-width: 200px"
class="q-ml-sm"
>
<template v-slot:append>
<q-icon v-if="inputfilter == ''" name="search" />
<q-icon
v-if="inputfilter !== ''"
name="clear"
class="cursor-pointer"
@click="resetFilter"
/>
</template>
</q-input>
<!-- แสดงคอลมนใน table -->
<q-select
:model-value="inputvisible"
@update:model-value="updateVisible"
:display-value="$q.lang.table.columns"
multiple
outlined
dense
:options="attrs.columns"
options-dense
option-value="name"
map-options
emit-value
style="min-width: 150px"
class="gt-xs q-ml-sm"
/>
</div>
</div>
<!-- header บน table นหา แสดงคอลมน (status nornmalData true) -->
<div class="col-12 row q-py-sm items-center" v-if="nornmalData == true">
<span class="text-subtitle1">{{ titleText }}</span>
<!-- <q-select
:model-value="inputvisibleFilter"
:options="optionsFilter"
style="min-width: 150px"
class="gt-xs q-ml-sm"
/> -->
<q-select
dense
outlined
:model-value="inputvisibleFilter"
:options="optionsFilter"
class="col-xs-12 col-sm-4 col-md-3"
option-value="id"
option-label="name"
map-options
emit-value
@update:model-value="updateVisibleFilter"
v-if="optionsFilter != undefined && optionsFilter.length > 0"
/>
<q-space />
<div class="items-center" style="display: flex">
<!-- นหาขอความใน table -->
<q-input
standout
dense
:model-value="inputfilter"
ref="filterRef"
@update:model-value="updateInput"
outlined
debounce="300"
placeholder="ค้นหา"
style="max-width: 200px"
class="q-ml-sm"
>
<template v-slot:append>
<q-icon v-if="inputfilter == ''" name="search" />
<q-icon
v-if="inputfilter !== ''"
name="clear"
class="cursor-pointer"
@click="resetFilter"
/>
</template>
</q-input>
<!-- แสดงคอลมนใน table -->
<q-select
:model-value="inputvisible"
@update:model-value="updateVisible"
:display-value="$q.lang.table.columns"
multiple
outlined
dense
:options="attrs.columns"
options-dense
option-value="name"
map-options
emit-value
style="min-width: 150px"
class="gt-xs q-ml-sm"
/>
</div>
</div>
<q-table
ref="table"
flat
bordered
class="custom-header-table"
v-bind="attrs"
virtual-scroll
:virtual-scroll-sticky-size-start="48"
dense
:pagination-label="paginationLabel"
:pagination="initialPagination"
:rows-per-page-options="paging == true ? [25, 50, 100, 500] : []"
>
<!-- :pagination="initialPagination" -->
<!-- :rows-per-page-options="[0]" -->
<template v-slot:header="props">
<q-tr :props="props">
<q-th auto-width v-if="boss == true" />
<q-th v-for="col in props.cols" :key="col.name" :props="props">
<span class="text-weight-medium">{{ col.label }}</span>
</q-th>
<q-th
auto-width
v-if="
editvisible == true || nextPageVisible == true || history == true
"
/>
</q-tr>
</template>
<!-- สำหรบเรยกใช template วขางนอก -->
<template #body="props">
<slot v-bind="props" name="columns"></slot>
</template>
</q-table>
</div>
<!-- อมลการเผยแพรอม -->
<!-- <notifyPublishDraft v-model:showModal="modalPublish" :ok="publish" /> -->
<!-- <q-dialog v-model="modalPublish" persistent>
<q-card class="q-pa-sm">
<q-card-section class="row">
<div class="q-pr-md">
<q-avatar
icon="public"
size="lg"
font-size="25px"
color="blue-1"
text-color="public"
/>
</div>
<div class="col text-dark">
<span class="text-bold">องการเผยแพรอมลนหรอไม?</span>
<br />
<span>อมลทกำลงถกเผยแพรจะมผลใชงานทนท</span>
</div>
</q-card-section>
<q-card-actions align="right" class="bg-white text-teal">
<q-btn label="ยกเลิก" flat color="grey-8" v-close-popup />
<q-btn
label="เผยแพร่"
color="public"
@click="publish()"
v-close-popup
/>
</q-card-actions>
</q-card>
</q-dialog> -->
<!-- อมลการลบเผยแพรอม -->
<!-- <notifyDeleteDraft v-model:showModal="modalDelete" :ok="deleted" /> -->
<!-- <q-dialog v-model="modalDelete" persistent>
<q-card class="q-pa-sm">
<q-card-section class="row">
<div class="q-pr-md">
<q-avatar
icon="mdi-file-remove-outline"
size="lg"
font-size="25px"
color="red-1"
text-color="deep-orange"
/>
</div>
<div class="col text-dark">
<span class="text-bold">องการลบขอมลบนทกรางนหรอไม?</span>
<br />
<span>อมลบนทกรางทกำลงถกลบนจะมผลใชงานทนท</span>
</div>
</q-card-section>
<q-card-actions align="right" class="bg-white text-teal">
<q-btn label="ยกเลิก" flat color="grey-8" v-close-popup />
<q-btn label="ลบบันทึก" color="red" @click="deleted()" v-close-popup />
</q-card-actions>
</q-card>
</q-dialog> -->
</template>
<script setup lang="ts">
import { ref, useAttrs } from "vue";
import { useCounterMixin } from "@/stores/mixin";
import { useQuasar } from "quasar";
const $q = useQuasar();
const mixin = useCounterMixin(); //
const { dialogMessage } = mixin;
const attrs = ref<any>(useAttrs());
const table = ref<any>(null);
const filterRef = ref<any>(null);
const modalPublish = ref<boolean>(false);
const modalDelete = ref<boolean>(false);
const props = defineProps({
inputfilter: String,
inputvisible: Array,
inputvisibleFilter: String,
editvisible: Boolean,
titleText: String,
optionsFilter: {
type: Array,
defualt: [],
},
boss: {
type: Boolean,
defualt: false,
},
saveNoDraft: {
type: Boolean,
defualt: false,
},
history: {
type: Boolean,
defualt: false,
},
paging: {
type: Boolean,
defualt: false,
},
nornmalData: {
type: Boolean,
defualt: false,
},
nextPageVisible: {
type: Boolean,
defualt: false,
},
publicData: {
type: Boolean,
defualt: true,
required: false,
},
updateData: {
type: Boolean,
defualt: true,
required: false,
},
publicNoBtn: {
type: Boolean,
defualt: false,
},
add: {
type: Function,
default: () => console.log("not function"),
},
edit: {
type: Function,
default: () => console.log("not function"),
},
save: {
type: Function,
default: () => console.log("not function"),
},
deleted: {
type: Function,
default: () => console.log("not function"),
},
cancel: {
type: Function,
default: () => console.log("not function"),
},
publish: {
type: Function,
default: () => console.log("not function"),
},
validate: {
type: Function,
default: () => console.log("not function"),
},
});
const initialPagination = ref<any>({
// descending: false,
rowsPerPage: props.paging == true ? 25 : 0,
});
const emit = defineEmits([
"update:inputfilter",
"update:inputvisible",
"update:editvisible",
"update:titleText",
"update:inputvisibleFilter",
]);
const updateEdit = (value: any) => {
emit("update:editvisible", value);
};
const updateInput = (value: any) => {
emit("update:inputfilter", value);
};
const updateVisible = (value: any) => {
emit("update:inputvisible", value);
};
const updateVisibleFilter = (value: any) => {
emit("update:inputvisibleFilter", value);
};
const paginationLabel = (start: string, end: string, total: string) => {
if (props.paging == true)
return " " + start + " ใน " + end + " จากจำนวน " + total + " รายการ";
else return start + "-" + end + " ใน " + total;
};
const checkSave = () => {
props.validate();
props.save();
// if (myForm.value !== null) {
// myForm.value.validate().then((success) => {
// if (success) {
// }
// });
// }
};
const publishModal = () => {
props.validate();
const filter = attrs.value.rows.filter((r: any) => r.name == "");
if (filter.length == 0 || attrs.value.rows.length == 0) {
// modalPublish.value = true;
dialogMessage(
$q,
"ต้องการเผยแพร่ข้อมูลนี้หรือไม่?",
"ข้อมูลที่กำลังถูกเผยแพร่นี้จะมีผลใช้งานทันที",
"public",
"เผยแพร่",
"public",
props.publish,
undefined
);
}
};
const DeleteModal = () => {
// modalDelete.value = true;
dialogMessage(
$q,
"ต้องการลบข้อมูลบันทึกร่างนี้หรือไม่?",
"ข้อมูลบันทึกร่างที่กำลังถูกลบนี้จะมีผลใช้งานทันที",
"mdi-file-remove-outline",
"ลบบันทึก",
"red",
props.deleted,
undefined
);
};
const edit = async () => {
updateEdit(!props.editvisible);
props.edit();
};
const add = async () => {
// if (myForm.value !== null) {
// myForm.value.validate();
// }
props.validate();
props.add();
await table.value.lastPage();
await table.value.scrollTo(attrs.value.rows.length - 1);
};
const deleted = async () => {
// const deletedF = () => {
if (props.publicNoBtn === false) {
updateEdit(false);
}
props.deleted();
};
const resetFilter = () => {
// reset X
emit("update:inputfilter", "");
filterRef.value.focus();
};
</script>
<style lang="scss">
.icon-color {
color: #4154b3;
}
.custom-header-table {
max-height: 64vh;
.q-table tr:nth-child(odd) td {
background: white;
}
.q-table tr:nth-child(even) td {
background: #f8f8f8;
}
.q-table thead tr {
background: #ecebeb;
}
.q-table thead tr th {
position: sticky;
z-index: 1;
}
/* this will be the loading indicator */
.q-table thead tr:last-child th {
/* height of all previous header rows */
top: 48px;
}
.q-table thead tr:first-child th {
top: 0;
}
}
</style>

View file

@ -0,0 +1,412 @@
<template>
<div class="q-px-md q-pb-md">
<!-- header บน table นหา แสดงคอลมน มแกไข เพ เผยแพรอม ยกเล-->
<div class="col-12 row q-py-sm q-col-gutter-sm">
<q-btn-group flat>
<q-btn
:push="!editvisible"
:outline="editvisible"
dense
:disabled="editvisible == true"
:color="editvisible == true ? 'grey-7' : 'primary'"
label="แก้ไข"
@click="edit"
icon="mdi-pencil-outline"
class="q-px-sm"
>
<!-- <q-tooltip>แกไขขอม</q-tooltip> -->
</q-btn>
<!-- <q-separator vertical /> -->
<q-btn
:push="editvisible"
:outline="!editvisible"
dense
:disabled="editvisible == false"
:color="editvisible == false ? 'grey-7' : 'primary'"
label="เพิ่ม"
@click="add"
icon="mdi-plus"
class="q-px-sm"
>
<!-- <q-tooltip>เพมขอม</q-tooltip> -->
</q-btn>
</q-btn-group>
<q-btn-group flat>
<!-- เผยแพร -->
<q-btn
dense
:push="publicData == false || updateData == true"
:outline="!(publicData == false || updateData == true)"
:disabled="!(publicData == false || updateData == true)"
:color="
!(publicData == false || updateData == true) ? 'grey-7' : 'public'
"
label="เผยแพร่"
@click="publishModal"
icon="mdi-file-upload-outline"
class="q-px-sm"
>
<!-- <q-tooltip>เผยแพร</q-tooltip> -->
</q-btn>
<!-- นทกราง แสดงเม กดปมแกไข อมลมการเปนแปลงหร งไมเผยแพรอม -->
<q-btn
dense
:push="
editvisible == true && (publicData == false || updateData == true)
"
:outline="
!(
editvisible == true &&
(publicData == false || updateData == true)
)
"
:disabled="
!(
editvisible == true &&
(publicData == false || updateData == true)
)
"
:color="
!(
editvisible == true &&
(publicData == false || updateData == true)
)
? 'grey-7'
: 'public'
"
label="บันทึกร่าง"
@click="checkSave"
icon="mdi-file-check-outline"
class="q-px-sm"
>
<!-- <q-tooltip>นทกราง</q-tooltip> -->
</q-btn>
<!-- ลบบนทกราง แสดงเม นทกรางแล -->
<q-btn
dense
:push="!publicData"
:disabled="publicData == true"
:outline="publicData == true"
label="ลบร่าง"
:color="publicData == true ? 'grey-7' : 'public'"
@click="deleted()"
icon="mdi-file-remove-outline"
class="q-px-sm"
>
<!-- <q-tooltip>ลบบนทกราง</q-tooltip> -->
</q-btn>
</q-btn-group>
<q-btn-group flat>
<!-- ยกเล แสดงเม กดปมแกไข -->
<q-btn
dense
:push="editvisible"
:disabled="editvisible == false"
:outline="editvisible == false"
label="ยกเลิก"
:color="editvisible == false ? 'grey-7' : 'red'"
@click="cancel()"
icon="mdi-close"
class="q-px-sm"
>
<!-- <q-tooltip>ยกเล</q-tooltip> -->
</q-btn>
</q-btn-group>
<q-space />
<div class="items-center" style="display: flex">
<!-- อความสถานะเผยแพร โดยใช parameter publicData เปนตวกำหนดขอความ -->
<!-- <div class="row items-center" style="display: flex" v-if="publicData == true">
<q-icon cener size="20px" name="label_important" class="icon-color" />
<div class="text-size">อมลเผยแพรแล</div>
</div> -->
<div
class="row items-center"
style="display: flex"
v-if="publicData == false"
>
<q-icon cener size="15px" name="label_important" color="amber" />
<div class="text-caption text-grey-7 text-weight-medium q-px-sm">
อมลยงไมเผยแพร
</div>
</div>
<!-- นหาขอความใน table -->
<q-input
standout
dense
:model-value="inputfilter"
@update:model-value="updateInput"
outlined
debounce="300"
placeholder="ค้นหา"
style="max-width: 200px"
class="q-ml-sm"
>
<template v-slot:append>
<q-icon name="search" />
</template>
</q-input>
<!-- แสดงคอลมนใน table -->
<q-select
:model-value="inputvisible"
@update:model-value="updateVisible"
:display-value="$q.lang.table.columns"
multiple
outlined
dense
:options="attrs.columns"
options-dense
option-value="name"
map-options
emit-value
style="min-width: 150px"
class="gt-xs q-ml-sm"
/>
</div>
</div>
<q-table
ref="table"
flat
bordered
class="custom-header-table"
v-bind="attrs"
virtual-scroll
:rows-per-page-options="[0]"
:virtual-scroll-sticky-size-start="48"
dense
><!-- :pagination="initialPagination"
:pagination-label="paginationLabel" -->
<template v-slot:header="props">
<q-tr :props="props">
<q-th v-for="col in props.cols" :key="col.name" :props="props">
<span class="text-weight-medium">{{ col.label }}</span>
</q-th>
<q-th
auto-width
v-if="editvisible == true || nextPageVisible == true"
/>
</q-tr>
</template>
<!-- สำหรบเรยกใช template วขางนอก -->
<template #body="props">
<slot v-bind="props" name="columns"></slot>
</template>
</q-table>
</div>
<!-- อมลการเผยแพรอม -->
<q-dialog v-model="modal" persistent>
<q-card class="q-pa-sm">
<q-card-section class="row">
<div class="q-pr-md">
<q-avatar
icon="public"
size="lg"
font-size="25px"
color="blue-1"
text-color="public"
/>
</div>
<div class="col text-dark">
<span class="text-bold">องการเผยแพรอมลนหรอไม?</span>
<br />
<span>อมลทกำลงถกเผยแพรจะมผลใชงานทนท</span>
</div>
</q-card-section>
<q-card-actions align="right" class="bg-white text-teal">
<q-btn label="ยกเลิก" flat color="grey-8" v-close-popup />
<q-btn
label="เผยแพร่"
color="public"
@click="publish()"
v-close-popup
/>
</q-card-actions>
</q-card>
</q-dialog>
<q-dialog
:model-value="modalError"
persistent
@update:model-value="updateClose"
>
<q-card class="q-pa-sm">
<q-card-section class="row items-center">
<div class="q-pr-md">
<q-avatar
icon="mdi-alert-circle-outline"
font-size="25px"
size="lg"
color="red-1"
text-color="red"
/>
</div>
<div class="col text-dark">
<span class="text-bold">{{ modalErrorTittle }}</span>
<br />
<span>{{ modalErrorDetail }}</span>
</div>
</q-card-section>
<q-card-actions align="right" class="bg-white text-teal">
<q-btn
label="ตกลง"
color="primary"
@click="updateClose"
v-close-popup
/>
</q-card-actions>
</q-card>
</q-dialog>
</template>
<script setup lang="ts">
import { ref, useAttrs } from "vue";
const attrs = ref<any>(useAttrs());
const table = ref<any>(null);
const modal = ref<boolean>(false);
const initialPagination = ref<any>({
descending: false,
rowsPerPage: 10,
});
const props = defineProps({
inputfilter: String,
inputvisible: Array,
editvisible: Boolean,
nextPageVisible: {
type: Boolean,
defualt: false,
},
modalError: Boolean,
modalErrorTittle: String,
modalErrorDetail: String,
publicData: {
type: Boolean,
defualt: true,
required: true,
},
updateData: {
type: Boolean,
defualt: true,
required: true,
},
add: {
type: Function,
default: () => console.log("not function"),
},
edit: {
type: Function,
default: () => console.log("not function"),
},
save: {
type: Function,
default: () => console.log("not function"),
},
deleted: {
type: Function,
default: () => console.log("not function"),
},
cancel: {
type: Function,
default: () => console.log("not function"),
},
publish: {
type: Function,
default: () => console.log("not function"),
},
});
const emit = defineEmits([
"update:inputfilter",
"update:inputvisible",
"update:editvisible",
"update:modalError",
"update:modalErrorTittle",
"update:modalErrorDetail",
]);
const updateEdit = (value: any) => {
emit("update:editvisible", value);
};
const updateInput = (value: any) => {
emit("update:inputfilter", value);
};
const updateVisible = (value: any) => {
emit("update:inputvisible", value);
};
const updateClose = (value: any) => {
// props.modalError = false;
emit("update:modalError", false);
emit("update:modalErrorTittle", "");
emit("update:modalErrorDetail", "");
};
const paginationLabel = (start: string, end: string, total: string) => {
return start + "-" + end + " ใน " + total;
};
const checkSave = () => {
props.save();
// if (myForm.value !== null) {
// myForm.value.validate().then((success) => {
// if (success) {
// }
// });
// }
};
const publishModal = () => {
const filter = attrs.value.rows.filter((r: any) => r.name == "");
if (filter.length == 0 && attrs.value.rows.length !== 0) {
modal.value = true;
}
};
const edit = async () => {
updateEdit(!props.editvisible);
props.edit();
};
const add = async () => {
// if (myForm.value !== null) {
// myForm.value.validate();
// }
props.add();
await table.value.lastPage();
await table.value.scrollTo(attrs.value.rows.length - 1);
};
</script>
<style lang="scss">
.icon-color {
color: #4154b3;
}
.custom-header-table {
max-height: 38vh;
.q-table tr:nth-child(odd) td {
background: white;
}
.q-table tr:nth-child(even) td {
background: #f8f8f8;
}
.q-table thead tr {
background: #ecebeb;
}
.q-table thead tr th {
position: sticky;
z-index: 1;
}
/* this will be the loading indicator */
.q-table thead tr:last-child th {
/* height of all previous header rows */
top: 48px;
}
.q-table thead tr:first-child th {
top: 0;
}
}
</style>

View file

View file

@ -0,0 +1,11 @@
import { describe, it, expect } from "vitest";
import { mount } from "@vue/test-utils";
// import HelloWorld from '../HelloWorld.vue'
describe("HelloWorld", () => {
it("renders properly", () => {
// const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } })
// expect(wrapper.text()).toContain('Hello Vitest')
});
});

View file

@ -0,0 +1,7 @@
<template>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor">
<path
d="M15 4a1 1 0 1 0 0 2V4zm0 11v-1a1 1 0 0 0-1 1h1zm0 4l-.707.707A1 1 0 0 0 16 19h-1zm-4-4l.707-.707A1 1 0 0 0 11 14v1zm-4.707-1.293a1 1 0 0 0-1.414 1.414l1.414-1.414zm-.707.707l-.707-.707.707.707zM9 11v-1a1 1 0 0 0-.707.293L9 11zm-4 0h1a1 1 0 0 0-1-1v1zm0 4H4a1 1 0 0 0 1.707.707L5 15zm10-9h2V4h-2v2zm2 0a1 1 0 0 1 1 1h2a3 3 0 0 0-3-3v2zm1 1v6h2V7h-2zm0 6a1 1 0 0 1-1 1v2a3 3 0 0 0 3-3h-2zm-1 1h-2v2h2v-2zm-3 1v4h2v-4h-2zm1.707 3.293l-4-4-1.414 1.414 4 4 1.414-1.414zM11 14H7v2h4v-2zm-4 0c-.276 0-.525-.111-.707-.293l-1.414 1.414C5.42 15.663 6.172 16 7 16v-2zm-.707 1.121l3.414-3.414-1.414-1.414-3.414 3.414 1.414 1.414zM9 12h4v-2H9v2zm4 0a3 3 0 0 0 3-3h-2a1 1 0 0 1-1 1v2zm3-3V3h-2v6h2zm0-6a3 3 0 0 0-3-3v2a1 1 0 0 1 1 1h2zm-3-3H3v2h10V0zM3 0a3 3 0 0 0-3 3h2a1 1 0 0 1 1-1V0zM0 3v6h2V3H0zm0 6a3 3 0 0 0 3 3v-2a1 1 0 0 1-1-1H0zm3 3h2v-2H3v2zm1-1v4h2v-4H4zm1.707 4.707l.586-.586-1.414-1.414-.586.586 1.414 1.414z"
/>
</svg>
</template>

View file

@ -0,0 +1,7 @@
<template>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="17" fill="currentColor">
<path
d="M11 2.253a1 1 0 1 0-2 0h2zm-2 13a1 1 0 1 0 2 0H9zm.447-12.167a1 1 0 1 0 1.107-1.666L9.447 3.086zM1 2.253L.447 1.42A1 1 0 0 0 0 2.253h1zm0 13H0a1 1 0 0 0 1.553.833L1 15.253zm8.447.833a1 1 0 1 0 1.107-1.666l-1.107 1.666zm0-14.666a1 1 0 1 0 1.107 1.666L9.447 1.42zM19 2.253h1a1 1 0 0 0-.447-.833L19 2.253zm0 13l-.553.833A1 1 0 0 0 20 15.253h-1zm-9.553-.833a1 1 0 1 0 1.107 1.666L9.447 14.42zM9 2.253v13h2v-13H9zm1.553-.833C9.203.523 7.42 0 5.5 0v2c1.572 0 2.961.431 3.947 1.086l1.107-1.666zM5.5 0C3.58 0 1.797.523.447 1.42l1.107 1.666C2.539 2.431 3.928 2 5.5 2V0zM0 2.253v13h2v-13H0zm1.553 13.833C2.539 15.431 3.928 15 5.5 15v-2c-1.92 0-3.703.523-5.053 1.42l1.107 1.666zM5.5 15c1.572 0 2.961.431 3.947 1.086l1.107-1.666C9.203 13.523 7.42 13 5.5 13v2zm5.053-11.914C11.539 2.431 12.928 2 14.5 2V0c-1.92 0-3.703.523-5.053 1.42l1.107 1.666zM14.5 2c1.573 0 2.961.431 3.947 1.086l1.107-1.666C18.203.523 16.421 0 14.5 0v2zm3.5.253v13h2v-13h-2zm1.553 12.167C18.203 13.523 16.421 13 14.5 13v2c1.573 0 2.961.431 3.947 1.086l1.107-1.666zM14.5 13c-1.92 0-3.703.523-5.053 1.42l1.107 1.666C11.539 15.431 12.928 15 14.5 15v-2z"
/>
</svg>
</template>

View file

@ -0,0 +1,7 @@
<template>
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="20" fill="currentColor">
<path
d="M11.447 8.894a1 1 0 1 0-.894-1.789l.894 1.789zm-2.894-.789a1 1 0 1 0 .894 1.789l-.894-1.789zm0 1.789a1 1 0 1 0 .894-1.789l-.894 1.789zM7.447 7.106a1 1 0 1 0-.894 1.789l.894-1.789zM10 9a1 1 0 1 0-2 0h2zm-2 2.5a1 1 0 1 0 2 0H8zm9.447-5.606a1 1 0 1 0-.894-1.789l.894 1.789zm-2.894-.789a1 1 0 1 0 .894 1.789l-.894-1.789zm2 .789a1 1 0 1 0 .894-1.789l-.894 1.789zm-1.106-2.789a1 1 0 1 0-.894 1.789l.894-1.789zM18 5a1 1 0 1 0-2 0h2zm-2 2.5a1 1 0 1 0 2 0h-2zm-5.447-4.606a1 1 0 1 0 .894-1.789l-.894 1.789zM9 1l.447-.894a1 1 0 0 0-.894 0L9 1zm-2.447.106a1 1 0 1 0 .894 1.789l-.894-1.789zm-6 3a1 1 0 1 0 .894 1.789L.553 4.106zm2.894.789a1 1 0 1 0-.894-1.789l.894 1.789zm-2-.789a1 1 0 1 0-.894 1.789l.894-1.789zm1.106 2.789a1 1 0 1 0 .894-1.789l-.894 1.789zM2 5a1 1 0 1 0-2 0h2zM0 7.5a1 1 0 1 0 2 0H0zm8.553 12.394a1 1 0 1 0 .894-1.789l-.894 1.789zm-1.106-2.789a1 1 0 1 0-.894 1.789l.894-1.789zm1.106 1a1 1 0 1 0 .894 1.789l-.894-1.789zm2.894.789a1 1 0 1 0-.894-1.789l.894 1.789zM8 19a1 1 0 1 0 2 0H8zm2-2.5a1 1 0 1 0-2 0h2zm-7.447.394a1 1 0 1 0 .894-1.789l-.894 1.789zM1 15H0a1 1 0 0 0 .553.894L1 15zm1-2.5a1 1 0 1 0-2 0h2zm12.553 2.606a1 1 0 1 0 .894 1.789l-.894-1.789zM17 15l.447.894A1 1 0 0 0 18 15h-1zm1-2.5a1 1 0 1 0-2 0h2zm-7.447-5.394l-2 1 .894 1.789 2-1-.894-1.789zm-1.106 1l-2-1-.894 1.789 2 1 .894-1.789zM8 9v2.5h2V9H8zm8.553-4.894l-2 1 .894 1.789 2-1-.894-1.789zm.894 0l-2-1-.894 1.789 2 1 .894-1.789zM16 5v2.5h2V5h-2zm-4.553-3.894l-2-1-.894 1.789 2 1 .894-1.789zm-2.894-1l-2 1 .894 1.789 2-1L8.553.106zM1.447 5.894l2-1-.894-1.789-2 1 .894 1.789zm-.894 0l2 1 .894-1.789-2-1-.894 1.789zM0 5v2.5h2V5H0zm9.447 13.106l-2-1-.894 1.789 2 1 .894-1.789zm0 1.789l2-1-.894-1.789-2 1 .894 1.789zM10 19v-2.5H8V19h2zm-6.553-3.894l-2-1-.894 1.789 2 1 .894-1.789zM2 15v-2.5H0V15h2zm13.447 1.894l2-1-.894-1.789-2 1 .894 1.789zM18 15v-2.5h-2V15h2z"
/>
</svg>
</template>

View file

@ -0,0 +1,7 @@
<template>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor">
<path
d="M10 3.22l-.61-.6a5.5 5.5 0 0 0-7.666.105 5.5 5.5 0 0 0-.114 7.665L10 18.78l8.39-8.4a5.5 5.5 0 0 0-.114-7.665 5.5 5.5 0 0 0-7.666-.105l-.61.61z"
/>
</svg>
</template>

View file

@ -0,0 +1,19 @@
<!-- This icon is from <https://github.com/Templarian/MaterialDesign>, distributed under Apache 2.0 (https://www.apache.org/licenses/LICENSE-2.0) license-->
<template>
<svg
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
aria-hidden="true"
role="img"
class="iconify iconify--mdi"
width="24"
height="24"
preserveAspectRatio="xMidYMid meet"
viewBox="0 0 24 24"
>
<path
d="M20 18v-4h-3v1h-2v-1H9v1H7v-1H4v4h16M6.33 8l-1.74 4H7v-1h2v1h6v-1h2v1h2.41l-1.74-4H6.33M9 5v1h6V5H9m12.84 7.61c.1.22.16.48.16.8V18c0 .53-.21 1-.6 1.41c-.4.4-.85.59-1.4.59H4c-.55 0-1-.19-1.4-.59C2.21 19 2 18.53 2 18v-4.59c0-.32.06-.58.16-.8L4.5 7.22C4.84 6.41 5.45 6 6.33 6H7V5c0-.55.18-1 .57-1.41C7.96 3.2 8.44 3 9 3h6c.56 0 1.04.2 1.43.59c.39.41.57.86.57 1.41v1h.67c.88 0 1.49.41 1.83 1.22l2.34 5.39z"
fill="currentColor"
></path>
</svg>
</template>

View file

@ -0,0 +1,41 @@
/**
* GLOABL Response Message for User
*
*/
import { useQuasar } from "quasar";
import { useCounterMixin } from "@/stores/mixin";
// const $q = useQuasar(); // show dialog Error:runtime-core.esm-bundler.js:40 [Vue warn]: inject() can only be used inside setup() or functional components.
const mixin = useCounterMixin();
const { success, modalConfirm, modalError, modalDelete } = mixin;
/**
*
* @param catchE throw catch error message (e)
* @param q $q quasar dialog
* @returns no values return only pop-up dialog message for user
*/
const manageApiErrorMsg = (catchE: any, q: any) => {
// console.log(catchE);
// console.log(catchE.response);
// console.log(catchE.response.status);
// if (!catchE || !catchE.response || !catchE.response.data) {
// console.error("Invalid error object:", catchE);
// return;
// }
if (catchE.response.status == 401 || catchE.response.data.status == 401) {
modalError(q, "พบข้อผิดพลาด", "กรุณาล็อกอินใหม่อีกครั้ง"); //invalid_token
} else if (
catchE.response.data.status == 400 ||
catchE.response.data.status == 403 ||
catchE.response.data.status == 404
) {
//ใส่เป็น error กลางๆ ถ้ามีเคสให้เห็นมากขึ้น ถึงจะแยกข้อความได้
modalError(q, "พบข้อผิดพลาด", "ไม่พบข้อมูล");
} else {
modalError(q, "พบข้อผิดพลาด", catchE.response.data.message);
}
return;
};
export default manageApiErrorMsg;

22
src/hooks/filters.ts Normal file
View file

@ -0,0 +1,22 @@
/**
* GLOABL Filters
* - Helper Functions
*/
const filters = {
/**
* compactNumber Social Media 1,000 1K 1,000,000 1M
* : {{ $filters.compactNumber(value) }}
*
* @param val
* @returns
*/
compactNumber (val: number) {
const formatter = Intl.NumberFormat('en', { notation: 'compact'})
return formatter.format(val)
}
}
export default filters;

314
src/hooks/share.ts Normal file
View file

@ -0,0 +1,314 @@
/**
*
*/
function date2Thai(srcDate: Date, isFullMonth = false, isTime = false) {
if (srcDate == null) {
return "";
}
const date = new Date(srcDate);
const isValidDate = Boolean(+date);
if (!isValidDate) return srcDate.toString();
if (isValidDate && date.getFullYear() < 1000) return srcDate.toString();
const fullMonthThai = [
"มกราคม",
"กุมภาพันธ์",
"มีนาคม",
"เมษายน",
"พฤษภาคม",
"มิถุนายน",
"กรกฎาคม",
"สิงหาคม",
"กันยายน",
"ตุลาคม",
"พฤศจิกายน",
"ธันวาคม",
];
const abbrMonthThai = [
"ม.ค.",
"ก.พ.",
"มี.ค.",
"เม.ย.",
"พ.ค.",
"มิ.ย.",
"ก.ค.",
"ส.ค.",
"ก.ย.",
"ต.ค.",
"พ.ย.",
"ธ.ค.",
];
let dstYear = 0;
if (date.getFullYear() > 2500) {
dstYear = date.getFullYear();
} else {
dstYear = date.getFullYear() + 543;
}
let dstMonth = "";
if (isFullMonth) {
dstMonth = fullMonthThai[date.getMonth()];
} else {
dstMonth = abbrMonthThai[date.getMonth()];
}
let dstTime = "";
if (isTime) {
const H =
date.getHours().toString().length === 1
? "0" + date.getHours()
: date.getHours();
const M =
date.getMinutes().toString().length === 1
? "0" + date.getMinutes()
: date.getMinutes();
// const S = date.getSeconds().toString().length === 1 ? "0" + date.getSeconds() : date.getSeconds()
// dstTime = " " + H + ":" + M + ":" + S + " น."
dstTime = " " + H + ":" + M + " น.";
}
return date.getDate() + " " + dstMonth + " " + dstYear + dstTime;
}
function dateMonth2Thai(srcDate: Date, isFullMonth = false, isTime = false) {
if (!srcDate) return srcDate;
const date = new Date(srcDate);
const isValidDate = Boolean(+date);
if (!isValidDate) return srcDate;
if (isValidDate && date.getFullYear() < 1000) return srcDate;
const fullMonthThai = [
"มกราคม",
"กุมภาพันธ์",
"มีนาคม",
"เมษายน",
"พฤษภาคม",
"มิถุนายน",
"กรกฎาคม",
"สิงหาคม",
"กันยายน",
"ตุลาคม",
"พฤศจิกายน",
"ธันวาคม",
];
const abbrMonthThai = [
"ม.ค.",
"ก.พ.",
"มี.ค.",
"เม.ย.",
"พ.ค.",
"มิ.ย.",
"ก.ค.",
"ส.ค.",
"ก.ย.",
"ต.ค.",
"พ.ย.",
"ธ.ค.",
];
let dstYear = 0;
if (date.getFullYear() > 2500) {
dstYear = date.getFullYear();
} else {
dstYear = date.getFullYear() + 543;
}
let dstMonth = "";
if (isFullMonth) {
dstMonth = fullMonthThai[date.getMonth()];
} else {
dstMonth = abbrMonthThai[date.getMonth()];
}
let dstTime = "";
if (isTime) {
const H =
date.getHours().toString().length === 1
? "0" + date.getHours()
: date.getHours();
const M =
date.getMinutes().toString().length === 1
? "0" + date.getMinutes()
: date.getMinutes();
// const S = date.getSeconds().toString().length === 1 ? "0" + date.getSeconds() : date.getSeconds()
// dstTime = " " + H + ":" + M + ":" + S + " น."
dstTime = " " + H + ":" + M + " น.";
}
return date.getDate() + " " + dstMonth;
}
function monthYear2Thai(month: number, year: number, isFullMonth = false) {
const date = new Date(`${year}-${month + 1}-1`);
const fullMonthThai = [
"มกราคม",
"กุมภาพันธ์",
"มีนาคม",
"เมษายน",
"พฤษภาคม",
"มิถุนายน",
"กรกฎาคม",
"สิงหาคม",
"กันยายน",
"ตุลาคม",
"พฤศจิกายน",
"ธันวาคม",
];
const abbrMonthThai = [
"ม.ค.",
"ก.พ.",
"มี.ค.",
"เม.ย.",
"พ.ค.",
"มิ.ย.",
"ก.ค.",
"ส.ค.",
"ก.ย.",
"ต.ค.",
"พ.ย.",
"ธ.ค.",
];
let dstYear = 0;
if (date.getFullYear() > 2500) {
dstYear = date.getFullYear();
} else {
dstYear = date.getFullYear() + 543;
}
let dstMonth = "";
if (isFullMonth) {
dstMonth = fullMonthThai[date.getMonth()];
} else {
dstMonth = abbrMonthThai[date.getMonth()];
}
return dstMonth + " " + dstYear;
}
function dateToISO(date: Date) {
return (
date.getFullYear() +
"-" +
appendLeadingZeroes(date.getMonth() + 1) +
"-" +
appendLeadingZeroes(date.getDate())
);
}
function appendLeadingZeroes(n: Number) {
if (n <= 9) return "0" + n;
return n;
}
const success = (q: any, val: string) => {
// useQuasar ไม่สามารถใช้นอกไฟล์ .vue
if (val !== "") {
return q.notify({
message: val,
color: "primary",
icon: "mdi-information",
position: "bottom-right",
multiLine: true,
timeout: 1000,
badgeColor: "positive",
classes: "my-notif-class",
});
}
};
function notify(q: any, val: string) {
if (val !== "") {
q.notify({
color: "teal-10",
message: val,
icon: "mdi-information",
position: "bottom-right",
multiLine: true,
timeout: 7000,
actions: [{ label: "ปิด", color: "white", handler: () => {} }],
});
}
}
function notifyError(q: any, val: string) {
if (val !== "") {
q.notify({
color: "negative",
message: val,
icon: "mdi-alert-circle",
position: "top",
multiLine: true,
timeout: 12000,
actions: [{ label: "ปิด", color: "white", handler: () => {} }],
});
}
}
const dateText = (val: Date) => {
if (val != null) {
return date2Thai(val);
} else {
return "-";
}
};
const weekThai = (val: Number) => {
switch (val) {
case 0:
return "วันอาทิตย์";
case 1:
return "วันจันทร์";
case 2:
return "วันอังคาร";
case 3:
return "วันพุธ";
case 4:
return "วันพฤหัสบดี";
case 5:
return "วันศุกร์";
case 6:
return "วันเสาร์";
default:
return "-";
}
};
const genColor15 = (val: number) => {
val = val % 15;
switch (val) {
case 1:
return "pink";
case 2:
return "purple";
case 3:
return "deep-purple";
case 4:
return "indigo";
case 5:
return "blue";
case 6:
return "light-blue";
case 7:
return "cyan";
case 8:
return "teal";
case 9:
return "green";
case 10:
return "light-green";
case 11:
return "amber";
case 12:
return "orange";
case 13:
return "deep-orange";
case 14:
return "brown";
case 0:
return "blue-grey";
default:
return null;
}
};
export default {
date2Thai,
dateToISO,
notify,
notifyError,
dateText,
monthYear2Thai,
dateMonth2Thai,
success,
weekThai,
genColor15,
};

View file

@ -0,0 +1,281 @@
import { readonly } from "vue";
interface ScrollType {
position: number;
direction: string;
directionChanged: boolean;
inflectionPoint: number;
delta: number;
}
interface tabType {
key: number;
label: string;
tag: string;
}
interface childrenType {
key: number;
label: string;
path?: string;
}
interface menuType {
key: number;
icon: string;
activeIcon: string;
label: string;
path: string;
children?: childrenType[];
}
interface notiType {
id: number;
sender: string;
body: string;
timereceive: string;
}
interface optionType {
icon: string;
label: string;
value: string;
color: string;
}
const menuList = readonly<any[]>([
{
key: 1,
icon: "mdi-home-variant-outline",
activeIcon: "mdi-home-variant",
label: "หน้าแรก",
path: "dashboard",
role: "dashboard",
},
{
key: 2,
icon: "o_person",
activeIcon: "person",
label: "ข้อมูลหลัก",
path: "metadata",
role: "metadata",
},
{
key: 3,
icon: "o_groups",
activeIcon: "groups",
label: "โครงสร้างอัตรากำลัง",
path: "organizational",
role: "organization",
children: [
{
key: 3.1,
label: "จัดการตำแหน่ง",
path: "organizationalMapping",
},
{
key: 3.2,
label: "แผนภูมิโครงสร้าง",
path: "organizationalStructChart",
},
{
key: 3.3,
label: "แผนภูมิองค์กร",
path: "organizationalOrgChart",
},
{
key: 3.4,
label: "ผังโครงสร้าง",
path: "organizationalTree",
},
{
key: 3.5,
label: "จัดการบัญชี 2",
path: "manageReport2",
},
{
key: 3.6,
label: "รายงานบัญชี",
path: "organizationalReport",
},
],
},
{
key: 4,
icon: "o_contact_page",
activeIcon: "contact_page",
label: "ทะเบียนประวัติ",
path: "registry",
role: "registry",
},
{
key: 5,
icon: "o_search",
activeIcon: "search",
label: "สรรหา",
path: "recruiting",
role: "recruit",
children: [
{
label: "ตั้งค่าเว็บสรรหา",
path: "editorweb",
key: 5.1,
role: "recruit",
},
{
label: "สอบแข่งขัน",
path: "",
key: 5.2,
role: "recruit",
children: [
{
label: "จัดการข้อมูลผู้สมัครสอบ" /* แข่งขัน */,
path: "competePeriod",
role: "recruit",
},
{
label: "ข้อมูลสถิติการสมัครสอบ" /* แข่งขัน */,
path: "competePeriodStat",
role: "recruit",
},
],
},
{
label: "คัดเลือก",
path: "",
key: 5.3,
role: "recruit",
children: [
{
label: "จัดการรอบคัดเลือก",
path: "qualifyPeriod",
role: "recruit",
},
{
label: "จัดการรอบคัดเลือกคนพิการ",
path: "disablePeriod",
role: "recruit",
},
{
label: "จัดการรายชื่อคัดเลือก",
path: "manage",
role: "recruit",
},
{
label: "สถิติสมัครคัดเลือก",
path: "qualifyPeriodStat",
role: "recruit",
},
{
label: "สถิติสมัครคัดเลือกคนพิการ",
path: "qualifyPeriodStatDisable",
role: "recruit",
},
],
},
],
},
{
key: 6,
icon: "mdi-home-variant-outline",
activeIcon: "mdi-home-variant",
label: "บรรจุ แต่งตั้ง ย้าย โอน",
path: "placement",
role: "placement",
},
{
key: 7,
icon: "mdi-home-variant-outline",
activeIcon: "mdi-home-variant",
label: "พ้นจากราชการ",
path: "retirement",
role: "retirement",
},
{
key: 8,
icon: "mdi-home-variant-outline",
activeIcon: "mdi-home-variant",
label: "เครื่องราชอิสริยาภรณ์",
path: "insignia",
role: "insignia",
},
]);
const tabList = readonly<tabType[]>([
{
key: 1,
label: "ข้อมูลทั่วไป",
tag: "information",
},
{
key: 15,
label: "ใบอนุญาตประกอบอาชีพ",
tag: "certicate",
},
{
key: 2,
label: "ประวัติการศึกษา",
tag: "education",
},
{
key: 3,
label: "การฝึกอบรม/ดูงาน",
tag: "training",
},
{
key: 4,
label: "เครื่องราชอิสริยาภรณ์",
tag: "insignia",
},
{
key: 5,
label: "ประกาศเกียรติคุณ",
tag: "coined",
},
{
key: 6,
label: "ผลการประเมินปฏิบัติราชการ",
tag: "assessment",
},
{
key: 7,
label: "ตำแหน่ง/เงินเดือน",
tag: "position",
},
{
key: 8,
label: "วินัย",
tag: "rule",
},
{
key: 9,
label: "การลา",
tag: "leave",
},
{
key: 10,
label: "ความสามารถพิเศษ",
tag: "talent",
},
{
key: 11,
label: "ปฎิบัติราชการพิเศษ",
tag: "work",
},
{
key: 12,
label: "บันทึกวันที่ไม่ได้รับเงินเดือนฯ",
tag: "record",
},
{
key: 13,
label: "อื่นๆ",
tag: "other",
},
{
key: 14,
label: "เอกสารหลักฐาน",
tag: "document",
},
]);
export { menuList, tabList };
export type { ScrollType, tabType, menuType, notiType, optionType };

View file

@ -0,0 +1,46 @@
//response api เกี่ยวกับ status code กับ error
interface RequestHistoryObject {
message: String;
result: ResultHistoryObject;
status: number;
}
//rusult แนบ id version mongo
interface ResultHistoryObject {
id: String;
items: RequestPrefixHistoryObject;
version: String;
}
//ข้อมูล คำนำหน้า
interface RequestPrefixHistoryObject {
createdAt?: Date;
createdFullName: String;
createdUserId: String;
id: String;
isActive: Boolean;
lastUpdateFullName: String;
lastUpdateUserId: String;
lastUpdatedAt?: Date;
name: String;
}
//columns
interface PrefixColumns {
[index: number]: {
name: String;
align: String;
label: String;
sortable: Boolean;
field: String;
headerStyle: String;
style: String;
};
}
export type {
RequestHistoryObject,
ResultHistoryObject,
RequestPrefixHistoryObject,
PrefixColumns,
};

View file

@ -0,0 +1,14 @@
//ข้อมูล คำนำหน้า
interface ResponsePrefixHistoryObject {
createdAt?: Date;
createdFullName: String;
createdUserId: String;
id: String;
isActive: Boolean;
lastUpdateFullName: String;
lastUpdateUserId: String;
lastUpdatedAt?: Date;
name: String;
}
export type { ResponsePrefixHistoryObject };

71
src/main.ts Normal file
View file

@ -0,0 +1,71 @@
import { createApp, defineAsyncComponent } from "vue";
import App from "./App.vue";
import router from "./router";
import { Dialog, Notify, Quasar } from "quasar";
import quasarUserOptions from "./quasar-user-options";
import "quasar/src/css/index.sass";
import th from "quasar/lang/th";
import "@vuepic/vue-datepicker/dist/main.css";
import http from "./plugins/http";
import { createPinia } from "pinia";
// organization
// position
// positionEmployee
//calendar
// insignia
// import './assets/main.css'
// Import GlobalFilters
import filters from "./hooks/filters";
const app = createApp(App);
const pinia = createPinia();
// เพิ่ม Global Filters ลงใน App
app.config.globalProperties.$filters = filters;
app.use(router);
app.use(pinia);
app.use(
Quasar,
{
plugins: {
Notify,
Dialog,
}, // import Quasar plugins and add here
config: {
notify: {
/* look at QuasarConfOptions from the API card */
},
},
lang: th,
}
// quasarUserOptions // build ไม่ผ่านหลัง install code org&structure chart เลยต้องคอมเม้นไว้ก่อน เทสแล้วยังรันได้หลังคอมเม้น
);
//** Global Components */
app.component(
"data-table",
defineAsyncComponent(() => import("./components/TableView.vue"))
);
app.component(
"datepicker",
defineAsyncComponent(() => import("@vuepic/vue-datepicker"))
);
app.component(
"full-loader",
defineAsyncComponent(() => import("./plugins/FullLoader.vue"))
);
app.component(
"selector",
defineAsyncComponent(() => import("./components/Selector.vue"))
);
app.config.globalProperties.$http = http;
app.mount("#app");

View file

@ -0,0 +1,859 @@
<!-- tab ปฏ หนาปฏนวนหย -->
<template>
<div class="q-mt-md">
<div class="row q-gutter-sm q-pb-sm main-content">
<div class="demo-app-main">
<!-- แสดงปฏ -->
<FullCalendar
ref="fullCalendar"
class="demo-app-calendar"
:options="calendarOptions"
>
<template v-slot:eventContent="arg">
<b>{{ arg.timeText }}</b>
<i>{{ arg.event.title }}</i>
<q-tooltip style="font-size: 15px">{{ arg.event.title }}</q-tooltip>
</template>
</FullCalendar>
</div>
</div>
<div class="row q-col-gutter-md">
<div class="items-center row">
<q-icon color="blue" name="mdi-circle" class="q-mr-sm" />
นทำงาน 5
</div>
<div class="items-center row">
<q-icon color="orange" name="mdi-circle" class="q-mr-sm" />
นทำงาน 6
</div>
</div>
</div>
<!-- modal เพมวนหย -->
<q-dialog v-model="modalAdd" persistent>
<q-card style="min-width: 550px">
<q-form ref="formDate" @submit.prevent.stop="onSubmit">
<q-card-section class="row items-center q-pa-sm">
<div class="text-bold" v-if="showEdit">แก้ไขวันหยุด</div>
<div class="text-bold" v-else>เพิ่มวันหยุด</div>
<q-space />
<q-btn
icon="close"
unelevated
round
dense
v-close-popup
style="color: #ff8080; background-color: #ffdede"
/>
</q-card-section>
<q-separator />
<q-card-section class="q-p-md row q-gutter-y-md">
<div class="row col-12">
<div class="col-12" v-if="!showEdit">
{{ dateThaiRange(dateRange) }}
</div>
<datepicker
v-else
:readonly="!edit"
v-model="dateRange"
:locale="'th'"
autoApply
range
:enableTimePicker="false"
week-start="0"
>
<template #year="{ year }">
{{ year + 543 }}
</template>
<template #year-overlay-value="{ value }">
{{ parseInt(value + 543) }}
</template>
<template #trigger>
<q-input
:class="getClass(edit)"
hide-bottom-space
:outlined="edit"
dense
label="วันที่"
lazy-rules
:borderless="!edit"
:model-value="dateThaiRange(dateRange)"
>
<template v-slot:prepend>
<q-icon
name="event"
class="cursor-pointer"
style="color: var(--q-primary)"
>
</q-icon>
</template>
</q-input>
</template>
</datepicker>
</div>
<q-input
:class="getClass(edit)"
hide-bottom-space
:outlined="edit"
label="คำอธิบาย"
dense
lazy-rules
:readonly="!edit"
:borderless="!edit"
v-model="name"
autogrow
:rules="[(val) => (val && val.length > 0) || '']"
/>
<q-option-group
v-if="showEdit == false"
v-model="category"
:options="categoryOptions"
color="primary"
inline
/>
</q-card-section>
<q-separator />
<q-card-actions align="right" class="text-primary">
<q-btn
v-if="showEdit && edit"
flat
round
outline
color="red"
@click="cancelClick()"
icon="mdi-undo"
>
<q-tooltip>ยกเล</q-tooltip>
</q-btn>
<q-btn
v-if="edit"
flat
round
color="public"
icon="mdi-content-save-outline"
type="submit"
>
<q-tooltip>นท</q-tooltip>
</q-btn>
<q-btn
v-if="!edit"
flat
round
color="primary"
@click="editClick"
icon="mdi-pencil-outline"
>
<q-tooltip>แกไขขอม</q-tooltip>
</q-btn>
<q-btn
v-if="showEdit && edit"
flat
round
outline
color="red"
@click="deleteClick()"
icon="mdi-delete"
>
<q-tooltip>ลบ</q-tooltip>
</q-btn>
</q-card-actions>
</q-form>
</q-card>
</q-dialog>
<!-- modal ลบวนหย -->
<q-dialog v-model="modalDelete" persistent>
<q-card style="min-width: 550px">
<q-card-section class="row items-center q-pb-xs">
<div class="text-bold">องการลบขอมลนหรอไม?</div>
<q-space />
<q-btn
icon="close"
unelevated
round
dense
v-close-popup
style="color: #ff8080; background-color: #ffdede"
/>
</q-card-section>
<q-separator />
<q-card-section class="row items-center">
<div class="q-pr-md">
<q-avatar
icon="mdi-trash-can-outline"
font-size="25px"
size="lg"
color="red-1"
text-color="red"
/>
</div>
<div class="col text-dark">
<span>อมลทกำลงถกลบนจะมผลใชงานทนท</span>
</div>
</q-card-section>
<q-separator />
<q-card-actions align="right" class="bg-white text-teal">
<q-btn label="ยกเลิก" flat color="grey-8" @click="cancelClick" />
<q-btn label="ตกลง" color="primary" @click="deleteData" />
</q-card-actions>
</q-card>
</q-dialog>
</template>
<script setup lang="ts">
import type { QTableProps } from "quasar";
import { onMounted, ref, watch } from "vue";
import FullCalendar from "@fullcalendar/vue3";
import dayGridPlugin from "@fullcalendar/daygrid";
import timeGridPlugin from "@fullcalendar/timegrid";
import interactionPlugin from "@fullcalendar/interaction";
import allLocales from "@fullcalendar/core/locales-all";
import listPlugin from "@fullcalendar/list";
import http from "@/plugins/http";
import config from "@/app.config";
import { useQuasar } from "quasar";
import { useCounterMixin } from "@/stores/mixin";
import type {
RequestItemsObject,
DataDateRowObject,
DataDateAddObject,
} from "@/modules/01_metadata/interface/request/Calendar";
import { useDataStore } from "@/stores/data";
const props = defineProps({
dateYear: {
//filter
type: Number,
default: () => new Date().getFullYear(),
},
dateMonth: {
//filter
type: Number,
default: () => new Date().getMonth(),
},
refreshData: {
// main refresh data
type: Boolean,
required: true,
},
fetchDataSummaryCalendar: {
//
type: Function,
default: () => console.log("not function"),
},
});
const store = useDataStore();
const { loaderPage } = store;
const mixin = useCounterMixin(); //
const { success, dateToISO, date2Thai, messageError } = mixin;
const $q = useQuasar(); // noti quasar
const modalAdd = ref<boolean>(false); //modal
const modalDelete = ref<boolean>(false); //modal
const edit = ref<boolean>(false); //modal
const showEdit = ref<boolean>(false); // event
const name = ref<string>(""); //
const type = ref<string>(""); //
const isSpecial = ref<boolean>(true); //
const id = ref<string>(""); //id
const fullCalendar = ref<any>(); //ref calendar
const dateRange = ref<[Date, Date]>([new Date(), new Date()]); //
const formDate = ref<any>(); //ref validate
const category = ref<string>("all");
const categoryOptions = ref<any>([
{
label: "ทั้งหมด",
value: "all",
},
{
label: "ทำงาน 5 วัน",
value: "normal",
},
{
label: "ทำงาน 6 วัน",
value: "6days",
},
]);
const dataHistory = ref<RequestItemsObject[]>([]);
const dataNormalRaw = ref<RequestItemsObject[]>([]);
const dataSixDaysRaw = ref<RequestItemsObject[]>([]);
/**
* เรยกฟงกนทงหมดตอนเรยกใชไฟล
*/
onMounted(async () => {
loaderPage(false);
const calen = fullCalendar.value.getApi();
const date = new Date(props.dateYear, props.dateMonth);
calen.gotoDate(date);
await fetchData();
});
/**
* props(นเดอนปเลอก) ตอนอพเดท าฏนใหพเดทใหม
*/
watch(props, async (count, prevCount) => {
const calen = fullCalendar.value.getApi();
const date = new Date(props.dateYear, props.dateMonth);
calen.gotoDate(date);
await fetchData();
});
/**
* เลอกคาปฏนในชองวาง
* @param selectInfo าทเลอกในฏ
*/
const handleDateSelect = async (selectInfo: any) => {
edit.value = true;
category.value = "all";
selectInfo.start;
const checkNormalDate = dataNormalRaw.value.filter(
(r: RequestItemsObject) =>
dateToISO(new Date(r.holidayDate)) == dateToISO(selectInfo.start)
);
const checkSixDaysDate = dataSixDaysRaw.value.filter(
(r: RequestItemsObject) =>
dateToISO(new Date(r.holidayDate)) == dateToISO(selectInfo.start)
);
if (checkNormalDate.length == 0 || checkSixDaysDate.length == 0) {
name.value = "";
isSpecial.value = true;
dateRange.value = [
selectInfo.startStr,
new Date(
new Date(selectInfo.endStr).setDate(
new Date(selectInfo.endStr).getDate() - 1
)
),
];
showEdit.value = false;
modalAdd.value = true;
}
};
/**
* เลอกค event ในปฏ
* @param selectInfo าทเลอกในฏ
*/
const handleEventClick = async (selectInfo: any) => {
modalAdd.value = true;
edit.value = false;
showEdit.value = true;
name.value = selectInfo.event.title;
type.value = selectInfo.event.id;
isSpecial.value = true;
id.value = selectInfo.event.groupId;
dataHistory.value = selectInfo.event.extendedProps.dataRangeRow;
dateRange.value = [
selectInfo.event.startStr,
selectInfo.event.endStr == ""
? selectInfo.event.startStr
: dateToISO(
new Date(
new Date(selectInfo.event.endStr).setDate(
new Date(selectInfo.event.endStr).getDate() - 1
)
)
),
];
};
/**
* กดปมแกไขใหแสดง modal แกไข
*/
const editClick = async () => {
showEdit.value = true;
edit.value = true;
};
/**
* กดปมลบใหแสดง modal ลบ
*/
const deleteClick = async () => {
modalDelete.value = true;
};
/**
* มยกเลกใหอนกลบไป modal เลอกแกไขหรอลบ
*/
const cancelClick = async () => {
modalDelete.value = false;
modalAdd.value = true;
edit.value = false;
};
/**
* option calendar
*/
const calendarOptions = ref<any>({
plugins: [
dayGridPlugin,
timeGridPlugin,
interactionPlugin, // needed for dateClick
listPlugin,
],
headerToolbar: null,
selectable: true,
select: handleDateSelect,
eventClick: handleEventClick,
locale: "th",
locales: allLocales,
height: "100%",
eventColor: "#e4f3ff",
eventTextColor: "#50a5fc",
eventBorderColor: "#50a5fc",
events: <any>[],
firstDay: 0,
});
/**
* มบนทกขอมลวนหย
*/
const onSubmit = async () => {
if (showEdit.value === true) {
await editData();
} else {
await addDate();
}
};
/**
* fetch นหยดในปฏ
*/
const fetchData = async () => {
calendarOptions.value.events = [];
loaderPage(true);
await http
.get(
config.API.listHolidayHistoryYearMonth(
props.dateYear,
props.dateMonth + 1
)
)
.then((res) => {
const dataNormal = res.data.result.normal;
const dataSixDays = res.data.result.sixDays;
const dateStart = ref<Date | null>();
const firstEvent = ref<boolean>(true);
const dateRow = ref<DataDateRowObject[]>([]);
dataNormalRaw.value = res.data.result.normal;
dataSixDaysRaw.value = res.data.result.sixDays;
dataNormal.map((e: RequestItemsObject, index: number) => {
dateRow.value.push({
holidayDate: new Date(e.holidayDate),
name: e.name,
isSpecial: true,
id: e.id,
});
if (
index == dataNormal.length - 1 ||
dataNormal[index + 1].name != e.name ||
(dataNormal[index + 1].name == e.name &&
dateToISO(new Date(dataNormal[index + 1].holidayDate)) !=
dateToISO(
new Date(
new Date(e.holidayDate).setDate(
new Date(e.holidayDate).getDate() + 1
)
)
))
) {
firstEvent.value = true;
calendarOptions.value.events.push({
id: "normal",
groupId: e.id,
title:
dateToISO(new Date(e.holidayDate)) ==
dateToISO(new Date(e.originalDate))
? e.name
: `ชดเชย ${e.name}`,
start: dateStart.value ? dateStart.value : new Date(e.holidayDate),
end: new Date(
new Date(e.holidayDate).setDate(
new Date(e.holidayDate).getDate() + 1
)
),
isSpecial: true,
allDay: true,
dataRangeRow: dateRow.value,
backgroundColor: "#CCE5FF",
textColor: "#0080FF",
});
dateStart.value = null;
dateRow.value = [];
} else if (firstEvent.value == true) {
firstEvent.value = false;
dateStart.value = new Date(e.holidayDate);
}
});
dataSixDays.map((e: RequestItemsObject, index: number) => {
dateRow.value.push({
holidayDate: new Date(e.holidayDate),
name: e.name,
isSpecial: true,
id: e.id,
});
if (
index == dataSixDays.length - 1 ||
dataSixDays[index + 1].name != e.name ||
(dataSixDays[index + 1].name == e.name &&
dateToISO(new Date(dataSixDays[index + 1].holidayDate)) !=
dateToISO(
new Date(
new Date(e.holidayDate).setDate(
new Date(e.holidayDate).getDate() + 1
)
)
))
) {
firstEvent.value = true;
calendarOptions.value.events.push({
id: "sixdays",
groupId: e.id,
title:
dateToISO(new Date(e.holidayDate)) ==
dateToISO(new Date(e.originalDate))
? e.name
: `ชดเชย ${e.name}`,
start: dateStart.value ? dateStart.value : new Date(e.holidayDate),
end: new Date(
new Date(e.holidayDate).setDate(
new Date(e.holidayDate).getDate() + 1
)
),
isSpecial: true,
allDay: true,
dataRangeRow: dateRow.value,
backgroundColor: "#FFE5CC",
textColor: "#FF8000",
});
dateStart.value = null;
dateRow.value = [];
} else if (firstEvent.value == true) {
firstEvent.value = false;
dateStart.value = new Date(e.holidayDate);
}
});
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await props.fetchDataSummaryCalendar();
});
};
/**
* นทกแกไขวนหย
*/
const editData = async () => {
await formDate.value.validate().then(async (result: boolean) => {
if (result) {
const dataEdit = ref<DataDateAddObject[]>([]);
let i = 0;
const dateStart = ref<Date>(dateRange.value[0]);
do {
i = i + 1;
dataEdit.value.push({
year: new Date(dateStart.value).getFullYear(),
holidayDate: dateToISO(new Date(dateStart.value)),
name: name.value,
isSpecial: true,
});
dateStart.value = new Date(
new Date(dateStart.value).setDate(
new Date(dateStart.value).getDate() + 1
)
);
} while (new Date(dateStart.value) <= new Date(dateRange.value[1]));
const _dataHistory = ref<RequestItemsObject[]>([]);
dataHistory.value.map((e: RequestItemsObject, index: number) => {
_dataHistory.value.push({
...e,
holidayDate: dateToISO(new Date(e.holidayDate)),
});
});
loaderPage(true);
await http
.post(config.API.listHolidayHistoryEdit(type.value), {
history: _dataHistory.value,
updated: dataEdit.value,
})
.then((res) => {
modalAdd.value = false;
success($q, "แก้ไขข้อมูลสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchData();
});
}
});
};
/**
* นทกเพมวนหย
*/
const addDate = async () => {
await formDate.value.validate().then(async (result: boolean) => {
if (result) {
const dataAdd = ref<DataDateAddObject[]>([]);
let i = 0;
const dateStart = ref<Date>(dateRange.value[0]);
do {
i = i + 1;
dataAdd.value.push({
year: new Date(dateStart.value).getFullYear(),
holidayDate: dateToISO(new Date(dateStart.value)),
name: name.value,
isSpecial: true,
});
dateStart.value = new Date(
new Date(dateStart.value).setDate(
new Date(dateStart.value).getDate() + 1
)
);
} while (new Date(dateStart.value) <= new Date(dateRange.value[1]));
loaderPage(true);
await http
.post(config.API.listHolidayHistoryAdd(category.value), dataAdd.value)
.then((res) => {
modalAdd.value = false;
success($q, "เพิ่มข้อมูลสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchData();
});
}
});
};
/**
* ลบขอมลวนหย
*/
const deleteData = async () => {
modalDelete.value = false;
const dataDelete = ref<DataDateAddObject[]>([]);
let i = 0;
const dateStart = ref<Date>(dateRange.value[0]);
do {
i = i + 1;
dataDelete.value.push({
year: new Date(dateStart.value).getFullYear(),
holidayDate: dateToISO(new Date(dateStart.value)),
name: name.value,
isSpecial: true,
});
dateStart.value = new Date(
new Date(dateStart.value).setDate(new Date(dateStart.value).getDate() + 1)
);
} while (new Date(dateStart.value) <= new Date(dateRange.value[1]));
loaderPage(true);
await http
.post(config.API.listHolidayHistoryDelete(type.value), dataDelete.value)
.then((res) => {
success($q, "ลบข้อมูลสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
modalAdd.value = false;
await fetchData();
});
};
/**
* แปลงชวงวนทา2คาเปนวนเดยวกนจะโชววนเดยวแตาไมเทากนจะแสดงเปนชวง
* @param val วงวนท
*/
const dateThaiRange = (val: [Date, Date]) => {
if (val === null) {
} else if (date2Thai(val[0]) === date2Thai(val[1])) {
return `${date2Thai(val[0])}`;
} else {
return `${date2Thai(val[0])} - ${date2Thai(val[1])} `;
}
};
const getClass = (val: boolean) => {
return {
"full-width inputgreen cursor-pointer": val,
"full-width cursor-pointer": !val,
};
};
</script>
<style scope lang="scss">
.main-content {
height: 70vh;
}
.color-main {
color: #18a259;
}
.padding-content {
padding: 10px;
}
.demo-app-main {
flex-grow: 1;
/* padding: 3em; */
}
.fc {
/* the calendar root */
max-width: 1100px;
margin: 0 auto;
background-color: white;
border-radius: 10px;
}
.fc-day-today {
background-color: rgb(255, 255, 255) !important;
}
// .fc-day-sun {
// background-color: rgba(207, 205, 205, 0.177) !important;
// width: 80px;
// }
// .fc-day-sat {
// background-color: rgba(207, 205, 205, 0.177) !important;
// width: 80px;
// }
.fc-day-today .fc-daygrid-day-number {
display: flex;
justify-content: center;
align-items: center;
/* border: 2px solid #17a259; */
border-radius: 50%;
height: 25px;
width: 25px;
font-weight: bold;
color: white !important;
background: #17a259;
}
.fc-day-today .fc-daygrid-day-frame {
padding: 5%;
}
.fc .fc-button-group > .fc-button {
color: black;
background-color: #fafafa;
border: none;
}
.fc .fc-button-group > .fc-button:active {
color: white;
background-color: #22a15e;
border: none;
}
.fc .fc-button-group > .fc-button.fc-button-active {
color: white;
background-color: #22a15e;
border: none;
}
.fc-header-toolbar {
background-color: white;
padding: 0px 10px 0px 10px;
border-radius: 10px 10px 0px 0px;
}
.fc .fc-scrollgrid-liquid > thead {
background-color: #f8f8f8;
}
.dp-custom-cell {
border-radius: 50%;
}
.dp__today {
border: 1px solid var(--q-primary);
}
.dp__range_end,
.dp__range_start,
.dp__active_date {
background: var(--q-primary);
color: var(--dp-primary-text-color);
}
.datepicker .q-field__label {
padding-left: 5px;
}
.datepicker .q-field__messages {
padding-left: 20px;
}
.datepicker .q-field__native {
padding-left: 5px;
color: var(--q-primary) !important;
}
.datepicker .q-field__prepend {
padding-left: 6px;
}
.datepicker .q-field__append {
padding-right: 6px;
}
.datepicker .q-field__after {
display: flex;
justify-content: flex-end;
align-items: center;
font-weight: 500;
}
.fc .fc-popover {
z-index: 6000;
}
.fc-direction-ltr .fc-daygrid-event.fc-event-end,
.fc-direction-rtl .fc-daygrid-event.fc-event-start {
cursor: pointer;
}
.subName {
display: flex;
justify-content: flex-end;
align-items: center;
font-weight: 500;
}
.subInput {
display: flex;
align-items: center;
}
.fc-event {
overflow: hidden;
border-color: transparent !important;
font-weight: 500;
}
.fc-event-main {
text-align: center;
}
.fc-direction-ltr .fc-daygrid-event.fc-event-end,
.fc-direction-rtl .fc-daygrid-event.fc-event-start {
padding-left: 0px;
}
</style>

View file

@ -0,0 +1,580 @@
<!-- tab รายการ หนาปฏนวนหย -->
<template>
<q-card class="q-mt-md" flat bordered>
<!-- list รายการนหย -->
<q-tabs
dense
v-model="currentTab"
indicator-color="primary"
active-color="primary bg-teal-1"
class="text-body2 text-grey-7"
>
<q-tab
v-for="tab in tabs"
:key="tab.value"
v-on:click="changeTab(tab.value)"
:label="tab.label"
:name="tab.value"
class="q-py-xs col-6 row"
/>
</q-tabs>
<q-table
ref="table"
flat
bordered
class="custom-header-table"
virtual-scroll
:rows="calendarData"
:columns="columns"
dense
:rows-per-page-options="[0]"
hide-header
>
<template v-slot:body="props">
<q-tr :props="props">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.name == 'week'" class="">
{{ dayThaiRange(props.row.dateRange) }}
</div>
<div v-else-if="col.name == 'holidayDate'" class="">
{{ dateThaiRange(props.row.dateRange) }}
</div>
<div v-else class="my-table-details">
{{ col.value }}
</div>
</q-td>
<q-td auto-width>
<q-btn
flat
round
color="grey"
@click.stop
size="10px"
icon="more_vert"
>
<q-menu>
<q-list>
<q-item
clickable
v-close-popup
@click="editCalendar(props.row)"
>
<q-item-section>
<q-item-label>แกไขวนหย</q-item-label>
</q-item-section>
</q-item>
<q-item
clickable
v-close-popup
@click="deleteClick(props.row)"
>
<q-item-section>
<q-item-label>ลบวนหย</q-item-label>
</q-item-section>
</q-item>
</q-list>
</q-menu>
</q-btn>
</q-td>
</q-tr>
</template>
</q-table>
</q-card>
<!-- modal เพมวนหย -->
<q-dialog v-model="modalAdd" persistent>
<q-card style="min-width: 550px">
<q-form ref="formDate" @submit.prevent.stop="editData">
<q-card-section class="row items-center q-pb-xs">
<div class="text-bold">แกไขวนหย</div>
<q-space />
<q-btn
icon="close"
unelevated
round
dense
v-close-popup
style="color: #ff8080; background-color: #ffdede"
/>
</q-card-section>
<q-separator />
<q-card-section class="q-p-sm">
<div class="row col-12 q-col-gutter-sm">
<div class="col-2 subName">
<label>เลอกวนท</label>
</div>
<div class="col-10">
<datepicker
v-model="dateAdd"
:locale="'th'"
autoApply
range
:enableTimePicker="false"
week-start="0"
>
<template #year="{ year }">
{{ year + 543 }}
</template>
<template #year-overlay-value="{ value }">
{{ parseInt(value + 543) }}
</template>
<template #trigger>
<q-input
outlined
dense
class="full-width datepicker"
:model-value="dateThaiRange(dateAdd)"
>
<template v-slot:prepend>
<q-icon
name="event"
class="cursor-pointer"
style="color: var(--q-primary)"
>
</q-icon>
</template>
</q-input>
</template>
</datepicker>
</div>
</div>
<div class="row col-12 q-col-gutter-sm">
<div class="col-2 subName">
<label>คำอธบาย</label>
</div>
<div class="col-10">
<q-input
dense
borderless
class="full-width datepicker q-pb-none"
v-model="name"
type="textarea"
:rules="[(val) => (val && val.length > 0) || '']"
/>
</div>
</div>
</q-card-section>
<q-separator />
<q-card-actions align="right" class="text-primary">
<q-btn
flat
round
color="public"
icon="mdi-content-save-outline"
type="submit"
>
<q-tooltip>นท</q-tooltip>
</q-btn>
</q-card-actions>
</q-form>
</q-card>
</q-dialog>
<!-- modal ลบวนหย -->
<q-dialog v-model="modalDelete" persistent>
<q-card style="min-width: 550px">
<q-card-section class="row items-center q-pb-xs">
<div class="text-bold">องการลบขอมลนหรอไม?</div>
<q-space />
<q-btn
icon="close"
unelevated
round
dense
v-close-popup
style="color: #ff8080; background-color: #ffdede"
/>
</q-card-section>
<q-separator />
<q-card-section class="row items-center">
<div class="q-pr-md">
<q-avatar
icon="mdi-trash-can-outline"
font-size="25px"
size="lg"
color="red-1"
text-color="red"
/>
</div>
<div class="col text-dark">
<span>อมลทกำลงถกลบนจะมผลใชงานทนท</span>
</div>
</q-card-section>
<q-separator />
<q-card-actions align="right" class="bg-white text-teal">
<q-btn label="ตกลง" color="primary" @click="deleteConfirm" />
</q-card-actions>
</q-card>
</q-dialog>
</template>
<script setup lang="ts">
import type { QTableProps } from "quasar";
import { onMounted, ref, watch } from "vue";
import http from "@/plugins/http";
import config from "@/app.config";
import { useQuasar } from "quasar";
import { useCounterMixin } from "@/stores/mixin";
import type {
RequestItemsObject,
DataDateRowObject,
DataDateAddObject,
DataDateListsObject,
TabsObject,
} from "@/modules/01_metadata/interface/request/Calendar";
import { useDataStore } from "@/stores/data";
const props = defineProps({
dateYear: {
//filter
type: Number,
required: true,
},
refreshData: {
// main refresh data
type: Boolean,
required: true,
},
fetchDataSummaryCalendar: {
//
type: Function,
default: () => console.log("not function"),
},
});
const store = useDataStore();
const { loaderPage } = store;
const mixin = useCounterMixin(); //
const { success, dateToISO, dateMonth2Thai, weekThai, messageError } = mixin;
const $q = useQuasar(); // noti quasar
const calendarData = ref<DataDateListsObject[]>([]); //data
const modalAdd = ref<boolean>(false); //modal
const modalDelete = ref<boolean>(false); //modal
const name = ref<string>(""); //
const isSpecial = ref<boolean>(true); //
const dateAdd = ref<[Date, Date]>([new Date(), new Date()]); //
const rowData = ref<DataDateListsObject>(); //data row
const formDate = ref<any>(); //ref validate
const currentTab = ref<string>("normal"); // tab
const tabs = ref<TabsObject[]>([
{ label: "ทำงานจันทร์-ศุกร์ (5 วัน)", value: "normal" },
{ label: "ทำงานจันทร์-เสาร์ (6 วัน)", value: "6day" },
]); //tab
//columns
const columns = ref<any>([
{
name: "week",
align: "left",
label: "-",
sortable: true,
field: "week",
style: "font-size: 15px",
},
{
name: "holidayDate",
align: "left",
label: "-",
sortable: true,
field: "holidayDate",
style: "font-size: 15px",
},
{
name: "detail",
align: "left",
label: "-",
sortable: true,
field: "detail",
style: "font-size: 15px",
},
]);
/**
* เรยกฟงกนทงหมดตอนเรยกใชไฟล
*/
onMounted(async () => {
await fetchData();
});
/**
* props(นปเลอก และเพมหรอแกไข) ตอนอพเดท าฏนใหพเดทใหม
*/
watch(props, async (count, prevCount) => {
await fetchData();
});
/**
* กดปมแกไขวนหย
* @param val data นหยดท row
*/
const editCalendar = async (val: DataDateListsObject) => {
rowData.value = val;
dateAdd.value = [val.dateRange[0], val.dateRange[1]];
name.value = val.detail;
isSpecial.value = true;
modalAdd.value = true;
};
/**
* กดปมลบวนหย
* @param val data นหยดท row
*/
const deleteClick = async (val: DataDateListsObject) => {
rowData.value = val;
modalDelete.value = true;
};
/**
* fetch นหยดในรายการ
*/
const fetchData = async () => {
calendarData.value = [];
loaderPage(true);
await http
.get(config.API.listHolidayHistoryYear(props.dateYear))
.then((res) => {
let data = res.data.result.normal;
if (currentTab.value == "6day") {
data = res.data.result.sixDays;
}
const dateStart = ref<Date | null>();
const firstEvent = ref<boolean>(true);
const dateRow = ref<DataDateRowObject[]>([]);
data.map((e: RequestItemsObject, index: number) => {
dateRow.value.push({
holidayDate: new Date(e.holidayDate),
name: e.name,
isSpecial: true,
id: e.id,
});
if (
index == data.length - 1 ||
data[index + 1].name != e.name ||
(data[index + 1].name == e.name &&
dateToISO(new Date(data[index + 1].holidayDate)) !=
dateToISO(
new Date(
new Date(e.holidayDate).setDate(
new Date(e.holidayDate).getDate() + 1
)
)
))
) {
firstEvent.value = true;
calendarData.value.push({
id: e.id,
dateRange: [
dateStart.value ? dateStart.value : new Date(e.holidayDate),
new Date(e.holidayDate),
],
dataRangeRow: dateRow.value,
detail:
dateToISO(new Date(e.holidayDate)) ==
dateToISO(new Date(e.originalDate))
? e.name
: `ชดเชย ${e.name}`,
isSpecial: true,
});
dateStart.value = null;
dateRow.value = [];
} else if (firstEvent.value == true) {
firstEvent.value = false;
dateStart.value = new Date(e.holidayDate);
}
});
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await props.fetchDataSummaryCalendar();
});
};
/**
* ลบขอมลวนหย
*/
const deleteConfirm = async () => {
modalDelete.value = false;
const dataDelete = ref<DataDateAddObject[]>([]);
if (rowData.value != null) {
await rowData.value.dataRangeRow.map((e: DataDateRowObject) => {
dataDelete.value.push({
year: new Date(e.holidayDate).getFullYear(),
holidayDate: dateToISO(e.holidayDate),
name: e.name,
isSpecial: true,
});
});
} else {
return;
}
loaderPage(true);
await http
.post(
config.API.listHolidayHistoryDelete(currentTab.value),
dataDelete.value
)
.then((res) => {
success($q, "ลบข้อมูลสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchData();
});
};
/**
* นทกแกไขวนหย
*/
const editData = async () => {
await formDate.value.validate().then(async (result: boolean) => {
if (result) {
const dataEdit = ref<DataDateAddObject[]>([]);
let i = 0;
const dateStart = ref<Date>(dateAdd.value[0]);
do {
i = i + 1;
dataEdit.value.push({
year: new Date(dateStart.value).getFullYear(),
holidayDate: dateToISO(new Date(dateStart.value)),
name: name.value,
isSpecial: true,
});
dateStart.value = new Date(
new Date(dateStart.value).setDate(
new Date(dateStart.value).getDate() + 1
)
);
} while (new Date(dateStart.value) <= new Date(dateAdd.value[1]));
const _dataHistory = ref<DataDateAddObject[]>([]);
if (rowData.value != null) {
rowData.value.dataRangeRow.map(
(e: DataDateRowObject, index: number) => {
_dataHistory.value.push({
year: new Date(e.holidayDate).getFullYear(),
holidayDate: dateToISO(e.holidayDate),
name: e.name,
isSpecial: true,
});
}
);
}
loaderPage(true);
await http
.post(config.API.listHolidayHistoryEdit(currentTab.value), {
history: _dataHistory.value,
updated: dataEdit.value,
})
.then((res) => {
modalAdd.value = false;
success($q, "แก้ไขข้อมูลสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchData();
});
} else {
}
});
};
/**
* เปลยน tab นหยดตามประเภท
* @param tab tab ประเภทวนหยดทเลอก
*/
const changeTab = async (tab: string) => {
currentTab.value = tab;
await fetchData();
};
/**
* แปลงชวงวนทา2คาเปนวนเดยวกนจะโชววนเดยวแตาไมเทากนจะแสดงเปนชวง
* @param val วงวนท
*/
const dateThaiRange = (val: [Date, Date]) => {
if (val === null) {
return "";
} else if (dateMonth2Thai(val[0], true) === dateMonth2Thai(val[1], true)) {
return `${dateMonth2Thai(val[0], true)}`;
} else {
return `${dateMonth2Thai(val[0], true)} - ${dateMonth2Thai(val[1], true)}`;
}
};
/**
* แปลงชวงวนทา2คาเปนวนเดยวกนจะโชววนเดยวแตาไมเทากนจะแสดงเปนชวง(เชนวนจนทร -นศกร)
* @param val วงวนท
*/
const dayThaiRange = (val: [Date, Date]) => {
if (val === null) {
} else if (dateToISO(val[0]) == dateToISO(val[1])) {
return `${weekThai(new Date(val[0]).getDay())}`;
} else {
return `${weekThai(new Date(val[0]).getDay())} - ${weekThai(
new Date(val[1]).getDay()
)}`;
}
};
</script>
<style lang="scss">
.custom-header-table {
max-height: 64vh;
.q-table tr:nth-child(odd) td {
background: white;
}
.q-table tr:nth-child(even) td {
background: #f8f8f8;
}
.q-table thead tr {
background: #ecebeb;
}
.q-table thead tr th {
position: sticky;
z-index: 1;
}
/* this will be the loading indicator */
.q-table thead tr:last-child th {
/* height of all previous header rows */
top: 48px;
}
.q-table thead tr:first-child th {
top: 0;
}
}
.my-table-details {
white-space: -moz-pre-wrap !important;
/* Mozilla, since 1999 */
white-space: -webkit-pre-wrap;
/* Chrome & Safari */
white-space: -pre-wrap;
/* Opera 4-6 */
white-space: -o-pre-wrap;
/* Opera 7 */
white-space: pre-wrap;
/* CSS3 */
word-wrap: break-word;
/* Internet Explorer 5.5+ */
word-break: break-all;
white-space: normal;
}
.table_ellipsis {
overflow: hidden;
text-overflow: ellipsis;
white-space: wrap;
max-width: 250px;
}
</style>

View file

@ -0,0 +1,198 @@
<template>
<q-dialog :model-value="modal" persistent>
<q-card style="min-width: 700px">
<q-form ref="myForm">
<div class="row items-center q-pa-sm">
<div class="row">
<div class="text-bold">{{ tittle }}</div>
</div>
<q-space />
<q-btn
icon="close"
unelevated
round
dense
style="color: #ff8080; background-color: #ffdede"
size="12px"
@click="close"
/>
</div>
<q-separator />
<div class="q-pa-sm">
<!-- header บน table นหา แสดงคอลมน (status nornmalData true) -->
<div class="col-12 row q-pb-sm">
<q-select
hide-bottom-space
@update:model-value="updateHistory"
outlined
dense
lazy-rules
borderless
:model-value="history"
:label="`${'ชื่อเครื่องราชฯ'}`"
emit-value
map-options
option-label="publishedDate"
:options="optionsHistory"
option-value="id"
/>
<q-space />
<div class="items-center" style="display: flex">
<!-- นหาขอความใน table -->
<q-input
standout
dense
:model-value="inputfilter"
ref="filterRef"
@update:model-value="updateInput"
outlined
debounce="300"
placeholder="ค้นหา"
style="max-width: 200px"
class="q-ml-sm"
>
<template v-slot:append>
<q-icon v-if="inputfilter == ''" name="search" />
<q-icon
v-if="inputfilter !== ''"
name="clear"
class="cursor-pointer"
@click="resetFilter"
/>
</template>
</q-input>
<!-- แสดงคอลมนใน table -->
<q-select
:model-value="inputvisible"
@update:model-value="updateVisible"
:display-value="$q.lang.table.columns"
multiple
outlined
dense
:options="attrs.columns"
options-dense
option-value="name"
map-options
emit-value
style="min-width: 150px"
class="gt-xs q-ml-sm"
/>
</div>
</div>
<q-table
ref="table"
flat
bordered
class="custom-header-table"
v-bind="attrs"
virtual-scroll
:virtual-scroll-sticky-size-start="48"
dense
:pagination-label="paginationLabel"
:pagination="initialPagination"
:rows-per-page-options="[0]"
>
<template v-slot:header="props">
<q-tr :props="props">
<q-th v-for="col in props.cols" :key="col.name" :props="props">
<span class="text-weight-medium">{{ col.label }}</span>
</q-th>
</q-tr>
</template>
<!-- สำหรบเรยกใช template วขางนอก -->
<template #body="props">
<slot v-bind="props" name="columns"></slot>
</template>
</q-table>
</div>
<q-separator />
</q-form>
</q-card>
</q-dialog>
</template>
<script setup lang="ts">
import type { QTableProps } from "quasar";
import { ref, useAttrs } from "vue";
import type { Pagination } from "@/modules/01_metadata/interface/index/Main";
const attrs = ref<any>(useAttrs());
const filterRef = ref<any>(null);
const initialPagination = ref<Pagination>({
rowsPerPage: 0,
});
const props = defineProps({
tittle: String,
inputfilter: String,
history: String,
inputvisible: Array,
modal: Boolean,
optionsHistory: Array,
updateHistory: {
type: Function,
default: () => console.log("not function"),
},
});
const emit = defineEmits([
"update:inputfilter",
"update:inputvisible",
"update:modal",
"update:history",
]);
const updateInput = (value: string | number | null) => {
emit("update:inputfilter", value);
};
const updateVisible = (value: []) => {
emit("update:inputvisible", value);
};
const close = () => {
emit("update:modal", false);
};
const updateHistory = (value: string) => {
emit("update:history", value);
props.updateHistory();
};
const paginationLabel = (start: string, end: string, total: string) => {
return start + "-" + end + " ใน " + total;
};
// reset X
const resetFilter = () => {
emit("update:inputfilter", "");
filterRef.value.focus();
};
</script>
<style lang="scss">
.icon-color {
color: #4154b3;
}
.custom-header-table {
max-height: 64vh;
.q-table tr:nth-child(odd) td {
background: white;
}
.q-table tr:nth-child(even) td {
background: #f8f8f8;
}
.q-table thead tr {
background: #ecebeb;
}
.q-table thead tr th {
position: sticky;
z-index: 1;
}
/* this will be the loading indicator */
.q-table thead tr:last-child th {
/* height of all previous header rows */
top: 48px;
}
.q-table thead tr:first-child th {
top: 0;
}
}
</style>

View file

@ -0,0 +1,966 @@
<!-- tab อเครองราช หนาจดการขอมลหล/อมลเครองราชอสรยาภรณ -->
<template>
<div>
<q-form ref="myForm">
<data-table
:rows="rows"
:columns="columns"
:filter="filter"
:visible-columns="visibleColumns"
v-model:inputfilter="filter"
v-model:inputvisible="visibleColumns"
v-model:editvisible="edit"
:add="clickAdd"
:edit="clickEdit"
:save="clickSave"
:deleted="clickDelete"
:cancel="clickCancel"
:publish="clickPublish"
:validate="validateData"
:publicData="version === 'published'"
:updateData="updateData"
:history="true"
>
<template #columns="props">
<q-tr :props="props" v-if="edit == false">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.name == 'isActive'" class="">
<q-icon
v-if="col.value == false"
name="mdi-close"
color="red"
class="text-h5"
/>
<q-icon
v-else
name="mdi-check"
color="positive"
class="text-h5"
/>
</div>
<div v-else-if="col.name == 'createdAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else-if="col.name == 'lastUpdatedAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else-if="col.name == 'insigniaType'" class="">
{{ col.value == null ? "" : col.value.name }}
</div>
<div v-else class="">
{{ col.value }}
</div>
</q-td>
<q-td auto-width>
<q-btn
color="info"
flat
dense
round
size="14px"
icon="mdi-history"
@click="clickHistory(props.row)"
/>
</q-td>
</q-tr>
<q-tr :props="props" v-if="edit == true">
<q-td
key="level"
:props="props"
v-if="props.row.level !== undefined"
>
<div class="">
{{ props.row.level }}
</div>
</q-td>
<q-td key="name" :props="props" v-if="props.row.name !== undefined">
<q-input
class=""
outlined
@update:model-value="clickEditRow"
v-model="props.row.name"
dense
lazy-rules
autofocus
hide-bottom-space
:rules="[
(val) => (val && val.length > 0) || 'กรุณากรอกข้อมูลให้ครบ',
(val) =>
checkDupDataName(val) || 'ชื่อซ้ำกันกับข้อมูลที่มีอยู่แล้ว',
]"
></q-input>
</q-td>
<q-td
key="shortName"
:props="props"
v-if="props.row.shortName !== undefined"
>
<q-input
class=""
outlined
@update:model-value="clickEditRow"
v-model="props.row.shortName"
dense
lazy-rules
hide-bottom-space
:rules="[
(val) => (val && val.length > 0) || 'กรุณากรอกข้อมูลให้ครบ',
(val) =>
checkDupDataShortName(val) ||
'ชื่อซ้ำกันกับข้อมูลที่มีอยู่แล้ว',
]"
></q-input>
</q-td>
<q-td
key="insigniaType"
:props="props"
v-if="props.row.shortName !== undefined"
>
<q-select
:options="insigniaTypeOption"
outlined
@update:model-value="clickEditRow"
v-model="props.row.insigniaType"
dense
lazy-rules
hide-bottom-space
option-label="name"
option-value="id"
:rules="[(val) => val || 'กรุณาเลือกลำดับชั้นเครื่องราชฯ']"
/>
</q-td>
<q-td
key="createdAt"
:props="props"
v-if="props.row.createdAt !== undefined"
>
<div class="">
{{ textDate(props.row.createdAt) }}
</div>
</q-td>
<q-td key="lastUpdatedAt" :props="props">
<div class="">
{{ textDate(props.row.lastUpdatedAt) }}
</div>
</q-td>
<q-td
key="lastUpdateFullName"
:props="props"
v-if="props.row.lastUpdateFullName !== undefined"
class=""
>
{{ props.row.lastUpdateFullName }}
</q-td>
<q-td
key="isActive"
:props="props"
v-if="props.row.isActive !== undefined"
>
<q-toggle
v-model="props.row.isActive"
dense
size="34px"
color="positive"
@update:model-value="clickEditRow"
/>
</q-td>
<q-td key="note" :props="props" v-if="props.row.note !== undefined">
<q-input
class=""
outlined
@update:model-value="clickEditRow"
v-model="props.row.note"
dense
lazy-rules
autofocus
hide-bottom-space
></q-input>
</q-td>
<q-td auto-width>
<div class="row">
<q-btn
:disable="props.row.level <= 1"
flat
dense
size="12px"
icon="mdi-menu-up"
style="
padding-top: 0em;
padding-right: 0.5em;
padding-bottom: 0em;
padding-left: 0.5em;
min-height: 0em;
"
@click="directionItem(props.row, 'up')"
/>
<q-btn
:disable="props.row.level >= rows.length"
flat
dense
size="12px"
icon="mdi-menu-down"
style="
padding-top: 0em;
padding-right: 0.5em;
padding-bottom: 0em;
padding-left: 0.5em;
min-height: 0em;
"
@click="directionItem(props.row, 'down')"
/>
</div>
<q-btn
v-if="props.row.id !== '00000000-0000-0000-0000-000000000000'"
color="info"
flat
dense
round
size="14px"
icon="mdi-history"
@click="clickHistory(props.row)"
/>
<q-btn
v-if="props.row.id === '00000000-0000-0000-0000-000000000000'"
color="red"
flat
dense
round
size="14px"
icon="mdi-trash-can-outline"
@click="clickDeleteRow(props.row)"
/>
</q-td>
</q-tr>
</template>
</data-table>
</q-form>
</div>
<HistoryTable
:rows="rowsHistory"
:columns="columnsHistory"
:filter="filterHistory"
:visible-columns="visibleColumnsHistory"
v-model:modal="modalHistory"
v-model:inputfilter="filterHistory"
v-model:inputvisible="visibleColumnsHistory"
v-model:tittle="tittleHistory"
>
<template #columns="props">
<q-tr :props="props">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.name == 'isActive'" class="">
<q-icon
v-if="col.value == false"
name="mdi-close"
color="red"
class="text-h5"
/>
<q-icon v-else name="mdi-check" color="positive" class="text-h5" />
</div>
<div v-else-if="col.name == 'lastUpdatedAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else-if="col.name == 'insigniaType'" class="">
{{ col.value == null ? "" : col.value.name }}
</div>
<div v-else class="">
{{ col.value }}
</div>
</q-td>
</q-tr>
</template>
</HistoryTable>
</template>
<script setup lang="ts">
import type { QTableProps } from "quasar";
import { useQuasar } from "quasar";
import { onMounted, ref, watch } from "vue";
import http from "@/plugins/http";
import config from "@/app.config";
import keycloak from "@/plugins/keycloak";
import { useCounterMixin } from "@/stores/mixin";
import { useManageDataStore } from "@/modules/01_metadata/store";
import type {
RequestItemsHistoryObject,
RequestItemsPublishHistoryObject,
Columns,
} from "@/modules/01_metadata/interface/request/insignia/Insignia";
import type { ResponseHistoryObject } from "@/modules/01_metadata/interface/response/insignia/Insignia";
import type { DataOption } from "@/modules/01_metadata/interface/index/Main";
import HistoryTable from "@/components/TableHistory.vue";
import { useDataStore } from "@/stores/data";
const props = defineProps({
fetchDataComponent: {
type: Function,
default: () => console.log("not function"),
},
});
const dataStore = useDataStore();
const { loaderPage } = dataStore;
const mixin = useCounterMixin();
const { success, dateText, messageError } = mixin;
const store = useManageDataStore();
const { manageData, changeManageColumns } = store;
const rows = ref<RequestItemsHistoryObject[]>([]); //list data table
const rowsHistory = ref<RequestItemsHistoryObject[]>([]); //select data history
const rawHistory = ref<RequestItemsHistoryObject[]>([]); //raw data history
const tittleHistory = ref<string>("ประวัติแก้ไขชื่อเครื่องราชฯ"); //
const myForm = ref<any>(null); //ref
const filter = ref<string>(""); //search data table
const filterHistory = ref<string>(""); //search data table history
const modalHistory = ref<boolean>(false); //modal
const edit = ref<boolean>(false); //
const idVersion = ref<string>(""); //id data mongodb
const version = ref<string>("published"); // published= draft=
const updateData = ref<boolean>(false); //
const checkValidate = ref<boolean>(false);
const insigniaTypeOption = ref<DataOption[]>([]); //
const columns = ref<QTableProps["columns"]>([
{
name: "level",
align: "left",
label: "ลำดับ",
sortable: true,
field: "level",
headerStyle: "font-size: 14px; width:0px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "name",
align: "left",
label: "ชื่อเครื่องราชฯ",
sortable: true,
field: "name",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "shortName",
align: "left",
label: "ชื่อย่อ",
sortable: true,
field: "shortName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "insigniaType",
align: "left",
label: "ลำดับชั้นเครื่องราชฯ",
sortable: true,
field: "insigniaType",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "createdAt",
align: "center",
label: "วันที่สร้าง",
sortable: true,
field: "createdAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdatedAt",
align: "center",
label: "วันที่แก้ไข",
sortable: true,
field: "lastUpdatedAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdateFullName",
align: "left",
label: "ผู้ดำเนินการ",
sortable: true,
field: "lastUpdateFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "isActive",
align: "left",
label: "สถานะ",
sortable: true,
field: "isActive",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "note",
align: "left",
label: "หมายเหตุ",
sortable: true,
field: "note",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumns = ref<String[]>([]);
manageData.insignia.class.columns.length == 0
? (visibleColumns.value = [
"level",
"name",
"shortName",
"insigniaType",
"createdAt",
"lastUpdatedAt",
"lastUpdateFullName",
"isActive",
"note",
])
: (visibleColumns.value = manageData.insignia.class.columns);
const columnsHistory = ref<QTableProps["columns"]>([
{
name: "level",
align: "left",
label: "ลำดับ",
sortable: true,
field: "level",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "name",
align: "left",
label: "ชื่อเครื่องราชฯ",
sortable: true,
field: "name",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "shortName",
align: "left",
label: "ชื่อย่อ",
sortable: true,
field: "shortName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "insigniaType",
align: "left",
label: "ลำดับชั้นเครื่องราชฯ",
sortable: true,
field: "insigniaType",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdatedAt",
align: "center",
label: "วันที่แก้ไข",
sortable: true,
field: "lastUpdatedAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdateFullName",
align: "left",
label: "ผู้ดำเนินการ",
sortable: true,
field: "lastUpdateFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "isActive",
align: "left",
label: "สถานะ",
sortable: true,
field: "isActive",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "note",
align: "left",
label: "หมายเหตุ",
sortable: true,
field: "note",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumnsHistory = ref<String[]>([
"level",
"name",
"shortName",
"insigniaType",
"lastUpdatedAt",
"lastUpdateFullName",
"isActive",
"note",
]);
/**
* เมอเขาหนานจะเรยกฟงชนนอน(get list data)
*/
onMounted(async () => {
await fetchData();
await fetchHistory();
});
watch(visibleColumns, async (count: String[], prevCount: String[]) => {
await changeManageColumns(6, "class", count);
});
/**
* แจงเตอนขอมลในกรณ success
*/
const $q = useQuasar();
/**
* งก get data าส
*/
const fetchData = async () => {
await props.fetchDataComponent();
rows.value.splice(0);
loaderPage(true);
await http
.get(config.API.listInsigniaHistory)
.then((res) => {
let data = res.data.result;
version.value = data.version; // published= draft=
idVersion.value = data.id; // id mongodb
data.items.map((e: RequestItemsHistoryObject) => {
rows.value.push({
id: e.id,
name: e.name,
shortName: e.shortName,
level: e.level,
createdAt: e.createdAt,
lastUpdatedAt: e.lastUpdatedAt,
lastUpdateFullName: e.lastUpdateFullName,
isActive: e.isActive,
createdFullName: e.createdFullName,
createdUserId: e.createdUserId,
lastUpdateUserId: e.lastUpdateUserId,
insigniaType: e.insigniaType,
note: e.note,
});
});
rows.value.sort(
(
firstItem: RequestItemsHistoryObject,
secondItem: RequestItemsHistoryObject
) => firstItem.level - secondItem.level
);
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchinsigniaType();
});
};
/**
* รายการลำดบเครองราชฯ
*/
const fetchinsigniaType = async () => {
loaderPage(true);
await http
.get(config.API.insigniaType)
.then((res) => {
const data = res.data.result;
let option: DataOption[] = [];
data.map((r: RequestItemsHistoryObject) => {
option.push({ id: r.id.toString(), name: r.name.toString() });
});
insigniaTypeOption.value = option;
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
updateData.value = false;
loaderPage(false);
});
};
/**
* งชนดอมลประวแกไขขอมลทงหมด
*/
const fetchHistory = async () => {
loaderPage(true);
await http
.get(config.API.listInsigniaPublishedHistory)
.then((res) => {
const data = res.data.result;
rawHistory.value = [];
if (data.length > 0) {
data.map((e: RequestItemsPublishHistoryObject) => {
e.items.map((i: RequestItemsHistoryObject) => {
rawHistory.value.push({
createdAt: i.createdAt,
createdFullName: i.createdFullName,
createdUserId: i.createdUserId,
id: i.id,
isActive: i.isActive,
lastUpdateFullName: i.lastUpdateFullName,
lastUpdateUserId: i.lastUpdateUserId,
lastUpdatedAt: i.lastUpdatedAt,
level: i.level,
name: i.name,
shortName: i.shortName,
insigniaType: i.insigniaType,
note: i.note,
});
});
});
}
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
loaderPage(false);
});
};
/**
* งก clear data แบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
*/
const clearPublishedData = async () => {
loaderPage(true);
await http
.delete(config.API.listInsigniaHistory)
.then((res) => {
success($q, "ลบข้อมูลร่างสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchHistory();
await fetchData();
});
};
/**
* งกนเผยแพรแบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
*/
const publishedData = async () => {
loaderPage(true);
await http
.get(config.API.listInsigniaPublished)
.then((res) => {
success($q, "เผยแพร่ข้อมูลสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchData();
});
};
/**
* งกนเพมขอม
*/
const clickAdd = async () => {
const filterRowNull = rows.value.filter(
(f: RequestItemsHistoryObject) =>
f.id === "00000000-0000-0000-0000-000000000000" &&
(f.name == "" || f.shortName == "") // array
);
if (filterRowNull.length == 0) {
//
rows.value.push({
createdAt: new Date(),
createdFullName: "",
createdUserId: "",
id: "00000000-0000-0000-0000-000000000000",
isActive: true,
lastUpdateFullName:
keycloak.tokenParsed == null ? "" : keycloak.tokenParsed.name,
lastUpdateUserId: "",
lastUpdatedAt: new Date(),
name: "",
shortName: "",
level: rows.value[rows.value.length - 1].level + 1,
note: "",
});
updateData.value = true;
}
};
/**
* งกนบนทกแบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
* publish เมอบนทกแบบรางแลวจะเผยแพรเลยไหม true=นทกและเผยแพร false=นทกอยางเดยว
*/
const save = async (publish: boolean) => {
await validateData();
if (checkValidate.value == false) return;
rows.value.map((e: ResponseHistoryObject) => ({
// data backend
id: e.id,
createdAt: e.createdAt,
lastUpdatedAt: e.lastUpdatedAt,
name: e.name,
shortName: e.shortName,
level: e.level,
isActive: e.isActive,
createdFullName: e.createdFullName,
createdUserId: e.createdUserId,
lastUpdateFullName: e.lastUpdateFullName,
lastUpdateUserId: e.lastUpdateUserId,
insigniaType: e.insigniaType,
}));
loaderPage(true);
await http
.post(config.API.listInsigniaHistoryId(idVersion.value), {
id: idVersion.value,
version: "draft",
items: rows.value,
})
.then(async (res) => {
if (publish === false) {
success($q, "บันทึกข้อมูลร่างสำเร็จ");
await fetchData(); // get data
} else {
await publishedData(); //
}
edit.value = false;
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
loaderPage(false);
});
};
/**
* เชคชอซำกบขอมลทอยแล
* @param val input
*/
const checkDupDataName = (val: string) => {
const filterNameNull = rows.value.filter(
(f: RequestItemsHistoryObject) => f.name == val
); //
if (filterNameNull.length > 1) {
return false;
}
return true;
};
/**
* เชคชอยอซำกบขอมลทอยแล
* @param val input อย
*/
const checkDupDataShortName = (val: string) => {
const filterShortNameNull = rows.value.filter(
(f: RequestItemsHistoryObject) => f.shortName == val
); //
if (filterShortNameNull.length > 1) {
return false;
}
return true;
};
/**
* งกนปมแกไข ให get data มาใหม
*/
const clickEdit = async () => {
await fetchData();
};
/**
* งกนปมบนทกแบบราง
*/
const clickSave = async () => {
await save(false);
};
/**
* งกนปมลบแบบราง
*/
const clickDelete = async () => {
await clearPublishedData();
};
/**
* งกนปมยกเลกการแกไขขอม
*/
const clickCancel = async () => {
edit.value = false;
await fetchData();
};
/**
* งกนปมเผยแพรอม
* เชคขอมลกอนวาใน array กรอกขอมลครบไหมถาครบกใหเผยแพรได
* าคาใน array ไมอมลใน row จะใหนทกได
*/
const clickPublish = async () => {
if (myForm.value !== null) {
myForm.value.validate().then(async (result: boolean) => {
if (result) {
save(true);
}
});
} else {
await save(true);
}
};
/**
* งกนปมลบ row data
* @param val data ใน row จะลบ
*/
const clickDeleteRow = (val: RequestItemsHistoryObject) => {
rows.value = rows.value.filter((x: RequestItemsHistoryObject) => x !== val);
updateData.value = true;
};
/**
* งกนเช input ามการแกไขหรอย
*/
const clickEditRow = () => {
myForm.value.validate(false);
updateData.value = true;
};
/**
* งชนดอมลประวแกไขขอมลทเลอก
* @param row อม row ประวการแกไข
*/
const clickHistory = async (row: RequestItemsHistoryObject) => {
modalHistory.value = true;
rowsHistory.value = rawHistory.value.filter(
(f: RequestItemsHistoryObject) => f.id == row.id
);
};
/**
* งกนแปลง date เปนภาษาไทย
* @param value นท type datetime จะแปลงเปนไทย
*/
const textDate = (value: Date) => {
return dateText(value);
};
/**
* validate component
*/
const validateData = async () => {
checkValidate.value = true;
await myForm.value.validate().then((result: boolean) => {
if (result == false) {
checkValidate.value = false;
}
});
};
/**
* ายลำด data
* @param row าใน row
* @param type ายตำแหนงแบบไหน up= down=ลง
*/
const directionItem = (row: RequestItemsHistoryObject, type: string) => {
clickEditRow();
if (type === "up") {
rows.value[
rows.value.findIndex((object: RequestItemsHistoryObject) => {
return object === row;
})
].level -= 1;
rows.value[
rows.value.findIndex((object: RequestItemsHistoryObject) => {
return object === row;
}) - 1
].level += 1;
} else {
rows.value[
rows.value.findIndex((object: RequestItemsHistoryObject) => {
return object === row;
})
].level += 1;
rows.value[
rows.value.findIndex((object: RequestItemsHistoryObject) => {
return object === row;
}) + 1
].level -= 1;
}
rows.value.sort(
(
firstItem: RequestItemsHistoryObject,
secondItem: RequestItemsHistoryObject
) => firstItem.level - secondItem.level
);
};
</script>
<style>
/* สีของnoti */
.my-notif-class {
background: rgba(33, 186, 69, 0.5) !important;
color: #008f17 !important;
}
</style>

View file

@ -0,0 +1,659 @@
<!-- tab ลำดบชนเครองราชฯ หนาจดการขอมลหล/อมลเครองราชอสรยาภรณ -->
<template>
<div>
<q-form ref="myForm">
<data-table
:rows="rows"
:columns="columns"
:filter="filter"
:visible-columns="visibleColumns"
v-model:inputfilter="filter"
v-model:inputvisible="visibleColumns"
v-model:editvisible="edit"
:add="clickAdd"
:edit="clickEdit"
:save="clickSave"
:deleted="clickDelete"
:cancel="clickCancel"
:publish="clickPublish"
:validate="validateData"
:publicData="version === 'published'"
:updateData="updateData"
:history="true"
>
<template #columns="props">
<q-tr :props="props" v-if="edit == false">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.name == 'isActive'" class="">
<q-icon
v-if="col.value == false"
name="mdi-close"
color="red"
class="text-h5"
/>
<q-icon
v-else
name="mdi-check"
color="positive"
class="text-h5"
/>
</div>
<div v-else-if="col.name == 'createdAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else-if="col.name == 'lastUpdatedAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else class="">
{{ col.value }}
</div>
</q-td>
<q-td auto-width>
<q-btn
color="info"
flat
dense
round
size="14px"
icon="mdi-history"
@click="clickHistory(props.row)"
/>
</q-td>
</q-tr>
<q-tr :props="props" v-if="edit == true">
<q-td key="name" :props="props" v-if="props.row.name !== undefined">
<q-input
class=""
outlined
@update:model-value="clickEditRow"
v-model="props.row.name"
dense
lazy-rules
autofocus
hide-bottom-space
:rules="[
(val) => (val && val.length > 0) || 'กรุณากรอกข้อมูลให้ครบ',
(val) =>
checkDupDataName(val) || 'ชื่อซ้ำกันกับข้อมูลที่มีอยู่แล้ว',
]"
></q-input>
</q-td>
<q-td
key="createdAt"
:props="props"
v-if="props.row.createdAt !== undefined"
>
<div class="">
{{ textDate(props.row.createdAt) }}
</div>
</q-td>
<q-td key="lastUpdatedAt" :props="props">
<div class="">
{{ textDate(props.row.lastUpdatedAt) }}
</div>
</q-td>
<q-td
key="lastUpdateFullName"
:props="props"
v-if="props.row.lastUpdateFullName !== undefined"
class=""
>
{{ props.row.lastUpdateFullName }}
</q-td>
<q-td
key="isActive"
:props="props"
v-if="props.row.isActive !== undefined"
>
<q-toggle
v-model="props.row.isActive"
dense
size="34px"
color="positive"
@update:model-value="clickEditRow"
/>
</q-td>
<q-td auto-width>
<q-btn
v-if="props.row.id === '00000000-0000-0000-0000-000000000000'"
color="red"
flat
dense
round
size="14px"
icon="mdi-trash-can-outline"
@click="clickDeleteRow(props.row)"
/>
<q-btn
v-if="props.row.id !== '00000000-0000-0000-0000-000000000000'"
color="info"
flat
dense
round
size="14px"
icon="mdi-history"
@click="clickHistory(props.row)"
/>
</q-td>
</q-tr>
</template>
</data-table>
</q-form>
</div>
<HistoryTable
:rows="rowsHistory"
:columns="columnsHistory"
:filter="filterHistory"
:visible-columns="visibleColumnsHistory"
v-model:modal="modalHistory"
v-model:inputfilter="filterHistory"
v-model:inputvisible="visibleColumnsHistory"
v-model:tittle="tittleHistory"
>
<template #columns="props">
<q-tr :props="props">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.name == 'isActive'" class="">
<q-icon
v-if="col.value == false"
name="mdi-close"
color="red"
class="text-h5"
/>
<q-icon v-else name="mdi-check" color="positive" class="text-h5" />
</div>
<div v-else-if="col.name == 'lastUpdatedAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else class="">
{{ col.value }}
</div>
</q-td>
</q-tr>
</template>
</HistoryTable>
</template>
<script setup lang="ts">
import type { QTableProps } from "quasar";
import { useQuasar } from "quasar";
import { onMounted, ref, watch } from "vue";
import http from "@/plugins/http";
import config from "@/app.config";
import keycloak from "@/plugins/keycloak";
import { useCounterMixin } from "@/stores/mixin";
import { useManageDataStore } from "@/modules/01_metadata/store";
import type {
RequestItemsHistoryObject,
RequestItemsPublishHistoryObject,
Columns,
} from "@/modules/01_metadata/interface/request/insignia/InsigniaType";
import type { ResponseHistoryObject } from "@/modules/01_metadata/interface/response/insignia/InsigniaType";
import HistoryTable from "@/components/TableHistory.vue";
import { useDataStore } from "@/stores/data";
const props = defineProps({
fetchDataComponent: {
type: Function,
default: () => console.log("not function"),
},
});
const dataStore = useDataStore();
const { loaderPage } = dataStore;
const mixin = useCounterMixin();
const { success, dateText, messageError } = mixin;
const store = useManageDataStore();
const { manageData, changeManageColumns } = store;
const rows = ref<RequestItemsHistoryObject[]>([]); //list data table
const rowsHistory = ref<RequestItemsHistoryObject[]>([]); //select data history
const rawHistory = ref<RequestItemsHistoryObject[]>([]); //raw data history
const tittleHistory = ref<string>("ประวัติแก้ไขลำดับชั้นเครื่องราชฯ"); //
const myForm = ref<any>(null); //ref
const filter = ref<string>(""); //search data table
const filterHistory = ref<string>(""); //search data table history
const modalHistory = ref<boolean>(false); //modal
const edit = ref<boolean>(false); //
const idVersion = ref<string>(""); //id data mongodb
const version = ref<string>("published"); // published= draft=
const updateData = ref<boolean>(false); //
const checkValidate = ref<boolean>(false);
const columns = ref<QTableProps["columns"]>([
{
name: "name",
align: "left",
label: "ลำดับชั้นเครื่องราชฯ",
sortable: true,
field: "name",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "createdAt",
align: "center",
label: "วันที่สร้าง",
sortable: true,
field: "createdAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdatedAt",
align: "center",
label: "วันที่แก้ไข",
sortable: true,
field: "lastUpdatedAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdateFullName",
align: "left",
label: "ผู้ดำเนินการ",
sortable: true,
field: "lastUpdateFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "isActive",
align: "left",
label: "สถานะ",
sortable: true,
field: "isActive",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumns = ref<String[]>([]);
manageData.insignia.type.columns.length == 0
? (visibleColumns.value = [
"name",
"createdAt",
"lastUpdatedAt",
"lastUpdateFullName",
"isActive",
])
: (visibleColumns.value = manageData.insignia.type.columns);
const columnsHistory = ref<QTableProps["columns"]>([
{
name: "name",
align: "left",
label: "ลำดับชั้นเครื่องราชฯ",
sortable: true,
field: "name",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdatedAt",
align: "center",
label: "วันที่แก้ไข",
sortable: true,
field: "lastUpdatedAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdateFullName",
align: "left",
label: "ผู้ดำเนินการ",
sortable: true,
field: "lastUpdateFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "isActive",
align: "left",
label: "สถานะ",
sortable: true,
field: "isActive",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumnsHistory = ref<String[]>([
"name",
"lastUpdatedAt",
"lastUpdateFullName",
"isActive",
]);
/**
* เมอเขาหนานจะเรยกฟงชนนอน(get list data)
*/
onMounted(async () => {
await fetchData();
await fetchHistory();
});
watch(visibleColumns, async (count: String[], prevCount: String[]) => {
await changeManageColumns(6, "type", count);
});
/**
* แจงเตอนขอมลในกรณ success
*/
const $q = useQuasar();
/**
* งก get data าส
*/
const fetchData = async () => {
await props.fetchDataComponent();
rows.value.splice(0);
loaderPage(true);
await http
.get(config.API.listInsigniaTypeHistory)
.then((res) => {
let data = res.data.result;
version.value = data.version; // published= draft=
idVersion.value = data.id; // id mongodb
data.items.map((e: RequestItemsHistoryObject) => {
rows.value.push({
id: e.id,
name: e.name,
createdAt: e.createdAt,
lastUpdatedAt: e.lastUpdatedAt,
lastUpdateFullName: e.lastUpdateFullName,
isActive: e.isActive,
createdFullName: e.createdFullName,
createdUserId: e.createdUserId,
lastUpdateUserId: e.lastUpdateUserId,
});
});
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
updateData.value = false;
loaderPage(false);
});
};
/**
* งชนดอมลประวแกไขขอมลทงหมด
*/
const fetchHistory = async () => {
loaderPage(true);
await http
.get(config.API.listInsigniaTypePublishedHistory)
.then((res) => {
const data = res.data.result;
rawHistory.value = [];
if (data.length > 0) {
data.map((e: RequestItemsPublishHistoryObject) => {
e.items.map((i: RequestItemsHistoryObject) => {
rawHistory.value.push({
createdAt: i.createdAt,
createdFullName: i.createdFullName,
createdUserId: i.createdUserId,
id: i.id,
isActive: i.isActive,
lastUpdateFullName: i.lastUpdateFullName,
lastUpdateUserId: i.lastUpdateUserId,
lastUpdatedAt: i.lastUpdatedAt,
name: i.name,
});
});
});
}
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
loaderPage(false);
});
};
/**
* งก clear data แบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
*/
const clearPublishedData = async () => {
loaderPage(true);
await http
.delete(config.API.listInsigniaTypeHistory)
.then((res) => {
success($q, "ลบข้อมูลร่างสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchHistory();
await fetchData();
});
};
/**
* งกนเผยแพรแบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
*/
const publishedData = async () => {
loaderPage(true);
await http
.get(config.API.listInsigniaTypePublished)
.then((res) => {
success($q, "เผยแพร่ข้อมูลสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchData();
});
};
/**
* งกนเพมขอม
*/
const clickAdd = async () => {
const filterRowNull = rows.value.filter(
(f: RequestItemsHistoryObject) =>
f.id === "00000000-0000-0000-0000-000000000000" && f.name == "" // array
);
if (filterRowNull.length == 0) {
//
rows.value.push({
createdAt: new Date(),
createdFullName: "",
createdUserId: "",
id: "00000000-0000-0000-0000-000000000000",
isActive: true,
lastUpdateFullName:
keycloak.tokenParsed == null ? "" : keycloak.tokenParsed.name,
lastUpdateUserId: "",
lastUpdatedAt: new Date(),
name: "",
});
updateData.value = true;
}
};
/**
* งกนบนทกแบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
* publish เมอบนทกแบบรางแลวจะเผยแพรเลยไหม true=นทกและเผยแพร false=นทกอยางเดยว
*/
const save = async (publish: boolean) => {
await validateData();
if (checkValidate.value == false) return;
rows.value.map((e: ResponseHistoryObject) => ({
// data backend
id: e.id,
createdAt: e.createdAt,
lastUpdatedAt: e.lastUpdatedAt,
name: e.name,
isActive: e.isActive,
createdFullName: e.createdFullName,
createdUserId: e.createdUserId,
lastUpdateFullName: e.lastUpdateFullName,
lastUpdateUserId: e.lastUpdateUserId,
}));
loaderPage(true);
await http
.post(config.API.listInsigniaTypeHistoryId(idVersion.value), {
id: idVersion.value,
version: "draft",
items: rows.value,
})
.then(async (res) => {
if (publish === false) {
success($q, "บันทึกข้อมูลร่างสำเร็จ");
await fetchData(); // get data
} else {
await publishedData(); //
}
edit.value = false;
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
loaderPage(false);
});
};
/**
* เชคชอซำกบขอมลทอยแล
* @param val input
*/
const checkDupDataName = (val: string) => {
const filterNameNull = rows.value.filter(
(f: RequestItemsHistoryObject) => f.name == val
); //
if (filterNameNull.length > 1) {
return false;
}
return true;
};
/**
* งกนปมแกไข ให get data มาใหม
*/
const clickEdit = async () => {
await fetchData();
};
/**
* งกนปมบนทกแบบราง
*/
const clickSave = async () => {
await save(false);
};
/**
* งกนปมลบแบบราง
*/
const clickDelete = async () => {
await clearPublishedData();
};
/**
* งกนปมยกเลกการแกไขขอม
*/
const clickCancel = async () => {
edit.value = false;
await fetchData();
};
/**
* งกนปมเผยแพรอม
* เชคขอมลกอนวาใน array กรอกขอมลครบไหมถาครบกใหเผยแพรได
* าคาใน array ไมอมลใน row จะใหนทกได
*/
const clickPublish = async () => {
if (myForm.value !== null) {
myForm.value.validate().then(async (result: boolean) => {
if (result) {
await save(true);
}
});
} else {
await save(true);
}
};
/**
* งกนปมลบ row data
* @param val data ใน row จะลบ
*/
const clickDeleteRow = (val: RequestItemsHistoryObject) => {
rows.value = rows.value.filter((x: RequestItemsHistoryObject) => x !== val);
updateData.value = true;
};
/**
* งกนเช input ามการแกไขหรอย
*/
const clickEditRow = () => {
myForm.value.validate(false);
updateData.value = true;
};
/**
* งชนดอมลประวแกไขขอมลทเลอก
* @param row อม row ประวการแกไข
*/
const clickHistory = async (row: RequestItemsHistoryObject) => {
modalHistory.value = true;
rowsHistory.value = rawHistory.value.filter(
(f: RequestItemsHistoryObject) => f.id == row.id
);
};
/**
* งกนแปลง date เปนภาษาไทย
* @param value นท type datetime จะแปลงเปนไทย
*/
const textDate = (value: Date) => {
return dateText(value);
};
/**
* validate component
*/
const validateData = async () => {
checkValidate.value = true;
await myForm.value.validate().then((result: boolean) => {
if (result == false) {
checkValidate.value = false;
}
});
};
</script>
<style>
/* สีของnoti */
.my-notif-class {
background: rgba(33, 186, 69, 0.5) !important;
color: #008f17 !important;
}
</style>

View file

@ -0,0 +1,660 @@
<!-- tab หนวยงานตนสงก หนาจดการขอมลหล/อมลโครงสรางหนวยงาน -->
<template>
<div>
<q-form ref="myForm">
<data-table
:rows="rows"
:columns="columns"
:filter="filter"
:visible-columns="visibleColumns"
v-model:inputfilter="filter"
v-model:inputvisible="visibleColumns"
v-model:editvisible="edit"
:add="clickAdd"
:edit="clickEdit"
:save="clickSave"
:deleted="clickDelete"
:cancel="clickCancel"
:publish="clickPublish"
:validate="validateData"
:publicData="version === 'published'"
:updateData="updateData"
:history="true"
>
<template #columns="props">
<q-tr :props="props" v-if="edit == false">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.name == 'isActive'" class="">
<q-icon
v-if="col.value == false"
name="mdi-close"
color="red"
class="text-h5"
/>
<q-icon
v-else
name="mdi-check"
color="positive"
class="text-h5"
/>
</div>
<div v-else-if="col.name == 'createdAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else-if="col.name == 'lastUpdatedAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else class="">
{{ col.value }}
</div>
</q-td>
<q-td auto-width>
<q-btn
color="info"
flat
dense
round
size="14px"
icon="mdi-history"
@click="clickHistory(props.row)"
/>
</q-td>
</q-tr>
<q-tr :props="props" v-if="edit == true">
<q-td key="name" :props="props" v-if="props.row.name !== undefined">
<q-input
class=""
outlined
@update:model-value="clickEditRow"
v-model="props.row.name"
dense
lazy-rules
autofocus
hide-bottom-space
:rules="[
(val) => (val && val.length > 0) || 'กรุณากรอกข้อมูลให้ครบ',
(val) =>
checkDupDataName(val) || 'ชื่อซ้ำกันกับข้อมูลที่มีอยู่แล้ว',
]"
></q-input>
</q-td>
<q-td
key="createdAt"
:props="props"
v-if="props.row.createdAt !== undefined"
>
<div class="">
{{ textDate(props.row.createdAt) }}
</div>
</q-td>
<q-td key="lastUpdatedAt" :props="props">
<div class="">
{{ textDate(props.row.lastUpdatedAt) }}
</div>
</q-td>
<q-td
key="lastUpdateFullName"
:props="props"
v-if="props.row.lastUpdateFullName !== undefined"
class=""
>
{{ props.row.lastUpdateFullName }}
</q-td>
<q-td
key="isActive"
:props="props"
v-if="props.row.isActive !== undefined"
>
<q-toggle
v-model="props.row.isActive"
dense
color="green"
@update:model-value="clickEditRow"
/>
</q-td>
<q-td auto-width>
<q-btn
v-if="props.row.id === '00000000-0000-0000-0000-000000000000'"
color="red"
flat
dense
round
size="14px"
icon="mdi-trash-can-outline"
@click="clickDeleteRow(props.row)"
/>
<q-btn
v-if="props.row.id !== '00000000-0000-0000-0000-000000000000'"
color="info"
flat
dense
round
size="14px"
icon="mdi-history"
@click="clickHistory(props.row)"
/>
</q-td>
</q-tr>
</template>
</data-table>
</q-form>
</div>
<HistoryTable
:rows="rowsHistory"
:columns="columnsHistory"
:filter="filterHistory"
:visible-columns="visibleColumnsHistory"
v-model:modal="modalHistory"
v-model:inputfilter="filterHistory"
v-model:inputvisible="visibleColumnsHistory"
v-model:tittle="tittleHistory"
>
<template #columns="props">
<q-tr :props="props">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.name == 'isActive'" class="">
<q-icon
v-if="col.value == false"
name="mdi-close"
color="red"
class="text-h5"
/>
<q-icon v-else name="mdi-check" color="positive" class="text-h5" />
</div>
<div v-else-if="col.name == 'lastUpdatedAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else class="">
{{ col.value }}
</div>
</q-td>
</q-tr>
</template>
</HistoryTable>
</template>
<script setup lang="ts">
import type { QTableProps } from "quasar";
import { useQuasar } from "quasar";
import { onMounted, ref, watch } from "vue";
import http from "@/plugins/http";
import config from "@/app.config";
import keycloak from "@/plugins/keycloak";
import { useCounterMixin } from "@/stores/mixin";
import { useManageDataStore } from "@/modules/01_metadata/store";
import type {
RequestItemsHistoryObject,
RequestItemsPublishHistoryObject,
Columns,
} from "@/modules/01_metadata/interface/request/organization/Agency";
import type { ResponseHistoryObject } from "@/modules/01_metadata/interface/response/organization/Agency";
import HistoryTable from "@/components/TableHistory.vue";
import { useDataStore } from "@/stores/data";
const props = defineProps({
fetchDataComponent: {
type: Function,
default: () => console.log("not function"),
},
});
const dataStore = useDataStore();
const { loaderPage } = dataStore;
const mixin = useCounterMixin();
const { success, dateText, messageError } = mixin;
const store = useManageDataStore();
const { manageData, changeManageColumns } = store;
const rows = ref<RequestItemsHistoryObject[]>([]); //list data table
const rowsHistory = ref<RequestItemsHistoryObject[]>([]); //select data history
const rawHistory = ref<RequestItemsHistoryObject[]>([]); //raw data history
const tittleHistory = ref<string>("ประวัติแก้ไขหน่วยงานต้นสังกัด"); //
const myForm = ref<any>(null); //ref
const filter = ref<string>(""); //search data table
const filterHistory = ref<string>(""); //search data table history
const modalHistory = ref<boolean>(false); //modal
const edit = ref<boolean>(false); //
const idVersion = ref<string>(""); //id data mongodb
const version = ref<string>("published"); // published= draft=
const updateData = ref<boolean>(false); //
const checkValidate = ref<boolean>(false);
const columns = ref<QTableProps["columns"]>([
{
name: "name",
align: "left",
label: "หน่วยงานต้นสังกัด",
sortable: true,
field: "name",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "createdAt",
align: "center",
label: "วันที่สร้าง",
sortable: true,
field: "createdAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdatedAt",
align: "center",
label: "วันที่แก้ไข",
sortable: true,
field: "lastUpdatedAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdateFullName",
align: "left",
label: "ผู้ดำเนินการ",
sortable: true,
field: "lastUpdateFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "isActive",
align: "left",
label: "สถานะ",
sortable: true,
field: "isActive",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumns = ref<String[]>([]);
manageData.organization.agency.columns.length == 0
? (visibleColumns.value = [
"name",
"createdAt",
"lastUpdatedAt",
"lastUpdateFullName",
"isActive",
])
: (visibleColumns.value = manageData.organization.agency.columns);
const columnsHistory = ref<QTableProps["columns"]>([
{
name: "name",
align: "left",
label: "หน่วยงานต้นสังกัด",
sortable: true,
field: "name",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdatedAt",
align: "center",
label: "วันที่แก้ไข",
sortable: true,
field: "lastUpdatedAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdateFullName",
align: "left",
label: "ผู้ดำเนินการ",
sortable: true,
field: "lastUpdateFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "isActive",
align: "left",
label: "สถานะ",
sortable: true,
field: "isActive",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumnsHistory = ref<String[]>([
"name",
"lastUpdatedAt",
"lastUpdateFullName",
"isActive",
]);
/**
* เมอเขาหนานจะเรยกฟงชนนอน(get list data)
*/
onMounted(async () => {
await fetchData();
await fetchHistory();
});
watch(visibleColumns, async (count: String[], prevCount: String[]) => {
await changeManageColumns(2, "agency", count);
});
/**
* แจงเตอนขอมลในกรณ success
*/
const $q = useQuasar();
/**
* งก get data าส
*/
const fetchData = async () => {
await props.fetchDataComponent();
rows.value.splice(0);
loaderPage(true);
await http
.get(config.API.listOrganizationAgencyHistory)
.then((res) => {
let data = res.data.result;
version.value = data.version; // published= draft=
idVersion.value = data.id; // id mongodb
data.items.map((e: RequestItemsHistoryObject) => {
rows.value.push({
id: e.id,
name: e.name,
createdAt: e.createdAt,
lastUpdatedAt: e.lastUpdatedAt,
lastUpdateFullName: e.lastUpdateFullName,
isActive: e.isActive,
createdFullName: e.createdFullName,
createdUserId: e.createdUserId,
lastUpdateUserId: e.lastUpdateUserId,
});
});
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
updateData.value = false;
loaderPage(false);
});
};
/**
* งชนดอมลประวแกไขขอมลทงหมด
*/
const fetchHistory = async () => {
loaderPage(true);
await http
.get(config.API.listOrganizationAgencyPublishedHistory)
.then((res) => {
const data = res.data.result;
rawHistory.value = [];
if (data.length > 0) {
data.map((e: RequestItemsPublishHistoryObject) => {
e.items.map((i: RequestItemsHistoryObject) => {
rawHistory.value.push({
createdAt: i.createdAt,
createdFullName: i.createdFullName,
createdUserId: i.createdUserId,
id: i.id,
isActive: i.isActive,
lastUpdateFullName: i.lastUpdateFullName,
lastUpdateUserId: i.lastUpdateUserId,
lastUpdatedAt: i.lastUpdatedAt,
name: i.name,
});
});
});
}
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
loaderPage(false);
});
};
/**
* งก clear data แบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
*/
const clearPublishedData = async () => {
loaderPage(true);
await http
.delete(config.API.listOrganizationAgencyHistory)
.then((res) => {
success($q, "ลบข้อมูลร่างสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchHistory();
await fetchData();
});
};
/**
* งกนเผยแพรแบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
*/
const publishedData = async () => {
loaderPage(true);
await http
.get(config.API.listOrganizationAgencyPublished)
.then((res) => {
success($q, "เผยแพร่ข้อมูลสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchData();
});
};
/**
* งกนเพมขอม
*/
const clickAdd = async () => {
const filterRowNull = rows.value.filter(
(f: RequestItemsHistoryObject) =>
f.id === "00000000-0000-0000-0000-000000000000" && f.name == "" // array
);
if (filterRowNull.length == 0) {
//
rows.value.push({
createdAt: new Date(),
createdFullName: "",
createdUserId: "",
id: "00000000-0000-0000-0000-000000000000",
isActive: true,
lastUpdateFullName:
keycloak.tokenParsed == null ? "" : keycloak.tokenParsed.name,
lastUpdateUserId: "",
lastUpdatedAt: new Date(),
name: "",
});
updateData.value = true;
}
};
/**
*
* งกนบนทกแบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
* @param publish เมอบนทกแบบรางแลวจะเผยแพรเลยไหม true=นทกและเผยแพร false=นทกอยางเดยว
*/
const save = async (publish: boolean) => {
await validateData();
if (checkValidate.value == false) return;
rows.value.map((e: ResponseHistoryObject) => ({
// data backend
id: e.id,
createdAt: e.createdAt,
lastUpdatedAt: e.lastUpdatedAt,
name: e.name,
isActive: e.isActive,
createdFullName: e.createdFullName,
createdUserId: e.createdUserId,
lastUpdateFullName: e.lastUpdateFullName,
lastUpdateUserId: e.lastUpdateUserId,
}));
loaderPage(true);
await http
.post(config.API.listOrganizationAgencyHistoryId(idVersion.value), {
id: idVersion.value,
version: "draft",
items: rows.value,
})
.then(async (res) => {
if (publish === false) {
success($q, "บันทึกข้อมูลร่างสำเร็จ");
await fetchData(); // get data
} else {
await publishedData(); //
}
edit.value = false;
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
loaderPage(false);
});
};
/**
* เชคชอซำกบขอมลทอยแล
* @param val input
*/
const checkDupDataName = (val: string) => {
const filterNameNull = rows.value.filter(
(f: RequestItemsHistoryObject) => f.name == val
); //
if (filterNameNull.length > 1) {
return false;
}
return true;
};
/**
* งกนปมแกไข ให get data มาใหม
*/
const clickEdit = async () => {
await fetchData();
};
/**
* งกนปมบนทกแบบราง
*/
const clickSave = async () => {
await save(false);
};
/**
* งกนปมลบแบบราง
*/
const clickDelete = async () => {
await clearPublishedData();
};
/**
* งกนปมยกเลกการแกไขขอม
*/
const clickCancel = async () => {
edit.value = false;
await fetchData();
};
/**
* งกนปมเผยแพรอม
* เชคขอมลกอนวาใน array กรอกขอมลครบไหมถาครบกใหเผยแพรได
* าคาใน array ไมอมลใน row จะใหนทกได
*/
const clickPublish = async () => {
if (myForm.value !== null) {
myForm.value.validate().then(async (result: boolean) => {
if (result) {
await save(true);
}
});
} else {
await save(true);
}
};
/**
* งกนปมลบ row data
* @param val data ใน row จะลบ
*/
const clickDeleteRow = (val: RequestItemsHistoryObject) => {
rows.value = rows.value.filter((x: RequestItemsHistoryObject) => x !== val);
updateData.value = true;
};
/**
* งกนเช input ามการแกไขหรอย
*/
const clickEditRow = () => {
myForm.value.validate(false);
updateData.value = true;
};
/**
* งชนดอมลประวแกไขขอมลทเลอก
* @param row อม row ประวการแกไข
*/
const clickHistory = async (row: RequestItemsHistoryObject) => {
modalHistory.value = true;
rowsHistory.value = rawHistory.value.filter(
(f: RequestItemsHistoryObject) => f.id == row.id
);
};
/**
* งกนแปลง date เปนภาษาไทย
* @param value นท type datetime จะแปลงเปนไทย
*/
const textDate = (value: Date) => {
return dateText(value);
};
/**
* validate component
*/
const validateData = async () => {
checkValidate.value = true;
await myForm.value.validate().then((result: boolean) => {
if (result == false) {
checkValidate.value = false;
}
});
};
</script>
<style>
/* สีของnoti */
.my-notif-class {
background: rgba(33, 186, 69, 0.5) !important;
color: #008f17 !important;
}
</style>

View file

@ -0,0 +1,659 @@
<!-- tab หมายเลขโทรสาร หนาจดการขอมลหล/อมลโครงสรางหนวยงาน -->
<template>
<div>
<q-form ref="myForm">
<data-table
:rows="rows"
:columns="columns"
:filter="filter"
:visible-columns="visibleColumns"
v-model:inputfilter="filter"
v-model:inputvisible="visibleColumns"
v-model:editvisible="edit"
:add="clickAdd"
:edit="clickEdit"
:save="clickSave"
:deleted="clickDelete"
:cancel="clickCancel"
:publish="clickPublish"
:validate="validateData"
:publicData="version === 'published'"
:updateData="updateData"
:history="true"
>
<template #columns="props">
<q-tr :props="props" v-if="edit == false">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.name == 'isActive'" class="">
<q-icon
v-if="col.value == false"
name="mdi-close"
color="red"
class="text-h5"
/>
<q-icon
v-else
name="mdi-check"
color="positive"
class="text-h5"
/>
</div>
<div v-else-if="col.name == 'createdAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else-if="col.name == 'lastUpdatedAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else class="">
{{ col.value }}
</div>
</q-td>
<q-td auto-width>
<q-btn
color="info"
flat
dense
round
size="14px"
icon="mdi-history"
@click="clickHistory(props.row)"
/>
</q-td>
</q-tr>
<q-tr :props="props" v-if="edit == true">
<q-td key="name" :props="props" v-if="props.row.name !== undefined">
<q-input
class=""
outlined
@update:model-value="clickEditRow"
v-model="props.row.name"
dense
lazy-rules
autofocus
hide-bottom-space
:rules="[
(val) => (val && val.length > 0) || 'กรุณากรอกข้อมูลให้ครบ',
(val) =>
checkDupDataName(val) || 'ชื่อซ้ำกันกับข้อมูลที่มีอยู่แล้ว',
]"
></q-input>
</q-td>
<q-td
key="createdAt"
:props="props"
v-if="props.row.createdAt !== undefined"
>
<div class="">
{{ textDate(props.row.createdAt) }}
</div>
</q-td>
<q-td key="lastUpdatedAt" :props="props">
<div class="">
{{ textDate(props.row.lastUpdatedAt) }}
</div>
</q-td>
<q-td
key="lastUpdateFullName"
:props="props"
v-if="props.row.lastUpdateFullName !== undefined"
class=""
>
{{ props.row.lastUpdateFullName }}
</q-td>
<q-td
key="isActive"
:props="props"
v-if="props.row.isActive !== undefined"
>
<q-toggle
v-model="props.row.isActive"
dense
color="green"
@update:model-value="clickEditRow"
/>
</q-td>
<q-td auto-width>
<q-btn
v-if="props.row.id === '00000000-0000-0000-0000-000000000000'"
color="red"
flat
dense
round
size="14px"
icon="mdi-trash-can-outline"
@click="clickDeleteRow(props.row)"
/>
<q-btn
v-if="props.row.id !== '00000000-0000-0000-0000-000000000000'"
color="info"
flat
dense
round
size="14px"
icon="mdi-history"
@click="clickHistory(props.row)"
/>
</q-td>
</q-tr>
</template>
</data-table>
</q-form>
</div>
<HistoryTable
:rows="rowsHistory"
:columns="columnsHistory"
:filter="filterHistory"
:visible-columns="visibleColumnsHistory"
v-model:modal="modalHistory"
v-model:inputfilter="filterHistory"
v-model:inputvisible="visibleColumnsHistory"
v-model:tittle="tittleHistory"
>
<template #columns="props">
<q-tr :props="props">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.name == 'isActive'" class="">
<q-icon
v-if="col.value == false"
name="mdi-close"
color="red"
class="text-h5"
/>
<q-icon v-else name="mdi-check" color="positive" class="text-h5" />
</div>
<div v-else-if="col.name == 'lastUpdatedAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else class="">
{{ col.value }}
</div>
</q-td>
</q-tr>
</template>
</HistoryTable>
</template>
<script setup lang="ts">
import type { QTableProps } from "quasar";
import { useQuasar } from "quasar";
import { onMounted, ref, watch } from "vue";
import http from "@/plugins/http";
import config from "@/app.config";
import keycloak from "@/plugins/keycloak";
import { useCounterMixin } from "@/stores/mixin";
import { useManageDataStore } from "@/modules/01_metadata/store";
import type {
RequestItemsHistoryObject,
RequestItemsPublishHistoryObject,
Columns,
} from "@/modules/01_metadata/interface/request/organization/Fax";
import type { ResponseHistoryObject } from "@/modules/01_metadata/interface/response/organization/Fax";
import HistoryTable from "@/components/TableHistory.vue";
import { useDataStore } from "@/stores/data";
const props = defineProps({
fetchDataComponent: {
type: Function,
default: () => console.log("not function"),
},
});
const dataStore = useDataStore();
const { loaderPage } = dataStore;
const mixin = useCounterMixin();
const { success, dateText, messageError } = mixin;
const store = useManageDataStore();
const { manageData, changeManageColumns } = store;
const rows = ref<RequestItemsHistoryObject[]>([]); //list data table
const rowsHistory = ref<RequestItemsHistoryObject[]>([]); //select data history
const rawHistory = ref<RequestItemsHistoryObject[]>([]); //raw data history
const tittleHistory = ref<string>("ประวัติแก้ไขหมายเลขโทรสาร"); //
const myForm = ref<any>(null); //ref
const filter = ref<string>(""); //search data table
const filterHistory = ref<string>(""); //search data table history
const modalHistory = ref<boolean>(false); //modal
const edit = ref<boolean>(false); //
const idVersion = ref<string>(""); //id data mongodb
const version = ref<string>("published"); // published= draft=
const updateData = ref<boolean>(false); //
const checkValidate = ref<boolean>(false);
const columns = ref<QTableProps["columns"]>([
{
name: "name",
align: "left",
label: "หมายเลขโทรสาร",
sortable: true,
field: "name",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "createdAt",
align: "center",
label: "วันที่สร้าง",
sortable: true,
field: "createdAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdatedAt",
align: "center",
label: "วันที่แก้ไข",
sortable: true,
field: "lastUpdatedAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdateFullName",
align: "left",
label: "ผู้ดำเนินการ",
sortable: true,
field: "lastUpdateFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "isActive",
align: "left",
label: "สถานะ",
sortable: true,
field: "isActive",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumns = ref<String[]>([]);
manageData.organization.fax.columns.length == 0
? (visibleColumns.value = [
"name",
"createdAt",
"lastUpdatedAt",
"lastUpdateFullName",
"isActive",
])
: (visibleColumns.value = manageData.organization.fax.columns);
const columnsHistory = ref<QTableProps["columns"]>([
{
name: "name",
align: "left",
label: "หมายเลขโทรสาร",
sortable: true,
field: "name",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdatedAt",
align: "center",
label: "วันที่แก้ไข",
sortable: true,
field: "lastUpdatedAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdateFullName",
align: "left",
label: "ผู้ดำเนินการ",
sortable: true,
field: "lastUpdateFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "isActive",
align: "left",
label: "สถานะ",
sortable: true,
field: "isActive",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumnsHistory = ref<String[]>([
"name",
"lastUpdatedAt",
"lastUpdateFullName",
"isActive",
]);
/**
* เมอเขาหนานจะเรยกฟงชนนอน(get list data)
*/
onMounted(async () => {
await fetchData();
await fetchHistory();
});
watch(visibleColumns, async (count: String[], prevCount: String[]) => {
await changeManageColumns(2, "fax", count);
});
/**
* แจงเตอนขอมลในกรณ success
*/
const $q = useQuasar();
/**
* งก get data าส
*/
const fetchData = async () => {
await props.fetchDataComponent();
rows.value.splice(0);
loaderPage(true);
await http
.get(config.API.listOrganizationFaxHistory)
.then((res) => {
let data = res.data.result;
version.value = data.version; // published= draft=
idVersion.value = data.id; // id mongodb
data.items.map((e: RequestItemsHistoryObject) => {
rows.value.push({
id: e.id,
name: e.name,
createdAt: e.createdAt,
lastUpdatedAt: e.lastUpdatedAt,
lastUpdateFullName: e.lastUpdateFullName,
isActive: e.isActive,
createdFullName: e.createdFullName,
createdUserId: e.createdUserId,
lastUpdateUserId: e.lastUpdateUserId,
});
});
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
updateData.value = false;
loaderPage(false);
});
};
/**
* งชนดอมลประวแกไขขอมลทงหมด
*/
const fetchHistory = async () => {
loaderPage(true);
await http
.get(config.API.listOrganizationFaxPublishedHistory)
.then((res) => {
const data = res.data.result;
rawHistory.value = [];
if (data.length > 0) {
data.map((e: RequestItemsPublishHistoryObject) => {
e.items.map((i: RequestItemsHistoryObject) => {
rawHistory.value.push({
createdAt: i.createdAt,
createdFullName: i.createdFullName,
createdUserId: i.createdUserId,
id: i.id,
isActive: i.isActive,
lastUpdateFullName: i.lastUpdateFullName,
lastUpdateUserId: i.lastUpdateUserId,
lastUpdatedAt: i.lastUpdatedAt,
name: i.name,
});
});
});
}
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
loaderPage(false);
});
};
/**
* งก clear data แบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
*/
const clearPublishedData = async () => {
loaderPage(true);
await http
.delete(config.API.listOrganizationFaxHistory)
.then((res) => {
success($q, "ลบข้อมูลร่างสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchHistory();
await fetchData();
});
};
/**
* งกนเผยแพรแบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
*/
const publishedData = async () => {
loaderPage(true);
await http
.get(config.API.listOrganizationFaxPublished)
.then((res) => {
success($q, "เผยแพร่ข้อมูลสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchData();
});
};
/**
* งกนเพมขอม
*/
const clickAdd = async () => {
const filterRowNull = rows.value.filter(
(f: RequestItemsHistoryObject) =>
f.id === "00000000-0000-0000-0000-000000000000" && f.name == "" // array
);
if (filterRowNull.length == 0) {
//
rows.value.push({
createdAt: new Date(),
createdFullName: "",
createdUserId: "",
id: "00000000-0000-0000-0000-000000000000",
isActive: true,
lastUpdateFullName:
keycloak.tokenParsed == null ? "" : keycloak.tokenParsed.name,
lastUpdateUserId: "",
lastUpdatedAt: new Date(),
name: "",
});
updateData.value = true;
}
};
/**
* งกนบนทกแบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
* publish เมอบนทกแบบรางแลวจะเผยแพรเลยไหม true=นทกและเผยแพร false=นทกอยางเดยว
*/
const save = async (publish: boolean) => {
await validateData();
if (checkValidate.value == false) return;
rows.value.map((e: ResponseHistoryObject) => ({
// data backend
id: e.id,
createdAt: e.createdAt,
lastUpdatedAt: e.lastUpdatedAt,
name: e.name,
isActive: e.isActive,
createdFullName: e.createdFullName,
createdUserId: e.createdUserId,
lastUpdateFullName: e.lastUpdateFullName,
lastUpdateUserId: e.lastUpdateUserId,
}));
loaderPage(true);
await http
.post(config.API.listOrganizationFaxHistoryId(idVersion.value), {
id: idVersion.value,
version: "draft",
items: rows.value,
})
.then(async (res) => {
if (publish === false) {
success($q, "บันทึกข้อมูลร่างสำเร็จ");
await fetchData(); // get data
} else {
await publishedData(); //
}
edit.value = false;
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
loaderPage(false);
});
};
/**
* เชคชอซำกบขอมลทอยแล
* @param val input
*/
const checkDupDataName = (val: string) => {
const filterNameNull = rows.value.filter(
(f: RequestItemsHistoryObject) => f.name == val
); //
if (filterNameNull.length > 1) {
return false;
}
return true;
};
/**
* งกนปมแกไข ให get data มาใหม
*/
const clickEdit = async () => {
await fetchData();
};
/**
* งกนปมบนทกแบบราง
*/
const clickSave = async () => {
await save(false);
};
/**
* งกนปมลบแบบราง
*/
const clickDelete = async () => {
await clearPublishedData();
};
/**
* งกนปมยกเลกการแกไขขอม
*/
const clickCancel = async () => {
edit.value = false;
await fetchData();
};
/**
* งกนปมเผยแพรอม
* เชคขอมลกอนวาใน array กรอกขอมลครบไหมถาครบกใหเผยแพรได
* าคาใน array ไมอมลใน row จะใหนทกได
*/
const clickPublish = async () => {
if (myForm.value !== null) {
myForm.value.validate().then(async (result: boolean) => {
if (result) {
await save(true);
}
});
} else {
await save(true);
}
};
/**
* งกนปมลบ row data
* @param val data ใน row จะลบ
*/
const clickDeleteRow = (val: RequestItemsHistoryObject) => {
rows.value = rows.value.filter((x: RequestItemsHistoryObject) => x !== val);
updateData.value = true;
};
/**
* งกนเช input ามการแกไขหรอย
*/
const clickEditRow = () => {
myForm.value.validate(false);
updateData.value = true;
};
/**
* งชนดอมลประวแกไขขอมลทเลอก
* @param row อม row ประวการแกไข
*/
const clickHistory = async (row: RequestItemsHistoryObject) => {
modalHistory.value = true;
rowsHistory.value = rawHistory.value.filter(
(f: RequestItemsHistoryObject) => f.id == row.id
);
};
/**
* งกนแปลง date เปนภาษาไทย
* @param value นท type datetime จะแปลงเปนไทย
*/
const textDate = (value: Date) => {
return dateText(value);
};
/**
* validate component
*/
const validateData = async () => {
checkValidate.value = true;
await myForm.value.validate().then((result: boolean) => {
if (result == false) {
checkValidate.value = false;
}
});
};
</script>
<style>
/* สีของnoti */
.my-notif-class {
background: rgba(33, 186, 69, 0.5) !important;
color: #008f17 !important;
}
</style>

View file

@ -0,0 +1,661 @@
<!-- tab วนราชการตนสงก หนาจดการขอมลหล/อมลโครงสรางหนวยงาน -->
<template>
<div>
<q-form ref="myForm">
<data-table
:rows="rows"
:columns="columns"
:filter="filter"
:visible-columns="visibleColumns"
v-model:inputfilter="filter"
v-model:inputvisible="visibleColumns"
v-model:editvisible="edit"
:add="clickAdd"
:edit="clickEdit"
:save="clickSave"
:deleted="clickDelete"
:cancel="clickCancel"
:publish="clickPublish"
:validate="validateData"
:publicData="version === 'published'"
:updateData="updateData"
:history="true"
>
<template #columns="props">
<q-tr :props="props" v-if="edit == false">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.name == 'isActive'" class="">
<q-icon
v-if="col.value == false"
name="mdi-close"
color="red"
class="text-h5"
/>
<q-icon
v-else
name="mdi-check"
color="positive"
class="text-h5"
/>
</div>
<div v-else-if="col.name == 'createdAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else-if="col.name == 'lastUpdatedAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else class="">
{{ col.value }}
</div>
</q-td>
<q-td auto-width>
<q-btn
color="info"
flat
dense
round
size="14px"
icon="mdi-history"
@click="clickHistory(props.row)"
/>
</q-td>
</q-tr>
<q-tr :props="props" v-if="edit == true">
<q-td key="name" :props="props" v-if="props.row.name !== undefined">
<q-input
class=""
outlined
@update:model-value="clickEditRow"
v-model="props.row.name"
dense
lazy-rules
autofocus
hide-bottom-space
:rules="[
(val) => (val && val.length > 0) || 'กรุณากรอกข้อมูลให้ครบ',
(val) =>
checkDupDataName(val) || 'ชื่อซ้ำกันกับข้อมูลที่มีอยู่แล้ว',
]"
></q-input>
</q-td>
<q-td
key="createdAt"
:props="props"
v-if="props.row.createdAt !== undefined"
>
<div class="">
{{ textDate(props.row.createdAt) }}
</div>
</q-td>
<q-td key="lastUpdatedAt" :props="props">
<div class="">
{{ textDate(props.row.lastUpdatedAt) }}
</div>
</q-td>
<q-td
key="lastUpdateFullName"
:props="props"
v-if="props.row.lastUpdateFullName !== undefined"
class=""
>
{{ props.row.lastUpdateFullName }}
</q-td>
<q-td
key="isActive"
:props="props"
v-if="props.row.isActive !== undefined"
>
<q-toggle
v-model="props.row.isActive"
dense
color="green"
@update:model-value="clickEditRow"
/>
</q-td>
<q-td auto-width>
<q-btn
v-if="props.row.id === '00000000-0000-0000-0000-000000000000'"
color="red"
flat
dense
round
size="14px"
icon="mdi-trash-can-outline"
@click="clickDeleteRow(props.row)"
/>
<q-btn
v-if="props.row.id !== '00000000-0000-0000-0000-000000000000'"
color="info"
flat
dense
round
size="14px"
icon="mdi-history"
@click="clickHistory(props.row)"
/>
</q-td>
</q-tr>
</template>
</data-table>
</q-form>
</div>
<HistoryTable
:rows="rowsHistory"
:columns="columnsHistory"
:filter="filterHistory"
:visible-columns="visibleColumnsHistory"
v-model:modal="modalHistory"
v-model:inputfilter="filterHistory"
v-model:inputvisible="visibleColumnsHistory"
v-model:tittle="tittleHistory"
>
<template #columns="props">
<q-tr :props="props">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.name == 'isActive'" class="">
<q-icon
v-if="col.value == false"
name="mdi-close"
color="red"
class="text-h5"
/>
<q-icon v-else name="mdi-check" color="positive" class="text-h5" />
</div>
<div v-else-if="col.name == 'lastUpdatedAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else class="">
{{ col.value }}
</div>
</q-td>
</q-tr>
</template>
</HistoryTable>
</template>
<script setup lang="ts">
import type { QTableProps } from "quasar";
import { useQuasar } from "quasar";
import { onMounted, ref, watch } from "vue";
import http from "@/plugins/http";
import config from "@/app.config";
import keycloak from "@/plugins/keycloak";
import { useCounterMixin } from "@/stores/mixin";
import { useManageDataStore } from "@/modules/01_metadata/store";
import type {
RequestItemsHistoryObject,
RequestItemsPublishHistoryObject,
Columns,
} from "@/modules/01_metadata/interface/request/organization/GovernmentAgency";
import type { ResponseHistoryObject } from "@/modules/01_metadata/interface/response/organization/GovernmentAgency";
import HistoryTable from "@/components/TableHistory.vue";
import { useDataStore } from "@/stores/data";
const props = defineProps({
fetchDataComponent: {
type: Function,
default: () => console.log("not function"),
},
});
const dataStore = useDataStore();
const { loaderPage } = dataStore;
const mixin = useCounterMixin();
const { success, dateText, messageError } = mixin;
const store = useManageDataStore();
const { manageData, changeManageColumns } = store;
const rows = ref<RequestItemsHistoryObject[]>([]); //list data table
const rowsHistory = ref<RequestItemsHistoryObject[]>([]); //select data history
const rawHistory = ref<RequestItemsHistoryObject[]>([]); //raw data history
const tittleHistory = ref<string>("ประวัติแก้ไขส่วนราชการต้นสังกัด"); //
const myForm = ref<any>(null); //ref
const filter = ref<string>(""); //search data table
const filterHistory = ref<string>(""); //search data table history
const modalHistory = ref<boolean>(false); //modal
const edit = ref<boolean>(false); //
const idVersion = ref<string>(""); //id data mongodb
const version = ref<string>("published"); // published= draft=
const updateData = ref<boolean>(false); //
const checkValidate = ref<boolean>(false);
const columns = ref<QTableProps["columns"]>([
{
name: "name",
align: "left",
label: "ส่วนราชการต้นสังกัด",
sortable: true,
field: "name",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "createdAt",
align: "center",
label: "วันที่สร้าง",
sortable: true,
field: "createdAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdatedAt",
align: "center",
label: "วันที่แก้ไข",
sortable: true,
field: "lastUpdatedAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdateFullName",
align: "left",
label: "ผู้ดำเนินการ",
sortable: true,
field: "lastUpdateFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "isActive",
align: "left",
label: "สถานะ",
sortable: true,
field: "isActive",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumns = ref<String[]>([]);
manageData.organization.governmentAgency.columns.length == 0
? (visibleColumns.value = [
"name",
"createdAt",
"lastUpdatedAt",
"lastUpdateFullName",
"isActive",
])
: (visibleColumns.value = manageData.organization.governmentAgency.columns);
const columnsHistory = ref<QTableProps["columns"]>([
{
name: "name",
align: "left",
label: "ส่วนราชการต้นสังกัด",
sortable: true,
field: "name",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdatedAt",
align: "center",
label: "วันที่แก้ไข",
sortable: true,
field: "lastUpdatedAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdateFullName",
align: "left",
label: "ผู้ดำเนินการ",
sortable: true,
field: "lastUpdateFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "isActive",
align: "left",
label: "สถานะ",
sortable: true,
field: "isActive",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumnsHistory = ref<String[]>([
"name",
"lastUpdatedAt",
"lastUpdateFullName",
"isActive",
]);
/**
* เมอเขาหนานจะเรยกฟงชนนอน(get list data)
*/
onMounted(async () => {
await fetchData();
await fetchHistory();
});
watch(visibleColumns, async (count: String[], prevCount: String[]) => {
await changeManageColumns(2, "governmentAgency", count);
});
/**
* แจงเตอนขอมลในกรณ success
*/
const $q = useQuasar();
/**
* งก get data าส
*/
const fetchData = async () => {
await props.fetchDataComponent();
rows.value.splice(0);
loaderPage(true);
await http
.get(config.API.listOrganizationGovernmentAgencyHistory)
.then((res) => {
let data = res.data.result;
version.value = data.version; // published= draft=
idVersion.value = data.id; // id mongodb
data.items.map((e: RequestItemsHistoryObject) => {
rows.value.push({
id: e.id,
name: e.name,
createdAt: e.createdAt,
lastUpdatedAt: e.lastUpdatedAt,
lastUpdateFullName: e.lastUpdateFullName,
isActive: e.isActive,
createdFullName: e.createdFullName,
createdUserId: e.createdUserId,
lastUpdateUserId: e.lastUpdateUserId,
});
});
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
updateData.value = false;
loaderPage(false);
});
};
/**
* งชนดอมลประวแกไขขอมลทงหมด
*/
const fetchHistory = async () => {
loaderPage(true);
await http
.get(config.API.listOrganizationGovernmentAgencyPublishedHistory)
.then((res) => {
const data = res.data.result;
rawHistory.value = [];
if (data.length > 0) {
data.map((e: RequestItemsPublishHistoryObject) => {
e.items.map((i: RequestItemsHistoryObject) => {
rawHistory.value.push({
createdAt: i.createdAt,
createdFullName: i.createdFullName,
createdUserId: i.createdUserId,
id: i.id,
isActive: i.isActive,
lastUpdateFullName: i.lastUpdateFullName,
lastUpdateUserId: i.lastUpdateUserId,
lastUpdatedAt: i.lastUpdatedAt,
name: i.name,
});
});
});
}
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
loaderPage(false);
});
};
/**
* งก clear data แบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
*/
const clearPublishedData = async () => {
loaderPage(true);
await http
.delete(config.API.listOrganizationGovernmentAgencyHistory)
.then((res) => {
success($q, "ลบข้อมูลร่างสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchData();
});
};
/**
* งกนเผยแพรแบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
*/
const publishedData = async () => {
loaderPage(true);
await http
.get(config.API.listOrganizationGovernmentAgencyPublished)
.then((res) => {
success($q, "เผยแพร่ข้อมูลสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchData();
});
};
/**
* งกนเพมขอม
*/
const clickAdd = async () => {
const filterRowNull = rows.value.filter(
(f: RequestItemsHistoryObject) =>
f.id === "00000000-0000-0000-0000-000000000000" && f.name == "" // array
);
if (filterRowNull.length == 0) {
//
rows.value.push({
createdAt: new Date(),
createdFullName: "",
createdUserId: "",
id: "00000000-0000-0000-0000-000000000000",
isActive: true,
lastUpdateFullName:
keycloak.tokenParsed == null ? "" : keycloak.tokenParsed.name,
lastUpdateUserId: "",
lastUpdatedAt: new Date(),
name: "",
});
updateData.value = true;
}
};
/**
* งกนบนทกแบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
* publish เมอบนทกแบบรางแลวจะเผยแพรเลยไหม true=นทกและเผยแพร false=นทกอยางเดยว
*/
const save = async (publish: boolean) => {
await validateData();
if (checkValidate.value == false) return;
rows.value.map((e: ResponseHistoryObject) => ({
// data backend
id: e.id,
createdAt: e.createdAt,
lastUpdatedAt: e.lastUpdatedAt,
name: e.name,
isActive: e.isActive,
createdFullName: e.createdFullName,
createdUserId: e.createdUserId,
lastUpdateFullName: e.lastUpdateFullName,
lastUpdateUserId: e.lastUpdateUserId,
}));
loaderPage(true);
await http
.post(
config.API.listOrganizationGovernmentAgencyHistoryId(idVersion.value),
{
id: idVersion.value,
version: "draft",
items: rows.value,
}
)
.then(async (res) => {
if (publish === false) {
success($q, "บันทึกข้อมูลร่างสำเร็จ");
await fetchData(); // get data
} else {
await publishedData(); //
}
edit.value = false;
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
loaderPage(false);
});
};
/**
* เชคชอซำกบขอมลทอยแล
* @param val input
*/
const checkDupDataName = (val: string) => {
const filterNameNull = rows.value.filter(
(f: RequestItemsHistoryObject) => f.name == val
); //
if (filterNameNull.length > 1) {
return false;
}
return true;
};
/**
* งกนปมแกไข ให get data มาใหม
*/
const clickEdit = async () => {
await fetchData();
};
/**
* งกนปมบนทกแบบราง
*/
const clickSave = async () => {
await save(false);
};
/**
* งกนปมลบแบบราง
*/
const clickDelete = async () => {
await clearPublishedData();
};
/**
* งกนปมยกเลกการแกไขขอม
*/
const clickCancel = async () => {
edit.value = false;
await fetchData();
};
/**
* งกนปมเผยแพรอม
* เชคขอมลกอนวาใน array กรอกขอมลครบไหมถาครบกใหเผยแพรได
* าคาใน array ไมอมลใน row จะใหนทกได
*/
const clickPublish = async () => {
if (myForm.value !== null) {
myForm.value.validate().then(async (result: boolean) => {
if (result) {
await save(true);
}
});
} else {
await save(true);
}
};
/**
* งกนปมลบ row data
* @param val data ใน row จะลบ
*/
const clickDeleteRow = (val: RequestItemsHistoryObject) => {
rows.value = rows.value.filter((x: RequestItemsHistoryObject) => x !== val);
updateData.value = true;
};
/**
* งกนเช input ามการแกไขหรอย
*/
const clickEditRow = () => {
myForm.value.validate(false);
updateData.value = true;
};
/**
* งชนดอมลประวแกไขขอมลทเลอก
* @param row อม row ประวการแกไข
*/
const clickHistory = async (row: RequestItemsHistoryObject) => {
modalHistory.value = true;
rowsHistory.value = rawHistory.value.filter(
(f: RequestItemsHistoryObject) => f.id == row.id
);
};
/**
* งกนแปลง date เปนภาษาไทย
* @param value นท type datetime จะแปลงเปนไทย
*/
const textDate = (value: Date) => {
return dateText(value);
};
/**
* validate component
*/
const validateData = async () => {
checkValidate.value = true;
await myForm.value.validate().then((result: boolean) => {
if (result == false) {
checkValidate.value = false;
}
});
};
</script>
<style>
/* สีของnoti */
.my-notif-class {
background: rgba(33, 186, 69, 0.5) !important;
color: #008f17 !important;
}
</style>

View file

@ -0,0 +1,659 @@
<!-- tab ระดบของหนวยงาน/วนราชการ หนาจดการขอมลหล/อมลโครงสรางหนวยงาน -->
<template>
<div>
<q-form ref="myForm">
<data-table
:rows="rows"
:columns="columns"
:filter="filter"
:visible-columns="visibleColumns"
v-model:inputfilter="filter"
v-model:inputvisible="visibleColumns"
v-model:editvisible="edit"
:add="clickAdd"
:edit="clickEdit"
:save="clickSave"
:deleted="clickDelete"
:cancel="clickCancel"
:publish="clickPublish"
:validate="validateData"
:publicData="version === 'published'"
:updateData="updateData"
:history="true"
>
<template #columns="props">
<q-tr :props="props" v-if="edit == false">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.name == 'isActive'" class="">
<q-icon
v-if="col.value == false"
name="mdi-close"
color="red"
class="text-h5"
/>
<q-icon
v-else
name="mdi-check"
color="positive"
class="text-h5"
/>
</div>
<div v-else-if="col.name == 'createdAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else-if="col.name == 'lastUpdatedAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else class="">
{{ col.value }}
</div>
</q-td>
<q-td auto-width>
<q-btn
color="info"
flat
dense
round
size="14px"
icon="mdi-history"
@click="clickHistory(props.row)"
/>
</q-td>
</q-tr>
<q-tr :props="props" v-if="edit == true">
<q-td key="name" :props="props" v-if="props.row.name !== undefined">
<q-input
class=""
outlined
@update:model-value="clickEditRow"
v-model="props.row.name"
dense
lazy-rules
autofocus
hide-bottom-space
:rules="[
(val) => (val && val.length > 0) || 'กรุณากรอกข้อมูลให้ครบ',
(val) =>
checkDupDataName(val) || 'ชื่อซ้ำกันกับข้อมูลที่มีอยู่แล้ว',
]"
></q-input>
</q-td>
<q-td
key="createdAt"
:props="props"
v-if="props.row.createdAt !== undefined"
>
<div class="">
{{ textDate(props.row.createdAt) }}
</div>
</q-td>
<q-td key="lastUpdatedAt" :props="props">
<div class="">
{{ textDate(props.row.lastUpdatedAt) }}
</div>
</q-td>
<q-td
key="lastUpdateFullName"
:props="props"
v-if="props.row.lastUpdateFullName !== undefined"
class=""
>
{{ props.row.lastUpdateFullName }}
</q-td>
<q-td
key="isActive"
:props="props"
v-if="props.row.isActive !== undefined"
>
<q-toggle
v-model="props.row.isActive"
dense
color="green"
@update:model-value="clickEditRow"
/>
</q-td>
<q-td auto-width>
<q-btn
v-if="props.row.id === '00000000-0000-0000-0000-000000000000'"
color="red"
flat
dense
round
size="14px"
icon="mdi-trash-can-outline"
@click="clickDeleteRow(props.row)"
/>
<q-btn
v-if="props.row.id !== '00000000-0000-0000-0000-000000000000'"
color="info"
flat
dense
round
size="14px"
icon="mdi-history"
@click="clickHistory(props.row)"
/>
</q-td>
</q-tr>
</template>
</data-table>
</q-form>
</div>
<HistoryTable
:rows="rowsHistory"
:columns="columnsHistory"
:filter="filterHistory"
:visible-columns="visibleColumnsHistory"
v-model:modal="modalHistory"
v-model:inputfilter="filterHistory"
v-model:inputvisible="visibleColumnsHistory"
v-model:tittle="tittleHistory"
>
<template #columns="props">
<q-tr :props="props">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.name == 'isActive'" class="">
<q-icon
v-if="col.value == false"
name="mdi-close"
color="red"
class="text-h5"
/>
<q-icon v-else name="mdi-check" color="positive" class="text-h5" />
</div>
<div v-else-if="col.name == 'lastUpdatedAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else class="">
{{ col.value }}
</div>
</q-td>
</q-tr>
</template>
</HistoryTable>
</template>
<script setup lang="ts">
import type { QTableProps } from "quasar";
import { useQuasar } from "quasar";
import { onMounted, ref, watch } from "vue";
import http from "@/plugins/http";
import config from "@/app.config";
import keycloak from "@/plugins/keycloak";
import { useCounterMixin } from "@/stores/mixin";
import { useManageDataStore } from "@/modules/01_metadata/store";
import type {
RequestItemsHistoryObject,
RequestItemsPublishHistoryObject,
Columns,
} from "@/modules/01_metadata/interface/request/organization/Level";
import type { ResponseHistoryObject } from "@/modules/01_metadata/interface/response/organization/Level";
import HistoryTable from "@/components/TableHistory.vue";
import { useDataStore } from "@/stores/data";
const props = defineProps({
fetchDataComponent: {
type: Function,
default: () => console.log("not function"),
},
});
const dataStore = useDataStore();
const { loaderPage } = dataStore;
const mixin = useCounterMixin();
const { success, dateText, messageError } = mixin;
const store = useManageDataStore();
const { manageData, changeManageColumns } = store;
const rows = ref<RequestItemsHistoryObject[]>([]); //list data table
const rowsHistory = ref<RequestItemsHistoryObject[]>([]); //select data history
const rawHistory = ref<RequestItemsHistoryObject[]>([]); //raw data history
const tittleHistory = ref<string>("ประวัติแก้ไขระดับของหน่วยงาน/ส่วนราชการ"); //
const myForm = ref<any>(null); //ref
const filter = ref<string>(""); //search data table
const filterHistory = ref<string>(""); //search data table history
const modalHistory = ref<boolean>(false); //modal
const edit = ref<boolean>(false); //
const idVersion = ref<string>(""); //id data mongodb
const version = ref<string>("published"); // published= draft=
const updateData = ref<boolean>(false); //
const checkValidate = ref<boolean>(false);
const columns = ref<QTableProps["columns"]>([
{
name: "name",
align: "left",
label: "ระดับของหน่วยงาน/ส่วนราชการ",
sortable: true,
field: "name",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "createdAt",
align: "center",
label: "วันที่สร้าง",
sortable: true,
field: "createdAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdatedAt",
align: "center",
label: "วันที่แก้ไข",
sortable: true,
field: "lastUpdatedAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdateFullName",
align: "left",
label: "ผู้ดำเนินการ",
sortable: true,
field: "lastUpdateFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "isActive",
align: "left",
label: "สถานะ",
sortable: true,
field: "isActive",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumns = ref<String[]>([]);
manageData.organization.level.columns.length == 0
? (visibleColumns.value = [
"name",
"createdAt",
"lastUpdatedAt",
"lastUpdateFullName",
"isActive",
])
: (visibleColumns.value = manageData.organization.level.columns);
const columnsHistory = ref<QTableProps["columns"]>([
{
name: "name",
align: "left",
label: "ระดับของหน่วยงาน/ส่วนราชการ",
sortable: true,
field: "name",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdatedAt",
align: "center",
label: "วันที่แก้ไข",
sortable: true,
field: "lastUpdatedAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdateFullName",
align: "left",
label: "ผู้ดำเนินการ",
sortable: true,
field: "lastUpdateFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "isActive",
align: "left",
label: "สถานะ",
sortable: true,
field: "isActive",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumnsHistory = ref<String[]>([
"name",
"lastUpdatedAt",
"lastUpdateFullName",
"isActive",
]);
/**
* เมอเขาหนานจะเรยกฟงชนนอน(get list data)
*/
onMounted(async () => {
await fetchData();
await fetchHistory();
});
watch(visibleColumns, async (count: String[], prevCount: String[]) => {
await changeManageColumns(2, "level", count);
});
/**
* แจงเตอนขอมลในกรณ success
*/
const $q = useQuasar();
/**
* งก get data าส
*/
const fetchData = async () => {
await props.fetchDataComponent();
rows.value.splice(0);
loaderPage(true);
await http
.get(config.API.listOrganizationLevelHistory)
.then((res) => {
let data = res.data.result;
version.value = data.version; // published= draft=
idVersion.value = data.id; // id mongodb
data.items.map((e: RequestItemsHistoryObject) => {
rows.value.push({
id: e.id,
name: e.name,
createdAt: e.createdAt,
lastUpdatedAt: e.lastUpdatedAt,
lastUpdateFullName: e.lastUpdateFullName,
isActive: e.isActive,
createdFullName: e.createdFullName,
createdUserId: e.createdUserId,
lastUpdateUserId: e.lastUpdateUserId,
});
});
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
updateData.value = false;
loaderPage(false);
});
};
/**
* งชนดอมลประวแกไขขอมลทงหมด
*/
const fetchHistory = async () => {
loaderPage(true);
await http
.get(config.API.listOrganizationLevelPublishedHistory)
.then((res) => {
const data = res.data.result;
rawHistory.value = [];
if (data.length > 0) {
data.map((e: RequestItemsPublishHistoryObject) => {
e.items.map((i: RequestItemsHistoryObject) => {
rawHistory.value.push({
createdAt: i.createdAt,
createdFullName: i.createdFullName,
createdUserId: i.createdUserId,
id: i.id,
isActive: i.isActive,
lastUpdateFullName: i.lastUpdateFullName,
lastUpdateUserId: i.lastUpdateUserId,
lastUpdatedAt: i.lastUpdatedAt,
name: i.name,
});
});
});
}
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
loaderPage(false);
});
};
/**
* งก clear data แบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
*/
const clearPublishedData = async () => {
loaderPage(true);
await http
.delete(config.API.listOrganizationLevelHistory)
.then((res) => {
success($q, "ลบข้อมูลร่างสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchHistory();
await fetchData();
});
};
/**
* งกนเผยแพรแบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
*/
const publishedData = async () => {
loaderPage(true);
await http
.get(config.API.listOrganizationLevelPublished)
.then((res) => {
success($q, "เผยแพร่ข้อมูลสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchData();
});
};
/**
* งกนเพมขอม
*/
const clickAdd = async () => {
const filterRowNull = rows.value.filter(
(f: RequestItemsHistoryObject) =>
f.id === "00000000-0000-0000-0000-000000000000" && f.name == "" // array
);
if (filterRowNull.length == 0) {
//
rows.value.push({
createdAt: new Date(),
createdFullName: "",
createdUserId: "",
id: "00000000-0000-0000-0000-000000000000",
isActive: true,
lastUpdateFullName:
keycloak.tokenParsed == null ? "" : keycloak.tokenParsed.name,
lastUpdateUserId: "",
lastUpdatedAt: new Date(),
name: "",
});
updateData.value = true;
}
};
/**
* งกนบนทกแบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
* publish เมอบนทกแบบรางแลวจะเผยแพรเลยไหม true=นทกและเผยแพร false=นทกอยางเดยว
*/
const save = async (publish: boolean) => {
await validateData();
if (checkValidate.value == false) return;
rows.value.map((e: ResponseHistoryObject) => ({
// data backend
id: e.id,
createdAt: e.createdAt,
lastUpdatedAt: e.lastUpdatedAt,
name: e.name,
isActive: e.isActive,
createdFullName: e.createdFullName,
createdUserId: e.createdUserId,
lastUpdateFullName: e.lastUpdateFullName,
lastUpdateUserId: e.lastUpdateUserId,
}));
loaderPage(true);
await http
.post(config.API.listOrganizationLevelHistoryId(idVersion.value), {
id: idVersion.value,
version: "draft",
items: rows.value,
})
.then(async (res) => {
if (publish === false) {
success($q, "บันทึกข้อมูลร่างสำเร็จ");
await fetchData(); // get data
} else {
await publishedData(); //
}
edit.value = false;
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
loaderPage(false);
});
};
/**
* เชคชอซำกบขอมลทอยแล
* @param val input
*/
const checkDupDataName = (val: string) => {
const filterNameNull = rows.value.filter(
(f: RequestItemsHistoryObject) => f.name == val
); //
if (filterNameNull.length > 1) {
return false;
}
return true;
};
/**
* งกนปมแกไข ให get data มาใหม
*/
const clickEdit = async () => {
await fetchData();
};
/**
* งกนปมบนทกแบบราง
*/
const clickSave = async () => {
await save(false);
};
/**
* งกนปมลบแบบราง
*/
const clickDelete = async () => {
await clearPublishedData();
};
/**
* งกนปมยกเลกการแกไขขอม
*/
const clickCancel = async () => {
edit.value = false;
await fetchData();
};
/**
* งกนปมเผยแพรอม
* เชคขอมลกอนวาใน array กรอกขอมลครบไหมถาครบกใหเผยแพรได
* าคาใน array ไมอมลใน row จะใหนทกได
*/
const clickPublish = async () => {
if (myForm.value !== null) {
myForm.value.validate().then(async (result: boolean) => {
if (result) {
await save(true);
}
});
} else {
await save(true);
}
};
/**
* งกนปมลบ row data
* @param val data ใน row จะลบ
*/
const clickDeleteRow = (val: RequestItemsHistoryObject) => {
rows.value = rows.value.filter((x: RequestItemsHistoryObject) => x !== val);
updateData.value = true;
};
/**
* งกนเช input ามการแกไขหรอย
*/
const clickEditRow = () => {
myForm.value.validate(false);
updateData.value = true;
};
/**
* งชนดอมลประวแกไขขอมลทเลอก
* @param row อม row ประวการแกไข
*/
const clickHistory = async (row: RequestItemsHistoryObject) => {
modalHistory.value = true;
rowsHistory.value = rawHistory.value.filter(
(f: RequestItemsHistoryObject) => f.id == row.id
);
};
/**
* งกนแปลง date เปนภาษาไทย
* @param value นท type datetime จะแปลงเปนไทย
*/
const textDate = (value: Date) => {
return dateText(value);
};
/**
* validate component
*/
const validateData = async () => {
checkValidate.value = true;
await myForm.value.validate().then((result: boolean) => {
if (result == false) {
checkValidate.value = false;
}
});
};
</script>
<style>
/* สีของnoti */
.my-notif-class {
background: rgba(33, 186, 69, 0.5) !important;
color: #008f17 !important;
}
</style>

View file

@ -0,0 +1,698 @@
<!-- tab อหนวยงาน หนาจดการขอมลหล/อมลโครงสรางหนวยงาน -->
<template>
<div>
<q-form ref="myForm">
<data-table
:rows="rows"
:columns="columns"
:filter="filter"
:visible-columns="visibleColumns"
v-model:inputfilter="filter"
v-model:inputvisible="visibleColumns"
v-model:editvisible="edit"
:add="clickAdd"
:edit="clickEdit"
:save="clickSave"
:deleted="clickDelete"
:cancel="clickCancel"
:publish="clickPublish"
:validate="validateData"
:publicData="version === 'published'"
:updateData="updateData"
:history="true"
>
<template #columns="props">
<q-tr :props="props" v-if="edit == false">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.name == 'isActive'" class="">
<q-icon
v-if="col.value == false"
name="mdi-close"
color="red"
class="text-h5"
/>
<q-icon
v-else
name="mdi-check"
color="positive"
class="text-h5"
/>
</div>
<div v-else-if="col.name == 'createdAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else-if="col.name == 'lastUpdatedAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else class="">
{{ col.value }}
</div>
</q-td>
<q-td auto-width>
<q-btn
color="info"
flat
dense
round
size="14px"
icon="mdi-history"
@click="clickHistory(props.row)"
/>
</q-td>
</q-tr>
<q-tr :props="props" v-if="edit == true">
<q-td key="name" :props="props" v-if="props.row.name !== undefined">
<q-input
class=""
outlined
@update:model-value="clickEditRow"
v-model="props.row.name"
dense
lazy-rules
autofocus
hide-bottom-space
:rules="[
(val) => (val && val.length > 0) || 'กรุณากรอกข้อมูลให้ครบ',
(val) =>
checkDupDataName(val) || 'ชื่อซ้ำกันกับข้อมูลที่มีอยู่แล้ว',
]"
></q-input>
</q-td>
<q-td
key="createdAt"
:props="props"
v-if="props.row.createdAt !== undefined"
>
<div class="">
{{ textDate(props.row.createdAt) }}
</div>
</q-td>
<q-td key="lastUpdatedAt" :props="props">
<div class="">
{{ textDate(props.row.lastUpdatedAt) }}
</div>
</q-td>
<q-td
key="lastUpdateFullName"
:props="props"
v-if="props.row.lastUpdateFullName !== undefined"
class=""
>
{{ props.row.lastUpdateFullName }}
</q-td>
<q-td
key="isActive"
:props="props"
v-if="props.row.isActive !== undefined"
>
<q-toggle
v-model="props.row.isActive"
dense
color="green"
@update:model-value="clickEditRow"
/>
</q-td>
<q-td key="note" :props="props" v-if="props.row.note !== undefined">
<q-input
class=""
outlined
@update:model-value="clickEditRow"
v-model="props.row.note"
dense
lazy-rules
autofocus
hide-bottom-space
></q-input>
</q-td>
<q-td auto-width>
<q-btn
v-if="props.row.id === '00000000-0000-0000-0000-000000000000'"
color="red"
flat
dense
round
size="14px"
icon="mdi-trash-can-outline"
@click="clickDeleteRow(props.row)"
/>
<q-btn
v-if="props.row.id !== '00000000-0000-0000-0000-000000000000'"
color="info"
flat
dense
round
size="14px"
icon="mdi-history"
@click="clickHistory(props.row)"
/>
</q-td>
</q-tr>
</template>
</data-table>
</q-form>
</div>
<HistoryTable
:rows="rowsHistory"
:columns="columnsHistory"
:filter="filterHistory"
:visible-columns="visibleColumnsHistory"
v-model:modal="modalHistory"
v-model:inputfilter="filterHistory"
v-model:inputvisible="visibleColumnsHistory"
v-model:tittle="tittleHistory"
>
<template #columns="props">
<q-tr :props="props">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.name == 'isActive'" class="">
<q-icon
v-if="col.value == false"
name="mdi-close"
color="red"
class="text-h5"
/>
<q-icon v-else name="mdi-check" color="positive" class="text-h5" />
</div>
<div v-else-if="col.name == 'lastUpdatedAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else class="">
{{ col.value }}
</div>
</q-td>
</q-tr>
</template>
</HistoryTable>
</template>
<script setup lang="ts">
import type { QTableProps } from "quasar";
import { useQuasar } from "quasar";
import { onMounted, ref, watch } from "vue";
import http from "@/plugins/http";
import config from "@/app.config";
import keycloak from "@/plugins/keycloak";
import { useCounterMixin } from "@/stores/mixin";
import { useManageDataStore } from "@/modules/01_metadata/store";
import type {
RequestItemsHistoryObject,
RequestItemsPublishHistoryObject,
Columns,
} from "@/modules/01_metadata/interface/request/organization/Organization";
import type { ResponseHistoryObject } from "@/modules/01_metadata/interface/response/organization/Organization";
import HistoryTable from "@/components/TableHistory.vue";
import { useDataStore } from "@/stores/data";
const props = defineProps({
fetchDataComponent: {
type: Function,
default: () => console.log("not function"),
},
});
const dataStore = useDataStore();
const { loaderPage } = dataStore;
const mixin = useCounterMixin();
const { success, dateText, messageError } = mixin;
const store = useManageDataStore();
const { manageData, changeManageColumns } = store;
const rows = ref<RequestItemsHistoryObject[]>([]); //list data table
const rowsHistory = ref<RequestItemsHistoryObject[]>([]); //select data history
const rawHistory = ref<RequestItemsHistoryObject[]>([]); //raw data history
const tittleHistory = ref<string>("ประวัติแก้ไขชื่อหน่วยงาน"); //
const myForm = ref<any>(null); //ref
const filter = ref<string>(""); //search data table
const filterHistory = ref<string>(""); //search data table history
const modalHistory = ref<boolean>(false); //modal
const edit = ref<boolean>(false); //
const idVersion = ref<string>(""); //id data mongodb
const version = ref<string>("published"); // published= draft=
const updateData = ref<boolean>(false); //
const checkValidate = ref<boolean>(false);
const columns = ref<QTableProps["columns"]>([
{
name: "name",
align: "left",
label: "ชื่อหน่วยงาน/หน่วยงานต้นสังกัด/ส่วนราชการต้นสังกัด",
sortable: true,
field: "name",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "createdAt",
align: "center",
label: "วันที่สร้าง",
sortable: true,
field: "createdAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdatedAt",
align: "center",
label: "วันที่แก้ไข",
sortable: true,
field: "lastUpdatedAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdateFullName",
align: "left",
label: "ผู้ดำเนินการ",
sortable: true,
field: "lastUpdateFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "isActive",
align: "left",
label: "สถานะ",
sortable: true,
field: "isActive",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "note",
align: "left",
label: "หมายเหตุ",
sortable: true,
field: "note",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumns = ref<String[]>([]);
manageData.organization.organization.columns.length == 0
? (visibleColumns.value = [
"name",
"createdAt",
"lastUpdatedAt",
"lastUpdateFullName",
"isActive",
"note",
])
: (visibleColumns.value = manageData.organization.organization.columns);
const columnsHistory = ref<QTableProps["columns"]>([
{
name: "name",
align: "left",
label: "ชื่อหน่วยงาน/หน่วยงานต้นสังกัด/ส่วนราชการต้นสังกัด",
sortable: true,
field: "name",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdatedAt",
align: "center",
label: "วันที่แก้ไข",
sortable: true,
field: "lastUpdatedAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdateFullName",
align: "left",
label: "ผู้ดำเนินการ",
sortable: true,
field: "lastUpdateFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "isActive",
align: "left",
label: "สถานะ",
sortable: true,
field: "isActive",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "note",
align: "left",
label: "หมายเหตุ",
sortable: true,
field: "note",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumnsHistory = ref<String[]>([
"name",
"lastUpdatedAt",
"lastUpdateFullName",
"isActive",
"note",
]);
/**
* เมอเขาหนานจะเรยกฟงชนนอน(get list data)
*/
onMounted(async () => {
await fetchData();
await fetchHistory();
});
watch(visibleColumns, async (count: String[], prevCount: String[]) => {
await changeManageColumns(2, "organization", count);
});
/**
* แจงเตอนขอมลในกรณ success
*/
const $q = useQuasar();
/**
* งก get data าส
*/
const fetchData = async () => {
await props.fetchDataComponent();
rows.value.splice(0);
loaderPage(true);
await http
.get(config.API.listOrganizationOrganizationHistory)
.then((res) => {
let data = res.data.result;
version.value = data.version; // published= draft=
idVersion.value = data.id; // id mongodb
data.items.map((e: RequestItemsHistoryObject) => {
rows.value.push({
id: e.id,
name: e.name,
createdAt: e.createdAt,
lastUpdatedAt: e.lastUpdatedAt,
lastUpdateFullName: e.lastUpdateFullName,
isActive: e.isActive,
createdFullName: e.createdFullName,
createdUserId: e.createdUserId,
lastUpdateUserId: e.lastUpdateUserId,
note: e.note,
});
});
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
updateData.value = false;
loaderPage(false);
});
};
/**
* งชนดอมลประวแกไขขอมลทงหมด
*/
const fetchHistory = async () => {
loaderPage(true);
await http
.get(config.API.listOrganizationOrganizationPublishedHistory)
.then((res) => {
const data = res.data.result;
rawHistory.value = [];
if (data.length > 0) {
data.map((e: RequestItemsPublishHistoryObject) => {
e.items.map((i: RequestItemsHistoryObject) => {
rawHistory.value.push({
createdAt: i.createdAt,
createdFullName: i.createdFullName,
createdUserId: i.createdUserId,
id: i.id,
isActive: i.isActive,
lastUpdateFullName: i.lastUpdateFullName,
lastUpdateUserId: i.lastUpdateUserId,
lastUpdatedAt: i.lastUpdatedAt,
name: i.name,
note: i.note,
});
});
});
}
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
loaderPage(false);
});
};
/**
* งก clear data แบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
*/
const clearPublishedData = async () => {
loaderPage(true);
await http
.delete(config.API.listOrganizationOrganizationHistory)
.then((res) => {
success($q, "ลบข้อมูลร่างสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchHistory();
await fetchData();
});
};
/**
* งกนเผยแพรแบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
*/
const publishedData = async () => {
loaderPage(true);
await http
.get(config.API.listOrganizationOrganizationPublished)
.then((res) => {
success($q, "เผยแพร่ข้อมูลสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchData();
});
};
/**
* งกนเพมขอม
*/
const clickAdd = async () => {
const filterRowNull = rows.value.filter(
(f: RequestItemsHistoryObject) =>
f.id === "00000000-0000-0000-0000-000000000000" && f.name == "" // array
);
if (filterRowNull.length == 0) {
//
rows.value.push({
createdAt: new Date(),
createdFullName: "",
createdUserId: "",
id: "00000000-0000-0000-0000-000000000000",
isActive: true,
lastUpdateFullName:
keycloak.tokenParsed == null ? "" : keycloak.tokenParsed.name,
lastUpdateUserId: "",
lastUpdatedAt: new Date(),
name: "",
note: "",
});
updateData.value = true;
}
};
/**
* งกนบนทกแบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
* publish เมอบนทกแบบรางแลวจะเผยแพรเลยไหม true=นทกและเผยแพร false=นทกอยางเดยว
*/
const save = async (publish: boolean) => {
await validateData();
if (checkValidate.value == false) return;
rows.value.map((e: ResponseHistoryObject) => ({
// data backend
id: e.id,
createdAt: e.createdAt,
lastUpdatedAt: e.lastUpdatedAt,
name: e.name,
isActive: e.isActive,
createdFullName: e.createdFullName,
createdUserId: e.createdUserId,
lastUpdateFullName: e.lastUpdateFullName,
lastUpdateUserId: e.lastUpdateUserId,
}));
loaderPage(true);
await http
.post(config.API.listOrganizationOrganizationHistoryId(idVersion.value), {
id: idVersion.value,
version: "draft",
items: rows.value,
})
.then(async (res) => {
if (publish === false) {
success($q, "บันทึกข้อมูลร่างสำเร็จ");
await fetchData(); // get data
} else {
await publishedData(); //
}
edit.value = false;
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
loaderPage(false);
});
};
/**
* เชคชอซำกบขอมลทอยแล
* @param val input
*/
const checkDupDataName = (val: string) => {
const filterNameNull = rows.value.filter(
(f: RequestItemsHistoryObject) => f.name == val
); //
if (filterNameNull.length > 1) {
return false;
}
return true;
};
/**
* งกนปมแกไข ให get data มาใหม
*/
const clickEdit = async () => {
await fetchData();
};
/**
* งกนปมบนทกแบบราง
*/
const clickSave = async () => {
await save(false);
};
/**
* งกนปมลบแบบราง
*/
const clickDelete = async () => {
await clearPublishedData();
};
/**
* งกนปมยกเลกการแกไขขอม
*/
const clickCancel = async () => {
edit.value = false;
await fetchData();
};
/**
* งกนปมเผยแพรอม
* เชคขอมลกอนวาใน array กรอกขอมลครบไหมถาครบกใหเผยแพรได
* าคาใน array ไมอมลใน row จะใหนทกได
*/
const clickPublish = async () => {
if (myForm.value !== null) {
myForm.value.validate().then(async (result: boolean) => {
if (result) {
await save(true);
}
});
} else {
await save(true);
}
};
/**
* งกนปมลบ row data
* @param val data ใน row จะลบ
*/
const clickDeleteRow = (val: RequestItemsHistoryObject) => {
rows.value = rows.value.filter((x: RequestItemsHistoryObject) => x !== val);
updateData.value = true;
};
/**
* งกนเช input ามการแกไขหรอย
*/
const clickEditRow = () => {
myForm.value.validate(false);
updateData.value = true;
};
/**
* งชนดอมลประวแกไขขอมลทเลอก
* @param row อม row ประวการแกไข
*/
const clickHistory = async (row: RequestItemsHistoryObject) => {
modalHistory.value = true;
rowsHistory.value = rawHistory.value.filter(
(f: RequestItemsHistoryObject) => f.id == row.id
);
};
/**
* งกนแปลง date เปนภาษาไทย
* @param value นท type datetime จะแปลงเปนไทย
*/
const textDate = (value: Date) => {
return dateText(value);
};
/**
* validate component
*/
const validateData = async () => {
checkValidate.value = true;
await myForm.value.validate().then((result: boolean) => {
if (result == false) {
checkValidate.value = false;
}
});
};
</script>
<style>
/* สีของnoti */
.my-notif-class {
background: rgba(33, 186, 69, 0.5) !important;
color: #008f17 !important;
}
</style>

View file

@ -0,0 +1,815 @@
<!-- tab อยอหนวยงาน หนาจดการขอมลหล/อมลโครงสรางหนวยงาน -->
<template>
<div>
<q-form ref="myForm">
<data-table
:rows="rows"
:columns="columns"
:filter="filter"
:visible-columns="visibleColumns"
v-model:inputfilter="filter"
v-model:inputvisible="visibleColumns"
v-model:editvisible="edit"
:add="clickAdd"
:edit="clickEdit"
:save="clickSave"
:deleted="clickDelete"
:cancel="clickCancel"
:publish="clickPublish"
:validate="validateData"
:publicData="version === 'published'"
:updateData="updateData"
:history="true"
>
<template #columns="props">
<q-tr :props="props" v-if="edit == false">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.name == 'isActive'" class="">
<q-icon
v-if="col.value == false"
name="mdi-close"
color="red"
class="text-h5"
/>
<q-icon
v-else
name="mdi-check"
color="positive"
class="text-h5"
/>
</div>
<div v-else-if="col.name == 'createdAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else-if="col.name == 'lastUpdatedAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else class="">
{{ col.value }}
</div>
</q-td>
<q-td auto-width>
<q-btn
color="info"
flat
dense
round
size="14px"
icon="mdi-history"
@click="clickHistory(props.row)"
/>
</q-td>
</q-tr>
<q-tr :props="props" v-if="edit == true">
<q-td
key="agencyCode"
:props="props"
v-if="props.row.agencyCode !== undefined"
>
<q-input
class=""
outlined
@update:model-value="clickEditRow"
v-model="props.row.agencyCode"
dense
lazy-rules
hide-bottom-space
:rules="[
(val) => (val && val.length > 0) || 'กรุณากรอกข้อมูลให้ครบ',
(val) =>
checkDupDataName(props.row) || 'ข้อมูลนี้มีอยู่แล้วในระบบ',
]"
></q-input>
</q-td>
<q-td
key="governmentCode"
:props="props"
v-if="props.row.governmentCode !== undefined"
>
<q-input
class=""
outlined
@update:model-value="clickEditRow"
v-model="props.row.governmentCode"
dense
lazy-rules
hide-bottom-space
:rules="[
(val) =>
checkDupDataName(props.row) || 'ข้อมูลนี้มีอยู่แล้วในระบบ',
]"
></q-input>
</q-td>
<q-td key="name" :props="props" v-if="props.row.name !== undefined">
<q-form ref="myForm3">
<q-input
class=""
outlined
@update:model-value="clickEditRow"
v-model="props.row.name"
dense
lazy-rules
hide-bottom-space
:rules="[
(val) => (val && val.length > 0) || 'กรุณากรอกข้อมูลให้ครบ',
(val) =>
checkDupDataName(props.row) ||
'ข้อมูลนี้มีอยู่แล้วในระบบ',
]"
></q-input>
</q-form>
</q-td>
<q-td
key="createdAt"
:props="props"
v-if="props.row.createdAt !== undefined"
>
<div class="">
{{ textDate(props.row.createdAt) }}
</div>
</q-td>
<q-td key="lastUpdatedAt" :props="props">
<div class="">
{{ textDate(props.row.lastUpdatedAt) }}
</div>
</q-td>
<q-td
key="lastUpdateFullName"
:props="props"
v-if="props.row.lastUpdateFullName !== undefined"
class=""
>
{{ props.row.lastUpdateFullName }}
</q-td>
<q-td
key="isActive"
:props="props"
v-if="props.row.isActive !== undefined"
>
<q-toggle
v-model="props.row.isActive"
dense
color="green"
@update:model-value="clickEditRow"
/>
</q-td>
<q-td key="note" :props="props" v-if="props.row.note !== undefined">
<q-input
class=""
outlined
@update:model-value="clickEditRow"
v-model="props.row.note"
dense
lazy-rules
autofocus
hide-bottom-space
></q-input>
</q-td>
<q-td auto-width>
<q-btn
v-if="props.row.id === '00000000-0000-0000-0000-000000000000'"
color="red"
flat
dense
round
size="14px"
icon="mdi-trash-can-outline"
@click="clickDeleteRow(props.row)"
/>
<q-btn
v-if="props.row.id !== '00000000-0000-0000-0000-000000000000'"
color="info"
flat
dense
round
size="14px"
icon="mdi-history"
@click="clickHistory(props.row)"
/>
</q-td>
</q-tr>
</template>
</data-table>
</q-form>
</div>
<HistoryTable
:rows="rowsHistory"
:columns="columnsHistory"
:filter="filterHistory"
:visible-columns="visibleColumnsHistory"
v-model:modal="modalHistory"
v-model:inputfilter="filterHistory"
v-model:inputvisible="visibleColumnsHistory"
v-model:tittle="tittleHistory"
>
<template #columns="props">
<q-tr :props="props">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.name == 'isActive'" class="">
<q-icon
v-if="col.value == false"
name="mdi-close"
color="red"
class="text-h5"
/>
<q-icon v-else name="mdi-check" color="positive" class="text-h5" />
</div>
<div v-else-if="col.name == 'lastUpdatedAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else class="">
{{ col.value }}
</div>
</q-td>
</q-tr>
</template>
</HistoryTable>
</template>
<script setup lang="ts">
import type { QTableProps } from "quasar";
import { useQuasar } from "quasar";
import { onMounted, ref, watch } from "vue";
import http from "@/plugins/http";
import config from "@/app.config";
import keycloak from "@/plugins/keycloak";
import { useCounterMixin } from "@/stores/mixin";
import { useManageDataStore } from "@/modules/01_metadata/store";
import type {
RequestItemsHistoryObject,
RequestItemsPublishHistoryObject,
Columns,
} from "@/modules/01_metadata/interface/request/organization/ShortName";
import type { ResponseHistoryObject } from "@/modules/01_metadata/interface/response/organization/ShortName";
import HistoryTable from "@/components/TableHistory.vue";
import { useDataStore } from "@/stores/data";
const props = defineProps({
fetchDataComponent: {
type: Function,
default: () => console.log("not function"),
},
});
const dataStore = useDataStore();
const { loaderPage } = dataStore;
const mixin = useCounterMixin();
const { success, dateText, messageError } = mixin;
const store = useManageDataStore();
const { manageData, changeManageColumns } = store;
const rows = ref<RequestItemsHistoryObject[]>([]); //list data table
const rowsHistory = ref<RequestItemsHistoryObject[]>([]); //select data history
const rawHistory = ref<RequestItemsHistoryObject[]>([]); //raw data history
const tittleHistory = ref<string>("ประวัติแก้ไขชื่อหน่วยงาน"); //
const myForm = ref<any>(null); //ref
const filter = ref<string>(""); //search data table
const filterHistory = ref<string>(""); //search data table history
const modalHistory = ref<boolean>(false); //modal
const edit = ref<boolean>(false); //
const idVersion = ref<string>(""); //id data mongodb
const version = ref<string>("published"); // published= draft=
const updateData = ref<boolean>(false); //
const checkValidate = ref<boolean>(false);
const columns = ref<QTableProps["columns"]>([
{
name: "agencyCode",
align: "left",
label: "รหัสหน่วยงาน",
sortable: true,
field: "agencyCode",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "governmentCode",
align: "left",
label: "รหัสส่วนราชการ",
sortable: true,
field: "governmentCode",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "name",
align: "left",
label: "ตัวย่อหน่วยงาน",
sortable: true,
field: "name",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "createdAt",
align: "center",
label: "วันที่สร้าง",
sortable: true,
field: "createdAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdatedAt",
align: "center",
label: "วันที่แก้ไข",
sortable: true,
field: "lastUpdatedAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdateFullName",
align: "left",
label: "ผู้ดำเนินการ",
sortable: true,
field: "lastUpdateFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "isActive",
align: "left",
label: "สถานะ",
sortable: true,
field: "isActive",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "note",
align: "left",
label: "หมายเหตุ",
sortable: true,
field: "note",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumns = ref<String[]>([]);
manageData.organization.shortName.columns.length == 0
? (visibleColumns.value = [
"agencyCode",
"governmentCode",
"name",
"createdAt",
"lastUpdatedAt",
"lastUpdateFullName",
"isActive",
"note",
])
: (visibleColumns.value = manageData.organization.shortName.columns);
const columnsHistory = ref<QTableProps["columns"]>([
{
name: "agencyCode",
align: "left",
label: "รหัสหน่วยงาน",
sortable: true,
field: "agencyCode",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "governmentCode",
align: "left",
label: "รหัสส่วนราชการ",
sortable: true,
field: "governmentCode",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "name",
align: "left",
label: "ตัวย่อหน่วยงาน",
sortable: true,
field: "name",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdatedAt",
align: "center",
label: "วันที่แก้ไข",
sortable: true,
field: "lastUpdatedAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdateFullName",
align: "left",
label: "ผู้ดำเนินการ",
sortable: true,
field: "lastUpdateFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "isActive",
align: "left",
label: "สถานะ",
sortable: true,
field: "isActive",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "note",
align: "left",
label: "หมายเหตุ",
sortable: true,
field: "note",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumnsHistory = ref<String[]>([
"agencyCode",
"governmentCode",
"name",
"lastUpdatedAt",
"lastUpdateFullName",
"isActive",
"note",
]);
/**
* เมอเขาหนานจะเรยกฟงชนนอน(get list data)
*/
onMounted(async () => {
await fetchData();
await fetchHistory();
});
watch(visibleColumns, async (count: String[], prevCount: String[]) => {
await changeManageColumns(2, "shortName", count);
});
/**
* แจงเตอนขอมลในกรณ success
*/
const $q = useQuasar();
/**
* งก get data าส
*/
const fetchData = async () => {
await props.fetchDataComponent();
rows.value.splice(0);
loaderPage(true);
await http
.get(config.API.listOrganizationShortNameHistory)
.then((res) => {
let data = res.data.result;
version.value = data.version; // published= draft=
idVersion.value = data.id; // id mongodb
data.items.map((e: RequestItemsHistoryObject) => {
rows.value.push({
id: e.id,
agencyCode: e.agencyCode,
governmentCode: e.governmentCode,
name: e.name,
createdAt: e.createdAt,
lastUpdatedAt: e.lastUpdatedAt,
lastUpdateFullName: e.lastUpdateFullName,
isActive: e.isActive,
createdFullName: e.createdFullName,
createdUserId: e.createdUserId,
lastUpdateUserId: e.lastUpdateUserId,
note: e.note,
});
});
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
updateData.value = false;
loaderPage(false);
});
};
/**
* งชนดอมลประวแกไขขอมลทงหมด
*/
const fetchHistory = async () => {
loaderPage(true);
await http
.get(config.API.listOrganizationShortNamePublishedHistory)
.then((res) => {
const data = res.data.result;
rawHistory.value = [];
if (data.length > 0) {
data.map((e: RequestItemsPublishHistoryObject) => {
e.items.map((i: RequestItemsHistoryObject) => {
rawHistory.value.push({
createdAt: i.createdAt,
createdFullName: i.createdFullName,
createdUserId: i.createdUserId,
id: i.id,
isActive: i.isActive,
lastUpdateFullName: i.lastUpdateFullName,
lastUpdateUserId: i.lastUpdateUserId,
lastUpdatedAt: i.lastUpdatedAt,
agencyCode: i.agencyCode,
governmentCode: i.governmentCode,
name: i.name,
note: i.note,
});
});
});
}
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
loaderPage(false);
});
};
/**
* งก clear data แบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
*/
const clearPublishedData = async () => {
loaderPage(true);
await http
.delete(config.API.listOrganizationShortNameHistory)
.then((res) => {
success($q, "ลบข้อมูลร่างสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchHistory();
await fetchData();
});
};
/**
* งกนเผยแพรแบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
*/
const publishedData = async () => {
loaderPage(true);
await http
.get(config.API.listOrganizationShortNamePublished)
.then((res) => {
success($q, "เผยแพร่ข้อมูลสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchData();
});
};
/**
* งกนเพมขอม
*/
const clickAdd = async () => {
const filterRowNull = rows.value.filter(
(f: RequestItemsHistoryObject) =>
f.id === "00000000-0000-0000-0000-000000000000" &&
(f.agencyCode == "" || f.name == "") // array
);
if (filterRowNull.length == 0) {
//
rows.value.push({
createdAt: new Date(),
createdFullName: "",
createdUserId: "",
id: "00000000-0000-0000-0000-000000000000",
isActive: true,
lastUpdateFullName:
keycloak.tokenParsed == null ? "" : keycloak.tokenParsed.name,
lastUpdateUserId: "",
lastUpdatedAt: new Date(),
agencyCode: "",
governmentCode: "",
name: "",
note: "",
});
updateData.value = true;
}
};
/**
* งกนบนทกแบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
* publish เมอบนทกแบบรางแลวจะเผยแพรเลยไหม true=นทกและเผยแพร false=นทกอยางเดยว
*/
const save = async (publish: boolean) => {
await validateData();
if (checkValidate.value == false) return;
rows.value.map((e: ResponseHistoryObject) => ({
// data backend
id: e.id,
createdAt: e.createdAt,
lastUpdatedAt: e.lastUpdatedAt,
agencyCode: e.agencyCode,
governmentCode: e.governmentCode,
name: e.name,
isActive: e.isActive,
createdFullName: e.createdFullName,
createdUserId: e.createdUserId,
lastUpdateFullName: e.lastUpdateFullName,
lastUpdateUserId: e.lastUpdateUserId,
}));
loaderPage(true);
await http
.post(config.API.listOrganizationShortNameHistoryId(idVersion.value), {
id: idVersion.value,
version: "draft",
items: rows.value,
})
.then(async (res) => {
if (publish === false) {
success($q, "บันทึกข้อมูลร่างสำเร็จ");
await fetchData(); // get data
} else {
await publishedData(); //
}
edit.value = false;
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
loaderPage(false);
});
};
/**
* เชครหสซำกบขอมลทอยแล
* @param val input รหสสวนราชการ
*/
const checkDupDataGovernmentCode = (gCode: string, aCode: string) => {
if (gCode == null || gCode == "") return true;
const filterCodeNull = rows.value.filter(
(f: RequestItemsHistoryObject) =>
f.governmentCode == gCode && f.agencyCode == aCode
); //
if (filterCodeNull.length > 1) {
return false;
}
return true;
};
/**
* เชคชอยอซำกบขอมลทอยแล
* @param val input อย
*/
const checkDupDataName = (row: any) => {
const filterShortNameNull = rows.value.filter(
(f: RequestItemsHistoryObject) =>
f.name == row.name &&
f.governmentCode == row.governmentCode &&
f.agencyCode == row.agencyCode
); //
if (filterShortNameNull.length > 1) {
return false;
}
return true;
};
/**
* งกนปมแกไข ให get data มาใหม
*/
const clickEdit = async () => {
await fetchData();
};
/**
* งกนปมบนทกแบบราง
*/
const clickSave = async () => {
await save(false);
};
/**
* งกนปมลบแบบราง
*/
const clickDelete = async () => {
await clearPublishedData();
};
/**
* งกนปมยกเลกการแกไขขอม
*/
const clickCancel = async () => {
edit.value = false;
await fetchData();
};
/**
* งกนปมเผยแพรอม
* เชคขอมลกอนวาใน array กรอกขอมลครบไหมถาครบกใหเผยแพรได
* าคาใน array ไมอมลใน row จะใหนทกได
*/
const clickPublish = async () => {
if (myForm.value !== null) {
myForm.value.validate().then(async (result: boolean) => {
if (result) {
await save(true);
}
});
} else {
await save(true);
}
};
/**
* งกนปมลบ row data
* @param val data ใน row จะลบ
*/
const clickDeleteRow = (val: RequestItemsHistoryObject) => {
rows.value = rows.value.filter((x: RequestItemsHistoryObject) => x !== val);
updateData.value = true;
};
/**
* งกนเช input ามการแกไขหรอย
*/
const clickEditRow = () => {
myForm.value.validate(false);
updateData.value = true;
};
/**
* งชนดอมลประวแกไขขอมลทเลอก
* @param row อม row ประวการแกไข
*/
const clickHistory = async (row: RequestItemsHistoryObject) => {
modalHistory.value = true;
rowsHistory.value = rawHistory.value.filter(
(f: RequestItemsHistoryObject) => f.id == row.id
);
};
/**
* งกนแปลง date เปนภาษาไทย
* @param value นท type datetime จะแปลงเปนไทย
*/
const textDate = (value: Date) => {
return dateText(value);
};
/**
* validate component
*/
const validateData = async () => {
checkValidate.value = true;
await myForm.value.validate().then((result: boolean) => {
if (result == false) {
checkValidate.value = false;
}
});
};
</script>
<style>
/* สีของnoti */
.my-notif-class {
background: rgba(33, 186, 69, 0.5) !important;
color: #008f17 !important;
}
</style>

View file

@ -0,0 +1,659 @@
<!-- tab สถานะของหนวยงาน/วนราชการ หนาจดการขอมลหล/อมลโครงสรางหนวยงาน -->
<template>
<div>
<q-form ref="myForm">
<data-table
:rows="rows"
:columns="columns"
:filter="filter"
:visible-columns="visibleColumns"
v-model:inputfilter="filter"
v-model:inputvisible="visibleColumns"
v-model:editvisible="edit"
:add="clickAdd"
:edit="clickEdit"
:save="clickSave"
:deleted="clickDelete"
:cancel="clickCancel"
:publish="clickPublish"
:validate="validateData"
:publicData="version === 'published'"
:updateData="updateData"
:history="true"
>
<template #columns="props">
<q-tr :props="props" v-if="edit == false">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.name == 'isActive'" class="">
<q-icon
v-if="col.value == false"
name="mdi-close"
color="red"
class="text-h5"
/>
<q-icon
v-else
name="mdi-check"
color="positive"
class="text-h5"
/>
</div>
<div v-else-if="col.name == 'createdAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else-if="col.name == 'lastUpdatedAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else class="">
{{ col.value }}
</div>
</q-td>
<q-td auto-width>
<q-btn
color="info"
flat
dense
round
size="14px"
icon="mdi-history"
@click="clickHistory(props.row)"
/>
</q-td>
</q-tr>
<q-tr :props="props" v-if="edit == true">
<q-td key="name" :props="props" v-if="props.row.name !== undefined">
<q-input
class=""
outlined
@update:model-value="clickEditRow"
v-model="props.row.name"
dense
lazy-rules
autofocus
hide-bottom-space
:rules="[
(val) => (val && val.length > 0) || 'กรุณากรอกข้อมูลให้ครบ',
(val) =>
checkDupDataName(val) || 'ชื่อซ้ำกันกับข้อมูลที่มีอยู่แล้ว',
]"
></q-input>
</q-td>
<q-td
key="createdAt"
:props="props"
v-if="props.row.createdAt !== undefined"
>
<div class="">
{{ textDate(props.row.createdAt) }}
</div>
</q-td>
<q-td key="lastUpdatedAt" :props="props">
<div class="">
{{ textDate(props.row.lastUpdatedAt) }}
</div>
</q-td>
<q-td
key="lastUpdateFullName"
:props="props"
v-if="props.row.lastUpdateFullName !== undefined"
class=""
>
{{ props.row.lastUpdateFullName }}
</q-td>
<q-td
key="isActive"
:props="props"
v-if="props.row.isActive !== undefined"
>
<q-toggle
v-model="props.row.isActive"
dense
color="green"
@update:model-value="clickEditRow"
/>
</q-td>
<q-td auto-width>
<q-btn
v-if="props.row.id === '00000000-0000-0000-0000-000000000000'"
color="red"
flat
dense
round
size="14px"
icon="mdi-trash-can-outline"
@click="clickDeleteRow(props.row)"
/>
<q-btn
v-if="props.row.id !== '00000000-0000-0000-0000-000000000000'"
color="info"
flat
dense
round
size="14px"
icon="mdi-history"
@click="clickHistory(props.row)"
/>
</q-td>
</q-tr>
</template>
</data-table>
</q-form>
</div>
<HistoryTable
:rows="rowsHistory"
:columns="columnsHistory"
:filter="filterHistory"
:visible-columns="visibleColumnsHistory"
v-model:modal="modalHistory"
v-model:inputfilter="filterHistory"
v-model:inputvisible="visibleColumnsHistory"
v-model:tittle="tittleHistory"
>
<template #columns="props">
<q-tr :props="props">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.name == 'isActive'" class="">
<q-icon
v-if="col.value == false"
name="mdi-close"
color="red"
class="text-h5"
/>
<q-icon v-else name="mdi-check" color="positive" class="text-h5" />
</div>
<div v-else-if="col.name == 'lastUpdatedAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else class="">
{{ col.value }}
</div>
</q-td>
</q-tr>
</template>
</HistoryTable>
</template>
<script setup lang="ts">
import type { QTableProps } from "quasar";
import { useQuasar } from "quasar";
import { onMounted, ref, watch } from "vue";
import http from "@/plugins/http";
import config from "@/app.config";
import keycloak from "@/plugins/keycloak";
import { useCounterMixin } from "@/stores/mixin";
import { useManageDataStore } from "@/modules/01_metadata/store";
import type {
RequestItemsHistoryObject,
RequestItemsPublishHistoryObject,
Columns,
} from "@/modules/01_metadata/interface/request/organization/Status";
import type { ResponseHistoryObject } from "@/modules/01_metadata/interface/response/organization/Status";
import HistoryTable from "@/components/TableHistory.vue";
import { useDataStore } from "@/stores/data";
const props = defineProps({
fetchDataComponent: {
type: Function,
default: () => console.log("not function"),
},
});
const dataStore = useDataStore();
const { loaderPage } = dataStore;
const mixin = useCounterMixin();
const { success, dateText, messageError } = mixin;
const store = useManageDataStore();
const { manageData, changeManageColumns } = store;
const rows = ref<RequestItemsHistoryObject[]>([]); //list data table
const rowsHistory = ref<RequestItemsHistoryObject[]>([]); //select data history
const rawHistory = ref<RequestItemsHistoryObject[]>([]); //raw data history
const tittleHistory = ref<string>("ประวัติแก้ไขสถานะของหน่วยงาน/ส่วนราชการ"); //
const myForm = ref<any>(null); //ref
const filter = ref<string>(""); //search data table
const filterHistory = ref<string>(""); //search data table history
const modalHistory = ref<boolean>(false); //modal
const edit = ref<boolean>(false); //
const idVersion = ref<string>(""); //id data mongodb
const version = ref<string>("published"); // published= draft=
const updateData = ref<boolean>(false); //
const checkValidate = ref<boolean>(false);
const columns = ref<QTableProps["columns"]>([
{
name: "name",
align: "left",
label: "สถานะของหน่วยงาน/ส่วนราชการ",
sortable: true,
field: "name",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "createdAt",
align: "center",
label: "วันที่สร้าง",
sortable: true,
field: "createdAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdatedAt",
align: "center",
label: "วันที่แก้ไข",
sortable: true,
field: "lastUpdatedAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdateFullName",
align: "left",
label: "ผู้ดำเนินการ",
sortable: true,
field: "lastUpdateFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "isActive",
align: "left",
label: "สถานะ",
sortable: true,
field: "isActive",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumns = ref<String[]>([]);
manageData.organization.status.columns.length == 0
? (visibleColumns.value = [
"name",
"createdAt",
"lastUpdatedAt",
"lastUpdateFullName",
"isActive",
])
: (visibleColumns.value = manageData.organization.status.columns);
const columnsHistory = ref<QTableProps["columns"]>([
{
name: "name",
align: "left",
label: "สถานะของหน่วยงาน/ส่วนราชการ",
sortable: true,
field: "name",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdatedAt",
align: "center",
label: "วันที่แก้ไข",
sortable: true,
field: "lastUpdatedAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdateFullName",
align: "left",
label: "ผู้ดำเนินการ",
sortable: true,
field: "lastUpdateFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "isActive",
align: "left",
label: "สถานะ",
sortable: true,
field: "isActive",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumnsHistory = ref<String[]>([
"name",
"lastUpdatedAt",
"lastUpdateFullName",
"isActive",
]);
/**
* เมอเขาหนานจะเรยกฟงชนนอน(get list data)
*/
onMounted(async () => {
await fetchData();
await fetchHistory();
});
watch(visibleColumns, async (count: String[], prevCount: String[]) => {
await changeManageColumns(2, "status", count);
});
/**
* แจงเตอนขอมลในกรณ success
*/
const $q = useQuasar();
/**
* งก get data าส
*/
const fetchData = async () => {
await props.fetchDataComponent();
rows.value.splice(0);
loaderPage(true);
await http
.get(config.API.listOrganizationStatusHistory)
.then((res) => {
let data = res.data.result;
version.value = data.version; // published= draft=
idVersion.value = data.id; // id mongodb
data.items.map((e: RequestItemsHistoryObject) => {
rows.value.push({
id: e.id,
name: e.name,
createdAt: e.createdAt,
lastUpdatedAt: e.lastUpdatedAt,
lastUpdateFullName: e.lastUpdateFullName,
isActive: e.isActive,
createdFullName: e.createdFullName,
createdUserId: e.createdUserId,
lastUpdateUserId: e.lastUpdateUserId,
});
});
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
updateData.value = false;
loaderPage(false);
});
};
/**
* งชนดอมลประวแกไขขอมลทงหมด
*/
const fetchHistory = async () => {
loaderPage(true);
await http
.get(config.API.listOrganizationStatusPublishedHistory)
.then((res) => {
const data = res.data.result;
rawHistory.value = [];
if (data.length > 0) {
data.map((e: RequestItemsPublishHistoryObject) => {
e.items.map((i: RequestItemsHistoryObject) => {
rawHistory.value.push({
createdAt: i.createdAt,
createdFullName: i.createdFullName,
createdUserId: i.createdUserId,
id: i.id,
isActive: i.isActive,
lastUpdateFullName: i.lastUpdateFullName,
lastUpdateUserId: i.lastUpdateUserId,
lastUpdatedAt: i.lastUpdatedAt,
name: i.name,
});
});
});
}
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
loaderPage(false);
});
};
/**
* งก clear data แบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
*/
const clearPublishedData = async () => {
loaderPage(true);
await http
.delete(config.API.listOrganizationStatusHistory)
.then((res) => {
success($q, "ลบข้อมูลร่างสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchHistory();
await fetchData();
});
};
/**
* งกนเผยแพรแบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
*/
const publishedData = async () => {
loaderPage(true);
await http
.get(config.API.listOrganizationStatusPublished)
.then((res) => {
success($q, "เผยแพร่ข้อมูลสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchData();
});
};
/**
* งกนเพมขอม
*/
const clickAdd = async () => {
const filterRowNull = rows.value.filter(
(f: RequestItemsHistoryObject) =>
f.id === "00000000-0000-0000-0000-000000000000" && f.name == "" // array
);
if (filterRowNull.length == 0) {
//
rows.value.push({
createdAt: new Date(),
createdFullName: "",
createdUserId: "",
id: "00000000-0000-0000-0000-000000000000",
isActive: true,
lastUpdateFullName:
keycloak.tokenParsed == null ? "" : keycloak.tokenParsed.name,
lastUpdateUserId: "",
lastUpdatedAt: new Date(),
name: "",
});
updateData.value = true;
}
};
/**
* งกนบนทกแบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
* publish เมอบนทกแบบรางแลวจะเผยแพรเลยไหม true=นทกและเผยแพร false=นทกอยางเดยว
*/
const save = async (publish: boolean) => {
await validateData();
if (checkValidate.value == false) return;
rows.value.map((e: ResponseHistoryObject) => ({
// data backend
id: e.id,
createdAt: e.createdAt,
lastUpdatedAt: e.lastUpdatedAt,
name: e.name,
isActive: e.isActive,
createdFullName: e.createdFullName,
createdUserId: e.createdUserId,
lastUpdateFullName: e.lastUpdateFullName,
lastUpdateUserId: e.lastUpdateUserId,
}));
loaderPage(true);
await http
.post(config.API.listOrganizationStatusHistoryId(idVersion.value), {
id: idVersion.value,
version: "draft",
items: rows.value,
})
.then(async (res) => {
if (publish === false) {
success($q, "บันทึกข้อมูลร่างสำเร็จ");
await fetchData(); // get data
} else {
await publishedData(); //
}
edit.value = false;
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
loaderPage(false);
});
};
/**
* เชคชอซำกบขอมลทอยแล
* @param val input
*/
const checkDupDataName = (val: string) => {
const filterNameNull = rows.value.filter(
(f: RequestItemsHistoryObject) => f.name == val
); //
if (filterNameNull.length > 1) {
return false;
}
return true;
};
/**
* งกนปมแกไข ให get data มาใหม
*/
const clickEdit = async () => {
await fetchData();
};
/**
* งกนปมบนทกแบบราง
*/
const clickSave = async () => {
await save(false);
};
/**
* งกนปมลบแบบราง
*/
const clickDelete = async () => {
await clearPublishedData();
};
/**
* งกนปมยกเลกการแกไขขอม
*/
const clickCancel = async () => {
edit.value = false;
await fetchData();
};
/**
* งกนปมเผยแพรอม
* เชคขอมลกอนวาใน array กรอกขอมลครบไหมถาครบกใหเผยแพรได
* าคาใน array ไมอมลใน row จะใหนทกได
*/
const clickPublish = async () => {
if (myForm.value !== null) {
myForm.value.validate().then(async (result: boolean) => {
if (result) {
await save(true);
}
});
} else {
await save(true);
}
};
/**
* งกนปมลบ row data
* @param val data ใน row จะลบ
*/
const clickDeleteRow = (val: RequestItemsHistoryObject) => {
rows.value = rows.value.filter((x: RequestItemsHistoryObject) => x !== val);
updateData.value = true;
};
/**
* งกนเช input ามการแกไขหรอย
*/
const clickEditRow = () => {
myForm.value.validate(false);
updateData.value = true;
};
/**
* งชนดอมลประวแกไขขอมลทเลอก
* @param row อม row ประวการแกไข
*/
const clickHistory = async (row: RequestItemsHistoryObject) => {
modalHistory.value = true;
rowsHistory.value = rawHistory.value.filter(
(f: RequestItemsHistoryObject) => f.id == row.id
);
};
/**
* งกนแปลง date เปนภาษาไทย
* @param value นท type datetime จะแปลงเปนไทย
*/
const textDate = (value: Date) => {
return dateText(value);
};
/**
* validate component
*/
const validateData = async () => {
checkValidate.value = true;
await myForm.value.validate().then((result: boolean) => {
if (result == false) {
checkValidate.value = false;
}
});
};
</script>
<style>
/* สีของnoti */
.my-notif-class {
background: rgba(33, 186, 69, 0.5) !important;
color: #008f17 !important;
}
</style>

View file

@ -0,0 +1,659 @@
<!-- tab หมายเลขโทรศพทภายนอก หนาจดการขอมลหล/อมลโครงสรางหนวยงาน -->
<template>
<div>
<q-form ref="myForm">
<data-table
:rows="rows"
:columns="columns"
:filter="filter"
:visible-columns="visibleColumns"
v-model:inputfilter="filter"
v-model:inputvisible="visibleColumns"
v-model:editvisible="edit"
:add="clickAdd"
:edit="clickEdit"
:save="clickSave"
:deleted="clickDelete"
:cancel="clickCancel"
:publish="clickPublish"
:validate="validateData"
:publicData="version === 'published'"
:updateData="updateData"
:history="true"
>
<template #columns="props">
<q-tr :props="props" v-if="edit == false">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.name == 'isActive'" class="">
<q-icon
v-if="col.value == false"
name="mdi-close"
color="red"
class="text-h5"
/>
<q-icon
v-else
name="mdi-check"
color="positive"
class="text-h5"
/>
</div>
<div v-else-if="col.name == 'createdAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else-if="col.name == 'lastUpdatedAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else class="">
{{ col.value }}
</div>
</q-td>
<q-td auto-width>
<q-btn
color="info"
flat
dense
round
size="14px"
icon="mdi-history"
@click="clickHistory(props.row)"
/>
</q-td>
</q-tr>
<q-tr :props="props" v-if="edit == true">
<q-td key="name" :props="props" v-if="props.row.name !== undefined">
<q-input
class=""
outlined
@update:model-value="clickEditRow"
v-model="props.row.name"
dense
lazy-rules
autofocus
hide-bottom-space
:rules="[
(val) => (val && val.length > 0) || 'กรุณากรอกข้อมูลให้ครบ',
(val) =>
checkDupDataName(val) || 'ชื่อซ้ำกันกับข้อมูลที่มีอยู่แล้ว',
]"
></q-input>
</q-td>
<q-td
key="createdAt"
:props="props"
v-if="props.row.createdAt !== undefined"
>
<div class="">
{{ textDate(props.row.createdAt) }}
</div>
</q-td>
<q-td key="lastUpdatedAt" :props="props">
<div class="">
{{ textDate(props.row.lastUpdatedAt) }}
</div>
</q-td>
<q-td
key="lastUpdateFullName"
:props="props"
v-if="props.row.lastUpdateFullName !== undefined"
class=""
>
{{ props.row.lastUpdateFullName }}
</q-td>
<q-td
key="isActive"
:props="props"
v-if="props.row.isActive !== undefined"
>
<q-toggle
v-model="props.row.isActive"
dense
color="green"
@update:model-value="clickEditRow"
/>
</q-td>
<q-td auto-width>
<q-btn
v-if="props.row.id === '00000000-0000-0000-0000-000000000000'"
color="red"
flat
dense
round
size="14px"
icon="mdi-trash-can-outline"
@click="clickDeleteRow(props.row)"
/>
<q-btn
v-if="props.row.id !== '00000000-0000-0000-0000-000000000000'"
color="info"
flat
dense
round
size="14px"
icon="mdi-history"
@click="clickHistory(props.row)"
/>
</q-td>
</q-tr>
</template>
</data-table>
</q-form>
</div>
<HistoryTable
:rows="rowsHistory"
:columns="columnsHistory"
:filter="filterHistory"
:visible-columns="visibleColumnsHistory"
v-model:modal="modalHistory"
v-model:inputfilter="filterHistory"
v-model:inputvisible="visibleColumnsHistory"
v-model:tittle="tittleHistory"
>
<template #columns="props">
<q-tr :props="props">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.name == 'isActive'" class="">
<q-icon
v-if="col.value == false"
name="mdi-close"
color="red"
class="text-h5"
/>
<q-icon v-else name="mdi-check" color="positive" class="text-h5" />
</div>
<div v-else-if="col.name == 'lastUpdatedAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else class="">
{{ col.value }}
</div>
</q-td>
</q-tr>
</template>
</HistoryTable>
</template>
<script setup lang="ts">
import type { QTableProps } from "quasar";
import { useQuasar } from "quasar";
import { onMounted, ref, watch } from "vue";
import http from "@/plugins/http";
import config from "@/app.config";
import keycloak from "@/plugins/keycloak";
import { useCounterMixin } from "@/stores/mixin";
import { useManageDataStore } from "@/modules/01_metadata/store";
import type {
RequestItemsHistoryObject,
RequestItemsPublishHistoryObject,
Columns,
} from "@/modules/01_metadata/interface/request/organization/TelExternal";
import type { ResponseHistoryObject } from "@/modules/01_metadata/interface/response/organization/TelExternal";
import HistoryTable from "@/components/TableHistory.vue";
import { useDataStore } from "@/stores/data";
const props = defineProps({
fetchDataComponent: {
type: Function,
default: () => console.log("not function"),
},
});
const dataStore = useDataStore();
const { loaderPage } = dataStore;
const mixin = useCounterMixin();
const { success, dateText, messageError } = mixin;
const store = useManageDataStore();
const { manageData, changeManageColumns } = store;
const rows = ref<RequestItemsHistoryObject[]>([]); //list data table
const rowsHistory = ref<RequestItemsHistoryObject[]>([]); //select data history
const rawHistory = ref<RequestItemsHistoryObject[]>([]); //raw data history
const tittleHistory = ref<string>("ประวัติแก้ไขหมายเลขโทรศัพท์ภายนอก"); //
const myForm = ref<any>(null); //ref
const filter = ref<string>(""); //search data table
const filterHistory = ref<string>(""); //search data table history
const modalHistory = ref<boolean>(false); //modal
const edit = ref<boolean>(false); //
const idVersion = ref<string>(""); //id data mongodb
const version = ref<string>("published"); // published= draft=
const updateData = ref<boolean>(false); //
const checkValidate = ref<boolean>(false);
const columns = ref<QTableProps["columns"]>([
{
name: "name",
align: "left",
label: "หมายเลขโทรศัพท์ภายนอก",
sortable: true,
field: "name",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "createdAt",
align: "center",
label: "วันที่สร้าง",
sortable: true,
field: "createdAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdatedAt",
align: "center",
label: "วันที่แก้ไข",
sortable: true,
field: "lastUpdatedAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdateFullName",
align: "left",
label: "ผู้ดำเนินการ",
sortable: true,
field: "lastUpdateFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "isActive",
align: "left",
label: "สถานะ",
sortable: true,
field: "isActive",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumns = ref<String[]>([]);
manageData.organization.telExternal.columns.length == 0
? (visibleColumns.value = [
"name",
"createdAt",
"lastUpdatedAt",
"lastUpdateFullName",
"isActive",
])
: (visibleColumns.value = manageData.organization.telExternal.columns);
const columnsHistory = ref<QTableProps["columns"]>([
{
name: "name",
align: "left",
label: "หมายเลขโทรศัพท์ภายนอก",
sortable: true,
field: "name",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdatedAt",
align: "center",
label: "วันที่แก้ไข",
sortable: true,
field: "lastUpdatedAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdateFullName",
align: "left",
label: "ผู้ดำเนินการ",
sortable: true,
field: "lastUpdateFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "isActive",
align: "left",
label: "สถานะ",
sortable: true,
field: "isActive",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumnsHistory = ref<String[]>([
"name",
"lastUpdatedAt",
"lastUpdateFullName",
"isActive",
]);
/**
* เมอเขาหนานจะเรยกฟงชนนอน(get list data)
*/
onMounted(async () => {
await fetchData();
await fetchHistory();
});
watch(visibleColumns, async (count: String[], prevCount: String[]) => {
await changeManageColumns(2, "telExternal", count);
});
/**
* แจงเตอนขอมลในกรณ success
*/
const $q = useQuasar();
/**
* งก get data าส
*/
const fetchData = async () => {
await props.fetchDataComponent();
rows.value.splice(0);
loaderPage(true);
await http
.get(config.API.listOrganizationTelExternalHistory)
.then((res) => {
let data = res.data.result;
version.value = data.version; // published= draft=
idVersion.value = data.id; // id mongodb
data.items.map((e: RequestItemsHistoryObject) => {
rows.value.push({
id: e.id,
name: e.name,
createdAt: e.createdAt,
lastUpdatedAt: e.lastUpdatedAt,
lastUpdateFullName: e.lastUpdateFullName,
isActive: e.isActive,
createdFullName: e.createdFullName,
createdUserId: e.createdUserId,
lastUpdateUserId: e.lastUpdateUserId,
});
});
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
updateData.value = false;
loaderPage(false);
});
};
/**
* งชนดอมลประวแกไขขอมลทงหมด
*/
const fetchHistory = async () => {
loaderPage(true);
await http
.get(config.API.listOrganizationTelExternalPublishedHistory)
.then((res) => {
const data = res.data.result;
rawHistory.value = [];
if (data.length > 0) {
data.map((e: RequestItemsPublishHistoryObject) => {
e.items.map((i: RequestItemsHistoryObject) => {
rawHistory.value.push({
createdAt: i.createdAt,
createdFullName: i.createdFullName,
createdUserId: i.createdUserId,
id: i.id,
isActive: i.isActive,
lastUpdateFullName: i.lastUpdateFullName,
lastUpdateUserId: i.lastUpdateUserId,
lastUpdatedAt: i.lastUpdatedAt,
name: i.name,
});
});
});
}
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
loaderPage(false);
});
};
/**
* งก clear data แบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
*/
const clearPublishedData = async () => {
loaderPage(true);
await http
.delete(config.API.listOrganizationTelExternalHistory)
.then((res) => {
success($q, "ลบข้อมูลร่างสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchHistory();
await fetchData();
});
};
/**
* งกนเผยแพรแบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
*/
const publishedData = async () => {
loaderPage(true);
await http
.get(config.API.listOrganizationTelExternalPublished)
.then((res) => {
success($q, "เผยแพร่ข้อมูลสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchData();
});
};
/**
* งกนเพมขอม
*/
const clickAdd = async () => {
const filterRowNull = rows.value.filter(
(f: RequestItemsHistoryObject) =>
f.id === "00000000-0000-0000-0000-000000000000" && f.name == "" // array
);
if (filterRowNull.length == 0) {
//
rows.value.push({
createdAt: new Date(),
createdFullName: "",
createdUserId: "",
id: "00000000-0000-0000-0000-000000000000",
isActive: true,
lastUpdateFullName:
keycloak.tokenParsed == null ? "" : keycloak.tokenParsed.name,
lastUpdateUserId: "",
lastUpdatedAt: new Date(),
name: "",
});
updateData.value = true;
}
};
/**
* งกนบนทกแบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
* publish เมอบนทกแบบรางแลวจะเผยแพรเลยไหม true=นทกและเผยแพร false=นทกอยางเดยว
*/
const save = async (publish: boolean) => {
await validateData();
if (checkValidate.value == false) return;
rows.value.map((e: ResponseHistoryObject) => ({
// data backend
id: e.id,
createdAt: e.createdAt,
lastUpdatedAt: e.lastUpdatedAt,
name: e.name,
isActive: e.isActive,
createdFullName: e.createdFullName,
createdUserId: e.createdUserId,
lastUpdateFullName: e.lastUpdateFullName,
lastUpdateUserId: e.lastUpdateUserId,
}));
loaderPage(true);
await http
.post(config.API.listOrganizationTelExternalHistoryId(idVersion.value), {
id: idVersion.value,
version: "draft",
items: rows.value,
})
.then(async (res) => {
if (publish === false) {
success($q, "บันทึกข้อมูลร่างสำเร็จ");
await fetchData(); // get data
} else {
await publishedData(); //
}
edit.value = false;
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
loaderPage(false);
});
};
/**
* เชคชอซำกบขอมลทอยแล
* @param val input
*/
const checkDupDataName = (val: string) => {
const filterNameNull = rows.value.filter(
(f: RequestItemsHistoryObject) => f.name == val
); //
if (filterNameNull.length > 1) {
return false;
}
return true;
};
/**
* งกนปมแกไข ให get data มาใหม
*/
const clickEdit = async () => {
await fetchData();
};
/**
* งกนปมบนทกแบบราง
*/
const clickSave = async () => {
await save(false);
};
/**
* งกนปมลบแบบราง
*/
const clickDelete = async () => {
await clearPublishedData();
};
/**
* งกนปมยกเลกการแกไขขอม
*/
const clickCancel = async () => {
edit.value = false;
await fetchData();
};
/**
* งกนปมเผยแพรอม
* เชคขอมลกอนวาใน array กรอกขอมลครบไหมถาครบกใหเผยแพรได
* าคาใน array ไมอมลใน row จะใหนทกได
*/
const clickPublish = async () => {
if (myForm.value !== null) {
myForm.value.validate().then(async (result: boolean) => {
if (result) {
await save(true);
}
});
} else {
await save(true);
}
};
/**
* งกนปมลบ row data
* @param val data ใน row จะลบ
*/
const clickDeleteRow = (val: RequestItemsHistoryObject) => {
rows.value = rows.value.filter((x: RequestItemsHistoryObject) => x !== val);
updateData.value = true;
};
/**
* งกนเช input ามการแกไขหรอย
*/
const clickEditRow = () => {
myForm.value.validate(false);
updateData.value = true;
};
/**
* งชนดอมลประวแกไขขอมลทเลอก
* @param row อม row ประวการแกไข
*/
const clickHistory = async (row: RequestItemsHistoryObject) => {
modalHistory.value = true;
rowsHistory.value = rawHistory.value.filter(
(f: RequestItemsHistoryObject) => f.id == row.id
);
};
/**
* งกนแปลง date เปนภาษาไทย
* @param value นท type datetime จะแปลงเปนไทย
*/
const textDate = (value: Date) => {
return dateText(value);
};
/**
* validate component
*/
const validateData = async () => {
checkValidate.value = true;
await myForm.value.validate().then((result: boolean) => {
if (result == false) {
checkValidate.value = false;
}
});
};
</script>
<style>
/* สีของnoti */
.my-notif-class {
background: rgba(33, 186, 69, 0.5) !important;
color: #008f17 !important;
}
</style>

View file

@ -0,0 +1,659 @@
<!-- tab หมายเลขโทรศพทภายใน หนาจดการขอมลหล/อมลโครงสรางหนวยงาน -->
<template>
<div>
<q-form ref="myForm">
<data-table
:rows="rows"
:columns="columns"
:filter="filter"
:visible-columns="visibleColumns"
v-model:inputfilter="filter"
v-model:inputvisible="visibleColumns"
v-model:editvisible="edit"
:add="clickAdd"
:edit="clickEdit"
:save="clickSave"
:deleted="clickDelete"
:cancel="clickCancel"
:publish="clickPublish"
:validate="validateData"
:publicData="version === 'published'"
:updateData="updateData"
:history="true"
>
<template #columns="props">
<q-tr :props="props" v-if="edit == false">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.name == 'isActive'" class="">
<q-icon
v-if="col.value == false"
name="mdi-close"
color="red"
class="text-h5"
/>
<q-icon
v-else
name="mdi-check"
color="positive"
class="text-h5"
/>
</div>
<div v-else-if="col.name == 'createdAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else-if="col.name == 'lastUpdatedAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else class="">
{{ col.value }}
</div>
</q-td>
<q-td auto-width>
<q-btn
color="info"
flat
dense
round
size="14px"
icon="mdi-history"
@click="clickHistory(props.row)"
/>
</q-td>
</q-tr>
<q-tr :props="props" v-if="edit == true">
<q-td key="name" :props="props" v-if="props.row.name !== undefined">
<q-input
class=""
outlined
@update:model-value="clickEditRow"
v-model="props.row.name"
dense
lazy-rules
autofocus
hide-bottom-space
:rules="[
(val) => (val && val.length > 0) || 'กรุณากรอกข้อมูลให้ครบ',
(val) =>
checkDupDataName(val) || 'ชื่อซ้ำกันกับข้อมูลที่มีอยู่แล้ว',
]"
></q-input>
</q-td>
<q-td
key="createdAt"
:props="props"
v-if="props.row.createdAt !== undefined"
>
<div class="">
{{ textDate(props.row.createdAt) }}
</div>
</q-td>
<q-td key="lastUpdatedAt" :props="props">
<div class="">
{{ textDate(props.row.lastUpdatedAt) }}
</div>
</q-td>
<q-td
key="lastUpdateFullName"
:props="props"
v-if="props.row.lastUpdateFullName !== undefined"
class=""
>
{{ props.row.lastUpdateFullName }}
</q-td>
<q-td
key="isActive"
:props="props"
v-if="props.row.isActive !== undefined"
>
<q-toggle
v-model="props.row.isActive"
dense
color="green"
@update:model-value="clickEditRow"
/>
</q-td>
<q-td auto-width>
<q-btn
v-if="props.row.id === '00000000-0000-0000-0000-000000000000'"
color="red"
flat
dense
round
size="14px"
icon="mdi-trash-can-outline"
@click="clickDeleteRow(props.row)"
/>
<q-btn
v-if="props.row.id !== '00000000-0000-0000-0000-000000000000'"
color="info"
flat
dense
round
size="14px"
icon="mdi-history"
@click="clickHistory(props.row)"
/>
</q-td>
</q-tr>
</template>
</data-table>
</q-form>
</div>
<HistoryTable
:rows="rowsHistory"
:columns="columnsHistory"
:filter="filterHistory"
:visible-columns="visibleColumnsHistory"
v-model:modal="modalHistory"
v-model:inputfilter="filterHistory"
v-model:inputvisible="visibleColumnsHistory"
v-model:tittle="tittleHistory"
>
<template #columns="props">
<q-tr :props="props">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.name == 'isActive'" class="">
<q-icon
v-if="col.value == false"
name="mdi-close"
color="red"
class="text-h5"
/>
<q-icon v-else name="mdi-check" color="positive" class="text-h5" />
</div>
<div v-else-if="col.name == 'lastUpdatedAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else class="">
{{ col.value }}
</div>
</q-td>
</q-tr>
</template>
</HistoryTable>
</template>
<script setup lang="ts">
import type { QTableProps } from "quasar";
import { useQuasar } from "quasar";
import { onMounted, ref, watch } from "vue";
import http from "@/plugins/http";
import config from "@/app.config";
import keycloak from "@/plugins/keycloak";
import { useCounterMixin } from "@/stores/mixin";
import { useManageDataStore } from "@/modules/01_metadata/store";
import type {
RequestItemsHistoryObject,
RequestItemsPublishHistoryObject,
Columns,
} from "@/modules/01_metadata/interface/request/organization/TelInternal";
import type { ResponseHistoryObject } from "@/modules/01_metadata/interface/response/organization/TelInternal";
import HistoryTable from "@/components/TableHistory.vue";
import { useDataStore } from "@/stores/data";
const props = defineProps({
fetchDataComponent: {
type: Function,
default: () => console.log("not function"),
},
});
const dataStore = useDataStore();
const { loaderPage } = dataStore;
const mixin = useCounterMixin();
const { success, dateText, messageError } = mixin;
const store = useManageDataStore();
const { manageData, changeManageColumns } = store;
const rows = ref<RequestItemsHistoryObject[]>([]); //list data table
const rowsHistory = ref<RequestItemsHistoryObject[]>([]); //select data history
const rawHistory = ref<RequestItemsHistoryObject[]>([]); //raw data history
const tittleHistory = ref<string>("ประวัติแก้ไขหมายเลขโทรศัพท์ภายใน"); //
const myForm = ref<any>(null); //ref
const filter = ref<string>(""); //search data table
const filterHistory = ref<string>(""); //search data table history
const modalHistory = ref<boolean>(false); //modal
const edit = ref<boolean>(false); //
const idVersion = ref<string>(""); //id data mongodb
const version = ref<string>("published"); // published= draft=
const updateData = ref<boolean>(false); //
const checkValidate = ref<boolean>(false);
const columns = ref<QTableProps["columns"]>([
{
name: "name",
align: "left",
label: "หมายเลขโทรศัพท์ภายใน",
sortable: true,
field: "name",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "createdAt",
align: "center",
label: "วันที่สร้าง",
sortable: true,
field: "createdAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdatedAt",
align: "center",
label: "วันที่แก้ไข",
sortable: true,
field: "lastUpdatedAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdateFullName",
align: "left",
label: "ผู้ดำเนินการ",
sortable: true,
field: "lastUpdateFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "isActive",
align: "left",
label: "สถานะ",
sortable: true,
field: "isActive",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumns = ref<String[]>([]);
manageData.organization.telInternal.columns.length == 0
? (visibleColumns.value = [
"name",
"createdAt",
"lastUpdatedAt",
"lastUpdateFullName",
"isActive",
])
: (visibleColumns.value = manageData.organization.telInternal.columns);
const columnsHistory = ref<QTableProps["columns"]>([
{
name: "name",
align: "left",
label: "หมายเลขโทรศัพท์ภายใน",
sortable: true,
field: "name",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdatedAt",
align: "center",
label: "วันที่แก้ไข",
sortable: true,
field: "lastUpdatedAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdateFullName",
align: "left",
label: "ผู้ดำเนินการ",
sortable: true,
field: "lastUpdateFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "isActive",
align: "left",
label: "สถานะ",
sortable: true,
field: "isActive",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumnsHistory = ref<String[]>([
"name",
"lastUpdatedAt",
"lastUpdateFullName",
"isActive",
]);
/**
* เมอเขาหนานจะเรยกฟงชนนอน(get list data)
*/
onMounted(async () => {
await fetchData();
await fetchHistory();
});
watch(visibleColumns, async (count: String[], prevCount: String[]) => {
await changeManageColumns(2, "telInternal", count);
});
/**
* แจงเตอนขอมลในกรณ success
*/
const $q = useQuasar();
/**
* งก get data าส
*/
const fetchData = async () => {
await props.fetchDataComponent();
rows.value.splice(0);
loaderPage(true);
await http
.get(config.API.listOrganizationTelInternalHistory)
.then((res) => {
let data = res.data.result;
version.value = data.version; // published= draft=
idVersion.value = data.id; // id mongodb
data.items.map((e: RequestItemsHistoryObject) => {
rows.value.push({
id: e.id,
name: e.name,
createdAt: e.createdAt,
lastUpdatedAt: e.lastUpdatedAt,
lastUpdateFullName: e.lastUpdateFullName,
isActive: e.isActive,
createdFullName: e.createdFullName,
createdUserId: e.createdUserId,
lastUpdateUserId: e.lastUpdateUserId,
});
});
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
updateData.value = false;
loaderPage(false);
});
};
/**
* งชนดอมลประวแกไขขอมลทงหมด
*/
const fetchHistory = async () => {
loaderPage(true);
await http
.get(config.API.listOrganizationTelInternalPublishedHistory)
.then((res) => {
const data = res.data.result;
rawHistory.value = [];
if (data.length > 0) {
data.map((e: RequestItemsPublishHistoryObject) => {
e.items.map((i: RequestItemsHistoryObject) => {
rawHistory.value.push({
createdAt: i.createdAt,
createdFullName: i.createdFullName,
createdUserId: i.createdUserId,
id: i.id,
isActive: i.isActive,
lastUpdateFullName: i.lastUpdateFullName,
lastUpdateUserId: i.lastUpdateUserId,
lastUpdatedAt: i.lastUpdatedAt,
name: i.name,
});
});
});
}
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
loaderPage(false);
});
};
/**
* งก clear data แบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
*/
const clearPublishedData = async () => {
loaderPage(true);
await http
.delete(config.API.listOrganizationTelInternalHistory)
.then((res) => {
success($q, "ลบข้อมูลร่างสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchHistory();
await fetchData();
});
};
/**
* งกนเผยแพรแบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
*/
const publishedData = async () => {
loaderPage(true);
await http
.get(config.API.listOrganizationTelInternalPublished)
.then((res) => {
success($q, "เผยแพร่ข้อมูลสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchData();
});
};
/**
* งกนเพมขอม
*/
const clickAdd = async () => {
const filterRowNull = rows.value.filter(
(f: RequestItemsHistoryObject) =>
f.id === "00000000-0000-0000-0000-000000000000" && f.name == "" // array
);
if (filterRowNull.length == 0) {
//
rows.value.push({
createdAt: new Date(),
createdFullName: "",
createdUserId: "",
id: "00000000-0000-0000-0000-000000000000",
isActive: true,
lastUpdateFullName:
keycloak.tokenParsed == null ? "" : keycloak.tokenParsed.name,
lastUpdateUserId: "",
lastUpdatedAt: new Date(),
name: "",
});
updateData.value = true;
}
};
/**
* งกนบนทกแบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
* publish เมอบนทกแบบรางแลวจะเผยแพรเลยไหม true=นทกและเผยแพร false=นทกอยางเดยว
*/
const save = async (publish: boolean) => {
await validateData();
if (checkValidate.value == false) return;
rows.value.map((e: ResponseHistoryObject) => ({
// data backend
id: e.id,
createdAt: e.createdAt,
lastUpdatedAt: e.lastUpdatedAt,
name: e.name,
isActive: e.isActive,
createdFullName: e.createdFullName,
createdUserId: e.createdUserId,
lastUpdateFullName: e.lastUpdateFullName,
lastUpdateUserId: e.lastUpdateUserId,
}));
loaderPage(true);
await http
.post(config.API.listOrganizationTelInternalHistoryId(idVersion.value), {
id: idVersion.value,
version: "draft",
items: rows.value,
})
.then(async (res) => {
if (publish === false) {
success($q, "บันทึกข้อมูลร่างสำเร็จ");
await fetchData(); // get data
} else {
await publishedData(); //
}
edit.value = false;
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
loaderPage(false);
});
};
/**
* เชคชอซำกบขอมลทอยแล
* @param val input
*/
const checkDupDataName = (val: string) => {
const filterNameNull = rows.value.filter(
(f: RequestItemsHistoryObject) => f.name == val
); //
if (filterNameNull.length > 1) {
return false;
}
return true;
};
/**
* งกนปมแกไข ให get data มาใหม
*/
const clickEdit = async () => {
await fetchData();
};
/**
* งกนปมบนทกแบบราง
*/
const clickSave = async () => {
await save(false);
};
/**
* งกนปมลบแบบราง
*/
const clickDelete = async () => {
await clearPublishedData();
};
/**
* งกนปมยกเลกการแกไขขอม
*/
const clickCancel = async () => {
edit.value = false;
await fetchData();
};
/**
* งกนปมเผยแพรอม
* เชคขอมลกอนวาใน array กรอกขอมลครบไหมถาครบกใหเผยแพรได
* าคาใน array ไมอมลใน row จะใหนทกได
*/
const clickPublish = async () => {
if (myForm.value !== null) {
myForm.value.validate().then(async (result: boolean) => {
if (result) {
await save(true);
}
});
} else {
await save(true);
}
};
/**
* งกนปมลบ row data
* @param val data ใน row จะลบ
*/
const clickDeleteRow = (val: RequestItemsHistoryObject) => {
rows.value = rows.value.filter((x: RequestItemsHistoryObject) => x !== val);
updateData.value = true;
};
/**
* งกนเช input ามการแกไขหรอย
*/
const clickEditRow = () => {
myForm.value.validate(false);
updateData.value = true;
};
/**
* งชนดอมลประวแกไขขอมลทเลอก
* @param row อม row ประวการแกไข
*/
const clickHistory = async (row: RequestItemsHistoryObject) => {
modalHistory.value = true;
rowsHistory.value = rawHistory.value.filter(
(f: RequestItemsHistoryObject) => f.id == row.id
);
};
/**
* งกนแปลง date เปนภาษาไทย
* @param value นท type datetime จะแปลงเปนไทย
*/
const textDate = (value: Date) => {
return dateText(value);
};
/**
* validate component
*/
const validateData = async () => {
checkValidate.value = true;
await myForm.value.validate().then((result: boolean) => {
if (result == false) {
checkValidate.value = false;
}
});
};
</script>
<style>
/* สีของnoti */
.my-notif-class {
background: rgba(33, 186, 69, 0.5) !important;
color: #008f17 !important;
}
</style>

View file

@ -0,0 +1,659 @@
<!-- tab ประเภทของหนวยงาน/วนราชการ หนาจดการขอมลหล/อมลโครงสรางหนวยงาน -->
<template>
<div>
<q-form ref="myForm">
<data-table
:rows="rows"
:columns="columns"
:filter="filter"
:visible-columns="visibleColumns"
v-model:inputfilter="filter"
v-model:inputvisible="visibleColumns"
v-model:editvisible="edit"
:add="clickAdd"
:edit="clickEdit"
:save="clickSave"
:deleted="clickDelete"
:cancel="clickCancel"
:publish="clickPublish"
:validate="validateData"
:publicData="version === 'published'"
:updateData="updateData"
:history="true"
>
<template #columns="props">
<q-tr :props="props" v-if="edit == false">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.name == 'isActive'" class="">
<q-icon
v-if="col.value == false"
name="mdi-close"
color="red"
class="text-h5"
/>
<q-icon
v-else
name="mdi-check"
color="positive"
class="text-h5"
/>
</div>
<div v-else-if="col.name == 'createdAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else-if="col.name == 'lastUpdatedAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else class="">
{{ col.value }}
</div>
</q-td>
<q-td auto-width>
<q-btn
color="info"
flat
dense
round
size="14px"
icon="mdi-history"
@click="clickHistory(props.row)"
/>
</q-td>
</q-tr>
<q-tr :props="props" v-if="edit == true">
<q-td key="name" :props="props" v-if="props.row.name !== undefined">
<q-input
class=""
outlined
@update:model-value="clickEditRow"
v-model="props.row.name"
dense
lazy-rules
autofocus
hide-bottom-space
:rules="[
(val) => (val && val.length > 0) || 'กรุณากรอกข้อมูลให้ครบ',
(val) =>
checkDupDataName(val) || 'ชื่อซ้ำกันกับข้อมูลที่มีอยู่แล้ว',
]"
></q-input>
</q-td>
<q-td
key="createdAt"
:props="props"
v-if="props.row.createdAt !== undefined"
>
<div class="">
{{ textDate(props.row.createdAt) }}
</div>
</q-td>
<q-td key="lastUpdatedAt" :props="props">
<div class="">
{{ textDate(props.row.lastUpdatedAt) }}
</div>
</q-td>
<q-td
key="lastUpdateFullName"
:props="props"
v-if="props.row.lastUpdateFullName !== undefined"
class=""
>
{{ props.row.lastUpdateFullName }}
</q-td>
<q-td
key="isActive"
:props="props"
v-if="props.row.isActive !== undefined"
>
<q-toggle
v-model="props.row.isActive"
dense
color="green"
@update:model-value="clickEditRow"
/>
</q-td>
<q-td auto-width>
<q-btn
v-if="props.row.id === '00000000-0000-0000-0000-000000000000'"
color="red"
flat
dense
round
size="14px"
icon="mdi-trash-can-outline"
@click="clickDeleteRow(props.row)"
/>
<q-btn
v-if="props.row.id !== '00000000-0000-0000-0000-000000000000'"
color="info"
flat
dense
round
size="14px"
icon="mdi-history"
@click="clickHistory(props.row)"
/>
</q-td>
</q-tr>
</template>
</data-table>
</q-form>
</div>
<HistoryTable
:rows="rowsHistory"
:columns="columnsHistory"
:filter="filterHistory"
:visible-columns="visibleColumnsHistory"
v-model:modal="modalHistory"
v-model:inputfilter="filterHistory"
v-model:inputvisible="visibleColumnsHistory"
v-model:tittle="tittleHistory"
>
<template #columns="props">
<q-tr :props="props">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.name == 'isActive'" class="">
<q-icon
v-if="col.value == false"
name="mdi-close"
color="red"
class="text-h5"
/>
<q-icon v-else name="mdi-check" color="positive" class="text-h5" />
</div>
<div v-else-if="col.name == 'lastUpdatedAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else class="">
{{ col.value }}
</div>
</q-td>
</q-tr>
</template>
</HistoryTable>
</template>
<script setup lang="ts">
import type { QTableProps } from "quasar";
import { useQuasar } from "quasar";
import { onMounted, ref, watch } from "vue";
import http from "@/plugins/http";
import config from "@/app.config";
import keycloak from "@/plugins/keycloak";
import { useCounterMixin } from "@/stores/mixin";
import { useManageDataStore } from "@/modules/01_metadata/store";
import type {
RequestItemsHistoryObject,
RequestItemsPublishHistoryObject,
Columns,
} from "@/modules/01_metadata/interface/request/organization/Type";
import type { ResponseHistoryObject } from "@/modules/01_metadata/interface/response/organization/Type";
import HistoryTable from "@/components/TableHistory.vue";
import { useDataStore } from "@/stores/data";
const props = defineProps({
fetchDataComponent: {
type: Function,
default: () => console.log("not function"),
},
});
const dataStore = useDataStore();
const { loaderPage } = dataStore;
const mixin = useCounterMixin();
const { success, dateText, messageError } = mixin;
const store = useManageDataStore();
const { manageData, changeManageColumns } = store;
const rows = ref<RequestItemsHistoryObject[]>([]); //list data table
const rowsHistory = ref<RequestItemsHistoryObject[]>([]); //select data history
const rawHistory = ref<RequestItemsHistoryObject[]>([]); //raw data history
const tittleHistory = ref<string>("ประวัติแก้ไขประเภทของหน่วยงาน/ส่วนราชการ"); //
const myForm = ref<any>(null); //ref
const filter = ref<string>(""); //search data table
const filterHistory = ref<string>(""); //search data table history
const modalHistory = ref<boolean>(false); //modal
const edit = ref<boolean>(false); //
const idVersion = ref<string>(""); //id data mongodb
const version = ref<string>("published"); // published= draft=
const updateData = ref<boolean>(false); //
const checkValidate = ref<boolean>(false);
const columns = ref<QTableProps["columns"]>([
{
name: "name",
align: "left",
label: "ประเภทของหน่วยงาน/ส่วนราชการ",
sortable: true,
field: "name",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "createdAt",
align: "center",
label: "วันที่สร้าง",
sortable: true,
field: "createdAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdatedAt",
align: "center",
label: "วันที่แก้ไข",
sortable: true,
field: "lastUpdatedAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdateFullName",
align: "left",
label: "ผู้ดำเนินการ",
sortable: true,
field: "lastUpdateFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "isActive",
align: "left",
label: "สถานะ",
sortable: true,
field: "isActive",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumns = ref<String[]>([]);
manageData.organization.type.columns.length == 0
? (visibleColumns.value = [
"name",
"createdAt",
"lastUpdatedAt",
"lastUpdateFullName",
"isActive",
])
: (visibleColumns.value = manageData.organization.type.columns);
const columnsHistory = ref<QTableProps["columns"]>([
{
name: "name",
align: "left",
label: "ประเภทของหน่วยงาน/ส่วนราชการ",
sortable: true,
field: "name",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdatedAt",
align: "center",
label: "วันที่แก้ไข",
sortable: true,
field: "lastUpdatedAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdateFullName",
align: "left",
label: "ผู้ดำเนินการ",
sortable: true,
field: "lastUpdateFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "isActive",
align: "left",
label: "สถานะ",
sortable: true,
field: "isActive",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumnsHistory = ref<String[]>([
"name",
"lastUpdatedAt",
"lastUpdateFullName",
"isActive",
]);
/**
* เมอเขาหนานจะเรยกฟงชนนอน(get list data)
*/
onMounted(async () => {
await fetchData();
await fetchHistory();
});
watch(visibleColumns, async (count: String[], prevCount: String[]) => {
await changeManageColumns(2, "type", count);
});
/**
* แจงเตอนขอมลในกรณ success
*/
const $q = useQuasar();
/**
* งก get data าส
*/
const fetchData = async () => {
await props.fetchDataComponent();
rows.value.splice(0);
loaderPage(true);
await http
.get(config.API.listOrganizationTypeHistory)
.then((res) => {
let data = res.data.result;
version.value = data.version; // published= draft=
idVersion.value = data.id; // id mongodb
data.items.map((e: RequestItemsHistoryObject) => {
rows.value.push({
id: e.id,
name: e.name,
createdAt: e.createdAt,
lastUpdatedAt: e.lastUpdatedAt,
lastUpdateFullName: e.lastUpdateFullName,
isActive: e.isActive,
createdFullName: e.createdFullName,
createdUserId: e.createdUserId,
lastUpdateUserId: e.lastUpdateUserId,
});
});
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
updateData.value = false;
loaderPage(false);
});
};
/**
* งชนดอมลประวแกไขขอมลทงหมด
*/
const fetchHistory = async () => {
loaderPage(true);
await http
.get(config.API.listOrganizationTypePublishedHistory)
.then((res) => {
const data = res.data.result;
rawHistory.value = [];
if (data.length > 0) {
data.map((e: RequestItemsPublishHistoryObject) => {
e.items.map((i: RequestItemsHistoryObject) => {
rawHistory.value.push({
createdAt: i.createdAt,
createdFullName: i.createdFullName,
createdUserId: i.createdUserId,
id: i.id,
isActive: i.isActive,
lastUpdateFullName: i.lastUpdateFullName,
lastUpdateUserId: i.lastUpdateUserId,
lastUpdatedAt: i.lastUpdatedAt,
name: i.name,
});
});
});
}
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
loaderPage(false);
});
};
/**
* งก clear data แบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
*/
const clearPublishedData = async () => {
loaderPage(true);
await http
.delete(config.API.listOrganizationTypeHistory)
.then((res) => {
success($q, "ลบข้อมูลร่างสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchHistory();
await fetchData();
});
};
/**
* งกนเผยแพรแบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
*/
const publishedData = async () => {
loaderPage(true);
await http
.get(config.API.listOrganizationTypePublished)
.then((res) => {
success($q, "เผยแพร่ข้อมูลสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchData();
});
};
/**
* งกนเพมขอม
*/
const clickAdd = async () => {
const filterRowNull = rows.value.filter(
(f: RequestItemsHistoryObject) =>
f.id === "00000000-0000-0000-0000-000000000000" && f.name == "" // array
);
if (filterRowNull.length == 0) {
//
rows.value.push({
createdAt: new Date(),
createdFullName: "",
createdUserId: "",
id: "00000000-0000-0000-0000-000000000000",
isActive: true,
lastUpdateFullName:
keycloak.tokenParsed == null ? "" : keycloak.tokenParsed.name,
lastUpdateUserId: "",
lastUpdatedAt: new Date(),
name: "",
});
updateData.value = true;
}
};
/**
* งกนบนทกแบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
* publish เมอบนทกแบบรางแลวจะเผยแพรเลยไหม true=นทกและเผยแพร false=นทกอยางเดยว
*/
const save = async (publish: boolean) => {
await validateData();
if (checkValidate.value == false) return;
rows.value.map((e: ResponseHistoryObject) => ({
// data backend
id: e.id,
createdAt: e.createdAt,
lastUpdatedAt: e.lastUpdatedAt,
name: e.name,
isActive: e.isActive,
createdFullName: e.createdFullName,
createdUserId: e.createdUserId,
lastUpdateFullName: e.lastUpdateFullName,
lastUpdateUserId: e.lastUpdateUserId,
}));
loaderPage(true);
await http
.post(config.API.listOrganizationTypeHistoryId(idVersion.value), {
id: idVersion.value,
version: "draft",
items: rows.value,
})
.then(async (res) => {
if (publish === false) {
success($q, "บันทึกข้อมูลร่างสำเร็จ");
await fetchData(); // get data
} else {
await publishedData(); //
}
edit.value = false;
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
loaderPage(false);
});
};
/**
* เชคชอซำกบขอมลทอยแล
* @param val input
*/
const checkDupDataName = (val: string) => {
const filterNameNull = rows.value.filter(
(f: RequestItemsHistoryObject) => f.name == val
); //
if (filterNameNull.length > 1) {
return false;
}
return true;
};
/**
* งกนปมแกไข ให get data มาใหม
*/
const clickEdit = async () => {
await fetchData();
};
/**
* งกนปมบนทกแบบราง
*/
const clickSave = async () => {
await save(false);
};
/**
* งกนปมลบแบบราง
*/
const clickDelete = async () => {
await clearPublishedData();
};
/**
* งกนปมยกเลกการแกไขขอม
*/
const clickCancel = async () => {
edit.value = false;
await fetchData();
};
/**
* งกนปมเผยแพรอม
* เชคขอมลกอนวาใน array กรอกขอมลครบไหมถาครบกใหเผยแพรได
* าคาใน array ไมอมลใน row จะใหนทกได
*/
const clickPublish = async () => {
if (myForm.value !== null) {
myForm.value.validate().then(async (result: boolean) => {
if (result) {
await save(true);
}
});
} else {
await save(true);
}
};
/**
* งกนปมลบ row data
* @param val data ใน row จะลบ
*/
const clickDeleteRow = (val: RequestItemsHistoryObject) => {
rows.value = rows.value.filter((x: RequestItemsHistoryObject) => x !== val);
updateData.value = true;
};
/**
* งกนเช input ามการแกไขหรอย
*/
const clickEditRow = () => {
myForm.value.validate(false);
updateData.value = true;
};
/**
* งชนดอมลประวแกไขขอมลทเลอก
* @param row อม row ประวการแกไข
*/
const clickHistory = async (row: RequestItemsHistoryObject) => {
modalHistory.value = true;
rowsHistory.value = rawHistory.value.filter(
(f: RequestItemsHistoryObject) => f.id == row.id
);
};
/**
* งกนแปลง date เปนภาษาไทย
* @param value นท type datetime จะแปลงเปนไทย
*/
const textDate = (value: Date) => {
return dateText(value);
};
/**
* validate component
*/
const validateData = async () => {
checkValidate.value = true;
await myForm.value.validate().then((result: boolean) => {
if (result == false) {
checkValidate.value = false;
}
});
};
</script>
<style>
/* สีของnoti */
.my-notif-class {
background: rgba(33, 186, 69, 0.5) !important;
color: #008f17 !important;
}
</style>

View file

@ -0,0 +1,663 @@
<!-- tab กลมเลอด หนาจดการขอมลหล/อมลเกยวกบบคคล -->
<template>
<div>
<q-form ref="myForm">
<data-table
:rows="rows"
:columns="columns"
:filter="filter"
:visible-columns="visibleColumns"
v-model:inputfilter="filter"
v-model:inputvisible="visibleColumns"
v-model:editvisible="edit"
:add="clickAdd"
:edit="clickEdit"
:save="clickSave"
:deleted="clickDelete"
:cancel="clickCancel"
:publish="clickPublish"
:validate="validateData"
:publicData="version === 'published'"
:updateData="updateData"
:history="true"
>
<template #columns="props">
<q-tr :props="props" v-if="edit == false">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.name == 'isActive'" class="">
<q-icon
v-if="col.value == false"
name="mdi-close"
color="red"
class="text-h5"
/>
<q-icon
v-else
name="mdi-check"
color="positive"
class="text-h5"
/>
</div>
<div v-else-if="col.name == 'createdAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else-if="col.name == 'lastUpdatedAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else class="">
{{ col.value }}
</div>
</q-td>
<q-td auto-width>
<q-btn
color="info"
flat
dense
round
size="14px"
icon="mdi-history"
@click="clickHistory(props.row)"
/>
</q-td>
</q-tr>
<q-tr :props="props" v-if="edit == true" class="items-center">
<q-td key="name" :props="props" v-if="props.row.name !== undefined">
<q-input
outlined
@update:model-value="clickEditRow"
v-model="props.row.name"
dense
lazy-rules
autofocus
hide-bottom-space
:rules="[
(val) => (val && val.length > 0) || 'กรุณากรอกข้อมูลให้ครบ',
(val) =>
checkDupDataName(val) || 'ชื่อซ้ำกันกับข้อมูลที่มีอยู่แล้ว',
]"
counter
maxlength="2"
>
<template v-slot:hint> วอกษร </template></q-input
>
</q-td>
<q-td
key="createdAt"
:props="props"
v-if="props.row.createdAt !== undefined"
>
<div class="">
{{ textDate(props.row.createdAt) }}
</div>
</q-td>
<q-td key="lastUpdatedAt" :props="props">
<div class="">
{{ textDate(props.row.lastUpdatedAt) }}
</div>
</q-td>
<q-td
key="lastUpdateFullName"
:props="props"
v-if="props.row.lastUpdateFullName !== undefined"
class=""
>
{{ props.row.lastUpdateFullName }}
</q-td>
<q-td
key="isActive"
:props="props"
v-if="props.row.isActive !== undefined"
>
<q-toggle
v-model="props.row.isActive"
dense
size="34px"
color="positive"
@update:model-value="clickEditRow"
/>
</q-td>
<q-td auto-width>
<q-btn
v-if="props.row.id === '00000000-0000-0000-0000-000000000000'"
color="red"
flat
dense
round
size="14px"
icon="mdi-trash-can-outline"
@click="clickDeleteRow(props.row)"
/>
<q-btn
v-if="props.row.id !== '00000000-0000-0000-0000-000000000000'"
color="info"
flat
dense
round
size="14px"
icon="mdi-history"
@click="clickHistory(props.row)"
/>
</q-td>
</q-tr>
</template>
</data-table>
</q-form>
</div>
<HistoryTable
:rows="rowsHistory"
:columns="columnsHistory"
:filter="filterHistory"
:visible-columns="visibleColumnsHistory"
v-model:modal="modalHistory"
v-model:inputfilter="filterHistory"
v-model:inputvisible="visibleColumnsHistory"
v-model:tittle="tittleHistory"
>
<template #columns="props">
<q-tr :props="props">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.name == 'isActive'" class="">
<q-icon
v-if="col.value == false"
name="mdi-close"
color="red"
class="text-h5"
/>
<q-icon v-else name="mdi-check" color="positive" class="text-h5" />
</div>
<div v-else-if="col.name == 'lastUpdatedAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else class="">
{{ col.value }}
</div>
</q-td>
</q-tr>
</template>
</HistoryTable>
</template>
<script setup lang="ts">
import type { QTableProps } from "quasar";
import { useQuasar } from "quasar";
import { onMounted, ref, watch } from "vue";
import http from "@/plugins/http";
import config from "@/app.config";
import keycloak from "@/plugins/keycloak";
import { useCounterMixin } from "@/stores/mixin";
import { useManageDataStore } from "@/modules/01_metadata/store";
import type {
RequestItemsHistoryObject,
RequestItemsPublishHistoryObject,
Columns,
} from "@/modules/01_metadata/interface/request/person/Blood";
import type { ResponseHistoryObject } from "@/modules/01_metadata/interface/response/person/Blood";
import HistoryTable from "@/components/TableHistory.vue";
import { useDataStore } from "@/stores/data";
const props = defineProps({
fetchDataComponent: {
type: Function,
default: () => console.log("not function"),
},
});
const dataStore = useDataStore();
const { loaderPage } = dataStore;
const mixin = useCounterMixin();
const { success, dateText, messageError } = mixin;
const store = useManageDataStore();
const { manageData, changeManageColumns } = store;
const rows = ref<RequestItemsHistoryObject[]>([]); //list data table
const rowsHistory = ref<RequestItemsHistoryObject[]>([]); //select data history
const rawHistory = ref<RequestItemsHistoryObject[]>([]); //raw data history
const tittleHistory = ref<string>("ประวัติแก้ไขกลุ่มเลือด"); //
const myForm = ref<any>(null); //ref
const filter = ref<string>(""); //search data table
const filterHistory = ref<string>(""); //search data table history
const modalHistory = ref<boolean>(false); //modal
const edit = ref<boolean>(false); //
const idVersion = ref<string>(""); //id data mongodb
const version = ref<string>("published"); // published= draft=
const updateData = ref<boolean>(false); //
const checkValidate = ref<boolean>(false);
const columns = ref<QTableProps["columns"]>([
{
name: "name",
align: "left",
label: "กลุ่มเลือด",
sortable: true,
field: "name",
headerStyle: "font-size: 14px;",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "createdAt",
align: "center",
label: "วันที่สร้าง",
sortable: true,
field: "createdAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdatedAt",
align: "center",
label: "วันที่แก้ไข",
sortable: true,
field: "lastUpdatedAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdateFullName",
align: "left",
label: "ผู้ดำเนินการ",
sortable: true,
field: "lastUpdateFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "isActive",
align: "left",
label: "สถานะ",
sortable: true,
field: "isActive",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumns = ref<String[]>([]);
manageData.person.blood.columns.length == 0
? (visibleColumns.value = [
"name",
"createdAt",
"lastUpdatedAt",
"lastUpdateFullName",
"isActive",
])
: (visibleColumns.value = manageData.person.blood.columns);
const columnsHistory = ref<QTableProps["columns"]>([
{
name: "name",
align: "left",
label: "กลุ่มเลือด",
sortable: true,
field: "name",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdatedAt",
align: "center",
label: "วันที่แก้ไข",
sortable: true,
field: "lastUpdatedAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdateFullName",
align: "left",
label: "ผู้ดำเนินการ",
sortable: true,
field: "lastUpdateFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "isActive",
align: "left",
label: "สถานะ",
sortable: true,
field: "isActive",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumnsHistory = ref<String[]>([
"name",
"lastUpdatedAt",
"lastUpdateFullName",
"isActive",
]);
/**
* เมอเขาหนานจะเรยกฟงชนนอน(get list data)
*/
onMounted(async () => {
await fetchData();
await fetchHistory();
});
watch(visibleColumns, async (count: String[], prevCount: String[]) => {
await changeManageColumns(1, "blood", count);
});
/**
* แจงเตอนขอมลในกรณ success
*/
const $q = useQuasar();
/**
* งก get data าส
*/
const fetchData = async () => {
await props.fetchDataComponent();
rows.value.splice(0);
loaderPage(true);
await http
.get(config.API.listBloodGroupHistory)
.then((res) => {
let data = res.data.result;
version.value = data.version; // published= draft=
idVersion.value = data.id; // id mongodb
data.items.map((e: RequestItemsHistoryObject) => {
rows.value.push({
id: e.id,
name: e.name,
createdAt: e.createdAt,
lastUpdatedAt: e.lastUpdatedAt,
lastUpdateFullName: e.lastUpdateFullName,
isActive: e.isActive,
createdFullName: e.createdFullName,
createdUserId: e.createdUserId,
lastUpdateUserId: e.lastUpdateUserId,
});
});
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
updateData.value = false;
loaderPage(false);
});
};
/**
* งชนดอมลประวแกไขขอมลทงหมด
*/
const fetchHistory = async () => {
loaderPage(true);
await http
.get(config.API.listBloodGroupPublishedHistory)
.then((res) => {
const data = res.data.result;
rawHistory.value = [];
if (data.length > 0) {
data.map((e: RequestItemsPublishHistoryObject) => {
e.items.map((i: RequestItemsHistoryObject) => {
rawHistory.value.push({
createdAt: i.createdAt,
createdFullName: i.createdFullName,
createdUserId: i.createdUserId,
id: i.id,
isActive: i.isActive,
lastUpdateFullName: i.lastUpdateFullName,
lastUpdateUserId: i.lastUpdateUserId,
lastUpdatedAt: i.lastUpdatedAt,
name: i.name,
});
});
});
}
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
loaderPage(false);
});
};
/**
* งก clear data แบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
*/
const clearPublishedData = async () => {
loaderPage(true);
await http
.delete(config.API.listBloodGroupHistory)
.then((res) => {
success($q, "ลบข้อมูลร่างสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchHistory();
await fetchData();
});
};
/**
* งกนเผยแพรแบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
*/
const publishedData = async () => {
loaderPage(true);
await http
.get(config.API.listBloodGroupPublished)
.then((res) => {
success($q, "เผยแพร่ข้อมูลสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchData();
});
};
/**
* งกนเพมขอม
*/
const clickAdd = async () => {
const filterRowNull = rows.value.filter(
(f: RequestItemsHistoryObject) =>
f.id === "00000000-0000-0000-0000-000000000000" && f.name == "" // array
);
if (filterRowNull.length == 0) {
//
rows.value.push({
createdAt: new Date(),
createdFullName: "",
createdUserId: "",
id: "00000000-0000-0000-0000-000000000000",
isActive: true,
lastUpdateFullName:
keycloak.tokenParsed == null ? "" : keycloak.tokenParsed.name,
lastUpdateUserId: "",
lastUpdatedAt: new Date(),
name: "",
});
updateData.value = true;
}
};
/**
* งกนบนทกแบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
* publish เมอบนทกแบบรางแลวจะเผยแพรเลยไหม true=นทกและเผยแพร false=นทกอยางเดยว
*/
const save = async (publish: boolean) => {
await validateData();
if (checkValidate.value == false) return;
rows.value.map((e: ResponseHistoryObject) => ({
// data backend
id: e.id,
createdAt: e.createdAt,
lastUpdatedAt: e.lastUpdatedAt,
name: e.name,
isActive: e.isActive,
createdFullName: e.createdFullName,
createdUserId: e.createdUserId,
lastUpdateFullName: e.lastUpdateFullName,
lastUpdateUserId: e.lastUpdateUserId,
}));
loaderPage(true);
await http
.post(config.API.listBloodGroupHistoryId(idVersion.value), {
id: idVersion.value,
version: "draft",
items: rows.value,
})
.then(async (res) => {
if (publish === false) {
success($q, "บันทึกข้อมูลร่างสำเร็จ");
await fetchData(); // get data
} else {
await publishedData(); //
}
edit.value = false;
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
loaderPage(false);
});
};
/**
* เชคชอซำกบขอมลทอยแล
* @param val input
*/
const checkDupDataName = (val: string) => {
const filterNameNull = rows.value.filter(
(f: RequestItemsHistoryObject) => f.name == val
); //
if (filterNameNull.length > 1) {
return false;
}
return true;
};
/**
* งกนปมแกไข ให get data มาใหม
*/
const clickEdit = async () => {
await fetchData();
};
/**
* งกนปมบนทกแบบราง
*/
const clickSave = async () => {
await save(false);
};
/**
* งกนปมลบแบบราง
*/
const clickDelete = async () => {
await clearPublishedData();
};
/**
* งกนปมยกเลกการแกไขขอม
*/
const clickCancel = async () => {
edit.value = false;
await fetchData();
};
/**
* งกนปมเผยแพรอม
* เชคขอมลกอนวาใน array กรอกขอมลครบไหมถาครบกใหเผยแพรได
* าคาใน array ไมอมลใน row จะใหนทกได
*/
const clickPublish = async () => {
if (myForm.value !== null) {
myForm.value.validate().then(async (result: boolean) => {
if (result) {
await save(true);
}
});
} else {
await save(true);
}
};
/**
* งกนปมลบ row data
* @param val data ใน row จะลบ
*/
const clickDeleteRow = (val: RequestItemsHistoryObject) => {
rows.value = rows.value.filter((x: RequestItemsHistoryObject) => x !== val);
updateData.value = true;
};
/**
* งกนเช input ามการแกไขหรอย
*/
const clickEditRow = () => {
myForm.value.validate(false);
updateData.value = true;
};
/**
* งชนดอมลประวแกไขขอมลทเลอก
* @param row อม row ประวการแกไข
*/
const clickHistory = async (row: RequestItemsHistoryObject) => {
modalHistory.value = true;
rowsHistory.value = rawHistory.value.filter(
(f: RequestItemsHistoryObject) => f.id == row.id
);
};
/**
* งกนแปลง date เปนภาษาไทย
* @param value นท type datetime จะแปลงเปนไทย
*/
const textDate = (value: Date) => {
return dateText(value);
};
/**
* validate component
*/
const validateData = async () => {
checkValidate.value = true;
await myForm.value.validate().then((result: boolean) => {
if (result == false) {
checkValidate.value = false;
}
});
};
</script>
<style>
/* สีของnoti */
.my-notif-class {
background: rgba(33, 186, 69, 0.5) !important;
color: #008f17 !important;
}
</style>

View file

@ -0,0 +1,715 @@
<!-- tab เขต/อำเภอ หนาจดการขอมลหล/อมลเกยวกบบคคล -->
<template>
<div class="row items-center q-mb-sm q-mr-md q-ml-sm">
<q-btn icon="chevron_left" color="grey" flat dense @click="goToManage()">
<q-tooltip>กล</q-tooltip>
</q-btn>
<div class="text-body1 text-weight-bold">การจดการขอมลเขต</div>
<q-space />
<div @click="goToManage()" class="cursor-pointer">
การจดการขอมลจงหว
<span class="text-primary text-weight-bold"> {{ provinceName }}</span>
</div>
</div>
<q-form ref="myForm">
<q-card flat bordered class="q-pa-md row col-12">
<div class="col-xs-12">
<div class="q-mt-md">
<data-table
:rows="rows"
:columns="columns"
:filter="filter"
:visible-columns="visibleColumns"
v-model:inputfilter="filter"
v-model:inputvisible="visibleColumns"
v-model:editvisible="edit"
:add="clickAdd"
:edit="clickEdit"
:save="clickSave"
:deleted="clickDelete"
:cancel="clickCancel"
:publish="clickPublish"
:validate="validateData"
:publicData="version === 'published'"
:updateData="updateData"
:nextPageVisible="true"
:history="true"
>
<template #columns="props">
<q-tr :props="props" v-if="edit == false">
<q-td
v-for="col in props.cols"
:key="col.name"
:props="props"
@click="clickRow(props.row.id)"
>
<div v-if="col.name == 'isActive'" class="">
<q-icon
v-if="col.value == false"
name="mdi-close"
color="red"
class="text-h5"
/>
<q-icon
v-else
name="mdi-check"
color="positive"
class="text-h5"
/>
</div>
<div v-else-if="col.name == 'createdAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else-if="col.name == 'lastUpdatedAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else class="">
{{ col.value }}
</div>
</q-td>
<q-td auto-width>
<q-btn
color="info"
flat
dense
round
size="14px"
icon="mdi-history"
@click="clickHistory(props.row)"
/>
<q-icon
size="30px"
color="grey-8"
name="chevron_right"
@click="clickRow(props.row.id)"
/>
</q-td>
</q-tr>
<q-tr :props="props" v-if="edit == true">
<q-td
key="name"
:props="props"
v-if="props.row.name !== undefined"
>
<q-input
class=""
outlined
@update:model-value="clickEditRow"
v-model="props.row.name"
dense
lazy-rules
autofocus
hide-bottom-space
:rules="[
(val) =>
(val && val.length > 0) || 'กรุณากรอกข้อมูลให้ครบ',
(val) =>
checkDupDataName(val) ||
'ชื่อซ้ำกันกับข้อมูลที่มีอยู่แล้ว',
]"
></q-input>
</q-td>
<q-td
key="createdAt"
:props="props"
v-if="props.row.createdAt !== undefined"
>
<div class="">
{{ textDate(props.row.createdAt) }}
</div>
</q-td>
<q-td key="lastUpdatedAt" :props="props">
<div class="">
{{ textDate(props.row.lastUpdatedAt) }}
</div>
</q-td>
<q-td
key="lastUpdateFullName"
:props="props"
v-if="props.row.lastUpdateFullName !== undefined"
class=""
>
{{ props.row.lastUpdateFullName }}
</q-td>
<q-td
key="isActive"
:props="props"
v-if="props.row.isActive !== undefined"
>
<q-toggle
v-model="props.row.isActive"
dense
color="green"
@update:model-value="clickEditRow"
/>
</q-td>
<q-td auto-width>
<q-btn
v-if="
props.row.id === '00000000-0000-0000-0000-000000000000'
"
color="red"
flat
dense
round
size="14px"
icon="mdi-trash-can-outline"
@click="clickDeleteRow(props.row)"
/>
<q-btn
v-if="
props.row.id !== '00000000-0000-0000-0000-000000000000'
"
color="info"
flat
dense
round
size="14px"
icon="mdi-history"
@click="clickHistory(props.row)"
/>
</q-td>
</q-tr>
</template>
</data-table>
</div>
</div>
</q-card>
</q-form>
<HistoryTable
:rows="rowsHistory"
:columns="columnsHistory"
:filter="filterHistory"
:visible-columns="visibleColumnsHistory"
v-model:modal="modalHistory"
v-model:inputfilter="filterHistory"
v-model:inputvisible="visibleColumnsHistory"
v-model:tittle="tittleHistory"
>
<template #columns="props">
<q-tr :props="props">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.name == 'isActive'" class="">
<q-icon
v-if="col.value == false"
name="mdi-close"
color="red"
class="text-h5"
/>
<q-icon v-else name="mdi-check" color="positive" class="text-h5" />
</div>
<div v-else-if="col.name == 'lastUpdatedAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else class="">
{{ col.value }}
</div>
</q-td>
</q-tr>
</template>
</HistoryTable>
</template>
<script setup lang="ts">
import type { QTableProps } from "quasar";
import { useQuasar } from "quasar";
import { onMounted, ref, watch } from "vue";
import http from "@/plugins/http";
import config from "@/app.config";
import keycloak from "@/plugins/keycloak";
import { useCounterMixin } from "@/stores/mixin";
import { useManageDataStore } from "@/modules/01_metadata/store";
import type {
RequestItemsHistoryObject,
RequestItemsPublishHistoryObject,
Columns,
} from "@/modules/01_metadata/interface/request/person/District";
import type { ResponseHistoryObject } from "@/modules/01_metadata/interface/response/person/District";
import HistoryTable from "@/components/TableHistory.vue";
import { useRoute, useRouter } from "vue-router";
import { useDataStore } from "@/stores/data";
const mixin = useCounterMixin();
const { success, dateText, messageError } = mixin;
const store = useManageDataStore();
const dataStore = useDataStore();
const { manageData, changeManageColumns, changeManageCurrentTab } = store;
const { loaderPage } = dataStore; // load api
const rows = ref<RequestItemsHistoryObject[]>([]); //list data table
const rowsHistory = ref<RequestItemsHistoryObject[]>([]); //select data history
const rawHistory = ref<RequestItemsHistoryObject[]>([]); //raw data history
const tittleHistory = ref<string>("ประวัติแก้ไขเขต/อำเภอ"); //
const myForm = ref<any>(null); //ref
const filter = ref<string>(""); //search data table
const filterHistory = ref<string>(""); //search data table history
const modalHistory = ref<boolean>(false); //modal
const edit = ref<boolean>(false); //
const idVersion = ref<string>(""); //id data mongodb
const version = ref<string>("published"); // published= draft=
const updateData = ref<boolean>(false); //
const router = useRouter();
const route = useRoute();
const provinceName = ref<string>("กรุงเทพมหานคร"); //
const provinceId = ref<string | string[]>(route.params.province); // Id
const checkValidate = ref<boolean>(false);
const columns = ref<QTableProps["columns"]>([
{
name: "name",
align: "left",
label: "เขต/อำเภอ",
sortable: true,
field: "name",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "createdAt",
align: "center",
label: "วันที่สร้าง",
sortable: true,
field: "createdAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdatedAt",
align: "center",
label: "วันที่แก้ไข",
sortable: true,
field: "lastUpdatedAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdateFullName",
align: "left",
label: "ผู้ดำเนินการ",
sortable: true,
field: "lastUpdateFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "isActive",
align: "left",
label: "สถานะ",
sortable: true,
field: "isActive",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumns = ref<String[]>([]);
manageData.person.district.columns.length == 0
? (visibleColumns.value = [
"name",
"createdAt",
"lastUpdatedAt",
"lastUpdateFullName",
"isActive",
])
: (visibleColumns.value = manageData.person.district.columns);
const columnsHistory = ref<QTableProps["columns"]>([
{
name: "name",
align: "left",
label: "เขต/อำเภอ",
sortable: true,
field: "name",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdatedAt",
align: "center",
label: "วันที่แก้ไข",
sortable: true,
field: "lastUpdatedAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdateFullName",
align: "left",
label: "ผู้ดำเนินการ",
sortable: true,
field: "lastUpdateFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "isActive",
align: "left",
label: "สถานะ",
sortable: true,
field: "isActive",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumnsHistory = ref<String[]>([
"name",
"lastUpdatedAt",
"lastUpdateFullName",
"isActive",
]);
/**
* เมอเขาหนานจะเรยกฟงชนนอน(get list data)
*/
onMounted(async () => {
await fetchData();
await fetchHistory();
});
watch(visibleColumns, async (count: String[], prevCount: String[]) => {
await changeManageColumns(1, "district", count);
});
/**
* แจงเตอนขอมลในกรณ success
*/
const $q = useQuasar();
/**
* งก get data าส
*/
const fetchData = async () => {
rows.value.splice(0);
loaderPage(true);
await http
.get(config.API.listDistrictHistoryId(provinceId.value))
.then((res) => {
let data = res.data.result;
version.value = data.version; // published= draft=
idVersion.value = data.id; // id mongodb
provinceName.value = data.provinceName.result;
data.items.map((e: RequestItemsHistoryObject) => {
rows.value.push({
id: e.id,
name: e.name,
createdAt: e.createdAt,
lastUpdatedAt: e.lastUpdatedAt,
lastUpdateFullName: e.lastUpdateFullName,
isActive: e.isActive,
createdFullName: e.createdFullName,
createdUserId: e.createdUserId,
lastUpdateUserId: e.lastUpdateUserId,
});
});
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
updateData.value = false;
loaderPage(false);
});
};
/**
* งชนดอมลประวแกไขขอมลทงหมด
*/
const fetchHistory = async () => {
loaderPage(true);
await http
.get(config.API.listDistrictPublishedHistory(provinceId.value))
.then((res) => {
const data = res.data.result;
rawHistory.value = [];
if (data.length > 0) {
data.map((e: RequestItemsPublishHistoryObject) => {
e.items.map((i: RequestItemsHistoryObject) => {
rawHistory.value.push({
createdAt: i.createdAt,
createdFullName: i.createdFullName,
createdUserId: i.createdUserId,
id: i.id,
isActive: i.isActive,
lastUpdateFullName: i.lastUpdateFullName,
lastUpdateUserId: i.lastUpdateUserId,
lastUpdatedAt: i.lastUpdatedAt,
name: i.name,
});
});
});
}
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
loaderPage(false);
});
};
/**
* งก clear data แบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
*/
const clearPublishedData = async () => {
loaderPage(true);
await http
.delete(config.API.listDistrictHistoryId(provinceId.value))
.then((res) => {
success($q, "ลบข้อมูลร่างสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchHistory();
await fetchData();
});
};
/**
* งกนเผยแพรแบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
*/
const publishedData = async () => {
loaderPage(true);
await http
.get(config.API.listProvincePublished)
.then((res) => {
success($q, "เผยแพร่ข้อมูลสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchData();
});
};
/**
* งกนเพมขอม
*/
const clickAdd = async () => {
const filterRowNull = rows.value.filter(
(f: RequestItemsHistoryObject) =>
f.id === "00000000-0000-0000-0000-000000000000" && f.name == "" // array
);
if (filterRowNull.length == 0) {
//
rows.value.push({
createdAt: new Date(),
createdFullName: "",
createdUserId: "",
id: "00000000-0000-0000-0000-000000000000",
isActive: true,
lastUpdateFullName:
keycloak.tokenParsed == null ? "" : keycloak.tokenParsed.name,
lastUpdateUserId: "",
lastUpdatedAt: new Date(),
name: "",
});
updateData.value = true;
}
};
/**
* งกนบนทกแบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
* publish เมอบนทกแบบรางแลวจะเผยแพรเลยไหม true=นทกและเผยแพร false=นทกอยางเดยว
*/
const save = async (publish: boolean) => {
await validateData();
if (checkValidate.value == false) return;
rows.value.map((e: ResponseHistoryObject) => ({
// data backend
id: e.id,
createdAt: e.createdAt,
lastUpdatedAt: e.lastUpdatedAt,
name: e.name,
isActive: e.isActive,
createdFullName: e.createdFullName,
createdUserId: e.createdUserId,
lastUpdateFullName: e.lastUpdateFullName,
lastUpdateUserId: e.lastUpdateUserId,
}));
loaderPage(true);
await http
.post(config.API.listDistrictHistoryId(idVersion.value), {
id: idVersion.value,
provinceId: provinceId.value,
version: "draft",
items: rows.value,
})
.then(async (res) => {
if (publish === false) {
success($q, "บันทึกข้อมูลร่างสำเร็จ");
await fetchData(); // get data
} else {
await publishedData(); //
}
edit.value = false;
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
loaderPage(false);
});
};
/**
* เชคชอซำกบขอมลทอยแล
* @param val input
*/
const checkDupDataName = (val: string) => {
const filterNameNull = rows.value.filter(
(f: RequestItemsHistoryObject) => f.name == val
); //
if (filterNameNull.length > 1) {
return false;
}
return true;
};
/**
* งกนปมแกไข ให get data มาใหม
*/
const clickEdit = async () => {
await fetchData();
};
/**
* งกนปมบนทกแบบราง
*/
const clickSave = async () => {
await save(false);
};
/**
* งกนปมลบแบบราง
*/
const clickDelete = async () => {
await clearPublishedData();
};
/**
* งกนปมยกเลกการแกไขขอม
*/
const clickCancel = async () => {
edit.value = false;
await fetchData();
};
/**
* งกนปมเผยแพรอม
* เชคขอมลกอนวาใน array กรอกขอมลครบไหมถาครบกใหเผยแพรได
* าคาใน array ไมอมลใน row จะใหนทกได
*/
const clickPublish = async () => {
if (myForm.value !== null) {
myForm.value.validate().then(async (result: boolean) => {
if (result) {
await save(true);
}
});
} else {
await save(true);
}
};
/**
* งกนปมลบ row data
* @param val data ใน row จะลบ
*/
const clickDeleteRow = (val: RequestItemsHistoryObject) => {
rows.value = rows.value.filter((x: RequestItemsHistoryObject) => x !== val);
updateData.value = true;
};
/**
* งกนเช input ามการแกไขหรอย
*/
const clickEditRow = () => {
myForm.value.validate(false);
updateData.value = true;
};
/**
* งชนดอมลประวแกไขขอมลทเลอก
* @param row อม row ประวการแกไข
*/
const clickHistory = async (row: RequestItemsHistoryObject) => {
modalHistory.value = true;
rowsHistory.value = rawHistory.value.filter(
(f: RequestItemsHistoryObject) => f.id == row.id
);
};
/**
* งกนแปลง date เปนภาษาไทย
* @param value นท type datetime จะแปลงเปนไทย
*/
const textDate = (value: Date) => {
return dateText(value);
};
/**
* validate component
*/
const validateData = async () => {
checkValidate.value = true;
await myForm.value.validate().then((result: boolean) => {
if (result == false) {
checkValidate.value = false;
}
});
};
/**
* งกนกดเลอก row ไหนจะเปลยนหนาไปหาเขตทงหมดในจงหวดทกดเลอก
*/
const clickRow = (val: string) => {
router.push(`/metadata/province/${provinceId.value}/${val}`);
};
/**
* งกนยอนกลบไปหนาจดการขอมลหล
*/
const goToManage = async () => {
await changeManageCurrentTab(1, "person_province");
router.push("/metadata");
};
</script>
<style>
/* สีของnoti */
.my-notif-class {
background: rgba(33, 186, 69, 0.5) !important;
color: #008f17 !important;
}
</style>

View file

@ -0,0 +1,660 @@
<!-- tab ระดบการศกษา หนาจดการขอมลหล/อมลเกยวกบบคคล -->
<template>
<div>
<q-form ref="myForm">
<data-table
:rows="rows"
:columns="columns"
:filter="filter"
:visible-columns="visibleColumns"
v-model:inputfilter="filter"
v-model:inputvisible="visibleColumns"
v-model:editvisible="edit"
:add="clickAdd"
:edit="clickEdit"
:save="clickSave"
:deleted="clickDelete"
:cancel="clickCancel"
:publish="clickPublish"
:validate="validateData"
:publicData="version === 'published'"
:updateData="updateData"
:history="true"
>
<template #columns="props">
<q-tr :props="props" v-if="edit == false">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.name == 'isActive'" class="">
<q-icon
v-if="col.value == false"
name="mdi-close"
color="red"
class="text-h5"
/>
<q-icon
v-else
name="mdi-check"
color="positive"
class="text-h5"
/>
</div>
<div v-else-if="col.name == 'createdAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else-if="col.name == 'lastUpdatedAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else class="">
{{ col.value }}
</div>
</q-td>
<q-td auto-width>
<q-btn
color="info"
flat
dense
round
size="14px"
icon="mdi-history"
@click="clickHistory(props.row)"
/>
</q-td>
</q-tr>
<q-tr :props="props" v-if="edit == true" class="items-center">
<q-td key="name" :props="props" v-if="props.row.name !== undefined">
<q-input
class=""
outlined
@update:model-value="clickEditRow"
v-model="props.row.name"
dense
lazy-rules
autofocus
hide-bottom-space
:rules="[
(val) => (val && val.length > 0) || 'กรุณากรอกข้อมูลให้ครบ',
(val) =>
checkDupDataName(val) || 'ชื่อซ้ำกันกับข้อมูลที่มีอยู่แล้ว',
]"
></q-input>
</q-td>
<q-td
key="createdAt"
:props="props"
v-if="props.row.createdAt !== undefined"
>
<div class="">
{{ textDate(props.row.createdAt) }}
</div>
</q-td>
<q-td key="lastUpdatedAt" :props="props">
<div class="">
{{ textDate(props.row.lastUpdatedAt) }}
</div>
</q-td>
<q-td
key="lastUpdateFullName"
:props="props"
v-if="props.row.lastUpdateFullName !== undefined"
class=""
>
{{ props.row.lastUpdateFullName }}
</q-td>
<q-td
key="isActive"
:props="props"
v-if="props.row.isActive !== undefined"
>
<q-toggle
v-model="props.row.isActive"
dense
size="34px"
color="positive"
@update:model-value="clickEditRow"
/>
</q-td>
<q-td auto-width>
<q-btn
v-if="props.row.id === '00000000-0000-0000-0000-000000000000'"
color="red"
flat
dense
round
size="14px"
icon="mdi-trash-can-outline"
@click="clickDeleteRow(props.row)"
/>
<q-btn
v-if="props.row.id !== '00000000-0000-0000-0000-000000000000'"
color="info"
flat
dense
round
size="14px"
icon="mdi-history"
@click="clickHistory(props.row)"
/>
</q-td>
</q-tr>
</template>
</data-table>
</q-form>
</div>
<HistoryTable
:rows="rowsHistory"
:columns="columnsHistory"
:filter="filterHistory"
:visible-columns="visibleColumnsHistory"
v-model:modal="modalHistory"
v-model:inputfilter="filterHistory"
v-model:inputvisible="visibleColumnsHistory"
v-model:tittle="tittleHistory"
>
<template #columns="props">
<q-tr :props="props">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.name == 'isActive'" class="">
<q-icon
v-if="col.value == false"
name="mdi-close"
color="red"
class="text-h5"
/>
<q-icon v-else name="mdi-check" color="positive" class="text-h5" />
</div>
<div v-else-if="col.name == 'lastUpdatedAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else class="">
{{ col.value }}
</div>
</q-td>
</q-tr>
</template>
</HistoryTable>
</template>
<script setup lang="ts">
import type { QTableProps } from "quasar";
import { useQuasar } from "quasar";
import { onMounted, ref, watch } from "vue";
import http from "@/plugins/http";
import config from "@/app.config";
import keycloak from "@/plugins/keycloak";
import { useCounterMixin } from "@/stores/mixin";
import { useManageDataStore } from "@/modules/01_metadata/store";
import type {
RequestItemsHistoryObject,
RequestItemsPublishHistoryObject,
Columns,
} from "@/modules/01_metadata/interface/request/person/Education";
import type { ResponseHistoryObject } from "@/modules/01_metadata/interface/response/person/Education";
import HistoryTable from "@/components/TableHistory.vue";
import { useDataStore } from "@/stores/data";
const props = defineProps({
fetchDataComponent: {
type: Function,
default: () => console.log("not function"),
},
});
const dataStore = useDataStore();
const { loaderPage } = dataStore;
const mixin = useCounterMixin();
const { success, dateText, messageError } = mixin;
const store = useManageDataStore();
const { manageData, changeManageColumns } = store;
const rows = ref<RequestItemsHistoryObject[]>([]); //list data table
const rowsHistory = ref<RequestItemsHistoryObject[]>([]); //select data history
const rawHistory = ref<RequestItemsHistoryObject[]>([]); //raw data history
const tittleHistory = ref<string>("ประวัติแก้ไขระดับการศึกษา"); //
const myForm = ref<any>(null); //ref
const filter = ref<string>(""); //search data table
const filterHistory = ref<string>(""); //search data table history
const modalHistory = ref<boolean>(false); //modal
const edit = ref<boolean>(false); //
const idVersion = ref<string>(""); //id data mongodb
const version = ref<string>("published"); // published= draft=
const updateData = ref<boolean>(false); //
const checkValidate = ref<boolean>(false);
const columns = ref<QTableProps["columns"]>([
{
name: "name",
align: "left",
label: "ระดับการศึกษา",
sortable: true,
field: "name",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "createdAt",
align: "center",
label: "วันที่สร้าง",
sortable: true,
field: "createdAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdatedAt",
align: "center",
label: "วันที่แก้ไข",
sortable: true,
field: "lastUpdatedAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdateFullName",
align: "left",
label: "ผู้ดำเนินการ",
sortable: true,
field: "lastUpdateFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "isActive",
align: "left",
label: "สถานะ",
sortable: true,
field: "isActive",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumns = ref<String[]>([]);
manageData.person.education.columns.length == 0
? (visibleColumns.value = [
"name",
"createdAt",
"lastUpdatedAt",
"lastUpdateFullName",
"isActive",
])
: (visibleColumns.value = manageData.person.education.columns);
const columnsHistory = ref<QTableProps["columns"]>([
{
name: "name",
align: "left",
label: "ระดับการศึกษา",
sortable: true,
field: "name",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdatedAt",
align: "center",
label: "วันที่แก้ไข",
sortable: true,
field: "lastUpdatedAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdateFullName",
align: "left",
label: "ผู้ดำเนินการ",
sortable: true,
field: "lastUpdateFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "isActive",
align: "left",
label: "สถานะ",
sortable: true,
field: "isActive",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumnsHistory = ref<String[]>([
"name",
"lastUpdatedAt",
"lastUpdateFullName",
"isActive",
]);
/**
* เมอเขาหนานจะเรยกฟงชนนอน(get list data)
*/
onMounted(async () => {
await fetchData();
await fetchHistory();
});
watch(visibleColumns, async (count: String[], prevCount: String[]) => {
await changeManageColumns(1, "education", count);
});
/**
* แจงเตอนขอมลในกรณ success
*/
const $q = useQuasar();
/**
* งก get data าส
*/
const fetchData = async () => {
await props.fetchDataComponent();
rows.value.splice(0);
loaderPage(true);
await http
.get(config.API.listEducationLevelHistory)
.then((res) => {
let data = res.data.result;
version.value = data.version; // published= draft=
idVersion.value = data.id; // id mongodb
data.items.map((e: RequestItemsHistoryObject) => {
rows.value.push({
id: e.id,
name: e.name,
createdAt: e.createdAt,
lastUpdatedAt: e.lastUpdatedAt,
lastUpdateFullName: e.lastUpdateFullName,
isActive: e.isActive,
createdFullName: e.createdFullName,
createdUserId: e.createdUserId,
lastUpdateUserId: e.lastUpdateUserId,
});
});
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
updateData.value = false;
loaderPage(false);
});
};
/**
* งชนดอมลประวแกไขขอมลทงหมด
*/
const fetchHistory = async () => {
loaderPage(true);
await http
.get(config.API.listEducationLevelPublishedHistory)
.then((res) => {
const data = res.data.result;
rawHistory.value = [];
if (data.length > 0) {
data.map((e: RequestItemsPublishHistoryObject) => {
e.items.map((i: RequestItemsHistoryObject) => {
rawHistory.value.push({
createdAt: i.createdAt,
createdFullName: i.createdFullName,
createdUserId: i.createdUserId,
id: i.id,
isActive: i.isActive,
lastUpdateFullName: i.lastUpdateFullName,
lastUpdateUserId: i.lastUpdateUserId,
lastUpdatedAt: i.lastUpdatedAt,
name: i.name,
});
});
});
}
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
loaderPage(false);
});
};
/**
* งก clear data แบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
*/
const clearPublishedData = async () => {
loaderPage(true);
await http
.delete(config.API.listEducationLevelHistory)
.then((res) => {
success($q, "ลบข้อมูลร่างสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchHistory();
await fetchData();
});
};
/**
* งกนเผยแพรแบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
*/
const publishedData = async () => {
loaderPage(true);
await http
.get(config.API.listEducationLevelPublished)
.then((res) => {
success($q, "เผยแพร่ข้อมูลสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchData();
});
};
/**
* งกนเพมขอม
*/
const clickAdd = async () => {
const filterRowNull = rows.value.filter(
(f: RequestItemsHistoryObject) =>
f.id === "00000000-0000-0000-0000-000000000000" && f.name == "" // array
);
if (filterRowNull.length == 0) {
//
rows.value.push({
createdAt: new Date(),
createdFullName: "",
createdUserId: "",
id: "00000000-0000-0000-0000-000000000000",
isActive: true,
lastUpdateFullName:
keycloak.tokenParsed == null ? "" : keycloak.tokenParsed.name,
lastUpdateUserId: "",
lastUpdatedAt: new Date(),
name: "",
});
updateData.value = true;
}
};
/**
* งกนบนทกแบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
* publish เมอบนทกแบบรางแลวจะเผยแพรเลยไหม true=นทกและเผยแพร false=นทกอยางเดยว
*/
const save = async (publish: boolean) => {
await validateData();
if (checkValidate.value == false) return;
rows.value.map((e: ResponseHistoryObject) => ({
// data backend
id: e.id,
createdAt: e.createdAt,
lastUpdatedAt: e.lastUpdatedAt,
name: e.name,
isActive: e.isActive,
createdFullName: e.createdFullName,
createdUserId: e.createdUserId,
lastUpdateFullName: e.lastUpdateFullName,
lastUpdateUserId: e.lastUpdateUserId,
}));
loaderPage(true);
await http
.post(config.API.listEducationLevelHistoryId(idVersion.value), {
id: idVersion.value,
version: "draft",
items: rows.value,
})
.then(async (res) => {
if (publish === false) {
success($q, "บันทึกข้อมูลร่างสำเร็จ");
await fetchData(); // get data
} else {
await publishedData(); //
}
edit.value = false;
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
loaderPage(false);
});
};
/**
* เชคชอซำกบขอมลทอยแล
* @param val input
*/
const checkDupDataName = (val: string) => {
const filterNameNull = rows.value.filter(
(f: RequestItemsHistoryObject) => f.name == val
); //
if (filterNameNull.length > 1) {
return false;
}
return true;
};
/**
* งกนปมแกไข ให get data มาใหม
*/
const clickEdit = async () => {
await fetchData();
};
/**
* งกนปมบนทกแบบราง
*/
const clickSave = async () => {
await save(false);
};
/**
* งกนปมลบแบบราง
*/
const clickDelete = async () => {
await clearPublishedData();
};
/**
* งกนปมยกเลกการแกไขขอม
*/
const clickCancel = async () => {
edit.value = false;
await fetchData();
};
/**
* งกนปมเผยแพรอม
* เชคขอมลกอนวาใน array กรอกขอมลครบไหมถาครบกใหเผยแพรได
* าคาใน array ไมอมลใน row จะใหนทกได
*/
const clickPublish = async () => {
if (myForm.value !== null) {
myForm.value.validate().then(async (result: boolean) => {
if (result) {
await save(true);
}
});
} else {
await save(true);
}
};
/**
* งกนปมลบ row data
* @param val data ใน row จะลบ
*/
const clickDeleteRow = (val: RequestItemsHistoryObject) => {
rows.value = rows.value.filter((x: RequestItemsHistoryObject) => x !== val);
updateData.value = true;
};
/**
* งกนเช input ามการแกไขหรอย
*/
const clickEditRow = () => {
myForm.value.validate(false);
updateData.value = true;
};
/**
* งชนดอมลประวแกไขขอมลทเลอก
* @param row อม row ประวการแกไข
*/
const clickHistory = async (row: RequestItemsHistoryObject) => {
modalHistory.value = true;
rowsHistory.value = rawHistory.value.filter(
(f: RequestItemsHistoryObject) => f.id == row.id
);
};
/**
* งกนแปลง date เปนภาษาไทย
* @param value นท type datetime จะแปลงเปนไทย
*/
const textDate = (value: Date) => {
return dateText(value);
};
/**
* validate component
*/
const validateData = async () => {
checkValidate.value = true;
await myForm.value.validate().then((result: boolean) => {
if (result == false) {
checkValidate.value = false;
}
});
};
</script>
<style>
/* สีของnoti */
.my-notif-class {
background: rgba(33, 186, 69, 0.5) !important;
color: #008f17 !important;
}
</style>

View file

@ -0,0 +1,660 @@
<!-- tab เพศ หนาจดการขอมลหล/อมลเกยวกบบคคล -->
<template>
<div>
<q-form ref="myForm">
<data-table
:rows="rows"
:columns="columns"
:filter="filter"
:visible-columns="visibleColumns"
v-model:inputfilter="filter"
v-model:inputvisible="visibleColumns"
v-model:editvisible="edit"
:add="clickAdd"
:edit="clickEdit"
:save="clickSave"
:deleted="clickDelete"
:cancel="clickCancel"
:publish="clickPublish"
:validate="validateData"
:publicData="version === 'published'"
:updateData="updateData"
:history="true"
>
<template #columns="props">
<q-tr :props="props" v-if="edit == false">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.name == 'isActive'">
<q-icon
v-if="col.value == false"
name="mdi-close"
color="red"
class="text-h5"
/>
<q-icon
v-else
name="mdi-check"
color="positive"
class="text-h5"
/>
</div>
<div v-else-if="col.name == 'createdAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else-if="col.name == 'lastUpdatedAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else class="">
{{ col.value }}
</div>
</q-td>
<q-td auto-width>
<q-btn
color="info"
flat
dense
round
size="14px"
icon="mdi-history"
@click="clickHistory(props.row)"
/>
</q-td>
</q-tr>
<q-tr :props="props" v-if="edit == true" class="items-center">
<q-td key="name" :props="props" v-if="props.row.name !== undefined">
<q-input
outlined
@update:model-value="clickEditRow"
v-model="props.row.name"
style="width: 150px"
dense
lazy-rules
autofocus
hide-bottom-space
:rules="[
(val) => (val && val.length > 0) || 'กรุณากรอกข้อมูลให้ครบ',
(val) =>
checkDupDataName(val) || 'ชื่อซ้ำกันกับข้อมูลที่มีอยู่แล้ว',
]"
></q-input>
</q-td>
<q-td
key="createdAt"
:props="props"
v-if="props.row.createdAt !== undefined"
>
<div class="">
{{ textDate(props.row.createdAt) }}
</div>
</q-td>
<q-td key="lastUpdatedAt" :props="props">
<div class="">
{{ textDate(props.row.lastUpdatedAt) }}
</div>
</q-td>
<q-td
key="lastUpdateFullName"
:props="props"
v-if="props.row.lastUpdateFullName !== undefined"
class=""
>
{{ props.row.lastUpdateFullName }}
</q-td>
<q-td
key="isActive"
:props="props"
v-if="props.row.isActive !== undefined"
>
<q-toggle
v-model="props.row.isActive"
dense
size="34px"
color="positive"
@update:model-value="clickEditRow"
/>
</q-td>
<q-td auto-width>
<q-btn
v-if="props.row.id === '00000000-0000-0000-0000-000000000000'"
color="red"
flat
dense
round
size="14px"
icon="mdi-trash-can-outline"
@click="clickDeleteRow(props.row)"
/>
<q-btn
v-if="props.row.id !== '00000000-0000-0000-0000-000000000000'"
color="info"
flat
dense
round
size="14px"
icon="mdi-history"
@click="clickHistory(props.row)"
/>
</q-td>
</q-tr>
</template>
</data-table>
</q-form>
</div>
<HistoryTable
:rows="rowsHistory"
:columns="columnsHistory"
:filter="filterHistory"
:visible-columns="visibleColumnsHistory"
v-model:modal="modalHistory"
v-model:inputfilter="filterHistory"
v-model:inputvisible="visibleColumnsHistory"
v-model:tittle="tittleHistory"
>
<template #columns="props">
<q-tr :props="props">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.name == 'isActive'" class="">
<q-icon
v-if="col.value == false"
name="mdi-close"
color="red"
class="text-h5"
/>
<q-icon v-else name="mdi-check" color="positive" class="text-h5" />
</div>
<div v-else-if="col.name == 'lastUpdatedAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else class="">
{{ col.value }}
</div>
</q-td>
</q-tr>
</template>
</HistoryTable>
</template>
<script setup lang="ts">
import type { QTableProps } from "quasar";
import { useQuasar } from "quasar";
import { onMounted, ref, watch } from "vue";
import http from "@/plugins/http";
import config from "@/app.config";
import keycloak from "@/plugins/keycloak";
import { useCounterMixin } from "@/stores/mixin";
import { useManageDataStore } from "@/modules/01_metadata/store";
import type {
RequestItemsHistoryObject,
RequestItemsPublishHistoryObject,
Columns,
} from "@/modules/01_metadata/interface/request/person/Gender";
import type { ResponseHistoryObject } from "@/modules/01_metadata/interface/response/person/Gender";
import HistoryTable from "@/components/TableHistory.vue";
import { useDataStore } from "@/stores/data";
const props = defineProps({
fetchDataComponent: {
type: Function,
default: () => console.log("not function"),
},
});
const dataStore = useDataStore();
const { loaderPage } = dataStore;
const mixin = useCounterMixin();
const { success, dateText, messageError } = mixin;
const store = useManageDataStore();
const { manageData, changeManageColumns } = store;
const rows = ref<RequestItemsHistoryObject[]>([]); //list data table
const rowsHistory = ref<RequestItemsHistoryObject[]>([]); //select data history
const rawHistory = ref<RequestItemsHistoryObject[]>([]); //raw data history
const tittleHistory = ref<string>("ประวัติแก้ไขเพศ"); //
const myForm = ref<any>(null); //ref
const filter = ref<string>(""); //search data table
const filterHistory = ref<string>(""); //search data table history
const modalHistory = ref<boolean>(false); //modal
const edit = ref<boolean>(false); //
const idVersion = ref<string>(""); //id data mongodb
const version = ref<string>("published"); // published= draft=
const updateData = ref<boolean>(false); //
const checkValidate = ref<boolean>(false);
const columns = ref<QTableProps["columns"]>([
{
name: "name",
align: "left",
label: "เพศ",
sortable: true,
field: "name",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "createdAt",
align: "center",
label: "วันที่สร้าง",
sortable: true,
field: "createdAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdatedAt",
align: "center",
label: "วันที่แก้ไข",
sortable: true,
field: "lastUpdatedAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdateFullName",
align: "left",
label: "ผู้ดำเนินการ",
sortable: true,
field: "lastUpdateFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "isActive",
align: "left",
label: "สถานะ",
sortable: true,
field: "isActive",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumns = ref<String[]>([]);
manageData.person.gender.columns.length == 0
? (visibleColumns.value = [
"name",
"createdAt",
"lastUpdatedAt",
"lastUpdateFullName",
"isActive",
])
: (visibleColumns.value = manageData.person.gender.columns);
const columnsHistory = ref<QTableProps["columns"]>([
{
name: "name",
align: "left",
label: "เพศ",
sortable: true,
field: "name",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdatedAt",
align: "center",
label: "วันที่แก้ไข",
sortable: true,
field: "lastUpdatedAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdateFullName",
align: "left",
label: "ผู้ดำเนินการ",
sortable: true,
field: "lastUpdateFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "isActive",
align: "left",
label: "สถานะ",
sortable: true,
field: "isActive",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumnsHistory = ref<String[]>([
"name",
"lastUpdatedAt",
"lastUpdateFullName",
"isActive",
]);
/**
* เมอเขาหนานจะเรยกฟงชนนอน(get list data)
*/
onMounted(async () => {
await fetchData();
await fetchHistory();
});
watch(visibleColumns, async (count: String[], prevCount: String[]) => {
await changeManageColumns(1, "gender", count);
});
/**
* แจงเตอนขอมลในกรณ success
*/
const $q = useQuasar();
/**
* งก get data าส
*/
const fetchData = async () => {
await props.fetchDataComponent();
rows.value.splice(0);
loaderPage(true);
await http
.get(config.API.listGenderHistory)
.then((res) => {
let data = res.data.result;
version.value = data.version; // published= draft=
idVersion.value = data.id; // id mongodb
data.items.map((e: RequestItemsHistoryObject) => {
rows.value.push({
id: e.id,
name: e.name,
createdAt: e.createdAt,
lastUpdatedAt: e.lastUpdatedAt,
lastUpdateFullName: e.lastUpdateFullName,
isActive: e.isActive,
createdFullName: e.createdFullName,
createdUserId: e.createdUserId,
lastUpdateUserId: e.lastUpdateUserId,
});
});
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
updateData.value = false;
loaderPage(false);
});
};
/**
* งชนดอมลประวแกไขขอมลทงหมด
*/
const fetchHistory = async () => {
loaderPage(true);
await http
.get(config.API.listGenderPublishedHistory)
.then((res) => {
const data = res.data.result;
rawHistory.value = [];
if (data.length > 0) {
data.map((e: RequestItemsPublishHistoryObject) => {
e.items.map((i: RequestItemsHistoryObject) => {
rawHistory.value.push({
createdAt: i.createdAt,
createdFullName: i.createdFullName,
createdUserId: i.createdUserId,
id: i.id,
isActive: i.isActive,
lastUpdateFullName: i.lastUpdateFullName,
lastUpdateUserId: i.lastUpdateUserId,
lastUpdatedAt: i.lastUpdatedAt,
name: i.name,
});
});
});
}
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
loaderPage(false);
});
};
/**
* งก clear data แบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
*/
const clearPublishedData = async () => {
loaderPage(true);
await http
.delete(config.API.listGenderHistory)
.then((res) => {
success($q, "ลบข้อมูลร่างสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchHistory();
await fetchData();
});
};
/**
* งกนเผยแพรแบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
*/
const publishedData = async () => {
loaderPage(true);
await http
.get(config.API.listGenderPublished)
.then((res) => {
success($q, "เผยแพร่ข้อมูลสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchData();
});
};
/**
* งกนเพมขอม
*/
const clickAdd = async () => {
const filterRowNull = rows.value.filter(
(f: RequestItemsHistoryObject) =>
f.id === "00000000-0000-0000-0000-000000000000" && f.name == "" // array
);
if (filterRowNull.length == 0) {
//
rows.value.push({
createdAt: new Date(),
createdFullName: "",
createdUserId: "",
id: "00000000-0000-0000-0000-000000000000",
isActive: true,
lastUpdateFullName:
keycloak.tokenParsed == null ? "" : keycloak.tokenParsed.name,
lastUpdateUserId: "",
lastUpdatedAt: new Date(),
name: "",
});
updateData.value = true;
}
};
/**
* งกนบนทกแบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
* publish เมอบนทกแบบรางแลวจะเผยแพรเลยไหม true=นทกและเผยแพร false=นทกอยางเดยว
*/
const save = async (publish: boolean) => {
await validateData();
if (checkValidate.value == false) return;
rows.value.map((e: ResponseHistoryObject) => ({
// data backend
id: e.id,
createdAt: e.createdAt,
lastUpdatedAt: e.lastUpdatedAt,
name: e.name,
isActive: e.isActive,
createdFullName: e.createdFullName,
createdUserId: e.createdUserId,
lastUpdateFullName: e.lastUpdateFullName,
lastUpdateUserId: e.lastUpdateUserId,
}));
loaderPage(true);
await http
.post(config.API.listGenderHistoryId(idVersion.value), {
id: idVersion.value,
version: "draft",
items: rows.value,
})
.then(async (res) => {
if (publish === false) {
success($q, "บันทึกข้อมูลร่างสำเร็จ");
await fetchData(); // get data
} else {
await publishedData(); //
}
edit.value = false;
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
loaderPage(false);
});
};
/**
* เชคชอซำกบขอมลทอยแล
* @param val input
*/
const checkDupDataName = (val: string) => {
const filterNameNull = rows.value.filter(
(f: RequestItemsHistoryObject) => f.name == val
); //
if (filterNameNull.length > 1) {
return false;
}
return true;
};
/**
* งกนปมแกไข ให get data มาใหม
*/
const clickEdit = async () => {
await fetchData();
};
/**
* งกนปมบนทกแบบราง
*/
const clickSave = async () => {
await save(false);
};
/**
* งกนปมลบแบบราง
*/
const clickDelete = async () => {
await clearPublishedData();
};
/**
* งกนปมยกเลกการแกไขขอม
*/
const clickCancel = async () => {
edit.value = false;
await fetchData();
};
/**
* งกนปมเผยแพรอม
* เชคขอมลกอนวาใน array กรอกขอมลครบไหมถาครบกใหเผยแพรได
* าคาใน array ไมอมลใน row จะใหนทกได
*/
const clickPublish = async () => {
if (myForm.value !== null) {
myForm.value.validate().then(async (result: boolean) => {
if (result) {
await save(true);
}
});
} else {
await save(true);
}
};
/**
* งกนปมลบ row data
* @param val data ใน row จะลบ
*/
const clickDeleteRow = (val: RequestItemsHistoryObject) => {
rows.value = rows.value.filter((x: RequestItemsHistoryObject) => x !== val);
updateData.value = true;
};
/**
* งกนเช input ามการแกไขหรอย
*/
const clickEditRow = () => {
myForm.value.validate(false);
updateData.value = true;
};
/**
* งชนดอมลประวแกไขขอมลทเลอก
* @param row อม row ประวการแกไข
*/
const clickHistory = async (row: RequestItemsHistoryObject) => {
modalHistory.value = true;
rowsHistory.value = rawHistory.value.filter(
(f: RequestItemsHistoryObject) => f.id == row.id
);
};
/**
* งกนแปลง date เปนภาษาไทย
* @param value นท type datetime จะแปลงเปนไทย
*/
const textDate = (value: Date) => {
return dateText(value);
};
/**
* validate component
*/
const validateData = async () => {
checkValidate.value = true;
await myForm.value.validate().then((result: boolean) => {
if (result == false) {
checkValidate.value = false;
}
});
};
</script>
<style>
/* สีของnoti */
.my-notif-class {
background: rgba(33, 186, 69, 0.5) !important;
color: #008f17 !important;
}
</style>

View file

@ -0,0 +1,660 @@
<!-- tab คำนำหน หนาจดการขอมลหล/อมลเกยวกบบคคล -->
<template>
<div>
<q-form ref="myForm">
<data-table
:rows="rows"
:columns="columns"
:filter="filter"
:visible-columns="visibleColumns"
v-model:inputfilter="filter"
v-model:inputvisible="visibleColumns"
v-model:editvisible="edit"
:add="clickAdd"
:edit="clickEdit"
:save="clickSave"
:deleted="clickDelete"
:cancel="clickCancel"
:publish="clickPublish"
:validate="validateData"
:publicData="version === 'published'"
:updateData="updateData"
:history="true"
>
<template #columns="props">
<q-tr :props="props" v-if="edit == false">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.name == 'isActive'" class="">
<q-icon
v-if="col.value == false"
name="mdi-close"
color="red"
class="text-h5"
/>
<q-icon
v-else
name="mdi-check"
color="positive"
class="text-h5"
/>
</div>
<div v-else-if="col.name == 'createdAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else-if="col.name == 'lastUpdatedAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else class="">
{{ col.value }}
</div>
</q-td>
<q-td auto-width>
<q-btn
color="info"
flat
dense
round
size="14px"
icon="mdi-history"
@click="clickHistory(props.row)"
/>
</q-td>
</q-tr>
<q-tr :props="props" v-if="edit == true" class="items-center">
<q-td key="name" :props="props" v-if="props.row.name !== undefined">
<q-input
class=""
outlined
@update:model-value="clickEditRow"
v-model="props.row.name"
dense
lazy-rules
autofocus
hide-bottom-space
:rules="[
(val) => (val && val.length > 0) || 'กรุณากรอกข้อมูลให้ครบ',
(val) =>
checkDupDataName(val) || 'ชื่อซ้ำกันกับข้อมูลที่มีอยู่แล้ว',
]"
></q-input>
</q-td>
<q-td
key="createdAt"
:props="props"
v-if="props.row.createdAt !== undefined"
>
<div class="">
{{ textDate(props.row.createdAt) }}
</div>
</q-td>
<q-td key="lastUpdatedAt" :props="props">
<div class="">
{{ textDate(props.row.lastUpdatedAt) }}
</div>
</q-td>
<q-td
key="lastUpdateFullName"
:props="props"
v-if="props.row.lastUpdateFullName !== undefined"
class=""
>
{{ props.row.lastUpdateFullName }}
</q-td>
<q-td
key="isActive"
:props="props"
v-if="props.row.isActive !== undefined"
>
<q-toggle
v-model="props.row.isActive"
dense
size="34px"
color="positive"
@update:model-value="clickEditRow"
/>
</q-td>
<q-td auto-width>
<q-btn
v-if="props.row.id === '00000000-0000-0000-0000-000000000000'"
color="red"
flat
dense
round
size="14px"
icon="mdi-trash-can-outline"
@click="clickDeleteRow(props.row)"
/>
<q-btn
v-if="props.row.id !== '00000000-0000-0000-0000-000000000000'"
color="info"
flat
dense
round
size="14px"
icon="mdi-history"
@click="clickHistory(props.row)"
/>
</q-td>
</q-tr>
</template>
</data-table>
</q-form>
</div>
<HistoryTable
:rows="rowsHistory"
:columns="columnsHistory"
:filter="filterHistory"
:visible-columns="visibleColumnsHistory"
v-model:modal="modalHistory"
v-model:inputfilter="filterHistory"
v-model:inputvisible="visibleColumnsHistory"
v-model:tittle="tittleHistory"
>
<template #columns="props">
<q-tr :props="props">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.name == 'isActive'" class="">
<q-icon
v-if="col.value == false"
name="mdi-close"
color="red"
class="text-h5"
/>
<q-icon v-else name="mdi-check" color="positive" class="text-h5" />
</div>
<div v-else-if="col.name == 'lastUpdatedAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else class="">
{{ col.value }}
</div>
</q-td>
</q-tr>
</template>
</HistoryTable>
</template>
<script setup lang="ts">
import type { QTableProps } from "quasar";
import { useQuasar } from "quasar";
import { onMounted, ref, watch } from "vue";
import http from "@/plugins/http";
import config from "@/app.config";
import keycloak from "@/plugins/keycloak";
import { useCounterMixin } from "@/stores/mixin";
import { useManageDataStore } from "@/modules/01_metadata/store";
import type {
RequestItemsHistoryObject,
RequestItemsPublishHistoryObject,
Columns,
} from "@/modules/01_metadata/interface/request/person/Prefix";
import type { ResponseHistoryObject } from "@/modules/01_metadata/interface/response/person/Prefix";
import HistoryTable from "@/components/TableHistory.vue";
import { useDataStore } from "@/stores/data";
const props = defineProps({
fetchDataComponent: {
type: Function,
default: () => console.log("not function"),
},
});
const dataStore = useDataStore();
const { loaderPage } = dataStore;
const mixin = useCounterMixin();
const { success, dateText, messageError } = mixin;
const store = useManageDataStore();
const { manageData, changeManageColumns } = store;
const rows = ref<RequestItemsHistoryObject[]>([]); //list data table
const rowsHistory = ref<RequestItemsHistoryObject[]>([]); //select data history
const rawHistory = ref<RequestItemsHistoryObject[]>([]); //raw data history
const tittleHistory = ref<string>("ประวัติแก้ไขคำนำหน้า"); //
const myForm = ref<any>(null); //ref
const filter = ref<string>(""); //search data table
const filterHistory = ref<string>(""); //search data table history
const modalHistory = ref<boolean>(false); //modal
const edit = ref<boolean>(false); //
const idVersion = ref<string>(""); //id data mongodb
const version = ref<string>("published"); // published= draft=
const updateData = ref<boolean>(false); //
const checkValidate = ref<boolean>(false);
const columns = ref<QTableProps["columns"]>([
{
name: "name",
align: "left",
label: "คำนำหน้า",
sortable: true,
field: "name",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "createdAt",
align: "center",
label: "วันที่สร้าง",
sortable: true,
field: "createdAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdatedAt",
align: "center",
label: "วันที่แก้ไข",
sortable: true,
field: "lastUpdatedAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdateFullName",
align: "left",
label: "ผู้ดำเนินการ",
sortable: true,
field: "lastUpdateFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "isActive",
align: "left",
label: "สถานะ",
sortable: true,
field: "isActive",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumns = ref<String[]>([]);
manageData.person.prefix.columns.length == 0
? (visibleColumns.value = [
"name",
"createdAt",
"lastUpdatedAt",
"lastUpdateFullName",
"isActive",
])
: (visibleColumns.value = manageData.person.prefix.columns);
const columnsHistory = ref<QTableProps["columns"]>([
{
name: "name",
align: "left",
label: "คำนำหน้า",
sortable: true,
field: "name",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdatedAt",
align: "center",
label: "วันที่แก้ไข",
sortable: true,
field: "lastUpdatedAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdateFullName",
align: "left",
label: "ผู้ดำเนินการ",
sortable: true,
field: "lastUpdateFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "isActive",
align: "left",
label: "สถานะ",
sortable: true,
field: "isActive",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumnsHistory = ref<String[]>([
"name",
"lastUpdatedAt",
"lastUpdateFullName",
"isActive",
]);
/**
* เมอเขาหนานจะเรยกฟงชนนอน(get list data)
*/
onMounted(async () => {
await fetchData();
await fetchHistory();
});
watch(visibleColumns, async (count: String[], prevCount: String[]) => {
await changeManageColumns(1, "prefix", count);
});
/**
* แจงเตอนขอมลในกรณ success
*/
const $q = useQuasar();
/**
* งก get data าส
*/
const fetchData = async () => {
await props.fetchDataComponent();
rows.value.splice(0);
loaderPage(true);
await http
.get(config.API.listPrefixHistory)
.then((res) => {
let data = res.data.result;
version.value = data.version; // published= draft=
idVersion.value = data.id; // id mongodb
data.items.map((e: RequestItemsHistoryObject) => {
rows.value.push({
id: e.id,
name: e.name,
createdAt: e.createdAt,
lastUpdatedAt: e.lastUpdatedAt,
lastUpdateFullName: e.lastUpdateFullName,
isActive: e.isActive,
createdFullName: e.createdFullName,
createdUserId: e.createdUserId,
lastUpdateUserId: e.lastUpdateUserId,
});
});
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
updateData.value = false;
loaderPage(false);
});
};
/**
* งชนดอมลประวแกไขขอมลทงหมด
*/
const fetchHistory = async () => {
loaderPage(true);
await http
.get(config.API.listPrefixPublishedHistory)
.then((res) => {
const data = res.data.result;
rawHistory.value = [];
if (data.length > 0) {
data.map((e: RequestItemsPublishHistoryObject) => {
e.items.map((i: RequestItemsHistoryObject) => {
rawHistory.value.push({
createdAt: i.createdAt,
createdFullName: i.createdFullName,
createdUserId: i.createdUserId,
id: i.id,
isActive: i.isActive,
lastUpdateFullName: i.lastUpdateFullName,
lastUpdateUserId: i.lastUpdateUserId,
lastUpdatedAt: i.lastUpdatedAt,
name: i.name,
});
});
});
}
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
loaderPage(false);
});
};
/**
* งก clear data แบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
*/
const clearPublishedData = async () => {
loaderPage(true);
await http
.delete(config.API.listPrefixHistory)
.then((res) => {
success($q, "ลบข้อมูลร่างสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchHistory();
await fetchData();
});
};
/**
* งกนเผยแพรแบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
*/
const publishedData = async () => {
loaderPage(true);
await http
.get(config.API.listPrefixPublished)
.then((res) => {
success($q, "เผยแพร่ข้อมูลสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchData();
});
};
/**
* งกนเพมขอม
*/
const clickAdd = async () => {
const filterRowNull = rows.value.filter(
(f: RequestItemsHistoryObject) =>
f.id === "00000000-0000-0000-0000-000000000000" && f.name == "" // array
);
if (filterRowNull.length == 0) {
//
rows.value.push({
createdAt: new Date(),
createdFullName: "",
createdUserId: "",
id: "00000000-0000-0000-0000-000000000000",
isActive: true,
lastUpdateFullName:
keycloak.tokenParsed == null ? "" : keycloak.tokenParsed.name,
lastUpdateUserId: "",
lastUpdatedAt: new Date(),
name: "",
});
updateData.value = true;
}
};
/**
* งกนบนทกแบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
* publish เมอบนทกแบบรางแลวจะเผยแพรเลยไหม true=นทกและเผยแพร false=นทกอยางเดยว
*/
const save = async (publish: boolean) => {
await validateData();
if (checkValidate.value == false) return;
rows.value.map((e: ResponseHistoryObject) => ({
// data backend
id: e.id,
createdAt: e.createdAt,
lastUpdatedAt: e.lastUpdatedAt,
name: e.name,
isActive: e.isActive,
createdFullName: e.createdFullName,
createdUserId: e.createdUserId,
lastUpdateFullName: e.lastUpdateFullName,
lastUpdateUserId: e.lastUpdateUserId,
}));
loaderPage(true);
await http
.post(config.API.listPrefixHistoryId(idVersion.value), {
id: idVersion.value,
version: "draft",
items: rows.value,
})
.then(async (res) => {
if (publish === false) {
success($q, "บันทึกข้อมูลร่างสำเร็จ");
await fetchData(); // get data
} else {
await publishedData(); //
}
edit.value = false;
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
loaderPage(false);
});
};
/**
* เชคชอซำกบขอมลทอยแล
* @param val input
*/
const checkDupDataName = (val: string) => {
const filterNameNull = rows.value.filter(
(f: RequestItemsHistoryObject) => f.name == val
); //
if (filterNameNull.length > 1) {
return false;
}
return true;
};
/**
* งกนปมแกไข ให get data มาใหม
*/
const clickEdit = async () => {
await fetchData();
};
/**
* งกนปมบนทกแบบราง
*/
const clickSave = async () => {
await save(false);
};
/**
* งกนปมลบแบบราง
*/
const clickDelete = async () => {
await clearPublishedData();
};
/**
* งกนปมยกเลกการแกไขขอม
*/
const clickCancel = async () => {
edit.value = false;
await fetchData();
};
/**
* งกนปมเผยแพรอม
* เชคขอมลกอนวาใน array กรอกขอมลครบไหมถาครบกใหเผยแพรได
* าคาใน array ไมอมลใน row จะใหนทกได
*/
const clickPublish = async () => {
if (myForm.value !== null) {
myForm.value.validate().then(async (result: boolean) => {
if (result) {
await save(true);
}
});
} else {
await save(true);
}
};
/**
* งกนปมลบ row data
* @param val data ใน row จะลบ
*/
const clickDeleteRow = (val: RequestItemsHistoryObject) => {
rows.value = rows.value.filter((x: RequestItemsHistoryObject) => x !== val);
updateData.value = true;
};
/**
* งกนเช input ามการแกไขหรอย
*/
const clickEditRow = () => {
myForm.value.validate(false);
updateData.value = true;
};
/**
* งชนดอมลประวแกไขขอมลทเลอก
* @param row อม row ประวการแกไข
*/
const clickHistory = async (row: RequestItemsHistoryObject) => {
modalHistory.value = true;
rowsHistory.value = rawHistory.value.filter(
(f: RequestItemsHistoryObject) => f.id == row.id
);
};
/**
* งกนแปลง date เปนภาษาไทย
* @param value นท type datetime จะแปลงเปนไทย
*/
const textDate = (value: Date) => {
return dateText(value);
};
/**
* validate component
*/
const validateData = async () => {
checkValidate.value = true;
await myForm.value.validate().then((result: boolean) => {
if (result == false) {
checkValidate.value = false;
}
});
};
</script>
<style>
/* สีของnoti */
.my-notif-class {
background: rgba(33, 186, 69, 0.5) !important;
color: #008f17 !important;
}
</style>

View file

@ -0,0 +1,679 @@
<!-- tab งหว หนาจดการขอมลหล/อมลเกยวกบบคคล -->
<template>
<div>
<q-form ref="myForm">
<data-table
:rows="rows"
:columns="columns"
:filter="filter"
:visible-columns="visibleColumns"
v-model:inputfilter="filter"
v-model:inputvisible="visibleColumns"
v-model:editvisible="edit"
:add="clickAdd"
:edit="clickEdit"
:save="clickSave"
:deleted="clickDelete"
:cancel="clickCancel"
:publish="clickPublish"
:validate="validateData"
:publicData="version === 'published'"
:updateData="updateData"
:history="true"
:nextPageVisible="true"
>
<template #columns="props">
<q-tr :props="props" v-if="edit == false">
<q-td
v-for="col in props.cols"
:key="col.name"
:props="props"
@click="clickRow(props.row.id)"
>
<div v-if="col.name == 'isActive'" class="">
<q-icon
v-if="col.value == false"
name="mdi-close"
color="red"
class="text-h5"
/>
<q-icon
v-else
name="mdi-check"
color="positive"
class="text-h5"
/>
</div>
<div v-else-if="col.name == 'createdAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else-if="col.name == 'lastUpdatedAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else class="">
{{ col.value }}
</div>
</q-td>
<q-td auto-width>
<q-btn
color="info"
flat
dense
round
size="14px"
icon="mdi-history"
@click="clickHistory(props.row)"
/>
<q-icon
size="30px"
color="grey-8"
name="chevron_right"
@click="clickRow(props.row.id)"
/>
</q-td>
</q-tr>
<q-tr :props="props" v-if="edit == true" class="items-center">
<q-td key="name" :props="props" v-if="props.row.name !== undefined">
<q-input
class=""
outlined
@update:model-value="clickEditRow"
v-model="props.row.name"
dense
lazy-rules
autofocus
hide-bottom-space
:rules="[
(val) => (val && val.length > 0) || 'กรุณากรอกข้อมูลให้ครบ',
(val) =>
checkDupDataName(val) || 'ชื่อซ้ำกันกับข้อมูลที่มีอยู่แล้ว',
]"
></q-input>
</q-td>
<q-td
key="createdAt"
:props="props"
v-if="props.row.createdAt !== undefined"
>
<div class="">
{{ textDate(props.row.createdAt) }}
</div>
</q-td>
<q-td key="lastUpdatedAt" :props="props">
<div class="">
{{ textDate(props.row.lastUpdatedAt) }}
</div>
</q-td>
<q-td
key="lastUpdateFullName"
:props="props"
v-if="props.row.lastUpdateFullName !== undefined"
class=""
>
{{ props.row.lastUpdateFullName }}
</q-td>
<q-td
key="isActive"
:props="props"
v-if="props.row.isActive !== undefined"
>
<q-toggle
v-model="props.row.isActive"
dense
size="34px"
color="positive"
@update:model-value="clickEditRow"
/>
</q-td>
<q-td auto-width>
<q-btn
v-if="props.row.id === '00000000-0000-0000-0000-000000000000'"
color="red"
flat
dense
round
size="14px"
icon="mdi-trash-can-outline"
@click="clickDeleteRow(props.row)"
/>
<q-btn
v-if="props.row.id !== '00000000-0000-0000-0000-000000000000'"
color="info"
flat
dense
round
size="14px"
icon="mdi-history"
@click="clickHistory(props.row)"
/>
</q-td>
</q-tr>
</template>
</data-table>
</q-form>
</div>
<HistoryTable
:rows="rowsHistory"
:columns="columnsHistory"
:filter="filterHistory"
:visible-columns="visibleColumnsHistory"
v-model:modal="modalHistory"
v-model:inputfilter="filterHistory"
v-model:inputvisible="visibleColumnsHistory"
v-model:tittle="tittleHistory"
>
<template #columns="props">
<q-tr :props="props">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.name == 'isActive'" class="">
<q-icon
v-if="col.value == false"
name="mdi-close"
color="red"
class="text-h5"
/>
<q-icon v-else name="mdi-check" color="positive" class="text-h5" />
</div>
<div v-else-if="col.name == 'lastUpdatedAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else class="">
{{ col.value }}
</div>
</q-td>
</q-tr>
</template>
</HistoryTable>
</template>
<script setup lang="ts">
import type { QTableProps } from "quasar";
import { useQuasar } from "quasar";
import { onMounted, ref, watch } from "vue";
import http from "@/plugins/http";
import config from "@/app.config";
import keycloak from "@/plugins/keycloak";
import { useCounterMixin } from "@/stores/mixin";
import { useManageDataStore } from "@/modules/01_metadata/store";
import type {
RequestItemsHistoryObject,
RequestItemsPublishHistoryObject,
Columns,
} from "@/modules/01_metadata/interface/request/person/Province";
import type { ResponseHistoryObject } from "@/modules/01_metadata/interface/response/person/Province";
import HistoryTable from "@/components/TableHistory.vue";
import { useRouter } from "vue-router";
import { useDataStore } from "@/stores/data";
const props = defineProps({
fetchDataComponent: {
type: Function,
default: () => console.log("not function"),
},
});
const dataStore = useDataStore();
const { loaderPage } = dataStore; // load api
const mixin = useCounterMixin();
const { success, dateText, messageError } = mixin;
const store = useManageDataStore();
const { manageData, changeManageColumns } = store;
const rows = ref<RequestItemsHistoryObject[]>([]); //list data table
const rowsHistory = ref<RequestItemsHistoryObject[]>([]); //select data history
const rawHistory = ref<RequestItemsHistoryObject[]>([]); //raw data history
const tittleHistory = ref<string>("ประวัติแก้ไขจังหวัด"); //
const myForm = ref<any>(null); //ref
const filter = ref<string>(""); //search data table
const filterHistory = ref<string>(""); //search data table history
const modalHistory = ref<boolean>(false); //modal
const edit = ref<boolean>(false); //
const idVersion = ref<string>(""); //id data mongodb
const version = ref<string>("published"); // published= draft=
const updateData = ref<boolean>(false); //
const router = useRouter();
const checkValidate = ref<boolean>(false);
const columns = ref<QTableProps["columns"]>([
{
name: "name",
align: "left",
label: "จังหวัด",
sortable: true,
field: "name",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "createdAt",
align: "center",
label: "วันที่สร้าง",
sortable: true,
field: "createdAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdatedAt",
align: "center",
label: "วันที่แก้ไข",
sortable: true,
field: "lastUpdatedAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdateFullName",
align: "left",
label: "ผู้ดำเนินการ",
sortable: true,
field: "lastUpdateFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "isActive",
align: "left",
label: "สถานะ",
sortable: true,
field: "isActive",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumns = ref<String[]>([]);
manageData.person.province.columns.length == 0
? (visibleColumns.value = [
"name",
"createdAt",
"lastUpdatedAt",
"lastUpdateFullName",
"isActive",
])
: (visibleColumns.value = manageData.person.province.columns);
const columnsHistory = ref<QTableProps["columns"]>([
{
name: "name",
align: "left",
label: "จังหวัด",
sortable: true,
field: "name",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdatedAt",
align: "center",
label: "วันที่แก้ไข",
sortable: true,
field: "lastUpdatedAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdateFullName",
align: "left",
label: "ผู้ดำเนินการ",
sortable: true,
field: "lastUpdateFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "isActive",
align: "left",
label: "สถานะ",
sortable: true,
field: "isActive",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumnsHistory = ref<String[]>([
"name",
"lastUpdatedAt",
"lastUpdateFullName",
"isActive",
]);
/**
* เมอเขาหนานจะเรยกฟงชนนอน(get list data)
*/
onMounted(async () => {
await fetchData();
await fetchHistory();
});
watch(visibleColumns, async (count: String[], prevCount: String[]) => {
await changeManageColumns(1, "province", count);
});
/**
* แจงเตอนขอมลในกรณ success
*/
const $q = useQuasar();
/**
* งก get data าส
*/
const fetchData = async () => {
await props.fetchDataComponent();
rows.value.splice(0);
loaderPage(true);
await http
.get(config.API.listProvinceHistory)
.then((res) => {
let data = res.data.result;
version.value = data.version; // published= draft=
idVersion.value = data.id; // id mongodb
data.items.map((e: RequestItemsHistoryObject) => {
rows.value.push({
id: e.id,
name: e.name,
createdAt: e.createdAt,
lastUpdatedAt: e.lastUpdatedAt,
lastUpdateFullName: e.lastUpdateFullName,
isActive: e.isActive,
createdFullName: e.createdFullName,
createdUserId: e.createdUserId,
lastUpdateUserId: e.lastUpdateUserId,
});
});
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
updateData.value = false;
loaderPage(false);
});
};
/**
* งชนดอมลประวแกไขขอมลทงหมด
*/
const fetchHistory = async () => {
loaderPage(true);
await http
.get(config.API.listProvincePublishedHistory)
.then((res) => {
const data = res.data.result;
rawHistory.value = [];
if (data.length > 0) {
data.map((e: RequestItemsPublishHistoryObject) => {
e.items.map((i: RequestItemsHistoryObject) => {
rawHistory.value.push({
createdAt: i.createdAt,
createdFullName: i.createdFullName,
createdUserId: i.createdUserId,
id: i.id,
isActive: i.isActive,
lastUpdateFullName: i.lastUpdateFullName,
lastUpdateUserId: i.lastUpdateUserId,
lastUpdatedAt: i.lastUpdatedAt,
name: i.name,
});
});
});
}
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
loaderPage(false);
});
};
/**
* งก clear data แบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
*/
const clearPublishedData = async () => {
loaderPage(true);
await http
.delete(config.API.listProvinceHistory)
.then((res) => {
success($q, "ลบข้อมูลร่างสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchHistory();
await fetchData();
});
};
/**
* งกนเผยแพรแบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
*/
const publishedData = async () => {
loaderPage(true);
await http
.get(config.API.listProvincePublished)
.then((res) => {
success($q, "เผยแพร่ข้อมูลสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchData();
});
};
/**
* งกนเพมขอม
*/
const clickAdd = async () => {
const filterRowNull = rows.value.filter(
(f: RequestItemsHistoryObject) =>
f.id === "00000000-0000-0000-0000-000000000000" && f.name == "" // array
);
if (filterRowNull.length == 0) {
//
rows.value.push({
createdAt: new Date(),
createdFullName: "",
createdUserId: "",
id: "00000000-0000-0000-0000-000000000000",
isActive: true,
lastUpdateFullName:
keycloak.tokenParsed == null ? "" : keycloak.tokenParsed.name,
lastUpdateUserId: "",
lastUpdatedAt: new Date(),
name: "",
});
updateData.value = true;
}
};
/**
* งกนบนทกแบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
* publish เมอบนทกแบบรางแลวจะเผยแพรเลยไหม true=นทกและเผยแพร false=นทกอยางเดยว
*/
const save = async (publish: boolean) => {
await validateData();
if (checkValidate.value == false) return;
rows.value.map((e: ResponseHistoryObject) => ({
// data backend
id: e.id,
createdAt: e.createdAt,
lastUpdatedAt: e.lastUpdatedAt,
name: e.name,
isActive: e.isActive,
createdFullName: e.createdFullName,
createdUserId: e.createdUserId,
lastUpdateFullName: e.lastUpdateFullName,
lastUpdateUserId: e.lastUpdateUserId,
}));
loaderPage(true);
await http
.post(config.API.listProvinceHistoryId(idVersion.value), {
id: idVersion.value,
version: "draft",
items: rows.value,
})
.then(async (res) => {
if (publish === false) {
success($q, "บันทึกข้อมูลร่างสำเร็จ");
await fetchData(); // get data
} else {
await publishedData(); //
}
edit.value = false;
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
loaderPage(false);
});
};
/**
* เชคชอซำกบขอมลทอยแล
* @param val input
*/
const checkDupDataName = (val: string) => {
const filterNameNull = rows.value.filter(
(f: RequestItemsHistoryObject) => f.name == val
); //
if (filterNameNull.length > 1) {
return false;
}
return true;
};
/**
* งกนปมแกไข ให get data มาใหม
*/
const clickEdit = async () => {
await fetchData();
};
/**
* งกนปมบนทกแบบราง
*/
const clickSave = async () => {
await save(false);
};
/**
* งกนปมลบแบบราง
*/
const clickDelete = async () => {
await clearPublishedData();
};
/**
* งกนปมยกเลกการแกไขขอม
*/
const clickCancel = async () => {
edit.value = false;
await fetchData();
};
/**
* งกนปมเผยแพรอม
* เชคขอมลกอนวาใน array กรอกขอมลครบไหมถาครบกใหเผยแพรได
* าคาใน array ไมอมลใน row จะใหนทกได
*/
const clickPublish = async () => {
if (myForm.value !== null) {
myForm.value.validate().then(async (result: boolean) => {
if (result) {
await save(true);
}
});
} else {
await save(true);
}
};
/**
* งกนปมลบ row data
* @param val data ใน row จะลบ
*/
const clickDeleteRow = (val: RequestItemsHistoryObject) => {
rows.value = rows.value.filter((x: RequestItemsHistoryObject) => x !== val);
updateData.value = true;
};
/**
* งกนเช input ามการแกไขหรอย
*/
const clickEditRow = () => {
myForm.value.validate(false);
updateData.value = true;
};
/**
* งชนดอมลประวแกไขขอมลทเลอก
* @param row อม row ประวการแกไข
*/
const clickHistory = async (row: RequestItemsHistoryObject) => {
modalHistory.value = true;
rowsHistory.value = rawHistory.value.filter(
(f: RequestItemsHistoryObject) => f.id == row.id
);
};
/**
* งกนแปลง date เปนภาษาไทย
* @param value นท type datetime จะแปลงเปนไทย
*/
const textDate = (value: Date) => {
return dateText(value);
};
/**
* validate component
*/
const validateData = async () => {
checkValidate.value = true;
await myForm.value.validate().then((result: boolean) => {
if (result == false) {
checkValidate.value = false;
}
});
};
/**
* งกนกดเลอก row ไหนจะเปลยนหนาไปหาเขตทงหมดในจงหวดทกดเลอก
*/
const clickRow = (val: string) => {
router.push(`/metadata/province/${val}`);
};
</script>
<style>
/* สีของnoti */
.my-notif-class {
background: rgba(33, 186, 69, 0.5) !important;
color: #008f17 !important;
}
</style>

View file

@ -0,0 +1,660 @@
<!-- tab สถานภาพ หนาจดการขอมลหล/อมลเกยวกบบคคล -->
<template>
<div>
<q-form ref="myForm">
<data-table
:rows="rows"
:columns="columns"
:filter="filter"
:visible-columns="visibleColumns"
v-model:inputfilter="filter"
v-model:inputvisible="visibleColumns"
v-model:editvisible="edit"
:add="clickAdd"
:edit="clickEdit"
:save="clickSave"
:deleted="clickDelete"
:cancel="clickCancel"
:publish="clickPublish"
:validate="validateData"
:publicData="version === 'published'"
:updateData="updateData"
:history="true"
>
<template #columns="props">
<q-tr :props="props" v-if="edit == false">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.name == 'isActive'" class="">
<q-icon
v-if="col.value == false"
name="mdi-close"
color="red"
class="text-h5"
/>
<q-icon
v-else
name="mdi-check"
color="positive"
class="text-h5"
/>
</div>
<div v-else-if="col.name == 'createdAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else-if="col.name == 'lastUpdatedAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else class="">
{{ col.value }}
</div>
</q-td>
<q-td auto-width>
<q-btn
color="info"
flat
dense
round
size="14px"
icon="mdi-history"
@click="clickHistory(props.row)"
/>
</q-td>
</q-tr>
<q-tr :props="props" v-if="edit == true" class="items-center">
<q-td key="name" :props="props" v-if="props.row.name !== undefined">
<q-input
class=""
outlined
@update:model-value="clickEditRow"
v-model="props.row.name"
dense
lazy-rules
autofocus
hide-bottom-space
:rules="[
(val) => (val && val.length > 0) || 'กรุณากรอกข้อมูลให้ครบ',
(val) =>
checkDupDataName(val) || 'ชื่อซ้ำกันกับข้อมูลที่มีอยู่แล้ว',
]"
></q-input>
</q-td>
<q-td
key="createdAt"
:props="props"
v-if="props.row.createdAt !== undefined"
>
<div class="">
{{ textDate(props.row.createdAt) }}
</div>
</q-td>
<q-td key="lastUpdatedAt" :props="props">
<div class="">
{{ textDate(props.row.lastUpdatedAt) }}
</div>
</q-td>
<q-td
key="lastUpdateFullName"
:props="props"
v-if="props.row.lastUpdateFullName !== undefined"
class=""
>
{{ props.row.lastUpdateFullName }}
</q-td>
<q-td
key="isActive"
:props="props"
v-if="props.row.isActive !== undefined"
>
<q-toggle
v-model="props.row.isActive"
dense
size="34px"
color="positive"
@update:model-value="clickEditRow"
/>
</q-td>
<q-td auto-width>
<q-btn
v-if="props.row.id === '00000000-0000-0000-0000-000000000000'"
color="red"
flat
dense
round
size="14px"
icon="mdi-trash-can-outline"
@click="clickDeleteRow(props.row)"
/>
<q-btn
v-if="props.row.id !== '00000000-0000-0000-0000-000000000000'"
color="info"
flat
dense
round
size="14px"
icon="mdi-history"
@click="clickHistory(props.row)"
/>
</q-td>
</q-tr>
</template>
</data-table>
</q-form>
</div>
<HistoryTable
:rows="rowsHistory"
:columns="columnsHistory"
:filter="filterHistory"
:visible-columns="visibleColumnsHistory"
v-model:modal="modalHistory"
v-model:inputfilter="filterHistory"
v-model:inputvisible="visibleColumnsHistory"
v-model:tittle="tittleHistory"
>
<template #columns="props">
<q-tr :props="props">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.name == 'isActive'" class="">
<q-icon
v-if="col.value == false"
name="mdi-close"
color="red"
class="text-h5"
/>
<q-icon v-else name="mdi-check" color="positive" class="text-h5" />
</div>
<div v-else-if="col.name == 'lastUpdatedAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else class="">
{{ col.value }}
</div>
</q-td>
</q-tr>
</template>
</HistoryTable>
</template>
<script setup lang="ts">
import type { QTableProps } from "quasar";
import { useQuasar } from "quasar";
import { onMounted, ref, watch } from "vue";
import http from "@/plugins/http";
import config from "@/app.config";
import keycloak from "@/plugins/keycloak";
import { useCounterMixin } from "@/stores/mixin";
import { useManageDataStore } from "@/modules/01_metadata/store";
import type {
RequestItemsHistoryObject,
RequestItemsPublishHistoryObject,
Columns,
} from "@/modules/01_metadata/interface/request/person/Relationship";
import type { ResponseHistoryObject } from "@/modules/01_metadata/interface/response/person/Relationship";
import HistoryTable from "@/components/TableHistory.vue";
import { useDataStore } from "@/stores/data";
const props = defineProps({
fetchDataComponent: {
type: Function,
default: () => console.log("not function"),
},
});
const dataStore = useDataStore();
const { loaderPage } = dataStore;
const mixin = useCounterMixin();
const { success, dateText, messageError } = mixin;
const store = useManageDataStore();
const { manageData, changeManageColumns } = store;
const rows = ref<RequestItemsHistoryObject[]>([]); //list data table
const rowsHistory = ref<RequestItemsHistoryObject[]>([]); //select data history
const rawHistory = ref<RequestItemsHistoryObject[]>([]); //raw data history
const tittleHistory = ref<string>("ประวัติแก้ไขสถานภาพ"); //
const myForm = ref<any>(null); //ref
const filter = ref<string>(""); //search data table
const filterHistory = ref<string>(""); //search data table history
const modalHistory = ref<boolean>(false); //modal
const edit = ref<boolean>(false); //
const idVersion = ref<string>(""); //id data mongodb
const version = ref<string>("published"); // published= draft=
const updateData = ref<boolean>(false); //
const checkValidate = ref<boolean>(false);
const columns = ref<QTableProps["columns"]>([
{
name: "name",
align: "left",
label: "สถานภาพ",
sortable: true,
field: "name",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "createdAt",
align: "center",
label: "วันที่สร้าง",
sortable: true,
field: "createdAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdatedAt",
align: "center",
label: "วันที่แก้ไข",
sortable: true,
field: "lastUpdatedAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdateFullName",
align: "left",
label: "ผู้ดำเนินการ",
sortable: true,
field: "lastUpdateFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "isActive",
align: "left",
label: "สถานะ",
sortable: true,
field: "isActive",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumns = ref<String[]>([]);
manageData.person.relationship.columns.length == 0
? (visibleColumns.value = [
"name",
"createdAt",
"lastUpdatedAt",
"lastUpdateFullName",
"isActive",
])
: (visibleColumns.value = manageData.person.relationship.columns);
const columnsHistory = ref<QTableProps["columns"]>([
{
name: "name",
align: "left",
label: "สถานภาพ",
sortable: true,
field: "name",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdatedAt",
align: "center",
label: "วันที่แก้ไข",
sortable: true,
field: "lastUpdatedAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdateFullName",
align: "left",
label: "ผู้ดำเนินการ",
sortable: true,
field: "lastUpdateFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "isActive",
align: "left",
label: "สถานะ",
sortable: true,
field: "isActive",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumnsHistory = ref<String[]>([
"name",
"lastUpdatedAt",
"lastUpdateFullName",
"isActive",
]);
/**
* เมอเขาหนานจะเรยกฟงชนนอน(get list data)
*/
onMounted(async () => {
await fetchData();
await fetchHistory();
});
watch(visibleColumns, async (count: String[], prevCount: String[]) => {
await changeManageColumns(1, "relationship", count);
});
/**
* แจงเตอนขอมลในกรณ success
*/
const $q = useQuasar();
/**
* งก get data าส
*/
const fetchData = async () => {
await props.fetchDataComponent();
rows.value.splice(0);
loaderPage(true);
await http
.get(config.API.listRelationshipHistory)
.then((res) => {
let data = res.data.result;
version.value = data.version; // published= draft=
idVersion.value = data.id; // id mongodb
data.items.map((e: RequestItemsHistoryObject) => {
rows.value.push({
id: e.id,
name: e.name,
createdAt: e.createdAt,
lastUpdatedAt: e.lastUpdatedAt,
lastUpdateFullName: e.lastUpdateFullName,
isActive: e.isActive,
createdFullName: e.createdFullName,
createdUserId: e.createdUserId,
lastUpdateUserId: e.lastUpdateUserId,
});
});
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
updateData.value = false;
loaderPage(false);
});
};
/**
* งชนดอมลประวแกไขขอมลทงหมด
*/
const fetchHistory = async () => {
loaderPage(true);
await http
.get(config.API.listRelationshipPublishedHistory)
.then((res) => {
const data = res.data.result;
rawHistory.value = [];
if (data.length > 0) {
data.map((e: RequestItemsPublishHistoryObject) => {
e.items.map((i: RequestItemsHistoryObject) => {
rawHistory.value.push({
createdAt: i.createdAt,
createdFullName: i.createdFullName,
createdUserId: i.createdUserId,
id: i.id,
isActive: i.isActive,
lastUpdateFullName: i.lastUpdateFullName,
lastUpdateUserId: i.lastUpdateUserId,
lastUpdatedAt: i.lastUpdatedAt,
name: i.name,
});
});
});
}
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
loaderPage(false);
});
};
/**
* งก clear data แบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
*/
const clearPublishedData = async () => {
loaderPage(true);
await http
.delete(config.API.listRelationshipHistory)
.then((res) => {
success($q, "ลบข้อมูลร่างสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchHistory();
await fetchData();
});
};
/**
* งกนเผยแพรแบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
*/
const publishedData = async () => {
loaderPage(true);
await http
.get(config.API.listRelationshipPublished)
.then((res) => {
success($q, "เผยแพร่ข้อมูลสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchData();
});
};
/**
* งกนเพมขอม
*/
const clickAdd = async () => {
const filterRowNull = rows.value.filter(
(f: RequestItemsHistoryObject) =>
f.id === "00000000-0000-0000-0000-000000000000" && f.name == "" // array
);
if (filterRowNull.length == 0) {
//
rows.value.push({
createdAt: new Date(),
createdFullName: "",
createdUserId: "",
id: "00000000-0000-0000-0000-000000000000",
isActive: true,
lastUpdateFullName:
keycloak.tokenParsed == null ? "" : keycloak.tokenParsed.name,
lastUpdateUserId: "",
lastUpdatedAt: new Date(),
name: "",
});
updateData.value = true;
}
};
/**
* งกนบนทกแบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
* publish เมอบนทกแบบรางแลวจะเผยแพรเลยไหม true=นทกและเผยแพร false=นทกอยางเดยว
*/
const save = async (publish: boolean) => {
await validateData();
if (checkValidate.value == false) return;
rows.value.map((e: ResponseHistoryObject) => ({
// data backend
id: e.id,
createdAt: e.createdAt,
lastUpdatedAt: e.lastUpdatedAt,
name: e.name,
isActive: e.isActive,
createdFullName: e.createdFullName,
createdUserId: e.createdUserId,
lastUpdateFullName: e.lastUpdateFullName,
lastUpdateUserId: e.lastUpdateUserId,
}));
loaderPage(true);
await http
.post(config.API.listRelationshipHistoryId(idVersion.value), {
id: idVersion.value,
version: "draft",
items: rows.value,
})
.then(async (res) => {
if (publish === false) {
success($q, "บันทึกข้อมูลร่างสำเร็จ");
await fetchData(); // get data
} else {
await publishedData(); //
}
edit.value = false;
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
loaderPage(false);
});
};
/**
* เชคชอซำกบขอมลทอยแล
* @param val input
*/
const checkDupDataName = (val: string) => {
const filterNameNull = rows.value.filter(
(f: RequestItemsHistoryObject) => f.name == val
); //
if (filterNameNull.length > 1) {
return false;
}
return true;
};
/**
* งกนปมแกไข ให get data มาใหม
*/
const clickEdit = async () => {
await fetchData();
};
/**
* งกนปมบนทกแบบราง
*/
const clickSave = async () => {
await save(false);
};
/**
* งกนปมลบแบบราง
*/
const clickDelete = async () => {
await clearPublishedData();
};
/**
* งกนปมยกเลกการแกไขขอม
*/
const clickCancel = async () => {
edit.value = false;
await fetchData();
};
/**
* งกนปมเผยแพรอม
* เชคขอมลกอนวาใน array กรอกขอมลครบไหมถาครบกใหเผยแพรได
* าคาใน array ไมอมลใน row จะใหนทกได
*/
const clickPublish = async () => {
if (myForm.value !== null) {
myForm.value.validate().then(async (result: boolean) => {
if (result) {
await save(true);
}
});
} else {
await save(true);
}
};
/**
* งกนปมลบ row data
* @param val data ใน row จะลบ
*/
const clickDeleteRow = (val: RequestItemsHistoryObject) => {
rows.value = rows.value.filter((x: RequestItemsHistoryObject) => x !== val);
updateData.value = true;
};
/**
* งกนเช input ามการแกไขหรอย
*/
const clickEditRow = () => {
myForm.value.validate(false);
updateData.value = true;
};
/**
* งชนดอมลประวแกไขขอมลทเลอก
* @param row อม row ประวการแกไข
*/
const clickHistory = async (row: RequestItemsHistoryObject) => {
modalHistory.value = true;
rowsHistory.value = rawHistory.value.filter(
(f: RequestItemsHistoryObject) => f.id == row.id
);
};
/**
* งกนแปลง date เปนภาษาไทย
* @param value นท type datetime จะแปลงเปนไทย
*/
const textDate = (value: Date) => {
return dateText(value);
};
/**
* validate component
*/
const validateData = async () => {
checkValidate.value = true;
await myForm.value.validate().then((result: boolean) => {
if (result == false) {
checkValidate.value = false;
}
});
};
</script>
<style>
/* สีของnoti */
.my-notif-class {
background: rgba(33, 186, 69, 0.5) !important;
color: #008f17 !important;
}
</style>

View file

@ -0,0 +1,660 @@
<!-- tab ศาสนา หนาจดการขอมลหล/อมลเกยวกบบคคล -->
<template>
<div>
<q-form ref="myForm">
<data-table
:rows="rows"
:columns="columns"
:filter="filter"
:visible-columns="visibleColumns"
v-model:inputfilter="filter"
v-model:inputvisible="visibleColumns"
v-model:editvisible="edit"
:add="clickAdd"
:edit="clickEdit"
:save="clickSave"
:deleted="clickDelete"
:cancel="clickCancel"
:publish="clickPublish"
:validate="validateData"
:publicData="version === 'published'"
:updateData="updateData"
:history="true"
>
<template #columns="props">
<q-tr :props="props" v-if="edit == false">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.name == 'isActive'" class="">
<q-icon
v-if="col.value == false"
name="mdi-close"
color="red"
class="text-h5"
/>
<q-icon
v-else
name="mdi-check"
color="positive"
class="text-h5"
/>
</div>
<div v-else-if="col.name == 'createdAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else-if="col.name == 'lastUpdatedAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else class="">
{{ col.value }}
</div>
</q-td>
<q-td auto-width>
<q-btn
color="info"
flat
dense
round
size="14px"
icon="mdi-history"
@click="clickHistory(props.row)"
/>
</q-td>
</q-tr>
<q-tr :props="props" v-if="edit == true" class="items-center">
<q-td key="name" :props="props" v-if="props.row.name !== undefined">
<q-input
class=""
outlined
@update:model-value="clickEditRow"
v-model="props.row.name"
dense
lazy-rules
autofocus
hide-bottom-space
:rules="[
(val) => (val && val.length > 0) || 'กรุณากรอกข้อมูลให้ครบ',
(val) =>
checkDupDataName(val) || 'ชื่อซ้ำกันกับข้อมูลที่มีอยู่แล้ว',
]"
></q-input>
</q-td>
<q-td
key="createdAt"
:props="props"
v-if="props.row.createdAt !== undefined"
>
<div class="">
{{ textDate(props.row.createdAt) }}
</div>
</q-td>
<q-td key="lastUpdatedAt" :props="props">
<div class="">
{{ textDate(props.row.lastUpdatedAt) }}
</div>
</q-td>
<q-td
key="lastUpdateFullName"
:props="props"
v-if="props.row.lastUpdateFullName !== undefined"
class=""
>
{{ props.row.lastUpdateFullName }}
</q-td>
<q-td
key="isActive"
:props="props"
v-if="props.row.isActive !== undefined"
>
<q-toggle
v-model="props.row.isActive"
dense
size="34px"
color="positive"
@update:model-value="clickEditRow"
/>
</q-td>
<q-td auto-width>
<q-btn
v-if="props.row.id === '00000000-0000-0000-0000-000000000000'"
color="red"
flat
dense
round
size="14px"
icon="mdi-trash-can-outline"
@click="clickDeleteRow(props.row)"
/>
<q-btn
v-if="props.row.id !== '00000000-0000-0000-0000-000000000000'"
color="info"
flat
dense
round
size="14px"
icon="mdi-history"
@click="clickHistory(props.row)"
/>
</q-td>
</q-tr>
</template>
</data-table>
</q-form>
</div>
<HistoryTable
:rows="rowsHistory"
:columns="columnsHistory"
:filter="filterHistory"
:visible-columns="visibleColumnsHistory"
v-model:modal="modalHistory"
v-model:inputfilter="filterHistory"
v-model:inputvisible="visibleColumnsHistory"
v-model:tittle="tittleHistory"
>
<template #columns="props">
<q-tr :props="props">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.name == 'isActive'" class="">
<q-icon
v-if="col.value == false"
name="mdi-close"
color="red"
class="text-h5"
/>
<q-icon v-else name="mdi-check" color="positive" class="text-h5" />
</div>
<div v-else-if="col.name == 'lastUpdatedAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else class="">
{{ col.value }}
</div>
</q-td>
</q-tr>
</template>
</HistoryTable>
</template>
<script setup lang="ts">
import type { QTableProps } from "quasar";
import { useQuasar } from "quasar";
import { onMounted, ref, watch } from "vue";
import http from "@/plugins/http";
import config from "@/app.config";
import keycloak from "@/plugins/keycloak";
import { useCounterMixin } from "@/stores/mixin";
import { useManageDataStore } from "@/modules/01_metadata/store";
import type {
RequestItemsHistoryObject,
RequestItemsPublishHistoryObject,
Columns,
} from "@/modules/01_metadata/interface/request/person/Religion";
import type { ResponseHistoryObject } from "@/modules/01_metadata/interface/response/person/Religion";
import HistoryTable from "@/components/TableHistory.vue";
import { useDataStore } from "@/stores/data";
const props = defineProps({
fetchDataComponent: {
type: Function,
default: () => console.log("not function"),
},
});
const dataStore = useDataStore();
const { loaderPage } = dataStore;
const mixin = useCounterMixin();
const { success, dateText, messageError } = mixin;
const store = useManageDataStore();
const { manageData, changeManageColumns } = store;
const rows = ref<RequestItemsHistoryObject[]>([]); //list data table
const rowsHistory = ref<RequestItemsHistoryObject[]>([]); //select data history
const rawHistory = ref<RequestItemsHistoryObject[]>([]); //raw data history
const tittleHistory = ref<string>("ประวัติแก้ไขศาสนา"); //
const myForm = ref<any>(null); //ref
const filter = ref<string>(""); //search data table
const filterHistory = ref<string>(""); //search data table history
const modalHistory = ref<boolean>(false); //modal
const edit = ref<boolean>(false); //
const idVersion = ref<string>(""); //id data mongodb
const version = ref<string>("published"); // published= draft=
const updateData = ref<boolean>(false); //
const checkValidate = ref<boolean>(false);
const columns = ref<QTableProps["columns"]>([
{
name: "name",
align: "left",
label: "ศาสนา",
sortable: true,
field: "name",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "createdAt",
align: "center",
label: "วันที่สร้าง",
sortable: true,
field: "createdAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdatedAt",
align: "center",
label: "วันที่แก้ไข",
sortable: true,
field: "lastUpdatedAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdateFullName",
align: "left",
label: "ผู้ดำเนินการ",
sortable: true,
field: "lastUpdateFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "isActive",
align: "left",
label: "สถานะ",
sortable: true,
field: "isActive",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumns = ref<String[]>([]);
manageData.person.religion.columns.length == 0
? (visibleColumns.value = [
"name",
"createdAt",
"lastUpdatedAt",
"lastUpdateFullName",
"isActive",
])
: (visibleColumns.value = manageData.person.religion.columns);
const columnsHistory = ref<QTableProps["columns"]>([
{
name: "name",
align: "left",
label: "ศาสนา",
sortable: true,
field: "name",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdatedAt",
align: "center",
label: "วันที่แก้ไข",
sortable: true,
field: "lastUpdatedAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdateFullName",
align: "left",
label: "ผู้ดำเนินการ",
sortable: true,
field: "lastUpdateFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "isActive",
align: "left",
label: "สถานะ",
sortable: true,
field: "isActive",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumnsHistory = ref<String[]>([
"name",
"lastUpdatedAt",
"lastUpdateFullName",
"isActive",
]);
/**
* เมอเขาหนานจะเรยกฟงชนนอน(get list data)
*/
onMounted(async () => {
await fetchData();
await fetchHistory();
});
watch(visibleColumns, async (count: String[], prevCount: String[]) => {
await changeManageColumns(1, "religion", count);
});
/**
* แจงเตอนขอมลในกรณ success
*/
const $q = useQuasar();
/**
* งก get data าส
*/
const fetchData = async () => {
await props.fetchDataComponent();
rows.value.splice(0);
loaderPage(true);
await http
.get(config.API.listReligionHistory)
.then((res) => {
let data = res.data.result;
version.value = data.version; // published= draft=
idVersion.value = data.id; // id mongodb
data.items.map((e: RequestItemsHistoryObject) => {
rows.value.push({
id: e.id,
name: e.name,
createdAt: e.createdAt,
lastUpdatedAt: e.lastUpdatedAt,
lastUpdateFullName: e.lastUpdateFullName,
isActive: e.isActive,
createdFullName: e.createdFullName,
createdUserId: e.createdUserId,
lastUpdateUserId: e.lastUpdateUserId,
});
});
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
updateData.value = false;
loaderPage(false);
});
};
/**
* งชนดอมลประวแกไขขอมลทงหมด
*/
const fetchHistory = async () => {
loaderPage(true);
await http
.get(config.API.listReligionPublishedHistory)
.then((res) => {
const data = res.data.result;
rawHistory.value = [];
if (data.length > 0) {
data.map((e: RequestItemsPublishHistoryObject) => {
e.items.map((i: RequestItemsHistoryObject) => {
rawHistory.value.push({
createdAt: i.createdAt,
createdFullName: i.createdFullName,
createdUserId: i.createdUserId,
id: i.id,
isActive: i.isActive,
lastUpdateFullName: i.lastUpdateFullName,
lastUpdateUserId: i.lastUpdateUserId,
lastUpdatedAt: i.lastUpdatedAt,
name: i.name,
});
});
});
}
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
loaderPage(false);
});
};
/**
* งก clear data แบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
*/
const clearPublishedData = async () => {
loaderPage(true);
await http
.delete(config.API.listReligionHistory)
.then((res) => {
success($q, "ลบข้อมูลร่างสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchHistory();
await fetchData();
});
};
/**
* งกนเผยแพรแบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
*/
const publishedData = async () => {
loaderPage(true);
await http
.get(config.API.listReligionPublished)
.then((res) => {
success($q, "เผยแพร่ข้อมูลสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchData();
});
};
/**
* งกนเพมขอม
*/
const clickAdd = async () => {
const filterRowNull = rows.value.filter(
(f: RequestItemsHistoryObject) =>
f.id === "00000000-0000-0000-0000-000000000000" && f.name == "" // array
);
if (filterRowNull.length == 0) {
//
rows.value.push({
createdAt: new Date(),
createdFullName: "",
createdUserId: "",
id: "00000000-0000-0000-0000-000000000000",
isActive: true,
lastUpdateFullName:
keycloak.tokenParsed == null ? "" : keycloak.tokenParsed.name,
lastUpdateUserId: "",
lastUpdatedAt: new Date(),
name: "",
});
updateData.value = true;
}
};
/**
* งกนบนทกแบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
* publish เมอบนทกแบบรางแลวจะเผยแพรเลยไหม true=นทกและเผยแพร false=นทกอยางเดยว
*/
const save = async (publish: boolean) => {
await validateData();
if (checkValidate.value == false) return;
rows.value.map((e: ResponseHistoryObject) => ({
// data backend
id: e.id,
createdAt: e.createdAt,
lastUpdatedAt: e.lastUpdatedAt,
name: e.name,
isActive: e.isActive,
createdFullName: e.createdFullName,
createdUserId: e.createdUserId,
lastUpdateFullName: e.lastUpdateFullName,
lastUpdateUserId: e.lastUpdateUserId,
}));
loaderPage(true);
await http
.post(config.API.listReligionHistoryId(idVersion.value), {
id: idVersion.value,
version: "draft",
items: rows.value,
})
.then(async (res) => {
if (publish === false) {
success($q, "บันทึกข้อมูลร่างสำเร็จ");
await fetchData(); // get data
} else {
await publishedData(); //
}
edit.value = false;
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
loaderPage(false);
});
};
/**
* เชคชอซำกบขอมลทอยแล
* @param val input
*/
const checkDupDataName = (val: string) => {
const filterNameNull = rows.value.filter(
(f: RequestItemsHistoryObject) => f.name == val
); //
if (filterNameNull.length > 1) {
return false;
}
return true;
};
/**
* งกนปมแกไข ให get data มาใหม
*/
const clickEdit = async () => {
await fetchData();
};
/**
* งกนปมบนทกแบบราง
*/
const clickSave = async () => {
await save(false);
};
/**
* งกนปมลบแบบราง
*/
const clickDelete = async () => {
await clearPublishedData();
};
/**
* งกนปมยกเลกการแกไขขอม
*/
const clickCancel = async () => {
edit.value = false;
await fetchData();
};
/**
* งกนปมเผยแพรอม
* เชคขอมลกอนวาใน array กรอกขอมลครบไหมถาครบกใหเผยแพรได
* าคาใน array ไมอมลใน row จะใหนทกได
*/
const clickPublish = async () => {
if (myForm.value !== null) {
myForm.value.validate().then(async (result: boolean) => {
if (result) {
await save(true);
}
});
} else {
await save(true);
}
};
/**
* งกนปมลบ row data
* @param val data ใน row จะลบ
*/
const clickDeleteRow = (val: RequestItemsHistoryObject) => {
rows.value = rows.value.filter((x: RequestItemsHistoryObject) => x !== val);
updateData.value = true;
};
/**
* งกนเช input ามการแกไขหรอย
*/
const clickEditRow = () => {
myForm.value.validate(false);
updateData.value = true;
};
/**
* งชนดอมลประวแกไขขอมลทเลอก
* @param row อม row ประวการแกไข
*/
const clickHistory = async (row: RequestItemsHistoryObject) => {
modalHistory.value = true;
rowsHistory.value = rawHistory.value.filter(
(f: RequestItemsHistoryObject) => f.id == row.id
);
};
/**
* งกนแปลง date เปนภาษาไทย
* @param value นท type datetime จะแปลงเปนไทย
*/
const textDate = (value: Date) => {
return dateText(value);
};
/**
* validate component
*/
const validateData = async () => {
checkValidate.value = true;
await myForm.value.validate().then((result: boolean) => {
if (result == false) {
checkValidate.value = false;
}
});
};
</script>
<style>
/* สีของnoti */
.my-notif-class {
background: rgba(33, 186, 69, 0.5) !important;
color: #008f17 !important;
}
</style>

View file

@ -0,0 +1,769 @@
<!-- tab แขวง/ตำบล หนาจดการขอมลหล/อมลเกยวกบบคคล -->
<template>
<div class="row items-center q-mb-sm q-mr-md q-ml-sm">
<q-btn icon="chevron_left" color="grey" flat dense @click="goToProvince()">
<q-tooltip>กล</q-tooltip>
</q-btn>
<div class="text-body1 text-weight-bold">การจดการขอมลแขวง/ตำบล</div>
<q-space />
<div @click="goToManage()" class="cursor-pointer">
การจดการขอมลจงหว /
</div>
<div @click="goToProvince()" class="cursor-pointer">
ดการขอมลเขต/อำเภอ
<span class="text-primary text-weight-bold"> {{ districtName }}</span>
</div>
</div>
<q-card flat bordered class="q-pa-md row col-12">
<div class="col-xs-12">
<div class="q-mt-md">
<q-form ref="myForm">
<data-table
:rows="rows"
:columns="columns"
:filter="filter"
:visible-columns="visibleColumns"
v-model:inputfilter="filter"
v-model:inputvisible="visibleColumns"
v-model:editvisible="edit"
:add="clickAdd"
:edit="clickEdit"
:save="clickSave"
:deleted="clickDelete"
:cancel="clickCancel"
:publish="clickPublish"
:validate="validateData"
:publicData="version === 'published'"
:updateData="updateData"
:history="true"
>
<template #columns="props">
<q-tr :props="props" v-if="edit == false">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.name == 'isActive'" class="">
<q-icon
v-if="col.value == false"
name="mdi-close"
color="red"
class="text-h5"
/>
<q-icon
v-else
name="mdi-check"
color="positive"
class="text-h5"
/>
</div>
<div v-else-if="col.name == 'createdAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else-if="col.name == 'lastUpdatedAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else class="">
{{ col.value }}
</div>
</q-td>
<q-td auto-width>
<q-btn
color="info"
flat
dense
round
size="14px"
icon="mdi-history"
@click="clickHistory(props.row)"
/>
</q-td>
</q-tr>
<q-tr :props="props" v-if="edit == true">
<q-td
key="name"
:props="props"
v-if="props.row.name !== undefined"
>
<q-input
class=""
outlined
@update:model-value="clickEditRow"
v-model="props.row.name"
dense
lazy-rules
autofocus
hide-bottom-space
:rules="[
(val) =>
(val && val.length > 0) || 'กรุณากรอกข้อมูลให้ครบ',
(val) =>
checkDupDataName(val) ||
'ชื่อซ้ำกันกับข้อมูลที่มีอยู่แล้ว',
]"
></q-input>
</q-td>
<q-td
key="zipCode"
:props="props"
v-if="props.row.zipCode !== undefined"
>
<q-input
class=""
outlined
@update:model-value="clickEditRow"
v-model="props.row.zipCode"
dense
lazy-rules
hide-bottom-space
:rules="[
(val) =>
(val && val.length > 0) || 'กรุณากรอกข้อมูลให้ครบ',
]"
></q-input>
</q-td>
<q-td
key="createdAt"
:props="props"
v-if="props.row.createdAt !== undefined"
>
<div class="">
{{ textDate(props.row.createdAt) }}
</div>
</q-td>
<q-td key="lastUpdatedAt" :props="props">
<div class="">
{{ textDate(props.row.lastUpdatedAt) }}
</div>
</q-td>
<q-td
key="lastUpdateFullName"
:props="props"
v-if="props.row.lastUpdateFullName !== undefined"
class=""
>
{{ props.row.lastUpdateFullName }}
</q-td>
<q-td
key="isActive"
:props="props"
v-if="props.row.isActive !== undefined"
>
<q-toggle
v-model="props.row.isActive"
dense
color="green"
@update:model-value="clickEditRow"
/>
</q-td>
<q-td auto-width>
<q-btn
v-if="
props.row.id === '00000000-0000-0000-0000-000000000000'
"
color="red"
flat
dense
round
size="14px"
icon="mdi-trash-can-outline"
@click="clickDeleteRow(props.row)"
/>
<q-btn
v-if="
props.row.id !== '00000000-0000-0000-0000-000000000000'
"
color="info"
flat
dense
round
size="14px"
icon="mdi-history"
@click="clickHistory(props.row)"
/>
</q-td>
</q-tr>
</template>
</data-table>
</q-form>
</div>
</div>
</q-card>
<HistoryTable
:rows="rowsHistory"
:columns="columnsHistory"
:filter="filterHistory"
:visible-columns="visibleColumnsHistory"
v-model:modal="modalHistory"
v-model:inputfilter="filterHistory"
v-model:inputvisible="visibleColumnsHistory"
v-model:tittle="tittleHistory"
>
<template #columns="props">
<q-tr :props="props">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.name == 'isActive'" class="">
<q-icon
v-if="col.value == false"
name="mdi-close"
color="red"
class="text-h5"
/>
<q-icon v-else name="mdi-check" color="positive" class="text-h5" />
</div>
<div v-else-if="col.name == 'lastUpdatedAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else class="">
{{ col.value }}
</div>
</q-td>
</q-tr>
</template>
</HistoryTable>
</template>
<script setup lang="ts">
import type { QTableProps } from "quasar";
import { useQuasar } from "quasar";
import { onMounted, ref, watch } from "vue";
import http from "@/plugins/http";
import config from "@/app.config";
import keycloak from "@/plugins/keycloak";
import { useCounterMixin } from "@/stores/mixin";
import { useManageDataStore } from "@/modules/01_metadata/store";
import type {
RequestItemsHistoryObject,
RequestItemsPublishHistoryObject,
Columns,
} from "@/modules/01_metadata/interface/request/person/SubDistrict";
import type { ResponseHistoryObject } from "@/modules/01_metadata/interface/response/person/SubDistrict";
import HistoryTable from "@/components/TableHistory.vue";
import { useRoute, useRouter } from "vue-router";
import { useDataStore } from "@/stores/data";
const mixin = useCounterMixin();
const { success, dateText, messageError } = mixin;
const store = useManageDataStore();
const dataStore = useDataStore();
const { manageData, changeManageColumns, changeManageCurrentTab } = store;
const { loaderPage } = dataStore; // load api
const rows = ref<RequestItemsHistoryObject[]>([]); //list data table
const rowsHistory = ref<RequestItemsHistoryObject[]>([]); //select data history
const rawHistory = ref<RequestItemsHistoryObject[]>([]); //raw data history
const tittleHistory = ref<string>("ประวัติแก้ไขแขวง/ตำบล"); //
const myForm = ref<any>(null); //ref
const filter = ref<string>(""); //search data table
const filterHistory = ref<string>(""); //search data table history
const modalHistory = ref<boolean>(false); //modal
const edit = ref<boolean>(false); //
const idVersion = ref<string>(""); //id data mongodb
const version = ref<string>("published"); // published= draft=
const updateData = ref<boolean>(false); //
const router = useRouter();
const route = useRoute();
const districtName = ref<string>("เขตพระนคร"); //
const provinceId = ref<string | string[]>(route.params.province); // Id
const districtId = ref<string | string[]>(route.params.district); // Id
const checkValidate = ref<boolean>(false);
const columns = ref<QTableProps["columns"]>([
{
name: "name",
align: "left",
label: "แขวง/ตำบล",
sortable: true,
field: "name",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "zipCode",
align: "left",
label: "รหัสไปรษณีย์",
sortable: true,
field: "zipCode",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "createdAt",
align: "center",
label: "วันที่สร้าง",
sortable: true,
field: "createdAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdatedAt",
align: "center",
label: "วันที่แก้ไข",
sortable: true,
field: "lastUpdatedAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdateFullName",
align: "left",
label: "ผู้ดำเนินการ",
sortable: true,
field: "lastUpdateFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "isActive",
align: "left",
label: "สถานะ",
sortable: true,
field: "isActive",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumns = ref<String[]>([]);
manageData.person.subDistrict.columns.length == 0
? (visibleColumns.value = [
"name",
"zipCode",
"createdAt",
"lastUpdatedAt",
"lastUpdateFullName",
"isActive",
])
: (visibleColumns.value = manageData.person.subDistrict.columns);
const columnsHistory = ref<QTableProps["columns"]>([
{
name: "name",
align: "left",
label: "แขวง/ตำบล",
sortable: true,
field: "name",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "zipCode",
align: "left",
label: "รหัสไปรษณีย์",
sortable: true,
field: "zipCode",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdatedAt",
align: "center",
label: "วันที่แก้ไข",
sortable: true,
field: "lastUpdatedAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdateFullName",
align: "left",
label: "ผู้ดำเนินการ",
sortable: true,
field: "lastUpdateFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "isActive",
align: "left",
label: "สถานะ",
sortable: true,
field: "isActive",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumnsHistory = ref<String[]>([
"name",
"zipCode",
"lastUpdatedAt",
"lastUpdateFullName",
"isActive",
]);
/**
* เมอเขาหนานจะเรยกฟงชนนอน(get list data)
*/
onMounted(async () => {
await fetchData();
await fetchHistory();
});
watch(visibleColumns, async (count: String[], prevCount: String[]) => {
await changeManageColumns(1, "subDistrict", count);
});
/**
* แจงเตอนขอมลในกรณ success
*/
const $q = useQuasar();
/**
* งก get data าส
*/
const fetchData = async () => {
rows.value.splice(0);
loaderPage(true);
await http
.get(
config.API.listSubDistrictHistoryProvinceId(
provinceId.value,
districtId.value
)
)
.then((res) => {
let data = res.data.result;
version.value = data.version; // published= draft=
idVersion.value = data.id; // id mongodb
districtName.value = data.districtName.result;
data.items.map((e: RequestItemsHistoryObject) => {
rows.value.push({
id: e.id,
name: e.name,
zipCode: e.zipCode,
createdAt: e.createdAt,
lastUpdatedAt: e.lastUpdatedAt,
lastUpdateFullName: e.lastUpdateFullName,
isActive: e.isActive,
createdFullName: e.createdFullName,
createdUserId: e.createdUserId,
lastUpdateUserId: e.lastUpdateUserId,
});
});
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
updateData.value = false;
loaderPage(false);
});
};
/**
* งชนดอมลประวแกไขขอมลทงหมด
*/
const fetchHistory = async () => {
loaderPage(true);
await http
.get(config.API.listSubDistrictPublishedHistory(districtId.value))
.then((res) => {
const data = res.data.result;
rawHistory.value = [];
if (data.length > 0) {
data.map((e: RequestItemsPublishHistoryObject) => {
e.items.map((i: RequestItemsHistoryObject) => {
rawHistory.value.push({
createdAt: i.createdAt,
createdFullName: i.createdFullName,
createdUserId: i.createdUserId,
id: i.id,
isActive: i.isActive,
lastUpdateFullName: i.lastUpdateFullName,
lastUpdateUserId: i.lastUpdateUserId,
lastUpdatedAt: i.lastUpdatedAt,
name: i.name,
zipCode: i.zipCode,
});
});
});
}
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
loaderPage(false);
});
};
/**
* งก clear data แบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
*/
const clearPublishedData = async () => {
loaderPage(true);
await http
.delete(config.API.listSubDistrictHistoryId(districtId.value))
.then((res) => {
success($q, "ลบข้อมูลร่างสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchHistory();
await fetchData();
});
};
/**
* งกนเผยแพรแบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
*/
const publishedData = async () => {
loaderPage(true);
await http
.get(config.API.listProvincePublished)
.then((res) => {
success($q, "เผยแพร่ข้อมูลสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchData();
});
};
/**
* งกนเพมขอม
*/
const clickAdd = async () => {
const filterRowNull = rows.value.filter(
(f: RequestItemsHistoryObject) =>
f.id === "00000000-0000-0000-0000-000000000000" &&
(f.name == "" || f.zipCode == "") // array
);
if (filterRowNull.length == 0) {
//
rows.value.push({
createdAt: new Date(),
createdFullName: "",
createdUserId: "",
id: "00000000-0000-0000-0000-000000000000",
isActive: true,
lastUpdateFullName:
keycloak.tokenParsed == null ? "" : keycloak.tokenParsed.name,
lastUpdateUserId: "",
lastUpdatedAt: new Date(),
name: "",
zipCode: "",
});
updateData.value = true;
}
};
/**
* งกนบนทกแบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
* publish เมอบนทกแบบรางแลวจะเผยแพรเลยไหม true=นทกและเผยแพร false=นทกอยางเดยว
*/
const save = async (publish: boolean) => {
await validateData();
if (checkValidate.value == false) return;
rows.value.map((e: ResponseHistoryObject) => ({
// data backend
id: e.id,
createdAt: e.createdAt,
lastUpdatedAt: e.lastUpdatedAt,
name: e.name,
zipCode: e.zipCode,
isActive: e.isActive,
createdFullName: e.createdFullName,
createdUserId: e.createdUserId,
lastUpdateFullName: e.lastUpdateFullName,
lastUpdateUserId: e.lastUpdateUserId,
}));
loaderPage(true);
await http
.post(config.API.listSubDistrictHistoryId(idVersion.value), {
id: idVersion.value,
districtId: districtId.value,
version: "draft",
items: rows.value,
})
.then(async (res) => {
if (publish === false) {
success($q, "บันทึกข้อมูลร่างสำเร็จ");
await fetchData(); // get data
} else {
await publishedData(); //
}
edit.value = false;
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
loaderPage(false);
});
};
/**
* เชคชอซำกบขอมลทอยแล
* @param val input
*/
const checkDupDataName = (val: string) => {
const filterNameNull = rows.value.filter(
(f: RequestItemsHistoryObject) => f.name == val
); //
if (filterNameNull.length > 1) {
return false;
}
return true;
};
/**
* เชครหสไปรษณำกบขอมลทอยแล
* @param val input รหสไปรษณ
*/
const checkDupDataZipCode = (val: string) => {
const filterZipCodeNull = rows.value.filter(
(f: RequestItemsHistoryObject) => f.zipCode == val
); //
if (filterZipCodeNull.length > 1) {
return false;
}
return true;
};
/**
* งกนปมแกไข ให get data มาใหม
*/
const clickEdit = async () => {
await fetchData();
};
/**
* งกนปมบนทกแบบราง
*/
const clickSave = async () => {
await save(false);
};
/**
* งกนปมลบแบบราง
*/
const clickDelete = async () => {
await clearPublishedData();
};
/**
* งกนปมยกเลกการแกไขขอม
*/
const clickCancel = async () => {
edit.value = false;
await fetchData();
};
/**
* งกนปมเผยแพรอม
* เชคขอมลกอนวาใน array กรอกขอมลครบไหมถาครบกใหเผยแพรได
* าคาใน array ไมอมลใน row จะใหนทกได
*/
const clickPublish = async () => {
if (myForm.value !== null) {
myForm.value.validate().then(async (result: boolean) => {
if (result) {
await save(true);
}
});
} else {
await save(true);
}
};
/**
* งกนปมลบ row data
* @param val data ใน row จะลบ
*/
const clickDeleteRow = (val: RequestItemsHistoryObject) => {
rows.value = rows.value.filter((x: RequestItemsHistoryObject) => x !== val);
updateData.value = true;
};
/**
* งกนเช input ามการแกไขหรอย
*/
const clickEditRow = () => {
myForm.value.validate(false);
updateData.value = true;
};
/**
* งชนดอมลประวแกไขขอมลทเลอก
* @param row อม row ประวการแกไข
*/
const clickHistory = async (row: RequestItemsHistoryObject) => {
modalHistory.value = true;
rowsHistory.value = rawHistory.value.filter(
(f: RequestItemsHistoryObject) => f.id == row.id
);
};
/**
* งกนแปลง date เปนภาษาไทย
* @param value นท type datetime จะแปลงเปนไทย
*/
const textDate = (value: Date) => {
return dateText(value);
};
/**
* validate component
*/
const validateData = async () => {
checkValidate.value = true;
await myForm.value.validate().then((result: boolean) => {
if (result == false) {
checkValidate.value = false;
}
});
};
/**
* งกนยอนกลบไปหนาจดการขอมลหล
*/
const goToManage = () => {
changeManageCurrentTab(1, "person_province");
router.push("/metadata");
};
/**
* งกนยอนกลบไปหนาจดการเขต
*/
const goToProvince = () => {
router.push(`/metadata/province/${provinceId.value}`);
};
</script>
<style>
/* สีของnoti */
.my-notif-class {
background: rgba(33, 186, 69, 0.5) !important;
color: #008f17 !important;
}
</style>

View file

@ -0,0 +1,660 @@
<!-- tab อตำแหนงทางการบรหาร หนาจดการขอมลหล/อมลตำแหนงของขาราชการกรงเทพมหานคร -->
<template>
<div>
<q-form ref="myForm">
<data-table
:rows="rows"
:columns="columns"
:filter="filter"
:visible-columns="visibleColumns"
v-model:inputfilter="filter"
v-model:inputvisible="visibleColumns"
v-model:editvisible="edit"
:add="clickAdd"
:edit="clickEdit"
:save="clickSave"
:deleted="clickDelete"
:cancel="clickCancel"
:publish="clickPublish"
:validate="validateData"
:publicData="version === 'published'"
:updateData="updateData"
:history="true"
>
<template #columns="props">
<q-tr :props="props" v-if="edit == false">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.name == 'isActive'" class="">
<q-icon
v-if="col.value == false"
name="mdi-close"
color="red"
class="text-h5"
/>
<q-icon
v-else
name="mdi-check"
color="positive"
class="text-h5"
/>
</div>
<div v-else-if="col.name == 'createdAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else-if="col.name == 'lastUpdatedAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else class="">
{{ col.value }}
</div>
</q-td>
<q-td auto-width>
<q-btn
color="info"
flat
dense
round
size="14px"
icon="mdi-history"
@click="clickHistory(props.row)"
/>
</q-td>
</q-tr>
<q-tr :props="props" v-if="edit == true">
<q-td key="name" :props="props" v-if="props.row.name !== undefined">
<q-input
class=""
outlined
@update:model-value="clickEditRow"
v-model="props.row.name"
dense
lazy-rules
autofocus
hide-bottom-space
:rules="[
(val) => (val && val.length > 0) || 'กรุณากรอกข้อมูลให้ครบ',
(val) =>
checkDupDataName(val) || 'ชื่อซ้ำกันกับข้อมูลที่มีอยู่แล้ว',
]"
></q-input>
</q-td>
<q-td
key="createdAt"
:props="props"
v-if="props.row.createdAt !== undefined"
>
<div class="">
{{ textDate(props.row.createdAt) }}
</div>
</q-td>
<q-td key="lastUpdatedAt" :props="props">
<div class="">
{{ textDate(props.row.lastUpdatedAt) }}
</div>
</q-td>
<q-td
key="lastUpdateFullName"
:props="props"
v-if="props.row.lastUpdateFullName !== undefined"
class=""
>
{{ props.row.lastUpdateFullName }}
</q-td>
<q-td
key="isActive"
:props="props"
v-if="props.row.isActive !== undefined"
>
<q-toggle
v-model="props.row.isActive"
dense
size="34px"
color="positive"
@update:model-value="clickEditRow"
/>
</q-td>
<q-td auto-width>
<q-btn
v-if="props.row.id === '00000000-0000-0000-0000-000000000000'"
color="red"
flat
dense
round
size="14px"
icon="mdi-trash-can-outline"
@click="clickDeleteRow(props.row)"
/>
<q-btn
v-if="props.row.id !== '00000000-0000-0000-0000-000000000000'"
color="info"
flat
dense
round
size="14px"
icon="mdi-history"
@click="clickHistory(props.row)"
/>
</q-td>
</q-tr>
</template>
</data-table>
</q-form>
</div>
<HistoryTable
:rows="rowsHistory"
:columns="columnsHistory"
:filter="filterHistory"
:visible-columns="visibleColumnsHistory"
v-model:modal="modalHistory"
v-model:inputfilter="filterHistory"
v-model:inputvisible="visibleColumnsHistory"
v-model:tittle="tittleHistory"
>
<template #columns="props">
<q-tr :props="props">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.name == 'isActive'" class="">
<q-icon
v-if="col.value == false"
name="mdi-close"
color="red"
class="text-h5"
/>
<q-icon v-else name="mdi-check" color="positive" class="text-h5" />
</div>
<div v-else-if="col.name == 'lastUpdatedAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else class="">
{{ col.value }}
</div>
</q-td>
</q-tr>
</template>
</HistoryTable>
</template>
<script setup lang="ts">
import type { QTableProps } from "quasar";
import { useQuasar } from "quasar";
import { onMounted, ref, watch } from "vue";
import http from "@/plugins/http";
import config from "@/app.config";
import keycloak from "@/plugins/keycloak";
import { useCounterMixin } from "@/stores/mixin";
import { useManageDataStore } from "@/modules/01_metadata/store";
import type {
RequestItemsHistoryObject,
RequestItemsPublishHistoryObject,
Columns,
} from "@/modules/01_metadata/interface/request/position/Executive";
import type { ResponseHistoryObject } from "@/modules/01_metadata/interface/response/position/Executive";
import HistoryTable from "@/components/TableHistory.vue";
import { useDataStore } from "@/stores/data";
const props = defineProps({
fetchDataComponent: {
type: Function,
default: () => console.log("not function"),
},
});
const dataStore = useDataStore();
const { loaderPage } = dataStore;
const mixin = useCounterMixin();
const { success, dateText, messageError } = mixin;
const store = useManageDataStore();
const { manageData, changeManageColumns } = store;
const rows = ref<RequestItemsHistoryObject[]>([]); //list data table
const rowsHistory = ref<RequestItemsHistoryObject[]>([]); //select data history
const rawHistory = ref<RequestItemsHistoryObject[]>([]); //raw data history
const tittleHistory = ref<string>("ประวัติแก้ไขชื่อตำแหน่งทางการบริหาร"); //
const myForm = ref<any>(null); //ref
const filter = ref<string>(""); //search data table
const filterHistory = ref<string>(""); //search data table history
const modalHistory = ref<boolean>(false); //modal
const edit = ref<boolean>(false); //
const idVersion = ref<string>(""); //id data mongodb
const version = ref<string>("published"); // published= draft=
const updateData = ref<boolean>(false); //
const checkValidate = ref<boolean>(false);
const columns = ref<QTableProps["columns"]>([
{
name: "name",
align: "left",
label: "ชื่อตำแหน่งทางการบริหาร",
sortable: true,
field: "name",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "createdAt",
align: "center",
label: "วันที่สร้าง",
sortable: true,
field: "createdAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdatedAt",
align: "center",
label: "วันที่แก้ไข",
sortable: true,
field: "lastUpdatedAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdateFullName",
align: "left",
label: "ผู้ดำเนินการ",
sortable: true,
field: "lastUpdateFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "isActive",
align: "left",
label: "สถานะ",
sortable: true,
field: "isActive",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumns = ref<String[]>([]);
manageData.position.executive.columns.length == 0
? (visibleColumns.value = [
"name",
"createdAt",
"lastUpdatedAt",
"lastUpdateFullName",
"isActive",
])
: (visibleColumns.value = manageData.position.executive.columns);
const columnsHistory = ref<QTableProps["columns"]>([
{
name: "name",
align: "left",
label: "ชื่อตำแหน่งทางการบริหาร",
sortable: true,
field: "name",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdatedAt",
align: "center",
label: "วันที่แก้ไข",
sortable: true,
field: "lastUpdatedAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdateFullName",
align: "left",
label: "ผู้ดำเนินการ",
sortable: true,
field: "lastUpdateFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "isActive",
align: "left",
label: "สถานะ",
sortable: true,
field: "isActive",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumnsHistory = ref<String[]>([
"name",
"lastUpdatedAt",
"lastUpdateFullName",
"isActive",
]);
/**
* เมอเขาหนานจะเรยกฟงชนนอน(get list data)
*/
onMounted(async () => {
await fetchData();
await fetchHistory();
});
watch(visibleColumns, async (count: String[], prevCount: String[]) => {
await changeManageColumns(3, "executive", count);
});
/**
* แจงเตอนขอมลในกรณ success
*/
const $q = useQuasar();
/**
* งก get data าส
*/
const fetchData = async () => {
await props.fetchDataComponent();
rows.value.splice(0);
loaderPage(true);
await http
.get(config.API.listPositionExecutiveHistory)
.then((res) => {
let data = res.data.result;
version.value = data.version; // published= draft=
idVersion.value = data.id; // id mongodb
data.items.map((e: RequestItemsHistoryObject) => {
rows.value.push({
id: e.id,
name: e.name,
createdAt: e.createdAt,
lastUpdatedAt: e.lastUpdatedAt,
lastUpdateFullName: e.lastUpdateFullName,
isActive: e.isActive,
createdFullName: e.createdFullName,
createdUserId: e.createdUserId,
lastUpdateUserId: e.lastUpdateUserId,
});
});
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
updateData.value = false;
loaderPage(false);
});
};
/**
* งชนดอมลประวแกไขขอมลทงหมด
*/
const fetchHistory = async () => {
loaderPage(true);
await http
.get(config.API.listPositionExecutivePublishedHistory)
.then((res) => {
const data = res.data.result;
rawHistory.value = [];
if (data.length > 0) {
data.map((e: RequestItemsPublishHistoryObject) => {
e.items.map((i: RequestItemsHistoryObject) => {
rawHistory.value.push({
createdAt: i.createdAt,
createdFullName: i.createdFullName,
createdUserId: i.createdUserId,
id: i.id,
isActive: i.isActive,
lastUpdateFullName: i.lastUpdateFullName,
lastUpdateUserId: i.lastUpdateUserId,
lastUpdatedAt: i.lastUpdatedAt,
name: i.name,
});
});
});
}
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
loaderPage(false);
});
};
/**
* งก clear data แบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
*/
const clearPublishedData = async () => {
loaderPage(true);
await http
.delete(config.API.listPositionExecutiveHistory)
.then((res) => {
success($q, "ลบข้อมูลร่างสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchHistory();
await fetchData();
});
};
/**
* งกนเผยแพรแบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
*/
const publishedData = async () => {
loaderPage(true);
await http
.get(config.API.listPositionExecutivePublished)
.then((res) => {
success($q, "เผยแพร่ข้อมูลสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchData();
});
};
/**
* งกนเพมขอม
*/
const clickAdd = async () => {
const filterRowNull = rows.value.filter(
(f: RequestItemsHistoryObject) =>
f.id === "00000000-0000-0000-0000-000000000000" && f.name == "" // array
);
if (filterRowNull.length == 0) {
//
rows.value.push({
createdAt: new Date(),
createdFullName: "",
createdUserId: "",
id: "00000000-0000-0000-0000-000000000000",
isActive: true,
lastUpdateFullName:
keycloak.tokenParsed == null ? "" : keycloak.tokenParsed.name,
lastUpdateUserId: "",
lastUpdatedAt: new Date(),
name: "",
});
updateData.value = true;
}
};
/**
* งกนบนทกแบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
* publish เมอบนทกแบบรางแลวจะเผยแพรเลยไหม true=นทกและเผยแพร false=นทกอยางเดยว
*/
const save = async (publish: boolean) => {
await validateData();
if (checkValidate.value == false) return;
rows.value.map((e: ResponseHistoryObject) => ({
// data backend
id: e.id,
createdAt: e.createdAt,
lastUpdatedAt: e.lastUpdatedAt,
name: e.name,
isActive: e.isActive,
createdFullName: e.createdFullName,
createdUserId: e.createdUserId,
lastUpdateFullName: e.lastUpdateFullName,
lastUpdateUserId: e.lastUpdateUserId,
}));
loaderPage(true);
await http
.post(config.API.listPositionExecutiveHistoryId(idVersion.value), {
id: idVersion.value,
version: "draft",
items: rows.value,
})
.then(async (res) => {
if (publish === false) {
success($q, "บันทึกข้อมูลร่างสำเร็จ");
await fetchData(); // get data
} else {
await publishedData(); //
}
edit.value = false;
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
loaderPage(false);
});
};
/**
* เชคชอซำกบขอมลทอยแล
* @param val input
*/
const checkDupDataName = (val: string) => {
const filterNameNull = rows.value.filter(
(f: RequestItemsHistoryObject) => f.name == val
); //
if (filterNameNull.length > 1) {
return false;
}
return true;
};
/**
* งกนปมแกไข ให get data มาใหม
*/
const clickEdit = async () => {
await fetchData();
};
/**
* งกนปมบนทกแบบราง
*/
const clickSave = async () => {
await save(false);
};
/**
* งกนปมลบแบบราง
*/
const clickDelete = async () => {
await clearPublishedData();
};
/**
* งกนปมยกเลกการแกไขขอม
*/
const clickCancel = async () => {
edit.value = false;
await fetchData();
};
/**
* งกนปมเผยแพรอม
* เชคขอมลกอนวาใน array กรอกขอมลครบไหมถาครบกใหเผยแพรได
* าคาใน array ไมอมลใน row จะใหนทกได
*/
const clickPublish = async () => {
if (myForm.value !== null) {
myForm.value.validate().then(async (result: boolean) => {
if (result) {
await save(true);
}
});
} else {
await save(true);
}
};
/**
* งกนปมลบ row data
* @param val data ใน row จะลบ
*/
const clickDeleteRow = (val: RequestItemsHistoryObject) => {
rows.value = rows.value.filter((x: RequestItemsHistoryObject) => x !== val);
updateData.value = true;
};
/**
* งกนเช input ามการแกไขหรอย
*/
const clickEditRow = () => {
myForm.value.validate(false);
updateData.value = true;
};
/**
* งชนดอมลประวแกไขขอมลทเลอก
* @param row อม row ประวการแกไข
*/
const clickHistory = async (row: RequestItemsHistoryObject) => {
modalHistory.value = true;
rowsHistory.value = rawHistory.value.filter(
(f: RequestItemsHistoryObject) => f.id == row.id
);
};
/**
* งกนแปลง date เปนภาษาไทย
* @param value นท type datetime จะแปลงเปนไทย
*/
const textDate = (value: Date) => {
return dateText(value);
};
/**
* validate component
*/
const validateData = async () => {
checkValidate.value = true;
await myForm.value.validate().then((result: boolean) => {
if (result == false) {
checkValidate.value = false;
}
});
};
</script>
<style>
/* สีของnoti */
.my-notif-class {
background: rgba(33, 186, 69, 0.5) !important;
color: #008f17 !important;
}
</style>

View file

@ -0,0 +1,699 @@
<!-- tab านทางการบรหาร หนาจดการขอมลหล/อมลตำแหนงของขาราชการกรงเทพมหานคร -->
<template>
<div>
<q-form ref="myForm">
<data-table
:rows="rows"
:columns="columns"
:filter="filter"
:visible-columns="visibleColumns"
v-model:inputfilter="filter"
v-model:inputvisible="visibleColumns"
v-model:editvisible="edit"
:add="clickAdd"
:edit="clickEdit"
:save="clickSave"
:deleted="clickDelete"
:cancel="clickCancel"
:publish="clickPublish"
:validate="validateData"
:publicData="version === 'published'"
:updateData="updateData"
:history="true"
>
<template #columns="props">
<q-tr :props="props" v-if="edit == false">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.name == 'isActive'" class="">
<q-icon
v-if="col.value == false"
name="mdi-close"
color="red"
class="text-h5"
/>
<q-icon
v-else
name="mdi-check"
color="positive"
class="text-h5"
/>
</div>
<div v-else-if="col.name == 'createdAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else-if="col.name == 'lastUpdatedAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else class="">
{{ col.value }}
</div>
</q-td>
<q-td auto-width>
<q-btn
color="info"
flat
dense
round
size="14px"
icon="mdi-history"
@click="clickHistory(props.row)"
/>
</q-td>
</q-tr>
<q-tr :props="props" v-if="edit == true">
<q-td key="name" :props="props" v-if="props.row.name !== undefined">
<q-input
class=""
outlined
@update:model-value="clickEditRow"
v-model="props.row.name"
dense
lazy-rules
autofocus
hide-bottom-space
:rules="[
(val) => (val && val.length > 0) || 'กรุณากรอกข้อมูลให้ครบ',
(val) =>
checkDupDataName(val) || 'ชื่อซ้ำกันกับข้อมูลที่มีอยู่แล้ว',
]"
></q-input>
</q-td>
<q-td
key="createdAt"
:props="props"
v-if="props.row.createdAt !== undefined"
>
<div class="">
{{ textDate(props.row.createdAt) }}
</div>
</q-td>
<q-td key="lastUpdatedAt" :props="props">
<div class="">
{{ textDate(props.row.lastUpdatedAt) }}
</div>
</q-td>
<q-td
key="lastUpdateFullName"
:props="props"
v-if="props.row.lastUpdateFullName !== undefined"
class=""
>
{{ props.row.lastUpdateFullName }}
</q-td>
<q-td
key="isActive"
:props="props"
v-if="props.row.isActive !== undefined"
>
<q-toggle
v-model="props.row.isActive"
dense
size="34px"
color="positive"
@update:model-value="clickEditRow"
/>
</q-td>
<q-td key="note" :props="props" v-if="props.row.note !== undefined">
<q-input
class=""
outlined
@update:model-value="clickEditRow"
v-model="props.row.note"
dense
lazy-rules
autofocus
hide-bottom-space
></q-input>
</q-td>
<q-td auto-width>
<q-btn
v-if="props.row.id === '00000000-0000-0000-0000-000000000000'"
color="red"
flat
dense
round
size="14px"
icon="mdi-trash-can-outline"
@click="clickDeleteRow(props.row)"
/>
<q-btn
v-if="props.row.id !== '00000000-0000-0000-0000-000000000000'"
color="info"
flat
dense
round
size="14px"
icon="mdi-history"
@click="clickHistory(props.row)"
/>
</q-td>
</q-tr>
</template>
</data-table>
</q-form>
</div>
<HistoryTable
:rows="rowsHistory"
:columns="columnsHistory"
:filter="filterHistory"
:visible-columns="visibleColumnsHistory"
v-model:modal="modalHistory"
v-model:inputfilter="filterHistory"
v-model:inputvisible="visibleColumnsHistory"
v-model:tittle="tittleHistory"
>
<template #columns="props">
<q-tr :props="props">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.name == 'isActive'" class="">
<q-icon
v-if="col.value == false"
name="mdi-close"
color="red"
class="text-h5"
/>
<q-icon v-else name="mdi-check" color="positive" class="text-h5" />
</div>
<div v-else-if="col.name == 'lastUpdatedAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else class="">
{{ col.value }}
</div>
</q-td>
</q-tr>
</template>
</HistoryTable>
</template>
<script setup lang="ts">
import type { QTableProps } from "quasar";
import { useQuasar } from "quasar";
import { onMounted, ref, watch } from "vue";
import http from "@/plugins/http";
import config from "@/app.config";
import keycloak from "@/plugins/keycloak";
import { useCounterMixin } from "@/stores/mixin";
import { useManageDataStore } from "@/modules/01_metadata/store";
import type {
RequestItemsHistoryObject,
RequestItemsPublishHistoryObject,
Columns,
} from "@/modules/01_metadata/interface/request/position/ExecutiveSide";
import type { ResponseHistoryObject } from "@/modules/01_metadata/interface/response/position/ExecutiveSide";
import HistoryTable from "@/components/TableHistory.vue";
import { useDataStore } from "@/stores/data";
const props = defineProps({
fetchDataComponent: {
type: Function,
default: () => console.log("not function"),
},
});
const dataStore = useDataStore();
const { loaderPage } = dataStore;
const mixin = useCounterMixin();
const { success, dateText, messageError } = mixin;
const store = useManageDataStore();
const { manageData, changeManageColumns } = store;
const rows = ref<RequestItemsHistoryObject[]>([]); //list data table
const rowsHistory = ref<RequestItemsHistoryObject[]>([]); //select data history
const rawHistory = ref<RequestItemsHistoryObject[]>([]); //raw data history
const tittleHistory = ref<string>("ประวัติแก้ไขด้านทางการบริหาร"); //
const myForm = ref<any>(null); //ref
const filter = ref<string>(""); //search data table
const filterHistory = ref<string>(""); //search data table history
const modalHistory = ref<boolean>(false); //modal
const edit = ref<boolean>(false); //
const idVersion = ref<string>(""); //id data mongodb
const version = ref<string>("published"); // published= draft=
const updateData = ref<boolean>(false); //
const checkValidate = ref<boolean>(false);
const columns = ref<QTableProps["columns"]>([
{
name: "name",
align: "left",
label: "ด้านทางการบริหาร",
sortable: true,
field: "name",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "createdAt",
align: "center",
label: "วันที่สร้าง",
sortable: true,
field: "createdAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdatedAt",
align: "center",
label: "วันที่แก้ไข",
sortable: true,
field: "lastUpdatedAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdateFullName",
align: "left",
label: "ผู้ดำเนินการ",
sortable: true,
field: "lastUpdateFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "isActive",
align: "left",
label: "สถานะ",
sortable: true,
field: "isActive",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "note",
align: "left",
label: "หมายเหตุ",
sortable: true,
field: "note",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumns = ref<String[]>([]);
manageData.position.executiveSide.columns.length == 0
? (visibleColumns.value = [
"name",
"createdAt",
"lastUpdatedAt",
"lastUpdateFullName",
"isActive",
"note",
])
: (visibleColumns.value = manageData.position.executiveSide.columns);
const columnsHistory = ref<QTableProps["columns"]>([
{
name: "name",
align: "left",
label: "ด้านทางการบริหาร",
sortable: true,
field: "name",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdatedAt",
align: "center",
label: "วันที่แก้ไข",
sortable: true,
field: "lastUpdatedAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdateFullName",
align: "left",
label: "ผู้ดำเนินการ",
sortable: true,
field: "lastUpdateFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "isActive",
align: "left",
label: "สถานะ",
sortable: true,
field: "isActive",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "note",
align: "left",
label: "หมายเหตุ",
sortable: true,
field: "note",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumnsHistory = ref<String[]>([
"name",
"lastUpdatedAt",
"lastUpdateFullName",
"isActive",
"note",
]);
/**
* เมอเขาหนานจะเรยกฟงชนนอน(get list data)
*/
onMounted(async () => {
await fetchData();
await fetchHistory();
});
watch(visibleColumns, async (count: String[], prevCount: String[]) => {
await changeManageColumns(3, "executiveSide", count);
});
/**
* แจงเตอนขอมลในกรณ success
*/
const $q = useQuasar();
/**
* งก get data าส
*/
const fetchData = async () => {
await props.fetchDataComponent();
rows.value.splice(0);
loaderPage(true);
await http
.get(config.API.listPositionExecutiveSideHistory)
.then((res) => {
let data = res.data.result;
version.value = data.version; // published= draft=
idVersion.value = data.id; // id mongodb
data.items.map((e: RequestItemsHistoryObject) => {
rows.value.push({
id: e.id,
name: e.name,
createdAt: e.createdAt,
lastUpdatedAt: e.lastUpdatedAt,
lastUpdateFullName: e.lastUpdateFullName,
isActive: e.isActive,
createdFullName: e.createdFullName,
createdUserId: e.createdUserId,
lastUpdateUserId: e.lastUpdateUserId,
note: e.note,
});
});
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
updateData.value = false;
loaderPage(false);
});
};
/**
* งชนดอมลประวแกไขขอมลทงหมด
*/
const fetchHistory = async () => {
loaderPage(true);
await http
.get(config.API.listPositionExecutiveSidePublishedHistory)
.then((res) => {
const data = res.data.result;
rawHistory.value = [];
if (data.length > 0) {
data.map((e: RequestItemsPublishHistoryObject) => {
e.items.map((i: RequestItemsHistoryObject) => {
rawHistory.value.push({
createdAt: i.createdAt,
createdFullName: i.createdFullName,
createdUserId: i.createdUserId,
id: i.id,
isActive: i.isActive,
lastUpdateFullName: i.lastUpdateFullName,
lastUpdateUserId: i.lastUpdateUserId,
lastUpdatedAt: i.lastUpdatedAt,
name: i.name,
note: i.note,
});
});
});
}
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
loaderPage(false);
});
};
/**
* งก clear data แบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
*/
const clearPublishedData = async () => {
loaderPage(true);
await http
.delete(config.API.listPositionExecutiveSideHistory)
.then((res) => {
success($q, "ลบข้อมูลร่างสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchHistory();
await fetchData();
});
};
/**
* งกนเผยแพรแบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
*/
const publishedData = async () => {
loaderPage(true);
await http
.get(config.API.listPositionExecutiveSidePublished)
.then((res) => {
success($q, "เผยแพร่ข้อมูลสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchData();
});
};
/**
* งกนเพมขอม
*/
const clickAdd = async () => {
const filterRowNull = rows.value.filter(
(f: RequestItemsHistoryObject) =>
f.id === "00000000-0000-0000-0000-000000000000" && f.name == "" // array
);
if (filterRowNull.length == 0) {
//
rows.value.push({
createdAt: new Date(),
createdFullName: "",
createdUserId: "",
id: "00000000-0000-0000-0000-000000000000",
isActive: true,
lastUpdateFullName:
keycloak.tokenParsed == null ? "" : keycloak.tokenParsed.name,
lastUpdateUserId: "",
lastUpdatedAt: new Date(),
name: "",
note: "",
});
updateData.value = true;
}
};
/**
* งกนบนทกแบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
* publish เมอบนทกแบบรางแลวจะเผยแพรเลยไหม true=นทกและเผยแพร false=นทกอยางเดยว
*/
const save = async (publish: boolean) => {
await validateData();
if (checkValidate.value == false) return;
rows.value.map((e: ResponseHistoryObject) => ({
// data backend
id: e.id,
createdAt: e.createdAt,
lastUpdatedAt: e.lastUpdatedAt,
name: e.name,
isActive: e.isActive,
createdFullName: e.createdFullName,
createdUserId: e.createdUserId,
lastUpdateFullName: e.lastUpdateFullName,
lastUpdateUserId: e.lastUpdateUserId,
}));
loaderPage(true);
await http
.post(config.API.listPositionExecutiveSideHistoryId(idVersion.value), {
id: idVersion.value,
version: "draft",
items: rows.value,
})
.then(async (res) => {
if (publish === false) {
success($q, "บันทึกข้อมูลร่างสำเร็จ");
await fetchData(); // get data
} else {
await publishedData(); //
}
edit.value = false;
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
loaderPage(false);
});
};
/**
* เชคชอซำกบขอมลทอยแล
* @param val input
*/
const checkDupDataName = (val: string) => {
const filterNameNull = rows.value.filter(
(f: RequestItemsHistoryObject) => f.name == val
); //
if (filterNameNull.length > 1) {
return false;
}
return true;
};
/**
* งกนปมแกไข ให get data มาใหม
*/
const clickEdit = async () => {
await fetchData();
};
/**
* งกนปมบนทกแบบราง
*/
const clickSave = async () => {
await save(false);
};
/**
* งกนปมลบแบบราง
*/
const clickDelete = async () => {
await clearPublishedData();
};
/**
* งกนปมยกเลกการแกไขขอม
*/
const clickCancel = async () => {
edit.value = false;
await fetchData();
};
/**
* งกนปมเผยแพรอม
* เชคขอมลกอนวาใน array กรอกขอมลครบไหมถาครบกใหเผยแพรได
* าคาใน array ไมอมลใน row จะใหนทกได
*/
const clickPublish = async () => {
if (myForm.value !== null) {
myForm.value.validate().then(async (result: boolean) => {
if (result) {
await save(true);
}
});
} else {
await save(true);
}
};
/**
* งกนปมลบ row data
* @param val data ใน row จะลบ
*/
const clickDeleteRow = (val: RequestItemsHistoryObject) => {
rows.value = rows.value.filter((x: RequestItemsHistoryObject) => x !== val);
updateData.value = true;
};
/**
* งกนเช input ามการแกไขหรอย
*/
const clickEditRow = () => {
myForm.value.validate(false);
updateData.value = true;
};
/**
* งชนดอมลประวแกไขขอมลทเลอก
* @param row อม row ประวการแกไข
*/
const clickHistory = async (row: RequestItemsHistoryObject) => {
modalHistory.value = true;
rowsHistory.value = rawHistory.value.filter(
(f: RequestItemsHistoryObject) => f.id == row.id
);
};
/**
* งกนแปลง date เปนภาษาไทย
* @param value นท type datetime จะแปลงเปนไทย
*/
const textDate = (value: Date) => {
return dateText(value);
};
/**
* validate component
*/
const validateData = async () => {
checkValidate.value = true;
await myForm.value.validate().then((result: boolean) => {
if (result == false) {
checkValidate.value = false;
}
});
};
</script>
<style>
/* สีของnoti */
.my-notif-class {
background: rgba(33, 186, 69, 0.5) !important;
color: #008f17 !important;
}
</style>

View file

@ -0,0 +1,837 @@
<!-- tab ระด หนาจดการขอมลหล/อมลตำแหนงของขาราชการกรงเทพมหานคร -->
<template>
<div>
<q-form ref="myForm">
<data-table
:rows="rows"
:columns="columns"
:filter="filter"
:visible-columns="visibleColumns"
v-model:inputfilter="filter"
v-model:inputvisible="visibleColumns"
v-model:editvisible="edit"
:add="clickAdd"
:edit="clickEdit"
:save="clickSave"
:deleted="clickDelete"
:cancel="clickCancel"
:publish="clickPublish"
:validate="validateData"
:publicData="version === 'published'"
:updateData="updateData"
:history="true"
>
<template #columns="props">
<q-tr :props="props" v-if="edit == false">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.name == 'isActive'" class="">
<q-icon
v-if="col.value == false"
name="mdi-close"
color="red"
class="text-h5"
/>
<q-icon
v-else
name="mdi-check"
color="positive"
class="text-h5"
/>
</div>
<div v-else-if="col.name == 'createdAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else-if="col.name == 'lastUpdatedAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else class="">
{{ col.value }}
</div>
</q-td>
<q-td auto-width>
<q-btn
color="info"
flat
dense
round
size="14px"
icon="mdi-history"
@click="clickHistory(props.row)"
/>
</q-td>
</q-tr>
<q-tr :props="props" v-if="edit == true">
<q-td
key="level"
:props="props"
v-if="props.row.level !== undefined"
>
<div class="">
{{ props.row.level }}
</div>
</q-td>
<q-td key="name" :props="props" v-if="props.row.name !== undefined">
<q-input
class=""
outlined
@update:model-value="clickEditRow"
v-model="props.row.name"
dense
lazy-rules
autofocus
hide-bottom-space
:rules="[
(val) => (val && val.length > 0) || 'กรุณากรอกข้อมูลให้ครบ',
(val) =>
checkDupDataName(val) || 'ชื่อซ้ำกันกับข้อมูลที่มีอยู่แล้ว',
]"
></q-input>
</q-td>
<q-td
key="shortName"
:props="props"
v-if="props.row.shortName !== undefined"
>
<q-input
class=""
outlined
@update:model-value="clickEditRow"
v-model="props.row.shortName"
dense
lazy-rules
autofocus
hide-bottom-space
:rules="[
(val) => (val && val.length > 0) || 'กรุณากรอกข้อมูลให้ครบ',
(val) =>
checkDupDataShortName(val) ||
'ชื่อย่อซ้ำกันกับข้อมูลที่มีอยู่แล้ว',
]"
></q-input>
</q-td>
<q-td
key="createdAt"
:props="props"
v-if="props.row.createdAt !== undefined"
>
<div class="">
{{ textDate(props.row.createdAt) }}
</div>
</q-td>
<q-td key="lastUpdatedAt" :props="props">
<div class="">
{{ textDate(props.row.lastUpdatedAt) }}
</div>
</q-td>
<q-td
key="lastUpdateFullName"
:props="props"
v-if="props.row.lastUpdateFullName !== undefined"
class=""
>
{{ props.row.lastUpdateFullName }}
</q-td>
<q-td
key="isActive"
:props="props"
v-if="props.row.isActive !== undefined"
>
<q-toggle
v-model="props.row.isActive"
dense
size="34px"
color="positive"
@update:model-value="clickEditRow"
/>
</q-td>
<q-td auto-width>
<div class="row">
<q-btn
:disable="props.row.level <= 1"
flat
dense
size="12px"
icon="mdi-menu-up"
style="
padding-top: 0em;
padding-right: 0.5em;
padding-bottom: 0em;
padding-left: 0.5em;
min-height: 0em;
"
@click="directionItem(props.row, 'up')"
/>
<q-btn
:disable="props.row.level >= rows.length"
flat
dense
size="12px"
icon="mdi-menu-down"
style="
padding-top: 0em;
padding-right: 0.5em;
padding-bottom: 0em;
padding-left: 0.5em;
min-height: 0em;
"
@click="directionItem(props.row, 'down')"
/>
</div>
<q-btn
v-if="props.row.id === '00000000-0000-0000-0000-000000000000'"
color="red"
flat
dense
round
size="14px"
icon="mdi-trash-can-outline"
@click="clickDeleteRow(props.row)"
/>
<q-btn
v-if="props.row.id !== '00000000-0000-0000-0000-000000000000'"
color="info"
flat
dense
round
size="14px"
icon="mdi-history"
@click="clickHistory(props.row)"
/>
</q-td>
</q-tr>
</template>
</data-table>
</q-form>
</div>
<HistoryTable
:rows="rowsHistory"
:columns="columnsHistory"
:filter="filterHistory"
:visible-columns="visibleColumnsHistory"
v-model:modal="modalHistory"
v-model:inputfilter="filterHistory"
v-model:inputvisible="visibleColumnsHistory"
v-model:tittle="tittleHistory"
>
<template #columns="props">
<q-tr :props="props">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.name == 'isActive'" class="">
<q-icon
v-if="col.value == false"
name="mdi-close"
color="red"
class="text-h5"
/>
<q-icon v-else name="mdi-check" color="positive" class="text-h5" />
</div>
<div v-else-if="col.name == 'lastUpdatedAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else class="">
{{ col.value }}
</div>
</q-td>
</q-tr>
</template>
</HistoryTable>
</template>
<script setup lang="ts">
import type { QTableProps } from "quasar";
import { useQuasar } from "quasar";
import { onMounted, ref, watch } from "vue";
import http from "@/plugins/http";
import config from "@/app.config";
import keycloak from "@/plugins/keycloak";
import { useCounterMixin } from "@/stores/mixin";
import { useManageDataStore } from "@/modules/01_metadata/store";
import type {
RequestItemsHistoryObject,
RequestItemsPublishHistoryObject,
Columns,
} from "@/modules/01_metadata/interface/request/position/Level";
import type { ResponseHistoryObject } from "@/modules/01_metadata/interface/response/position/Level";
import HistoryTable from "@/components/TableHistory.vue";
import { useDataStore } from "@/stores/data";
const props = defineProps({
fetchDataComponent: {
type: Function,
default: () => console.log("not function"),
},
});
const dataStore = useDataStore();
const { loaderPage } = dataStore;
const mixin = useCounterMixin();
const { success, dateText, messageError } = mixin;
const store = useManageDataStore();
const { manageData, changeManageColumns } = store;
const rows = ref<RequestItemsHistoryObject[]>([]); //list data table
const rowsHistory = ref<RequestItemsHistoryObject[]>([]); //select data history
const rawHistory = ref<RequestItemsHistoryObject[]>([]); //raw data history
const tittleHistory = ref<string>("ประวัติแก้ไขระดับ"); //
const myForm = ref<any>(null); //ref
const filter = ref<string>(""); //search data table
const filterHistory = ref<string>(""); //search data table history
const modalHistory = ref<boolean>(false); //modal
const edit = ref<boolean>(false); //
const idVersion = ref<string>(""); //id data mongodb
const version = ref<string>("published"); // published= draft=
const updateData = ref<boolean>(false); //
const checkValidate = ref<boolean>(false);
const columns = ref<QTableProps["columns"]>([
{
name: "level",
align: "left",
label: "ลำดับ",
sortable: true,
field: "level",
headerStyle: "font-size: 14px; width:0px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "name",
align: "left",
label: "ระดับ",
sortable: true,
field: "name",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "shortName",
align: "left",
label: "ชื่อย่อ",
sortable: true,
field: "shortName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "createdAt",
align: "center",
label: "วันที่สร้าง",
sortable: true,
field: "createdAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdatedAt",
align: "center",
label: "วันที่แก้ไข",
sortable: true,
field: "lastUpdatedAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdateFullName",
align: "left",
label: "ผู้ดำเนินการ",
sortable: true,
field: "lastUpdateFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "isActive",
align: "left",
label: "สถานะ",
sortable: true,
field: "isActive",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumns = ref<String[]>([]);
manageData.position.level.columns.length == 0
? (visibleColumns.value = [
"level",
"name",
"shortName",
"createdAt",
"lastUpdatedAt",
"lastUpdateFullName",
"isActive",
])
: (visibleColumns.value = manageData.position.level.columns);
const columnsHistory = ref<QTableProps["columns"]>([
{
name: "level",
align: "left",
label: "ลำดับ",
sortable: true,
field: "level",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "name",
align: "left",
label: "ระดับ",
sortable: true,
field: "name",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "shortName",
align: "left",
label: "ชื่อย่อ",
sortable: true,
field: "shortName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdatedAt",
align: "center",
label: "วันที่แก้ไข",
sortable: true,
field: "lastUpdatedAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdateFullName",
align: "left",
label: "ผู้ดำเนินการ",
sortable: true,
field: "lastUpdateFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "isActive",
align: "left",
label: "สถานะ",
sortable: true,
field: "isActive",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumnsHistory = ref<String[]>([
"level",
"name",
"shortName",
"lastUpdatedAt",
"lastUpdateFullName",
"isActive",
]);
/**
* เมอเขาหนานจะเรยกฟงชนนอน(get list data)
*/
onMounted(async () => {
await fetchData();
await fetchHistory();
});
watch(visibleColumns, async (count: String[], prevCount: String[]) => {
await changeManageColumns(3, "level", count);
});
/**
* แจงเตอนขอมลในกรณ success
*/
const $q = useQuasar();
/**
* งก get data าส
*/
const fetchData = async () => {
await props.fetchDataComponent();
rows.value.splice(0);
loaderPage(true);
await http
.get(config.API.listPositionLevelHistory)
.then((res) => {
let data = res.data.result;
version.value = data.version; // published= draft=
idVersion.value = data.id; // id mongodb
data.items.map((e: RequestItemsHistoryObject) => {
rows.value.push({
id: e.id,
level: e.level,
name: e.name,
shortName: e.shortName,
createdAt: e.createdAt,
lastUpdatedAt: e.lastUpdatedAt,
lastUpdateFullName: e.lastUpdateFullName,
isActive: e.isActive,
createdFullName: e.createdFullName,
createdUserId: e.createdUserId,
lastUpdateUserId: e.lastUpdateUserId,
});
});
rows.value.sort(
(
firstItem: RequestItemsHistoryObject,
secondItem: RequestItemsHistoryObject
) => firstItem.level - secondItem.level
);
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
updateData.value = false;
loaderPage(false);
});
};
/**
* งชนดอมลประวแกไขขอมลทงหมด
*/
const fetchHistory = async () => {
loaderPage(true);
await http
.get(config.API.listPositionLevelPublishedHistory)
.then((res) => {
const data = res.data.result;
rawHistory.value = [];
if (data.length > 0) {
data.map((e: RequestItemsPublishHistoryObject) => {
e.items.map((i: RequestItemsHistoryObject) => {
rawHistory.value.push({
createdAt: i.createdAt,
createdFullName: i.createdFullName,
createdUserId: i.createdUserId,
id: i.id,
isActive: i.isActive,
lastUpdateFullName: i.lastUpdateFullName,
lastUpdateUserId: i.lastUpdateUserId,
lastUpdatedAt: i.lastUpdatedAt,
level: i.level,
name: i.name,
shortName: i.shortName,
});
});
});
}
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
loaderPage(false);
});
};
/**
* งก clear data แบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
*/
const clearPublishedData = async () => {
loaderPage(true);
await http
.delete(config.API.listPositionLevelHistory)
.then((res) => {
success($q, "ลบข้อมูลร่างสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchHistory();
await fetchData();
});
};
/**
* งกนเผยแพรแบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
*/
const publishedData = async () => {
loaderPage(true);
await http
.get(config.API.listPositionLevelPublished)
.then((res) => {
success($q, "เผยแพร่ข้อมูลสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchData();
});
};
/**
* งกนเพมขอม
*/
const clickAdd = async () => {
const filterRowNull = rows.value.filter(
(f: RequestItemsHistoryObject) =>
f.id === "00000000-0000-0000-0000-000000000000" && f.name == "" // array
);
if (filterRowNull.length == 0) {
//
rows.value.push({
createdAt: new Date(),
createdFullName: "",
createdUserId: "",
id: "00000000-0000-0000-0000-000000000000",
isActive: true,
lastUpdateFullName:
keycloak.tokenParsed == null ? "" : keycloak.tokenParsed.name,
lastUpdateUserId: "",
lastUpdatedAt: new Date(),
level: rows.value[rows.value.length - 1].level + 1,
name: "",
shortName: "",
});
updateData.value = true;
}
};
/**
* งกนบนทกแบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
* publish เมอบนทกแบบรางแลวจะเผยแพรเลยไหม true=นทกและเผยแพร false=นทกอยางเดยว
*/
const save = async (publish: boolean) => {
await validateData();
if (checkValidate.value == false) return;
rows.value.map((e: ResponseHistoryObject) => ({
// data backend
id: e.id,
createdAt: e.createdAt,
lastUpdatedAt: e.lastUpdatedAt,
level: e.level,
name: e.name,
shortName: e.shortName,
isActive: e.isActive,
createdFullName: e.createdFullName,
createdUserId: e.createdUserId,
lastUpdateFullName: e.lastUpdateFullName,
lastUpdateUserId: e.lastUpdateUserId,
}));
loaderPage(true);
await http
.post(config.API.listPositionLevelHistoryId(idVersion.value), {
id: idVersion.value,
version: "draft",
items: rows.value,
})
.then(async (res) => {
if (publish === false) {
success($q, "บันทึกข้อมูลร่างสำเร็จ");
await fetchData(); // get data
} else {
await publishedData(); //
}
edit.value = false;
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
loaderPage(false);
});
};
/**
* เชคชอซำกบขอมลทอยแล
* @param val input
*/
const checkDupDataName = (val: string) => {
const filterNameNull = rows.value.filter(
(f: RequestItemsHistoryObject) => f.name == val
); //
if (filterNameNull.length > 1) {
return false;
}
return true;
};
/**
* เชคชอยอซำกบขอมลทอยแล
* @param val input
*/
const checkDupDataShortName = (val: string) => {
const filterNameNull = rows.value.filter(
(f: RequestItemsHistoryObject) => f.shortName == val
); //
if (filterNameNull.length > 1) {
return false;
}
return true;
};
/**
* งกนปมแกไข ให get data มาใหม
*/
const clickEdit = async () => {
await fetchData();
};
/**
* งกนปมบนทกแบบราง
*/
const clickSave = async () => {
await save(false);
};
/**
* งกนปมลบแบบราง
*/
const clickDelete = async () => {
await clearPublishedData();
};
/**
* งกนปมยกเลกการแกไขขอม
*/
const clickCancel = async () => {
edit.value = false;
await fetchData();
};
/**
* งกนปมเผยแพรอม
* เชคขอมลกอนวาใน array กรอกขอมลครบไหมถาครบกใหเผยแพรได
* าคาใน array ไมอมลใน row จะใหนทกได
*/
const clickPublish = async () => {
if (myForm.value !== null) {
myForm.value.validate().then(async (result: boolean) => {
if (result) {
await save(true);
}
});
} else {
await save(true);
}
};
/**
* งกนปมลบ row data
* @param val data ใน row จะลบ
*/
const clickDeleteRow = (val: RequestItemsHistoryObject) => {
rows.value = rows.value.filter((x: RequestItemsHistoryObject) => x !== val);
updateData.value = true;
};
/**
* งกนเช input ามการแกไขหรอย
*/
const clickEditRow = () => {
myForm.value.validate(false);
updateData.value = true;
};
/**
* งชนดอมลประวแกไขขอมลทเลอก
* @param row อม row ประวการแกไข
*/
const clickHistory = async (row: RequestItemsHistoryObject) => {
modalHistory.value = true;
rowsHistory.value = rawHistory.value.filter(
(f: RequestItemsHistoryObject) => f.id == row.id
);
};
/**
* งกนแปลง date เปนภาษาไทย
* @param value นท type datetime จะแปลงเปนไทย
*/
const textDate = (value: Date) => {
return dateText(value);
};
/**
* validate component
*/
const validateData = async () => {
checkValidate.value = true;
await myForm.value.validate().then((result: boolean) => {
if (result == false) {
checkValidate.value = false;
}
});
};
/**
* ายลำด data
* @param row าใน row
* @param type ายตำแหนงแบบไหน up= down=ลง
*/
const directionItem = async (row: RequestItemsHistoryObject, type: string) => {
await clickEditRow();
if (type === "up") {
rows.value[
rows.value.findIndex((object: RequestItemsHistoryObject) => {
return object === row;
})
].level -= 1;
rows.value[
rows.value.findIndex((object: RequestItemsHistoryObject) => {
return object === row;
}) - 1
].level += 1;
} else {
rows.value[
rows.value.findIndex((object: RequestItemsHistoryObject) => {
return object === row;
})
].level += 1;
rows.value[
rows.value.findIndex((object: RequestItemsHistoryObject) => {
return object === row;
}) + 1
].level -= 1;
}
rows.value.sort(
(
firstItem: RequestItemsHistoryObject,
secondItem: RequestItemsHistoryObject
) => firstItem.level - secondItem.level
);
};
</script>
<style>
/* สีของnoti */
.my-notif-class {
background: rgba(33, 186, 69, 0.5) !important;
color: #008f17 !important;
}
</style>

View file

@ -0,0 +1,660 @@
<!-- tab สายงาน หนาจดการขอมลหล/อมลตำแหนงของขาราชการกรงเทพมหานคร -->
<template>
<div>
<q-form ref="myForm">
<data-table
:rows="rows"
:columns="columns"
:filter="filter"
:visible-columns="visibleColumns"
v-model:inputfilter="filter"
v-model:inputvisible="visibleColumns"
v-model:editvisible="edit"
:add="clickAdd"
:edit="clickEdit"
:save="clickSave"
:deleted="clickDelete"
:cancel="clickCancel"
:publish="clickPublish"
:validate="validateData"
:publicData="version === 'published'"
:updateData="updateData"
:history="true"
>
<template #columns="props">
<q-tr :props="props" v-if="edit == false">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.name == 'isActive'" class="">
<q-icon
v-if="col.value == false"
name="mdi-close"
color="red"
class="text-h5"
/>
<q-icon
v-else
name="mdi-check"
color="positive"
class="text-h5"
/>
</div>
<div v-else-if="col.name == 'createdAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else-if="col.name == 'lastUpdatedAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else class="">
{{ col.value }}
</div>
</q-td>
<q-td auto-width>
<q-btn
color="info"
flat
dense
round
size="14px"
icon="mdi-history"
@click="clickHistory(props.row)"
/>
</q-td>
</q-tr>
<q-tr :props="props" v-if="edit == true">
<q-td key="name" :props="props" v-if="props.row.name !== undefined">
<q-input
class=""
outlined
@update:model-value="clickEditRow"
v-model="props.row.name"
dense
lazy-rules
autofocus
hide-bottom-space
:rules="[
(val) => (val && val.length > 0) || 'กรุณากรอกข้อมูลให้ครบ',
(val) =>
checkDupDataName(val) || 'ชื่อซ้ำกันกับข้อมูลที่มีอยู่แล้ว',
]"
></q-input>
</q-td>
<q-td
key="createdAt"
:props="props"
v-if="props.row.createdAt !== undefined"
>
<div class="">
{{ textDate(props.row.createdAt) }}
</div>
</q-td>
<q-td key="lastUpdatedAt" :props="props">
<div class="">
{{ textDate(props.row.lastUpdatedAt) }}
</div>
</q-td>
<q-td
key="lastUpdateFullName"
:props="props"
v-if="props.row.lastUpdateFullName !== undefined"
class=""
>
{{ props.row.lastUpdateFullName }}
</q-td>
<q-td
key="isActive"
:props="props"
v-if="props.row.isActive !== undefined"
>
<q-toggle
v-model="props.row.isActive"
dense
size="34px"
color="positive"
@update:model-value="clickEditRow"
/>
</q-td>
<q-td auto-width>
<q-btn
v-if="props.row.id === '00000000-0000-0000-0000-000000000000'"
color="red"
flat
dense
round
size="14px"
icon="mdi-trash-can-outline"
@click="clickDeleteRow(props.row)"
/>
<q-btn
v-if="props.row.id !== '00000000-0000-0000-0000-000000000000'"
color="info"
flat
dense
round
size="14px"
icon="mdi-history"
@click="clickHistory(props.row)"
/>
</q-td>
</q-tr>
</template>
</data-table>
</q-form>
</div>
<HistoryTable
:rows="rowsHistory"
:columns="columnsHistory"
:filter="filterHistory"
:visible-columns="visibleColumnsHistory"
v-model:modal="modalHistory"
v-model:inputfilter="filterHistory"
v-model:inputvisible="visibleColumnsHistory"
v-model:tittle="tittleHistory"
>
<template #columns="props">
<q-tr :props="props">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.name == 'isActive'" class="">
<q-icon
v-if="col.value == false"
name="mdi-close"
color="red"
class="text-h5"
/>
<q-icon v-else name="mdi-check" color="positive" class="text-h5" />
</div>
<div v-else-if="col.name == 'lastUpdatedAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else class="">
{{ col.value }}
</div>
</q-td>
</q-tr>
</template>
</HistoryTable>
</template>
<script setup lang="ts">
import type { QTableProps } from "quasar";
import { useQuasar } from "quasar";
import { onMounted, ref, watch } from "vue";
import http from "@/plugins/http";
import config from "@/app.config";
import keycloak from "@/plugins/keycloak";
import { useCounterMixin } from "@/stores/mixin";
import { useManageDataStore } from "@/modules/01_metadata/store";
import type {
RequestItemsHistoryObject,
RequestItemsPublishHistoryObject,
Columns,
} from "@/modules/01_metadata/interface/request/position/Line";
import type { ResponseHistoryObject } from "@/modules/01_metadata/interface/response/position/Line";
import HistoryTable from "@/components/TableHistory.vue";
import { useDataStore } from "@/stores/data";
const props = defineProps({
fetchDataComponent: {
type: Function,
default: () => console.log("not function"),
},
});
const dataStore = useDataStore();
const { loaderPage } = dataStore;
const mixin = useCounterMixin();
const { success, dateText, messageError } = mixin;
const store = useManageDataStore();
const { manageData, changeManageColumns } = store;
const rows = ref<RequestItemsHistoryObject[]>([]); //list data table
const rowsHistory = ref<RequestItemsHistoryObject[]>([]); //select data history
const rawHistory = ref<RequestItemsHistoryObject[]>([]); //raw data history
const tittleHistory = ref<string>("ประวัติแก้ไขสายงาน"); //
const myForm = ref<any>(null); //ref
const filter = ref<string>(""); //search data table
const filterHistory = ref<string>(""); //search data table history
const modalHistory = ref<boolean>(false); //modal
const edit = ref<boolean>(false); //
const idVersion = ref<string>(""); //id data mongodb
const version = ref<string>("published"); // published= draft=
const updateData = ref<boolean>(false); //
const checkValidate = ref<boolean>(false);
const columns = ref<QTableProps["columns"]>([
{
name: "name",
align: "left",
label: "สายงาน",
sortable: true,
field: "name",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "createdAt",
align: "center",
label: "วันที่สร้าง",
sortable: true,
field: "createdAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdatedAt",
align: "center",
label: "วันที่แก้ไข",
sortable: true,
field: "lastUpdatedAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdateFullName",
align: "left",
label: "ผู้ดำเนินการ",
sortable: true,
field: "lastUpdateFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "isActive",
align: "left",
label: "สถานะ",
sortable: true,
field: "isActive",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumns = ref<String[]>([]);
manageData.position.line.columns.length == 0
? (visibleColumns.value = [
"name",
"createdAt",
"lastUpdatedAt",
"lastUpdateFullName",
"isActive",
])
: (visibleColumns.value = manageData.position.line.columns);
const columnsHistory = ref<QTableProps["columns"]>([
{
name: "name",
align: "left",
label: "สายงาน",
sortable: true,
field: "name",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdatedAt",
align: "center",
label: "วันที่แก้ไข",
sortable: true,
field: "lastUpdatedAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdateFullName",
align: "left",
label: "ผู้ดำเนินการ",
sortable: true,
field: "lastUpdateFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "isActive",
align: "left",
label: "สถานะ",
sortable: true,
field: "isActive",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumnsHistory = ref<String[]>([
"name",
"lastUpdatedAt",
"lastUpdateFullName",
"isActive",
]);
/**
* เมอเขาหนานจะเรยกฟงชนนอน(get list data)
*/
onMounted(async () => {
await fetchData();
await fetchHistory();
});
watch(visibleColumns, async (count: String[], prevCount: String[]) => {
await changeManageColumns(3, "line", count);
});
/**
* แจงเตอนขอมลในกรณ success
*/
const $q = useQuasar();
/**
* งก get data าส
*/
const fetchData = async () => {
await props.fetchDataComponent();
rows.value.splice(0);
loaderPage(true);
await http
.get(config.API.listPositionLineHistory)
.then((res) => {
let data = res.data.result;
version.value = data.version; // published= draft=
idVersion.value = data.id; // id mongodb
data.items.map((e: RequestItemsHistoryObject) => {
rows.value.push({
id: e.id,
name: e.name,
createdAt: e.createdAt,
lastUpdatedAt: e.lastUpdatedAt,
lastUpdateFullName: e.lastUpdateFullName,
isActive: e.isActive,
createdFullName: e.createdFullName,
createdUserId: e.createdUserId,
lastUpdateUserId: e.lastUpdateUserId,
});
});
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
updateData.value = false;
loaderPage(false);
});
};
/**
* งชนดอมลประวแกไขขอมลทงหมด
*/
const fetchHistory = async () => {
loaderPage(true);
await http
.get(config.API.listPositionLinePublishedHistory)
.then((res) => {
const data = res.data.result;
rawHistory.value = [];
if (data.length > 0) {
data.map((e: RequestItemsPublishHistoryObject) => {
e.items.map((i: RequestItemsHistoryObject) => {
rawHistory.value.push({
createdAt: i.createdAt,
createdFullName: i.createdFullName,
createdUserId: i.createdUserId,
id: i.id,
isActive: i.isActive,
lastUpdateFullName: i.lastUpdateFullName,
lastUpdateUserId: i.lastUpdateUserId,
lastUpdatedAt: i.lastUpdatedAt,
name: i.name,
});
});
});
}
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
loaderPage(false);
});
};
/**
* งก clear data แบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
*/
const clearPublishedData = async () => {
loaderPage(true);
await http
.delete(config.API.listPositionLineHistory)
.then((res) => {
success($q, "ลบข้อมูลร่างสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchHistory();
await fetchData();
});
};
/**
* งกนเผยแพรแบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
*/
const publishedData = async () => {
loaderPage(true);
await http
.get(config.API.listPositionLinePublished)
.then((res) => {
success($q, "เผยแพร่ข้อมูลสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchData();
});
};
/**
* งกนเพมขอม
*/
const clickAdd = async () => {
const filterRowNull = rows.value.filter(
(f: RequestItemsHistoryObject) =>
f.id === "00000000-0000-0000-0000-000000000000" && f.name == "" // array
);
if (filterRowNull.length == 0) {
//
rows.value.push({
createdAt: new Date(),
createdFullName: "",
createdUserId: "",
id: "00000000-0000-0000-0000-000000000000",
isActive: true,
lastUpdateFullName:
keycloak.tokenParsed == null ? "" : keycloak.tokenParsed.name,
lastUpdateUserId: "",
lastUpdatedAt: new Date(),
name: "",
});
updateData.value = true;
}
};
/**
* งกนบนทกแบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
* publish เมอบนทกแบบรางแลวจะเผยแพรเลยไหม true=นทกและเผยแพร false=นทกอยางเดยว
*/
const save = async (publish: boolean) => {
await validateData();
if (checkValidate.value == false) return;
rows.value.map((e: ResponseHistoryObject) => ({
// data backend
id: e.id,
createdAt: e.createdAt,
lastUpdatedAt: e.lastUpdatedAt,
name: e.name,
isActive: e.isActive,
createdFullName: e.createdFullName,
createdUserId: e.createdUserId,
lastUpdateFullName: e.lastUpdateFullName,
lastUpdateUserId: e.lastUpdateUserId,
}));
loaderPage(true);
await http
.post(config.API.listPositionLineHistoryId(idVersion.value), {
id: idVersion.value,
version: "draft",
items: rows.value,
})
.then(async (res) => {
if (publish === false) {
success($q, "บันทึกข้อมูลร่างสำเร็จ");
await fetchData(); // get data
} else {
await publishedData(); //
}
edit.value = false;
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
loaderPage(false);
});
};
/**
* เชคชอซำกบขอมลทอยแล
* @param val input
*/
const checkDupDataName = (val: string) => {
const filterNameNull = rows.value.filter(
(f: RequestItemsHistoryObject) => f.name == val
); //
if (filterNameNull.length > 1) {
return false;
}
return true;
};
/**
* งกนปมแกไข ให get data มาใหม
*/
const clickEdit = async () => {
await fetchData();
};
/**
* งกนปมบนทกแบบราง
*/
const clickSave = async () => {
await save(false);
};
/**
* งกนปมลบแบบราง
*/
const clickDelete = async () => {
await clearPublishedData();
};
/**
* งกนปมยกเลกการแกไขขอม
*/
const clickCancel = async () => {
edit.value = false;
await fetchData();
};
/**
* งกนปมเผยแพรอม
* เชคขอมลกอนวาใน array กรอกขอมลครบไหมถาครบกใหเผยแพรได
* าคาใน array ไมอมลใน row จะใหนทกได
*/
const clickPublish = async () => {
if (myForm.value !== null) {
myForm.value.validate().then(async (result: boolean) => {
if (result) {
await save(true);
}
});
} else {
await save(true);
}
};
/**
* งกนปมลบ row data
* @param val data ใน row จะลบ
*/
const clickDeleteRow = (val: RequestItemsHistoryObject) => {
rows.value = rows.value.filter((x: RequestItemsHistoryObject) => x !== val);
updateData.value = true;
};
/**
* งกนเช input ามการแกไขหรอย
*/
const clickEditRow = () => {
myForm.value.validate(false);
updateData.value = true;
};
/**
* งชนดอมลประวแกไขขอมลทเลอก
* @param row อม row ประวการแกไข
*/
const clickHistory = async (row: RequestItemsHistoryObject) => {
modalHistory.value = true;
rowsHistory.value = rawHistory.value.filter(
(f: RequestItemsHistoryObject) => f.id == row.id
);
};
/**
* งกนแปลง date เปนภาษาไทย
* @param value นท type datetime จะแปลงเปนไทย
*/
const textDate = (value: Date) => {
return dateText(value);
};
/**
* validate component
*/
const validateData = async () => {
checkValidate.value = true;
await myForm.value.validate().then((result: boolean) => {
if (result == false) {
checkValidate.value = false;
}
});
};
</script>
<style>
/* สีของnoti */
.my-notif-class {
background: rgba(33, 186, 69, 0.5) !important;
color: #008f17 !important;
}
</style>

View file

@ -0,0 +1,699 @@
<!-- tab อตำแหน หนาจดการขอมลหล/อมลตำแหนงของขาราชการกรงเทพมหานคร -->
<template>
<div>
<q-form ref="myForm">
<data-table
:rows="rows"
:columns="columns"
:filter="filter"
:visible-columns="visibleColumns"
v-model:inputfilter="filter"
v-model:inputvisible="visibleColumns"
v-model:editvisible="edit"
:add="clickAdd"
:edit="clickEdit"
:save="clickSave"
:deleted="clickDelete"
:cancel="clickCancel"
:publish="clickPublish"
:validate="validateData"
:publicData="version === 'published'"
:updateData="updateData"
:history="true"
>
<template #columns="props">
<q-tr :props="props" v-if="edit == false">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.name == 'isActive'" class="">
<q-icon
v-if="col.value == false"
name="mdi-close"
color="red"
class="text-h5"
/>
<q-icon
v-else
name="mdi-check"
color="positive"
class="text-h5"
/>
</div>
<div v-else-if="col.name == 'createdAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else-if="col.name == 'lastUpdatedAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else class="">
{{ col.value }}
</div>
</q-td>
<q-td auto-width>
<q-btn
color="info"
flat
dense
round
size="14px"
icon="mdi-history"
@click="clickHistory(props.row)"
/>
</q-td>
</q-tr>
<q-tr :props="props" v-if="edit == true">
<q-td key="name" :props="props" v-if="props.row.name !== undefined">
<q-input
class=""
outlined
@update:model-value="clickEditRow"
v-model="props.row.name"
dense
lazy-rules
autofocus
hide-bottom-space
:rules="[
(val) => (val && val.length > 0) || 'กรุณากรอกข้อมูลให้ครบ',
(val) =>
checkDupDataName(val) || 'ชื่อซ้ำกันกับข้อมูลที่มีอยู่แล้ว',
]"
></q-input>
</q-td>
<q-td
key="createdAt"
:props="props"
v-if="props.row.createdAt !== undefined"
>
<div class="">
{{ textDate(props.row.createdAt) }}
</div>
</q-td>
<q-td key="lastUpdatedAt" :props="props">
<div class="">
{{ textDate(props.row.lastUpdatedAt) }}
</div>
</q-td>
<q-td
key="lastUpdateFullName"
:props="props"
v-if="props.row.lastUpdateFullName !== undefined"
class=""
>
{{ props.row.lastUpdateFullName }}
</q-td>
<q-td
key="isActive"
:props="props"
v-if="props.row.isActive !== undefined"
>
<q-toggle
v-model="props.row.isActive"
dense
size="34px"
color="positive"
@update:model-value="clickEditRow"
/>
</q-td>
<q-td key="note" :props="props" v-if="props.row.note !== undefined">
<q-input
class=""
outlined
@update:model-value="clickEditRow"
v-model="props.row.note"
dense
lazy-rules
autofocus
hide-bottom-space
></q-input>
</q-td>
<q-td auto-width>
<q-btn
v-if="props.row.id === '00000000-0000-0000-0000-000000000000'"
color="red"
flat
dense
round
size="14px"
icon="mdi-trash-can-outline"
@click="clickDeleteRow(props.row)"
/>
<q-btn
v-if="props.row.id !== '00000000-0000-0000-0000-000000000000'"
color="info"
flat
dense
round
size="14px"
icon="mdi-history"
@click="clickHistory(props.row)"
/>
</q-td>
</q-tr>
</template>
</data-table>
</q-form>
</div>
<HistoryTable
:rows="rowsHistory"
:columns="columnsHistory"
:filter="filterHistory"
:visible-columns="visibleColumnsHistory"
v-model:modal="modalHistory"
v-model:inputfilter="filterHistory"
v-model:inputvisible="visibleColumnsHistory"
v-model:tittle="tittleHistory"
>
<template #columns="props">
<q-tr :props="props">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.name == 'isActive'" class="">
<q-icon
v-if="col.value == false"
name="mdi-close"
color="red"
class="text-h5"
/>
<q-icon v-else name="mdi-check" color="positive" class="text-h5" />
</div>
<div v-else-if="col.name == 'lastUpdatedAt'" class="">
{{ textDate(col.value) }}
</div>
<div v-else class="">
{{ col.value }}
</div>
</q-td>
</q-tr>
</template>
</HistoryTable>
</template>
<script setup lang="ts">
import type { QTableProps } from "quasar";
import { useQuasar } from "quasar";
import { onMounted, ref, watch } from "vue";
import http from "@/plugins/http";
import config from "@/app.config";
import keycloak from "@/plugins/keycloak";
import { useCounterMixin } from "@/stores/mixin";
import { useManageDataStore } from "@/modules/01_metadata/store";
import type {
RequestItemsHistoryObject,
RequestItemsPublishHistoryObject,
Columns,
} from "@/modules/01_metadata/interface/request/position/Path";
import type { ResponseHistoryObject } from "@/modules/01_metadata/interface/response/position/Path";
import HistoryTable from "@/components/TableHistory.vue";
import { useDataStore } from "@/stores/data";
const props = defineProps({
fetchDataComponent: {
type: Function,
default: () => console.log("not function"),
},
});
const dataStore = useDataStore();
const { loaderPage } = dataStore;
const mixin = useCounterMixin();
const { success, dateText, messageError } = mixin;
const store = useManageDataStore();
const { manageData, changeManageColumns } = store;
const rows = ref<RequestItemsHistoryObject[]>([]); //list data table
const rowsHistory = ref<RequestItemsHistoryObject[]>([]); //select data history
const rawHistory = ref<RequestItemsHistoryObject[]>([]); //raw data history
const tittleHistory = ref<string>("ประวัติแก้ไขชื่อตำแหน่ง"); //
const myForm = ref<any>(null); //ref
const filter = ref<string>(""); //search data table
const filterHistory = ref<string>(""); //search data table history
const modalHistory = ref<boolean>(false); //modal
const edit = ref<boolean>(false); //
const idVersion = ref<string>(""); //id data mongodb
const version = ref<string>("published"); // published= draft=
const updateData = ref<boolean>(false); //
const checkValidate = ref<boolean>(false);
const columns = ref<QTableProps["columns"]>([
{
name: "name",
align: "left",
label: "ชื่อตำแหน่ง",
sortable: true,
field: "name",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "createdAt",
align: "center",
label: "วันที่สร้าง",
sortable: true,
field: "createdAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdatedAt",
align: "center",
label: "วันที่แก้ไข",
sortable: true,
field: "lastUpdatedAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdateFullName",
align: "left",
label: "ผู้ดำเนินการ",
sortable: true,
field: "lastUpdateFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "isActive",
align: "left",
label: "สถานะ",
sortable: true,
field: "isActive",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "note",
align: "left",
label: "หมายเหตุ",
sortable: true,
field: "note",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumns = ref<String[]>([]);
manageData.position.path.columns.length == 0
? (visibleColumns.value = [
"name",
"createdAt",
"lastUpdatedAt",
"lastUpdateFullName",
"isActive",
"note",
])
: (visibleColumns.value = manageData.position.path.columns);
const columnsHistory = ref<QTableProps["columns"]>([
{
name: "name",
align: "left",
label: "ชื่อตำแหน่ง",
sortable: true,
field: "name",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdatedAt",
align: "center",
label: "วันที่แก้ไข",
sortable: true,
field: "lastUpdatedAt",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "lastUpdateFullName",
align: "left",
label: "ผู้ดำเนินการ",
sortable: true,
field: "lastUpdateFullName",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "isActive",
align: "left",
label: "สถานะ",
sortable: true,
field: "isActive",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
{
name: "note",
align: "left",
label: "หมายเหตุ",
sortable: true,
field: "note",
headerStyle: "font-size: 14px",
style: "font-size: 14px",
sort: (a: string, b: string) =>
a.localeCompare(b, undefined, { numeric: true, sensitivity: "base" }),
},
]);
const visibleColumnsHistory = ref<String[]>([
"name",
"lastUpdatedAt",
"lastUpdateFullName",
"isActive",
"note",
]);
/**
* เมอเขาหนานจะเรยกฟงชนนอน(get list data)
*/
onMounted(async () => {
await fetchData();
await fetchHistory();
});
watch(visibleColumns, async (count: String[], prevCount: String[]) => {
await changeManageColumns(3, "path", count);
});
/**
* แจงเตอนขอมลในกรณ success
*/
const $q = useQuasar();
/**
* งก get data าส
*/
const fetchData = async () => {
await props.fetchDataComponent();
rows.value.splice(0);
loaderPage(true);
await http
.get(config.API.listPositionPathHistory)
.then((res) => {
let data = res.data.result;
version.value = data.version; // published= draft=
idVersion.value = data.id; // id mongodb
data.items.map((e: RequestItemsHistoryObject) => {
rows.value.push({
id: e.id,
name: e.name,
createdAt: e.createdAt,
lastUpdatedAt: e.lastUpdatedAt,
lastUpdateFullName: e.lastUpdateFullName,
isActive: e.isActive,
createdFullName: e.createdFullName,
createdUserId: e.createdUserId,
lastUpdateUserId: e.lastUpdateUserId,
note: e.note,
});
});
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
updateData.value = false;
loaderPage(false);
});
};
/**
* งชนดอมลประวแกไขขอมลทงหมด
*/
const fetchHistory = async () => {
loaderPage(true);
await http
.get(config.API.listPositionPathPublishedHistory)
.then((res) => {
const data = res.data.result;
rawHistory.value = [];
if (data.length > 0) {
data.map((e: RequestItemsPublishHistoryObject) => {
e.items.map((i: RequestItemsHistoryObject) => {
rawHistory.value.push({
createdAt: i.createdAt,
createdFullName: i.createdFullName,
createdUserId: i.createdUserId,
id: i.id,
isActive: i.isActive,
lastUpdateFullName: i.lastUpdateFullName,
lastUpdateUserId: i.lastUpdateUserId,
lastUpdatedAt: i.lastUpdatedAt,
name: i.name,
note: i.note,
});
});
});
}
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
loaderPage(false);
});
};
/**
* งก clear data แบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
*/
const clearPublishedData = async () => {
loaderPage(true);
await http
.delete(config.API.listPositionPathHistory)
.then((res) => {
success($q, "ลบข้อมูลร่างสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchHistory();
await fetchData();
});
};
/**
* งกนเผยแพรแบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
*/
const publishedData = async () => {
loaderPage(true);
await http
.get(config.API.listPositionPathPublished)
.then((res) => {
success($q, "เผยแพร่ข้อมูลสำเร็จ");
})
.catch((e) => {
messageError($q, e);
})
.finally(async () => {
await fetchData();
});
};
/**
* งกนเพมขอม
*/
const clickAdd = async () => {
const filterRowNull = rows.value.filter(
(f: RequestItemsHistoryObject) =>
f.id === "00000000-0000-0000-0000-000000000000" && f.name == "" // array
);
if (filterRowNull.length == 0) {
//
rows.value.push({
createdAt: new Date(),
createdFullName: "",
createdUserId: "",
id: "00000000-0000-0000-0000-000000000000",
isActive: true,
lastUpdateFullName:
keycloak.tokenParsed == null ? "" : keycloak.tokenParsed.name,
lastUpdateUserId: "",
lastUpdatedAt: new Date(),
name: "",
note: "",
});
updateData.value = true;
}
};
/**
* งกนบนทกแบบราง
* เมอเรยก api เสรจแลวจะ get data มาใหม
* publish เมอบนทกแบบรางแลวจะเผยแพรเลยไหม true=นทกและเผยแพร false=นทกอยางเดยว
*/
const save = async (publish: boolean) => {
await validateData();
if (checkValidate.value == false) return;
rows.value.map((e: ResponseHistoryObject) => ({
// data backend
id: e.id,
createdAt: e.createdAt,
lastUpdatedAt: e.lastUpdatedAt,
name: e.name,
isActive: e.isActive,
createdFullName: e.createdFullName,
createdUserId: e.createdUserId,
lastUpdateFullName: e.lastUpdateFullName,
lastUpdateUserId: e.lastUpdateUserId,
}));
loaderPage(true);
await http
.post(config.API.listPositionPathHistoryId(idVersion.value), {
id: idVersion.value,
version: "draft",
items: rows.value,
})
.then(async (res) => {
if (publish === false) {
success($q, "บันทึกข้อมูลร่างสำเร็จ");
await fetchData(); // get data
} else {
await publishedData(); //
}
edit.value = false;
})
.catch((e) => {
messageError($q, e);
})
.finally(() => {
loaderPage(false);
});
};
/**
* เชคชอซำกบขอมลทอยแล
* @param val input
*/
const checkDupDataName = (val: string) => {
const filterNameNull = rows.value.filter(
(f: RequestItemsHistoryObject) => f.name == val
); //
if (filterNameNull.length > 1) {
return false;
}
return true;
};
/**
* งกนปมแกไข ให get data มาใหม
*/
const clickEdit = async () => {
await fetchData();
};
/**
* งกนปมบนทกแบบราง
*/
const clickSave = async () => {
await save(false);
};
/**
* งกนปมลบแบบราง
*/
const clickDelete = async () => {
await clearPublishedData();
};
/**
* งกนปมยกเลกการแกไขขอม
*/
const clickCancel = async () => {
edit.value = false;
await fetchData();
};
/**
* งกนปมเผยแพรอม
* เชคขอมลกอนวาใน array กรอกขอมลครบไหมถาครบกใหเผยแพรได
* าคาใน array ไมอมลใน row จะใหนทกได
*/
const clickPublish = async () => {
if (myForm.value !== null) {
myForm.value.validate().then(async (result: boolean) => {
if (result) {
await save(true);
}
});
} else {
await save(true);
}
};
/**
* งกนปมลบ row data
* @param val data ใน row จะลบ
*/
const clickDeleteRow = (val: RequestItemsHistoryObject) => {
rows.value = rows.value.filter((x: RequestItemsHistoryObject) => x !== val);
updateData.value = true;
};
/**
* งกนเช input ามการแกไขหรอย
*/
const clickEditRow = () => {
myForm.value.validate(false);
updateData.value = true;
};
/**
* งชนดอมลประวแกไขขอมลทเลอก
* @param row อม row ประวการแกไข
*/
const clickHistory = async (row: RequestItemsHistoryObject) => {
modalHistory.value = true;
rowsHistory.value = rawHistory.value.filter(
(f: RequestItemsHistoryObject) => f.id == row.id
);
};
/**
* งกนแปลง date เปนภาษาไทย
* @param value นท type datetime จะแปลงเปนไทย
*/
const textDate = (value: Date) => {
return dateText(value);
};
/**
* validate component
*/
const validateData = async () => {
checkValidate.value = true;
await myForm.value.validate().then((result: boolean) => {
if (result == false) {
checkValidate.value = false;
}
});
};
</script>
<style>
/* สีของnoti */
.my-notif-class {
background: rgba(33, 186, 69, 0.5) !important;
color: #008f17 !important;
}
</style>

Some files were not shown because too many files have changed in this diff Show more