Continue work on updating identifier

This commit is contained in:
Carlos Fernandez 2026-05-01 22:09:21 -04:00
parent d2ec5283a0
commit 20f42e8a0d
12 changed files with 122 additions and 69 deletions

View file

@ -9,7 +9,8 @@ export default class ClassSheet extends DHBaseItemSheet {
position: { width: 700 },
actions: {
removeItemFromCollection: ClassSheet.#removeItemFromCollection,
removeSuggestedItem: ClassSheet.#removeSuggestedItem
removeSuggestedItem: ClassSheet.#removeSuggestedItem,
resetIdentifier: ClassSheet.#resetIdentifier
},
tagifyConfigs: [
{
@ -107,6 +108,7 @@ export default class ClassSheet extends DHBaseItemSheet {
async _prepareContext(_options) {
const context = await super._prepareContext(_options);
context.domains = this.document.system.domains;
context.subclasses = await this.document.system.getSubclasses();
return context;
}
@ -129,19 +131,7 @@ export default class ClassSheet extends DHBaseItemSheet {
const itemType = data.type === 'ActiveEffect' ? data.type : item.type;
const target = event.target.closest('fieldset.drop-section');
if (itemType === 'subclass') {
if (!this.document.system.identifier) {
return ui.notifications.error(
game.i18n.localize('DAGGERHEART.UI.Notifications.classMissingIdentifier')
);
}
if (item.system.classIdentifiers.includes(this.document.system.identifier)) return;
await item.update({
'system.classIdentifiers': [...item.system.classIdentifiers, this.document.system.identifier]
});
} else if (['feature', 'ActiveEffect'].includes(itemType)) {
if (['feature', 'ActiveEffect'].includes(itemType)) {
super._onDrop(event);
} else if (this.document.parent?.type !== 'character') {
if (itemType === 'weapon') {
@ -218,4 +208,10 @@ export default class ClassSheet extends DHBaseItemSheet {
const { target } = element.dataset;
await this.document.update({ [`system.characterGuide.${target}`]: null });
}
static async #resetIdentifier() {
const document = this.document;
const initial = document.system.schema.fields.identifier.getInitialValue(document._source);
document.update({ 'system.identifier': initial });
}
}

View file

@ -40,4 +40,27 @@ export default class SubclassSheet extends DHBaseItemSheet {
get relatedDocs() {
return this.document.system.features.map(x => x.item);
}
async _onDrop(event) {
event.stopPropagation();
const data = TextEditor.getDragEventData(event);
const item = await fromUuid(data.uuid);
const itemType = data.type === 'ActiveEffect' ? data.type : item.type;
if (itemType === 'class') {
const identifier = item.system.identifier;
if (!identifier) {
return ui.notifications.error(
game.i18n.localize('DAGGERHEART.UI.Notifications.classMissingIdentifier')
);
}
if (this.document.system.classLink.identifier !== identifier) {
const { img, name } = item;
await this.document.update({ 'system.classLink': { identifier, img, name } });
}
return;
}
return super._onDrop(event);
}
}

View file

@ -2,7 +2,7 @@ import BaseDataItem from './base.mjs';
import ForeignDocumentUUIDField from '../fields/foreignDocumentUUIDField.mjs';
import ForeignDocumentUUIDArrayField from '../fields/foreignDocumentUUIDArrayField.mjs';
import ItemLinkFields from '../fields/itemLinkFields.mjs';
import { addLinkedItemsDiff, getFeaturesHTMLData, updateLinkedItemApps } from '../../helpers/utils.mjs';
import { addLinkedItemsDiff, camelize, getFeaturesHTMLData, updateLinkedItemApps } from '../../helpers/utils.mjs';
export default class DHClass extends BaseDataItem {
/** @inheritDoc */
@ -51,7 +51,7 @@ export default class DHClass extends BaseDataItem {
backgroundQuestions: new fields.ArrayField(new fields.StringField(), { initial: ['', '', ''] }),
connections: new fields.ArrayField(new fields.StringField(), { initial: ['', '', ''] }),
isMulticlass: new fields.BooleanField({ initial: false }),
identifier: new fields.StringField(),
identifier: new fields.StringField({ blank: false, initial: obj => camelize(obj?.name ?? '') }),
/* Subclasses is legacy. If we can safetely migrate it away at some point we could remove it*/
subclasses: new ForeignDocumentUUIDArrayField({ type: 'Item', required: false })
};
@ -73,24 +73,21 @@ export default class DHClass extends BaseDataItem {
}
async getSubclasses() {
const oldLinkedSubclasses = this.subclasses.filter(x => x);
if (!this.identifier) return oldLinkedSubclasses;
const oldLinkedSubclasses = this.subclasses;
if (oldLinkedSubclasses.length) return oldLinkedSubclasses;
const subclasses = game.items.filter(
x => x.type === 'subclass' && x.system.classIdentifiers.includes(this.identifier)
x => x.type === 'subclass' && x.system.classLink.identifier === this.identifier
);
for (const pack of game.packs) {
const indexes = await pack.getIndex({ fields: ['system.classIdentifiers'] });
const indexes = await pack.getIndex({ fields: ['system.classLink.identifier'] });
for (const index of indexes) {
if (
index.type === 'subclass' &&
(index.system.classIdentifiers ?? []).includes(
this.identifier && !subclasses.find(x => x.uuid === index.uuid)
)
) {
const subclass = await foundry.utils.fromUuid(index.uuid);
subclasses.push(subclass);
}
if (index.type !== 'subclass') continue;
if (index.system?.classLink?.identifier !== this.identifier) continue;
if (subclasses.find(x => x.uuid === index.uuid)) continue;
const subclass = await foundry.utils.fromUuid(index.uuid);
subclasses.push(subclass);
}
}

View file

@ -28,7 +28,11 @@ export default class DHSubclass extends BaseDataItem {
features: new ItemLinkFields(),
featureState: new fields.NumberField({ required: true, initial: 1, min: 1 }),
isMulticlass: new fields.BooleanField({ initial: false }),
classIdentifiers: new fields.ArrayField(new fields.StringField({ nullable: false })),
classLink: new fields.SchemaField({
identifier: new fields.StringField({ nullable: true, initial: null }),
name: new fields.StringField(),
img: new fields.StringField()
}),
/* Linked class is legacy. If we can safetely migrate it away at some point we could remove it */
linkedClass: new ForeignDocumentUUIDField({ type: 'Item', nullable: true, initial: null })
};

View file

@ -841,3 +841,11 @@ export function createShallowProxy(obj) {
}
});
}
export function camelize(str) {
return str
.replace(/(?:^\w|[A-Z]|\b\w)/g, (part, index) => {
return index === 0 ? part.toLowerCase() : part.toUpperCase();
})
.replace(/\s+/g, '');
}