commit
This commit is contained in:
@@ -3,7 +3,7 @@
|
|||||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||||
layout:decorate="~{layouts/signin-layout}" lang="ko" xml:lang="ko">
|
layout:decorate="~{layouts/signin-layout}" lang="ko" xml:lang="ko">
|
||||||
<head>
|
<head>
|
||||||
<title>로그인 페이지</title>
|
<title>Sign In</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<section layout:fragment="content">
|
<section layout:fragment="content">
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ public class QuartzConfig {
|
|||||||
factory.setDataSource(dataSource);
|
factory.setDataSource(dataSource);
|
||||||
factory.setTransactionManager(transactionManager);
|
factory.setTransactionManager(transactionManager);
|
||||||
factory.setJobFactory(jobFactory);
|
factory.setJobFactory(jobFactory);
|
||||||
factory.setAutoStartup(false);
|
factory.setAutoStartup(true);
|
||||||
factory.setWaitForJobsToCompleteOnShutdown(true);
|
factory.setWaitForJobsToCompleteOnShutdown(true);
|
||||||
return factory;
|
return factory;
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 355 KiB After Width: | Height: | Size: 19 KiB |
@@ -13,18 +13,18 @@ const scheduleService = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
pauseJob: async (groupName, jobName) => {
|
pauseJob: async (groupName, jobName) => {
|
||||||
const response = await apiClient.get(`/api/schedule/pause/${groupName}/${jobName}`);
|
await apiClient.get(`/api/schedule/pause/${groupName}/${jobName}`);
|
||||||
return response.data.data;
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
resumeJob: async (groupName, jobName) => {
|
resumeJob: async (groupName, jobName) => {
|
||||||
const response = await apiClient.get(`/api/schedule/resume/${groupName}/${jobName}`);
|
await apiClient.get(`/api/schedule/resume/${groupName}/${jobName}`);
|
||||||
return response.data.data;
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
triggerJob: async (groupName, jobName) => {
|
triggerJob: async (groupName, jobName) => {
|
||||||
const response = await apiClient.get(`/api/schedule/trigger/${groupName}/${jobName}`);
|
await apiClient.get(`/api/schedule/trigger/${groupName}/${jobName}`);
|
||||||
return response.data.data;
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
rescheduleJob: async (jobGroup, jobName, cronExpression) => {
|
rescheduleJob: async (jobGroup, jobName, cronExpression) => {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ let selectedMonth;
|
|||||||
document.addEventListener('DOMContentLoaded', () => {
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
initMonthPicker();
|
initMonthPicker();
|
||||||
fetchDataAndRender();
|
fetchDataAndRender();
|
||||||
|
setupEventListeners();
|
||||||
});
|
});
|
||||||
|
|
||||||
const initMonthPicker = () => {
|
const initMonthPicker = () => {
|
||||||
@@ -38,6 +39,12 @@ const fetchDataAndRender = async () => {
|
|||||||
renderRecentJobsTable(recentJobs);
|
renderRecentJobsTable(recentJobs);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const setupEventListeners = () => {
|
||||||
|
document.getElementById('refreshBtn').addEventListener('click', async (e) => {
|
||||||
|
fetchDataAndRender();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const chartOptions = {
|
const chartOptions = {
|
||||||
responsive: true,
|
responsive: true,
|
||||||
maintainAspectRatio: false,
|
maintainAspectRatio: false,
|
||||||
|
|||||||
@@ -1,16 +1,17 @@
|
|||||||
import signService from '../../apis/sign-api.js';
|
import signService from '../../apis/sign-api.js';
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
const signOutButton = document.getElementById('signOut');
|
setupEventListeners();
|
||||||
const toggleSidebar = document.getElementById('toggleSidebar');
|
});
|
||||||
|
|
||||||
signOutButton.addEventListener('click', (e) => {
|
const setupEventListeners = () => {
|
||||||
|
document.getElementById('signOut').addEventListener('click', (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
signService.signOut();
|
signService.signOut();
|
||||||
});
|
});
|
||||||
|
|
||||||
toggleSidebar.addEventListener('click', (e) => {
|
document.getElementById('toggleSidebar').addEventListener('click', () => {
|
||||||
const body = document.body;
|
const body = document.body;
|
||||||
body.classList.toggle("toggle-sidebar");
|
body.classList.toggle("toggle-sidebar");
|
||||||
});
|
});
|
||||||
});
|
};
|
||||||
@@ -12,7 +12,12 @@ const setupEventListeners = () => {
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
fetchDataAndRender();
|
fetchDataAndRender();
|
||||||
});
|
});
|
||||||
document.getElementById('refreshJobBtn').addEventListener('click', refreshJobs);
|
document.getElementById('refreshJobBtn').addEventListener('click', () => {
|
||||||
|
const confirmUpdate = confirm('스케줄 재적용 하시겠습니까?');
|
||||||
|
if (confirmUpdate) {
|
||||||
|
refreshJobs();
|
||||||
|
}
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const fetchDataAndRender = async () => {
|
const fetchDataAndRender = async () => {
|
||||||
@@ -99,16 +104,21 @@ const getStatusBadgeClass = (status) => {
|
|||||||
const setupDetailModalEventListeners = (group, name) => {
|
const setupDetailModalEventListeners = (group, name) => {
|
||||||
document.getElementById('pauseJobBtn').onclick = () => updateJobStatus(group, name, 'PAUSED', scheduleService.pauseJob);
|
document.getElementById('pauseJobBtn').onclick = () => updateJobStatus(group, name, 'PAUSED', scheduleService.pauseJob);
|
||||||
document.getElementById('resumeJobBtn').onclick = () => updateJobStatus(group, name, 'NORMAL', scheduleService.resumeJob);
|
document.getElementById('resumeJobBtn').onclick = () => updateJobStatus(group, name, 'NORMAL', scheduleService.resumeJob);
|
||||||
document.getElementById('updateCronBtn').onclick = () => updateCronExpression(group, name);
|
document.getElementById('updateCronBtn').onclick = () => {
|
||||||
|
const confirmUpdate = confirm('스케줄을 수정하시겠습니까?');
|
||||||
|
if (confirmUpdate) {
|
||||||
|
updateCronExpression(group, name);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateCronExpression = async (group, name) => {
|
const updateCronExpression = async (group, name) => {
|
||||||
const newCronExpression = document.getElementById('cronExpression').value;
|
const newCronExpression = document.getElementById('cronExpression').value;
|
||||||
if (await scheduleService.rescheduleJob(group, name, newCronExpression)) {
|
if (await scheduleService.rescheduleJob(group, name, newCronExpression)) {
|
||||||
alert('스케쥴이 수정 되었습니다.');
|
alert('스케줄이 수정 되었습니다.');
|
||||||
fetchDataAndRender();
|
fetchDataAndRender();
|
||||||
} else {
|
} else {
|
||||||
alert('스케쥴 수정이 실패했습니다.');
|
alert('스케줄 수정이 실패했습니다.');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -128,7 +138,8 @@ const updateJobControlButtons = (status) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const updateJobStatus = async (group, name, newStatus, action) => {
|
const updateJobStatus = async (group, name, newStatus, action) => {
|
||||||
if (await action(group, name)) {
|
const result = await action(group, name);
|
||||||
|
if (result) {
|
||||||
const statusElement = document.querySelector('#scheduleDetailContent .badge');
|
const statusElement = document.querySelector('#scheduleDetailContent .badge');
|
||||||
statusElement.className = `badge ${getStatusBadgeClass(newStatus)}`;
|
statusElement.className = `badge ${getStatusBadgeClass(newStatus)}`;
|
||||||
statusElement.textContent = newStatus;
|
statusElement.textContent = newStatus;
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ let users = [];
|
|||||||
document.addEventListener('DOMContentLoaded', () => {
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
fetchDataAndRender();
|
fetchDataAndRender();
|
||||||
setupEventListeners();
|
setupEventListeners();
|
||||||
|
manageTooltips.init();
|
||||||
});
|
});
|
||||||
|
|
||||||
const setupEventListeners = () => {
|
const setupEventListeners = () => {
|
||||||
@@ -77,6 +78,7 @@ const updateUser = async () => {
|
|||||||
|
|
||||||
await userService.changeRoleApprove(getModifiedRows(users, updatedUsers, "id"));
|
await userService.changeRoleApprove(getModifiedRows(users, updatedUsers, "id"));
|
||||||
alert('회원정보가 수정 되었습니다.');
|
alert('회원정보가 수정 되었습니다.');
|
||||||
|
manageTooltips.hideAll();
|
||||||
fetchDataAndRender();
|
fetchDataAndRender();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -84,4 +86,15 @@ const deleteUser = async (id) => {
|
|||||||
await userService.deleteUser(id);
|
await userService.deleteUser(id);
|
||||||
alert('사용자가 삭제되었습니다.');
|
alert('사용자가 삭제되었습니다.');
|
||||||
fetchDataAndRender();
|
fetchDataAndRender();
|
||||||
|
};
|
||||||
|
|
||||||
|
const manageTooltips = {
|
||||||
|
init: () => {
|
||||||
|
document.querySelectorAll('[data-bs-toggle="tooltip"]')
|
||||||
|
.forEach(el => new bootstrap.Tooltip(el));
|
||||||
|
},
|
||||||
|
hideAll: () => {
|
||||||
|
const tooltip = bootstrap.Tooltip.getInstance('#updateUserBtn');
|
||||||
|
setTimeout(() => tooltip.hide(), 100);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
@@ -25,11 +25,14 @@
|
|||||||
</div>
|
</div>
|
||||||
<section class="section">
|
<section class="section">
|
||||||
<div class="row mb-4">
|
<div class="row mb-4">
|
||||||
<div class="col-md-4">
|
<div class="col-md-4 d-flex align-items-center">
|
||||||
<div class="input-group">
|
<div class="input-group me-2">
|
||||||
<span class="input-group-text"><i class="bi bi-calendar-month"></i></span>
|
<span class="input-group-text"><i class="bi bi-calendar-month"></i></span>
|
||||||
<input type="month" id="monthPicker" class="form-control">
|
<input type="month" id="monthPicker" class="form-control">
|
||||||
</div>
|
</div>
|
||||||
|
<button id="refreshBtn" class="btn btn-sm btn-outline-primary" title="재조회">
|
||||||
|
<i class="bi bi-arrow-clockwise"></i>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
@@ -86,10 +89,10 @@
|
|||||||
<table class="table table-hover">
|
<table class="table table-hover">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th class="col-1 text-nowrap sticky-top bg-light"><i class="bi bi-people"></i> 그룹명</th>
|
<th class="col-1 text-nowrap bg-light"><i class="bi bi-people"></i> 그룹명</th>
|
||||||
<th class="col-1 text-nowrap sticky-top bg-light"><i class="bi bi-briefcase"></i> 잡 이름</th>
|
<th class="col-1 text-nowrap bg-light"><i class="bi bi-briefcase"></i> 잡 이름</th>
|
||||||
<th class="col-1 text-nowrap sticky-top bg-light"><i class="bi bi-calendar-event me-2"></i> 실행 시간</th>
|
<th class="col-1 text-nowrap bg-light"><i class="bi bi-calendar-event me-2"></i> 실행 시간</th>
|
||||||
<th class="col-1 text-nowrap sticky-top bg-light"><i class="bi bi-activity"></i> 상태</th>
|
<th class="col-1 text-nowrap bg-light"><i class="bi bi-activity"></i> 상태</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody id="recentJobsTable">
|
<tbody id="recentJobsTable">
|
||||||
|
|||||||
@@ -64,11 +64,11 @@
|
|||||||
<table class="table table-hover">
|
<table class="table table-hover">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th class="col-1 text-nowrap sticky-top bg-light"><i class="bi bi-people"></i> 그룹</th>
|
<th class="col-1 text-nowrap bg-light"><i class="bi bi-people"></i> 그룹</th>
|
||||||
<th class="col-1 text-nowrap sticky-top bg-light"><i class="bi bi-briefcase"></i> 잡 이름</th>
|
<th class="col-1 text-nowrap bg-light"><i class="bi bi-briefcase"></i> 잡 이름</th>
|
||||||
<th class="col-1 text-nowrap sticky-top bg-light"><i class="bi bi-calendar-event"></i> 스케줄</th>
|
<th class="col-1 text-nowrap bg-light"><i class="bi bi-calendar-event"></i> 스케줄</th>
|
||||||
<th class="col-1 text-nowrap sticky-top bg-light"><i class="bi bi-activity"></i> 상태</th>
|
<th class="col-1 text-nowrap bg-light"><i class="bi bi-activity"></i> 상태</th>
|
||||||
<th class="col-1 text-nowrap sticky-top bg-light"><i class="bi bi-gear"></i> 액션</th>
|
<th class="col-1 text-nowrap bg-light"><i class="bi bi-gear"></i> 액션</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@@ -81,7 +81,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<div class="modal fade" id="scheduleDetailModal" tabindex="-1" aria-labelledby="scheduleDetailModalLabel" aria-hidden="true">
|
<div class="modal fade" id="scheduleDetailModal" tabindex="-1" aria-labelledby="scheduleDetailModalLabel" aria-hidden="true" data-bs-backdrop="static">
|
||||||
<div class="modal-dialog modal-dialog-scrollable modal-dialog-centered">
|
<div class="modal-dialog modal-dialog-scrollable modal-dialog-centered">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header bg-dark text-white">
|
<div class="modal-header bg-dark text-white">
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||||
layout:decorate="~{layouts/signin-layout}" lang="ko" xml:lang="ko">
|
layout:decorate="~{layouts/signin-layout}" lang="ko" xml:lang="ko">
|
||||||
<head>
|
<head>
|
||||||
<title>로그인 페이지</title>
|
<title>Sign In</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<section layout:fragment="content">
|
<section layout:fragment="content">
|
||||||
@@ -13,8 +13,8 @@
|
|||||||
<div class="card shadow-sm">
|
<div class="card shadow-sm">
|
||||||
<div class="card-body p-5">
|
<div class="card-body p-5">
|
||||||
<div class="text-center mb-4">
|
<div class="text-center mb-4">
|
||||||
<i class="bi bi-person-circle text-primary" style="font-size: 3rem;"></i>
|
<i class="bi bi-person-bounding-box text-primary" style="font-size: 4rem;"></i>
|
||||||
<h2 class="card-title mt-3">Sign in to NXCUS-Agent</h2>
|
<h2 class="card-title mt-3" style="font-weight: bold;">Sign in to NXCUS-Agent</h2>
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
@@ -52,7 +52,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 회원가입 모달 -->
|
<!-- 회원가입 모달 -->
|
||||||
<div class="modal fade" id="signupModal" tabindex="-1" aria-labelledby="signupModalLabel" aria-hidden="true">
|
<div class="modal fade" id="signupModal" tabindex="-1" aria-labelledby="signupModalLabel" aria-hidden="true" data-bs-backdrop="static">
|
||||||
<div class="modal-dialog modal-dialog-scrollable modal-dialog-centered">
|
<div class="modal-dialog modal-dialog-scrollable modal-dialog-centered">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header bg-dark text-white">
|
<div class="modal-header bg-dark text-white">
|
||||||
@@ -108,7 +108,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 비밀번호 변경 모달 -->
|
<!-- 비밀번호 변경 모달 -->
|
||||||
<div class="modal fade" id="changePasswordModal" tabindex="-1" aria-labelledby="changePasswordModalLabel" aria-hidden="true">
|
<div class="modal fade" id="changePasswordModal" tabindex="-1" aria-labelledby="changePasswordModalLabel" aria-hidden="true" data-bs-backdrop="static">
|
||||||
<div class="modal-dialog modal-dialog-centered">
|
<div class="modal-dialog modal-dialog-centered">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header bg-info text-white">
|
<div class="modal-header bg-info text-white">
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
layout:decorate="~{layouts/layout}"
|
layout:decorate="~{layouts/layout}"
|
||||||
layout:fragment="content" lang="ko" xml:lang="ko">
|
layout:fragment="content" lang="ko" xml:lang="ko">
|
||||||
<head>
|
<head>
|
||||||
<title>사용자 관리</title>
|
<title>User Management</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<main id="main" class="main">
|
<main id="main" class="main">
|
||||||
|
|||||||
Reference in New Issue
Block a user