Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions www/webapp/.gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
.DS_Store
node_modules
.vite

/tests/e2e/videos/
/tests/e2e/screenshots/
Expand Down
23 changes: 14 additions & 9 deletions www/webapp/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
"serve": "vite preview",
"build": "vite build",
"lint": "eslint --ignore-path .gitignore --no-fix src/**/*.{vue,js,json}",
"lint:fix": "eslint --ignore-path .gitignore --fix src/**/*.{vue,js,json}"
"lint:fix": "eslint --ignore-path .gitignore --fix src/**/*.{vue,js,json}",
"postinstall": "vue-demi-switch 3"
},
"type": "module",
"engines": {
Expand All @@ -16,26 +17,30 @@
"dependencies": {
"@fontsource/roboto": "^5.0.3",
"@mdi/js": "~7.4.47",
"@vuelidate/core": "^2.0.3",
"@vuelidate/validators": "^2.0.4",
"axios": "^1.4.0",
"date-fns": "^4.1.0",
"pinia": "^2.0.30",
"vue": "~2.7.14",
"vue-router": "~3.6.5",
"vuelidate": "^0.7.7",
"vuetify": "^2.7.0"
"vue": "^3.4.19",
"vue-router": "^4.3.0",
"vuetify": "^3.7.5"
},
"devDependencies": {
"@vitejs/plugin-legacy": "^6.0.0",
"@vitejs/plugin-vue2": "^2.3.3",
"@vitejs/plugin-vue": "^5.2.0",
"eslint": "^8.45.0",
"eslint-import-resolver-alias": "^1.1.2",
"eslint-plugin-import": "^2.27.5",
"eslint-plugin-vue": "^9.15.1",
"eslint-plugin-vue-scoped-css": "^2.6.1",
"eslint-plugin-vuetify": "^1.1.0",
"eslint-plugin-vuetify": "^2.1.1",
"sass": "~1.83.4",
"unplugin-vue-components": "^28.0.0",
"vite": "^6.0.11",
"vuetify-loader": "~1.9.1"
"vite-plugin-vuetify": "^2.0.4",
"vue-demi": "^0.14.10"
},
"overrides": {
"vue-demi": "^0.14.10"
}
}
224 changes: 127 additions & 97 deletions www/webapp/src/App.vue
Original file line number Diff line number Diff line change
@@ -1,90 +1,91 @@
<template>
<v-app id="inspire">
<v-navigation-drawer
v-model="drawer"
app
right
disable-resize-watcher
v-model="drawer"
app
location="right"
disable-resize-watcher
>
<v-list dense>
<v-list density="compact">
<v-list-item
v-for="(item, key) in menu"
:key="key"
link
:to="{name: item.name}"
:exact="true">
<v-list-item-action>
<v-icon>{{ item.icon }}</v-icon>
</v-list-item-action>
<v-list-item-content>
<v-list-item-title>
{{ item.text }}
<v-icon :color="item.post_icon_color" class="text--darken-2" small v-if="item.post_icon">{{ item.post_icon }}</v-icon>
</v-list-item-title>
</v-list-item-content>
v-for="(item, key) in menu"
:key="key"
:to="{name: item.name}"
:exact="true"
>
<template #prepend>
<v-icon :icon="item.icon" />
</template>
<v-list-item-title>
{{ item.text }}
<v-icon v-if="item.post_icon" :icon="item.post_icon" :color="item.post_icon_color" size="small" />
</v-list-item-title>
</v-list-item>
</v-list>
</v-navigation-drawer>

<v-app-bar app class="white">
<v-toolbar-title><router-link :to="{name: 'home'}">
<v-app-bar app color="white" :extended="authenticated">
<v-app-bar-title><router-link :to="{name: 'home'}">
<v-img
src="./assets/logo.svg"
alt="deSEC Logo"
eager
contain
src="./assets/logo.svg"
alt="deSEC Logo"
class="app-logo"
height="32"
eager
contain
></v-img>
</router-link></v-toolbar-title>
</router-link></v-app-bar-title>
<v-spacer/>
<div class="d-none d-md-block">
<span class="mx-2" v-for="(item, key) in menu" :key="key">
<router-link
class="primary--text text--darken-2"
:to="{name: item.name}"
class="text-primary"
:to="{name: item.name}"
>{{ item.text }}</router-link>
<v-icon :color="item.post_icon_color" class="ml-1 text--darken-1" small v-if="item.post_icon">{{ item.post_icon }}</v-icon>
<v-icon v-if="item.post_icon" :icon="item.post_icon" :color="item.post_icon_color" class="ml-1" size="small" />
</span>
</div>
<v-btn class="mx-4" color="primary" depressed :to="{name: 'signup', query: $route.query}" v-if="!user.authenticated">Create Account</v-btn>
<v-btn class="mx-4 mr-0" color="primary" depressed :to="{name: 'login'}" v-if="!user.authenticated">Log In</v-btn>
<v-btn class="mx-4 mr-0" color="primary" depressed outlined @click="logout" v-if="user.authenticated">Log Out</v-btn>
<v-btn class="mx-4" color="primary" variant="flat" :to="{name: 'signup', query: $route.query}" v-if="!authenticated">Create Account</v-btn>
<v-btn class="mx-4 mr-0" color="primary" variant="flat" :to="{name: 'login'}" v-if="!authenticated">Log In</v-btn>
<v-btn class="mx-4 mr-0" color="primary" variant="outlined" @click="logout" v-if="authenticated">Log Out</v-btn>
<v-app-bar-nav-icon class="d-md-none" @click.stop="drawer = !drawer" />
<template #extension v-if="user.authenticated">
<v-tabs background-color="primary darken-1" fixed-tabs>
<v-tab
v-for="(item, key) in tabmenu"
:key="key"
:to="{name: item.name}"
>
{{ item.text }}
</v-tab>
<v-spacer></v-spacer>
<v-menu
bottom
left
>
<template #activator="{ on }">
<template #extension v-if="authenticated">
<div class="d-flex align-center w-100 bg-primary text-white">
<v-tabs v-model="activeTab" class="flex-grow-1 text-white" bg-color="primary" color="white" slider-color="white" grow>
<v-tab
v-for="(item, key) in tabmenu"
:key="key"
:value="item.name"
:to="{name: item.name}"
class="text-white"
>
{{ item.text }}
</v-tab>
</v-tabs>
<v-menu location="bottom">
<template #activator="{ props }">
<v-btn
text
class="align-self-center mr-4"
v-on="on"
variant="text"
color="white"
class="align-self-center mr-4"
v-bind="props"
>
more
<v-icon right>{{ mdiMenuDown }}</v-icon>
<v-icon :icon="mdiMenuDown" end />
</v-btn>
</template>

<v-list class="grey lighten-3">
<v-list class="bg-grey-lighten-3">
<v-list-item
v-for="(item, key) in tabmenumore"
:key="key"
:to="{name: item.name}"
v-for="(item, key) in tabmenumore"
:key="key"
:to="{name: item.name}"
>
{{ item.text }}
</v-list-item>
</v-list>
</v-menu>
</v-tabs>
</div>
</template>
</v-app-bar>

Expand All @@ -94,23 +95,22 @@
<v-icon
color="warning"
size="36"
>
{{ alert.icon }}
</v-icon>
:icon="alert.icon"
/>
</template>
{{ alert.teaser }}
<template #actions>
<v-btn
color="primary"
depressed
variant="flat"
:href="alert.href"
v-if="alert.href"
>
{{ alert.button || 'More' }}
</v-btn>
<v-btn
color="primary"
text
variant="text"
@click="user.unalert(alert.id)"
>
Hide
Expand All @@ -127,9 +127,9 @@
<router-view/>
</v-main>
<v-footer
class="d-flex flex-column align-stretch pa-0 white--text text--darken-1 elevation-12"
class="d-flex flex-column align-stretch pa-0 text-white elevation-12"
>
<div class="grey darken-3 d-sm-flex flex-row justify-space-between pa-4">
<div class="bg-grey-darken-3 d-sm-flex flex-row justify-space-between pa-4">
<div class="pa-2">
<b>deSEC e.V.</b>
</div>
Expand All @@ -141,7 +141,7 @@
<div class="px-2"><router-link :to="{name: 'impressum'}">Legal Notice (Impressum)</router-link></div>
</div>
</div>
<div class="grey darken-4 d-md-flex flex-row justify-space-between pa-6">
<div class="bg-grey-darken-4 d-md-flex flex-row justify-space-between pa-6">
<div>
<p>{{ email }}</p>
<p>
Expand All @@ -153,7 +153,7 @@
<div>
<p>
Please <router-link :to="{name: 'donate'}">donate</router-link>!
<v-icon color="red" class="text--darken-2" dense>{{ mdiHeart }}</v-icon>
<v-icon :icon="mdiHeart" color="red" />
</p>
<p>
European Bank Account:<br>
Expand All @@ -167,7 +167,7 @@
</div>
<div>
<p>Vorstand</p>
<p class="white--text text--darken-2">
<p class="text-white">
Nils Wisiol<br/>
Peter Thomassen<br/>
Wolfgang Studier<br/>
Expand Down Expand Up @@ -196,38 +196,10 @@ import {

export default {
name: 'App',
data: () => ({
user: useUserStore(),
drawer: false,
email: import.meta.env.VITE_APP_EMAIL,
mdiHeart,
mdiMenuDown,
tabmenu: {
'domains': {
'name': 'domains',
'text': 'Domain Management',
},
'tokens': {
'name': 'tokens',
'text': 'Token Management',
},
},
tabmenumore: {
'totp': {
'name': 'totp',
'text': 'Manage 2-Factor Authentication',
},
'change-email': {
'name': 'change-email',
'text': 'Change Email Address',
},
'delete-account': {
'name': 'delete-account',
'text': 'Delete Account',
},
},
}),
computed: {
authenticated() {
return this.user?.authenticated;
},
menu: () => {
const user = useUserStore();
const menu_perma = {
Expand Down Expand Up @@ -277,6 +249,46 @@ export default {
return {...menu_perma, ...menu_opt};
},
},
data: () => ({
user: useUserStore(),
drawer: false,
email: import.meta.env.VITE_APP_EMAIL,
activeTab: null,
mdiHeart,
mdiMenuDown,
tabmenu: {
'domains': {
'name': 'domains',
'text': 'Domain Management',
},
'tokens': {
'name': 'tokens',
'text': 'Token Management',
},
},
tabmenumore: {
'totp': {
'name': 'totp',
'text': 'Manage 2-Factor Authentication',
},
'change-email': {
'name': 'change-email',
'text': 'Change Email Address',
},
'delete-account': {
'name': 'delete-account',
'text': 'Delete Account',
},
},
}),
watch: {
$route: {
immediate: true,
handler(to) {
this.activeTab = to?.name ?? null;
},
},
},
methods: {
async logout() {
await logout();
Expand All @@ -285,3 +297,21 @@ export default {
}
}
</script>

<style>
.v-application a {
color: rgb(var(--v-theme-primary));
text-decoration: none;
}
.v-application a:hover,
.v-application a:focus {
text-decoration: underline;
}
.v-application .bg-grey-darken-3 a,
.v-application .bg-grey-darken-4 a {
color: rgb(var(--v-theme-secondary));
}
.app-logo {
width: auto;
}
</style>
Loading