2022-03-19 10:17:29 +01:00
< script lang = "ts" >
2022-06-28 08:04:19 +02:00
import { Container , Row , Col , Alert , Spinner , Card , CardHeader , CardBody , CardTitle , Tooltip } from "sveltestrap";
2022-11-26 13:23:59 +01:00
import Body from '../../../components/member/Body.svelte';
import ListView from '../../../components/list/ListView.svelte';
2022-10-02 22:09:13 +02:00
import { useParams , Link , navigate , useLocation } from 'svelte-navigator';
2023-06-03 12:27:58 +02:00
import { onMount , setContext } from 'svelte';
2022-11-26 13:23:59 +01:00
import api from "../../../api";
2022-11-26 13:41:01 +01:00
import type { Member , Group } from "../../../api/types";
2022-11-26 13:23:59 +01:00
import CardsHeader from "../../../components/common/CardsHeader.svelte";
2022-03-19 10:17:29 +01:00
import FaAddressCard from 'svelte-icons/fa/FaAddressCard.svelte'
2022-11-26 13:23:59 +01:00
import ListPagination from '../../../components/common/ListPagination.svelte';
import CardView from '../../../components/list/CardView.svelte';
2022-11-27 19:27:07 +01:00
import type { List as Lists , ListOptions , PageOptions } from '../../../components/list/types';
import { defaultListOptions , defaultPageOptions } from '../../../components/list/types';
import { filterList , getPageAmount , paginateList } from '../../../components/list/functions';
import PageControl from "../../../components/list/PageControl.svelte";
2023-06-03 12:27:58 +02:00
import { writable , type Writable } from "svelte/store";
2023-09-21 13:19:29 +02:00
import TinyView from "../../../components/list/TinyView.svelte";
import TextView from "../../../components/list/TextView.svelte";
2022-10-02 22:09:13 +02:00
// get the state from the navigator so that we know which tab to start on
let location = useLocation();
let urlParams = $location.search & & new URLSearchParams($location.search);
let listView: string = urlParams & & urlParams.get("view") || "list";
2022-03-19 10:17:29 +01:00
let loading = true;
let groupLoading = false;
let params = useParams();
let err = "";
let groupErr = "";
2022-03-19 11:45:47 +01:00
let isDeleted = false;
2022-03-19 17:22:50 +01:00
let notOwnSystem = false;
2022-06-28 08:04:19 +02:00
let copied = false;
2022-11-27 19:27:07 +01:00
let pageAmount = 1;
2022-03-19 11:45:47 +01:00
2022-03-19 10:17:29 +01:00
export let isPublic = true;
let settings = JSON.parse(localStorage.getItem("pk-settings"));
2022-11-27 19:27:07 +01:00
if (!isPublic) {
2022-05-30 13:02:04 +02:00
let user = localStorage.getItem("pk-user");
if (!user) navigate("/");
}
2023-06-03 12:27:58 +02:00
onMount(async () => {
await fetchMember();
2022-03-19 10:17:29 +01:00
});
2023-06-03 12:27:58 +02:00
let membersStore: Writable< Member [ ] > = writable([])
let groupsStore: Writable< Group [ ] > = writable([])
$: members = setContext< Writable < Member [ ] > >("members", membersStore)
$: groups = setContext< Writable < Group [ ] > >("groups", groupsStore)
2024-06-23 18:56:18 +02:00
let member: Member|null = null
2023-06-03 12:27:58 +02:00
2022-05-30 10:01:36 +02:00
let title = isPublic ? "member" : "member (dash)";
2022-03-19 10:17:29 +01:00
async function fetchMember() {
try {
2023-06-03 12:27:58 +02:00
if (isPublic) {
const res: Member = await api().members($params.id).get({ auth : ! isPublic } );
2024-06-23 18:56:18 +02:00
member = res;
2023-06-03 12:27:58 +02:00
} else {
2024-06-23 18:56:18 +02:00
const res: Member = await api().members($params.id).get({ auth : ! isPublic } );
member = res
2023-06-03 12:27:58 +02:00
if (!member.privacy) {
notOwnSystem = true;
throw new Error("Member is not from own system.");
}
2022-03-19 17:22:50 +01:00
}
2022-03-19 10:17:29 +01:00
err = "";
loading = false;
2022-05-30 10:01:36 +02:00
if (member.name) {
title = isPublic ? member.name : `${ member . name } (dash)`;
}
2022-03-19 10:17:29 +01:00
groupLoading = true;
fetchGroups();
} catch (error) {
console.log(error);
err = error.message;
loading = false;
}
}
async function fetchGroups() {
try {
if (!isPublic) {
2023-06-03 12:27:58 +02:00
const systemGroups: Group[] = await api().systems("@me").groups.get({ auth : true , query : { with_members : true } } );
2024-06-23 18:56:18 +02:00
const memberList: Member[] = await api().systems("@me").members.get({ auth : true } )
members.set(memberList)
2023-06-03 12:27:58 +02:00
groups.set(systemGroups)
2024-06-23 18:56:18 +02:00
} else {
let memberGroups: Group[] = await api().members($params.id).groups().get({ auth : ! isPublic } );
if (!isPublic) memberGroups.forEach(g => g.members = [])
groups.set(memberGroups)
2022-03-19 10:17:29 +01:00
}
2024-06-23 18:56:18 +02:00
2022-03-19 10:17:29 +01:00
groupErr = "";
groupLoading = false;
} catch (error) {
console.log(error);
groupErr = error.message;
groupLoading = false;
}
}
2022-11-27 19:27:07 +01:00
let listOptions: ListOptions = {... defaultListOptions } ;
2022-03-19 12:42:28 +01:00
2022-11-27 19:27:07 +01:00
let pageOptions: PageOptions = {... defaultPageOptions ,
view: listView,
isPublic: isPublic,
type: 'group',
isMain: false,
2022-11-28 07:19:12 +01:00
itemsPerPage: getDefaultItemsPerpage()
2022-11-27 19:27:07 +01:00
};
2022-05-30 10:01:36 +02:00
2022-11-28 07:19:12 +01:00
function getDefaultItemsPerpage(): number {
if (listView === 'card') return 24;
2023-09-21 13:19:29 +02:00
else if (listView === 'tiny') return 36;
2022-11-28 07:19:12 +01:00
else if (settings & & settings.accessibility & & settings.accessibility.expandedcards)
return 10;
else return 25
}
2022-06-28 08:04:19 +02:00
async function copyShortLink(event?) {
if (event) {
let ctrlDown = event.ctrlKey||event.metaKey; // mac support
if (!(ctrlDown & & event.key === "c") & & event.key !== "Enter") return;
}
try {
await navigator.clipboard.writeText(`https://pk.mt/m/${ member . id } `);
copied = true;
await new Promise(resolve => setTimeout(resolve, 2000));
copied = false;
} catch (error) {
console.log(error);
}
}
2022-11-27 19:27:07 +01:00
2024-02-18 13:52:18 +01:00
$: memberGroups = !isPublic ? $groups.filter(g => g.members.includes(member.uuid)) : $groups;
2023-06-04 09:46:44 +02:00
$: processedList = filterList(memberGroups, $groups,listOptions);
2023-06-03 12:27:58 +02:00
$: currentPage = paginateList(processedList, pageOptions);
$: pageAmount = getPageAmount(processedList, pageOptions);
2022-03-19 10:17:29 +01:00
< / script >
2022-03-19 17:22:50 +01:00
{ #if settings && settings . appearance . color_background && ! notOwnSystem }
2022-03-19 10:17:29 +01:00
< div class = "background" style = "background-color: { member && `#$ { member . color } ` } " ></ div >
{ /if }
2022-03-19 17:22:50 +01:00
{ #if member && member . banner && settings && settings . appearance . banner_top && ! notOwnSystem }
2022-03-19 10:43:31 +01:00
< div class = "banner" style = "background-image: url( { member . banner } )" />
{ /if }
2022-03-19 10:17:29 +01:00
< Container >
< Row >
< Col class = "mx-auto" xs = { 12 } lg= { 11 } xl = { 10 } >
2022-05-20 12:09:10 +02:00
< h2 class = "visually-hidden" > Viewing { isPublic ? "a public" : "your own" } member</ h2 >
2022-03-19 11:45:47 +01:00
{ #if isDeleted }
< Alert color = "success" > Member has been successfully deleted. < Link to = "/dash" > Return to dash< / Link > < / Alert >
{ : else }
{ #if isPublic }
2022-05-20 12:09:10 +02:00
< Alert color = "info" aria-hidden > You are currently < b > viewing< / b > a member.< / Alert >
2022-03-19 11:45:47 +01:00
{ /if }
2022-03-19 17:22:50 +01:00
{ #if notOwnSystem }
< Alert color = "danger" > This member does not belong to your system, did you mean to look up < Link to = { `/profile/m/ ${ member . id } ` } > their public page </ Link > ?</ Alert >
{ :else if err }
< Alert color = "danger" > { @html err } </ Alert >
2022-03-19 10:17:29 +01:00
{ :else if loading }
< Spinner / >
{ :else if member && member . id }
2022-03-19 11:45:47 +01:00
< Card class = "mb-4" >
2022-03-19 10:17:29 +01:00
< CardHeader >
2023-09-21 13:23:44 +02:00
< CardsHeader item = { member } avatarUsed="avatar" type = "member" >
2022-06-28 08:04:19 +02:00
< div slot = "icon" style = "cursor: pointer;" id = { `member-copy- ${ member . id } ` } on:click | stopPropagation= {() => copyShortLink ()} on:keydown = {( e ) => copyShortLink ( e )} tabindex= { 0 } >
< FaAddressCard slot = "icon" / >
< / div >
2022-03-19 10:17:29 +01:00
< / CardsHeader >
2022-06-28 08:04:19 +02:00
< Tooltip placement = "top" target = { `member-copy- ${ member . id } ` } > { copied ? "Copied!" : "Copy public link" } </Tooltip >
2022-03-19 10:17:29 +01:00
< / CardHeader >
< CardBody >
2023-06-03 12:27:58 +02:00
< Body { member } isPage = { true } isPublic= { isPublic } / >
2022-03-19 10:17:29 +01:00
< / CardBody >
< / Card >
{ /if }
{ #if groupLoading }
2022-03-19 11:45:47 +01:00
< Alert color = "primary" > < Spinner size = "sm" / > Fetching groups...< / Alert >
2022-03-19 10:17:29 +01:00
{ :else if groupErr }
< Alert color = "danger" > { groupErr } </ Alert >
2023-06-03 12:27:58 +02:00
{ :else if memberGroups && memberGroups . length > 0 }
2022-11-27 19:27:07 +01:00
< PageControl bind:options = { listOptions } bind:pageOptions />
2023-06-03 12:27:58 +02:00
< span class = "itemcounter" > { processedList . length } { pageOptions . type } s ({ currentPage . length } shown)</ span >
2022-11-27 19:27:07 +01:00
< ListPagination bind:currentPage = { pageOptions . currentPage } { pageAmount } / >
{ #if pageOptions . view === "card" }
2023-09-21 13:23:44 +02:00
< CardView { pageOptions } currentList = { currentPage } { listOptions } / >
2023-09-21 13:19:29 +02:00
{ :else if pageOptions . view === "tiny" }
2023-09-21 13:23:44 +02:00
< TinyView { pageOptions } currentList = { currentPage } { listOptions } / >
2023-09-21 13:19:29 +02:00
{ :else if pageOptions . view === "text" }
< TextView { pageOptions } currentList = { currentPage } { listOptions } / >
2022-10-02 22:09:13 +02:00
{ : else }
2023-09-21 13:23:44 +02:00
< ListView { pageOptions } currentList = { currentPage } fullListLength= { memberGroups . length } options = { listOptions } / >
2022-10-02 22:09:13 +02:00
{ /if }
2022-11-27 19:27:07 +01:00
< ListPagination bind:currentPage = { pageOptions . currentPage } { pageAmount } / >
2024-02-18 15:01:02 +01:00
< div class = "spacer" > < / div >
2022-03-19 11:45:47 +01:00
{ /if }
2022-03-19 10:17:29 +01:00
{ /if }
< / Col >
< / Row >
< / Container >
< style >
.background {
2022-03-19 10:43:31 +01:00
position: fixed;
top: 0;
left: 0;
width: 100%;
flex: 1;
min-height: 100%;
2022-03-19 10:17:29 +01:00
z-index: -30;
}
2022-11-27 20:07:35 +01:00
.itemcounter {
width: 100%;
text-align: center;
display: inline-block;
margin-bottom: 0.5rem;
}
2022-05-30 10:01:36 +02:00
< / style >
< svelte:head >
< title > PluralKit | { title } </ title >
< / svelte:head >