Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Collaborator addons #390

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions package-lock.json

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

69 changes: 60 additions & 9 deletions src/lib/components/Modals/ServerInvitation.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,33 @@
import * as timeago from 'timeago.js'
import { page } from '$app/stores'

const { supabase } = $page.data
const { supabase, session } = $page.data

const owner = session?.user

let loading = false
let email = ''
let role = 'DEV'

async function invite_editor() {
loading = true
await supabase.from('invitations').insert({
email,
inviter_email: $page.data.user.email,
role,
server_invitation: true,
})
const { data } = await axios.post('/api/invitations', {
url: $page.url.origin,
email,
role,
server_invitation: true,
})

if (data.success) {
if (data.isNew) {
await supabase.from('invitations').insert({
email,
inviter_email: $page.data.user.email,
role,
server_invitation: true,
})
}
invitations = await get_invitations()
editors = await get_collaborators()
} else {
alert(data.error)
}
Expand Down Expand Up @@ -62,11 +66,41 @@
} else return data
}

async function remove_editor(user_id) {
loading = true
const { data: success } = await axios.delete('/api/invitations', {
params: {
user: user_id,
server_invitation: true,
},
})
if (success) {
get_collaborators().then((res) => {
editors = res
})
}
loading = false
}

async function cancel_invitation(email) {
loading = true
const { data: success } = await axios.put('/api/invitations', {
email,
})
if (success) {
get_invitations().then((res) => {
invitations = res
})
}
loading = false
}

const Role = (role) =>
({
DEV: 'Developer',
EDITOR: 'Content Editor',
}[role])
ADMIN: 'Admin',
})[role]
</script>

<div class="Invitation">
Expand All @@ -91,6 +125,7 @@
<select bind:value={role}>
<option value="DEV">{Role('DEV')}</option>
<option value="EDITOR">{Role('EDITOR')}</option>
<option value="ADMIN">{Role('ADMIN')}</option>
</select>
</div>
<button type="submit" disabled={!email}>
Expand All @@ -111,6 +146,13 @@
<span class="letter">{email[0]}</span>
<span class="email">{email}</span>
<span>Sent {timeago.format(created_at)}</span>
<button
class="site-button"
on:click={() => cancel_invitation(email)}
>
<Icon icon="pepicons-pop:trash" />
<span>Cancel</span>
</button>
</li>
{/each}
</ul>
Expand All @@ -124,6 +166,15 @@
<span class="letter">{user.email[0]}</span>
<span class="email">{user.email}</span>
<span class="role">{Role(role)}</span>
{#if user.id !== owner.id}
<button
class="site-button"
on:click={() => remove_editor(user.id)}
>
<Icon icon="pepicons-pop:trash" />
<span>Remove</span>
</button>
{/if}
</li>
{/each}
</ul>
Expand Down
82 changes: 63 additions & 19 deletions src/lib/components/Modals/SiteInvitation.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import axios from 'axios'
import * as timeago from 'timeago.js'
import { page } from '$app/stores'
import Icon from '@iconify/svelte'

export let site

Expand All @@ -11,31 +12,28 @@

let loading = false
let email = ''
let role = 'DEV'
let role = 'EDITOR'

async function invite_editor() {
loading = true
await supabase.from('invitations').insert({
email,
inviter_email: owner.email,
site: site.id,
role,
})
const { data: success } = await axios.post('/api/invitations', {
const { data: res } = await axios.post('/api/invitations', {
site: site.id,
email,
role,
server_invitation: false,
url: $page.url.origin,
})
if (success) {
const { data, error } = await supabase
.from('invitations')
.select('*')
.eq('site', site.id)
if (data) {
invitations = data
if (res.success) {
if (res.isNew) {
await supabase.from('invitations').insert({
email,
inviter_email: owner.email,
site: site.id,
role,
})
}
invitations = await get_invitations(site.id)
editors = await get_collaborators(site.id)
} else {
alert('Could not send invitation. Please try again.')
}
Expand Down Expand Up @@ -64,12 +62,46 @@
export async function get_collaborators(site_id) {
const { data, error } = await supabase
.from('collaborators')
.select(`user (*)`)
.select(`role, user (*)`)
.filter('site', 'eq', site_id)
if (error) {
console.error(error)
return []
} else return data.map((item) => item.user)
} else
return data.map((item) => {
return { role: item.role, ...item.user }
})
}

async function remove_editor(user_id) {
loading = true
const { data: success } = await axios.delete('/api/invitations', {
params: {
site: site.id,
user: user_id,
server_invitation: false,
},
})
if (success) {
get_collaborators(site.id).then((res) => {
editors = res
})
}
loading = false
}

async function cancel_invitation(email) {
loading = true
const { data: success } = await axios.put('/api/invitations', {
site: site.id,
email,
})
if (success) {
get_invitations(site.id).then((res) => {
invitations = res
})
}
loading = false
}
</script>

Expand All @@ -89,6 +121,7 @@
<select bind:value={role}>
<option value="DEV">Developer</option>
<option value="EDITOR">Content Editor</option>
<option value="OWNER">Owner</option>
</select>
</div>
<button type="submit">Send invite</button>
Expand All @@ -103,6 +136,13 @@
<span class="letter">{email[0]}</span>
<span class="email">{email}</span>
<span>Sent {timeago.format(created_at)}</span>
<button
class="site-button"
on:click={() => cancel_invitation(email)}
>
<Icon icon="pepicons-pop:trash" />
<span>Cancel</span>
</button>
</li>
{/each}
</ul>
Expand All @@ -116,11 +156,15 @@
<span class="email">{owner.email}</span>
<span class="role">Owner</span>
</li>
{#each editors as { email }}
{#each editors as { id, role, email }}
<li>
<span class="letter">{email[0]}</span>
<span class="email">{email}</span>
<span class="role">Editor</span>
<span class="role">{role}</span>
<button class="site-button" on:click={() => remove_editor(id)}>
<Icon icon="pepicons-pop:trash" />
<span>Remove</span>
</button>
</li>
{/each}
</ul>
Expand Down
2 changes: 1 addition & 1 deletion src/lib/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export type User = {
email: string;
server_member: boolean;
admin: boolean;
role: 'DEV' | 'EDITOR';
role: 'DEV' | 'EDITOR' | 'OWNER';
created_at: string;
}

Expand Down
15 changes: 11 additions & 4 deletions src/routes/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@
<div class="site-name">
{#if siteBeingEdited.id === site.id}
<form
on:submit|preventDefault={() => (siteBeingEdited = { id: null, element: null })}
on:submit|preventDefault={() =>
(siteBeingEdited = { id: null, element: null })}
>
<input
bind:this={siteBeingEdited.element}
Expand Down Expand Up @@ -98,9 +99,12 @@
{site.id}
</button>
{/if}
{#if $page.data.user.admin}
{#if $page.data.user.admin || site.collaborators.some((c) => c.site === $page.data.user.id && c.role === 'OWNER')}
<div class="buttons">
<button on:click={() => beginInvitation(site)} class="site-button">
<button
on:click={() => beginInvitation(site)}
class="site-button"
>
<Icon icon="clarity:users-solid" />
<span>Collaborators</span>
</button>
Expand All @@ -115,7 +119,10 @@
<Icon icon="material-symbols:edit-square-outline-rounded" />
<span>Rename</span>
</button>
<button class="site-button" on:click={() => delete_site(site)}>
<button
class="site-button"
on:click={() => delete_site(site)}
>
<Icon icon="pepicons-pop:trash" />
<span>Delete</span>
</button>
Expand Down
Loading