Support rudimentary adding outfits
This commit is contained in:
parent
ac9cc6f78f
commit
93530781ba
7 changed files with 102 additions and 20 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -10,6 +10,9 @@
|
|||
*.userosscache
|
||||
*.sln.docstates
|
||||
|
||||
# Mac crap
|
||||
.DS_Store
|
||||
|
||||
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||
*.userprefs
|
||||
|
||||
|
|
|
|||
19
src/web/package-lock.json
generated
19
src/web/package-lock.json
generated
|
|
@ -17,6 +17,7 @@
|
|||
"devDependencies": {
|
||||
"@sveltejs/vite-plugin-svelte": "^2.0.2",
|
||||
"@tsconfig/svelte": "^3.0.0",
|
||||
"@types/bootstrap": "^5.2.6",
|
||||
"sass": "^1.58.3",
|
||||
"svelte": "^3.55.1",
|
||||
"svelte-check": "^2.10.3",
|
||||
|
|
@ -474,6 +475,15 @@
|
|||
"integrity": "sha512-pYrtLtOwku/7r1i9AMONsJMVYAtk3hzOfiGNekhtq5tYBGA7unMve8RvUclKLMT3PrihvJqUmzsRGh0RP84hKg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/bootstrap": {
|
||||
"version": "5.2.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/bootstrap/-/bootstrap-5.2.6.tgz",
|
||||
"integrity": "sha512-BlAc3YATdasbHoxMoBWODrSF6qwQO/E9X8wVxCCSa6rWjnaZfpkr2N6pUMCY6jj2+wf0muUtLySbvU9etX6YqA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@popperjs/core": "^2.9.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/pug": {
|
||||
"version": "2.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/pug/-/pug-2.0.6.tgz",
|
||||
|
|
@ -1833,6 +1843,15 @@
|
|||
"integrity": "sha512-pYrtLtOwku/7r1i9AMONsJMVYAtk3hzOfiGNekhtq5tYBGA7unMve8RvUclKLMT3PrihvJqUmzsRGh0RP84hKg==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/bootstrap": {
|
||||
"version": "5.2.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/bootstrap/-/bootstrap-5.2.6.tgz",
|
||||
"integrity": "sha512-BlAc3YATdasbHoxMoBWODrSF6qwQO/E9X8wVxCCSa6rWjnaZfpkr2N6pUMCY6jj2+wf0muUtLySbvU9etX6YqA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@popperjs/core": "^2.9.2"
|
||||
}
|
||||
},
|
||||
"@types/pug": {
|
||||
"version": "2.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/pug/-/pug-2.0.6.tgz",
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
"devDependencies": {
|
||||
"@sveltejs/vite-plugin-svelte": "^2.0.2",
|
||||
"@tsconfig/svelte": "^3.0.0",
|
||||
"@types/bootstrap": "^5.2.6",
|
||||
"sass": "^1.58.3",
|
||||
"svelte": "^3.55.1",
|
||||
"svelte-check": "^2.10.3",
|
||||
|
|
|
|||
|
|
@ -106,14 +106,9 @@
|
|||
/>
|
||||
</Route>
|
||||
<Route fallback>
|
||||
<div
|
||||
class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom"
|
||||
>
|
||||
<h1 class="h2">Outfits</h1>
|
||||
</div>
|
||||
{#if state.outfits}
|
||||
<OutfitTable
|
||||
toggleFavorite={(outfitName) => {
|
||||
toggleFavorite={outfitName => {
|
||||
let outfit = state.outfits.find(
|
||||
(item) => item.name == outfitName
|
||||
);
|
||||
|
|
@ -125,6 +120,11 @@
|
|||
}
|
||||
changedState();
|
||||
}}
|
||||
createOutfit={newOutfitName => {
|
||||
state.outfits = [...state.outfits, {
|
||||
name: newOutfitName
|
||||
}]
|
||||
}}
|
||||
outfits={[...state.outfits].sort((a, b) =>
|
||||
a.name.localeCompare(b.name)
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@
|
|||
let response = await fetch("/api/armors/search?" + params);
|
||||
let response_json: ArmorInfo[] = await response.json();
|
||||
response_json.length = 100;
|
||||
// console.log(response_json);
|
||||
return response_json;
|
||||
}
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@
|
|||
resolveLocator = (locator) => undefined;
|
||||
async function updateArmorInfo() {
|
||||
allArmorInfo = await Promise.all(
|
||||
outfit.armors.map((armor) => dataForLocator(armor))
|
||||
(outfit.armors ?? []).map((armor) => dataForLocator(armor))
|
||||
);
|
||||
allArmorInfoMap = allArmorInfo.reduce((map, item) => {
|
||||
// @ts-ignore
|
||||
|
|
@ -66,7 +66,7 @@
|
|||
onMount(async () => await updateArmorInfo());
|
||||
$: {
|
||||
// @ts-ignore
|
||||
outfit.armor; // Name it here so that Svelte knows we depend on it
|
||||
(outfit.armors ?? []); // Name it here so that Svelte knows we depend on it
|
||||
updateArmorInfo();
|
||||
}
|
||||
</script>
|
||||
|
|
@ -138,14 +138,14 @@
|
|||
|
||||
<ArmorSearch
|
||||
onAdd={(armor) => {
|
||||
outfit.armors = outfit.armors.filter(
|
||||
outfit.armors = (outfit.armors ?? []).filter(
|
||||
(otherLoc) =>
|
||||
!masksConflict(
|
||||
resolveLocator(otherLoc)?.mask,
|
||||
armor.mask
|
||||
)
|
||||
);
|
||||
outfit.armors = outfit.armors.concat([armor.locator]);
|
||||
outfit.armors = (outfit.armors ?? []).concat([armor.locator]);
|
||||
}}
|
||||
existingArmors={allArmorInfo}
|
||||
/>
|
||||
|
|
@ -153,7 +153,7 @@
|
|||
<div class="mb-3">
|
||||
<label class="form-label" for="outfitItemsList">Outfit Items</label>
|
||||
<div id="outfitItemsList" class="list-group">
|
||||
{#each typedClone(outfit.armors).sort((a, b) => (resolveLocator(a)?.mask ?? 0 + resolveLocator(a)?.name?.length ?? 0) - (resolveLocator(b)?.mask ?? 0 + resolveLocator(b)?.name?.length ?? 0)) as armor}
|
||||
{#each typedClone((outfit.armors ?? [])).sort((a, b) => (resolveLocator(a)?.mask ?? 0 + resolveLocator(a)?.name?.length ?? 0) - (resolveLocator(b)?.mask ?? 0 + resolveLocator(b)?.name?.length ?? 0)) as armor}
|
||||
<div class="list-group-item">
|
||||
<div class="d-flex w-100 justify-content-between">
|
||||
<h5 style="--bs-breadcrumb-divider: '—';">
|
||||
|
|
@ -174,7 +174,7 @@
|
|||
<button
|
||||
class="btn btn-outline-danger btn-sm"
|
||||
on:click|preventDefault={() => {
|
||||
outfit.armors = outfit.armors.filter(
|
||||
outfit.armors = (outfit.armors ?? []).filter(
|
||||
(item) => !_.isEqual(item, armor)
|
||||
);
|
||||
}}>Remove</button
|
||||
|
|
@ -207,7 +207,7 @@
|
|||
>Slot Policies</label
|
||||
>
|
||||
<div id="slotPoliciesList" class="list-group">
|
||||
{#each Object.keys(outfit.slotPolicies).map( (value) => parseInt(value) ) as slot}
|
||||
{#each Object.keys(outfit.slotPolicies ?? {}).map( (value) => parseInt(value) ) as slot}
|
||||
<div class="list-group-item">
|
||||
<div class="d-flex justify-content-between">
|
||||
<h5>{slot} - {slotNames[slot]}</h5>
|
||||
|
|
@ -256,7 +256,7 @@
|
|||
bind:value={newSlotPolicySlot}
|
||||
>
|
||||
{#each Object.keys(slotNames)
|
||||
.filter((slot) => !Object.keys(outfit.slotPolicies).find((other) => other == slot))
|
||||
.filter((slot) => !Object.keys(outfit.slotPolicies ?? {}).find((other) => other == slot))
|
||||
.map((value) => parseInt(value)) as slot}
|
||||
<option value={slot}>
|
||||
{slot} - {slotNames[slot]}
|
||||
|
|
@ -287,8 +287,7 @@
|
|||
<button
|
||||
class="btn btn-outline-success btn-sm"
|
||||
on:click|preventDefault={() => {
|
||||
outfit.slotPolicies[newSlotPolicySlot] =
|
||||
newSlotPolicyValue;
|
||||
outfit.slotPolicies = {[newSlotPolicySlot]: newSlotPolicyValue, ...(outfit.slotPolicies ?? {})};
|
||||
}}>Add</button
|
||||
>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,10 +1,71 @@
|
|||
<script lang="ts">
|
||||
import { link } from "svelte-navigator";
|
||||
import type {Outfit} from "./APITypes";
|
||||
import { link } from "svelte-navigator";
|
||||
import type { Outfit } from "./APITypes";
|
||||
import { Modal } from 'bootstrap';
|
||||
export let outfits: Outfit[];
|
||||
export let toggleFavorite: (outfitName: string) => void;
|
||||
export let createOutfit: (outfitName: string) => void
|
||||
|
||||
let newOutfitName: string = "";
|
||||
let newOutfitAllowed = false;
|
||||
let modalElement: Element | undefined;
|
||||
var modal: Modal | undefined;
|
||||
$: {
|
||||
if (modalElement) {
|
||||
modal = new Modal(modalElement);
|
||||
}
|
||||
}
|
||||
function openModel() {
|
||||
newOutfitName = "";
|
||||
modal.show();
|
||||
}
|
||||
function createOutfitHandler() {
|
||||
createOutfit(newOutfitName);
|
||||
modal.hide();
|
||||
}
|
||||
|
||||
// Comment this out when not hacking on modal.
|
||||
// setTimeout(openModel, 0.1);
|
||||
$: {
|
||||
newOutfitAllowed = !(newOutfitName === "" || outfits.find(outfit => outfit.name.toLocaleLowerCase() === newOutfitName.toLocaleLowerCase()));
|
||||
}
|
||||
</script>
|
||||
|
||||
<div
|
||||
class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom"
|
||||
>
|
||||
<h1 class="h2">Outfits</h1>
|
||||
<div class="btn-group me-2">
|
||||
<button type="button" class="btn btn-outline-primary btn-sm" on:click={() => openModel()}
|
||||
>New Outfit</button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal fade" id="exampleModal" bind:this={modalElement} tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h1 class="modal-title fs-5" id="exampleModalLabel">New Outfit</h1>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form>
|
||||
<div class="mb-3">
|
||||
<label for="newOutfitName" class="form-label">Outfit Name</label>
|
||||
<input type="email" class="form-control" id="newOutfitName" bind:value={newOutfitName} aria-describedby="name">
|
||||
<div id="emailHelp" class="form-text">This name must be unique.</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
|
||||
<button type="button" class="btn btn-primary {newOutfitAllowed ? "" : "disabled"}" on:click={createOutfitHandler}>Create Outfit</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-sm">
|
||||
<thead>
|
||||
|
|
@ -27,7 +88,7 @@
|
|||
/>
|
||||
</td>
|
||||
<td>{outfit.name}</td>
|
||||
<td>{outfit.armors.length}</td>
|
||||
<td>{outfit.armors?.length ?? 0}</td>
|
||||
<td />
|
||||
<td>
|
||||
<a href="/outfits/{outfit.name}" use:link>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue