|
@@ -1,552 +0,0 @@
|
|
|
-import { Template } from 'meteor/templating';
|
|
|
-import { ReactiveVar } from 'meteor/reactive-var';
|
|
|
-import { Meteor } from 'meteor/meteor';
|
|
|
-import { TAPi18n } from '/imports/i18n';
|
|
|
-
|
|
|
-// Reactive variables for cron settings
|
|
|
-const migrationProgress = new ReactiveVar(0);
|
|
|
-const migrationStatus = new ReactiveVar('');
|
|
|
-const migrationCurrentStep = new ReactiveVar('');
|
|
|
-const migrationSteps = new ReactiveVar([]);
|
|
|
-const isMigrating = new ReactiveVar(false);
|
|
|
-const cronJobs = new ReactiveVar([]);
|
|
|
-
|
|
|
-Template.cronSettings.onCreated(function() {
|
|
|
- this.loading = new ReactiveVar(true);
|
|
|
- this.showMigrations = new ReactiveVar(true);
|
|
|
- this.showBoardOperations = new ReactiveVar(false);
|
|
|
- this.showJobs = new ReactiveVar(false);
|
|
|
- this.showAddJob = new ReactiveVar(false);
|
|
|
-
|
|
|
- // Board operations pagination
|
|
|
- this.currentPage = new ReactiveVar(1);
|
|
|
- this.pageSize = new ReactiveVar(20);
|
|
|
- this.searchTerm = new ReactiveVar('');
|
|
|
- this.boardOperations = new ReactiveVar([]);
|
|
|
- this.operationStats = new ReactiveVar({});
|
|
|
- this.pagination = new ReactiveVar({});
|
|
|
- this.queueStats = new ReactiveVar({});
|
|
|
- this.systemResources = new ReactiveVar({});
|
|
|
- this.boardMigrationStats = new ReactiveVar({});
|
|
|
-
|
|
|
- // Load initial data
|
|
|
- loadCronData(this);
|
|
|
-});
|
|
|
-
|
|
|
-Template.cronSettings.helpers({
|
|
|
- loading() {
|
|
|
- const instance = Template.instance();
|
|
|
- return instance && instance.loading ? instance.loading.get() : true;
|
|
|
- },
|
|
|
-
|
|
|
- showMigrations() {
|
|
|
- const instance = Template.instance();
|
|
|
- return instance && instance.showMigrations ? instance.showMigrations.get() : true;
|
|
|
- },
|
|
|
-
|
|
|
- showBoardOperations() {
|
|
|
- const instance = Template.instance();
|
|
|
- return instance && instance.showBoardOperations ? instance.showBoardOperations.get() : false;
|
|
|
- },
|
|
|
-
|
|
|
- showJobs() {
|
|
|
- const instance = Template.instance();
|
|
|
- return instance && instance.showJobs ? instance.showJobs.get() : false;
|
|
|
- },
|
|
|
-
|
|
|
- showAddJob() {
|
|
|
- const instance = Template.instance();
|
|
|
- return instance && instance.showAddJob ? instance.showAddJob.get() : false;
|
|
|
- },
|
|
|
-
|
|
|
- migrationProgress() {
|
|
|
- return migrationProgress.get();
|
|
|
- },
|
|
|
-
|
|
|
- migrationStatus() {
|
|
|
- return migrationStatus.get();
|
|
|
- },
|
|
|
-
|
|
|
- migrationCurrentStep() {
|
|
|
- return migrationCurrentStep.get();
|
|
|
- },
|
|
|
-
|
|
|
- migrationSteps() {
|
|
|
- const steps = migrationSteps.get();
|
|
|
- const currentStep = migrationCurrentStep.get();
|
|
|
-
|
|
|
- return steps.map(step => ({
|
|
|
- ...step,
|
|
|
- isCurrentStep: step.name === currentStep
|
|
|
- }));
|
|
|
- },
|
|
|
-
|
|
|
- cronJobs() {
|
|
|
- return cronJobs.get();
|
|
|
- },
|
|
|
-
|
|
|
- formatDate(date) {
|
|
|
- if (!date) return '-';
|
|
|
- return new Date(date).toLocaleString();
|
|
|
- },
|
|
|
-
|
|
|
- boardOperations() {
|
|
|
- const instance = Template.instance();
|
|
|
- return instance && instance.boardOperations ? instance.boardOperations.get() : [];
|
|
|
- },
|
|
|
-
|
|
|
- operationStats() {
|
|
|
- const instance = Template.instance();
|
|
|
- return instance && instance.operationStats ? instance.operationStats.get() : {};
|
|
|
- },
|
|
|
-
|
|
|
- pagination() {
|
|
|
- const instance = Template.instance();
|
|
|
- return instance && instance.pagination ? instance.pagination.get() : {};
|
|
|
- },
|
|
|
-
|
|
|
- queueStats() {
|
|
|
- const instance = Template.instance();
|
|
|
- return instance && instance.queueStats ? instance.queueStats.get() : {};
|
|
|
- },
|
|
|
-
|
|
|
- systemResources() {
|
|
|
- const instance = Template.instance();
|
|
|
- return instance && instance.systemResources ? instance.systemResources.get() : {};
|
|
|
- },
|
|
|
-
|
|
|
- boardMigrationStats() {
|
|
|
- const instance = Template.instance();
|
|
|
- return instance && instance.boardMigrationStats ? instance.boardMigrationStats.get() : {};
|
|
|
- },
|
|
|
-
|
|
|
- formatDateTime(date) {
|
|
|
- if (!date) return '-';
|
|
|
- return new Date(date).toLocaleString();
|
|
|
- },
|
|
|
-
|
|
|
- formatDuration(startTime, endTime) {
|
|
|
- if (!startTime) return '-';
|
|
|
- const start = new Date(startTime);
|
|
|
- const end = endTime ? new Date(endTime) : new Date();
|
|
|
- const diffMs = end - start;
|
|
|
- const diffMins = Math.floor(diffMs / 60000);
|
|
|
- const diffSecs = Math.floor((diffMs % 60000) / 1000);
|
|
|
-
|
|
|
- if (diffMins > 0) {
|
|
|
- return `${diffMins}m ${diffSecs}s`;
|
|
|
- } else {
|
|
|
- return `${diffSecs}s`;
|
|
|
- }
|
|
|
- }
|
|
|
-});
|
|
|
-
|
|
|
-Template.cronSettings.switchMenu = function(event, targetID) {
|
|
|
- const instance = Template.instance();
|
|
|
-
|
|
|
- // Reset all tabs
|
|
|
- instance.showMigrations.set(false);
|
|
|
- instance.showBoardOperations.set(false);
|
|
|
- instance.showJobs.set(false);
|
|
|
- instance.showAddJob.set(false);
|
|
|
-
|
|
|
- // Set the selected tab
|
|
|
- if (targetID === 'cron-migrations') {
|
|
|
- instance.showMigrations.set(true);
|
|
|
- } else if (targetID === 'cron-board-operations') {
|
|
|
- instance.showBoardOperations.set(true);
|
|
|
- } else if (targetID === 'cron-jobs') {
|
|
|
- instance.showJobs.set(true);
|
|
|
- } else if (targetID === 'cron-add') {
|
|
|
- instance.showAddJob.set(true);
|
|
|
- }
|
|
|
-};
|
|
|
-
|
|
|
-Template.cronSettings.events({
|
|
|
- 'click .js-cron-migrations'(event) {
|
|
|
- event.preventDefault();
|
|
|
- const instance = Template.instance();
|
|
|
- instance.showMigrations.set(true);
|
|
|
- instance.showJobs.set(false);
|
|
|
- instance.showAddJob.set(false);
|
|
|
- },
|
|
|
-
|
|
|
- 'click .js-cron-board-operations'(event) {
|
|
|
- event.preventDefault();
|
|
|
- const instance = Template.instance();
|
|
|
- instance.showMigrations.set(false);
|
|
|
- instance.showBoardOperations.set(true);
|
|
|
- instance.showJobs.set(false);
|
|
|
- instance.showAddJob.set(false);
|
|
|
- loadBoardOperations(instance);
|
|
|
- },
|
|
|
-
|
|
|
- 'click .js-cron-jobs'(event) {
|
|
|
- event.preventDefault();
|
|
|
- const instance = Template.instance();
|
|
|
- instance.showMigrations.set(false);
|
|
|
- instance.showBoardOperations.set(false);
|
|
|
- instance.showJobs.set(true);
|
|
|
- instance.showAddJob.set(false);
|
|
|
- loadCronJobs(instance);
|
|
|
- },
|
|
|
-
|
|
|
- 'click .js-cron-add'(event) {
|
|
|
- event.preventDefault();
|
|
|
- const instance = Template.instance();
|
|
|
- instance.showMigrations.set(false);
|
|
|
- instance.showJobs.set(false);
|
|
|
- instance.showAddJob.set(true);
|
|
|
- },
|
|
|
-
|
|
|
- 'click .js-start-all-migrations'(event) {
|
|
|
- event.preventDefault();
|
|
|
- Meteor.call('cron.startAllMigrations', (error, result) => {
|
|
|
- if (error) {
|
|
|
- console.error('Failed to start migrations:', error);
|
|
|
- alert('Failed to start migrations: ' + error.message);
|
|
|
- } else {
|
|
|
- // Migrations started successfully
|
|
|
- pollMigrationProgress(Template.instance());
|
|
|
- }
|
|
|
- });
|
|
|
- },
|
|
|
-
|
|
|
- 'click .js-pause-all-migrations'(event) {
|
|
|
- event.preventDefault();
|
|
|
- // Pause all migration cron jobs
|
|
|
- const jobs = cronJobs.get();
|
|
|
- jobs.forEach(job => {
|
|
|
- if (job.name.startsWith('migration_')) {
|
|
|
- Meteor.call('cron.pauseJob', job.name);
|
|
|
- }
|
|
|
- });
|
|
|
- },
|
|
|
-
|
|
|
- 'click .js-stop-all-migrations'(event) {
|
|
|
- event.preventDefault();
|
|
|
- // Stop all migration cron jobs
|
|
|
- const jobs = cronJobs.get();
|
|
|
- jobs.forEach(job => {
|
|
|
- if (job.name.startsWith('migration_')) {
|
|
|
- Meteor.call('cron.stopJob', job.name);
|
|
|
- }
|
|
|
- });
|
|
|
- },
|
|
|
-
|
|
|
- 'click .js-refresh-jobs'(event) {
|
|
|
- event.preventDefault();
|
|
|
- loadCronJobs(Template.instance());
|
|
|
- },
|
|
|
-
|
|
|
- 'click .js-start-job'(event) {
|
|
|
- event.preventDefault();
|
|
|
- const jobName = $(event.currentTarget).data('job');
|
|
|
- Meteor.call('cron.startJob', jobName, (error, result) => {
|
|
|
- if (error) {
|
|
|
- console.error('Failed to start job:', error);
|
|
|
- alert('Failed to start job: ' + error.message);
|
|
|
- } else {
|
|
|
- console.log('Job started successfully');
|
|
|
- loadCronJobs(Template.instance());
|
|
|
- }
|
|
|
- });
|
|
|
- },
|
|
|
-
|
|
|
- 'click .js-pause-job'(event) {
|
|
|
- event.preventDefault();
|
|
|
- const jobName = $(event.currentTarget).data('job');
|
|
|
- Meteor.call('cron.pauseJob', jobName, (error, result) => {
|
|
|
- if (error) {
|
|
|
- console.error('Failed to pause job:', error);
|
|
|
- alert('Failed to pause job: ' + error.message);
|
|
|
- } else {
|
|
|
- console.log('Job paused successfully');
|
|
|
- loadCronJobs(Template.instance());
|
|
|
- }
|
|
|
- });
|
|
|
- },
|
|
|
-
|
|
|
- 'click .js-stop-job'(event) {
|
|
|
- event.preventDefault();
|
|
|
- const jobName = $(event.currentTarget).data('job');
|
|
|
- Meteor.call('cron.stopJob', jobName, (error, result) => {
|
|
|
- if (error) {
|
|
|
- console.error('Failed to stop job:', error);
|
|
|
- alert('Failed to stop job: ' + error.message);
|
|
|
- } else {
|
|
|
- console.log('Job stopped successfully');
|
|
|
- loadCronJobs(Template.instance());
|
|
|
- }
|
|
|
- });
|
|
|
- },
|
|
|
-
|
|
|
- 'click .js-remove-job'(event) {
|
|
|
- event.preventDefault();
|
|
|
- const jobName = $(event.currentTarget).data('job');
|
|
|
- if (confirm('Are you sure you want to remove this job?')) {
|
|
|
- Meteor.call('cron.removeJob', jobName, (error, result) => {
|
|
|
- if (error) {
|
|
|
- console.error('Failed to remove job:', error);
|
|
|
- alert('Failed to remove job: ' + error.message);
|
|
|
- } else {
|
|
|
- console.log('Job removed successfully');
|
|
|
- loadCronJobs(Template.instance());
|
|
|
- }
|
|
|
- });
|
|
|
- }
|
|
|
- },
|
|
|
-
|
|
|
- 'submit .js-add-cron-job-form'(event) {
|
|
|
- event.preventDefault();
|
|
|
- const form = event.currentTarget;
|
|
|
- const formData = new FormData(form);
|
|
|
-
|
|
|
- const jobData = {
|
|
|
- name: formData.get('name'),
|
|
|
- description: formData.get('description'),
|
|
|
- schedule: formData.get('schedule'),
|
|
|
- weight: parseInt(formData.get('weight'))
|
|
|
- };
|
|
|
-
|
|
|
- Meteor.call('cron.addJob', jobData, (error, result) => {
|
|
|
- if (error) {
|
|
|
- console.error('Failed to add job:', error);
|
|
|
- alert('Failed to add job: ' + error.message);
|
|
|
- } else {
|
|
|
- console.log('Job added successfully');
|
|
|
- form.reset();
|
|
|
- Template.instance().showJobs.set(true);
|
|
|
- Template.instance().showAddJob.set(false);
|
|
|
- loadCronJobs(Template.instance());
|
|
|
- }
|
|
|
- });
|
|
|
- },
|
|
|
-
|
|
|
- 'click .js-cancel-add-job'(event) {
|
|
|
- event.preventDefault();
|
|
|
- const instance = Template.instance();
|
|
|
- instance.showJobs.set(true);
|
|
|
- instance.showAddJob.set(false);
|
|
|
- },
|
|
|
-
|
|
|
- 'click .js-refresh-board-operations'(event) {
|
|
|
- event.preventDefault();
|
|
|
- loadBoardOperations(Template.instance());
|
|
|
- },
|
|
|
-
|
|
|
- 'click .js-start-test-operation'(event) {
|
|
|
- event.preventDefault();
|
|
|
- const testBoardId = 'test-board-' + Date.now();
|
|
|
- const operationData = {
|
|
|
- sourceBoardId: 'source-board',
|
|
|
- targetBoardId: 'target-board',
|
|
|
- copyOptions: { includeCards: true, includeAttachments: true }
|
|
|
- };
|
|
|
-
|
|
|
- Meteor.call('cron.startBoardOperation', testBoardId, 'copy_board', operationData, (error, result) => {
|
|
|
- if (error) {
|
|
|
- console.error('Failed to start test operation:', error);
|
|
|
- alert('Failed to start test operation: ' + error.message);
|
|
|
- } else {
|
|
|
- console.log('Test operation started:', result);
|
|
|
- loadBoardOperations(Template.instance());
|
|
|
- }
|
|
|
- });
|
|
|
- },
|
|
|
-
|
|
|
- 'input .js-search-board-operations'(event) {
|
|
|
- const searchTerm = $(event.currentTarget).val();
|
|
|
- const instance = Template.instance();
|
|
|
- instance.searchTerm.set(searchTerm);
|
|
|
- instance.currentPage.set(1);
|
|
|
- loadBoardOperations(instance);
|
|
|
- },
|
|
|
-
|
|
|
- 'click .js-prev-page'(event) {
|
|
|
- event.preventDefault();
|
|
|
- const instance = Template.instance();
|
|
|
- const currentPage = instance.currentPage.get();
|
|
|
- if (currentPage > 1) {
|
|
|
- instance.currentPage.set(currentPage - 1);
|
|
|
- loadBoardOperations(instance);
|
|
|
- }
|
|
|
- },
|
|
|
-
|
|
|
- 'click .js-next-page'(event) {
|
|
|
- event.preventDefault();
|
|
|
- const instance = Template.instance();
|
|
|
- const currentPage = instance.currentPage.get();
|
|
|
- const pagination = instance.pagination.get();
|
|
|
- if (currentPage < pagination.totalPages) {
|
|
|
- instance.currentPage.set(currentPage + 1);
|
|
|
- loadBoardOperations(instance);
|
|
|
- }
|
|
|
- },
|
|
|
-
|
|
|
- 'click .js-pause-operation'(event) {
|
|
|
- event.preventDefault();
|
|
|
- const operationId = $(event.currentTarget).data('operation');
|
|
|
- // Implementation for pausing operation
|
|
|
- console.log('Pause operation:', operationId);
|
|
|
- },
|
|
|
-
|
|
|
- 'click .js-resume-operation'(event) {
|
|
|
- event.preventDefault();
|
|
|
- const operationId = $(event.currentTarget).data('operation');
|
|
|
- // Implementation for resuming operation
|
|
|
- console.log('Resume operation:', operationId);
|
|
|
- },
|
|
|
-
|
|
|
- 'click .js-stop-operation'(event) {
|
|
|
- event.preventDefault();
|
|
|
- const operationId = $(event.currentTarget).data('operation');
|
|
|
- if (confirm('Are you sure you want to stop this operation?')) {
|
|
|
- // Implementation for stopping operation
|
|
|
- console.log('Stop operation:', operationId);
|
|
|
- }
|
|
|
- },
|
|
|
-
|
|
|
- 'click .js-view-details'(event) {
|
|
|
- event.preventDefault();
|
|
|
- const operationId = $(event.currentTarget).data('operation');
|
|
|
- // Implementation for viewing operation details
|
|
|
- console.log('View details for operation:', operationId);
|
|
|
- },
|
|
|
-
|
|
|
- 'click .js-force-board-scan'(event) {
|
|
|
- event.preventDefault();
|
|
|
- Meteor.call('cron.forceBoardMigrationScan', (error, result) => {
|
|
|
- if (error) {
|
|
|
- console.error('Failed to force board scan:', error);
|
|
|
- alert('Failed to force board scan: ' + error.message);
|
|
|
- } else {
|
|
|
- // Board scan started successfully
|
|
|
- // Refresh the data
|
|
|
- loadBoardOperations(Template.instance());
|
|
|
- }
|
|
|
- });
|
|
|
- }
|
|
|
-});
|
|
|
-
|
|
|
-// Helper functions for cron settings
|
|
|
-function loadCronData(instance) {
|
|
|
- instance.loading.set(true);
|
|
|
-
|
|
|
- // Load migration progress
|
|
|
- Meteor.call('cron.getMigrationProgress', (error, result) => {
|
|
|
- if (result) {
|
|
|
- migrationProgress.set(result.progress);
|
|
|
- migrationStatus.set(result.status);
|
|
|
- migrationCurrentStep.set(result.currentStep);
|
|
|
- migrationSteps.set(result.steps);
|
|
|
- isMigrating.set(result.isMigrating);
|
|
|
- }
|
|
|
- });
|
|
|
-
|
|
|
- // Load cron jobs
|
|
|
- loadCronJobs(instance);
|
|
|
-
|
|
|
- instance.loading.set(false);
|
|
|
-}
|
|
|
-
|
|
|
-function loadCronJobs(instance) {
|
|
|
- Meteor.call('cron.getJobs', (error, result) => {
|
|
|
- if (result) {
|
|
|
- cronJobs.set(result);
|
|
|
- }
|
|
|
- });
|
|
|
-}
|
|
|
-
|
|
|
-function loadBoardOperations(instance) {
|
|
|
- const page = instance.currentPage.get();
|
|
|
- const limit = instance.pageSize.get();
|
|
|
- const searchTerm = instance.searchTerm.get();
|
|
|
-
|
|
|
- Meteor.call('cron.getAllBoardOperations', page, limit, searchTerm, (error, result) => {
|
|
|
- if (result) {
|
|
|
- instance.boardOperations.set(result.operations);
|
|
|
- instance.pagination.set({
|
|
|
- total: result.total,
|
|
|
- page: result.page,
|
|
|
- limit: result.limit,
|
|
|
- totalPages: result.totalPages,
|
|
|
- start: ((result.page - 1) * result.limit) + 1,
|
|
|
- end: Math.min(result.page * result.limit, result.total),
|
|
|
- hasPrev: result.page > 1,
|
|
|
- hasNext: result.page < result.totalPages
|
|
|
- });
|
|
|
- }
|
|
|
- });
|
|
|
-
|
|
|
- // Load operation stats
|
|
|
- Meteor.call('cron.getBoardOperationStats', (error, result) => {
|
|
|
- if (result) {
|
|
|
- instance.operationStats.set(result);
|
|
|
- }
|
|
|
- });
|
|
|
-
|
|
|
- // Load queue stats
|
|
|
- Meteor.call('cron.getQueueStats', (error, result) => {
|
|
|
- if (result) {
|
|
|
- instance.queueStats.set(result);
|
|
|
- }
|
|
|
- });
|
|
|
-
|
|
|
- // Load system resources
|
|
|
- Meteor.call('cron.getSystemResources', (error, result) => {
|
|
|
- if (result) {
|
|
|
- instance.systemResources.set(result);
|
|
|
- }
|
|
|
- });
|
|
|
-
|
|
|
- // Load board migration stats
|
|
|
- Meteor.call('cron.getBoardMigrationStats', (error, result) => {
|
|
|
- if (result) {
|
|
|
- instance.boardMigrationStats.set(result);
|
|
|
- }
|
|
|
- });
|
|
|
-}
|
|
|
-
|
|
|
-function pollMigrationProgress(instance) {
|
|
|
- const pollInterval = setInterval(() => {
|
|
|
- Meteor.call('cron.getMigrationProgress', (error, result) => {
|
|
|
- if (result) {
|
|
|
- migrationProgress.set(result.progress);
|
|
|
- migrationStatus.set(result.status);
|
|
|
- migrationCurrentStep.set(result.currentStep);
|
|
|
- migrationSteps.set(result.steps);
|
|
|
- isMigrating.set(result.isMigrating);
|
|
|
-
|
|
|
- // Stop polling if migration is complete
|
|
|
- if (!result.isMigrating && result.progress === 100) {
|
|
|
- clearInterval(pollInterval);
|
|
|
- }
|
|
|
- }
|
|
|
- });
|
|
|
- }, 1000);
|
|
|
-}
|
|
|
-
|
|
|
-// Template helpers for cronSettings
|
|
|
-Template.cronSettings.helpers({
|
|
|
- loading() {
|
|
|
- const instance = Template.instance();
|
|
|
- return instance.loading && instance.loading.get();
|
|
|
- },
|
|
|
- showMigrations() {
|
|
|
- const instance = Template.instance();
|
|
|
- return instance.showMigrations && instance.showMigrations.get();
|
|
|
- },
|
|
|
- showBoardOperations() {
|
|
|
- const instance = Template.instance();
|
|
|
- return instance.showBoardOperations && instance.showBoardOperations.get();
|
|
|
- },
|
|
|
- showJobs() {
|
|
|
- const instance = Template.instance();
|
|
|
- return instance.showJobs && instance.showJobs.get();
|
|
|
- },
|
|
|
- showAddJob() {
|
|
|
- const instance = Template.instance();
|
|
|
- return instance.showAddJob && instance.showAddJob.get();
|
|
|
- },
|
|
|
-});
|