Remove deprecated web interface

This commit is contained in:
Ske 2019-07-10 16:19:38 +02:00
parent d7ffa8830d
commit 8afb2f892b
14 changed files with 0 additions and 3895 deletions

View File

@ -1,14 +0,0 @@
{
"presets": [
[
"env",
{
"targets": {
"browsers": [
"last 2 Chrome versions"
]
}
}
]
]
}

3
web/.gitignore vendored
View File

@ -1,3 +0,0 @@
.cache/
dist/
node_modules/

View File

@ -1,63 +0,0 @@
import { EventEmitter } from "eventemitter3"
const SITE_ROOT = process.env.NODE_ENV === "production" ? "https://pluralkit.me" : "http://localhost:1234";
const API_ROOT = process.env.NODE_ENV === "production" ? "https://api.pluralkit.me" : "http://localhost:2939";
const CLIENT_ID = process.env.NODE_ENV === "production" ? "466378653216014359" : "467772037541134367";
export const AUTH_URI = `https://discordapp.com/api/oauth2/authorize?client_id=${CLIENT_ID}&redirect_uri=${encodeURIComponent(SITE_ROOT + "/auth/discord")}&response_type=code&scope=identify`
class API extends EventEmitter {
async init() {
this.token = localStorage.getItem("pk-token");
if (this.token) {
this.me = await fetch(API_ROOT + "/s", {headers: {"X-Token": this.token}}).then(r => r.json());
this.emit("update", this.me);
}
}
async fetchSystem(id) {
return await fetch(API_ROOT + "/s/" + id).then(r => r.json()) || null;
}
async fetchSystemMembers(id) {
return await fetch(API_ROOT + "/s/" + id + "/members").then(r => r.json()) || [];
}
async fetchSystemSwitches(id) {
return await fetch(API_ROOT + "/s/" + id + "/switches").then(r => r.json()) || [];
}
async fetchMember(id) {
return await fetch(API_ROOT + "/m/" + id).then(r => r.json()) || null;
}
async saveSystem(system) {
return await fetch(API_ROOT + "/s", {
method: "PATCH",
headers: {"X-Token": this.token},
body: JSON.stringify(system)
});
}
async login(code) {
this.token = await fetch(API_ROOT + "/discord_oauth", {method: "POST", body: code}).then(r => r.text());
this.me = await fetch(API_ROOT + "/s", {headers: {"X-Token": this.token}}).then(r => r.json());
if (this.me) {
localStorage.setItem("pk-token", this.token);
this.emit("update", this.me);
} else {
this.logout();
}
return this.me;
}
logout() {
localStorage.removeItem("pk-token");
this.emit("update", null);
this.token = null;
this.me = null;
}
}
export default new API();

View File

@ -1,84 +0,0 @@
<template>
<div class="app">
<b-navbar>
<b-navbar-brand :to="{name: 'home'}">PluralKit</b-navbar-brand>
<b-navbar-toggle target="nav-collapse"></b-navbar-toggle>
<b-collapse id="nav-collapse" is-nav>
<b-navbar-nav class="ml-auto">
<b-nav-item v-if="me" :to="{name: 'system', params: {id: me.id}}">My system</b-nav-item>
<b-nav-item variant="primary" :href="authUri" v-if="!me">Log in</b-nav-item>
<b-nav-item v-on:click="logout" v-if="me">Log out</b-nav-item>
</b-navbar-nav>
</b-collapse>
</b-navbar>
<router-view :me="me"></router-view>
</div>
</template>
<script>
import BCollapse from 'bootstrap-vue/es/components/collapse/collapse';
import BNav from 'bootstrap-vue/es/components/nav/nav';
import BNavItem from 'bootstrap-vue/es/components/nav/nav-item';
import BNavbar from 'bootstrap-vue/es/components/navbar/navbar';
import BNavbarBrand from 'bootstrap-vue/es/components/navbar/navbar-brand';
import BNavbarNav from 'bootstrap-vue/es/components/navbar/navbar-nav';
import BNavbarToggle from 'bootstrap-vue/es/components/navbar/navbar-toggle';
import API from "./API";
import { AUTH_URI } from "./API";
export default {
data() {
return {
me: null
}
},
created() {
API.on("update", this.apply);
API.init();
},
methods: {
apply(system) {
this.me = system;
},
logout() {
API.logout();
}
},
computed: {
authUri() {
return AUTH_URI;
}
},
components: {BCollapse, BNav, BNavItem, BNavbar, BNavbarBrand, BNavbarNav, BNavbarToggle}
};
</script>
<style lang="scss">
$font-family-sans-serif: "PT Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji" !default;
$container-max-widths: (
sm: 540px,
md: 720px,
lg: 959px,
xl: 960px,
) !default;
@import '~bootstrap/scss/_functions';
@import '~bootstrap/scss/_variables';
@import '~bootstrap/scss/_mixins';
@import '~bootstrap/scss/_buttons';
@import '~bootstrap/scss/_code';
@import '~bootstrap/scss/_forms';
@import '~bootstrap/scss/_grid';
@import '~bootstrap/scss/_nav';
@import '~bootstrap/scss/_navbar';
@import '~bootstrap/scss/_reboot';
@import '~bootstrap/scss/_type';
@import '~bootstrap/scss/_utilities';
@import '~bootstrap-vue/src/index.scss';
</style>

View File

@ -1,9 +0,0 @@
<template>
<h1>Hello</h1>
</template>
<script>
export default {
}
</script>

View File

@ -1,66 +0,0 @@
<template>
<div class="member-card">
<div
class="member-avatar"
:style="{backgroundImage: `url(${member.avatar_url})`, borderColor: member.color}"
></div>
<div class="member-body">
<span class="member-name">{{ member.name }}</span>
<div class="member-description">{{ member.description }}</div>
<ul class="taglist">
<li>
<hash-icon></hash-icon>
{{ member.id }}
</li>
<li v-if="member.birthday">
<calendar-icon></calendar-icon>
{{ member.birthday }}
</li>
<li v-if="member.pronouns">
<message-circle-icon></message-circle-icon>
{{ member.pronouns }}
</li>
</ul>
</div>
</div>
</template>
<script>
import CalendarIcon from "vue-feather-icons/icons/CalendarIcon";
import HashIcon from "vue-feather-icons/icons/HashIcon";
import MessageCircleIcon from "vue-feather-icons/icons/MessageCircleIcon";
export default {
props: ["member"],
components: { HashIcon, CalendarIcon, MessageCircleIcon }
};
</script>
<style lang="scss">
.member-card {
display: flex;
flex-direction: row;
.member-avatar {
margin: 1.5rem 1rem 0 0;
border-radius: 50%;
background-size: cover;
background-position: top center;
flex-basis: 4rem;
height: 4rem;
border: 4px solid white;
}
.member-body {
flex: 1;
display: flex;
flex-direction: column;
padding: 1rem 1rem 1rem 0;
.member-name {
font-size: 13pt;
font-weight: bold;
}
}
}
</style>

View File

@ -1,93 +0,0 @@
<template>
<b-container v-if="loading" class="d-flex justify-content-center">
<b-spinner class="m-5"></b-spinner>
</b-container>
<b-container v-else-if="error">Error</b-container>
<b-container v-else>
<h1>Editing "{{member.name}}"</h1>
<b-form>
<b-form-group label="Name">
<b-form-input v-model="member.name" required></b-form-input>
</b-form-group>
<b-form-group label="Description">
<b-form-textarea v-model="member.description" rows="3" max-rows="6"></b-form-textarea>
</b-form-group>
<b-form-group label="Proxy tags">
<b-row>
<b-col>
<b-input-group prepend="Prefix">
<b-form-input class="text-right" v-model="member.prefix" placeholder="ex: ["></b-form-input>
</b-input-group>
</b-col>
<b-col>
<b-input-group append="Suffix">
<b-form-input v-model="member.suffix" placeholder="ex: ]"></b-form-input>
</b-input-group>
</b-col>
<b-col></b-col>
</b-row>
<template
v-slot:description
v-if="member.prefix || member.suffix"
>Example proxy message: {{member.prefix}}text{{member.suffix}}</template>
<template v-slot:description v-else>(no prefix or suffix defined, proxying will be disabled)</template>
</b-form-group>
<b-form-group label="Pronouns" description="Free text field - put anything you'd like :)">
<b-form-input v-model="member.pronouns" placeholder="eg. he/him"></b-form-input>
</b-form-group>
<b-row>
<b-col md>
<b-form-group label="Birthday">
<b-input-group>
<b-input-group-prepend is-text>
<input type="checkbox" v-model="hideBirthday" label="uwu">&nbsp;Hide year
</b-input-group-prepend>
<b-form-input v-model="member.birthday" type="date"></b-form-input>
</b-input-group>
</b-form-group>
</b-col>
<b-col md>
<b-form-group label="Color" description="Will be displayed on system profile cards.">
<b-form-input type="color" v-model="member.color"></b-form-input>
</b-form-group>
</b-col>
</b-row>
</b-form>
</b-container>
</template>
<script>
import API from "./API";
export default {
props: ["id"],
data() {
return {
loading: false,
error: false,
hideBirthday: false,
member: null
};
},
created() {
this.fetch();
},
methods: {
async fetch() {
this.loading = true;
this.error = false;
this.member = await API.fetchMember(this.id);
if (!this.member) this.error = true;
this.loading = false;
}
}
};
</script>
<style>
</style>

View File

@ -1,20 +0,0 @@
<template>
<b-container class="d-flex justify-content-center"><span class="sr-only">Loading...</span><b-spinner class="m-5"></b-spinner></b-container>
</template>
<script>
import API from "./API";
export default {
async created() {
const code = this.$route.query.code;
if (!code) this.$router.push({ name: "home" });
const me = await API.login(code);
if (me) this.$router.push({ name: "home" });
}
}
</script>
<style>
</style>

View File

@ -1,83 +0,0 @@
<template>
<b-container>
<b-container v-if="loading" class="d-flex justify-content-center"><b-spinner class="m-5"></b-spinner></b-container>
<b-form v-else>
<h1>Editing "{{ system.name || system.id }}"</h1>
<b-form-group label="System name">
<b-form-input v-model="system.name" placeholder="Enter something..."></b-form-input>
</b-form-group>
<b-form-group label="Description">
<b-form-textarea v-model="system.description" placeholder="Enter something..." rows="3" max-rows="3" maxlength="1000"></b-form-textarea>
</b-form-group>
<b-form-group label="System tag">
<b-form-input maxlength="30" v-model="system.tag" placeholder="Enter something..."></b-form-input>
<template v-slot:description>
This is added to the names of proxied accounts. For example: <code>John {{ system.tag }}</code>
</template>
</b-form-group>
<b-form-group class="d-flex justify-content-end">
<b-button type="reset" variant="outline-secondary">Back</b-button>
<b-button v-if="!saving" type="submit" variant="primary" v-on:click="save">Save</b-button>
<b-button v-else variant="primary" disabled>
<b-spinner small></b-spinner>
<span class="sr-only">Saving...</span>
</b-button>
<b-form-group>
</b-form>
</b-container>
</template>
<script>
import BButton from 'bootstrap-vue/es/components/button/button';
import BContainer from 'bootstrap-vue/es/components/layout/container';
import BLink from 'bootstrap-vue/es/components/link/link';
import BSpinner from 'bootstrap-vue/es/components/spinner/spinner';
import BForm from 'bootstrap-vue/es/components/form/form';
import BFormInput from 'bootstrap-vue/es/components/form-input/form-input';
import BFormGroup from 'bootstrap-vue/es/components/form-group/form-group';
import BFormTextarea from 'bootstrap-vue/es/components/form-textarea/form-textarea';
import API from "./API";
export default {
data() {
return {
loading: false,
saving: false,
system: null
}
},
props: ["me", "id"],
created() {
this.fetch()
},
watch: {
"id": "fetch"
},
methods: {
async fetch() {
this.loading = true;
this.system = await API.fetchSystem(this.id);
if (!this.me || !this.system || this.system.id != this.me.id) {
this.$router.push({name: "system", params: {id: this.id}});
}
this.loading = false;
},
async save() {
this.saving = true;
if (await API.saveSystem(this.system)) {
this.$router.push({ name: "system", params: {id: this.system.id} });
}
this.saving = false;
}
},
components: {BButton, BContainer, BLink, BSpinner, BForm, BFormGroup, BFormInput, BFormTextarea}
}
</script>
<style>
</style>

View File

@ -1,113 +0,0 @@
<template>
<b-container v-if="loading" class="d-flex justify-content-center"><b-spinner class="m-5"></b-spinner></b-container>
<b-container v-else-if="error">An error occurred.</b-container>
<b-container v-else>
<ul v-if="system" class="taglist">
<li>
<hash-icon></hash-icon>
{{ system.id }}
</li>
<li v-if="system.tag">
<tag-icon></tag-icon>
{{ system.tag }}
</li>
<li v-if="system.tz">
<clock-icon></clock-icon>
{{ system.tz }}
</li>
<li v-if="isMine" class="ml-auto">
<b-link :to="{name: 'edit-system', params: {id: system.id}}">
<edit-2-icon></edit-2-icon>
Edit
</b-link>
</li>
</ul>
<h1 v-if="system && system.name">{{ system.name }}</h1>
<div v-if="system && system.description">{{ system.description }}</div>
<h2>Members</h2>
<div v-if="members">
<MemberCard v-for="member in members" :member="member" :key="member.id"/>
</div>
</b-container>
</template>
<script>
import API from "./API";
import BContainer from 'bootstrap-vue/es/components/layout/container';
import BLink from 'bootstrap-vue/es/components/link/link';
import BSpinner from 'bootstrap-vue/es/components/spinner/spinner';
import MemberCard from "./MemberCard.vue";
import Edit2Icon from "vue-feather-icons/icons/Edit2Icon";
import ClockIcon from "vue-feather-icons/icons/ClockIcon";
import HashIcon from "vue-feather-icons/icons/HashIcon";
import TagIcon from "vue-feather-icons/icons/TagIcon";
export default {
data() {
return {
loading: false,
error: false,
system: null,
members: null
};
},
props: ["me", "id"],
created() {
this.fetch();
},
methods: {
async fetch() {
this.loading = true;
this.system = await API.fetchSystem(this.id);
if (!this.system) {
this.error = true;
this.loading = false;
return;
}
this.members = await API.fetchSystemMembers(this.id);
this.loading = false;
}
},
watch: {
id: "fetch"
},
computed: {
isMine() {
return this.system && this.me && this.me.id == this.system.id;
}
},
components: {
Edit2Icon,
ClockIcon,
HashIcon,
TagIcon,
MemberCard,
BContainer, BLink, BSpinner
}
};
</script>
<style lang="scss">
.taglist {
margin: 0;
padding: 0;
color: #aaa;
display: flex;
li {
display: inline-block;
margin-right: 1rem;
list-style-type: none;
.feather {
display: inline-block;
margin-top: -2px;
width: 1em;
}
}
}
</style>

View File

@ -1,23 +0,0 @@
import Vue from "vue";
import VueRouter from "vue-router";
Vue.use(VueRouter);
const App = () => import("./App.vue");
const HomePage = () => import("./HomePage.vue");
const SystemPage = () => import("./SystemPage.vue");
const SystemEditPage = () => import("./SystemEditPage.vue");
const MemberEditPage = () => import("./MemberEditPage.vue");
const OAuthRedirectPage = () => import("./OAuthRedirectPage.vue");
const router = new VueRouter({
mode: "history",
routes: [
{ name: "home", path: "/", component: HomePage },
{ name: "system", path: "/s/:id", component: SystemPage, props: true },
{ name: "edit-system", path: "/s/:id/edit", component: SystemEditPage, props: true },
{ name: "edit-member", path: "/m/:id/edit", component: MemberEditPage, props: true },
{ name: "auth-discord", path: "/auth/discord", component: OAuthRedirectPage }
]
})
new Vue({ el: "#app", render: r => r(App), router });

View File

@ -1,9 +0,0 @@
<html>
<head>
<link href="https://fonts.googleapis.com/css?family=PT+Sans:400,700" rel="stylesheet">
</head>
<body>
<div id="app"></div>
<script src="app/index.js"></script>
</body>
</html>

View File

@ -1,19 +0,0 @@
{
"dependencies": {
"bootstrap": "^4.3.1",
"bootstrap-vue": "^2.0.0-rc.16",
"eventemitter3": "^3.1.0",
"vue": "^2.6.10",
"vue-feather-icons": "^4.10.0",
"vue-router": "^3.0.2"
},
"devDependencies": {
"@vue/component-compiler-utils": "^2.6.0",
"babel-core": "^6.26.3",
"babel-preset-env": "^1.7.0",
"cssnano": "^4.1.10",
"parcel-plugin-bundle-visualiser": "^1.2.0",
"sass": "^1.17.3",
"vue-template-compiler": "^2.6.10"
}
}

File diff suppressed because it is too large Load Diff