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-03-19 10:17:29 +01:00
import Body from '../lib/member/Body.svelte';
2022-06-27 11:55:54 +02:00
import CardsList from '../lib/list/CardsList.svelte';
2022-05-30 13:02:04 +02:00
import { useParams , Link , navigate } from 'svelte-navigator';
2022-03-19 10:17:29 +01:00
import { onMount } from 'svelte';
import api from "../api";
import { Member , Group } from "../api/types";
import CardsHeader from "../lib/CardsHeader.svelte";
import FaAddressCard from 'svelte-icons/fa/FaAddressCard.svelte'
2022-03-19 11:45:47 +01:00
import FaList from 'svelte-icons/fa/FaList.svelte'
import ListPagination from '../lib/ListPagination.svelte';
2022-03-19 10:17:29 +01:00
let loading = true;
let groupLoading = false;
let params = useParams();
let err = "";
let groupErr = "";
let member: Member;
2022-03-19 11:45:47 +01:00
let groups: Group[] = [];
let systemGroups: Group[] = [];
2022-03-19 12:42:28 +01:00
let systemMembers: Member[] = [];
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-03-19 11:45:47 +01:00
2022-03-19 10:17:29 +01:00
const isPage = true;
export let isPublic = true;
let settings = JSON.parse(localStorage.getItem("pk-settings"));
2022-03-19 11:45:47 +01:00
let currentPage = 1;
2022-04-25 20:03:34 +02:00
let itemsPerPage = settings & & settings.accessibility & & settings.accessibility.expandedcards ? 5 : 10;
2022-03-19 11:45:47 +01:00
$: indexOfLastItem = currentPage * itemsPerPage;
$: indexOfFirstItem = indexOfLastItem - itemsPerPage;
$: pageAmount = Math.ceil(groups.length / itemsPerPage);
2022-03-19 12:42:11 +01:00
$: orderedGroups = groups.sort((a, b) => a.name.localeCompare(b.name));
$: slicedGroups = orderedGroups.slice(indexOfFirstItem, indexOfLastItem);
2022-03-19 11:45:47 +01:00
2022-05-30 13:02:04 +02:00
if (!isPublic && isPage) {
let user = localStorage.getItem("pk-user");
if (!user) navigate("/");
}
2022-03-19 10:17:29 +01:00
onMount(() => {
fetchMember();
});
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 {
member = await api().members($params.id).get({ auth : ! isPublic } );
2022-03-19 17:22:50 +01:00
if (!isPublic && !member.privacy) {
notOwnSystem = true;
throw new Error("Member is not from own system.");
}
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;
await new Promise(resolve => setTimeout(resolve, 1000));
fetchGroups();
} catch (error) {
console.log(error);
err = error.message;
loading = false;
}
}
async function fetchGroups() {
try {
2022-03-19 12:42:28 +01:00
groups = await api().members($params.id).groups().get({ auth : ! isPublic , query : { with_members : ! isPublic } } );
2022-03-19 10:17:29 +01:00
if (!isPublic) {
await new Promise(resolve => setTimeout(resolve, 1000));
systemGroups = await api().systems("@me").groups.get({ auth : true , query : { with_members : true } } );
}
groupErr = "";
groupLoading = false;
2022-03-19 12:42:28 +01:00
// we can't use with_members from a group list from a member endpoint yet, but I'm leaving this in in case we do
// (this is needed for editing a group member list from the member page)
/* if (!isPublic) {
await new Promise(resolve => setTimeout(resolve, 1000));
systemMembers = await api().systems("@me").members.get({ auth : true } );
} */
2022-03-19 10:17:29 +01:00
} catch (error) {
console.log(error);
groupErr = error.message;
groupLoading = false;
}
}
async function updateGroups() {
groupLoading = true;
await new Promise(resolve => setTimeout(resolve, 500));
fetchGroups();
}
2022-03-19 11:45:47 +01:00
function updateDelete() {
isDeleted = true;
}
2022-03-19 12:42:28 +01:00
function deleteGroupFromList(event: any) {
groups = groups.filter(group => group.id !== event.detail);
systemGroups = systemGroups.filter(group => group.id !== event.detail);
}
2022-05-30 10:01:36 +02:00
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-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 >
< CardsHeader bind:item = { 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 >
2022-03-19 11:45:47 +01:00
< Body on:deletion = { updateDelete } on:updateGroups= { updateGroups } bind:groups = { systemGroups } bind:member= { member } isPage = { isPage } 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 >
{ :else if groups && groups . length > 0 }
2022-03-19 11:45:47 +01:00
< Card class = "mb-2" >
< CardHeader >
< CardTitle style = "margin-top: 8px; outline: none;" >
< div class = "icon d-inline-block" >
< FaList / >
< / div > Member groups
< / CardTitle >
< / CardHeader >
< / Card >
< ListPagination bind:currentPage bind:pageAmount / >
2022-06-27 17:00:48 +02:00
< CardsList on:deletion = {( e ) => deleteGroupFromList ( e )} bind:list= { slicedGroups } isPublic = { isPublic } itemType="group" itemsPerPage = { itemsPerPage } currentPage= { currentPage } fullLength = { groups . length } / >
2022-03-19 11:45:47 +01:00
< ListPagination bind:currentPage bind:pageAmount / >
{ /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-05-30 10:01:36 +02:00
< / style >
< svelte:head >
< title > PluralKit | { title } </ title >
< / svelte:head >