Commit 8970142c authored by Richard Blechinger's avatar Richard Blechinger
Browse files

Auth wall and permission implementation. Minor cleanups in design

parent 8ba13dab
......@@ -8077,9 +8077,9 @@
}
},
"jquery": {
"version": "3.4.1",
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.4.1.tgz",
"integrity": "sha512-36+AdBzCL+y6qjw5Tx7HgzeGCzC81MDDgaUP8ld2zhx58HdqXGoBd+tHdrBMiyjGQs0Hxs/MLZTu/eHNJJuWPw=="
"version": "3.5.1",
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.5.1.tgz",
"integrity": "sha512-XwIBPqcMn57FxfT+Go5pzySnm4KWkT1Tv7gjrpT1srtf8Weynl6R273VJ5GjkRb51IzMp5nbaPjJXMWeju2MKg=="
},
"js-levenshtein": {
"version": "1.1.6",
......@@ -13548,6 +13548,11 @@
"integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==",
"dev": true
},
"vue-toast-notification": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/vue-toast-notification/-/vue-toast-notification-0.6.0.tgz",
"integrity": "sha512-GSXLTemx/+YLDpeObuMcz+gQ6NxvBcJxGhj5PB8CZDDBUQWbeAp0ZUPZEixDun/GtbxBOA9jLxo4MFPHTbIBYw=="
},
"vuejs-logger": {
"version": "1.5.4",
"resolved": "https://registry.npmjs.org/vuejs-logger/-/vuejs-logger-1.5.4.tgz",
......
......@@ -5,7 +5,7 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title>dboard</title>
<title>AURA Dashboard</title>
</head>
<body>
<noscript>
......
......@@ -6,81 +6,133 @@
/>
<div class="tw-flex-1 tw-flex tw-my-8">
<router-view/>
<router-view :modules="modules" :user="user"/>
</div>
<app-footer />
<app-footer :modules="modules"/>
</div>
</template>
<script>
import 'bootstrap/dist/css/bootstrap.css'
import 'bootstrap-vue/dist/bootstrap-vue.css'
import 'bootstrap/dist/css/bootstrap.css'
import 'bootstrap-vue/dist/bootstrap-vue.css'
import { translationVm } from '@/plugins/translation'
import {translationVm} from '@/plugins/translation'
import header from './components/Header.vue'
import footer from './components/Footer.vue'
import header from './components/Header.vue'
import footer from './components/Footer.vue'
export default {
export default {
name: 'App',
components: {
'app-header': header,
'app-footer': footer
},
computed: {
userOIDC () { return this.$store.state.auth.userOIDC },
user () { return this.$store.state.auth.user },
userOIDC() {
return this.$store.state.auth.userOIDC
},
user() {
return this.$store.state.auth.user
},
localeKey: () => translationVm.activeLocale,
modules: function () {
// Logged out
let modules = [
{ slug: 'home', title: this.$t('navigation.home') },
]
let modules = []
// All icons used are taken from the Tango Project, which put them into public domain:
// http://tango.freedesktop.org
if (this.user.logged_in === true) {
modules = (this.user.steeringUser && this.user.steeringUser.is_superuser)
// Super user
? [ { slug: 'home', title: this.$t('navigation.home') },
{ slug: 'shows', title: this.$t('navigation.shows') },
{ slug: 'files', title: this.$t('navigation.filesPlaylists') },
{ slug: 'calendar', title: this.$t('navigation.calendar') }, ]
? {
main: [
{
icon: '/assets/applications-multimedia.png',
slug: 'shows',
title: this.$t('navigation.shows')
},
{
icon: '/assets/audio-x-generic.png',
slug: 'files',
title: this.$t('navigation.filesPlaylists')
},
{
icon: '/assets/x-office-calendar.png',
slug: 'calendar',
title: this.$t('navigation.calendar')
},
],
footer: [
{
slug: 'settings',
title: this.$t('navigation.settings'),
},
{
slug: 'help',
title: this.$t('navigation.help'),
}
]
}
// Regular user
: [ { slug: 'home', title: this.$t('navigation.home') },
{ slug: 'shows', title: this.$t('navigation.shows') },
{ slug: 'files', title: this.$t('navigation.filesPlaylists') }, ]
: {
main: [
{
icon: '/assets/applications-multimedia.png',
slug: 'shows',
title: this.$t('navigation.shows')
},
{
icon: '/assets/audio-x-generic.png',
slug: 'files',
title: this.$t('navigation.filesPlaylists')
},
],
footer: [
{
slug: 'help',
title: this.$t('navigation.help'),
}
]
}
}
return modules
},
},
created () {
created() {
this.$store.dispatch('auth/oidcInit')
},
methods: {
signIn () {
signIn() {
this.$store.dispatch('auth/signinRedirect')
},
signOut () {
signOut() {
this.$store.dispatch('auth/signoutRedirect')
},
}
}
}
</script>
<style>
html, body {
html, body {
min-height: 100vh;
}
#app {
}
#app {
color: #2e3436;
}
/*
#app .content-width {
}
/*
#app .content-width {
margin: auto;
width: 920px;
max-width: 920px;
}
*/
}
*/
</style>
......@@ -488,7 +488,6 @@
editPlaylist() {
let playlist = this.getPlaylistById(this.id);
console.log("AAAAA", playlist);
if (!playlist) {
this.$router.push({ name: 'addPlaylist' })
......
<template>
<auth-wall>
<b-container>
<show-selector
ref="showSelector"
......@@ -92,21 +93,25 @@
ref="appModalEmissionManagerEdit"
/>
</b-container>
</auth-wall>
</template>
<script>
import { mapGetters } from 'vuex'
import { FullCalendar } from 'vue-full-calendar'
import 'fullcalendar/dist/fullcalendar.css'
import showSelector from '../components/ShowSelector.vue'
import modalEmissionManagerCreate from '../components/emissions/ModalCreate.vue'
import modalEmissionManagerResolve from '../components/emissions/ModalResolve.vue'
import modalEmissionManagerEdit from '../components/emissions/ModalEdit.vue'
import rrules from '../mixins/rrules'
import showSelector from '@/components/ShowSelector.vue'
import modalEmissionManagerCreate from '@/components/emissions/ModalCreate.vue'
import modalEmissionManagerResolve from '@/components/emissions/ModalResolve.vue'
import modalEmissionManagerEdit from '@/components/emissions/ModalEdit.vue'
import AuthWall from '@/components/AuthWall.vue'
import rrules from '@/mixins/rrules'
export default {
components: {
FullCalendar,
AuthWall,
'show-selector': showSelector,
'app-modalEmissionManagerCreate': modalEmissionManagerCreate,
'app-modalEmissionManagerResolve': modalEmissionManagerResolve,
......@@ -177,6 +182,8 @@ export default {
},
created () {
this.$store.dispatch('shows/fetchShows', {
callback: () => {
this.showHasSwitched()
......
......@@ -7,22 +7,14 @@
<br>
</div>
<div class="tw-mx-auto tw-max-w-4xl tw-grid sm:tw-grid-cols-2 md:tw-grid-cols-4 tw-gap-8 tw-text-center">
<router-link to="shows">
<img src="/assets/applications-multimedia.png">
<p>Schedule your shows</p>
</router-link>
<router-link to="files">
<img src="/assets/audio-x-generic.png">
<p>Manage files and playlists</p>
</router-link>
<router-link to="settings">
<img src="/assets/applications-system.png">
<p>Settings</p>
</router-link>
<router-link to="help">
<img src="/assets/help-browser.png">
<p>Help pages</p>
<div :class="{
'tw-mx-auto tw-grid sm:tw-grid-cols-2 tw-gap-8 tw-text-center': true,
'md:tw-grid-cols-3 tw-max-w-3xl': $parent.user.steeringUser.is_superuser,
'md:tw-grid-cols-2 tw-max-w-lg': !$parent.user.steeringUser.is_superuser
}">
<router-link v-for="mod in modules.main" :to="mod.slug" :key="mod.slug">
<img :src="mod.icon">
<p>{{ mod.title }}</p>
</router-link>
</div>
</div>
......@@ -40,14 +32,12 @@
</b-button>
</div>
</b-container>
<!--
All icons used are taken from the Tango Project, which put them into public domain:
http://tango.freedesktop.org
-->
</template>
<script>
export default {}
export default {
props: ['user', 'modules']
}
</script>
<style>
......
<template>
<auth-wall>
<b-container align="center">
<h1>Dashboard Settings</h1>
<br><br>
......@@ -9,10 +10,15 @@
<br><br>
</div>
</b-container>
</auth-wall>
</template>
<script>
export default {}
import AuthWall from '@/components/AuthWall'
export default {
components: { AuthWall }
}
</script>
<style>
......
<template>
<div v-if="$store.state.auth.user.steeringUser" class="tw-w-full">
<slot></slot>
</div>
<div v-else class="tw-w-full tw-text-center">
{{ $t('loading') }}
</div>
</template>
<script>
export default {
created() {
const user = this.$store.state.auth.user.steeringUser;
// We might not have a user at load-time.
// In this case wait until the store gives us one.
if (user === null) {
this.$store.watch(
(state) => state.auth.user.steeringUser,
(user) => this.redirectToHome(user)
)
return;
}
this.redirectToHome(user);
},
methods: {
redirectToHome(user) {
if (!user.is_superuser) {
this.$toast.error(this.$t('auth.permissionError'), { position: 'bottom-left' })
this.$router.push({ name: 'home' })
}
}
}
}
</script>
......@@ -3,8 +3,14 @@
<b-container>
<b-row>
<b-col>
aura/<b>dashboard v{{ version }}</b> |
<router-link to="/credits">
aura/<b>dashboard v{{ version }}</b>
<span v-for="mod in modules.footer" :key="mod.slug">
| <router-link :to="mod.slug">
{{ mod.title }}
</router-link>
</span>
| <router-link to="/credits">
Credits
</router-link>
</b-col>
......@@ -17,25 +23,25 @@
</template>
<script>
export default {
export default {
props: ["modules"],
computed: {
version() {
console.log(process.env)
return process.env.VUE_APP_VERSION
}
}
}
}
</script>
<style scoped>
footer {
footer {
border-top: 1px solid #2e3436;
color: rgba(255, 255, 255, 0.5);
width: 100%;
margin-top: auto;
}
}
a {
a {
color: #cc149e;
}
}
</style>
......@@ -9,7 +9,7 @@
>
<span class="d-none d-sm-inline d-lg-none menu-context-info">For more options tap the menu button on the right:</span>
<span class="d-sm-none menu-context-info">Hit menu button for more:</span>
<b-navbar-toggle target="nav_collapse" />
<b-navbar-toggle target="nav_collapse"/>
<b-collapse
id="nav_collapse"
is-nav
......@@ -24,7 +24,7 @@
</b-nav-item>
<b-nav-item
v-for="mod in modules"
v-for="mod in modules.main"
:key="mod.slug"
:active="mod.slug === $route.name"
:to="'/' + mod.slug"
......@@ -95,28 +95,30 @@
</template>
<script>
export default {
export default {
props: {
modules: { type: Array, required: true },
user: { type: Object, required: true }
modules: {type: Array, required: true},
user: {type: Object, required: true}
},
}
}
</script>
<style scoped>
.header-title a {
.header-title a {
text-decoration: none;
color: #c09;
text-shadow: #fff 0 0 2px;
}
.help-image {
}
.help-image {
width: 24px;
height: 24px;
padding: 0;
margin: 0;
}
.menu-context-info {
}
.menu-context-info {
color: rgba(255, 255, 255, 0.5);
}
}
</style>
......@@ -124,11 +124,10 @@ export default {
if (!this.loaded.types) {
this.$store.dispatch('shows/fetchMetaArray', {property: 'types', onlyActive: true})
}
if (!this.loaded.fundingcategories) {
this.$store.dispatch('shows/fetchMetaArray', {property: 'fundingcategories', onlyActive: true})
}
console.log(this.selectedShow)
},
methods: {
......
......@@ -7,11 +7,12 @@ export default {
},
// Layout
'settings': 'Einstellungen',
'loading': 'Lädt..',
'profile': 'Profil',
'auth': {
'signOut': 'Abmelden',
'signIn': 'Anmelden'
'signIn': 'Anmelden',
'permissionError': 'Du bist nicht berechtigt diese Seite zu sehen'
},
'navigation': {
......@@ -19,6 +20,8 @@ export default {
'shows': 'Sendungen',
'filesPlaylists': 'Dateien & Playlists',
'calendar': 'Kalender',
'settings': 'Einstellungen',
'help': 'Hilfe'
},
'footer': {
......@@ -32,5 +35,5 @@ export default {
'duration': 'Dauer',
'playlist': 'Playlist',
'actions': 'Aktionen',
}
},
}
......@@ -7,11 +7,13 @@ export default {
},
// Layout
'loading': 'Loading..',
'settings': 'Settings',
'profile': 'Profile',
'auth': {
'signOut': 'Sign out',
'signIn': 'Sign in'
'signIn': 'Sign in',
'permissionError': 'You are not permitted to view this page'
},
'navigation': {
......@@ -19,6 +21,8 @@ export default {
'shows': 'Shows',
'filesPlaylists': 'Files & Playlists',
'calendar': 'Calendar',
'settings': 'Settings',
'help': 'Help'
},
'footer': {
......
......@@ -3,11 +3,13 @@ import App from './App.vue'
import router from './router'
import store from './store'
import Translation from '@/plugins/translation';
import Translation from '@/plugins/translation'
import BootstrapVue from 'bootstrap-vue'
import VueLogger from 'vuejs-logger';
import VueLogger from 'vuejs-logger'
import VueToast from 'vue-toast-notification'
import '../public/assets/tailwind.css'
import 'vue-toast-notification/dist/theme-default.css'
// Use this if you also have to debug a production build
// Only use it temporarily!
......@@ -21,10 +23,11 @@ Vue.use(VueLogger, {
showMethodName : false,
separator: '|',
showConsoleColors: true
});
})
Vue.use(BootstrapVue)
Vue.use(Translation)
Vue.use(VueToast)
Vue.config.productionTip = false
......
......@@ -14,14 +14,14 @@ Vue.use(Router)
export default new Router({
mode: 'history',
routes: [
{ path: '/', alias: '/home', name: 'home', component: Home },
{ path: '/shows', name: 'shows', component: ShowManager },
{ path: '/files', name: 'files', component: FileManager },
{ path: '/calendar', name: 'emissions', component: EmissionManager },
{ path: '/help', name: 'help', component: Help },
{ path: '/settings', name: 'settings', component: Settings },
{ path: '/credits', name: 'credits', component: Credits },
{ path: '/playlist/new', name: 'addPlaylist', component: AddOrEditPlaylist, props: { id: false, }},
{ path: '/playlist/:id', name: 'editPlaylist', component: AddOrEditPlaylist, props: true }
{path: '/', alias: '/home', name: 'home', component: Home},
{path: '/shows', name: 'shows', component: ShowManager},
{path: '/files', name: 'files', component: FileManager},
{path: '/calendar', name: 'emissions', component: EmissionManager},
{path: '/help', name: 'help', component: Help},
{path: '/settings', name: 'settings', component: Settings},
{path: '/credits', name: 'credits', component: Credits},
{path: '/playlist/new', name: 'addPlaylist', component: AddOrEditPlaylist, props: {id: false,}},
{path: '/playlist/:id', name: 'editPlaylist', component: AddOrEditPlaylist, props: true}
]
})