-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
* Added application for assigning spells to source classes. Added needed loc keys. Added Tools button menu to character / npc spellbook tab toolbars. * Removed TidyHooks comment. That's not the right place or foundry hooks that I'm using but not broadcasting.
- Loading branch information
Showing
7 changed files
with
308 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
147 changes: 147 additions & 0 deletions
147
src/applications/spell-source-class-assignments/SpellSourceClassAssignments.svelte
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
<script lang="ts"> | ||
import type { Readable, Writable } from 'svelte/store'; | ||
import type { SpellSourceClassAssignmentsContext } from './SpellSourceClassAssignmentsFormApplication'; | ||
import { getContext } from 'svelte'; | ||
import { CONSTANTS } from 'src/constants'; | ||
import Search from 'src/components/utility-bar/Search.svelte'; | ||
import { FoundryAdapter } from 'src/foundry/foundry-adapter'; | ||
import TidyTable from 'src/components/table/TidyTable.svelte'; | ||
import type { Item5e } from 'src/types/item.types'; | ||
import TidyTableHeaderCell from 'src/components/table/TidyTableHeaderCell.svelte'; | ||
import TidyTableHeaderRow from 'src/components/table/TidyTableHeaderRow.svelte'; | ||
import TidyTableRow from 'src/components/table/TidyTableRow.svelte'; | ||
import TidyTableCell from 'src/components/table/TidyTableCell.svelte'; | ||
import TidySwitch from 'src/components/toggle/TidySwitch.svelte'; | ||
import TextInput from 'src/components/inputs/TextInput.svelte'; | ||
let context = getContext<Writable<SpellSourceClassAssignmentsContext>>( | ||
CONSTANTS.SVELTE_CONTEXT.CONTEXT, | ||
); | ||
let searchCriteria: string = ''; | ||
$: visibleSelectablesIdSubset = new Set<string>( | ||
$context.assignments | ||
.filter( | ||
(s) => | ||
searchCriteria.trim() === '' || | ||
s.item.name?.toLowerCase().includes(searchCriteria.toLowerCase()), | ||
) | ||
.map((d) => d.item.id), | ||
); | ||
$: classColumns = Object.entries<Item5e>( | ||
$context.actor.spellcastingClasses, | ||
).map(([key, value]) => ({ | ||
key: key, | ||
item: value, | ||
})); | ||
let gridTemplateColumns: string = ''; | ||
$: { | ||
let standardClassColumnWidth = '10rem'; | ||
let columns = '/* Spell Name */ minmax(200px, 1fr)'; | ||
classColumns.forEach((column) => { | ||
columns += ` /* ${column.item.name} */ ${standardClassColumnWidth}`; | ||
}); | ||
columns += ' /* Identifier */ 200px'; | ||
gridTemplateColumns = columns; | ||
} | ||
async function setItemSourceClass(item: Item5e, sourceClass: string) { | ||
await item.update({ | ||
'system.sourceClass': sourceClass, | ||
}); | ||
} | ||
const localize = FoundryAdapter.localize; | ||
var showUnassignedOnly = false; | ||
</script> | ||
|
||
<section class="flex-column small-gap full-height"> | ||
<div role="presentation" class="flex-row small-gap"> | ||
<Search bind:value={searchCriteria} /> | ||
<label class="flex-row extra-small-gap align-items-center"> | ||
<input type="checkbox" bind:checked={showUnassignedOnly} /> | ||
{localize('TIDY5E.SpellSourceClassAssignments.ShowUnassignedOnly.Text')} | ||
</label> | ||
</div> | ||
<div role="presentation" class="scroll-container flex-1"> | ||
<TidyTable | ||
key="spell-source-class-assignments-matrix" | ||
toggleable={false} | ||
--grid-template-columns={gridTemplateColumns} | ||
> | ||
<svelte:fragment slot="header"> | ||
<TidyTableHeaderRow> | ||
<TidyTableHeaderCell primary={true} class="p-1 capitalize"> | ||
{localize('DND5E.spell')} | ||
</TidyTableHeaderCell> | ||
{#each classColumns as classColumn} | ||
<TidyTableHeaderCell> | ||
{classColumn.item.name} | ||
</TidyTableHeaderCell> | ||
{/each} | ||
<TidyTableHeaderCell class="flex-row small-gap"> | ||
<span | ||
>{localize('TIDY5E.SpellSourceClassAssignments.Identifier')}</span | ||
> | ||
<i | ||
class="fas fa-question-circle" | ||
title={localize( | ||
'TIDY5E.SpellSourceClassAssignments.IdentifierHint', | ||
)} | ||
></i> | ||
</TidyTableHeaderCell> | ||
</TidyTableHeaderRow> | ||
</svelte:fragment> | ||
<svelte:fragment slot="body"> | ||
{#each $context.assignments as assignment (assignment.item.id)} | ||
{@const sourceClassIsUnassigned = | ||
(assignment.item.system.sourceClass?.trim() ?? '') === ''} | ||
{@const hideRow = | ||
!visibleSelectablesIdSubset.has(assignment.item.id) || | ||
(showUnassignedOnly && !sourceClassIsUnassigned)} | ||
<TidyTableRow hidden={hideRow}> | ||
<TidyTableCell primary={true} class="p-1 semibold"> | ||
<button | ||
type="button" | ||
class="inline-transparent-button highlight-on-hover" | ||
on:click={async () => | ||
FoundryAdapter.renderSheetFromUuid(assignment.item.uuid)} | ||
> | ||
{assignment.item.name} | ||
</button> | ||
</TidyTableCell> | ||
{#each classColumns as classColumn} | ||
{@const selected = | ||
assignment.item.system.sourceClass === classColumn.key} | ||
<TidyTableHeaderCell> | ||
<TidySwitch | ||
value={selected} | ||
on:change={() => | ||
setItemSourceClass( | ||
assignment.item, | ||
selected ? '' : classColumn.key, | ||
)} | ||
/> | ||
</TidyTableHeaderCell> | ||
{/each} | ||
<TidyTableCell> | ||
<TextInput | ||
document={assignment.item} | ||
disabled={!assignment.item.isOwner} | ||
field="system.sourceClass" | ||
selectOnFocus={true} | ||
value={assignment.item.system.sourceClass} | ||
/> | ||
</TidyTableCell> | ||
</TidyTableRow> | ||
{/each} | ||
</svelte:fragment> | ||
</TidyTable> | ||
</div> | ||
</section> |
87 changes: 87 additions & 0 deletions
87
...applications/spell-source-class-assignments/SpellSourceClassAssignmentsFormApplication.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
import type { SvelteComponent } from 'svelte'; | ||
import AssignSpellsToSourceClasses from './SpellSourceClassAssignments.svelte'; | ||
import SvelteFormApplicationBase from '../SvelteFormApplicationBase'; | ||
import type { Actor5e } from 'src/types/types'; | ||
import { writable, type Writable } from 'svelte/store'; | ||
import type { Item5e } from 'src/types/item.types'; | ||
import { CONSTANTS } from 'src/constants'; | ||
import { StoreSubscriptionsService } from 'src/features/store/StoreSubscriptionsService'; | ||
import { FoundryAdapter } from 'src/foundry/foundry-adapter'; | ||
|
||
export type SpellSourceClassAssignment = { | ||
/** | ||
* The spell to receive an assignment. | ||
*/ | ||
item: Item5e; | ||
/** | ||
* Represents the chosen source class. | ||
*/ | ||
sourceClass: string; | ||
}; | ||
|
||
export type SpellSourceClassAssignmentsContext = { | ||
actor: Actor5e; | ||
assignments: SpellSourceClassAssignment[]; | ||
}; | ||
|
||
export default class SpellSourceClassAssignmentsFormApplication extends SvelteFormApplicationBase { | ||
context: Writable<SpellSourceClassAssignmentsContext> = writable(); | ||
actor: Actor5e; | ||
subscriptionsService: StoreSubscriptionsService; | ||
updateHook: number | undefined; | ||
|
||
constructor(actor: Actor5e, ...args: any[]) { | ||
super(...args); | ||
this.actor = actor; | ||
this.subscriptionsService = new StoreSubscriptionsService(); | ||
} | ||
|
||
createComponent(node: HTMLElement): SvelteComponent { | ||
this.context.set(this.getData()); | ||
|
||
return new AssignSpellsToSourceClasses({ | ||
target: node, | ||
context: new Map<any, any>([ | ||
['appId', this.appId], | ||
['context', this.context], | ||
]), | ||
}); | ||
} | ||
|
||
getData(): SpellSourceClassAssignmentsContext { | ||
return { | ||
actor: this.actor, | ||
assignments: this.actor.items | ||
.filter((item: Item5e) => item.type === CONSTANTS.ITEM_TYPE_SPELL) | ||
.map((item: Item5e) => ({ | ||
item, | ||
sourceClass: 'test', | ||
})), | ||
}; | ||
} | ||
|
||
activateListeners(html: any): void { | ||
Hooks.off('updateItem', this.updateHook); | ||
this.trackActorChanges(); | ||
super.activateListeners(html); | ||
} | ||
|
||
private trackActorChanges() { | ||
this.updateHook = Hooks.on('updateItem', (item: Item5e) => { | ||
if (item.actor?.id !== this.actor.id) { | ||
return; | ||
} | ||
|
||
this.context.set(this.getData()); | ||
}); | ||
} | ||
|
||
get title() { | ||
return FoundryAdapter.localize('TIDY5E.Utilities.AssignSpellsToClasses'); | ||
} | ||
|
||
close(options: unknown = {}) { | ||
Hooks.off('updateItem', this.updateHook); | ||
return super.close(options); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters