diff --git a/discord-invite/index.html b/discord-invite/index.html new file mode 100644 index 00000000..8a803912 --- /dev/null +++ b/discord-invite/index.html @@ -0,0 +1,34 @@ + + + + + + + + + Discord Invite + + + +
+

Create Discord invite for RDS Server

+
+ +
+ + + +
+ + diff --git a/discord-invite/script.js b/discord-invite/script.js new file mode 100644 index 00000000..834ad365 --- /dev/null +++ b/discord-invite/script.js @@ -0,0 +1,52 @@ +// Script file for discord-invite feature. +import { + createElement, + getIsSuperUser, + generateDiscordInviteLink, +} from './utils.js'; + +const discordInviteDescription = document.querySelector( + '#discord-invite-link-description', +); +const createInviteButton = document.querySelector('#create-discord-invite'); +const loader = document.querySelector('.loader'); +const mainContainer = document.querySelector('.container'); +const subContainer = document.querySelector('.wrapper'); +const showDataWrapper = document.querySelector('.show-data-wrapper'); +const invitePurpose = document.querySelector('.invite-purpose'); +const discordInviteLink = document.querySelector('.discord-invite-link'); + +function changeLoaderVisibility({ hide }) { + if (hide) loader.classList.add('hidden'); + else loader.classList.remove('hidden'); +} + +(async function renderCardsInitial() { + changeLoaderVisibility({ hide: false }); + + const isSuperUser = await getIsSuperUser(); + + if (!isSuperUser) { + const unAuthorizedText = createElement({ + type: 'h2', + attributes: { class: 'unauthorized-text' }, + innerText: 'You are not authorized to view this page.', + }); + mainContainer.append(unAuthorizedText); + subContainer.classList.add('hidden'); + changeLoaderVisibility({ hide: true }); + return; + } + + subContainer.classList.remove('hidden'); + + changeLoaderVisibility({ hide: true }); +})(); + +createInviteButton.addEventListener('click', async () => { + const data = await generateDiscordInviteLink(discordInviteDescription.value); + subContainer.classList.add('hidden'); + showDataWrapper.classList.remove('hidden'); + invitePurpose.innerHTML = data.purpose; + discordInviteLink.innerHTML = data.inviteLink; +}); diff --git a/discord-invite/style.css b/discord-invite/style.css new file mode 100644 index 00000000..9eeab8e0 --- /dev/null +++ b/discord-invite/style.css @@ -0,0 +1,69 @@ +:root { + font-family: 'Inter', sans-serif; + --color-primary: #1d1283; + --color-primary-hover: #11085c; + --color-button-hover: #2c1bc6; + --white: #fff; + --color-gray: #666; + --black-color: black; + --black-transparent: #000000a8; + --light-gray-color: lightgray; + --red-color: red; + --elevation-1: 0 1px 3px 1px rgba(0, 0, 0, 0.1), + 0 1px 2px 0 rgba(0, 0, 0, 0.1); + --elevation-3: 0px 1px 3px 0px rgba(0, 0, 0, 0.3), + 0px 4px 8px 3px rgba(0, 0, 0, 0.15); + --color-green: green; + --color-red-variant1: #f43030; +} + +body { + font-family: 'Roboto', sans-serif; + margin: 0; + padding: 0; +} + +.header { + text-align: center; +} + +.container { + text-align: center; +} + +.wrapper { + display: flex; + justify-content: center; + align-items: center; +} + +.create-discord-invite { + margin: 2rem; + padding: 10px; +} + +.hidden { + visibility: hidden; +} + +#toast { + position: fixed; + top: 20px; + right: -300px; + color: #fff; + padding: 15px; + border-radius: 5px; +} + +.success { + background: var(--color-green); +} + +.failure { + background: var(--color-red-variant1); +} + +.animated_toast { + animation: slideIn 0.5s ease-in-out forwards, + slideOut 0.5s ease-in-out 2.5s forwards; +} diff --git a/discord-invite/utils.js b/discord-invite/utils.js new file mode 100644 index 00000000..17d815ef --- /dev/null +++ b/discord-invite/utils.js @@ -0,0 +1,77 @@ +const BASE_URL = + window.location.hostname === 'localhost' + ? 'https://staging-api.realdevsquad.com' + : window.API_BASE_URL; + +const toast = document.getElementById('toast'); + +function createElement({ type, attributes = {}, innerText }) { + const element = document.createElement(type); + Object.keys(attributes).forEach((item) => { + element.setAttribute(item, attributes[item]); + }); + element.textContent = innerText; + return element; +} + +async function getIsSuperUser() { + try { + const res = await fetch(`${BASE_URL}/users/self`, { + method: 'GET', + credentials: 'include', + headers: { + 'Content-type': 'application/json', + }, + }); + const self_user = await res.json(); + return self_user?.roles['super_user']; + } catch (error) { + console.error(error); + const errorMessage = error?.message || 'Something went wrong!'; + showToast({ message: errorMessage, type: 'error' }); + } +} + +async function generateDiscordInviteLink(purpose) { + const body = { + purpose, + }; + try { + const res = await fetch(`${BASE_URL}/discord-actions/invite?dev=true`, { + method: 'POST', + credentials: 'include', + body: JSON.stringify(body), + headers: { + 'Content-type': 'application/json', + }, + }); + const data = await res.json(); + return data; + } catch (error) { + console.error(error); + const errorMessage = error?.message || 'Something went wrong!'; + showToast({ message: errorMessage, type: 'error' }); + } +} + +function showToast({ message, type }) { + toast.innerText = message; + + if (type === 'success') { + toast.classList.add('success'); + toast.classList.remove('failure'); + } else { + toast.classList.add('failure'); + toast.classList.remove('success'); + } + + toast.classList.remove('hidden'); + toast.classList.add('animated_toast'); + + setTimeout(() => { + toast.classList.add('hidden'); + toast.classList.remove('animated_toast'); + }, 3000); +} + +export { createElement, getIsSuperUser, showToast, generateDiscordInviteLink }; diff --git a/index.html b/index.html index b473a0bf..270d9e6d 100644 --- a/index.html +++ b/index.html @@ -146,6 +146,13 @@ Applications + + Create Discord Invite +