mirror of
https://github.com/PluralKit/PluralKit.git
synced 2026-02-15 02:00:09 +00:00
feat(dashboard): add tiny list view
This commit is contained in:
parent
65044c1012
commit
5083a181de
6 changed files with 184 additions and 2 deletions
71
dashboard/src/components/group/TinyGroupView.svelte
Normal file
71
dashboard/src/components/group/TinyGroupView.svelte
Normal file
|
|
@ -0,0 +1,71 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import { Card, CardImg, CardBody, Tooltip } from "sveltestrap"
|
||||||
|
import type { Group } from "../../api/types"
|
||||||
|
import resizeMedia from "../../api/resize-media";
|
||||||
|
import default_avatar from '../../assets/default_avatar.png';
|
||||||
|
import { useLocation } from "svelte-navigator";
|
||||||
|
import FaLock from "svelte-icons/fa/FaLock.svelte";
|
||||||
|
import FaUsers from "svelte-icons/fa/FaUserCircle.svelte"
|
||||||
|
|
||||||
|
export let group: Group
|
||||||
|
|
||||||
|
let location = useLocation()
|
||||||
|
let pathName = $location.pathname;
|
||||||
|
|
||||||
|
function getGroupPageUrl() {
|
||||||
|
let str: string;
|
||||||
|
if (pathName.startsWith("/dash")) str = "/dash";
|
||||||
|
else str = "/profile";
|
||||||
|
|
||||||
|
str += `/g/${group.id}`;
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<a href={getGroupPageUrl()} class="card-link rounded flex-1 mb-3" >
|
||||||
|
<Card style={`border: 3px solid #${group.color}`} class="h-100" >
|
||||||
|
<CardImg style="border-bottom-right-radius: 0; border-bottom-left-radius: 0;" src={group.icon ? resizeMedia(group.icon, [256, 256], "webp") : default_avatar} />
|
||||||
|
<CardBody class="text-center p-2 d-flex flex-col align-items-center justify-content-center">
|
||||||
|
<h3>
|
||||||
|
<button class="button-reset" style="width: auto; height: 1em; cursor: pointer; margin-right: 0.25em;" id={`m-copy-${group.uuid}`} >
|
||||||
|
{#if group.privacy && group.privacy.visibility === "private"}
|
||||||
|
<FaLock />
|
||||||
|
{:else}
|
||||||
|
<FaUsers />
|
||||||
|
{/if}
|
||||||
|
</button>
|
||||||
|
{group.name} <span class="unbold">({group.id})</span>
|
||||||
|
</h3>
|
||||||
|
</CardBody>
|
||||||
|
</Card>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
a.card-link, a.card-link:hover {
|
||||||
|
color: unset;
|
||||||
|
text-decoration: unset;
|
||||||
|
display: inline-block;
|
||||||
|
word-wrap: break-word;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.card-link:hover {
|
||||||
|
border: 4px solid var(--bs-primary);
|
||||||
|
transform: scale(96%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.unbold {
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-reset {
|
||||||
|
background: none;
|
||||||
|
color: inherit;
|
||||||
|
border: none;
|
||||||
|
padding: 0;
|
||||||
|
font: inherit;
|
||||||
|
cursor: pointer;
|
||||||
|
outline: inherit;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
import api from '../../api';
|
import api from '../../api';
|
||||||
import type { ListOptions, PageOptions } from './types';
|
import type { ListOptions, PageOptions } from './types';
|
||||||
import { createShortList, filterList, getPageAmount, paginateList } from './functions';
|
import { createShortList, filterList, getPageAmount, paginateList } from './functions';
|
||||||
|
import TinyView from './TinyView.svelte';
|
||||||
|
|
||||||
$: memberList = getContext<Writable<Member[]>>("members")
|
$: memberList = getContext<Writable<Member[]>>("members")
|
||||||
$: groupList = getContext<Writable<Group[]>>("groups")
|
$: groupList = getContext<Writable<Group[]>>("groups")
|
||||||
|
|
@ -36,6 +37,7 @@
|
||||||
// set the default items per page based on settings and view
|
// set the default items per page based on settings and view
|
||||||
// this probably should be moved to it's own function
|
// this probably should be moved to it's own function
|
||||||
if (pageOptions.view === "card") pageOptions.itemsPerPage = 24;
|
if (pageOptions.view === "card") pageOptions.itemsPerPage = 24;
|
||||||
|
else if (pageOptions.view === "tiny") pageOptions.itemsPerPage = 36;
|
||||||
else if (settings && settings.accessibility && settings.accessibility.expandedcards) pageOptions.itemsPerPage = 10;
|
else if (settings && settings.accessibility && settings.accessibility.expandedcards) pageOptions.itemsPerPage = 10;
|
||||||
else pageOptions.itemsPerPage = 25;
|
else pageOptions.itemsPerPage = 25;
|
||||||
|
|
||||||
|
|
@ -86,7 +88,7 @@
|
||||||
{#if pageOptions.view === "card"}
|
{#if pageOptions.view === "card"}
|
||||||
<CardView {pageOptions} currentList={currentGroups} />
|
<CardView {pageOptions} currentList={currentGroups} />
|
||||||
{:else if pageOptions.view === "tiny"}
|
{:else if pageOptions.view === "tiny"}
|
||||||
tiny!
|
<TinyView {pageOptions} currentList={currentGroups} />
|
||||||
{:else}
|
{:else}
|
||||||
<ListView currentList={currentGroups} {pageOptions} {options} fullListLength={groups.length} />
|
<ListView currentList={currentGroups} {pageOptions} {options} fullListLength={groups.length} />
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,11 @@ let itemsPerPageSelection = {
|
||||||
$: { if (pageOptions.view === "card") itemsPerPageSelection = {
|
$: { if (pageOptions.view === "card") itemsPerPageSelection = {
|
||||||
small: 12,
|
small: 12,
|
||||||
default: 24,
|
default: 24,
|
||||||
|
large: 48
|
||||||
|
}
|
||||||
|
else if (pageOptions.view === "tiny") itemsPerPageSelection = {
|
||||||
|
small: 18,
|
||||||
|
default: 36,
|
||||||
large: 60
|
large: 60
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
@ -173,6 +178,7 @@ function resetPage() {
|
||||||
<Input bind:value={pageOptions.view} type="select" aria-label="view mode" on:change={(e) => onViewChange(e)} >
|
<Input bind:value={pageOptions.view} type="select" aria-label="view mode" on:change={(e) => onViewChange(e)} >
|
||||||
<option value="list">List</option>
|
<option value="list">List</option>
|
||||||
<option value="card">Cards</option>
|
<option value="card">Cards</option>
|
||||||
|
<option value="tiny">Tiny</option>
|
||||||
</Input>
|
</Input>
|
||||||
</InputGroup>
|
</InputGroup>
|
||||||
</Col>
|
</Col>
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
import api from '../../api';
|
import api from '../../api';
|
||||||
import type { ListOptions, List, PageOptions } from './types';
|
import type { ListOptions, List, PageOptions } from './types';
|
||||||
import { createShortList, filterList, getPageAmount, paginateList } from './functions';
|
import { createShortList, filterList, getPageAmount, paginateList } from './functions';
|
||||||
|
import TinyView from './TinyView.svelte';
|
||||||
|
|
||||||
$: memberList = getContext<Writable<Member[]>>("members")
|
$: memberList = getContext<Writable<Member[]>>("members")
|
||||||
$: groupList = getContext<Writable<Group[]>>("groups")
|
$: groupList = getContext<Writable<Group[]>>("groups")
|
||||||
|
|
@ -36,6 +37,7 @@
|
||||||
// set the default items per page based on settings and view
|
// set the default items per page based on settings and view
|
||||||
// this probably should be moved to it's own function
|
// this probably should be moved to it's own function
|
||||||
if (pageOptions.view === "card") pageOptions.itemsPerPage = 24;
|
if (pageOptions.view === "card") pageOptions.itemsPerPage = 24;
|
||||||
|
else if (pageOptions.view === "tiny") pageOptions.itemsPerPage = 36;
|
||||||
else if (settings && settings.accessibility && settings.accessibility.expandedcards) pageOptions.itemsPerPage = 10;
|
else if (settings && settings.accessibility && settings.accessibility.expandedcards) pageOptions.itemsPerPage = 10;
|
||||||
else pageOptions.itemsPerPage = 25;
|
else pageOptions.itemsPerPage = 25;
|
||||||
|
|
||||||
|
|
@ -86,7 +88,7 @@
|
||||||
{#if pageOptions.view === "card"}
|
{#if pageOptions.view === "card"}
|
||||||
<CardView {pageOptions} currentList={currentMembers} />
|
<CardView {pageOptions} currentList={currentMembers} />
|
||||||
{:else if pageOptions.view === "tiny"}
|
{:else if pageOptions.view === "tiny"}
|
||||||
tiny!
|
<TinyView {pageOptions} currentList={currentMembers} />
|
||||||
{:else}
|
{:else}
|
||||||
<ListView currentList={currentMembers} {pageOptions} {options} fullListLength={members.length} />
|
<ListView currentList={currentMembers} {pageOptions} {options} fullListLength={members.length} />
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
||||||
30
dashboard/src/components/list/TinyView.svelte
Normal file
30
dashboard/src/components/list/TinyView.svelte
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import { Card, CardImg, Row, Col } from "sveltestrap";
|
||||||
|
import type { Group, Member } from "../../api/types";
|
||||||
|
import type { PageOptions } from "./types";
|
||||||
|
import default_avatar from '../../assets/default_avatar.png';
|
||||||
|
import resizeMedia from "../../api/resize-media";
|
||||||
|
import TinyMemberView from "../member/TinyMemberView.svelte";
|
||||||
|
import TinyGroupView from "../group/TinyGroupView.svelte";
|
||||||
|
|
||||||
|
export let pageOptions: PageOptions;
|
||||||
|
export let currentList: Member[]|Group[];
|
||||||
|
$: memberList = currentList as Member[]
|
||||||
|
$: groupList = currentList as Group[]
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Row class="mx-4 mx-sm-5 mx-md-0">
|
||||||
|
{#if pageOptions.type === "member"}
|
||||||
|
{#each memberList as item (item.uuid)}
|
||||||
|
<Col xs={6} md={4} lg={3} xl={2} class="d-flex flex-col">
|
||||||
|
<TinyMemberView member={item} />
|
||||||
|
</Col>
|
||||||
|
{/each}
|
||||||
|
{:else if pageOptions.type === "group"}
|
||||||
|
{#each groupList as item (item.uuid)}
|
||||||
|
<Col xs={6} md={4} lg={3} xl={2} class="d-flex flex-col">
|
||||||
|
<TinyGroupView group={item} />
|
||||||
|
</Col>
|
||||||
|
{/each}
|
||||||
|
{/if}
|
||||||
|
</Row>
|
||||||
71
dashboard/src/components/member/TinyMemberView.svelte
Normal file
71
dashboard/src/components/member/TinyMemberView.svelte
Normal file
|
|
@ -0,0 +1,71 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import { Card, CardImg, CardBody, Tooltip } from "sveltestrap"
|
||||||
|
import type { Member } from "../../api/types"
|
||||||
|
import resizeMedia from "../../api/resize-media";
|
||||||
|
import default_avatar from '../../assets/default_avatar.png';
|
||||||
|
import { useLocation } from "svelte-navigator";
|
||||||
|
import FaLock from "svelte-icons/fa/FaLock.svelte";
|
||||||
|
import FaUserCircle from "svelte-icons/fa/FaUserCircle.svelte"
|
||||||
|
|
||||||
|
export let member: Member
|
||||||
|
|
||||||
|
let location = useLocation()
|
||||||
|
let pathName = $location.pathname;
|
||||||
|
|
||||||
|
function getMemberPageUrl() {
|
||||||
|
let str: string;
|
||||||
|
if (pathName.startsWith("/dash")) str = "/dash";
|
||||||
|
else str = "/profile";
|
||||||
|
|
||||||
|
str += `/m/${member.id}`;
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<a href={getMemberPageUrl()} class="card-link rounded flex-1 mb-3" >
|
||||||
|
<Card style={`border: 3px solid #${member.color}`} class="h-100" >
|
||||||
|
<CardImg style="border-bottom-right-radius: 0; border-bottom-left-radius: 0;" src={member.avatar_url ? resizeMedia(member.avatar_url, [256, 256], "webp") : default_avatar} />
|
||||||
|
<CardBody class="text-center p-2 d-flex flex-col align-items-center justify-content-center">
|
||||||
|
<h3>
|
||||||
|
<button class="button-reset" style="width: auto; height: 1em; cursor: pointer; margin-right: 0.25em;" id={`m-copy-${member.uuid}`} >
|
||||||
|
{#if member.privacy && member.privacy.visibility === "private"}
|
||||||
|
<FaLock />
|
||||||
|
{:else}
|
||||||
|
<FaUserCircle />
|
||||||
|
{/if}
|
||||||
|
</button>
|
||||||
|
{member.name} <span class="unbold">({member.id})</span>
|
||||||
|
</h3>
|
||||||
|
</CardBody>
|
||||||
|
</Card>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
a.card-link, a.card-link:hover {
|
||||||
|
color: unset;
|
||||||
|
text-decoration: unset;
|
||||||
|
display: inline-block;
|
||||||
|
word-wrap: break-word;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.card-link:hover {
|
||||||
|
border: 4px solid var(--bs-primary);
|
||||||
|
transform: scale(96%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.unbold {
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-reset {
|
||||||
|
background: none;
|
||||||
|
color: inherit;
|
||||||
|
border: none;
|
||||||
|
padding: 0;
|
||||||
|
font: inherit;
|
||||||
|
cursor: pointer;
|
||||||
|
outline: inherit;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Loading…
Add table
Add a link
Reference in a new issue