app/src/ui/views/Dashboard.vue

391 lines
9.8 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div :class="{dashboard: true, 'edit-mode': editMode, lightMode: this.themeMode == 'light'}" :style="dashboardStyle">
<div @click="vade_click" class="vade">vade</div>
<div class="editmode-tiles">
<new-item-tile title="New App" v-if="editMode" @click="openNewApp" />
<new-item-tile title="New App Category" v-if="editMode" @click="openNewAppCat" />
<new-item-tile title="New Bookmark" v-if="editMode" @click="openNewBookmark" />
<new-item-tile title="New Bookmark Category" v-if="editMode" @click="openNewBookmarkCat" />
<div class="settings-tile" v-if="editMode" @click="settingsClick">
<font-awesome-icon icon="cog" />
</div>
</div>
<div class="container" v-if="appsForCategory(null).length > 0 || editMode">
<h1>APPLICATIONS</h1>
<div class="app-tiles">
<application-tile
@clicked="appTileClicked"
v-for="app in appsForCategory(null)"
:appData="app"
:key="app.id"
/>
</div>
</div>
<div class="container" v-for="cat in applicationCategories" :key="cat.id">
<h1 @click="appCatClicked(cat)" class="editable">
<font-awesome-icon v-if="cat.glyph" :icon="cat.glyph" />
{{cat.categoryName}}
</h1>
<div class="app-tiles">
<application-tile
@clicked="appTileClicked"
v-for="app in appsForCategory(cat.id)"
:appData="app"
:key="app.id"
/>
</div>
</div>
<div class="container" v-if="bookmarks.length">
<h1 class="bookmark">BOOKMARKS</h1>
<div class="bookmark-container">
<div class="bookmark-category" v-if="bookmarksForCategory(null).length">
<h2>UNCATEGORZED</h2>
<bookmark-tile
v-for="bm in bookmarksForCategory(null)"
:key="bm.id"
:bookmark="bm"
@clicked="bookmarkClicked"
/>
</div>
<div class="bookmark-category" v-for="cat in bookmarkCategories" :key="cat.id">
<h2 @click="bookmarkCatClicked(cat)" class="editable">
<font-awesome-icon v-if="cat.glyph" :icon="cat.glyph" />
{{cat.categoryName}}
</h2>
<bookmark-tile
@clicked="bookmarkClicked"
v-for="bm in bookmarksForCategory(cat.id)"
:key="bm.id"
:bookmark="bm"
/>
</div>
</div>
</div>
<edit-mode-button :editMode="editMode" @click="toggleEdit" />
<application-modal
:open="appOpen"
:data="editApp"
:categories="applicationCategories"
@close="closeNewApp"
@update="reload"
/>
<application-category-modal
:open="appCatOpen"
:data="editAppCat"
@close="closeNewAppCat"
@update="reload"
/>
<bookmark-modal
:open="bookmarkOpen"
:data="editBookmark"
:categories="bookmarkCategories"
@close="closeBookmark"
@update="reload"
/>
<bookmark-category-modal
:open="bookmarkCatOpen"
:data="editBookmarkCat"
@close="closeNewBookmarkCat"
@update="reload"
/>
</div>
</template>
<script>
import axios from "axios";
import ApplicationTile from "../components/ApplicationTile.vue";
import ApplicationModal from "../components/ApplicationModal.vue";
import ApplicationCategoryModal from "../components/ApplicationCategoryModal.vue";
import EditModeButton from "../components/EditModeButton.vue";
import NewItemTile from "../components/NewItemTile.vue";
import BookmarkModal from "../components/BookmarkModal.vue";
import BookmarkTile from "../components/BookmarkTile.vue";
import BookmarkCategoryModal from "../components/BookmarkCategoryModal.vue";
export default {
name: "Dashboard",
unmounted() {
this.connection = null;
},
methods: {
vade_click() {
window.open('https://vade.5σ.com/');
},
connect_ws() {
const token = localStorage.getItem("token")
this.connection = new WebSocket("ws://localhost:8089/events/" + encodeURIComponent(token));
this.connection.onmessage = (event) => {
const data = JSON.parse(event.data);
const { app_id, alive } = data.HealthcheckChange;
const idx = this.applications.findIndex((app) => app.id == app_id);
this.applications[idx].healthcheckStatus = alive;
}
this.connection.onclose = () => {
setTimeout(() => this.connect_ws(), 1000);
};
},
appsForCategory(catId) {
return this.applications.filter((i) => i.applicationCategoryId === catId);
},
bookmarksForCategory(catId) {
return this.bookmarks.filter((i) => i.bookmarkCategoryId === catId);
},
openNewApp() {
this.editApp = {};
this.appOpen = true;
},
openNewBookmark() {
this.bookmarkOpen = true;
},
closeNewApp() {
this.editApp = {};
this.appOpen = false;
},
closeBookmark() {
this.editBookmark = {};
this.bookmarkOpen = false;
},
openNewAppCat() {
this.appCatOpen = true;
this.editAppCat = {};
},
closeNewAppCat() {
this.editAppCat = {};
this.appCatOpen = false;
},
openNewBookmarkCat() {
this.bookmarkCatOpen = true;
},
closeNewBookmarkCat() {
this.editBookmarkCat = {};
this.bookmarkCatOpen = false;
},
settingsClick() {
this.$router.push("/settings");
},
toggleEdit() {
this.editMode = !this.editMode;
},
appTileClicked(e, app) {
if (this.editMode) {
this.editApp = app;
this.appOpen = true;
} else {
window.open(app.url);
}
},
appCatClicked(cat) {
if (this.editMode) {
this.editAppCat = cat;
this.appCatOpen = true;
}
},
bookmarkCatClicked(cat) {
if (this.editMode) {
this.editBookmarkCat = cat;
this.bookmarkCatOpen = true;
}
},
bookmarkClicked(bm) {
if (this.editMode) {
this.editBookmark = bm;
this.bookmarkOpen = true;
} else {
window.open(bm.url);
}
},
async reload() {
this.applications = (await axios.get("/api/applications")).data.items || [];
this.applicationCategories = (
await axios.get("/api/application_categories")
).data.items || [];
this.bookmarks = (await axios.get("/api/bookmarks")).data.items || [];
this.bookmarkCategories = (
await axios.get("/api/bookmark_categories")
).data.items || [];
this.editApp = {};
this.editAppCat = {};
this.appOpen = false;
this.appCatOpen = false;
this.editBookmark = {};
this.editBookmarkCat = {};
this.bookmarkCatOpen = false;
this.bookmarkOpen = false;
this.themeMode = (await axios.get("/api/settings/theme/mode")).data.mode || "dark";
localStorage.setItem("themeMode", this.themeMode);
},
},
components: {
ApplicationTile,
ApplicationModal,
ApplicationCategoryModal,
EditModeButton,
NewItemTile,
BookmarkModal,
BookmarkTile,
BookmarkCategoryModal,
},
computed: {
dashboardStyle() {
return {
backgroundImage: `url('${this.$rootUrl()}/bg.jpg')`
};
}
},
data() {
return {
editMode: false,
applications: [],
applicationCategories: [],
appOpen: false,
appCatOpen: false,
bookmarkOpen: false,
bookmarkCatOpen: false,
editApp: {},
editAppCat: {},
editBookmark: {},
editBookmarkCat: {},
bookmarks: [],
bookmarkCategories: [],
connection: null,
themeMode: localStorage.getItem("themeMode"),
};
},
async mounted() {
this.connect_ws();
this.reload();
},
};
</script>
<style scoped>
h1 {
margin-top: 0px;
font-weight: bold;
line-height: 1;
margin-bottom: 5px;
font-size: 18px;
padding-bottom: 10px;
color: rgba(255,255,255,0.25);
text-shadow: 1px 1px rgba(0,0,0,0.25);
text-transform: uppercase;
text-align: right;
}
.lightMode h1 {
color: rgba(0,0,0,0.5);
text-shadow: none;
}
h2 {
font-size: 18px;
text-transform: uppercase;
padding-left: 25px;
font-weight: bold;
margin-bottom: 5px;
color: rgba(255,255,255,0.25);
text-shadow: 1px 1px rgba(0,0,0,0.25);
}
.lightMode h2 {
color: rgba(0,0,0,0.5);
text-shadow: none;
}
.edit-mode .editable {
cursor: pointer;
}
h2 svg {
margin-right: 5px;
}
.app-tiles {
display: grid;
grid-template-columns: repeat(4, 25%);
}
.container {
padding: 25px;
width: 1000px;
margin: 20px auto;
-webkit-backdrop-filter: blur(6px);
backdrop-filter: blur(6px);
background-color: rgba(0,0,0,0.4);
border-radius: 15px;
}
.lightMode .container {
background-color: rgba(255,255,255,0.4);
}
.container svg {
color: rgba(255,255,255,0.25);
}
.lightMode .container svg {
color: rgba(0,0,0,0.25);
}
.dashboard {
user-select: none;
min-height: calc(100vh - 150px);
min-width: 100vw;
padding-top: 150px;
background-position: center center;
background-size: cover;
}
.editmode-tiles {
display: flex;
padding: 10px 50px;
width: 1000px;
margin: 15px auto;
flex-direction: row;
justify-content: space-between;
}
.bookmark-container {
display: grid;
grid-template-columns: repeat(4, 1fr);
}
.vade {
cursor: pointer;
font-size: 44px;
font-weight: 900;
color: rgba(255,255,255,0.035);
text-shadow: 1px 1px rgba(0,0,0,0.15);
position: absolute;
bottom: 20px;
left: 40px;
}
.settings-tile {
background: rgba(0,0,0,0.8);
transition: all 0.5s;
padding: 16px 25px;
border-radius: 5px;
margin: 5px;
cursor: pointer;
display: flex;
flex-direction: row;
align-items: flex-start;
}
.settings-tile:hover {
transition: all 0.1s;
box-shadow: rgba(0, 0, 0, 0.5) 0px 20px 30px -10px;
}
.settings-tile svg {
color: #fff;
margin: auto auto;
}
.lightMode .settings-tile {
background: rgba(255,255,255,0.8);
}
.lightMode .settings-tile svg {
color: #222;
}
</style>