lots of style stuff, can delete guild intros

master
Patrick Cleavelin 2023-03-14 21:44:10 -05:00
parent b8e65797de
commit a464e48287
6 changed files with 124 additions and 25 deletions

View File

@ -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}

View File

@ -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>

View File

@ -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');
}

View File

@ -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>

View File

@ -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>

View File

@ -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;