Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
8fbbb4f788
|
|||
|
e6e8ae4f3f
|
|||
|
fb9eeba103
|
|||
|
04aee6e44c
|
|||
|
3fdaadf7e0
|
|||
|
4cd01570f7
|
|||
|
a9ba4f27ff
|
|||
|
1d698c0ef1
|
|||
|
07db5da750
|
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
src/packs/** binary
|
||||||
22
src/main.js
22
src/main.js
@@ -8,7 +8,8 @@ export class AscAssetManager {
|
|||||||
static TEMPLATES = {
|
static TEMPLATES = {
|
||||||
UPLOAD_CHOOSE:`modules/${this.ID}/templates/upload-choose.hbs`,
|
UPLOAD_CHOOSE:`modules/${this.ID}/templates/upload-choose.hbs`,
|
||||||
UPLOAD_FORM:`modules/${this.ID}/templates/upload-form.hbs`,
|
UPLOAD_FORM:`modules/${this.ID}/templates/upload-form.hbs`,
|
||||||
SETTINGS_MENU_MACRO:`modules/${this.ID}/templates/settings-menu-macro.hbs`
|
SETTINGS_MENU_MACRO:`modules/${this.ID}/templates/settings-menu-macro.hbs`,
|
||||||
|
SETTINGS_TAGS_AND_CATEGORIES:`modules/${this.ID}/templates/settings-tags-and-categories.hbs`
|
||||||
}
|
}
|
||||||
|
|
||||||
static getDirectory () {
|
static getDirectory () {
|
||||||
@@ -35,11 +36,20 @@ export class AscAssetManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Hooks.on('init', ()=>CONFIG.debug.hooks = true)
|
Hooks.on('init', ()=>{
|
||||||
|
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
Hooks.on("ready", function() {
|
Hooks.on("ready", function() {
|
||||||
AscAssetManager.log(false, "Deno nodule reody")
|
|
||||||
registerSettings(AscAssetManager);
|
registerSettings(AscAssetManager);
|
||||||
|
const DEBUG = game.settings.get(AscAssetManager.ID, "enableDebugMode")
|
||||||
|
if (DEBUG) {
|
||||||
|
AscAssetManager.log(false, "Debug Mode Enabled")
|
||||||
|
CONFIG.debug.hooks = true
|
||||||
|
}
|
||||||
|
AscAssetManager.log(false, "Deno nodule reody")
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
Hooks.on("ascAssetManager.renderUploadChoose", (data={}) => {
|
Hooks.on("ascAssetManager.renderUploadChoose", (data={}) => {
|
||||||
@@ -139,7 +149,11 @@ Hooks.on("renderHotbar", ({macros}, html) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
Hooks.on("ascAssetManager.renderUploadForm", (data={})=>{
|
Hooks.on("ascAssetManager.renderUploadForm", (data={})=>{
|
||||||
const templateData = {moduleId: AscAssetManager.ID, fileCategories: AscAssetManager.fileCategories, fileTags: AscAssetManager.fileTags}
|
const templateData = {
|
||||||
|
moduleId: AscAssetManager.ID,
|
||||||
|
fileCategories: game.settings.get(AscAssetManager.ID, "categories"),
|
||||||
|
fileTags: game.settings.get(AscAssetManager.ID, "tags")
|
||||||
|
}
|
||||||
renderTemplate(AscAssetManager.TEMPLATES.UPLOAD_FORM, templateData).then(content => {
|
renderTemplate(AscAssetManager.TEMPLATES.UPLOAD_FORM, templateData).then(content => {
|
||||||
let {file} = data
|
let {file} = data
|
||||||
const dialog = new Dialog({
|
const dialog = new Dialog({
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
{
|
{
|
||||||
"id": "asc-asset-manager",
|
"id": "asc-asset-manager",
|
||||||
"title": "asc-asset-manager",
|
"title": "Asset Manager",
|
||||||
"version": "0.1.0",
|
"version": "0.2.1",
|
||||||
|
"download": "https://gitea.ascorrea.com/asc/asc-asset-manager/releases/download/0.2.1/module.zip",
|
||||||
|
"manifest": "https://gitea.ascorrea.com/asc/asc-asset-manager/releases/download/latest/module.json",
|
||||||
"compatibility": {
|
"compatibility": {
|
||||||
"minimum": "12",
|
"minimum": "12",
|
||||||
"verified": "12"
|
"verified": "12.331"
|
||||||
},
|
},
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
{
|
||||||
|
|||||||
Binary file not shown.
@@ -1 +1 @@
|
|||||||
MANIFEST-000010
|
MANIFEST-000039
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
2025/01/19-15:09:29.737471 17359b000 Recovering log #9
|
2025/01/29-15:45:18.681004 30ad38000 Recovering log #38
|
||||||
2025/01/19-15:09:29.737887 17359b000 Delete type=3 #7
|
2025/01/29-15:45:18.681277 30ad38000 Delete type=0 #38
|
||||||
2025/01/19-15:09:29.737973 17359b000 Delete type=0 #9
|
2025/01/29-15:45:18.681298 30ad38000 Delete type=3 #37
|
||||||
|
2025/01/29-15:46:39.436862 310dbb000 Level-0 table #42: started
|
||||||
|
2025/01/29-15:46:39.436930 310dbb000 Level-0 table #42: 0 bytes OK
|
||||||
|
2025/01/29-15:46:39.437031 310dbb000 Delete type=0 #40
|
||||||
|
2025/01/29-15:46:39.437558 310dbb000 Manual compaction at level-0 from '!macros!rdl3Dw3jRkibnQQC' @ 72057594037927935 : 1 .. '!macros!rdl3Dw3jRkibnQQC' @ 0 : 0; will stop at (end)
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
2025/01/19-15:04:17.219781 17397b000 Recovering log #6
|
2025/01/27-20:40:12.716406 16fa73000 Recovering log #35
|
||||||
2025/01/19-15:04:17.219809 17397b000 Level-0 table #8: started
|
2025/01/27-20:40:12.716718 16fa73000 Delete type=3 #33
|
||||||
2025/01/19-15:04:17.219961 17397b000 Level-0 table #8: 634 bytes OK
|
2025/01/27-20:40:12.716753 16fa73000 Delete type=0 #35
|
||||||
2025/01/19-15:04:17.220279 17397b000 Delete type=0 #6
|
|
||||||
2025/01/19-15:04:17.220330 17397b000 Delete type=3 #4
|
|
||||||
|
|||||||
Binary file not shown.
BIN
src/packs/asc-asset-manager-macros/MANIFEST-000039
Normal file
BIN
src/packs/asc-asset-manager-macros/MANIFEST-000039
Normal file
Binary file not shown.
210
src/settings.js
210
src/settings.js
@@ -3,18 +3,54 @@ export function registerSettings(AscAssetManager) {
|
|||||||
const ID = AscAssetManager.ID
|
const ID = AscAssetManager.ID
|
||||||
//<a class="content-link" draggable="true" data-link="" data-uuid="Item.VF90ijwtDojmEQE5" data-id="VF90ijwtDojmEQE5" data-type="Item" data-tooltip="Ability Item"><i class="fas fa-suitcase"></i>Ability</a>
|
//<a class="content-link" draggable="true" data-link="" data-uuid="Item.VF90ijwtDojmEQE5" data-id="VF90ijwtDojmEQE5" data-type="Item" data-tooltip="Ability Item"><i class="fas fa-suitcase"></i>Ability</a>
|
||||||
// Register the "enableFeature" setting
|
// Register the "enableFeature" setting
|
||||||
game.settings.register(ID, "enableFeature", {
|
game.settings.register(ID, "enableDebugMode", {
|
||||||
name: "Enable Feature",
|
name: "Enable Debug Mode",
|
||||||
hint: "Enable or disable the special feature of this module.",
|
hint: "Enable or disable debug mode for this module. When enabled, additional debugging information will be logged to the console.",
|
||||||
scope: "world",
|
scope: "world",
|
||||||
config: true,
|
config: true,
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true,
|
requiresReload: true,
|
||||||
|
default: false,
|
||||||
onChange: value => {
|
onChange: value => {
|
||||||
console.log(`Enable Feature setting changed to: ${value}`);
|
console.log(`Debug Mode setting changed to: ${value}`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Register default tags setting
|
||||||
|
game.settings.register(ID, "tags", {
|
||||||
|
name: "Tags",
|
||||||
|
hint: "A list of tags to use in the module.",
|
||||||
|
scope: "world", // "world" means the setting is shared across all users; "client" means it's per-user
|
||||||
|
config: false, // Whether the setting shows up in the settings menu
|
||||||
|
type: Object, // Data type
|
||||||
|
default: [
|
||||||
|
{id:"tk", label: "Token"},
|
||||||
|
{id:"sq", label: "Square"}
|
||||||
|
], // Default tags
|
||||||
|
onChange: (value) => console.log("Tags updated to:", value) // Optional: Triggered when setting is updated
|
||||||
|
});
|
||||||
|
|
||||||
|
// Register default categories setting
|
||||||
|
game.settings.register(ID, "categories", {
|
||||||
|
name: "Categories",
|
||||||
|
hint: "A list of categories to use in the module.",
|
||||||
|
scope: "world",
|
||||||
|
config: false,
|
||||||
|
type: Object,
|
||||||
|
default: [
|
||||||
|
{id: "npcn", label: "NPC (Named)"},
|
||||||
|
{id: "npcu", label: "NPC (Unnamed)"},
|
||||||
|
{id: "scene", label: "Scene Background"},
|
||||||
|
{id: "pc", label: "PC"},
|
||||||
|
{id: "inset", label: "Inset"},
|
||||||
|
{id: "vehicle", label: "Vehicle"},
|
||||||
|
{id: "weapon", label: "Weapon"},
|
||||||
|
{id: "icon", label: "Icon"},
|
||||||
|
{id: "map", label: "Map"}
|
||||||
|
],
|
||||||
|
onChange: (value) => console.log("Categories updated to:", value)
|
||||||
|
});
|
||||||
|
|
||||||
// Register the "customMessage" setting
|
// Register the "customMessage" setting
|
||||||
game.settings.register(ID, "rootDirectory", {
|
game.settings.register(ID, "rootDirectory", {
|
||||||
name: "Root Directory",
|
name: "Root Directory",
|
||||||
@@ -29,24 +65,6 @@ export function registerSettings(AscAssetManager) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Register a dropdown setting
|
|
||||||
game.settings.register(ID, "theme", {
|
|
||||||
name: "Select Theme",
|
|
||||||
hint: "Choose a theme for the module.",
|
|
||||||
scope: "world",
|
|
||||||
config: true,
|
|
||||||
type: String,
|
|
||||||
choices: {
|
|
||||||
light: "Light Theme",
|
|
||||||
dark: "Dark Theme",
|
|
||||||
system: "Use System Default"
|
|
||||||
},
|
|
||||||
default: "system",
|
|
||||||
onChange: value => {
|
|
||||||
console.log(`Theme changed to: ${value}`);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
game.settings.registerMenu(ID, "instructions", {
|
game.settings.registerMenu(ID, "instructions", {
|
||||||
name: "Add macro to hotbar",
|
name: "Add macro to hotbar",
|
||||||
label: "Get Macro",
|
label: "Get Macro",
|
||||||
@@ -55,7 +73,7 @@ export function registerSettings(AscAssetManager) {
|
|||||||
config: true,
|
config: true,
|
||||||
type: class extends FormApplication {
|
type: class extends FormApplication {
|
||||||
static get defaultOptions() {
|
static get defaultOptions() {
|
||||||
return mergeObject(super.defaultOptions, {
|
return foundry.utils.FormApplicationmergeObject(super.defaultOptions, {
|
||||||
id: ID, // Unique ID for the application
|
id: ID, // Unique ID for the application
|
||||||
title: "Simple Form Application", // Title of the window
|
title: "Simple Form Application", // Title of the window
|
||||||
template: AscAssetManager.TEMPLATES.SETTINGS_MENU_MACRO, // Path to your Handlebars template
|
template: AscAssetManager.TEMPLATES.SETTINGS_MENU_MACRO, // Path to your Handlebars template
|
||||||
@@ -72,4 +90,148 @@ export function registerSettings(AscAssetManager) {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
game.settings.registerMenu(ID, "categories", {
|
||||||
|
name: "Set Tags and Categories",
|
||||||
|
label: "Set Tags and Categories",
|
||||||
|
scope: "world",
|
||||||
|
icon: "fas fa-list",
|
||||||
|
config: true,
|
||||||
|
type: class extends FormApplication {
|
||||||
|
static get defaultOptions() {
|
||||||
|
return foundry.utils.mergeObject(super.defaultOptions, {
|
||||||
|
id: ID, // Unique ID for the application
|
||||||
|
title: "Simple Form Application", // Title of the window
|
||||||
|
template: AscAssetManager.TEMPLATES.SETTINGS_TAGS_AND_CATEGORIES, // Path to your Handlebars template
|
||||||
|
width: 300, // Width of the form
|
||||||
|
height: "auto", // Adjust height automatically
|
||||||
|
});
|
||||||
|
}
|
||||||
|
getData() {
|
||||||
|
return {
|
||||||
|
moduleId: ID,
|
||||||
|
categories: game.settings.get(ID, "categories"),
|
||||||
|
tags: game.settings.get(ID, "tags")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
activateListeners(html) {
|
||||||
|
super.activateListeners(html);
|
||||||
|
|
||||||
|
function addRow (html) {
|
||||||
|
// Find the nearest parent div
|
||||||
|
const parentDiv = html.closest("div:has(table)");
|
||||||
|
|
||||||
|
// Find the last row in the body
|
||||||
|
const lastRow = parentDiv.find("tbody tr:last");
|
||||||
|
|
||||||
|
// Clone the last row
|
||||||
|
const newRow = lastRow.clone();
|
||||||
|
|
||||||
|
// Loop through each input in the new row to reset values and update names/ids
|
||||||
|
newRow.find("input").each(function () {
|
||||||
|
const input = $(this);
|
||||||
|
|
||||||
|
// Reset the input value
|
||||||
|
input.val("");
|
||||||
|
|
||||||
|
// Update the name and id to n+1
|
||||||
|
const name = input.attr("name");
|
||||||
|
const id = input.attr("id");
|
||||||
|
|
||||||
|
if (name) {
|
||||||
|
const match = name.match(/(\d+)/); // Find the index in the name
|
||||||
|
if (match) {
|
||||||
|
const index = parseInt(match[1], 10) + 1;
|
||||||
|
input.attr("name", name.replace(/\d+/, index));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (id) {
|
||||||
|
const match = id.match(/(\d+)/); // Find the index in the id
|
||||||
|
if (match) {
|
||||||
|
const index = parseInt(match[1], 10) + 1;
|
||||||
|
input.attr("id", id.replace(/\d+/, index));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Append the new row to the table
|
||||||
|
parentDiv.find("tbody").append(newRow);
|
||||||
|
}
|
||||||
|
|
||||||
|
html.find('#add-category, #add-tag').click((evt)=>{
|
||||||
|
evt.preventDefault()
|
||||||
|
addRow($(evt.currentTarget));
|
||||||
|
})
|
||||||
|
html.find('#reset-category, #reset-tag').click((evt)=>{
|
||||||
|
evt.preventDefault()
|
||||||
|
let data
|
||||||
|
let item_id
|
||||||
|
if (evt.currentTarget.id == "reset-category"){
|
||||||
|
item_id = "category"
|
||||||
|
data = game.settings.settings.get(`${ID}.categories`).default
|
||||||
|
} else if (evt.currentTarget.id == "reset-tag") {
|
||||||
|
item_id = "tag"
|
||||||
|
data = game.settings.settings.get(`${ID}.tags`).default
|
||||||
|
}
|
||||||
|
const tbody = $(evt.currentTarget).closest('div:has(table)').find("tbody")
|
||||||
|
tbody.empty();
|
||||||
|
for (let [idx, {id, label}] of data.entries()){
|
||||||
|
const newRow = $(`<tr></tr>`)
|
||||||
|
newRow.append(`<td><input type="text" name="${item_id}-id-${idx}" value="${id}"></input></td>`)
|
||||||
|
newRow.append(`<td><input type="text" name="${item_id}-label-${idx}" value="${label}"></input></td>`)
|
||||||
|
newRow.append(`<td><button id="delete-row-${idx}" class="delete-row"><i class="delete-row fa-solid fa-trash-can"></i></button></td>`)
|
||||||
|
tbody.append(newRow)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
html.find('.delete-row').click((evt)=>{
|
||||||
|
evt.preventDefault();
|
||||||
|
const button = $(evt.currentTarget)
|
||||||
|
button.closest('tr').remove()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async _updateObject(event, formData) {
|
||||||
|
// Save updates when the form is submitted
|
||||||
|
|
||||||
|
const categories = [];
|
||||||
|
const tags = [];
|
||||||
|
|
||||||
|
// Dynamically group rows for categories and tags
|
||||||
|
for (const [key, value] of Object.entries(formData)) {
|
||||||
|
// Match category rows
|
||||||
|
const categoryMatch = key.match(/^category-(id|label)-(\d+)$/);
|
||||||
|
if (categoryMatch) {
|
||||||
|
const [_, field, index] = categoryMatch; // Extract field (id/label) and index
|
||||||
|
const i = parseInt(index);
|
||||||
|
|
||||||
|
// Ensure the index exists in the categories array
|
||||||
|
if (!categories[i]) categories[i] = { id: "", label: "" };
|
||||||
|
categories[i][field] = value;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Match tag rows
|
||||||
|
const tagMatch = key.match(/^tag-(id|label)-(\d+)$/);
|
||||||
|
if (tagMatch) {
|
||||||
|
const [_, field, index] = tagMatch; // Extract field (id/label) and index
|
||||||
|
const i = parseInt(index);
|
||||||
|
|
||||||
|
// Ensure the index exists in the tags array
|
||||||
|
if (!tags[i]) tags[i] = { id: "", label: "" };
|
||||||
|
tags[i][field] = value;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await game.settings.set(ID, "tags", tags);
|
||||||
|
await game.settings.set(ID, "categories", categories);
|
||||||
|
|
||||||
|
ui.notifications.info("Settings updated!");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
game
|
||||||
|
|
||||||
}
|
}
|
||||||
44
src/templates/settings-tags-and-categories.hbs
Normal file
44
src/templates/settings-tags-and-categories.hbs
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
{{#*inline "table"}}
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr><th colspan=3>{{collection_title}}</th></tr>
|
||||||
|
<tr>
|
||||||
|
<th>ID</th>
|
||||||
|
<th>Label</th>
|
||||||
|
<th></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{{#each collection}}
|
||||||
|
<tr>
|
||||||
|
<td><input type="text" name="{{../item_id}}-id-{{@index}}" value="{{id}}"></input></td>
|
||||||
|
<td><input type="text" name="{{../item_id}}-label-{{@index}}" value="{{label}}"></input></td>
|
||||||
|
<td><button id="delete-row-{{@index}}" class="delete-row"><i class="delete-row fa-solid fa-trash-can"></i></button></td>
|
||||||
|
</tr>
|
||||||
|
{{else}}
|
||||||
|
<tr>
|
||||||
|
<td><input type="text" name="{{../item_id}}-id-0" value="" placeholder="id"></input></td>
|
||||||
|
<td><input type="text" name="{{../item_id}}-label-0" value="" placeholder="label"></input></td>
|
||||||
|
<td><button id="delete-row-0" class="delete-row"><i class="delete-row fa-solid fa-trash-can"></i></button></td>
|
||||||
|
</tr>
|
||||||
|
{{/each}}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<div class="dialog-buttons">
|
||||||
|
<button id="add-{{item_id}}" class="dialog-button"><i class="fa-solid fa-plus"></i>Add {{item_title}}</button>
|
||||||
|
<button id="reset-{{item_id}}" class="dialog-button"><i class="fa-solid fa-arrow-rotate-left"></i>Reset {{collection_ttitle}}</button>
|
||||||
|
</div>
|
||||||
|
{{/inline}}
|
||||||
|
<div class="{{moduleId}}">
|
||||||
|
<form id="form-categories-and-tags">
|
||||||
|
<div>
|
||||||
|
{{> table collection_title="Categories" item_title="Category" collection=categories item_id="category"}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
{{> table collection_title="Tags" item_title="Tag" collection=tags item_id="tag"}}
|
||||||
|
</div>
|
||||||
|
<hr>
|
||||||
|
<button id="save" class="dialog-button"><i class="fa-solid fa-check"></i> Save</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
Reference in New Issue
Block a user