Attribute Item Subtype #76
4 changed files with 56 additions and 5 deletions
|
|
@ -134,7 +134,8 @@
|
||||||
"missing-id": "An ID must be provided",
|
"missing-id": "An ID must be provided",
|
||||||
"invalid-socket": "Invalid socket data received, this means a module or system bug is present.",
|
"invalid-socket": "Invalid socket data received, this means a module or system bug is present.",
|
||||||
"unknown-socket-event": "An unknown socket event was received: {event}",
|
"unknown-socket-event": "An unknown socket event was received: {event}",
|
||||||
"duplicate-attribute-key": "Cannot create an Attribute with a key (\"{key}\") that already exists on the Actor"
|
"duplicate-attribute-key": "Cannot create an Attribute with a key (\"{key}\") that already exists on the Actor",
|
||||||
|
"invalid-attribute-key": "Attribute keys must be alphanumeric (a-z, 0-9) with underscores, invalid key provided: \"{key}\""
|
||||||
},
|
},
|
||||||
"warn": {
|
"warn": {
|
||||||
"migration-in-progress": "Applying data migrations for version {version}. Please do NOT refresh the window while this warning is present."
|
"migration-in-progress": "Applying data migrations for version {version}. Please do NOT refresh the window while this warning is present."
|
||||||
|
|
|
||||||
|
|
@ -5,11 +5,11 @@ import { PlayerSheet } from "./apps/PlayerSheet.mjs";
|
||||||
import { QueryStatus } from "./apps/QueryStatus.mjs";
|
import { QueryStatus } from "./apps/QueryStatus.mjs";
|
||||||
|
|
||||||
// Utils
|
// Utils
|
||||||
|
import { toID, isValidID, } from "./utils/toID.mjs";
|
||||||
import { attributeSorter } from "./utils/attributeSort.mjs";
|
import { attributeSorter } from "./utils/attributeSort.mjs";
|
||||||
import { DialogManager } from "./utils/DialogManager.mjs";
|
import { DialogManager } from "./utils/DialogManager.mjs";
|
||||||
import { localizer } from "./utils/localizer.mjs";
|
import { localizer } from "./utils/localizer.mjs";
|
||||||
import { QueryManager } from "./utils/QueryManager.mjs";
|
import { QueryManager } from "./utils/QueryManager.mjs";
|
||||||
import { toID } from "./utils/toID.mjs";
|
|
||||||
|
|
||||||
const { deepFreeze } = foundry.utils;
|
const { deepFreeze } = foundry.utils;
|
||||||
|
|
||||||
|
|
@ -26,5 +26,6 @@ export const api = deepFreeze({
|
||||||
attributeSorter,
|
attributeSorter,
|
||||||
localizer,
|
localizer,
|
||||||
toID,
|
toID,
|
||||||
|
isValidID,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,7 @@
|
||||||
|
import { isValidID, toID } from "../../utils/toID.mjs";
|
||||||
|
|
||||||
|
const { hasProperty } = foundry.utils;
|
||||||
|
|
||||||
export class AttributeItemData extends foundry.abstract.TypeDataModel {
|
export class AttributeItemData extends foundry.abstract.TypeDataModel {
|
||||||
// #region Schema
|
// #region Schema
|
||||||
static defineSchema() {
|
static defineSchema() {
|
||||||
|
|
@ -37,6 +41,17 @@ export class AttributeItemData extends foundry.abstract.TypeDataModel {
|
||||||
|
|
||||||
// #region Lifecycle
|
// #region Lifecycle
|
||||||
async _preCreate(data, options, user) {
|
async _preCreate(data, options, user) {
|
||||||
|
// Assign the key as the ID'd name if isn't provided, or validate if
|
||||||
|
// it is provided.
|
||||||
|
if (!this.key) {
|
||||||
|
this.updateSource({ key: toID(this.parent.name) });
|
||||||
|
} else if (!isValidID(this.key)) {
|
||||||
|
ui.notifications.error(_loc(
|
||||||
|
`taf.notifs.error.invalid-attribute-key`,
|
||||||
|
{ key: this.key },
|
||||||
|
));
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
// Prevent duplicate Attribute keys from existing on a single Actor
|
// Prevent duplicate Attribute keys from existing on a single Actor
|
||||||
if (this.parent.isEmbedded) {
|
if (this.parent.isEmbedded) {
|
||||||
|
|
@ -55,6 +70,19 @@ export class AttributeItemData extends foundry.abstract.TypeDataModel {
|
||||||
|
|
||||||
return super._preCreate(data, options, user);
|
return super._preCreate(data, options, user);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
async _preUpdate(data, options, user) {
|
||||||
|
// Prevent invalid IDs
|
||||||
|
if (hasProperty(data, `system.key`) && !isValidID(data.system.key)) {
|
||||||
|
ui.notifications.error(_loc(
|
||||||
|
`taf.notifs.error.invalid-attribute-key`,
|
||||||
|
{ key: data.system.key },
|
||||||
|
));
|
||||||
|
delete data.system?.key;
|
||||||
|
};
|
||||||
|
|
||||||
|
return super._preUpdate(data, options, user);
|
||||||
|
};
|
||||||
// #endregion Lifecycle
|
// #endregion Lifecycle
|
||||||
|
|
||||||
// #region Methods
|
// #region Methods
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
* A helper method that converts an arbitrary string into a format that can be
|
* A helper method that converts an arbitrary string into a format
|
||||||
* used as an object key easily.
|
* that can be used as an object key easily.
|
||||||
*
|
*
|
||||||
* @param {string} text The text to convert
|
* @param {string} text The text to convert
|
||||||
* @returns The converted ID
|
* @returns The converted ID
|
||||||
|
|
@ -9,5 +9,26 @@ export function toID(text) {
|
||||||
return text
|
return text
|
||||||
.toLowerCase()
|
.toLowerCase()
|
||||||
.replace(/\s+/g, `_`)
|
.replace(/\s+/g, `_`)
|
||||||
.replace(/\W/g, ``);
|
.replace(/\W/g, ``)
|
||||||
|
.replace(/(^_|_$)/);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A helper method that reports if an arbitrary string is considered a
|
||||||
|
* valid ID for use in the system
|
||||||
|
*
|
||||||
|
* @param {string} text The text to check
|
||||||
|
* @returns Whether or not the text is a valid ID
|
||||||
|
*/
|
||||||
|
export function isValidID(text) {
|
||||||
|
return !(
|
||||||
|
// any uppercase characters
|
||||||
|
text.match(/[A-Z]/)
|
||||||
|
|
||||||
|
// any non-word characters
|
||||||
|
|| text.match(/\W/)
|
||||||
|
|
||||||
|
// any whitespace characters
|
||||||
|
|| text.match(/\s/)
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue