Merge branch 'main' into develop

This commit is contained in:
AnandaTon 2023-11-15 11:04:41 +07:00
commit 8b1d2e93f5
12 changed files with 227 additions and 5 deletions

View file

@ -1,3 +1,7 @@
VITE_REALM_KEYCLOAK=VITE_REALM_KEYCLOAK
VITE_CLIENTID_KEYCLOAK=VITE_CLIENTID_KEYCLOAK
VITE_URL_KEYCLOAK=VITE_URL_KEYCLOAK
VITE_URL_KEYCLOAK=VITE_URL_KEYCLOAK
# VITE_REALM_KEYCLOAK: "bma-ehr"
# VITE_CLIENTID_KEYCLOAK: "bma-ehr-exam-vue3"
# VITE_URL_KEYCLOAK: "https://id.frappet.synology.me/"

View file

@ -24,6 +24,7 @@
"@googlemaps/js-api-loader": "^1.16.2",
"@quasar/extras": "^1.15.8",
"@vuepic/vue-datepicker": "^5.2.1",
"keycloak-js": "^22.0.5",
"moment": "^2.29.4",
"pinia": "^2.1.4",
"quasar": "^2.11.1",

7
src/api/api.checkin.ts Normal file
View file

@ -0,0 +1,7 @@
import env from "./index";
const leave = `${env.API_URI}/leave`;
export default {
checkin: () => `${leave}/check-in`,
checkTime: () => `${leave}/check-time`,
};

6
src/api/api.history.ts Normal file
View file

@ -0,0 +1,6 @@
import env from "./index";
const history = `${env.API_URI}/leave/check-in/history`;
export default {
history
};

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

@ -0,0 +1,29 @@
/**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:7260/api",
API_URI: "https://bma-ehr.frappet.synology.me/api/v1",
},
test: {
API_URI: "http://localhost:5010/api/v1",
},
production: {
// API_URI: "https://localhost:5010",
API_URI: `${window.location.protocol}//${window.location.host}/api/v1`,
},
});
const API_URI = ref<string>(config.value[env.value].API_URI);
export default {
env: env.value,
config: config.value,
API_URI: API_URI.value,
};

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

@ -0,0 +1,20 @@
/**ใช้รวมไฟล์ย่อยๆ ของ api แต่ละไฟล์ */
/** API ระบบลงเวลา */
import leave from "@/api/api.checkin";
import history from "@/api/api.history";
// environment variables
export const s3ClusterUrl = import.meta.env.VITE_S3CLUSTER_PUBLIC_URL;
const API = {
/**leave */
...leave,
/**history */
...history,
};
export default {
API: API,
s3ClusterUrl,
};

View file

@ -9,8 +9,9 @@ import '@vuepic/vue-datepicker/dist/main.css'
import quasarUserOptions from './quasar-user-options'
import 'quasar/src/css/index.sass'
import th from "quasar/lang/th";
import th from 'quasar/lang/th'
import http from '@/plugins/http'
const app = createApp(App)
const pinia = createPinia()
@ -30,7 +31,9 @@ app.use(Quasar, {
app.component(
'datepicker',
defineAsyncComponent(() => import('@vuepic/vue-datepicker'))
defineAsyncComponent(() => import('@vuepic/vue-datepicker')),
)
app.config.globalProperties.$http = http
app.mount('#app')

25
src/plugins/axios.ts Normal file
View file

@ -0,0 +1,25 @@
import axios from "axios"
import config from "process"
// import { dotnetPath } from "../path/axiosPath";
// import { getToken } from "@baloise/vue-keycloak";
import keycloak from "../plugins/keycloak"
const axiosInstance = axios.create({
withCredentials: false,
})
// axiosInstance.defaults.baseURL = dotnetPath;
axiosInstance.interceptors.request.use(
async (config) => {
const token = await keycloak.token
config.headers = {
Authorization: `Bearer ${token}`,
}
return config
},
(error) => {
Promise.reject(error)
}
)
export default axiosInstance

22
src/plugins/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;

45
src/plugins/http.ts Normal file
View file

@ -0,0 +1,45 @@
import Axios, { type AxiosRequestConfig, type AxiosResponse } from "axios";
import keycloak from "./keycloak";
const http = Axios.create({
timeout: 1000000000, // เพิ่มค่า timeout
headers: {
"X-Requested-With": "XMLHttpRequest",
},
});
http.interceptors.request.use(
async function (config: AxiosRequestConfig<any>) {
await keycloak.updateToken(1);
config.headers = config.headers ?? {};
const token = keycloak.token;
// const token = localStorage.getItem("access_token")
// const token =
// "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICIxU2VKV2dVRFVlNXZwNS13Q1ZHaG9lT2l4bDJTTkdKemthLU5ZN211NXZJIn0.eyJleHAiOjE2NzI0MTI1NDksImlhdCI6MTY3MjM3NjU0OSwiYXV0aF90aW1lIjoxNjcyMzc2NTQ5LCJqdGkiOiI1MTVhY2IwNC1jODQ3LTQzM2YtYjUxOC03ODUzMzJhY2ZjNWYiLCJpc3MiOiJodHRwczovL2tleWNsb2FrLmZyYXBwZXQuc3lub2xvZ3kubWUvYXV0aC9yZWFsbXMvYm1hLWVociIsImF1ZCI6ImFjY291bnQiLCJzdWIiOiJlZmM5YjRlMC1mZGU2LTQ1NDQtYmU1OS1lMTA0MjEwMjUzZjAiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJibWEtZWhyIiwibm9uY2UiOiI3NjMyMGI3ZS0xZTMxLTQ5ODYtYWIzOC1iOTUyYjFlODY3OGYiLCJzZXNzaW9uX3N0YXRlIjoiMDZlNTBkZjktNzAyNi00ZGIwLTkxMjgtMWY3Y2FiYTRkNDEyIiwiYWNyIjoiMSIsImFsbG93ZWQtb3JpZ2lucyI6WyJodHRwczovL2xvY2FsaG9zdDo3MDA2Il0sInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJkZWZhdWx0LXJvbGVzLWJtYS1laHIiLCJvZmZsaW5lX2FjY2VzcyIsImFkbWluIiwidW1hX2F1dGhvcml6YXRpb24iXX0sInJlc291cmNlX2FjY2VzcyI6eyJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6Im9wZW5pZCBlbWFpbCBwcm9maWxlIiwic2lkIjoiMDZlNTBkZjktNzAyNi00ZGIwLTkxMjgtMWY3Y2FiYTRkNDEyIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsInJvbGUiOlsiZGVmYXVsdC1yb2xlcy1ibWEtZWhyIiwib2ZmbGluZV9hY2Nlc3MiLCJhZG1pbiIsInVtYV9hdXRob3JpemF0aW9uIl0sIm5hbWUiOiJTeXN0ZW0gQWRtaW5pc3RyYXRvciIsInByZWZlcnJlZF91c2VybmFtZSI6ImFkbWluIiwiZ2l2ZW5fbmFtZSI6IlN5c3RlbSIsImZhbWlseV9uYW1lIjoiQWRtaW5pc3RyYXRvciIsImVtYWlsIjoiYWRtaW5AbG9jYWxob3N0In0.xmfJ3pzI-jLYsaiFXyjTW7gfAEpvUmMVsp9BsB1CfRCVOKiGBbuZhnQY8W-1SWVAx1NjJ55L-zMHPK6hk1dRPLbEse3DlIBZw04W9j8m-Wz3eqdHf_UCjmrXb8qAwkeq0Iaxq9mVfJJeQWeKhFBi-Ff8ek4hCXTYDICXS8ny_BaC5WkyrefHQ2xBqQjwRyoxsg4IoVMjXYNb8L9A-4BNlRfs928SqgFYCRlF5h6zw_rC0XoLrGTmqeacBdpey-r3j2g_lTqWy8mQg2T9s65IDqW3kFPOsr0SVO88sjlFbN9Et0L57RmiqORk_RwzbWg-_Yb6dOuolXsnjBOhOoTzkA";
if (token) config.headers.Authorization = `Bearer ${token}`;
return config;
},
function (error: any) {
return Promise.reject(error);
}
);
http.interceptors.response.use(
function (response: AxiosResponse<any, any>) {
return response;
},
function (error: any) {
if (typeof error !== undefined) {
// eslint-disable-next-line no-prototype-builtins
if (error.hasOwnProperty("response")) {
if (error.response.status === 401 || error.response.status === 403) {
// Store.commit("SET_ERROR_MESSAGE", error.response.data.message);
// Store.commit("REMOVE_ACCESS_TOKEN")
}
}
}
return Promise.reject(error);
}
);
export default http;

23
src/plugins/keycloak.ts Normal file
View file

@ -0,0 +1,23 @@
/**
* front connect to keycloak
*/
import Keycloak from "keycloak-js";
// import config from "../app.config";
// import http from "../shared/http";
// import router from "../router";
const initOptions = {
realm: import.meta.env.VITE_REALM_KEYCLOAK,
clientId: import.meta.env.VITE_CLIENTID_KEYCLOAK,
url: import.meta.env.VITE_URL_KEYCLOAK,
// realm: "bma-ehr",
// clientId: "bma-ehr-vue3",
// url: "https://id.frappet.synology.me/",
}; //option keycloak ที่จะ connect
const keycloak = new Keycloak(initOptions);
keycloak.onAuthSuccess = () => {}; //เพิ่มlogin สำเร็จจะมาทำฟังก์ชันนี้
await keycloak.init({ onLoad: "check-sso", checkLoginIframe: false }); //ทำการ connect keycloak
export default keycloak;

View file

@ -1,6 +1,8 @@
import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '@/views/HomeView.vue'
import keycloak from '@/plugins/keycloak'
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
@ -8,6 +10,9 @@ const router = createRouter({
path: '/',
name: 'home',
component: HomeView,
meta: {
Auth: true,
},
},
{
path: '/about',
@ -16,11 +21,17 @@ const router = createRouter({
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import('@/views/AboutView.vue'),
meta: {
Auth: true,
},
},
{
path: '/history',
name: 'history',
component: () => import('@/views/HistoryView.vue'),
meta: {
Auth: true,
},
},
// {
// path: '/camera',
@ -30,13 +41,39 @@ const router = createRouter({
/**
* 404 Not Found
* ref: https://router.vuejs.org/guide/essentials/dynamic-matching.html#catch-all-404-not-found-route
*/
*/
{
path: '/:pathMatch(.*)*',
name: 'NotFound',
component: () => import('@/views/ErrorNotFoundPage.vue'),
},
meta: {
Auth: true,
},
},
],
})
router.beforeEach((to, from, next) => {
if (to.meta.Auth) {
if (!keycloak.authenticated) {
keycloak.login({
redirectUri: `${window.location.protocol}//${window.location.host}${to.path}`,
locale: 'th',
})
} else {
// keycloak.updateToken(60);
// const role = keycloak.tokenParsed?.role
// if (role.includes(to.meta.Role)) {
next()
// } else {
// next({ path: '' })
// // next();
// }
}
} else {
next()
}
// next();
})
export default router