dashboard/frontend/src/views/integrations/Integrations.svelte
2022-08-01 00:00:24 +01:00

252 lines
7.3 KiB
Svelte

<div class="parent">
<div class="content">
<div class="container">
<div class="spread">
<h4 class="title">My Integrations</h4>
<Button icon="fas fa-server" on:click={() => navigateTo(`/manage/${guildId}/integrations/create`)}>Create
Integration
</Button>
</div>
<div class="integrations my-integrations">
{#each ownedIntegrations as integration}
<div class="integration">
<Integration owned name={integration.name} {guildId} integrationId={integration.id}
imageUrl={generateProxyUrl(integration)} guildCount={integration.guild_count}>
<span slot="description">
{integration.description}
</span>
</Integration>
</div>
{/each}
</div>
</div>
<div>
<h4 class="title">Available Integrations</h4>
<div class="integrations">
<!-- Built in -->
{#if page === 1}
<div class="integration">
<Integration builtIn name="Bloxlink"
imageUrl="https://dbl-static.b-cdn.net/9bbd1f9504ddefc89606b19b290e9a0f.png"
viewLink="https://docs.ticketsbot.net/setup/placeholders#bloxlink">
<span slot="description">
Our Bloxlink integration inserts the Roblox usernames, profile URLs and more of your users into
ticket welcome messages automatically! This integration is automatically enabled in all servers, press the
View button below to check out the full list of placeholders you can use!
</span>
</Integration>
</div>
{/if}
{#each availableIntegrations as integration}
<div class="integration">
<Integration name={integration.name} {guildId} integrationId={integration.id}
imageUrl={generateProxyUrl(integration)} ownerId={integration.owner_id}
added={integration.added} guildCount={integration.guild_count} showAuthor
author={integration.author} on:remove={() => removeIntegration(integration.id)}>
<span slot="description">
{integration.description}
</span>
</Integration>
</div>
{/each}
</div>
</div>
<div class="pagination">
<i class="fas fa-chevron-left pagination-chevron" class:disabled-chevron={page === 1} on:click={previousPage}></i>
<p>Page {page}</p>
<i class="fas fa-chevron-right pagination-chevron" class:disabled-chevron={!hasNextPage} on:click={nextPage}></i>
</div>
</div>
</div>
<script>
import {notifyError, notifySuccess, withLoadingScreen} from '../../js/util'
import axios from "axios";
import {API_URL} from "../../js/constants";
import {setDefaultHeaders} from '../../includes/Auth.svelte'
import Integration from "../../components/manage/Integration.svelte";
import Button from "../../components/Button.svelte";
import {navigateTo} from "svelte-router-spa";
export let currentRoute;
let guildId = currentRoute.namedParams.id;
let freshlyRemoved = currentRoute.queryParams.removed === "true";
let freshlyAdded = currentRoute.queryParams.added === "true";
let ownedIntegrations = [];
let availableIntegrations = [];
const pageLimit = 20;
const builtInIntegrationCount = 1;
let page = 1;
function previousPage() {
if (page > 1) {
page--;
loadAvailableIntegrations();
}
}
function nextPage() {
if (hasNextPage) {
page++;
loadAvailableIntegrations();
}
}
let hasNextPage = true;
$: if (page === 1) {
hasNextPage = availableIntegrations.length + builtInIntegrationCount >= pageLimit;
} else {
hasNextPage = availableIntegrations.length >= pageLimit;
}
function generateProxyUrl(integration) {
if (integration.image_url === null || integration.proxy_token === undefined || integration.proxy_token === null) {
return null;
}
return `https://image-cdn.ticketsbot.net/proxy?token=${integration.proxy_token}`
}
async function removeIntegration(integrationId) {
const res = await axios.delete(`${API_URL}/api/${guildId}/integrations/${integrationId}`);
if (res.status !== 204) {
notifyError(res.data.error);
return;
}
await loadAvailableIntegrations();
notifySuccess("Integration removed from server successfully");
}
async function loadAvailableIntegrations() {
const res = await axios.get(`${API_URL}/api/${guildId}/integrations/available?page=${page}`);
if (res.status !== 200) {
notifyError(res.data.error);
return
}
availableIntegrations = res.data;
}
async function loadOwnedIntegrations() {
let res = await axios.get(`${API_URL}/api/integrations/self`);
if (res.status !== 200) {
notifyError(res.data.error);
return;
}
ownedIntegrations = res.data;
}
withLoadingScreen(async () => {
setDefaultHeaders();
await Promise.all([
loadOwnedIntegrations(),
loadAvailableIntegrations()
]);
if (freshlyAdded) {
notifySuccess("Integration added to server successfully!");
} else if (freshlyRemoved) {
notifySuccess("Integration removed from server successfully!");
}
});
</script>
<style>
.parent {
display: flex;
justify-content: center;
width: 100%;
height: 100%;
}
.content {
display: flex;
flex-direction: column;
justify-content: space-between;
width: 96%;
height: 100%;
margin-top: 30px;
padding-bottom: 5vh;
row-gap: 4vh;
}
.container {
display: flex;
flex-direction: column;
}
.integrations {
display: flex;
flex-direction: row;
flex-wrap: wrap;
gap: 2%;
row-gap: 4vh;
}
.integration {
flex: 0 0 23.5%;
}
.my-integrations {
margin-top: 2vh;
}
.title {
color: white;
font-size: 22px;
font-weight: bolder;
}
.spread {
display: flex;
flex-direction: row;
justify-content: space-between;
gap: 10px;
}
.pagination {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
gap: 5px;
}
.pagination-chevron {
cursor: pointer;
color: #3472f7;
}
.disabled-chevron {
color: #777 !important;
cursor: default !important;
}
@media only screen and (max-width: 1180px) {
.integration {
flex: 0 0 32%;
}
}
@media only screen and (max-width: 930px) {
.integration {
flex: 0 0 49%;
}
}
@media only screen and (max-width: 576px) {
.integration {
flex: 0 0 100%;
}
}
</style>