fix(dashboard): dont use same indexes per page

changing the accordion to individual collapses meant we could implement keyboard navigation between the cards

however, I only handled card collapsing state per-page, which caused an issue where opening one card on one page would open the card with the same index on every page

this fixes that by indexing the cards based on its position in the whole list rather than per-page
This commit is contained in:
Jake/Rads 2022-06-27 14:45:04 +02:00
parent ce431364a0
commit 7ee5bba14c
5 changed files with 25 additions and 20 deletions

View File

@ -20,9 +20,13 @@
export let isPublic: boolean; export let isPublic: boolean;
export let itemType: string; export let itemType: string;
export let isMainDash: boolean; export let isMainDash: boolean;
export let itemsPerPage: number;
export let currentPage: number;
export let openByDefault = false; export let openByDefault = false;
$: indexStart = itemsPerPage * (currentPage - 1);
let cardIndexArray = []; let cardIndexArray = [];
function getItemLink(item: Member | Group): string { function getItemLink(item: Member | Group): string {
@ -43,13 +47,13 @@
let el; let el;
if (event.key === "ArrowDown") { if (event.key === "ArrowDown") {
if (cardIndexArray[index + 1]) el = cardIndexArray[index + 1]; if (index + 1 < indexStart + itemsPerPage) el = cardIndexArray[index + 1];
else el = cardIndexArray[0]; else el = cardIndexArray[indexStart];
} }
if (event.key === "ArrowUp") { if (event.key === "ArrowUp") {
if (cardIndexArray[index - 1]) el = cardIndexArray[index - 1]; if (index - 1 >= indexStart) el = cardIndexArray[index - 1];
else el = cardIndexArray[cardIndexArray.length - 1]; else el = cardIndexArray[indexStart + itemsPerPage - 1];
} }
if (el) { if (el) {
@ -106,9 +110,9 @@
{#each list as item, index (item.id + index)} {#each list as item, index (item.id + index)}
<Card> <Card>
<h2 class="accordion-header"> <h2 class="accordion-header">
<button class="w-100 accordion-button collapsed" bind:this={cardIndexArray[index]} on:click={() => toggleCard(index)} on:keydown={(e) => skipToNextItem(e, index)}> <button class="w-100 accordion-button collapsed" bind:this={cardIndexArray[indexStart + index]} on:click={() => toggleCard(indexStart + index)} on:keydown={(e) => skipToNextItem(e, indexStart + index)}>
<CardsHeader {item}> <CardsHeader {item}>
<div slot="icon" style="cursor: pointer;" id={`copy-${item.id}-${index}`} on:click|stopPropagation={() => copyShortLink(index, item.id)} on:keydown={(e) => copyShortLink(index, item.id, e)} tabindex={0} > <div slot="icon" style="cursor: pointer;" id={`copy-${item.id}-${index}`} on:click|stopPropagation={() => copyShortLink(indexStart + index, item.id)} on:keydown={(e) => copyShortLink(indexStart + index, item.id, e)} tabindex={0} >
{#if isPublic || item.privacy.visibility === "public"} {#if isPublic || item.privacy.visibility === "public"}
{#if itemType === "member"} {#if itemType === "member"}
<FaUserCircle /> <FaUserCircle />
@ -120,10 +124,10 @@
{/if} {/if}
</div> </div>
</CardsHeader> </CardsHeader>
<Tooltip placement="top" target={`copy-${item.id}-${index}`}>{copiedArray[index] ? "Copied!" : "Copy public link"}</Tooltip> <Tooltip placement="top" target={`copy-${item.id}-${index}`}>{copiedArray[indexStart + index] ? "Copied!" : "Copy public link"}</Tooltip>
</button> </button>
</h2> </h2>
<Collapse isOpen={isOpenArray[index]}> <Collapse isOpen={isOpenArray[indexStart + index]}>
<CardBody> <CardBody>
{#if itemType === "member"} {#if itemType === "member"}
<MemberBody on:deletion bind:isPublic bind:groups bind:member={item} /> <MemberBody on:deletion bind:isPublic bind:groups bind:member={item} />
@ -138,10 +142,10 @@
{:else if openByDefault || settings.accessibility.expandedcards} {:else if openByDefault || settings.accessibility.expandedcards}
{#each list as item, index (item.id + index)} {#each list as item, index (item.id + index)}
<Card class="mb-3"> <Card class="mb-3">
<div class="accordion-button collapsed p-0" bind:this={cardIndexArray[index]} on:keydown={(e) => skipToNextItem(e, index)} tabindex={0}> <div class="accordion-button collapsed p-0" bind:this={cardIndexArray[indexStart + index]} on:keydown={(e) => skipToNextItem(e, indexStart + index)} tabindex={0}>
<CardHeader class="w-100"> <CardHeader class="w-100">
<CardsHeader {item}> <CardsHeader {item}>
<div slot="icon" style="cursor: pointer;" id={`copy-${item.id}-${index}`} on:click|stopPropagation={() => copyShortLink(index, item.id)} on:keydown|stopPropagation={(e) => copyShortLink(index, item.id, e)} tabindex={0} > <div slot="icon" style="cursor: pointer;" id={`copy-${item.id}-${index}`} on:click|stopPropagation={() => copyShortLink(indexStart + index, item.id)} on:keydown|stopPropagation={(e) => copyShortLink(indexStart + index, item.id, e)} tabindex={0} >
{#if isPublic || item.privacy.visibility === "public"} {#if isPublic || item.privacy.visibility === "public"}
{#if itemType === "member"} {#if itemType === "member"}
<FaUserCircle /> <FaUserCircle />
@ -153,7 +157,7 @@
{/if} {/if}
</div> </div>
</CardsHeader> </CardsHeader>
<Tooltip placement="top" target={`copy-${item.id}-${index}`}>{copiedArray[index] ? "Copied!" : "Copy public link"}</Tooltip> <Tooltip placement="top" target={`copy-${item.id}-${index}`}>{copiedArray[indexStart + index] ? "Copied!" : "Copy public link"}</Tooltip>
</CardHeader> </CardHeader>
</div> </div>
<CardBody> <CardBody>
@ -169,9 +173,9 @@
<div class="my-3"> <div class="my-3">
{#each list as item, index (item.id + index)} {#each list as item, index (item.id + index)}
<Card> <Card>
<a class="accordion-button collapsed" style="text-decoration: none;" href={getItemLink(item)} bind:this={cardIndexArray[index]} on:keydown={(e) => skipToNextItem(e, index)} use:link > <a class="accordion-button collapsed" style="text-decoration: none;" href={getItemLink(item)} bind:this={cardIndexArray[indexStart + index]} on:keydown={(e) => skipToNextItem(e, indexStart + index)} use:link >
<CardsHeader {item}> <CardsHeader {item}>
<div slot="icon" style="cursor: pointer;" id={`copy-${item.id}-${index}`} on:click|stopPropagation={() => copyShortLink(index, item.id)} on:keydown|stopPropagation={(e) => copyShortLink(index, item.id, e)} tabindex={0} > <div slot="icon" style="cursor: pointer;" id={`copy-${item.id}-${index}`} on:click|stopPropagation={() => copyShortLink(indexStart + index, item.id)} on:keydown|stopPropagation={(e) => copyShortLink(indexStart + index, item.id, e)} tabindex={0} >
{#if isPublic || item.privacy.visibility === "public"} {#if isPublic || item.privacy.visibility === "public"}
{#if itemType === "member"} {#if itemType === "member"}
<FaUserCircle /> <FaUserCircle />
@ -183,7 +187,7 @@
{/if} {/if}
</div> </div>
</CardsHeader> </CardsHeader>
<Tooltip placement="top" target={`copy-${item.id}-${index}`}>{copiedArray[index] ? "Copied!" : "Copy public link"}</Tooltip> <Tooltip placement="top" target={`copy-${item.id}-${index}`}>{copiedArray[indexStart + index] ? "Copied!" : "Copy public link"}</Tooltip>
</a> </a>
</Card> </Card>
{/each} {/each}

View File

@ -132,6 +132,6 @@
<NewGroup on:create={addItemToList} /> <NewGroup on:create={addItemToList} />
{/if} {/if}
{/if} {/if}
<CardsList on:deletion bind:list={slicedList} bind:groups bind:members isMainDash={isMainDash} isPublic={isPublic} itemType={itemType} /> <CardsList on:deletion bind:list={slicedList} bind:groups bind:members isMainDash={isMainDash} isPublic={isPublic} itemType={itemType} itemsPerPage={itemsPerPage} currentPage={currentPage} />
<ListPagination bind:currentPage {pageAmount} /> <ListPagination bind:currentPage {pageAmount} />
{/if} {/if}

View File

@ -156,7 +156,7 @@
</CardHeader> </CardHeader>
</Card> </Card>
<ListPagination bind:currentPage bind:pageAmount /> <ListPagination bind:currentPage bind:pageAmount />
<CardsList on:deletion={(e) => deleteMemberFromList(e)} bind:list={members} isPublic={isPublic} isMainDash={false} itemType="member" /> <CardsList on:deletion={(e) => deleteMemberFromList(e)} bind:list={members} isPublic={isPublic} isMainDash={false} itemType="member" itemsPerPage={itemsPerPage} currentPage={currentPage} />
<ListPagination bind:currentPage bind:pageAmount /> <ListPagination bind:currentPage bind:pageAmount />
{/if} {/if}
{/if} {/if}

View File

@ -158,7 +158,7 @@
</CardHeader> </CardHeader>
</Card> </Card>
<ListPagination bind:currentPage bind:pageAmount /> <ListPagination bind:currentPage bind:pageAmount />
<CardsList on:deletion={(e) => deleteGroupFromList(e)} bind:list={groups} isPublic={isPublic} isMainDash={false} itemType="group" /> <CardsList on:deletion={(e) => deleteGroupFromList(e)} bind:list={groups} isPublic={isPublic} isMainDash={false} itemType="group" itemsPerPage={itemsPerPage} currentPage={currentPage} />
<ListPagination bind:currentPage bind:pageAmount /> <ListPagination bind:currentPage bind:pageAmount />
{/if} {/if}
{/if} {/if}

View File

@ -46,7 +46,7 @@
let openByDefault = false; let openByDefault = false;
if (searchParams && searchParams.get("open") === "true") openByDefault = true; if (searchParams && searchParams.get("open") === "true") openByDefault = true;
let settings = JSON.parse(localStorage.getItem("pk-settings")); let rollCounter = 1;
onMount(async () => { onMount(async () => {
await fetchList(amount, usePrivateMembers); await fetchList(amount, usePrivateMembers);
@ -110,6 +110,7 @@
randomList = randomizeList(parseInt(optionAmount), optionUsePrivateMembers, optionAllowDoubles); randomList = randomizeList(parseInt(optionAmount), optionUsePrivateMembers, optionAllowDoubles);
navigate(`${path}${paramArray.length > 0 ? `?${paramArray.join('&')}` : ""}`); navigate(`${path}${paramArray.length > 0 ? `?${paramArray.join('&')}` : ""}`);
rollCounter ++;
} }
function capitalizeFirstLetter(string: string) { function capitalizeFirstLetter(string: string) {
@ -205,7 +206,7 @@
{:else if err} {:else if err}
<Alert color="danger">{err}</Alert> <Alert color="danger">{err}</Alert>
{:else} {:else}
<CardsList openByDefault={openByDefault} bind:list={randomList} isPublic={true} isMainDash={false} itemType={type} /> <CardsList openByDefault={openByDefault} bind:list={randomList} isPublic={true} isMainDash={false} itemType={type} itemsPerPage={5} currentPage={rollCounter} />
{/if} {/if}
</Col> </Col>
</Row> </Row>