@cyberismo/data-handler 0.0.20 → 0.0.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/command-handler.js +13 -24
- package/dist/command-handler.js.map +1 -1
- package/dist/command-manager.d.ts +21 -6
- package/dist/command-manager.js +34 -32
- package/dist/command-manager.js.map +1 -1
- package/dist/commands/calculate.js +101 -46
- package/dist/commands/calculate.js.map +1 -1
- package/dist/commands/create.js +420 -320
- package/dist/commands/create.js.map +1 -1
- package/dist/commands/edit.js +117 -68
- package/dist/commands/edit.js.map +1 -1
- package/dist/commands/export.js +301 -252
- package/dist/commands/export.js.map +1 -1
- package/dist/commands/fetch.js +205 -156
- package/dist/commands/fetch.js.map +1 -1
- package/dist/commands/import.js +189 -134
- package/dist/commands/import.js.map +1 -1
- package/dist/commands/migrate.js +91 -45
- package/dist/commands/migrate.js.map +1 -1
- package/dist/commands/move.js +347 -267
- package/dist/commands/move.js.map +1 -1
- package/dist/commands/remove.d.ts +1 -0
- package/dist/commands/remove.js +202 -135
- package/dist/commands/remove.js.map +1 -1
- package/dist/commands/rename.js +233 -187
- package/dist/commands/rename.js.map +1 -1
- package/dist/commands/show.d.ts +8 -8
- package/dist/commands/show.js +477 -372
- package/dist/commands/show.js.map +1 -1
- package/dist/commands/transition.js +119 -73
- package/dist/commands/transition.js.map +1 -1
- package/dist/commands/update.js +8 -3
- package/dist/commands/update.js.map +1 -1
- package/dist/commands/validate.js +1 -1
- package/dist/commands/validate.js.map +1 -1
- package/dist/containers/project/calculation-engine.js +0 -1
- package/dist/containers/project/calculation-engine.js.map +1 -1
- package/dist/containers/project/card-cache.js +1 -1
- package/dist/containers/project/card-cache.js.map +1 -1
- package/dist/containers/project.d.ts +16 -0
- package/dist/containers/project.js +59 -1
- package/dist/containers/project.js.map +1 -1
- package/dist/containers/template.js +1 -1
- package/dist/containers/template.js.map +1 -1
- package/dist/interfaces/command-options.d.ts +1 -0
- package/dist/interfaces/resource-interfaces.d.ts +5 -12
- package/dist/interfaces/resource-interfaces.js.map +1 -1
- package/dist/macros/base-macro.js +1 -1
- package/dist/macros/base-macro.js.map +1 -1
- package/dist/macros/graph/index.js +3 -1
- package/dist/macros/graph/index.js.map +1 -1
- package/dist/macros/include/index.js +16 -1
- package/dist/macros/include/index.js.map +1 -1
- package/dist/macros/include/types.d.ts +15 -12
- package/dist/macros/index.js +4 -1
- package/dist/macros/index.js.map +1 -1
- package/dist/macros/report/index.js +1 -1
- package/dist/macros/report/index.js.map +1 -1
- package/dist/module-manager.js +5 -3
- package/dist/module-manager.js.map +1 -1
- package/dist/project-settings.js +2 -2
- package/dist/project-settings.js.map +1 -1
- package/dist/resources/card-type-resource.js +1 -1
- package/dist/resources/card-type-resource.js.map +1 -1
- package/dist/resources/create-defaults.js +0 -1
- package/dist/resources/create-defaults.js.map +1 -1
- package/dist/resources/field-type-resource.js +2 -5
- package/dist/resources/field-type-resource.js.map +1 -1
- package/dist/resources/file-resource.js +4 -1
- package/dist/resources/file-resource.js.map +1 -1
- package/dist/resources/folder-resource.d.ts +1 -1
- package/dist/resources/folder-resource.js +4 -1
- package/dist/resources/folder-resource.js.map +1 -1
- package/dist/resources/graph-model-resource.d.ts +1 -8
- package/dist/resources/graph-model-resource.js +0 -14
- package/dist/resources/graph-model-resource.js.map +1 -1
- package/dist/resources/graph-view-resource.d.ts +1 -8
- package/dist/resources/graph-view-resource.js +0 -14
- package/dist/resources/graph-view-resource.js.map +1 -1
- package/dist/resources/link-type-resource.js +1 -1
- package/dist/resources/link-type-resource.js.map +1 -1
- package/dist/resources/report-resource.d.ts +1 -8
- package/dist/resources/report-resource.js +0 -14
- package/dist/resources/report-resource.js.map +1 -1
- package/dist/resources/resource-object.d.ts +11 -1
- package/dist/resources/resource-object.js +19 -2
- package/dist/resources/resource-object.js.map +1 -1
- package/dist/resources/template-resource.d.ts +1 -9
- package/dist/resources/template-resource.js +0 -15
- package/dist/resources/template-resource.js.map +1 -1
- package/dist/resources/workflow-resource.d.ts +6 -0
- package/dist/resources/workflow-resource.js +29 -13
- package/dist/resources/workflow-resource.js.map +1 -1
- package/dist/utils/card-utils.js +1 -1
- package/dist/utils/card-utils.js.map +1 -1
- package/dist/utils/commit-context.d.ts +23 -0
- package/dist/utils/commit-context.js +30 -0
- package/dist/utils/commit-context.js.map +1 -0
- package/dist/utils/csv.d.ts +8 -0
- package/dist/utils/csv.js +11 -0
- package/dist/utils/csv.js.map +1 -1
- package/dist/utils/file-utils.js +3 -1
- package/dist/utils/file-utils.js.map +1 -1
- package/dist/utils/git-manager.d.ts +29 -0
- package/dist/utils/git-manager.js +76 -0
- package/dist/utils/git-manager.js.map +1 -0
- package/dist/utils/handlebars-helpers.d.ts +22 -0
- package/dist/utils/handlebars-helpers.js +78 -0
- package/dist/utils/handlebars-helpers.js.map +1 -0
- package/dist/utils/json.d.ts +17 -10
- package/dist/utils/json.js +27 -14
- package/dist/utils/json.js.map +1 -1
- package/dist/utils/log-utils.d.ts +7 -2
- package/dist/utils/log-utils.js +28 -3
- package/dist/utils/log-utils.js.map +1 -1
- package/dist/utils/report.d.ts +0 -19
- package/dist/utils/report.js +4 -63
- package/dist/utils/report.js.map +1 -1
- package/dist/utils/rw-lock.d.ts +71 -0
- package/dist/utils/rw-lock.js +220 -0
- package/dist/utils/rw-lock.js.map +1 -0
- package/dist/utils/user-preferences.js +3 -3
- package/dist/utils/user-preferences.js.map +1 -1
- package/package.json +10 -10
- package/src/command-handler.ts +14 -22
- package/src/command-manager.ts +43 -37
- package/src/commands/calculate.ts +8 -1
- package/src/commands/create.ts +39 -6
- package/src/commands/edit.ts +3 -0
- package/src/commands/export.ts +8 -2
- package/src/commands/fetch.ts +3 -0
- package/src/commands/import.ts +5 -0
- package/src/commands/migrate.ts +2 -0
- package/src/commands/move.ts +34 -0
- package/src/commands/remove.ts +24 -2
- package/src/commands/rename.ts +2 -0
- package/src/commands/show.ts +63 -34
- package/src/commands/transition.ts +2 -0
- package/src/commands/update.ts +9 -3
- package/src/commands/validate.ts +1 -1
- package/src/containers/project/calculation-engine.ts +0 -1
- package/src/containers/project/card-cache.ts +1 -0
- package/src/containers/project.ts +75 -1
- package/src/containers/template.ts +1 -1
- package/src/interfaces/command-options.ts +1 -0
- package/src/interfaces/resource-interfaces.ts +5 -12
- package/src/macros/base-macro.ts +1 -1
- package/src/macros/graph/index.ts +3 -0
- package/src/macros/include/index.ts +19 -1
- package/src/macros/include/types.ts +15 -12
- package/src/macros/index.ts +4 -1
- package/src/macros/report/index.ts +1 -0
- package/src/module-manager.ts +5 -2
- package/src/project-settings.ts +2 -1
- package/src/resources/card-type-resource.ts +1 -1
- package/src/resources/create-defaults.ts +0 -1
- package/src/resources/field-type-resource.ts +2 -4
- package/src/resources/file-resource.ts +3 -1
- package/src/resources/folder-resource.ts +7 -2
- package/src/resources/graph-model-resource.ts +1 -25
- package/src/resources/graph-view-resource.ts +1 -25
- package/src/resources/link-type-resource.ts +1 -1
- package/src/resources/report-resource.ts +1 -25
- package/src/resources/resource-object.ts +22 -1
- package/src/resources/template-resource.ts +0 -23
- package/src/resources/workflow-resource.ts +45 -16
- package/src/utils/card-utils.ts +1 -1
- package/src/utils/commit-context.ts +45 -0
- package/src/utils/csv.ts +12 -0
- package/src/utils/file-utils.ts +3 -1
- package/src/utils/git-manager.ts +87 -0
- package/src/utils/handlebars-helpers.ts +95 -0
- package/src/utils/json.ts +29 -15
- package/src/utils/log-utils.ts +33 -4
- package/src/utils/report.ts +8 -74
- package/src/utils/rw-lock.ts +279 -0
- package/src/utils/user-preferences.ts +3 -0
package/dist/commands/move.js
CHANGED
|
@@ -10,292 +10,372 @@
|
|
|
10
10
|
details. You should have received a copy of the GNU Affero General Public
|
|
11
11
|
License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
12
12
|
*/
|
|
13
|
+
var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
|
|
14
|
+
var useValue = arguments.length > 2;
|
|
15
|
+
for (var i = 0; i < initializers.length; i++) {
|
|
16
|
+
value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
|
|
17
|
+
}
|
|
18
|
+
return useValue ? value : void 0;
|
|
19
|
+
};
|
|
20
|
+
var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
|
|
21
|
+
function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
|
|
22
|
+
var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
|
|
23
|
+
var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
|
|
24
|
+
var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
|
|
25
|
+
var _, done = false;
|
|
26
|
+
for (var i = decorators.length - 1; i >= 0; i--) {
|
|
27
|
+
var context = {};
|
|
28
|
+
for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
|
|
29
|
+
for (var p in contextIn.access) context.access[p] = contextIn.access[p];
|
|
30
|
+
context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
|
|
31
|
+
var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
|
|
32
|
+
if (kind === "accessor") {
|
|
33
|
+
if (result === void 0) continue;
|
|
34
|
+
if (result === null || typeof result !== "object") throw new TypeError("Object expected");
|
|
35
|
+
if (_ = accept(result.get)) descriptor.get = _;
|
|
36
|
+
if (_ = accept(result.set)) descriptor.set = _;
|
|
37
|
+
if (_ = accept(result.init)) initializers.unshift(_);
|
|
38
|
+
}
|
|
39
|
+
else if (_ = accept(result)) {
|
|
40
|
+
if (kind === "field") initializers.unshift(_);
|
|
41
|
+
else descriptor[key] = _;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (target) Object.defineProperty(target, contextIn.name, descriptor);
|
|
45
|
+
done = true;
|
|
46
|
+
};
|
|
13
47
|
// node
|
|
14
48
|
import { join } from 'node:path';
|
|
15
49
|
import { ActionGuard } from '../permissions/action-guard.js';
|
|
16
50
|
import { copyDir, deleteDir } from '../utils/file-utils.js';
|
|
51
|
+
import { write } from '../utils/rw-lock.js';
|
|
17
52
|
import { EMPTY_RANK, FIRST_RANK, getRankAfter, getRankBetween, rebalanceRanks, sortItems, } from '../utils/lexorank.js';
|
|
18
53
|
import { cardPathParts, isModuleCard, isTemplateCard, } from '../utils/card-utils.js';
|
|
19
54
|
import { ROOT } from '../utils/constants.js';
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
55
|
+
let Move = (() => {
|
|
56
|
+
let _instanceExtraInitializers = [];
|
|
57
|
+
let _moveCard_decorators;
|
|
58
|
+
let _rankByIndex_decorators;
|
|
59
|
+
let _rankCard_decorators;
|
|
60
|
+
let _rankFirst_decorators;
|
|
61
|
+
let _rebalanceChildren_decorators;
|
|
62
|
+
let _rebalanceProject_decorators;
|
|
63
|
+
return class Move {
|
|
64
|
+
static {
|
|
65
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
|
|
66
|
+
_moveCard_decorators = [write((source, destination) => `Move card ${source} to ${destination}`)];
|
|
67
|
+
_rankByIndex_decorators = [write((cardKey) => `Reorder card ${cardKey}`)];
|
|
68
|
+
_rankCard_decorators = [write((cardKey) => `Reorder card ${cardKey}`)];
|
|
69
|
+
_rankFirst_decorators = [write((cardKey) => `Rank card ${cardKey} first`)];
|
|
70
|
+
_rebalanceChildren_decorators = [write((parentCardKey) => `Rebalance children of ${parentCardKey}`)];
|
|
71
|
+
_rebalanceProject_decorators = [write(() => 'Rebalance project')];
|
|
72
|
+
__esDecorate(this, null, _moveCard_decorators, { kind: "method", name: "moveCard", static: false, private: false, access: { has: obj => "moveCard" in obj, get: obj => obj.moveCard }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
73
|
+
__esDecorate(this, null, _rankByIndex_decorators, { kind: "method", name: "rankByIndex", static: false, private: false, access: { has: obj => "rankByIndex" in obj, get: obj => obj.rankByIndex }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
74
|
+
__esDecorate(this, null, _rankCard_decorators, { kind: "method", name: "rankCard", static: false, private: false, access: { has: obj => "rankCard" in obj, get: obj => obj.rankCard }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
75
|
+
__esDecorate(this, null, _rankFirst_decorators, { kind: "method", name: "rankFirst", static: false, private: false, access: { has: obj => "rankFirst" in obj, get: obj => obj.rankFirst }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
76
|
+
__esDecorate(this, null, _rebalanceChildren_decorators, { kind: "method", name: "rebalanceChildren", static: false, private: false, access: { has: obj => "rebalanceChildren" in obj, get: obj => obj.rebalanceChildren }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
77
|
+
__esDecorate(this, null, _rebalanceProject_decorators, { kind: "method", name: "rebalanceProject", static: false, private: false, access: { has: obj => "rebalanceProject" in obj, get: obj => obj.rebalanceProject }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
78
|
+
if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
79
|
+
}
|
|
80
|
+
project = __runInitializers(this, _instanceExtraInitializers);
|
|
81
|
+
constructor(project) {
|
|
82
|
+
this.project = project;
|
|
83
|
+
}
|
|
84
|
+
// Returns children of a parent card or root cards
|
|
85
|
+
getSiblings(card) {
|
|
86
|
+
const parentCardKey = card.parent || ROOT;
|
|
87
|
+
// since we don't know if 'root' is templateRoot or cardRoot, we need to check the card
|
|
88
|
+
if (parentCardKey === ROOT) {
|
|
89
|
+
if (isTemplateCard(card)) {
|
|
90
|
+
if (isModuleCard(card)) {
|
|
91
|
+
throw new Error(`Cannot rank module cards`);
|
|
92
|
+
}
|
|
93
|
+
const { template } = cardPathParts(this.project.projectPrefix, card.path);
|
|
94
|
+
return this.project.templateCards(template);
|
|
33
95
|
}
|
|
34
|
-
const { template } = cardPathParts(this.project.projectPrefix, card.path);
|
|
35
|
-
return this.project.templateCards(template);
|
|
36
96
|
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
return this.project.cardKeysToCards(parentCard.children);
|
|
42
|
-
}
|
|
43
|
-
return this.project
|
|
44
|
-
.showProjectCards()
|
|
45
|
-
.filter((item) => item.parent === 'root' || item.parent === '');
|
|
46
|
-
}
|
|
47
|
-
// Rebalances cards
|
|
48
|
-
async rebalanceCards(cards) {
|
|
49
|
-
const ranks = rebalanceRanks(cards.length);
|
|
50
|
-
cards = sortItems(cards, (item) => item.metadata?.rank || 'z');
|
|
51
|
-
for (let i = 0; i < cards.length; i++) {
|
|
52
|
-
const card = cards[i];
|
|
53
|
-
await this.project.updateCardMetadataKey(card.key, 'rank', ranks[i]);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
// Rebalances the project recursively.
|
|
57
|
-
async rebalanceProjectRecursively(cards) {
|
|
58
|
-
const ranks = rebalanceRanks(cards.length);
|
|
59
|
-
cards = sortItems(cards, (item) => item.metadata?.rank || 'z');
|
|
60
|
-
for (let i = 0; i < cards.length; i++) {
|
|
61
|
-
const card = cards[i];
|
|
62
|
-
await this.project.updateCardMetadataKey(card.key, 'rank', ranks[i]);
|
|
63
|
-
if (card.children && card.children.length > 0) {
|
|
64
|
-
await this.rebalanceProjectRecursively(this.project.cardKeysToCards(card.children));
|
|
97
|
+
let parentCard;
|
|
98
|
+
if (parentCardKey !== ROOT) {
|
|
99
|
+
parentCard = this.project.findCard(parentCardKey);
|
|
100
|
+
return this.project.cardKeysToCards(parentCard.children);
|
|
65
101
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
if (source === destination) {
|
|
78
|
-
throw new Error(`Card cannot be moved to itself`);
|
|
79
|
-
}
|
|
80
|
-
const movingToRoot = destination === ROOT;
|
|
81
|
-
const sourceCard = this.project.findCard(source);
|
|
82
|
-
const destinationCard = !movingToRoot
|
|
83
|
-
? this.project.findCard(destination)
|
|
84
|
-
: undefined;
|
|
85
|
-
// Prevent moving card to inside its descendants
|
|
86
|
-
if (destinationCard) {
|
|
87
|
-
const { parents } = cardPathParts(this.project.projectPrefix, destinationCard.path);
|
|
88
|
-
if (parents.includes(source)) {
|
|
89
|
-
throw new Error(`Card cannot be moved to inside itself`);
|
|
102
|
+
return this.project
|
|
103
|
+
.showProjectCards()
|
|
104
|
+
.filter((item) => item.parent === 'root' || item.parent === '');
|
|
105
|
+
}
|
|
106
|
+
// Rebalances cards
|
|
107
|
+
async rebalanceCards(cards) {
|
|
108
|
+
const ranks = rebalanceRanks(cards.length);
|
|
109
|
+
cards = sortItems(cards, (item) => item.metadata?.rank || 'z');
|
|
110
|
+
for (let i = 0; i < cards.length; i++) {
|
|
111
|
+
const card = cards[i];
|
|
112
|
+
await this.project.updateCardMetadataKey(card.key, 'rank', ranks[i]);
|
|
90
113
|
}
|
|
91
114
|
}
|
|
92
|
-
//
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
115
|
+
// Rebalances the project recursively.
|
|
116
|
+
async rebalanceProjectRecursively(cards) {
|
|
117
|
+
const ranks = rebalanceRanks(cards.length);
|
|
118
|
+
cards = sortItems(cards, (item) => item.metadata?.rank || 'z');
|
|
119
|
+
for (let i = 0; i < cards.length; i++) {
|
|
120
|
+
const card = cards[i];
|
|
121
|
+
await this.project.updateCardMetadataKey(card.key, 'rank', ranks[i]);
|
|
122
|
+
if (card.children && card.children.length > 0) {
|
|
123
|
+
await this.rebalanceProjectRecursively(this.project.cardKeysToCards(card.children));
|
|
124
|
+
}
|
|
101
125
|
}
|
|
102
126
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
throw new Error(`Cards cannot be moved from project to template or vice versa`);
|
|
127
|
+
/**
|
|
128
|
+
* Moves card from 'destination' to 'source'.
|
|
129
|
+
* @param source source card to move
|
|
130
|
+
* @param destination destination card where source card will be moved to; or to root
|
|
131
|
+
*/
|
|
132
|
+
async moveCard(source, destination) {
|
|
133
|
+
if (source === ROOT) {
|
|
134
|
+
throw new Error('Cannot move "root"');
|
|
112
135
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
let children;
|
|
127
|
-
if (!movingToRoot) {
|
|
128
|
-
const parent = this.project.findCard(destination);
|
|
129
|
-
children = this.project.cardKeysToCards(parent.children);
|
|
130
|
-
}
|
|
131
|
-
else {
|
|
132
|
-
children = this.project.showProjectCards();
|
|
133
|
-
}
|
|
134
|
-
if (!children) {
|
|
135
|
-
throw new Error(`Children not found from card ${destination}`);
|
|
136
|
-
}
|
|
137
|
-
children = sortItems(children, (item) => item?.metadata?.rank || '1|z');
|
|
138
|
-
const lastChild = children[children.length - 1];
|
|
139
|
-
const rank = lastChild && lastChild.metadata
|
|
140
|
-
? getRankAfter(lastChild.metadata.rank)
|
|
141
|
-
: FIRST_RANK;
|
|
142
|
-
// First do the file operations, then update metadata
|
|
143
|
-
await copyDir(sourceCard.path, destinationPath);
|
|
144
|
-
await deleteDir(sourceCard.path);
|
|
145
|
-
// Update card with new path, parent, and rank
|
|
146
|
-
sourceCard.path = destinationPath;
|
|
147
|
-
sourceCard.parent = movingToRoot ? ROOT : destination;
|
|
148
|
-
if (sourceCard.metadata) {
|
|
149
|
-
sourceCard.metadata.rank = rank;
|
|
150
|
-
}
|
|
151
|
-
// Handle cache update and persistence
|
|
152
|
-
await this.project.updateCard(sourceCard);
|
|
153
|
-
const updatedCard = {
|
|
154
|
-
...sourceCard,
|
|
155
|
-
path: destinationPath,
|
|
156
|
-
parent: movingToRoot ? ROOT : destination,
|
|
157
|
-
metadata: sourceCard.metadata
|
|
158
|
-
? {
|
|
159
|
-
...sourceCard.metadata,
|
|
160
|
-
rank: rank,
|
|
136
|
+
if (source === destination) {
|
|
137
|
+
throw new Error(`Card cannot be moved to itself`);
|
|
138
|
+
}
|
|
139
|
+
const movingToRoot = destination === ROOT;
|
|
140
|
+
const sourceCard = this.project.findCard(source);
|
|
141
|
+
const destinationCard = !movingToRoot
|
|
142
|
+
? this.project.findCard(destination)
|
|
143
|
+
: undefined;
|
|
144
|
+
// Prevent moving card to inside its descendants
|
|
145
|
+
if (destinationCard) {
|
|
146
|
+
const { parents } = cardPathParts(this.project.projectPrefix, destinationCard.path);
|
|
147
|
+
if (parents.includes(source)) {
|
|
148
|
+
throw new Error(`Card cannot be moved to inside itself`);
|
|
161
149
|
}
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
150
|
+
}
|
|
151
|
+
// Imported templates cannot be modified.
|
|
152
|
+
if ((destinationCard && isModuleCard(destinationCard)) ||
|
|
153
|
+
isModuleCard(sourceCard)) {
|
|
154
|
+
throw new Error(`Cannot modify imported module templates`);
|
|
155
|
+
}
|
|
156
|
+
// Special handling for moving to root
|
|
157
|
+
if (movingToRoot) {
|
|
158
|
+
if (isTemplateCard(sourceCard)) {
|
|
159
|
+
throw new Error(`Template cards cannot be moved to project root`);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
const bothTemplateCards = isTemplateCard(sourceCard) &&
|
|
164
|
+
destinationCard &&
|
|
165
|
+
isTemplateCard(destinationCard);
|
|
166
|
+
const bothProjectCards = this.project.hasProjectCard(sourceCard.key) &&
|
|
167
|
+
destinationCard &&
|
|
168
|
+
this.project.hasProjectCard(destinationCard.key);
|
|
169
|
+
if (!(bothTemplateCards || bothProjectCards)) {
|
|
170
|
+
throw new Error(`Cards cannot be moved from project to template or vice versa`);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
const destinationPath = movingToRoot
|
|
174
|
+
? join(this.project.paths.cardRootFolder, sourceCard.key)
|
|
175
|
+
: join(destinationCard.path, 'c', sourceCard.key);
|
|
176
|
+
// if the card is already in the destination, do nothing
|
|
177
|
+
if (sourceCard.path === destinationPath) {
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
// if both are project cards, make sure source card can be moved
|
|
181
|
+
const actionGuard = new ActionGuard(this.project.calculationEngine);
|
|
182
|
+
await actionGuard.checkPermission('move', source);
|
|
183
|
+
// re-rank the card in the new location
|
|
184
|
+
// it will be the last one in the new location
|
|
185
|
+
let children;
|
|
186
|
+
if (!movingToRoot) {
|
|
187
|
+
const parent = this.project.findCard(destination);
|
|
188
|
+
children = this.project.cardKeysToCards(parent.children);
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
children = this.project.showProjectCards();
|
|
192
|
+
}
|
|
193
|
+
if (!children) {
|
|
194
|
+
throw new Error(`Children not found from card ${destination}`);
|
|
195
|
+
}
|
|
196
|
+
children = sortItems(children, (item) => item?.metadata?.rank || '1|z');
|
|
197
|
+
const lastChild = children[children.length - 1];
|
|
198
|
+
const rank = lastChild && lastChild.metadata
|
|
199
|
+
? getRankAfter(lastChild.metadata.rank)
|
|
200
|
+
: FIRST_RANK;
|
|
201
|
+
// Save old path before moving (needed to update descendant paths)
|
|
202
|
+
const oldPath = sourceCard.path;
|
|
203
|
+
// First do the file operations, then update metadata
|
|
204
|
+
await copyDir(sourceCard.path, destinationPath);
|
|
205
|
+
await deleteDir(sourceCard.path);
|
|
206
|
+
// Update card with new path, parent, and rank
|
|
207
|
+
sourceCard.path = destinationPath;
|
|
208
|
+
sourceCard.parent = movingToRoot ? ROOT : destination;
|
|
209
|
+
if (sourceCard.metadata) {
|
|
210
|
+
sourceCard.metadata.rank = rank;
|
|
211
|
+
}
|
|
212
|
+
// Update attachment paths for the moved card
|
|
213
|
+
if (sourceCard.attachments && sourceCard.attachments.length > 0) {
|
|
214
|
+
for (const attachment of sourceCard.attachments) {
|
|
215
|
+
if (attachment.path.startsWith(oldPath)) {
|
|
216
|
+
attachment.path = attachment.path.replace(oldPath, destinationPath);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
// Handle cache update and persistence
|
|
221
|
+
await this.project.updateCard(sourceCard);
|
|
222
|
+
// Update all descendant card paths in the cache to reflect the new filesystem location.
|
|
223
|
+
// This is critical: files have been moved on disk, but children's cached paths
|
|
224
|
+
// still point to the old location. Without this, operations on children
|
|
225
|
+
// (like edit or delete) would target non-existent paths, leaving orphaned files.
|
|
226
|
+
if (sourceCard.children && sourceCard.children.length > 0) {
|
|
227
|
+
for (const childKey of sourceCard.children) {
|
|
228
|
+
this.project.updateDescendantPathsAfterMove(childKey, oldPath, destinationPath);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
const updatedCard = {
|
|
232
|
+
...sourceCard,
|
|
233
|
+
path: destinationPath,
|
|
234
|
+
parent: movingToRoot ? ROOT : destination,
|
|
235
|
+
metadata: sourceCard.metadata
|
|
236
|
+
? {
|
|
237
|
+
...sourceCard.metadata,
|
|
238
|
+
rank: rank,
|
|
239
|
+
}
|
|
240
|
+
: undefined,
|
|
241
|
+
};
|
|
242
|
+
// Fetch old parent
|
|
243
|
+
const oldParent = sourceCard.parent;
|
|
244
|
+
let oldParentCard;
|
|
245
|
+
if (oldParent && oldParent !== ROOT) {
|
|
246
|
+
oldParentCard = this.project.findCard(oldParent);
|
|
247
|
+
}
|
|
248
|
+
let newParentCard;
|
|
249
|
+
if (!movingToRoot) {
|
|
250
|
+
newParentCard = this.project.findCard(destination);
|
|
251
|
+
}
|
|
252
|
+
// Finally, update the project
|
|
253
|
+
await this.project.handleCardMoved(updatedCard, newParentCard, oldParentCard);
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Ranks card using position given as 'index'.
|
|
257
|
+
* @param cardKey card key
|
|
258
|
+
* @param index to which position should card be ranked to
|
|
259
|
+
*/
|
|
260
|
+
async rankByIndex(cardKey, index) {
|
|
261
|
+
if (index < 0) {
|
|
262
|
+
throw new Error(`Index must be greater than 0`);
|
|
263
|
+
}
|
|
264
|
+
if (index === 0) {
|
|
265
|
+
await this.rankFirst(cardKey);
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
const card = this.project.findCard(cardKey);
|
|
269
|
+
if (!card.parent) {
|
|
270
|
+
throw new Error(`Parent card ${cardKey} not found from project`);
|
|
271
|
+
}
|
|
272
|
+
const children = sortItems(this.getSiblings(card), (item) => item.metadata?.rank || EMPTY_RANK);
|
|
273
|
+
if (!children || children.length === 0) {
|
|
274
|
+
throw new Error(`Children not found from card ${card.parent}`);
|
|
275
|
+
}
|
|
276
|
+
if (children.length < index) {
|
|
277
|
+
throw new Error(`Index ${index} is out of bounds`);
|
|
278
|
+
}
|
|
279
|
+
await this.rankCard(cardKey, children[index - 1].key);
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Sets the rank of a card to be after another card.
|
|
283
|
+
* @param cardKey Card to rank
|
|
284
|
+
* @param beforeCardKey Card key after which the card will be ranked
|
|
285
|
+
*/
|
|
286
|
+
async rankCard(cardKey, beforeCardKey) {
|
|
287
|
+
const card = this.project.findCard(cardKey);
|
|
288
|
+
const beforeCard = this.project.findCard(beforeCardKey);
|
|
289
|
+
if (beforeCard.parent !== card.parent) {
|
|
290
|
+
throw new Error(`Cards must be from the same parent`);
|
|
291
|
+
}
|
|
292
|
+
const children = sortItems(this.getSiblings(beforeCard), (item) => item.metadata?.rank || EMPTY_RANK);
|
|
293
|
+
if (!children) {
|
|
294
|
+
throw new Error(`Children not found from card ${beforeCard.parent}`);
|
|
295
|
+
}
|
|
296
|
+
const beforeCardIndex = children.findIndex((child) => child.key === beforeCard.key);
|
|
297
|
+
if (beforeCardIndex === -1) {
|
|
298
|
+
throw new Error(`Card ${beforeCardKey} is not a child of ${beforeCard.parent}`);
|
|
299
|
+
}
|
|
300
|
+
if (children[beforeCardIndex].key === cardKey) {
|
|
301
|
+
throw new Error(`Card cannot be ranked after itself`);
|
|
302
|
+
}
|
|
303
|
+
if (beforeCardIndex === children.length - 1) {
|
|
304
|
+
await this.project.updateCardMetadataKey(cardKey, 'rank', getRankAfter(beforeCard.metadata?.rank));
|
|
305
|
+
}
|
|
306
|
+
else {
|
|
307
|
+
await this.project.updateCardMetadataKey(cardKey, 'rank', getRankBetween(beforeCard.metadata?.rank, children[beforeCardIndex + 1].metadata?.rank));
|
|
308
|
+
}
|
|
264
309
|
}
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
310
|
+
/**
|
|
311
|
+
* Ranks card first.
|
|
312
|
+
* @param cardKey card key
|
|
313
|
+
*/
|
|
314
|
+
async rankFirst(cardKey) {
|
|
315
|
+
const card = this.project.findCard(cardKey);
|
|
316
|
+
const children = sortItems(this.getSiblings(card), (item) => item.metadata?.rank || EMPTY_RANK);
|
|
317
|
+
if (!children || children.length === 0) {
|
|
318
|
+
throw new Error(`Children not found from card ${card.parent}`);
|
|
319
|
+
}
|
|
320
|
+
if (children[0].key === cardKey && children[0].metadata?.rank) {
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
const firstRank = children[0].metadata?.rank;
|
|
324
|
+
if (!firstRank) {
|
|
325
|
+
await this.project.updateCardMetadataKey(cardKey, 'rank', FIRST_RANK);
|
|
326
|
+
return;
|
|
327
|
+
}
|
|
328
|
+
// Set the rank to be the first one
|
|
329
|
+
if (firstRank === FIRST_RANK) {
|
|
330
|
+
// if the first card is already at the first rank, we need to move the card to the next one
|
|
331
|
+
const secondRank = children[1].metadata?.rank;
|
|
332
|
+
if (!secondRank) {
|
|
333
|
+
throw new Error(`Second rank not found`);
|
|
334
|
+
}
|
|
335
|
+
const rankBetween = getRankBetween(firstRank, secondRank);
|
|
336
|
+
await this.project.updateCardMetadataKey(children[0].key, 'rank', rankBetween);
|
|
337
|
+
await this.project.updateCardMetadataKey(cardKey, 'rank', firstRank);
|
|
338
|
+
}
|
|
339
|
+
else {
|
|
340
|
+
// if the card is not at the first rank, we just use the first rank
|
|
341
|
+
await this.project.updateCardMetadataKey(cardKey, 'rank', FIRST_RANK);
|
|
342
|
+
}
|
|
274
343
|
}
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
await this.rebalanceProjectRecursively(cards);
|
|
284
|
-
const templateCards = this.project.allTemplateCards();
|
|
285
|
-
const cardGroups = templateCards.reduce((result, card) => {
|
|
286
|
-
// template card root cards always have a parent(, thus this shouldn't happen
|
|
287
|
-
if (!card.parent) {
|
|
288
|
-
return result;
|
|
344
|
+
/**
|
|
345
|
+
* Rebalances the ranks of the children of a card.
|
|
346
|
+
* @param parentCardKey parent card key
|
|
347
|
+
*/
|
|
348
|
+
async rebalanceChildren(parentCardKey) {
|
|
349
|
+
const parentCard = this.project.findCard(parentCardKey);
|
|
350
|
+
if (!parentCard || !parentCard.children) {
|
|
351
|
+
throw new Error(`Card ${parentCardKey} not found from project`);
|
|
289
352
|
}
|
|
290
|
-
|
|
291
|
-
|
|
353
|
+
await this.rebalanceCards(this.project.cardKeysToCards(parentCard.children));
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* Rebalances the ranks of the cards in the whole project, including templates
|
|
357
|
+
* Can be used even if the ranks do not exist
|
|
358
|
+
*/
|
|
359
|
+
async rebalanceProject() {
|
|
360
|
+
const cards = this.project.showProjectCards();
|
|
361
|
+
await this.rebalanceProjectRecursively(cards);
|
|
362
|
+
const templateCards = this.project.allTemplateCards();
|
|
363
|
+
const cardGroups = templateCards.reduce((result, card) => {
|
|
364
|
+
// template card root cards always have a parent(, thus this shouldn't happen
|
|
365
|
+
if (!card.parent) {
|
|
366
|
+
return result;
|
|
367
|
+
}
|
|
368
|
+
if (!result[card.parent]) {
|
|
369
|
+
result[card.parent] = [];
|
|
370
|
+
}
|
|
371
|
+
result[card.parent].push(card);
|
|
372
|
+
return result;
|
|
373
|
+
}, {});
|
|
374
|
+
for (const [, cards] of Object.entries(cardGroups)) {
|
|
375
|
+
await this.rebalanceCards(cards);
|
|
292
376
|
}
|
|
293
|
-
result[card.parent].push(card);
|
|
294
|
-
return result;
|
|
295
|
-
}, {});
|
|
296
|
-
for (const [, cards] of Object.entries(cardGroups)) {
|
|
297
|
-
await this.rebalanceCards(cards);
|
|
298
377
|
}
|
|
299
|
-
}
|
|
300
|
-
}
|
|
378
|
+
};
|
|
379
|
+
})();
|
|
380
|
+
export { Move };
|
|
301
381
|
//# sourceMappingURL=move.js.map
|