Gisle Aune
2 years ago
9 changed files with 231 additions and 58 deletions
-
6frontend/src/lib/clients/sl3.ts
-
71frontend/src/lib/components/contexts/ItemMultiListContext.svelte
-
20frontend/src/lib/components/scope/ItemListRow.svelte
-
3frontend/src/lib/modals/ItemCreateModal.svelte
-
2frontend/src/lib/models/item.ts
-
56frontend/src/lib/utils/object.ts
-
119frontend/src/routes/[scope=prettyid]/overview.svelte
-
2models/item.go
-
8ports/mysql/items.go
@ -0,0 +1,71 @@ |
|||
<script lang="ts" context="module"> |
|||
const contextKey = {ctx: "itemMultiListContext"}; |
|||
|
|||
interface ItemMultiListContextData { |
|||
lists: Readable<Record<string, Item[]>>, |
|||
reloadItemLists(): void, |
|||
}; |
|||
|
|||
const fallback: ItemMultiListContextData = { |
|||
lists: readable({}), |
|||
reloadItemLists() {}, |
|||
} |
|||
|
|||
export function getItemMultiListContext() { |
|||
return getContext(contextKey) as ItemMultiListContextData || fallback |
|||
} |
|||
</script> |
|||
|
|||
<script lang="ts"> |
|||
import { readable, writable, type Readable } from "svelte/store"; |
|||
import { getContext, setContext } from "svelte"; |
|||
import type Item from "$lib/models/item"; |
|||
import type { ItemFilter } from "$lib/models/item"; |
|||
import { getScopeContext } from "./ScopeContext.svelte"; |
|||
import deepEqual from "$lib/utils/object"; |
|||
import { sl3 } from "$lib/clients/sl3"; |
|||
|
|||
const {scope} = getScopeContext(); |
|||
|
|||
export let lists: Record<string, Item[]> |
|||
export let filters: Record<string, ItemFilter> |
|||
|
|||
let loaded: Record<string, ItemFilter> = {...filters}; |
|||
let loading: Record<string, boolean> = {}; |
|||
const listsWritable = writable<Record<string, Item[]>>({...lists}); |
|||
|
|||
function reloadItemLists() { |
|||
loaded = {}; |
|||
} |
|||
|
|||
async function runLoad(key: string, filter: ItemFilter) { |
|||
loading = {...loading, [key]: true}; |
|||
|
|||
try { |
|||
const items = await sl3(fetch).listItems($scope.id, filter) |
|||
listsWritable.update(l => ({...l, [key.replace("Filter", "Items")]: items})); |
|||
} catch(_err) { |
|||
// TODO: Use err |
|||
} |
|||
|
|||
loading = {...loading, [key]: false}; |
|||
loaded = {...loaded, [key]: filter}; |
|||
} |
|||
|
|||
setContext<ItemMultiListContextData>(contextKey, { |
|||
lists: {subscribe: listsWritable.subscribe}, |
|||
reloadItemLists, |
|||
}); |
|||
|
|||
$: for (const key in filters) { |
|||
if (loading[key]) { |
|||
continue; |
|||
} |
|||
|
|||
if (loaded[key] == null || !deepEqual(filters[key], loaded[key])) { |
|||
runLoad(key, {...filters[key]}) |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<slot></slot> |
@ -0,0 +1,20 @@ |
|||
<script lang="ts"> |
|||
import { getItemMultiListContext } from "../contexts/ItemMultiListContext.svelte"; |
|||
import Row from "../layout/Row.svelte"; |
|||
import ItemSubSection from "../project/ItemSubSection.svelte"; |
|||
|
|||
export let key: string; |
|||
export let title: string; |
|||
export let showAcquiredTime: boolean = false; |
|||
|
|||
const {lists} = getItemMultiListContext(); |
|||
</script> |
|||
|
|||
|
|||
{#if ($lists[key]||[]).length > 0} |
|||
<Row title={title}> |
|||
{#each $lists[key] as item (item.id)} |
|||
<ItemSubSection showAcquiredTime={showAcquiredTime} item={item} /> |
|||
{/each} |
|||
</Row> |
|||
{/if} |
@ -0,0 +1,56 @@ |
|||
export default function deepEqual(a: Object, b: Object) { |
|||
if (a === void(0)) { |
|||
if (b !== void(0)) { |
|||
return false; |
|||
} |
|||
return true; |
|||
} |
|||
if (a === null) { |
|||
if (b !== null) { |
|||
return false; |
|||
} |
|||
return true; |
|||
} |
|||
|
|||
if (a instanceof Date) { |
|||
if (b instanceof Date) { |
|||
b = b.toISOString(); |
|||
} |
|||
a = a.toISOString(); |
|||
|
|||
return a === b; |
|||
} |
|||
|
|||
if (Array.isArray(a)) { |
|||
if (!Array.isArray(b) || b.length !== a.length) { |
|||
return false; |
|||
} |
|||
|
|||
for (let i = 0; i < a.length; i++) { |
|||
if (!deepEqual(a[i], b[i])) { |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
|
|||
if (typeof(a) === "object") { |
|||
if (typeof(b) !== "object") { |
|||
return false; |
|||
} |
|||
|
|||
for (const key in a) { |
|||
if (!a.hasOwnProperty(key)) { |
|||
continue |
|||
} |
|||
if (!deepEqual(a[key], b[key])) { |
|||
return false |
|||
} |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
|
|||
return a === b; |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue