commit
This commit is contained in:
@@ -94,7 +94,7 @@ public class QuartzConfig {
|
||||
factory.setDataSource(dataSource);
|
||||
factory.setTransactionManager(transactionManager);
|
||||
factory.setJobFactory(jobFactory);
|
||||
factory.setAutoStartup(true);
|
||||
factory.setAutoStartup(false);
|
||||
factory.setWaitForJobsToCompleteOnShutdown(true);
|
||||
return factory;
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@ import apiClient, { saveAccessToken, removeTokens } from '../common/axios-instan
|
||||
|
||||
const signService = {
|
||||
|
||||
signIn: async (username, password) => {
|
||||
const response = await apiClient.post('/sign-in', { username, password });
|
||||
signIn: async (params) => {
|
||||
const response = await apiClient.post('/sign-in', params);
|
||||
const accessToken = response.headers['authorization'].split(' ')[1];
|
||||
saveAccessToken(accessToken);
|
||||
return response.data;
|
||||
@@ -24,8 +24,8 @@ const signService = {
|
||||
return response.data.data;
|
||||
},
|
||||
|
||||
changePassword: async (userId, email, newPassword) => {
|
||||
const response = await apiClient.post('/api/user/change-password', { userId, email, newPassword });
|
||||
changePassword: async (params) => {
|
||||
const response = await apiClient.post('/api/user/change-password', params);
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,20 @@
|
||||
dayjs.locale('ko');
|
||||
|
||||
export const addEvents = (eventMap) => {
|
||||
Object.entries(eventMap).forEach(([selector, { event, handler }]) => {
|
||||
const elements = selector.startsWith('#') || selector.startsWith('.') || document.getElementsByName(selector).length > 0
|
||||
? document.querySelectorAll(selector)
|
||||
: document.querySelectorAll(`[id="${selector}"], [class="${selector}"], [name="${selector}"]`);
|
||||
|
||||
elements.forEach(element => {
|
||||
element.addEventListener(event, (e) => {
|
||||
e.preventDefault();
|
||||
handler(e);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export const formatDateTime = (dateTimeString) => {
|
||||
if (!dateTimeString) return '-';
|
||||
const date = new Date(dateTimeString);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { formatDateTime } from '../../common/common.js';
|
||||
import { addEvents, formatDateTime } from '../../common/common.js';
|
||||
import dashBoardService from '../../apis/dashboard-api.js';
|
||||
|
||||
let selectedMonth;
|
||||
@@ -40,9 +40,8 @@ const fetchDataAndRender = async () => {
|
||||
};
|
||||
|
||||
const setupEventListeners = () => {
|
||||
document.getElementById('refreshBtn').addEventListener('click', async (e) => {
|
||||
fetchDataAndRender();
|
||||
});
|
||||
const eventMap = {'refreshBtn': { event: 'click', handler: fetchDataAndRender }};
|
||||
addEvents(eventMap);
|
||||
};
|
||||
|
||||
const chartOptions = {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { addEvents } from '../../common/common.js';
|
||||
import signService from '../../apis/sign-api.js';
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
@@ -5,13 +6,14 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
});
|
||||
|
||||
const setupEventListeners = () => {
|
||||
document.getElementById('signOut').addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
signService.signOut();
|
||||
});
|
||||
const eventMap = {
|
||||
'signOut': { event: 'click', handler: signService.signOut },
|
||||
'toggleSidebar': { event: 'click', handler: toggleSidebar }
|
||||
};
|
||||
addEvents(eventMap);
|
||||
};
|
||||
|
||||
document.getElementById('toggleSidebar').addEventListener('click', () => {
|
||||
const body = document.body;
|
||||
body.classList.toggle("toggle-sidebar");
|
||||
});
|
||||
};
|
||||
const toggleSidebar = () => {
|
||||
const body = document.body;
|
||||
body.classList.toggle("toggle-sidebar");
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { formatDateTime } from '../../common/common.js';
|
||||
import { addEvents, formatDateTime } from '../../common/common.js';
|
||||
import scheduleService from '../../apis/schedule-api.js';
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
@@ -8,16 +8,11 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
});
|
||||
|
||||
const setupEventListeners = () => {
|
||||
document.getElementById('searchForm').addEventListener('submit', async (e) => {
|
||||
e.preventDefault();
|
||||
fetchDataAndRender();
|
||||
});
|
||||
document.getElementById('refreshJobBtn').addEventListener('click', () => {
|
||||
const confirmUpdate = confirm('스케줄 재적용 하시겠습니까?');
|
||||
if (confirmUpdate) {
|
||||
refreshJobs();
|
||||
}
|
||||
});
|
||||
const eventMap = {
|
||||
'searchForm': { event: 'submit', handler: fetchDataAndRender },
|
||||
'refreshJobBtn': { event: 'click', handler: refreshJobs }
|
||||
};
|
||||
addEvents(eventMap);
|
||||
};
|
||||
|
||||
const fetchDataAndRender = async () => {
|
||||
@@ -27,10 +22,13 @@ const fetchDataAndRender = async () => {
|
||||
};
|
||||
|
||||
const refreshJobs = async () => {
|
||||
if (await scheduleService.refreshJob()) {
|
||||
alert('스케줄이 재적용 되었습니다.');
|
||||
manageTooltips.hideAll();
|
||||
fetchDataAndRender();
|
||||
const confirmRefresh = confirm('스케줄 재적용 하시겠습니까?');
|
||||
if (confirmRefresh) {
|
||||
if (await scheduleService.refreshJob()) {
|
||||
alert('스케줄이 재적용 되었습니다.');
|
||||
manageTooltips.hideAll();
|
||||
fetchDataAndRender();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -50,7 +48,8 @@ const updateTable = (jobs) => {
|
||||
</tr>
|
||||
`).join('');
|
||||
|
||||
document.querySelectorAll('.detail-btn').forEach(btn => btn.addEventListener('click', showJobDetail));
|
||||
const eventMap = {'.detail-btn': { event: 'click', handler: showJobDetail }};
|
||||
addEvents(eventMap);
|
||||
};
|
||||
|
||||
const showJobDetail = async ({ target }) => {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { addEvents } from '../../common/common.js';
|
||||
import signService from '../../apis/sign-api.js';
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
@@ -12,7 +13,7 @@ const initializeElements = () => {
|
||||
|
||||
const setupEventListeners = () => {
|
||||
const eventMap = {
|
||||
'signIn': { event: 'click', handler: handleSignIn },
|
||||
'signinForm': { event: 'submit', handler: handleSignIn },
|
||||
'signUp': { event: 'click', handler: () => signupModal.show() },
|
||||
'signupForm': { event: 'submit', handler: handleSignUp },
|
||||
'signupModal': { event: 'hidden.bs.modal', handler: resetForm },
|
||||
@@ -20,21 +21,16 @@ const setupEventListeners = () => {
|
||||
'changePasswordForm': { event: 'submit', handler: handleChangePassword },
|
||||
'changePasswordModal': { event: 'hidden.bs.modal', handler: resetForm }
|
||||
};
|
||||
|
||||
Object.entries(eventMap).forEach(([id, { event, handler }]) => {
|
||||
document.getElementById(id)?.addEventListener(event, handler);
|
||||
});
|
||||
addEvents(eventMap);
|
||||
};
|
||||
|
||||
const handleSignIn = async () => {
|
||||
const username = document.getElementById('username').value;
|
||||
const password = document.getElementById('password').value;
|
||||
const { status, redirectUrl } = await signService.signIn(username, password);
|
||||
const handleSignIn = async (e) => {
|
||||
const params = Object.fromEntries(new FormData(e.target));
|
||||
const { status, redirectUrl } = await signService.signIn(params);
|
||||
if (status) window.location.href = redirectUrl;
|
||||
};
|
||||
|
||||
const handleSignUp = async (e) => {
|
||||
e.preventDefault();
|
||||
const userId = document.getElementById('userId').value;
|
||||
const isConflict = await signService.isConflictUserId(userId);
|
||||
if (!isConflict) {
|
||||
@@ -46,9 +42,8 @@ const handleSignUp = async (e) => {
|
||||
};
|
||||
|
||||
const handleChangePassword = async (e) => {
|
||||
e.preventDefault();
|
||||
const [userId, email, newPassword] = ['changeUserId', 'changeEmail', 'newPassword'].map(id => document.getElementById(id).value);
|
||||
await signService.changePassword(userId, email, newPassword);
|
||||
const params = Object.fromEntries(new FormData(e.target));
|
||||
await signService.changePassword(params);
|
||||
alert('비밀번호가 변경되었습니다.');
|
||||
changePasswordModal.hide();
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { getModifiedRows } from '../../common/common.js';
|
||||
import { addEvents, getModifiedRows } from '../../common/common.js';
|
||||
import userService from '../../apis/user-api.js';
|
||||
|
||||
let users = [];
|
||||
@@ -10,16 +10,11 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
});
|
||||
|
||||
const setupEventListeners = () => {
|
||||
document.getElementById('searchForm').addEventListener('submit', async (e) => {
|
||||
e.preventDefault();
|
||||
fetchDataAndRender();
|
||||
});
|
||||
document.getElementById('updateUserBtn').addEventListener('click', () => {
|
||||
const confirmUpdate = confirm('회원정보를 수정하시겠습니까?');
|
||||
if (confirmUpdate) {
|
||||
updateUser();
|
||||
}
|
||||
});
|
||||
const eventMap = {
|
||||
'searchForm': { event: 'submit', handler: fetchDataAndRender },
|
||||
'updateUserBtn': { event: 'click', handler: updateUser }
|
||||
};
|
||||
addEvents(eventMap);
|
||||
};
|
||||
|
||||
const fetchDataAndRender = async () => {
|
||||
@@ -53,39 +48,41 @@ const updateTable = (users) => {
|
||||
</tr>
|
||||
`).join('');
|
||||
|
||||
document.querySelectorAll('.delete-btn').forEach(btn => btn.addEventListener('click', (e) => {
|
||||
const confirmUpdate = confirm('회원정보를 삭제하시겠습니까?');
|
||||
if (confirmUpdate) {
|
||||
const {id} = e.target.closest('button').dataset;
|
||||
deleteUser(id);
|
||||
}
|
||||
}));
|
||||
const eventMap = {'.delete-btn': { event: 'click', handler: deleteUser }};
|
||||
addEvents(eventMap);
|
||||
};
|
||||
|
||||
const updateUser = async () => {
|
||||
const updatedUsers = Array.from(document.querySelectorAll('tbody tr')).map(row => {
|
||||
const id = row.dataset.key;
|
||||
const selectElement = row.querySelector(`#userRole-${id}`);
|
||||
const checkboxElement = row.querySelector(`#approved-${id}`);
|
||||
const userRole = selectElement ? selectElement.value : null;
|
||||
const isApproved = checkboxElement ? checkboxElement.checked : false;
|
||||
return {
|
||||
id: id,
|
||||
userRole: userRole,
|
||||
approved: isApproved
|
||||
};
|
||||
});
|
||||
const confirmUpdate = confirm('회원정보를 수정하시겠습니까?');
|
||||
if (confirmUpdate) {
|
||||
const updatedUsers = Array.from(document.querySelectorAll('tbody tr')).map(row => {
|
||||
const id = row.dataset.key;
|
||||
const selectElement = row.querySelector(`#userRole-${id}`);
|
||||
const checkboxElement = row.querySelector(`#approved-${id}`);
|
||||
const userRole = selectElement ? selectElement.value : null;
|
||||
const isApproved = checkboxElement ? checkboxElement.checked : false;
|
||||
return {
|
||||
id: id,
|
||||
userRole: userRole,
|
||||
approved: isApproved
|
||||
};
|
||||
});
|
||||
|
||||
await userService.changeRoleApprove(getModifiedRows(users, updatedUsers, "id"));
|
||||
alert('회원정보가 수정 되었습니다.');
|
||||
manageTooltips.hideAll();
|
||||
fetchDataAndRender();
|
||||
await userService.changeRoleApprove(getModifiedRows(users, updatedUsers, "id"));
|
||||
alert('회원정보가 수정 되었습니다.');
|
||||
manageTooltips.hideAll();
|
||||
fetchDataAndRender();
|
||||
}
|
||||
};
|
||||
|
||||
const deleteUser = async (id) => {
|
||||
await userService.deleteUser(id);
|
||||
alert('사용자가 삭제되었습니다.');
|
||||
fetchDataAndRender();
|
||||
const deleteUser = async (e) => {
|
||||
const confirmDelete = confirm('사용자를 삭제하시겠습니까?');
|
||||
if (confirmDelete) {
|
||||
const { id } = e.target.closest('button').dataset;
|
||||
await userService.deleteUser(id);
|
||||
alert('사용자가 삭제되었습니다.');
|
||||
fetchDataAndRender();
|
||||
}
|
||||
};
|
||||
|
||||
const manageTooltips = {
|
||||
|
||||
@@ -11,41 +11,43 @@
|
||||
<div class="row justify-content-center align-items-center min-vh-100">
|
||||
<div class="col-lg-4 col-md-6">
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-body p-5">
|
||||
<div class="text-center mb-4">
|
||||
<i class="bi bi-person-bounding-box text-primary" style="font-size: 4rem;"></i>
|
||||
<h2 class="card-title mt-3" style="font-weight: bold;">Sign in to NXCUS-Agent</h2>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<div class="input-group">
|
||||
<span class="input-group-text">
|
||||
<i class="bi bi-person"></i>
|
||||
<form id="signinForm">
|
||||
<div class="card-body p-5">
|
||||
<div class="text-center mb-4">
|
||||
<i class="bi bi-person-bounding-box text-primary" style="font-size: 4rem;"></i>
|
||||
<h2 class="card-title mt-3" style="font-weight: bold;">Sign in to NXCUS-Agent</h2>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<div class="input-group">
|
||||
<span class="input-group-text">
|
||||
<i class="bi bi-person"></i>
|
||||
</span>
|
||||
<input type="text" id="username" name="username" class="form-control" placeholder="아이디" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<div class="input-group">
|
||||
<span class="input-group-text">
|
||||
<i class="bi bi-lock"></i>
|
||||
</span>
|
||||
<input type="password" id="password" name="password" class="form-control" placeholder="비밀번호" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-grid gap-2">
|
||||
<button id="signIn" type="submit" class="btn btn-primary">
|
||||
<i class="bi bi-box-arrow-in-right me-2"></i>Sign in
|
||||
</button>
|
||||
<button id="signUp" type="button" class="btn btn-outline-secondary">
|
||||
<i class="bi bi-person-plus-fill me-2"></i>Sign up
|
||||
</button>
|
||||
</div>
|
||||
<div class="text-end mt-3">
|
||||
<span id="changePassword" class="text-info text-decoration-none" style="cursor: pointer;">
|
||||
<small><i class="bi bi-key-fill me-1"></i>Reset your password</small>
|
||||
</span>
|
||||
<input type="text" id="username" name="username" class="form-control" placeholder="아이디" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<div class="input-group">
|
||||
<span class="input-group-text">
|
||||
<i class="bi bi-lock"></i>
|
||||
</span>
|
||||
<input type="password" id="password" name="password" class="form-control" placeholder="비밀번호" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-grid gap-2">
|
||||
<button id="signIn" type="button" class="btn btn-primary">
|
||||
<i class="bi bi-box-arrow-in-right me-2"></i>Sign in
|
||||
</button>
|
||||
<button id="signUp" type="button" class="btn btn-outline-secondary">
|
||||
<i class="bi bi-person-plus-fill me-2"></i>Sign up
|
||||
</button>
|
||||
</div>
|
||||
<div class="text-end mt-3">
|
||||
<span id="changePassword" class="text-info text-decoration-none" style="cursor: pointer;">
|
||||
<small><i class="bi bi-key-fill me-1"></i>Reset your password</small>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user