intelligent-system-design-language 0.3.21 → 0.3.23
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/.claude/agents/langium-language-designer.md +38 -38
- package/.claude/agents/typescript-vscode-expert.md +29 -29
- package/.claude/agents/ui-ux-designer.md +36 -36
- package/.claude/settings.local.json +33 -33
- package/.idea/inspectionProfiles/Project_Default.xml +6 -6
- package/.idea/isdl.iml +13 -13
- package/.idea/modules.xml +8 -8
- package/.idea/vcs.xml +6 -6
- package/.idea/watcherTasks.xml +3 -3
- package/.vscodeignore +18 -18
- package/LICENSE +673 -673
- package/README.md +86 -86
- package/bin/cli.js +4 -4
- package/bin/lsp.js +8 -8
- package/out/_backgrounds.scss +91 -91
- package/out/_handlebars.scss +497 -497
- package/out/_isdlStyles.scss +1444 -1381
- package/out/_vuetifyOverrides.scss +425 -425
- package/out/_vuetifyStyles.scss +31957 -31957
- package/out/cli/components/_backgrounds.scss +91 -91
- package/out/cli/components/_handlebars.scss +497 -497
- package/out/cli/components/_isdlStyles.scss +1444 -1381
- package/out/cli/components/_vuetifyOverrides.scss +425 -425
- package/out/cli/components/_vuetifyStyles.scss +31957 -31957
- package/out/cli/components/active-effect-sheet-generator.js +453 -453
- package/out/cli/components/chat-card-generator.js +654 -651
- package/out/cli/components/chat-card-generator.js.map +1 -1
- package/out/cli/components/css-generator.js +4 -4
- package/out/cli/components/damage-roll-generator.js +160 -160
- package/out/cli/components/datamodel-generator.js +264 -257
- package/out/cli/components/datamodel-generator.js.map +1 -1
- package/out/cli/components/derived-data-generator.js +923 -923
- package/out/cli/components/hotbar-drop-hook-generator.js +82 -82
- package/out/cli/components/init-hook-generator.js +495 -495
- package/out/cli/components/language-generator.js +1 -1
- package/out/cli/components/language-generator.js.map +1 -1
- package/out/cli/components/measured-template-preview.js +221 -221
- package/out/cli/components/method-generator.js +979 -887
- package/out/cli/components/method-generator.js.map +1 -1
- package/out/cli/components/ready-hook-generator.js +404 -404
- package/out/cli/components/token-generator.js +116 -116
- package/out/cli/components/vue/base-components/vue-attribute.js +138 -138
- package/out/cli/components/vue/base-components/vue-boolean.js +64 -64
- package/out/cli/components/vue/base-components/vue-calculator.js +93 -93
- package/out/cli/components/vue/base-components/vue-damage-application.js +356 -356
- package/out/cli/components/vue/base-components/vue-damage-bonuses.js +165 -165
- package/out/cli/components/vue/base-components/vue-damage-resistances.js +196 -196
- package/out/cli/components/vue/base-components/vue-damage-track.js +121 -121
- package/out/cli/components/vue/base-components/vue-date-time.js +42 -42
- package/out/cli/components/vue/base-components/vue-dice.js +98 -98
- package/out/cli/components/vue/base-components/vue-die.js +73 -73
- package/out/cli/components/vue/base-components/vue-document-choice.js +149 -149
- package/out/cli/components/vue/base-components/vue-document-choices.js +179 -179
- package/out/cli/components/vue/base-components/vue-document-link.js +60 -60
- package/out/cli/components/vue/base-components/vue-extended-choice.js +88 -88
- package/out/cli/components/vue/base-components/vue-inventory.js +519 -519
- package/out/cli/components/vue/base-components/vue-macro-choice.js +138 -138
- package/out/cli/components/vue/base-components/vue-measured-template.js +530 -530
- package/out/cli/components/vue/base-components/vue-money.js +483 -483
- package/out/cli/components/vue/base-components/vue-number.js +174 -174
- package/out/cli/components/vue/base-components/vue-paperdoll.js +43 -43
- package/out/cli/components/vue/base-components/vue-parent-property-reference.js +76 -76
- package/out/cli/components/vue/base-components/vue-prosemirror.js +18 -18
- package/out/cli/components/vue/base-components/vue-resource.js +136 -136
- package/out/cli/components/vue/base-components/vue-roll-visualizer.js +286 -109
- package/out/cli/components/vue/base-components/vue-roll-visualizer.js.map +1 -1
- package/out/cli/components/vue/base-components/vue-self-property-reference.js +62 -62
- package/out/cli/components/vue/base-components/vue-string-choice.js +98 -98
- package/out/cli/components/vue/base-components/vue-string-choices.js +203 -203
- package/out/cli/components/vue/base-components/vue-string.js +60 -60
- package/out/cli/components/vue/base-components/vue-text-field.js +53 -53
- package/out/cli/components/vue/base-components/vue-tracker.js +431 -431
- package/out/cli/components/vue/vue-action-component-generator.js +64 -64
- package/out/cli/components/vue/vue-active-effect-sheet-generator.js +856 -856
- package/out/cli/components/vue/vue-datatable-sheet-class-generator.js +292 -292
- package/out/cli/components/vue/vue-datatable2-component-generator.js +824 -824
- package/out/cli/components/vue/vue-document-creation-app.js +121 -121
- package/out/cli/components/vue/vue-document-creation-sheet.js +94 -94
- package/out/cli/components/vue/vue-generator.js +40 -40
- package/out/cli/components/vue/vue-mixin.js +296 -296
- package/out/cli/components/vue/vue-pinned-datatable-component-generator.js +260 -260
- package/out/cli/components/vue/vue-prompt-generator.js +91 -76
- package/out/cli/components/vue/vue-prompt-generator.js.map +1 -1
- package/out/cli/components/vue/vue-prompt-sheet-class-generator.js +317 -317
- package/out/cli/components/vue/vue-sheet-application-generator.js +1177 -1167
- package/out/cli/components/vue/vue-sheet-application-generator.js.map +1 -1
- package/out/cli/components/vue/vue-sheet-class-generator.js +510 -510
- package/out/cli/generator.js +438 -433
- package/out/cli/generator.js.map +1 -1
- package/out/extension/github/githubAuthProvider.js +71 -29
- package/out/extension/github/githubAuthProvider.js.map +1 -1
- package/out/extension/github/githubGistManager.js +4 -3
- package/out/extension/github/githubGistManager.js.map +1 -1
- package/out/extension/github/githubManager.js +40 -38
- package/out/extension/github/githubManager.js.map +1 -1
- package/out/extension/github/githubQuickActions.js +120 -120
- package/out/extension/github/system-workflow.yml +47 -47
- package/out/extension/main.cjs +909 -532
- package/out/extension/main.cjs.map +3 -3
- package/out/extension/package.json +419 -419
- package/out/language/generated/ast.js +51 -2
- package/out/language/generated/ast.js.map +1 -1
- package/out/language/generated/grammar.js +14240 -13991
- package/out/language/generated/grammar.js.map +1 -1
- package/out/language/intelligent-system-design-language-validator.js +32 -2
- package/out/language/intelligent-system-design-language-validator.js.map +1 -1
- package/out/language/isdl-scope-provider.js +14 -1
- package/out/language/isdl-scope-provider.js.map +1 -1
- package/out/language/main.cjs +913 -569
- package/out/language/main.cjs.map +3 -3
- package/out/package.json +419 -419
- package/out/progressbar.min.js +6 -6
- package/out/styles.scss +762 -747
- package/out/test/validating/diagnostics.test.js +40 -0
- package/out/test/validating/diagnostics.test.js.map +1 -1
- package/package.json +419 -419
|
@@ -15,23 +15,23 @@ export function generateDatatableVueSheet(entry, id, destination) {
|
|
|
15
15
|
const type = isActor(document) ? 'actor' : 'item';
|
|
16
16
|
const page = AstUtils.getContainerOfType(datatable, isPage);
|
|
17
17
|
const pageName = page ? page.name : document.name;
|
|
18
|
-
return expandToNode `
|
|
19
|
-
import { ${type}${document.name}${pageName}${datatable.name}VuetifyDatatable } from "./components/components.vue.es.mjs";
|
|
18
|
+
return expandToNode `
|
|
19
|
+
import { ${type}${document.name}${pageName}${datatable.name}VuetifyDatatable } from "./components/components.vue.es.mjs";
|
|
20
20
|
`;
|
|
21
21
|
}
|
|
22
22
|
function generatePinnedImport(pinnedField) {
|
|
23
23
|
const type = isActor(document) ? 'actor' : 'item';
|
|
24
24
|
const page = AstUtils.getContainerOfType(pinnedField, isPage);
|
|
25
25
|
const pageName = page ? page.name : document.name;
|
|
26
|
-
return expandToNode `
|
|
27
|
-
import { ${type}${document.name}${pageName}${pinnedField.name}VuetifyDatatable } from "./components/components.vue.es.mjs";
|
|
26
|
+
return expandToNode `
|
|
27
|
+
import { ${type}${document.name}${pageName}${pinnedField.name}VuetifyDatatable } from "./components/components.vue.es.mjs";
|
|
28
28
|
`;
|
|
29
29
|
}
|
|
30
30
|
const tables = getAllOfType(document.body, isTableField, false);
|
|
31
31
|
const pinnedFields = getAllOfType(document.body, isPinnedField, true);
|
|
32
|
-
return expandToNode `
|
|
33
|
-
${joinToNode(tables, generateVuetifyImport, { appendNewLineIfNotEmpty: true })}
|
|
34
|
-
${joinToNode(pinnedFields, generatePinnedImport, { appendNewLineIfNotEmpty: true })}
|
|
32
|
+
return expandToNode `
|
|
33
|
+
${joinToNode(tables, generateVuetifyImport, { appendNewLineIfNotEmpty: true })}
|
|
34
|
+
${joinToNode(pinnedFields, generatePinnedImport, { appendNewLineIfNotEmpty: true })}
|
|
35
35
|
`;
|
|
36
36
|
}
|
|
37
37
|
function generateDatatableSwitch(document) {
|
|
@@ -39,303 +39,303 @@ export function generateDatatableVueSheet(entry, id, destination) {
|
|
|
39
39
|
const type = isActor(document) ? 'actor' : 'item';
|
|
40
40
|
const page = AstUtils.getContainerOfType(datatable, isPage);
|
|
41
41
|
const pageName = page ? page.name : document.name;
|
|
42
|
-
return expandToNode `
|
|
43
|
-
case "${type}${document.name}${pageName}${datatable.name}": return ${type}${document.name}${pageName}${datatable.name}VuetifyDatatable; break;
|
|
42
|
+
return expandToNode `
|
|
43
|
+
case "${type}${document.name}${pageName}${datatable.name}": return ${type}${document.name}${pageName}${datatable.name}VuetifyDatatable; break;
|
|
44
44
|
`;
|
|
45
45
|
}
|
|
46
46
|
function generatePinnedCase(pinnedField) {
|
|
47
47
|
const type = isActor(document) ? 'actor' : 'item';
|
|
48
48
|
const page = AstUtils.getContainerOfType(pinnedField, isPage);
|
|
49
49
|
const pageName = page ? page.name : document.name;
|
|
50
|
-
return expandToNode `
|
|
51
|
-
case "${type}${document.name}${document.name}${pinnedField.name}": return ${type}${document.name}${pageName}${pinnedField.name}VuetifyDatatable; break;
|
|
50
|
+
return expandToNode `
|
|
51
|
+
case "${type}${document.name}${document.name}${pinnedField.name}": return ${type}${document.name}${pageName}${pinnedField.name}VuetifyDatatable; break;
|
|
52
52
|
`;
|
|
53
53
|
}
|
|
54
54
|
const tables = getAllOfType(document.body, isTableField, false);
|
|
55
55
|
const pinnedFields = getAllOfType(document.body, isPinnedField, true);
|
|
56
|
-
return expandToNode `
|
|
57
|
-
${joinToNode(tables, generateVuetifyCase, { appendNewLineIfNotEmpty: true })}
|
|
58
|
-
${joinToNode(pinnedFields, generatePinnedCase, { appendNewLineIfNotEmpty: true })}
|
|
56
|
+
return expandToNode `
|
|
57
|
+
${joinToNode(tables, generateVuetifyCase, { appendNewLineIfNotEmpty: true })}
|
|
58
|
+
${joinToNode(pinnedFields, generatePinnedCase, { appendNewLineIfNotEmpty: true })}
|
|
59
59
|
`;
|
|
60
60
|
}
|
|
61
|
-
const fileNode = expandToNode `
|
|
62
|
-
import VueRenderingMixin from './VueRenderingMixin.mjs';
|
|
63
|
-
${joinToNode(entry.documents, generateImportForDocument, { appendNewLineIfNotEmpty: true })}
|
|
64
|
-
|
|
65
|
-
export default class DatatableApp extends VueRenderingMixin(foundry.applications.api.ApplicationV2) {
|
|
66
|
-
|
|
67
|
-
document;
|
|
68
|
-
constructor(document, table, systemPath, tabName, options = {}) {
|
|
69
|
-
super(options);
|
|
70
|
-
this.#dragDrop = this.#createDragDropHandlers();
|
|
71
|
-
this.document = document;
|
|
72
|
-
this.systemPath = systemPath;
|
|
73
|
-
this.tabName = tabName;
|
|
74
|
-
|
|
75
|
-
const component = this._chooseComponent(table);
|
|
76
|
-
this.vueParts = {
|
|
77
|
-
"datatable": {
|
|
78
|
-
component,
|
|
79
|
-
template: \`<datatable :is="component" :systemPath="systemPath" :context="context">Vue rendering for datatable failed.</datatable>\`
|
|
80
|
-
}
|
|
81
|
-
};
|
|
82
|
-
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
vueData(context) {
|
|
86
|
-
return {
|
|
87
|
-
systemPath: this.systemPath,
|
|
88
|
-
context: context
|
|
89
|
-
};
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
_getProvidedData() {
|
|
93
|
-
// This is a placeholder for any data you want to provide to the Vue app.
|
|
94
|
-
// You can override this method in your subclass to provide additional data.
|
|
95
|
-
return {
|
|
96
|
-
systemPath: this.systemPath,
|
|
97
|
-
};
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
_chooseComponent(table) {
|
|
101
|
-
switch (table) {
|
|
102
|
-
${joinToNode(entry.documents, generateDatatableSwitch, { appendNewLineIfNotEmpty: true })}
|
|
103
|
-
default: throw new Error("No component found for table " + table);
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
_arrayEntryKey = 0;
|
|
108
|
-
_renderKey = 0;
|
|
109
|
-
|
|
110
|
-
/** @override */
|
|
111
|
-
static DEFAULT_OPTIONS = {
|
|
112
|
-
classes: ["${id}", "dialog", "vue-sheet", "isdl-datatable"],
|
|
113
|
-
position: {
|
|
114
|
-
width: 800,
|
|
115
|
-
height: 400,
|
|
116
|
-
},
|
|
117
|
-
window: {
|
|
118
|
-
resizable: true,
|
|
119
|
-
title: "Datatable",
|
|
120
|
-
},
|
|
121
|
-
tag: "form",
|
|
122
|
-
actions: {
|
|
123
|
-
},
|
|
124
|
-
changeActions: {
|
|
125
|
-
},
|
|
126
|
-
// Custom property that's merged into this.options
|
|
127
|
-
dragDrop: [
|
|
128
|
-
{dropSelector: ".single-document"},
|
|
129
|
-
{dragSelector: ".paper-doll-slot", dropSelector: ".paper-doll-slot"}
|
|
130
|
-
],
|
|
131
|
-
form: {
|
|
132
|
-
submitOnChange: false,
|
|
133
|
-
submitOnClose: true,
|
|
134
|
-
closeOnSubmit: true,
|
|
135
|
-
}
|
|
136
|
-
};
|
|
137
|
-
|
|
138
|
-
get title() {
|
|
139
|
-
return \`\${this.document.name} - \${this.tabName}\`;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
async _prepareContext(options) {
|
|
143
|
-
// Output initialization
|
|
144
|
-
const context = {
|
|
145
|
-
// Validates both permissions and compendium status
|
|
146
|
-
editable: true,
|
|
147
|
-
owner: this.document.isOwner,
|
|
148
|
-
limited: this.document.limited,
|
|
149
|
-
|
|
150
|
-
// Add the document.
|
|
151
|
-
object: this.document.toObject(),
|
|
152
|
-
document: this.document,
|
|
153
|
-
|
|
154
|
-
// Add the data to context.data for easier access, as well as flags.
|
|
155
|
-
system: this.document.system,
|
|
156
|
-
flags: this.document.flags,
|
|
157
|
-
|
|
158
|
-
// Roll data.
|
|
159
|
-
rollData: this.document.getRollData() ?? {},
|
|
160
|
-
|
|
161
|
-
// Editors
|
|
162
|
-
editors: {},
|
|
163
|
-
|
|
164
|
-
// Force re-renders. Defined in the vue mixin.
|
|
165
|
-
_renderKey: this._renderKey ?? 0,
|
|
166
|
-
_arrayEntryKey: this._arrayEntryKey ?? 0,
|
|
167
|
-
|
|
168
|
-
// Necessary for formInput and formFields helpers
|
|
169
|
-
fields: this.document.schema.fields,
|
|
170
|
-
systemFields: this.document.system.schema.fields
|
|
171
|
-
};
|
|
172
|
-
|
|
173
|
-
return context;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
/**
|
|
177
|
-
* Actions performed after any render of the Application.
|
|
178
|
-
* Post-render steps are not awaited by the render process.
|
|
179
|
-
* @param {ApplicationRenderContext} context Prepared context data
|
|
180
|
-
* @param {RenderOptions} options Provided render options
|
|
181
|
-
* @protected
|
|
182
|
-
*/
|
|
183
|
-
_onRender(context, options) {
|
|
184
|
-
if (options.isFirstRender) {
|
|
185
|
-
function update(doc, context, id) {
|
|
186
|
-
console.dir(doc);
|
|
187
|
-
if (doc.parent?.uuid === this.document.uuid) {
|
|
188
|
-
console.log("Updating document: ", doc);
|
|
189
|
-
this.document = doc.parent;
|
|
190
|
-
this.render();
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
Hooks.on("createItem", update.bind(this));
|
|
194
|
-
Hooks.on("updateItem", update.bind(this));
|
|
195
|
-
Hooks.on("deleteItem", update.bind(this));
|
|
196
|
-
}
|
|
197
|
-
this.#dragDrop.forEach((d) => d.bind(this.element));
|
|
198
|
-
// You may want to add other special handling here
|
|
199
|
-
// Foundry comes with a large number of utility classes, e.g. SearchFilter
|
|
200
|
-
// That you may want to implement yourself.
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
// Drag and Drop
|
|
205
|
-
|
|
206
|
-
/**
|
|
207
|
-
* Returns an array of DragDrop instances
|
|
208
|
-
* @type {DragDrop[]}
|
|
209
|
-
*/
|
|
210
|
-
get dragDrop() {
|
|
211
|
-
return this.#dragDrop;
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
/**
|
|
215
|
-
* Define whether a user is able to begin a dragstart workflow for a given drag selector
|
|
216
|
-
* @param {string} selector The candidate HTML selector for dragging
|
|
217
|
-
* @returns {boolean} Can the current user drag this selector?
|
|
218
|
-
* @protected
|
|
219
|
-
*/
|
|
220
|
-
_canDragStart(selector) {
|
|
221
|
-
return this.isEditable;
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
/**
|
|
225
|
-
* Define whether a user is able to conclude a drag-and-drop workflow for a given drop selector
|
|
226
|
-
* @param {string} selector The candidate HTML selector for the drop target
|
|
227
|
-
* @returns {boolean} Can the current user drop on this selector?
|
|
228
|
-
* @protected
|
|
229
|
-
*/
|
|
230
|
-
_canDragDrop(selector) {
|
|
231
|
-
return this.isEditable;
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
/**
|
|
235
|
-
* Callback actions which occur at the beginning of a drag start workflow.
|
|
236
|
-
* @param {DragEvent} event The originating DragEvent
|
|
237
|
-
* @protected
|
|
238
|
-
*/
|
|
239
|
-
_onDragStart(event) {
|
|
240
|
-
console.log("Drag Start");
|
|
241
|
-
|
|
242
|
-
if (event.currentTarget.classList.contains("paper-doll-slot")) {
|
|
243
|
-
// Remove the item from the slot
|
|
244
|
-
const name = event.currentTarget.dataset.name;
|
|
245
|
-
const update = {};
|
|
246
|
-
update[name] = null;
|
|
247
|
-
this.document.update(update);
|
|
248
|
-
}
|
|
249
|
-
else {
|
|
250
|
-
const tr = event.currentTarget.closest("tr");
|
|
251
|
-
const data = {
|
|
252
|
-
type: tr.dataset.type == "ActiveEffect" ? "ActiveEffect" : "Item",
|
|
253
|
-
uuid: tr.dataset.uuid
|
|
254
|
-
};
|
|
255
|
-
|
|
256
|
-
event.dataTransfer.setData("text/plain", JSON.stringify(data));
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
/**
|
|
261
|
-
* Callback actions which occur when a dragged element is over a drop target.
|
|
262
|
-
* @param {DragEvent} event The originating DragEvent
|
|
263
|
-
* @protected
|
|
264
|
-
*/
|
|
265
|
-
_onDragOver(event) {}
|
|
266
|
-
|
|
267
|
-
/* -------------------------------------------- */
|
|
268
|
-
|
|
269
|
-
async _onDrop(event) {
|
|
270
|
-
const data = JSON.parse(event.dataTransfer.getData("text/plain"));
|
|
271
|
-
|
|
272
|
-
// If the drop target is a single document, handle it differently
|
|
273
|
-
const linkedClasses = [ "single-document", "paper-doll-slot" ];
|
|
274
|
-
const eventClasses = Array.from(event.currentTarget.classList);
|
|
275
|
-
if (eventClasses.find(c => linkedClasses.includes(c))) {
|
|
276
|
-
const doc = await fromUuid(data.uuid);
|
|
277
|
-
if ( !doc ) return;
|
|
278
|
-
if ( doc.type !== event.currentTarget.dataset.type ) {
|
|
279
|
-
ui.notifications.error(\`Expected a \${event.currentTarget.dataset.type} type Document, but got a \${doc.type} type one instead. \`);
|
|
280
|
-
return;
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
const update = {};
|
|
284
|
-
update[event.currentTarget.dataset.name] = data.uuid;
|
|
285
|
-
await this.document.update(update);
|
|
286
|
-
return;
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
const dropTypes = ["Item", "ActiveEffect"];
|
|
290
|
-
if ( !dropTypes.includes(data.type) ) return;
|
|
291
|
-
const item = await fromUuid(data.uuid);
|
|
292
|
-
if ( !item ) return;
|
|
293
|
-
|
|
294
|
-
// Prevent duplicates when dropping an item that's already owned by this document
|
|
295
|
-
if ( item.parent?.uuid === this.document.uuid ) return;
|
|
296
|
-
|
|
297
|
-
if ( data.type === "ActiveEffect" ) {
|
|
298
|
-
ActiveEffect.createDocuments([item], {parent: this.document})
|
|
299
|
-
return;
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
Item.createDocuments([item], {parent: this.document})
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
/* -------------------------------------------- */
|
|
306
|
-
|
|
307
|
-
/**
|
|
308
|
-
* Returns an array of DragDrop instances
|
|
309
|
-
* @type {DragDrop[]}
|
|
310
|
-
*/
|
|
311
|
-
get dragDrop() {
|
|
312
|
-
return this.#dragDrop;
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
// This is marked as private because there's no real need
|
|
316
|
-
// for subclasses or external hooks to mess with it directly
|
|
317
|
-
#dragDrop;
|
|
318
|
-
|
|
319
|
-
/**
|
|
320
|
-
* Create drag-and-drop workflow handlers for this Application
|
|
321
|
-
* @returns {DragDrop[]} An array of DragDrop handlers
|
|
322
|
-
* @private
|
|
323
|
-
*/
|
|
324
|
-
#createDragDropHandlers() {
|
|
325
|
-
return this.options.dragDrop.map((d) => {
|
|
326
|
-
d.permissions = {
|
|
327
|
-
dragstart: this._canDragStart.bind(this),
|
|
328
|
-
drop: this._canDragDrop.bind(this)
|
|
329
|
-
};
|
|
330
|
-
d.callbacks = {
|
|
331
|
-
dragstart: this._onDragStart.bind(this),
|
|
332
|
-
dragover: this._onDragOver.bind(this),
|
|
333
|
-
drop: this._onDrop.bind(this)
|
|
334
|
-
};
|
|
335
|
-
return new DragDrop(d);
|
|
336
|
-
});
|
|
337
|
-
}
|
|
338
|
-
}
|
|
61
|
+
const fileNode = expandToNode `
|
|
62
|
+
import VueRenderingMixin from './VueRenderingMixin.mjs';
|
|
63
|
+
${joinToNode(entry.documents, generateImportForDocument, { appendNewLineIfNotEmpty: true })}
|
|
64
|
+
|
|
65
|
+
export default class DatatableApp extends VueRenderingMixin(foundry.applications.api.ApplicationV2) {
|
|
66
|
+
|
|
67
|
+
document;
|
|
68
|
+
constructor(document, table, systemPath, tabName, options = {}) {
|
|
69
|
+
super(options);
|
|
70
|
+
this.#dragDrop = this.#createDragDropHandlers();
|
|
71
|
+
this.document = document;
|
|
72
|
+
this.systemPath = systemPath;
|
|
73
|
+
this.tabName = tabName;
|
|
74
|
+
|
|
75
|
+
const component = this._chooseComponent(table);
|
|
76
|
+
this.vueParts = {
|
|
77
|
+
"datatable": {
|
|
78
|
+
component,
|
|
79
|
+
template: \`<datatable :is="component" :systemPath="systemPath" :context="context">Vue rendering for datatable failed.</datatable>\`
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
vueData(context) {
|
|
86
|
+
return {
|
|
87
|
+
systemPath: this.systemPath,
|
|
88
|
+
context: context
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
_getProvidedData() {
|
|
93
|
+
// This is a placeholder for any data you want to provide to the Vue app.
|
|
94
|
+
// You can override this method in your subclass to provide additional data.
|
|
95
|
+
return {
|
|
96
|
+
systemPath: this.systemPath,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
_chooseComponent(table) {
|
|
101
|
+
switch (table) {
|
|
102
|
+
${joinToNode(entry.documents, generateDatatableSwitch, { appendNewLineIfNotEmpty: true })}
|
|
103
|
+
default: throw new Error("No component found for table " + table);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
_arrayEntryKey = 0;
|
|
108
|
+
_renderKey = 0;
|
|
109
|
+
|
|
110
|
+
/** @override */
|
|
111
|
+
static DEFAULT_OPTIONS = {
|
|
112
|
+
classes: ["${id}", "dialog", "vue-sheet", "isdl-datatable"],
|
|
113
|
+
position: {
|
|
114
|
+
width: 800,
|
|
115
|
+
height: 400,
|
|
116
|
+
},
|
|
117
|
+
window: {
|
|
118
|
+
resizable: true,
|
|
119
|
+
title: "Datatable",
|
|
120
|
+
},
|
|
121
|
+
tag: "form",
|
|
122
|
+
actions: {
|
|
123
|
+
},
|
|
124
|
+
changeActions: {
|
|
125
|
+
},
|
|
126
|
+
// Custom property that's merged into this.options
|
|
127
|
+
dragDrop: [
|
|
128
|
+
{dropSelector: ".single-document"},
|
|
129
|
+
{dragSelector: ".paper-doll-slot", dropSelector: ".paper-doll-slot"}
|
|
130
|
+
],
|
|
131
|
+
form: {
|
|
132
|
+
submitOnChange: false,
|
|
133
|
+
submitOnClose: true,
|
|
134
|
+
closeOnSubmit: true,
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
get title() {
|
|
139
|
+
return \`\${this.document.name} - \${this.tabName}\`;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
async _prepareContext(options) {
|
|
143
|
+
// Output initialization
|
|
144
|
+
const context = {
|
|
145
|
+
// Validates both permissions and compendium status
|
|
146
|
+
editable: true,
|
|
147
|
+
owner: this.document.isOwner,
|
|
148
|
+
limited: this.document.limited,
|
|
149
|
+
|
|
150
|
+
// Add the document.
|
|
151
|
+
object: this.document.toObject(),
|
|
152
|
+
document: this.document,
|
|
153
|
+
|
|
154
|
+
// Add the data to context.data for easier access, as well as flags.
|
|
155
|
+
system: this.document.system,
|
|
156
|
+
flags: this.document.flags,
|
|
157
|
+
|
|
158
|
+
// Roll data.
|
|
159
|
+
rollData: this.document.getRollData() ?? {},
|
|
160
|
+
|
|
161
|
+
// Editors
|
|
162
|
+
editors: {},
|
|
163
|
+
|
|
164
|
+
// Force re-renders. Defined in the vue mixin.
|
|
165
|
+
_renderKey: this._renderKey ?? 0,
|
|
166
|
+
_arrayEntryKey: this._arrayEntryKey ?? 0,
|
|
167
|
+
|
|
168
|
+
// Necessary for formInput and formFields helpers
|
|
169
|
+
fields: this.document.schema.fields,
|
|
170
|
+
systemFields: this.document.system.schema.fields
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
return context;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Actions performed after any render of the Application.
|
|
178
|
+
* Post-render steps are not awaited by the render process.
|
|
179
|
+
* @param {ApplicationRenderContext} context Prepared context data
|
|
180
|
+
* @param {RenderOptions} options Provided render options
|
|
181
|
+
* @protected
|
|
182
|
+
*/
|
|
183
|
+
_onRender(context, options) {
|
|
184
|
+
if (options.isFirstRender) {
|
|
185
|
+
function update(doc, context, id) {
|
|
186
|
+
console.dir(doc);
|
|
187
|
+
if (doc.parent?.uuid === this.document.uuid) {
|
|
188
|
+
console.log("Updating document: ", doc);
|
|
189
|
+
this.document = doc.parent;
|
|
190
|
+
this.render();
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
Hooks.on("createItem", update.bind(this));
|
|
194
|
+
Hooks.on("updateItem", update.bind(this));
|
|
195
|
+
Hooks.on("deleteItem", update.bind(this));
|
|
196
|
+
}
|
|
197
|
+
this.#dragDrop.forEach((d) => d.bind(this.element));
|
|
198
|
+
// You may want to add other special handling here
|
|
199
|
+
// Foundry comes with a large number of utility classes, e.g. SearchFilter
|
|
200
|
+
// That you may want to implement yourself.
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
// Drag and Drop
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Returns an array of DragDrop instances
|
|
208
|
+
* @type {DragDrop[]}
|
|
209
|
+
*/
|
|
210
|
+
get dragDrop() {
|
|
211
|
+
return this.#dragDrop;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Define whether a user is able to begin a dragstart workflow for a given drag selector
|
|
216
|
+
* @param {string} selector The candidate HTML selector for dragging
|
|
217
|
+
* @returns {boolean} Can the current user drag this selector?
|
|
218
|
+
* @protected
|
|
219
|
+
*/
|
|
220
|
+
_canDragStart(selector) {
|
|
221
|
+
return this.isEditable;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Define whether a user is able to conclude a drag-and-drop workflow for a given drop selector
|
|
226
|
+
* @param {string} selector The candidate HTML selector for the drop target
|
|
227
|
+
* @returns {boolean} Can the current user drop on this selector?
|
|
228
|
+
* @protected
|
|
229
|
+
*/
|
|
230
|
+
_canDragDrop(selector) {
|
|
231
|
+
return this.isEditable;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Callback actions which occur at the beginning of a drag start workflow.
|
|
236
|
+
* @param {DragEvent} event The originating DragEvent
|
|
237
|
+
* @protected
|
|
238
|
+
*/
|
|
239
|
+
_onDragStart(event) {
|
|
240
|
+
console.log("Drag Start");
|
|
241
|
+
|
|
242
|
+
if (event.currentTarget.classList.contains("paper-doll-slot")) {
|
|
243
|
+
// Remove the item from the slot
|
|
244
|
+
const name = event.currentTarget.dataset.name;
|
|
245
|
+
const update = {};
|
|
246
|
+
update[name] = null;
|
|
247
|
+
this.document.update(update);
|
|
248
|
+
}
|
|
249
|
+
else {
|
|
250
|
+
const tr = event.currentTarget.closest("tr");
|
|
251
|
+
const data = {
|
|
252
|
+
type: tr.dataset.type == "ActiveEffect" ? "ActiveEffect" : "Item",
|
|
253
|
+
uuid: tr.dataset.uuid
|
|
254
|
+
};
|
|
255
|
+
|
|
256
|
+
event.dataTransfer.setData("text/plain", JSON.stringify(data));
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Callback actions which occur when a dragged element is over a drop target.
|
|
262
|
+
* @param {DragEvent} event The originating DragEvent
|
|
263
|
+
* @protected
|
|
264
|
+
*/
|
|
265
|
+
_onDragOver(event) {}
|
|
266
|
+
|
|
267
|
+
/* -------------------------------------------- */
|
|
268
|
+
|
|
269
|
+
async _onDrop(event) {
|
|
270
|
+
const data = JSON.parse(event.dataTransfer.getData("text/plain"));
|
|
271
|
+
|
|
272
|
+
// If the drop target is a single document, handle it differently
|
|
273
|
+
const linkedClasses = [ "single-document", "paper-doll-slot" ];
|
|
274
|
+
const eventClasses = Array.from(event.currentTarget.classList);
|
|
275
|
+
if (eventClasses.find(c => linkedClasses.includes(c))) {
|
|
276
|
+
const doc = await fromUuid(data.uuid);
|
|
277
|
+
if ( !doc ) return;
|
|
278
|
+
if ( doc.type !== event.currentTarget.dataset.type ) {
|
|
279
|
+
ui.notifications.error(\`Expected a \${event.currentTarget.dataset.type} type Document, but got a \${doc.type} type one instead. \`);
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
const update = {};
|
|
284
|
+
update[event.currentTarget.dataset.name] = data.uuid;
|
|
285
|
+
await this.document.update(update);
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
const dropTypes = ["Item", "ActiveEffect"];
|
|
290
|
+
if ( !dropTypes.includes(data.type) ) return;
|
|
291
|
+
const item = await fromUuid(data.uuid);
|
|
292
|
+
if ( !item ) return;
|
|
293
|
+
|
|
294
|
+
// Prevent duplicates when dropping an item that's already owned by this document
|
|
295
|
+
if ( item.parent?.uuid === this.document.uuid ) return;
|
|
296
|
+
|
|
297
|
+
if ( data.type === "ActiveEffect" ) {
|
|
298
|
+
ActiveEffect.createDocuments([item], {parent: this.document})
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
Item.createDocuments([item], {parent: this.document})
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/* -------------------------------------------- */
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Returns an array of DragDrop instances
|
|
309
|
+
* @type {DragDrop[]}
|
|
310
|
+
*/
|
|
311
|
+
get dragDrop() {
|
|
312
|
+
return this.#dragDrop;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
// This is marked as private because there's no real need
|
|
316
|
+
// for subclasses or external hooks to mess with it directly
|
|
317
|
+
#dragDrop;
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* Create drag-and-drop workflow handlers for this Application
|
|
321
|
+
* @returns {DragDrop[]} An array of DragDrop handlers
|
|
322
|
+
* @private
|
|
323
|
+
*/
|
|
324
|
+
#createDragDropHandlers() {
|
|
325
|
+
return this.options.dragDrop.map((d) => {
|
|
326
|
+
d.permissions = {
|
|
327
|
+
dragstart: this._canDragStart.bind(this),
|
|
328
|
+
drop: this._canDragDrop.bind(this)
|
|
329
|
+
};
|
|
330
|
+
d.callbacks = {
|
|
331
|
+
dragstart: this._onDragStart.bind(this),
|
|
332
|
+
dragover: this._onDragOver.bind(this),
|
|
333
|
+
drop: this._onDrop.bind(this)
|
|
334
|
+
};
|
|
335
|
+
return new DragDrop(d);
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
339
|
`;
|
|
340
340
|
fs.writeFileSync(generatedFilePath, toString(fileNode));
|
|
341
341
|
}
|