lots of style stuff, can delete guild intros
parent
b8e65797de
commit
a464e48287
|
@ -51,7 +51,7 @@
|
||||||
|
|
||||||
{#if canDownloadAny}
|
{#if canDownloadAny}
|
||||||
<div id="cardContent">
|
<div id="cardContent">
|
||||||
<div id="uploader">
|
<div id="nestedCardContent">
|
||||||
<h3>Download New Intro</h3>
|
<h3>Download New Intro</h3>
|
||||||
{#if !!downloadPromise}
|
{#if !!downloadPromise}
|
||||||
{#await downloadPromise}
|
{#await downloadPromise}
|
||||||
|
@ -76,7 +76,7 @@
|
||||||
<button on:click={download}>Download</button>
|
<button on:click={download}>Download</button>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
<div id="uploader">
|
<div id="nestedCardContent">
|
||||||
<h3>Upload New Intro</h3>
|
<h3>Upload New Intro</h3>
|
||||||
{#if !!uploadPromise}
|
{#if !!uploadPromise}
|
||||||
{#await uploadPromise}
|
{#await uploadPromise}
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
export let exclude = null;
|
export let exclude = null;
|
||||||
export let include = null;
|
export let include = null;
|
||||||
export let btnLabel = 'Add';
|
export let btnLabel = 'Add';
|
||||||
|
export let btnDanger = false;
|
||||||
export let emptyMsg = null;
|
export let emptyMsg = null;
|
||||||
|
|
||||||
let filteredIntroList = [];
|
let filteredIntroList = [];
|
||||||
|
@ -82,16 +83,35 @@
|
||||||
let selectedIntros = [];
|
let selectedIntros = [];
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div id="list">
|
<div id="nestedCardContent" class="cardLight cardNoShadow">
|
||||||
{#if !!filteredIntroList && filteredIntroList.length > 0}
|
<div id="list">
|
||||||
{#each filteredIntroList as intro (intro.index)}
|
{#if !!filteredIntroList && filteredIntroList.length > 0}
|
||||||
<label out:send={{ key: intro.index }} in:receive={{ key: intro.index }} animate:flip={{ duration: 200 }} id="list-item">
|
{#each filteredIntroList as intro (intro.index)}
|
||||||
<input type="checkbox" bind:group={selectedIntros} name="selectedIntros" value={intro.index}>
|
<label out:send={{ key: intro.index }} in:receive={{ key: intro.index }} animate:flip={{ duration: 200 }} id="list-item">
|
||||||
{intro.name}
|
<input type="checkbox" bind:group={selectedIntros} name="selectedIntros" value={intro.index}>
|
||||||
</label>
|
{intro.name}
|
||||||
{/each}
|
</label>
|
||||||
{:else}
|
{/each}
|
||||||
<p style="color: red">{emptyMsg}</p>
|
{:else}
|
||||||
{/if}
|
<p style="color: red">{emptyMsg}</p>
|
||||||
<button on:click={onConfirm}>{btnLabel}</button>
|
{/if}
|
||||||
|
</div>
|
||||||
|
<button style="background-image: linear-gradient(0deg, {btnDanger ? '#a81111' : '#1f1f36'}, {btnDanger ? '#db1616' : '#23233d'});"on:click={onConfirm}>{btnLabel}</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
div#list {
|
||||||
|
display: flex;
|
||||||
|
width: 85%;
|
||||||
|
border-radius: 4px;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
background-color: #323259;
|
||||||
|
padding: 1em;
|
||||||
|
overflow-x: hidden;
|
||||||
|
overflow-y: auto;
|
||||||
|
margin: 16px;
|
||||||
|
height: 256px;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { env } from '$env/dynamic/public';
|
import { env } from '$env/dynamic/public';
|
||||||
|
|
||||||
export const apiCall = async (method, endpoint, token, body) => {
|
export const apiCall = async (method, endpoint, token, body, contentType) => {
|
||||||
const headers = (() => {
|
const headers = (() => {
|
||||||
if (!!token) {
|
if (!!token) {
|
||||||
return { 'token': token };
|
return { 'token': token };
|
||||||
|
@ -12,7 +12,7 @@ export const apiCall = async (method, endpoint, token, body) => {
|
||||||
return (await
|
return (await
|
||||||
fetch(
|
fetch(
|
||||||
`${env.PUBLIC_API_URL}/${endpoint}`,
|
`${env.PUBLIC_API_URL}/${endpoint}`,
|
||||||
{ method: method, headers: headers, body: body })
|
{ method: method, headers: { 'Content-Type': contentType, ...headers }, body: body })
|
||||||
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -48,3 +48,7 @@ export const removeIntro = async (guild, channel, selectedIntros, token) => {
|
||||||
export const uploadIntro = async (guild, name, file, token) => {
|
export const uploadIntro = async (guild, name, file, token) => {
|
||||||
await apiCall('POST', `intros/${guild}/upload?name=${encodeURIComponent(name)}`, token, file);
|
await apiCall('POST', `intros/${guild}/upload?name=${encodeURIComponent(name)}`, token, file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const deleteIntro = async (guild, selectedIntros, token) => {
|
||||||
|
await apiCall('DELETE', `intros/${guild}/delete`, token, JSON.stringify(selectedIntros), 'application/json');
|
||||||
|
}
|
||||||
|
|
20
src/app.html
20
src/app.html
|
@ -23,7 +23,7 @@
|
||||||
div#cardContent {
|
div#cardContent {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(auto-fit, minmax(500px, 1fr));
|
grid-template-columns: repeat(auto-fit, minmax(500px, 1fr));
|
||||||
align-items: center;
|
align-items: stretch;
|
||||||
justify-items: center;
|
justify-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
background-color: #323259;
|
background-color: #323259;
|
||||||
|
@ -33,14 +33,24 @@
|
||||||
gap: 1em;
|
gap: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
div#list {
|
div#nestedCardContent {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
position: relative;
|
||||||
width: 85%;
|
width: 85%;
|
||||||
border-radius: 4px;
|
height: fit-content;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
background-color: #2a2a4a;
|
||||||
|
padding: 16px;
|
||||||
|
box-shadow: 1px 3px 4px 1px #1f1f36;
|
||||||
|
}
|
||||||
|
|
||||||
|
div#nestedCardContent.cardNoShadow{
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
div#nestedCardContent.cardLight{
|
||||||
background-color: #323259;
|
background-color: #323259;
|
||||||
padding: 1em;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
button, #list-item {
|
button, #list-item {
|
||||||
|
@ -68,5 +78,5 @@
|
||||||
background-image: linear-gradient(0deg, #40406e, #444475);
|
background-image: linear-gradient(0deg, #40406e, #444475);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<body data-sveltekit-preload-data="hover" style="display: block; margin: 0; width: 100%; overflow-x: hidden; overflow-y: scroll;">%sveltekit.body%</body>
|
<body data-sveltekit-preload-data="hover" style="display: block; margin: 0; width: 100%; overflow-x: hidden; overflow-y: scroll;"><div>%sveltekit.body%</div></body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
<script>
|
||||||
|
import { member, intros } from '../store.ts';
|
||||||
|
import IntroSelector from '../IntroSelector.svelte';
|
||||||
|
import { slide } from 'svelte/transition';
|
||||||
|
import { deleteIntro } from '../api.js';
|
||||||
|
|
||||||
|
let deletePromise = null;
|
||||||
|
let dashboardVisible = false;
|
||||||
|
|
||||||
|
const apiDeleteIntro = async (guild, selectedIntros) => {
|
||||||
|
await deleteIntro(guild, selectedIntros, $member.token);
|
||||||
|
await member.pullData($member.token);
|
||||||
|
await intros.fetchIntros($member.guilds);
|
||||||
|
};
|
||||||
|
const deleteIntros = (event) => {
|
||||||
|
deletePromise = apiDeleteIntro(event.detail.guild, event.detail.intros);
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<h3>Wow you're a moderator, here is a cool dashboard for you to use</h3>
|
||||||
|
<div id="cardContent" class="noGrid">
|
||||||
|
<div id="nestedCardContent" class="cardLight cardNoShadow">
|
||||||
|
{#if dashboardVisible}
|
||||||
|
<div id="nestedCardContent" class="cardLight cardNoShadow" transition:slide>
|
||||||
|
<button on:click={() => dashboardVisible = false}>
|
||||||
|
Hide dashboard ^
|
||||||
|
</button>
|
||||||
|
{#if !!deletePromise}
|
||||||
|
{#await deletePromise}
|
||||||
|
{:catch err}
|
||||||
|
<p style="color: red">{err}</p>
|
||||||
|
{/await}
|
||||||
|
{/if}
|
||||||
|
<div id="nestedCardContent">
|
||||||
|
{#each $member.guilds as guild}
|
||||||
|
<h4>{guild.name}</h4>
|
||||||
|
<IntroSelector
|
||||||
|
guild={guild.id}
|
||||||
|
exclude={[]}
|
||||||
|
on:confirm={deleteIntros}
|
||||||
|
btnLabel="Delete Intro From Guild"
|
||||||
|
btnDanger={true}
|
||||||
|
emptyMsg="Your guild doesn't have any intros, try adding some below"
|
||||||
|
/>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{:else}
|
||||||
|
<button on:click={() => dashboardVisible = true}>
|
||||||
|
Show dashboard v
|
||||||
|
</button>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
h3 {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
import Login from '../Login.svelte';
|
import Login from '../Login.svelte';
|
||||||
import IntroSelector from '../IntroSelector.svelte';
|
import IntroSelector from '../IntroSelector.svelte';
|
||||||
import IntroDownloader from '../IntroDownloader.svelte';
|
import IntroDownloader from '../IntroDownloader.svelte';
|
||||||
|
import ModDashboard from '../components/ModDashboard.svelte';
|
||||||
|
|
||||||
let addIntroPromise = null;
|
let addIntroPromise = null;
|
||||||
let removeIntroPromise = null;
|
let removeIntroPromise = null;
|
||||||
|
@ -33,14 +34,16 @@
|
||||||
<h1>MemeJoin - A bot for user intros</h1>
|
<h1>MemeJoin - A bot for user intros</h1>
|
||||||
<p style='text-align:center;'>{$member.username}</p>
|
<p style='text-align:center;'>{$member.username}</p>
|
||||||
|
|
||||||
|
<ModDashboard />
|
||||||
<IntroDownloader />
|
<IntroDownloader />
|
||||||
|
<h3>Guild Settings</h3>
|
||||||
<div id="cardContent">
|
<div id="cardContent">
|
||||||
{#each $member.guilds as guild}
|
{#each $member.guilds as guild}
|
||||||
<div id="guild">
|
<div id="nestedCardContent" class="cardLight cardNoShadow">
|
||||||
<h4>{guild.name}</h4>
|
<h4>{guild.name}</h4>
|
||||||
<div id="guild-settings">
|
<div id="nestedCardContent">
|
||||||
{#each guild.channels as channel}
|
{#each guild.channels as channel}
|
||||||
<div id="channel-settings">
|
<div id="nestedCardContent" class="cardNoShadow">
|
||||||
<h4>{channel.name}</h4>
|
<h4>{channel.name}</h4>
|
||||||
{#await addIntroPromise then result}
|
{#await addIntroPromise then result}
|
||||||
{:catch err}
|
{:catch err}
|
||||||
|
@ -81,7 +84,7 @@
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
h1 {
|
h1, h2, h3 {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,6 +113,7 @@
|
||||||
div#channel-settings {
|
div#channel-settings {
|
||||||
display: flex;
|
display: flex;
|
||||||
width: 85%;
|
width: 85%;
|
||||||
|
height: 95%;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background-color: #2a2a4a;
|
background-color: #2a2a4a;
|
||||||
|
|
Reference in New Issue