123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404 |
- /**
- * Server-side Migration Runner
- * Handles actual execution of database migrations with progress tracking
- */
- import { Meteor } from 'meteor/meteor';
- import { Migrations } from 'meteor/percolate:migrations';
- import { ReactiveVar } from 'meteor/reactive-var';
- // Server-side reactive variables for migration progress
- export const serverMigrationProgress = new ReactiveVar(0);
- export const serverMigrationStatus = new ReactiveVar('');
- export const serverMigrationCurrentStep = new ReactiveVar('');
- export const serverMigrationSteps = new ReactiveVar([]);
- export const serverIsMigrating = new ReactiveVar(false);
- class ServerMigrationRunner {
- constructor() {
- this.migrationSteps = this.initializeMigrationSteps();
- this.currentStepIndex = 0;
- this.startTime = null;
- }
- /**
- * Initialize migration steps with their actual migration functions
- */
- initializeMigrationSteps() {
- return [
- {
- id: 'board-background-color',
- name: 'Board Background Colors',
- description: 'Setting up board background colors',
- weight: 1,
- completed: false,
- progress: 0,
- migrationFunction: this.runBoardBackgroundColorMigration
- },
- {
- id: 'add-cardcounterlist-allowed',
- name: 'Card Counter List Settings',
- description: 'Adding card counter list permissions',
- weight: 1,
- completed: false,
- progress: 0,
- migrationFunction: this.runCardCounterListMigration
- },
- {
- id: 'add-boardmemberlist-allowed',
- name: 'Board Member List Settings',
- description: 'Adding board member list permissions',
- weight: 1,
- completed: false,
- progress: 0,
- migrationFunction: this.runBoardMemberListMigration
- },
- {
- id: 'lowercase-board-permission',
- name: 'Board Permission Standardization',
- description: 'Converting board permissions to lowercase',
- weight: 1,
- completed: false,
- progress: 0,
- migrationFunction: this.runLowercaseBoardPermissionMigration
- },
- {
- id: 'change-attachments-type-for-non-images',
- name: 'Attachment Type Standardization',
- description: 'Updating attachment types for non-images',
- weight: 2,
- completed: false,
- progress: 0,
- migrationFunction: this.runAttachmentTypeMigration
- },
- {
- id: 'card-covers',
- name: 'Card Covers System',
- description: 'Setting up card cover functionality',
- weight: 2,
- completed: false,
- progress: 0,
- migrationFunction: this.runCardCoversMigration
- },
- {
- id: 'use-css-class-for-boards-colors',
- name: 'Board Color CSS Classes',
- description: 'Converting board colors to CSS classes',
- weight: 2,
- completed: false,
- progress: 0,
- migrationFunction: this.runBoardColorCSSMigration
- },
- {
- id: 'denormalize-star-number-per-board',
- name: 'Board Star Counts',
- description: 'Calculating star counts per board',
- weight: 3,
- completed: false,
- progress: 0,
- migrationFunction: this.runStarNumberMigration
- },
- {
- id: 'add-member-isactive-field',
- name: 'Member Activity Status',
- description: 'Adding member activity tracking',
- weight: 2,
- completed: false,
- progress: 0,
- migrationFunction: this.runMemberIsActiveMigration
- },
- {
- id: 'add-sort-checklists',
- name: 'Checklist Sorting',
- description: 'Adding sort order to checklists',
- weight: 2,
- completed: false,
- progress: 0,
- migrationFunction: this.runSortChecklistsMigration
- },
- {
- id: 'add-swimlanes',
- name: 'Swimlanes System',
- description: 'Setting up swimlanes functionality',
- weight: 4,
- completed: false,
- progress: 0,
- migrationFunction: this.runSwimlanesMigration
- },
- {
- id: 'add-views',
- name: 'Board Views',
- description: 'Adding board view options',
- weight: 2,
- completed: false,
- progress: 0,
- migrationFunction: this.runViewsMigration
- },
- {
- id: 'add-checklist-items',
- name: 'Checklist Items',
- description: 'Setting up checklist items system',
- weight: 3,
- completed: false,
- progress: 0,
- migrationFunction: this.runChecklistItemsMigration
- },
- {
- id: 'add-card-types',
- name: 'Card Types',
- description: 'Adding card type functionality',
- weight: 2,
- completed: false,
- progress: 0,
- migrationFunction: this.runCardTypesMigration
- },
- {
- id: 'add-custom-fields-to-cards',
- name: 'Custom Fields',
- description: 'Adding custom fields to cards',
- weight: 3,
- completed: false,
- progress: 0,
- migrationFunction: this.runCustomFieldsMigration
- },
- {
- id: 'migrate-attachments-collectionFS-to-ostrioFiles',
- name: 'Migrate Attachments to Meteor-Files',
- description: 'Migrating attachments from CollectionFS to Meteor-Files',
- weight: 8,
- completed: false,
- progress: 0,
- migrationFunction: this.runAttachmentMigration
- },
- {
- id: 'migrate-avatars-collectionFS-to-ostrioFiles',
- name: 'Migrate Avatars to Meteor-Files',
- description: 'Migrating avatars from CollectionFS to Meteor-Files',
- weight: 6,
- completed: false,
- progress: 0,
- migrationFunction: this.runAvatarMigration
- },
- {
- id: 'migrate-lists-to-per-swimlane',
- name: 'Migrate Lists to Per-Swimlane',
- description: 'Migrating lists to per-swimlane structure',
- weight: 5,
- completed: false,
- progress: 0,
- migrationFunction: this.runListsToPerSwimlaneMigration
- }
- ];
- }
- /**
- * Start migration process
- */
- async startMigration() {
- if (serverIsMigrating.get()) {
- return; // Already migrating
- }
- serverIsMigrating.set(true);
- serverMigrationSteps.set([...this.migrationSteps]);
- this.startTime = Date.now();
- try {
- for (let i = 0; i < this.migrationSteps.length; i++) {
- const step = this.migrationSteps[i];
- this.currentStepIndex = i;
- if (step.completed) {
- continue; // Skip already completed steps
- }
- serverMigrationCurrentStep.set(step.name);
- serverMigrationStatus.set(`Running: ${step.description}`);
- // Run the migration step
- await this.runMigrationStep(step);
- // Mark as completed
- step.completed = true;
- step.progress = 100;
- // Update progress
- this.updateProgress();
- // Allow other processes to run
- await new Promise(resolve => setTimeout(resolve, 100));
- }
- // Migration completed
- serverMigrationStatus.set('All migrations completed successfully!');
- serverMigrationProgress.set(100);
- serverMigrationCurrentStep.set('');
- // Clear status after delay
- setTimeout(() => {
- serverIsMigrating.set(false);
- serverMigrationStatus.set('');
- serverMigrationProgress.set(0);
- }, 3000);
- } catch (error) {
- console.error('Migration failed:', error);
- serverMigrationStatus.set(`Migration failed: ${error.message}`);
- serverIsMigrating.set(false);
- }
- }
- /**
- * Run a single migration step
- */
- async runMigrationStep(step) {
- try {
- // Update progress during migration
- const progressSteps = 10;
- for (let i = 0; i <= progressSteps; i++) {
- step.progress = (i / progressSteps) * 100;
- this.updateProgress();
-
- // Run actual migration function
- if (i === progressSteps) {
- await step.migrationFunction.call(this);
- }
-
- // Allow other processes to run
- await new Promise(resolve => setTimeout(resolve, 50));
- }
- } catch (error) {
- console.error(`Migration step ${step.name} failed:`, error);
- throw error;
- }
- }
- /**
- * Update progress variables
- */
- updateProgress() {
- const totalWeight = this.migrationSteps.reduce((total, step) => total + step.weight, 0);
- const completedWeight = this.migrationSteps.reduce((total, step) => {
- return total + (step.completed ? step.weight : step.progress * step.weight / 100);
- }, 0);
- const progress = Math.round((completedWeight / totalWeight) * 100);
-
- serverMigrationProgress.set(progress);
- serverMigrationSteps.set([...this.migrationSteps]);
- }
- // Individual migration functions
- async runBoardBackgroundColorMigration() {
- // Implementation for board background color migration
- console.log('Running board background color migration');
- }
- async runCardCounterListMigration() {
- // Implementation for card counter list migration
- console.log('Running card counter list migration');
- }
- async runBoardMemberListMigration() {
- // Implementation for board member list migration
- console.log('Running board member list migration');
- }
- async runLowercaseBoardPermissionMigration() {
- // Implementation for lowercase board permission migration
- console.log('Running lowercase board permission migration');
- }
- async runAttachmentTypeMigration() {
- // Implementation for attachment type migration
- console.log('Running attachment type migration');
- }
- async runCardCoversMigration() {
- // Implementation for card covers migration
- console.log('Running card covers migration');
- }
- async runBoardColorCSSMigration() {
- // Implementation for board color CSS migration
- console.log('Running board color CSS migration');
- }
- async runStarNumberMigration() {
- // Implementation for star number migration
- console.log('Running star number migration');
- }
- async runMemberIsActiveMigration() {
- // Implementation for member is active migration
- console.log('Running member is active migration');
- }
- async runSortChecklistsMigration() {
- // Implementation for sort checklists migration
- console.log('Running sort checklists migration');
- }
- async runSwimlanesMigration() {
- // Implementation for swimlanes migration
- console.log('Running swimlanes migration');
- }
- async runViewsMigration() {
- // Implementation for views migration
- console.log('Running views migration');
- }
- async runChecklistItemsMigration() {
- // Implementation for checklist items migration
- console.log('Running checklist items migration');
- }
- async runCardTypesMigration() {
- // Implementation for card types migration
- console.log('Running card types migration');
- }
- async runCustomFieldsMigration() {
- // Implementation for custom fields migration
- console.log('Running custom fields migration');
- }
- async runAttachmentMigration() {
- // Implementation for attachment migration from CollectionFS to Meteor-Files
- console.log('Running attachment migration from CollectionFS to Meteor-Files');
- }
- async runAvatarMigration() {
- // Implementation for avatar migration from CollectionFS to Meteor-Files
- console.log('Running avatar migration from CollectionFS to Meteor-Files');
- }
- async runListsToPerSwimlaneMigration() {
- // Implementation for lists to per-swimlane migration
- console.log('Running lists to per-swimlane migration');
- }
- }
- // Export singleton instance
- export const serverMigrationRunner = new ServerMigrationRunner();
- // Meteor methods for client-server communication
- Meteor.methods({
- 'migration.start'() {
- if (!this.userId) {
- throw new Meteor.Error('not-authorized');
- }
-
- return serverMigrationRunner.startMigration();
- },
-
- 'migration.getProgress'() {
- return {
- progress: serverMigrationProgress.get(),
- status: serverMigrationStatus.get(),
- currentStep: serverMigrationCurrentStep.get(),
- steps: serverMigrationSteps.get(),
- isMigrating: serverIsMigrating.get()
- };
- }
- });
|