Reverted New UI Design of WeKan v8.29 and added more fixes and performance improvements.

Thanks to xet7 !
This commit is contained in:
Lauri Ojansivu 2026-02-08 00:48:39 +02:00
parent d152d8fc1b
commit 1b8b8d2eef
196 changed files with 17659 additions and 10028 deletions

View file

@ -2,15 +2,23 @@ import { ReactiveCache } from '/imports/reactiveCache';
import { TAPi18n } from '/imports/i18n';
import { ALLOWED_WAIT_SPINNERS } from '/config/const';
import LockoutSettings from '/models/lockoutSettings';
import {
cronMigrationProgress,
cronMigrationStatus,
cronMigrationCurrentStep,
cronMigrationSteps,
cronIsMigrating,
import {
cronMigrationProgress,
cronMigrationStatus,
cronMigrationCurrentStep,
cronMigrationSteps,
cronIsMigrating,
cronJobs,
cronMigrationCurrentStepNum,
cronMigrationTotalSteps
cronMigrationTotalSteps,
cronMigrationCurrentAction,
cronMigrationJobProgress,
cronMigrationJobStepNum,
cronMigrationJobTotalSteps,
cronMigrationEtaSeconds,
cronMigrationElapsedSeconds,
cronMigrationCurrentNumber,
cronMigrationCurrentName
} from '/imports/cronMigrationClient';
@ -39,7 +47,7 @@ BlazeComponent.extendComponent({
Meteor.subscribe('accessibilitySettings');
Meteor.subscribe('globalwebhooks');
Meteor.subscribe('lockoutSettings');
// Poll for migration errors
this.errorPollInterval = Meteor.setInterval(() => {
if (this.cronSettings.get()) {
@ -62,7 +70,7 @@ BlazeComponent.extendComponent({
setError(error) {
this.error.set(error);
},
// Template helpers moved to BlazeComponent - using different names to avoid conflicts
isGeneralSetting() {
return this.generalSetting && this.generalSetting.get();
@ -102,41 +110,41 @@ BlazeComponent.extendComponent({
filesystemPath() {
return process.env.WRITABLE_PATH || '/data';
},
attachmentsPath() {
const writablePath = process.env.WRITABLE_PATH || '/data';
return `${writablePath}/attachments`;
},
avatarsPath() {
const writablePath = process.env.WRITABLE_PATH || '/data';
return `${writablePath}/avatars`;
},
gridfsEnabled() {
return process.env.GRIDFS_ENABLED === 'true';
},
s3Enabled() {
return process.env.S3_ENABLED === 'true';
},
s3Endpoint() {
return process.env.S3_ENDPOINT || '';
},
s3Bucket() {
return process.env.S3_BUCKET || '';
},
s3Region() {
return process.env.S3_REGION || '';
},
s3SslEnabled() {
return process.env.S3_SSL_ENABLED === 'true';
},
s3Port() {
return process.env.S3_PORT || 443;
},
@ -145,23 +153,23 @@ BlazeComponent.extendComponent({
migrationStatus() {
return cronMigrationStatus.get() || TAPi18n.__('idle');
},
migrationProgress() {
return cronMigrationProgress.get() || 0;
},
migrationCurrentStep() {
return cronMigrationCurrentStep.get() || '';
},
isMigrating() {
return cronIsMigrating.get() || false;
},
migrationSteps() {
return cronMigrationSteps.get() || [];
},
migrationStepsWithIndex() {
const steps = cronMigrationSteps.get() || [];
return steps.map((step, idx) => ({
@ -169,11 +177,15 @@ BlazeComponent.extendComponent({
index: idx + 1
}));
},
cronJobs() {
return cronJobs.get() || [];
},
isCronJobPaused(status) {
return status === 'paused';
},
migrationCurrentStepNum() {
return cronMigrationCurrentStepNum.get() || 0;
},
@ -182,6 +194,52 @@ BlazeComponent.extendComponent({
return cronMigrationTotalSteps.get() || 0;
},
migrationCurrentAction() {
return cronMigrationCurrentAction.get() || '';
},
migrationJobProgress() {
return cronMigrationJobProgress.get() || 0;
},
migrationJobStepNum() {
return cronMigrationJobStepNum.get() || 0;
},
migrationJobTotalSteps() {
return cronMigrationJobTotalSteps.get() || 0;
},
migrationEtaSeconds() {
return cronMigrationEtaSeconds.get();
},
migrationElapsedSeconds() {
return cronMigrationElapsedSeconds.get();
},
migrationNumber() {
return cronMigrationCurrentNumber.get();
},
migrationName() {
return cronMigrationCurrentName.get() || '';
},
migrationStatusLine() {
const number = cronMigrationCurrentNumber.get();
const name = cronMigrationCurrentName.get();
if (number && name) {
return `${number} - ${name}`;
}
return this.migrationStatus();
},
isUpdatingMigrationDropdown() {
const status = this.migrationStatus();
return status && status.startsWith('Updating Select Migration dropdown menu');
},
migrationErrors() {
return this.migrationErrorsList ? this.migrationErrorsList.get() : [];
},
@ -196,6 +254,19 @@ BlazeComponent.extendComponent({
return moment(date).format('YYYY-MM-DD HH:mm:ss');
},
formatDurationSeconds(seconds) {
if (seconds === null || seconds === undefined) return '';
const total = Math.max(0, Math.floor(seconds));
const hrs = Math.floor(total / 3600);
const mins = Math.floor((total % 3600) / 60);
const secs = total % 60;
const parts = [];
if (hrs > 0) parts.push(String(hrs).padStart(2, '0'));
parts.push(String(mins).padStart(2, '0'));
parts.push(String(secs).padStart(2, '0'));
return parts.join(':');
},
setLoading(w) {
this.loading.set(w);
},
@ -240,8 +311,14 @@ BlazeComponent.extendComponent({
'click button.js-start-migration'(event) {
event.preventDefault();
this.setLoading(true);
cronIsMigrating.set(true);
cronMigrationStatus.set(TAPi18n.__('migration-starting'));
cronMigrationCurrentAction.set('');
cronMigrationJobProgress.set(0);
cronMigrationJobStepNum.set(0);
cronMigrationJobTotalSteps.set(0);
const selectedIndex = parseInt($('.js-migration-select').val() || '0', 10);
if (selectedIndex === 0) {
// Run all migrations
Meteor.call('cron.startAllMigrations', (error, result) => {
@ -258,6 +335,10 @@ BlazeComponent.extendComponent({
this.setLoading(false);
if (error) {
alert(TAPi18n.__('migration-start-failed') + ': ' + error.reason);
} else if (result && result.skipped) {
cronIsMigrating.set(false);
cronMigrationStatus.set(TAPi18n.__('migration-not-needed'));
alert(TAPi18n.__('migration-not-needed'));
} else {
alert(TAPi18n.__('migration-started'));
}
@ -265,9 +346,52 @@ BlazeComponent.extendComponent({
}
},
'click button.js-start-all-migrations'(event) {
event.preventDefault();
this.setLoading(true);
Meteor.call('cron.startAllMigrations', (error) => {
this.setLoading(false);
if (error) {
alert(TAPi18n.__('migration-start-failed') + ': ' + error.reason);
} else {
alert(TAPi18n.__('migration-started'));
}
});
},
'click button.js-pause-all-migrations'(event) {
event.preventDefault();
this.setLoading(true);
Meteor.call('cron.pauseAllMigrations', (error) => {
this.setLoading(false);
if (error) {
alert(TAPi18n.__('migration-pause-failed') + ': ' + error.reason);
} else {
alert(TAPi18n.__('migration-paused'));
}
});
},
'click button.js-stop-all-migrations'(event) {
event.preventDefault();
if (confirm(TAPi18n.__('migration-stop-confirm'))) {
this.setLoading(true);
Meteor.call('cron.stopAllMigrations', (error) => {
this.setLoading(false);
if (error) {
alert(TAPi18n.__('migration-stop-failed') + ': ' + error.reason);
} else {
alert(TAPi18n.__('migration-stopped'));
}
});
}
},
'click button.js-pause-migration'(event) {
event.preventDefault();
this.setLoading(true);
cronIsMigrating.set(false);
cronMigrationStatus.set(TAPi18n.__('migration-pausing'));
Meteor.call('cron.pauseAllMigrations', (error, result) => {
this.setLoading(false);
if (error) {
@ -282,6 +406,12 @@ BlazeComponent.extendComponent({
event.preventDefault();
if (confirm(TAPi18n.__('migration-stop-confirm'))) {
this.setLoading(true);
cronIsMigrating.set(false);
cronMigrationStatus.set(TAPi18n.__('migration-stopping'));
cronMigrationCurrentAction.set('');
cronMigrationJobProgress.set(0);
cronMigrationJobStepNum.set(0);
cronMigrationJobTotalSteps.set(0);
Meteor.call('cron.stopAllMigrations', (error, result) => {
this.setLoading(false);
if (error) {
@ -293,29 +423,25 @@ BlazeComponent.extendComponent({
}
},
'click button.js-schedule-board-cleanup'(event) {
'click button.js-start-job'(event) {
event.preventDefault();
// Placeholder - board cleanup scheduling
alert(TAPi18n.__('board-cleanup-scheduled'));
},
'click button.js-schedule-board-archive'(event) {
event.preventDefault();
// Placeholder - board archive scheduling
alert(TAPi18n.__('board-archive-scheduled'));
},
'click button.js-schedule-board-backup'(event) {
event.preventDefault();
// Placeholder - board backup scheduling
alert(TAPi18n.__('board-backup-scheduled'));
const jobName = $(event.target).data('job-name');
this.setLoading(true);
Meteor.call('cron.startJob', jobName, (error) => {
this.setLoading(false);
if (error) {
alert(TAPi18n.__('cron-job-start-failed') + ': ' + error.reason);
} else {
alert(TAPi18n.__('cron-job-started'));
}
});
},
'click button.js-pause-job'(event) {
event.preventDefault();
const jobId = $(event.target).data('job-id');
const jobName = $(event.target).data('job-name');
this.setLoading(true);
Meteor.call('cron.pauseJob', jobId, (error, result) => {
Meteor.call('cron.pauseJob', jobName, (error) => {
this.setLoading(false);
if (error) {
alert(TAPi18n.__('cron-job-pause-failed') + ': ' + error.reason);
@ -325,12 +451,26 @@ BlazeComponent.extendComponent({
});
},
'click button.js-resume-job'(event) {
event.preventDefault();
const jobName = $(event.target).data('job-name');
this.setLoading(true);
Meteor.call('cron.resumeJob', jobName, (error) => {
this.setLoading(false);
if (error) {
alert(TAPi18n.__('cron-job-resume-failed') + ': ' + error.reason);
} else {
alert(TAPi18n.__('cron-job-resumed'));
}
});
},
'click button.js-delete-job'(event) {
event.preventDefault();
const jobId = $(event.target).data('job-id');
const jobName = $(event.target).data('job-name');
if (confirm(TAPi18n.__('cron-job-delete-confirm'))) {
this.setLoading(true);
Meteor.call('cron.removeJob', jobId, (error, result) => {
Meteor.call('cron.removeJob', jobName, (error) => {
this.setLoading(false);
if (error) {
alert(TAPi18n.__('cron-job-delete-failed') + ': ' + error.reason);
@ -429,7 +569,7 @@ BlazeComponent.extendComponent({
$('.side-menu li.active').removeClass('active');
target.parent().addClass('active');
const targetID = target.data('id');
// Reset all settings to false
this.forgotPasswordSetting.set(false);
this.generalSetting.set(false);
@ -442,7 +582,7 @@ BlazeComponent.extendComponent({
this.webhookSetting.set(false);
this.attachmentSettings.set(false);
this.cronSettings.set(false);
// Set the selected setting to true
if (targetID === 'registration-setting') {
this.generalSetting.set(true);
@ -847,7 +987,7 @@ BlazeComponent.extendComponent({
const content = $('#admin-accessibility-content')
.val()
.trim();
try {
AccessibilitySettings.update(AccessibilitySettings.findOne()._id, {
$set: {