Skip to content

Commit

Permalink
Merge pull request #78 from sheodox/mod-management-etc
Browse files Browse the repository at this point in the history
Mod management etc
  • Loading branch information
sheodox authored Sep 28, 2023
2 parents 51c3848 + 33c4cd3 commit 0f9d059
Show file tree
Hide file tree
Showing 32 changed files with 645 additions and 200 deletions.
10 changes: 5 additions & 5 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "Alexandrite",
"version": "0.8.7",
"version": "0.8.8",
"private": true,
"scripts": {
"dev": "vite dev",
Expand Down
142 changes: 95 additions & 47 deletions src/lib/CommunitySidebar.svelte
Original file line number Diff line number Diff line change
@@ -1,68 +1,116 @@
<article>
<Sidebar description={community.description ?? ''} bannerImageSrc={community.banner} context="Community">
<a href={communityHref} slot="name">
<NameAtInstance place={community} prefix="!" />
</a>
{#if community && communityView}
<Sidebar description={community.description ?? ''} bannerImageSrc={community.banner} context="Community">
<a href={communityHref} slot="name">
<NameAtInstance place={community} prefix="!" />
</a>

<div slot="actions">
<Stack dir="c" gap={2}>
{#if communityView}
<CommunityCounts {communityView} />
{/if}
<Stack dir="r" gap={2} align="center">
<ExternalLink href={community.actor_id} cl="inline-link">
<Icon icon="arrow-up-right-from-square" />
View on {communityInstance}
</ExternalLink>
<ModlogLink
communityId={community.id}
highlight={userModerates ?? false}
highlightColor="green"
warn={warnModlog}
/>
<div slot="actions">
<Stack dir="c" gap={2}>
{#if communityView}
<CommunityCounts {communityView} />
{/if}
<Stack dir="r" gap={2} align="center">
<ExternalLink href={community.actor_id} cl="inline-link">
<Icon icon="arrow-up-right-from-square" />
View on {communityInstance}
</ExternalLink>
</Stack>
</Stack>
</Stack>
</div>
<div slot="end">
<Stack dir="c" gap={2}>
{#if moderators}
<Accordion buttonClasses="tertiary">
<span slot="title">Moderators ({moderators.length})</span>
<Stack dir="c" gap={2}>
{#each moderators as mod}
<UserLink user={mod.moderator} />
{/each}
</Stack>
</Accordion>
{/if}
</Stack>
</div>
</Sidebar>
</div>
<div slot="end">
<Stack dir="c" gap={2}>
{#if moderators}
<Accordion buttonClasses="tertiary">
<span slot="title">Moderation</span>
<Stack dir="c" gap={2}>
<Stack dir="r" gap={2} align="center" justify="between">
<h3 class="m-0">Moderators</h3>
<ModlogLink
communityId={community.id}
highlight={userModerates ?? false}
highlightColor="green"
warn={warnModlog}
/>
</Stack>
<ul class="p-0 hover-list" style="list-style: none">
{#each moderators as mod}
<ModeratorRow hasSeniority={hasModSeniority(moderators, mod.moderator.id)} {mod} />
{/each}
</ul>
{#if userModerates && !userIsHeadMod}
<Stack dir="r" justify="end">
<BusyButton small icon="user-minus" busy={$userModResignPending} on:click={resignFromModTeam}
>Leave Mod Team</BusyButton
>
</Stack>
{/if}
</Stack>
</Accordion>
{/if}
</Stack>
</div>
</Sidebar>
{/if}
</article>

<script lang="ts">
import { Stack, Icon, ExternalLink, Accordion } from 'sheodox-ui';
import Sidebar from '$lib/Sidebar.svelte';
import NameAtInstance from '$lib/NameAtInstance.svelte';
import CommunityCounts from './CommunityCounts.svelte';
import BusyButton from './BusyButton.svelte';
import ModlogLink from './ModlogLink.svelte';
import UserLink from './UserLink.svelte';
import type { CommunityView, Community, CommunityModeratorView } from 'lemmy-js-client';
import ModeratorRow from './mod-list/ModeratorRow.svelte';
import { nameAtInstance } from './nav-utils';
import { profile } from '$lib/profiles/profiles';
import { getAppContext } from './app-context';
import { getSettingsContext } from './settings-context';
import { getCommunityContext } from './community-context/community-context';
import { getModActionPending, getModContext } from './mod/mod-context';
import { readable } from 'svelte/store';
export let communityName: string;
const communityContext = getCommunityContext();
$: communityRes = communityContext.getCommunity(communityName);
$: communityView = $communityRes?.community_view;
$: community = communityView?.community;
$: moderators = $communityRes?.moderators;
$: communityHref = community ? `/${$profile.instance}/c/${nameAtInstance(community)}` : '';
$: userModerates = $siteMeta.my_user?.moderates.some(
(moderates) => community && moderates.community.id === community.id
);
$: userIsHeadMod = moderators?.[0]?.moderator.id === $userId;
$: warnModlog = userModerates ? $showModlogWarningModerated : $showModlogWarning;
export let community: Community;
export let communityView: CommunityView | null = null;
export let moderators: CommunityModeratorView[] | null = null;
$: communityInstance = community ? new URL(community.actor_id).host : null;
const { siteMeta } = getAppContext();
const { siteMeta, userId } = getAppContext();
const { showModlogWarning, showModlogWarningModerated } = getSettingsContext();
const { hasModSeniority } = getCommunityContext();
const modContext = getModContext();
$: communityHref = `/${$profile.instance}/c/${nameAtInstance(community)}`;
$: userModerates = $siteMeta.my_user?.moderates.some((moderates) => moderates.community.id === community.id);
$: warnModlog = userModerates ? $showModlogWarningModerated : $showModlogWarning;
const userModResignPending = community
? getModActionPending('add-mod', `${community.id}-${userId}`)
: readable(false);
async function resignFromModTeam() {
if (!community) {
return;
}
const communityName = nameAtInstance(community, community.title);
$: communityInstance = new URL(community.actor_id).host;
if (!$userId || !$siteMeta.my_user || !confirm(`Are you sure you want to resign as a mod of "${communityName}".`)) {
return;
}
const me = $siteMeta.my_user.local_user_view.person,
myName = nameAtInstance(me, me.display_name);
await modContext.addMod({
added: false,
communityId: community.id,
personId: $userId,
personName: myName
});
}
</script>
37 changes: 22 additions & 15 deletions src/lib/ExtraActionButton.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,28 @@
}
</style>

{#if action.href}
<a href={action.href} class="button m-0 ws-nowrap {cl}"><Icon icon={action.icon} {variant} /> {action.text}</a>
{:else if action.click}
<button on:click={action.click} class="button m-0 ws-nowrap {cl}" disabled={action.busy ?? false} use:ripple>
<div class="f-row gap-1">
{#if action.busy}
<div class="spinner">
<Spinner />
</div>
{:else}
<Icon icon={action.icon} {variant} />
{/if}
<span>{action.text}</span>
</div>
</button>
{#if !action.hidden}
{#if action.href}
<a href={action.href} class="button m-0 ws-nowrap {cl}"><Icon icon={action.icon} {variant} /> {action.text}</a>
{:else if action.click}
<button
on:click={action.click}
class="button m-0 ws-nowrap {cl}"
disabled={action.busy ?? action.disabled ?? false}
use:ripple
>
<div class="f-row gap-1">
{#if action.busy}
<div class="spinner">
<Spinner />
</div>
{:else}
<Icon icon={action.icon} {variant} />
{/if}
<span>{action.text}</span>
</div>
</button>
{/if}
{/if}

<script lang="ts">
Expand Down
2 changes: 1 addition & 1 deletion src/lib/ExtraActions.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
{#if actions.length}
{@const text = 'Extra actions'}
<Tooltip title={text}>
<MenuButton triggerClasses="{small ? 'small' : ''} m-0 {cl}">
<MenuButton triggerClasses="{small ? 'small' : ''} m-0 {cl}" on:open>
<span slot="trigger" class="extra-actions-trigger">
<span class="sr-only">{text}</span>
<Icon icon="ellipsis-vertical" />
Expand Down
2 changes: 1 addition & 1 deletion src/lib/PostPage.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@
<!-- svelte-ignore a11y-no-noninteractive-tabindex -->
<div class="page-column page-column-sidebar virtual-feed-scroll-container" tabindex="0">
<aside>
<CommunitySidebar community={postView.community} />
<CommunitySidebar {communityName} />
</aside>
</div>
</div>
Expand Down
8 changes: 4 additions & 4 deletions src/lib/RelativeTime.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@
differenceInMinutes,
differenceInMonths,
differenceInSeconds,
differenceInYears,
parseISO
differenceInYears
} from 'date-fns';
import { parseDate } from './utils';
export let date: string;
export let variant: 'icon' | 'text' = 'text';
Expand All @@ -44,7 +44,7 @@
style: 'narrow'
});
$: d = parseISO(date + 'Z');
$: d = parseDate(date);
let formatted = '';
$: {
const now = new Date(),
Expand All @@ -58,7 +58,7 @@
};
for (const unit of ['years', 'months', 'days', 'hours', 'minutes', 'seconds'] as const) {
if (diff[unit] < 0) {
if (Math.abs(diff[unit]) > 0) {
formatted = rtf.format(diff[unit], unit);
break;
}
Expand Down
23 changes: 5 additions & 18 deletions src/lib/UserLink.svelte
Original file line number Diff line number Diff line change
@@ -1,18 +1,4 @@
<style lang="scss">
.user-avatar {
height: 3rem;
width: 3rem;
:global(img) {
object-fit: cover;
border-radius: 10rem;
height: 100%;
width: 100%;
}
}
.user-avatar.inline {
height: 1em;
width: 1em;
}
.op {
color: var(--sx-peach-300) !important;
}
Expand All @@ -23,7 +9,7 @@
<Stack gap={2} dir="r" align="center">
{#if user.avatar && showAvatar}
<div class="user-avatar">
<Image src={user.avatar} mode="thumbnail" />
<Avatar src={user.avatar} icon="user" size="3rem" />
</div>
{/if}
<h1 class="sx-font-size-4 m-0">
Expand All @@ -38,9 +24,9 @@
data-sveltekit-preload-data="off"
class:op={isOP}
>
{#if user.avatar && showAvatar}
{#if (user.avatar && showAvatar) || showAvatarFallback}
<div class="user-avatar inline">
<Image src={user.avatar} mode="thumbnail" thumbnailResolution={16} />
<Avatar src={user.avatar} size="1em" icon="user" />
</div>
{/if}
<span>
Expand All @@ -51,14 +37,15 @@

<script lang="ts">
import { Stack, Tooltip } from 'sheodox-ui';
import Image from './Image.svelte';
import Avatar from './Avatar.svelte';
import NameAtInstance from './NameAtInstance.svelte';
import type { Person } from 'lemmy-js-client';
import { nameAtInstance } from './nav-utils';
import { profile } from './profiles/profiles';
export let user: Person;
export let isOP = false;
export let showAvatarFallback = false;
$: creatorName = nameAtInstance(user);
Expand Down
2 changes: 2 additions & 0 deletions src/lib/app-context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import type { Readable } from 'svelte/motion';
export const APP_CONTEXT_KEY = '__SX_APP_CONTEXT__';

export interface AppContext {
// the logged in user's ID
userId: Readable<number | null>;
ctrlBasedHotkeys: boolean;
siteMeta: Writable<GetSiteResponse>;
unreadCount: Writable<number>;
Expand Down
Loading

0 comments on commit 0f9d059

Please sign in to comment.