Stuff
This commit is contained in:
parent
42d2973a05
commit
50ef516ed6
19 changed files with 1174 additions and 52 deletions
5
package-lock.json
generated
5
package-lock.json
generated
|
@ -10918,6 +10918,11 @@
|
|||
"vue-style-loader": "^4.1.0"
|
||||
}
|
||||
},
|
||||
"vue-router": {
|
||||
"version": "3.0.6",
|
||||
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.0.6.tgz",
|
||||
"integrity": "sha512-Ox0ciFLswtSGRTHYhGvx2L44sVbTPNS+uD2kRISuo8B39Y79rOo0Kw0hzupTmiVtftQYCZl87mwldhh2L9Aquw=="
|
||||
},
|
||||
"vue-style-loader": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/vue-style-loader/-/vue-style-loader-4.1.2.tgz",
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
"axios": "^0.18.0",
|
||||
"core-js": "^2.6.5",
|
||||
"vue": "^2.6.10",
|
||||
"vue-router": "^3.0.6",
|
||||
"vuetify": "^1.5.5",
|
||||
"vuex": "^3.1.1"
|
||||
},
|
||||
|
|
51
src/App.vue
51
src/App.vue
|
@ -1,48 +1,30 @@
|
|||
<template>
|
||||
<v-app v-scroll="handleScroll" v-if="$store.state.settingsLoaded">
|
||||
<v-toolbar app :flat="flat" :prominent="big" :dense="!big" :color="bgcolor" clipped-left >
|
||||
<v-toolbar-title class="headline text-uppercase" >
|
||||
<span>{{ nameBig }}</span>
|
||||
<span class="font-weight-light">{{ nameSmall }}</span>
|
||||
</v-toolbar-title>
|
||||
<v-spacer></v-spacer>
|
||||
<v-toolbar-items class="hidden-sm-and-down">
|
||||
<v-btn
|
||||
v-for="item in menu"
|
||||
:key="item.icon"
|
||||
:to="item.link"
|
||||
flat
|
||||
>{{ item.title }}</v-btn>
|
||||
</v-toolbar-items>
|
||||
<v-menu class="hidden-md-and-up">
|
||||
<v-toolbar-side-icon slot="activator"></v-toolbar-side-icon>
|
||||
<v-list>
|
||||
<v-list-tile v-for="item in menu" :key="item.icon">
|
||||
<v-list-tile-content>
|
||||
<v-list-tile-title>{{ item.title }}</v-list-tile-title>
|
||||
</v-list-tile-content>
|
||||
</v-list-tile>
|
||||
</v-list>
|
||||
</v-menu>
|
||||
<v-app >
|
||||
<div v-if="$store.getters.getAllDataLoaded">
|
||||
<Menu></Menu>
|
||||
<MenuMobile></MenuMobile>
|
||||
|
||||
</v-toolbar>
|
||||
|
||||
|
||||
<v-content style="background-color: #fff;">
|
||||
<Startpage/>
|
||||
<router-view></router-view>
|
||||
</v-content>
|
||||
</div>
|
||||
<div v-if="!$store.getters.getAllDataLoaded">
|
||||
Loading ...
|
||||
</div>
|
||||
</v-app>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import HelloWorld from './components/HelloWorld'
|
||||
import Startpage from './components/Startpage'
|
||||
import Menu from "./components/Menu";
|
||||
import MenuMobile from "./components/MenuMobile"
|
||||
|
||||
export default {
|
||||
name: 'App',
|
||||
components: {
|
||||
HelloWorld,
|
||||
Startpage
|
||||
'Menu': Menu,
|
||||
'MenuMobile': MenuMobile
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
|
@ -69,7 +51,7 @@ export default {
|
|||
}
|
||||
},
|
||||
methods: {
|
||||
handleScroll: function (evt, el) {
|
||||
/*handleScroll: function (evt, el) {
|
||||
if(evt.pageY > 100) {
|
||||
this.big = false;
|
||||
this.bgcolor = "#fff";
|
||||
|
@ -79,10 +61,11 @@ export default {
|
|||
this.bgcolor = "transparent";
|
||||
this.flat = true;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
},
|
||||
mounted: function () {
|
||||
|
||||
this.$store.dispatch('checkAccount');
|
||||
console.log("MOUNTED");
|
||||
this.$store.dispatch('getSettings').then(() => {
|
||||
this.nameBig = this.$store.getters.getSettingValue("name_big");
|
||||
this.nameSmall = this.$store.getters.getSettingValue("name_small");
|
||||
|
|
96
src/components/Login.vue
Normal file
96
src/components/Login.vue
Normal file
|
@ -0,0 +1,96 @@
|
|||
<template>
|
||||
<div>
|
||||
<h1>Login</h1>
|
||||
<v-alert
|
||||
:value="true"
|
||||
type="error"
|
||||
v-if="errorMessage"
|
||||
>
|
||||
{{ errorMessage }}
|
||||
</v-alert>
|
||||
<p>Login to your <span v-if="loginToService">{{ serviceName }}</span><span v-if="!loginToService">{{nameBig}}{{nameSmall}}</span> with your credentials.</p>
|
||||
<v-text-field
|
||||
label="Username"
|
||||
value=""
|
||||
v-model="username"
|
||||
></v-text-field>
|
||||
<v-text-field
|
||||
label="Password"
|
||||
value=""
|
||||
type="password"
|
||||
v-model="password"
|
||||
></v-text-field>
|
||||
<v-checkbox
|
||||
v-model="logintoMainAccount"
|
||||
:label="loginText"
|
||||
v-if="loginToService"
|
||||
disabled="true"
|
||||
></v-checkbox>
|
||||
<v-checkbox
|
||||
v-model="allowSpaces"
|
||||
label="Permanent Login at this Device"
|
||||
v-if="showPermanentLogin()"
|
||||
></v-checkbox>
|
||||
<v-btn
|
||||
color="success"
|
||||
@click="login"
|
||||
>
|
||||
Login
|
||||
</v-btn>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import UserService from '../services/User'
|
||||
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
username: '',
|
||||
password: '',
|
||||
errorMessage: '',
|
||||
nameBig: '',
|
||||
nameSmall: '',
|
||||
loginText: '',
|
||||
logintoMainAccount: true
|
||||
}
|
||||
},
|
||||
props: [
|
||||
'loginToService',
|
||||
'serviceName'
|
||||
],
|
||||
methods: {
|
||||
'login': function () {
|
||||
UserService.login(this.username, this.password).then((res) => {
|
||||
this.errorMessage = '';
|
||||
UserService.setAccessToken(res.data.data["access_token"]);
|
||||
console.log("Login ok, dispatch event");
|
||||
this.$store.dispatch('checkAccount');
|
||||
this.$emit('loggedIn')
|
||||
}, (res) => {
|
||||
this.errorMessage = res.response.data.msg;
|
||||
});
|
||||
},
|
||||
showPermanentLogin: function () {
|
||||
return false;
|
||||
if(this.loginToService && this.logintoMainAccount) {
|
||||
return true;
|
||||
}
|
||||
if(!this.loginToService) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
},
|
||||
mounted: function() {
|
||||
this.nameBig = this.$store.getters.getSettingValue("name_big");
|
||||
this.nameSmall = this.$store.getters.getSettingValue("name_small");
|
||||
this.loginText = "Login to "+this.nameBig+this.nameSmall+" too"
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
155
src/components/Menu.vue
Normal file
155
src/components/Menu.vue
Normal file
|
@ -0,0 +1,155 @@
|
|||
<template>
|
||||
<v-toolbar v-scroll="handleScroll" app :flat="flat" :prominent="big" :dense="!big" :color="bgcolor" clipped-left >
|
||||
<v-toolbar-title class="headline text-uppercase" >
|
||||
<span>{{ nameBig }}</span>
|
||||
<span class="font-weight-light">{{ nameSmall }}</span>
|
||||
</v-toolbar-title>
|
||||
<v-spacer></v-spacer>
|
||||
<v-toolbar-items class="hidden-sm-and-down">
|
||||
<v-btn
|
||||
v-if="this.$store.state.loggedIn && this.$store.getters.getMe.developer"
|
||||
:to="{path: '/apps'}"
|
||||
flat
|
||||
>Apps</v-btn>
|
||||
|
||||
<v-btn
|
||||
v-if="this.$store.state.loggedIn && this.$store.getters.getMe.admin"
|
||||
:to="{path: '/admin'}"
|
||||
flat
|
||||
>Admin</v-btn>
|
||||
|
||||
|
||||
<v-menu offset-y v-if="this.$store.state.loggedIn">
|
||||
<template v-slot:activator="{ on }">
|
||||
<v-btn
|
||||
v-on="on"
|
||||
flat
|
||||
>
|
||||
Profile
|
||||
</v-btn>
|
||||
</template>
|
||||
<v-list>
|
||||
<v-list-tile>
|
||||
<v-list-tile-title @click="clickLoogut()">Logout</v-list-tile-title>
|
||||
</v-list-tile>
|
||||
</v-list>
|
||||
</v-menu>
|
||||
|
||||
<v-btn
|
||||
v-if="!this.$store.state.loggedIn"
|
||||
:to="{path: '/login'}"
|
||||
flat
|
||||
>Login</v-btn>
|
||||
|
||||
<v-btn
|
||||
v-if="!this.$store.state.loggedIn && this.$store.getters.getSettingValue('invites')"
|
||||
:to="{path: '/invited'}"
|
||||
flat
|
||||
>Invited</v-btn>
|
||||
<v-btn
|
||||
v-if="!this.$store.state.loggedIn && this.$store.getters.getSettingValue('registration_possible')"
|
||||
:to="{path: '/register'}"
|
||||
flat
|
||||
>Register</v-btn>
|
||||
|
||||
|
||||
<!--<v-menu offset-y>
|
||||
<template v-slot:activator="{ on }">
|
||||
<v-btn
|
||||
color="primary"
|
||||
dark
|
||||
v-on="on"
|
||||
>
|
||||
Dropdown
|
||||
</v-btn>
|
||||
</template>
|
||||
<v-list>
|
||||
<v-list-tile
|
||||
v-for="(item, index) in menu"
|
||||
:key="index"
|
||||
@click=""
|
||||
>
|
||||
<v-list-tile-title>{{ item.title }}</v-list-tile-title>
|
||||
</v-list-tile>
|
||||
</v-list>
|
||||
</v-menu>!-->
|
||||
|
||||
</v-toolbar-items>
|
||||
<v-menu class="hidden-md-and-up">
|
||||
<v-toolbar-side-icon slot="activator" @click.stop="toggleSideMenu()"></v-toolbar-side-icon>
|
||||
</v-menu>
|
||||
</v-toolbar>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import UserServie from '../services/User'
|
||||
|
||||
export default {
|
||||
name: 'Menu',
|
||||
components: {
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
big: true,
|
||||
bgcolor: "transparent",
|
||||
flat: true,
|
||||
nameBig: '',
|
||||
nameSmall: '',
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
setting: (name) => {
|
||||
//this.$store.getters.getSettingValue(this.$store.state, name);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
toggleSideMenu: function() {
|
||||
console.log("TOGGLE");
|
||||
this.$store.state.sideMenu = !this.$store.state.sideMenu;
|
||||
},
|
||||
generateMenu: function () {
|
||||
this.menu = [];
|
||||
if(!this.$store.state.loggedIn) {
|
||||
this.menu.push({ icon: 'home', title: 'Login' , link: "Login" });
|
||||
if(this.$store.getters.getSettingValue("invites")) {
|
||||
this.menu.push({ icon: 'home', title: 'Invited' , link: "Invited" });
|
||||
}
|
||||
if(this.$store.getters.getSettingValue("registration_possible")) {
|
||||
this.menu.push({ icon: 'home', title: 'Register' , link: "Register" });
|
||||
}
|
||||
} else {
|
||||
if(this.$store.getters.getMe.developer) {
|
||||
this.menu.push({ icon: 'home', title: 'Apps' , link: "Apps" });
|
||||
}
|
||||
if(this.$store.getters.getMe.admin) {
|
||||
this.menu.push({ icon: 'home', title: 'Admin' , link: "Admin" });
|
||||
}
|
||||
this.menu.push({ icon: 'home', title: 'Profile' , link: "profile", submenu: true, menu: [
|
||||
{ icon: 'home', title: 'Logout' , link: "Logout" }
|
||||
] });
|
||||
}
|
||||
},
|
||||
handleScroll: function (evt, el) {
|
||||
if(evt.pageY > 100) {
|
||||
this.big = false;
|
||||
this.bgcolor = "#fff";
|
||||
this.flat = false;
|
||||
} else {
|
||||
this.big = true;
|
||||
this.bgcolor = "transparent";
|
||||
this.flat = true;
|
||||
}
|
||||
},
|
||||
clickLoogut: function () {
|
||||
UserServie.logout();
|
||||
this.$store.dispatch('checkAccount')
|
||||
this.$router.push({"path": "login"})
|
||||
}
|
||||
},
|
||||
mounted: function () {
|
||||
this.nameBig = this.$store.getters.getSettingValue("name_big");
|
||||
this.nameSmall = this.$store.getters.getSettingValue("name_small");
|
||||
this.generateMenu();
|
||||
}
|
||||
}
|
||||
</script>
|
146
src/components/MenuMobile.vue
Normal file
146
src/components/MenuMobile.vue
Normal file
|
@ -0,0 +1,146 @@
|
|||
<template>
|
||||
<v-navigation-drawer
|
||||
stateless
|
||||
absolute
|
||||
value="true"
|
||||
v-model="$store.state.sideMenu"
|
||||
>
|
||||
<v-list>
|
||||
<v-list-tile>
|
||||
<v-list-tile-action>
|
||||
<v-icon>home</v-icon>
|
||||
</v-list-tile-action>
|
||||
<v-list-tile-title>Home</v-list-tile-title>
|
||||
</v-list-tile>
|
||||
|
||||
<v-list-group
|
||||
prepend-icon="account_circle"
|
||||
value="true"
|
||||
>
|
||||
<template v-slot:activator>
|
||||
<v-list-tile>
|
||||
<v-list-tile-title>Users</v-list-tile-title>
|
||||
</v-list-tile>
|
||||
</template>
|
||||
<v-list-group
|
||||
no-action
|
||||
sub-group
|
||||
value="true"
|
||||
>
|
||||
<template v-slot:activator>
|
||||
<v-list-tile>
|
||||
<v-list-tile-title>Admin</v-list-tile-title>
|
||||
</v-list-tile>
|
||||
</template>
|
||||
|
||||
<v-list-tile
|
||||
v-for="(admin, i) in admins"
|
||||
:key="i"
|
||||
@click=""
|
||||
>
|
||||
<v-list-tile-title v-text="admin[0]"></v-list-tile-title>
|
||||
<v-list-tile-action>
|
||||
<v-icon v-text="admin[1]"></v-icon>
|
||||
</v-list-tile-action>
|
||||
</v-list-tile>
|
||||
</v-list-group>
|
||||
|
||||
<v-list-group
|
||||
sub-group
|
||||
no-action
|
||||
>
|
||||
<template v-slot:activator>
|
||||
<v-list-tile>
|
||||
<v-list-tile-title>Actions</v-list-tile-title>
|
||||
</v-list-tile>
|
||||
</template>
|
||||
<v-list-tile
|
||||
v-for="(crud, i) in cruds"
|
||||
:key="i"
|
||||
@click=""
|
||||
>
|
||||
<v-list-tile-title v-text="crud[0]"></v-list-tile-title>
|
||||
<v-list-tile-action>
|
||||
<v-icon v-text="crud[1]"></v-icon>
|
||||
</v-list-tile-action>
|
||||
</v-list-tile>
|
||||
</v-list-group>
|
||||
</v-list-group>
|
||||
</v-list>
|
||||
</v-navigation-drawer>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
name: 'MenuMobile',
|
||||
components: {
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
big: true,
|
||||
bgcolor: "transparent",
|
||||
flat: true,
|
||||
nameBig: '',
|
||||
nameSmall: '',
|
||||
sideMenu: this.$store.state.sideMenu,
|
||||
menu: [
|
||||
{ icon: 'home', title: 'Login' , link: "Login" },
|
||||
{ icon: 'info', title: 'Invited' },
|
||||
{ icon: 'warning', title: 'Register' }
|
||||
],
|
||||
menu2: [
|
||||
{ icon: 'home', title: 'Apps' },
|
||||
{ icon: 'info', title: 'Admin' },
|
||||
{ icon: 'warning', title: 'Account' }
|
||||
],
|
||||
menu3: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
setting: (name) => {
|
||||
//this.$store.getters.getSettingValue(this.$store.state, name);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
generateMenu: function () {
|
||||
this.menu = [];
|
||||
if(!this.$store.state.loggedIn) {
|
||||
this.menu.push({ icon: 'home', title: 'Login' , link: "Login" });
|
||||
if(this.$store.getters.getSettingValue("invites")) {
|
||||
this.menu.push({ icon: 'home', title: 'Invited' , link: "Invited" });
|
||||
}
|
||||
if(this.$store.getters.getSettingValue("registration_possible")) {
|
||||
this.menu.push({ icon: 'home', title: 'Register' , link: "Register" });
|
||||
}
|
||||
} else {
|
||||
if(this.$store.getters.getMe.developer) {
|
||||
this.menu.push({ icon: 'home', title: 'Apps' , link: "Apps" });
|
||||
}
|
||||
if(this.$store.getters.getMe.admin) {
|
||||
this.menu.push({ icon: 'home', title: 'Admin' , link: "Admin" });
|
||||
}
|
||||
this.menu.push({ icon: 'home', title: 'Profile' , link: "profile", submenu: true, menu: [
|
||||
{ icon: 'home', title: 'Logout' , link: "Logout" }
|
||||
] });
|
||||
}
|
||||
},
|
||||
handleScroll: function (evt, el) {
|
||||
if(evt.pageY > 100) {
|
||||
this.big = false;
|
||||
this.bgcolor = "#fff";
|
||||
this.flat = false;
|
||||
} else {
|
||||
this.big = true;
|
||||
this.bgcolor = "transparent";
|
||||
this.flat = true;
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted: function () {
|
||||
this.nameBig = this.$store.getters.getSettingValue("name_big");
|
||||
this.nameSmall = this.$store.getters.getSettingValue("name_small");
|
||||
this.generateMenu();
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -2,6 +2,7 @@ import Vue from 'vue'
|
|||
import './plugins/vuetify'
|
||||
import App from './App.vue'
|
||||
import store from './store/store'
|
||||
import router from './router'
|
||||
|
||||
|
||||
|
||||
|
@ -20,5 +21,6 @@ Vue.config.productionTip = false
|
|||
|
||||
new Vue({
|
||||
store,
|
||||
router,
|
||||
render: h => h(App),
|
||||
}).$mount('#app')
|
||||
|
|
59
src/router/index.js
Normal file
59
src/router/index.js
Normal file
|
@ -0,0 +1,59 @@
|
|||
import Vue from 'vue'
|
||||
import Router from 'vue-router'
|
||||
import Startpage from '../views/Startpage'
|
||||
import HelloWorld from '../components/HelloWorld'
|
||||
import Login from '../views/Login'
|
||||
import Dashboard from '../views/Dashboard'
|
||||
import store from '../store/store';
|
||||
import OAuthPermission from '../views/OAuthPermission'
|
||||
import ListApps from '../views/ListApps'
|
||||
import AppDetails from '../views/AppDetails'
|
||||
|
||||
Vue.use(Router)
|
||||
|
||||
function guard(to, from, next){
|
||||
if(store.state.loggedIn) {
|
||||
next(); // allow to enter route
|
||||
} else{
|
||||
store.state.redirectIfLoggedIn = to;
|
||||
next('/login'); // go to '/login';
|
||||
}
|
||||
}
|
||||
|
||||
export default new Router({
|
||||
routes: [
|
||||
{
|
||||
path: '/',
|
||||
name: 'Startpage',
|
||||
component: Startpage
|
||||
},
|
||||
{
|
||||
path: '/login',
|
||||
name: 'Login',
|
||||
component: Login
|
||||
},
|
||||
{
|
||||
path: '/oauth',
|
||||
name: 'oAuthPermission',
|
||||
component: OAuthPermission
|
||||
},
|
||||
{
|
||||
beforeEnter: guard,
|
||||
path: '/dashboard',
|
||||
name: 'Dashboard',
|
||||
component: Dashboard
|
||||
},
|
||||
{
|
||||
beforeEnter: guard,
|
||||
path: '/apps',
|
||||
name: 'Apps',
|
||||
component: ListApps
|
||||
},
|
||||
{
|
||||
beforeEnter: guard,
|
||||
path: '/apps/:id',
|
||||
name: 'appDetails',
|
||||
component: AppDetails
|
||||
}
|
||||
]
|
||||
})
|
|
@ -2,7 +2,8 @@ import axios from 'axios'
|
|||
|
||||
export default() => {
|
||||
return axios.create({
|
||||
baseURL: `http://localhost:8000/api/`,
|
||||
baseURL: `http://127.0.0.1:8000/api/`,
|
||||
//baseURL: `https://account.keks.cloud/api/`,
|
||||
withCredentials: false,
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
|
|
22
src/services/Apps.js
Normal file
22
src/services/Apps.js
Normal file
|
@ -0,0 +1,22 @@
|
|||
import Api from '@/services/Api'
|
||||
|
||||
export default {
|
||||
listApps (params) {
|
||||
return Api().get('/v1/app')
|
||||
},
|
||||
getAppImage(id) {
|
||||
return "https://account.keks.cloud/gui/apps/"+id+"/icon";
|
||||
},
|
||||
getApp(id) {
|
||||
return Api().get('/v1/app/'+id)
|
||||
},
|
||||
getAppByKey(key) {
|
||||
return Api().get("/v1/app/find?apiKey="+key);
|
||||
},
|
||||
getAccess(id) {
|
||||
return Api().get('/v1/app/'+id+'/access?create=1')
|
||||
},
|
||||
allowAccess(id, redirect_uri, scope) {
|
||||
return Api().post('/v1/app/'+id+'/access/allow', {redirect_uri: redirect_uri, scope:scope});
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
import Api from '@/services/Api'
|
||||
|
||||
export default {
|
||||
getSettings (params) {
|
||||
getPublicSettings (params) {
|
||||
return Api().get('/v1/server/settings')
|
||||
}
|
||||
}
|
21
src/services/User.js
Normal file
21
src/services/User.js
Normal file
|
@ -0,0 +1,21 @@
|
|||
import Api from '@/services/Api'
|
||||
|
||||
export default {
|
||||
login(username, password) {
|
||||
return Api().post('/v1/user/login', {username: username, password: password});
|
||||
},
|
||||
|
||||
setAccessToken(access_token) {
|
||||
localStorage.setItem('access_token', access_token)
|
||||
Api().defaults.headers.common['Authorization'] = `Bearer ${access_token}`
|
||||
},
|
||||
getTokenFromStorage() {
|
||||
this.setAccessToken(localStorage.getItem("access_token"));
|
||||
},
|
||||
me() {
|
||||
return Api().get('/v1/user/me')
|
||||
},
|
||||
logout() {
|
||||
localStorage.removeItem("access_token");
|
||||
}
|
||||
}
|
|
@ -1,13 +1,19 @@
|
|||
import Vuex from 'vuex'
|
||||
import Vue from 'vue'
|
||||
import ServerService from '../services/Server'
|
||||
import UserService from '../services/User'
|
||||
|
||||
Vue.use(Vuex)
|
||||
|
||||
export default new Vuex.Store({
|
||||
state: {
|
||||
settingsLoaded: false,
|
||||
settings: [] // The TV inventory
|
||||
loggedIn : false,
|
||||
meLoaded: false,
|
||||
me: [],
|
||||
redirectIfLoggedIn: null,
|
||||
settings: [], // The TV inventory
|
||||
sideMenu: false, //Toggle Side Menu on side Bar
|
||||
},
|
||||
|
||||
getters: {
|
||||
|
@ -21,6 +27,19 @@ export default new Vuex.Store({
|
|||
return state.settings[i]["value"];
|
||||
}
|
||||
}
|
||||
},
|
||||
getAllDataLoaded: (state) => {
|
||||
var loaded = true;
|
||||
if(!state.meLoaded) {
|
||||
loaded = false;
|
||||
}
|
||||
if(!state.settingsLoaded) {
|
||||
loaded = false;
|
||||
}
|
||||
return loaded;
|
||||
},
|
||||
getMe: (state) => {
|
||||
return state.me;
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -28,19 +47,41 @@ export default new Vuex.Store({
|
|||
setSettings: function(state, settings) {
|
||||
state.settings = settings;
|
||||
state.settingsLoaded = true;
|
||||
},
|
||||
setMe: function(state, me) {
|
||||
if(me == false) {
|
||||
state.loggedIn = false;
|
||||
state.meLoaded = true;
|
||||
} else {
|
||||
state.me = me;
|
||||
state.loggedIn = true;
|
||||
state.meLoaded = true;
|
||||
}
|
||||
},
|
||||
|
||||
},
|
||||
|
||||
actions: {
|
||||
getSettings: function (context) {
|
||||
return new Promise((resolve, reject) => {
|
||||
ServerService.getSettings().then((res) => {
|
||||
console.log(res);
|
||||
ServerService.getPublicSettings().then((res) => {
|
||||
context.commit('setSettings', res.data.data)
|
||||
resolve()
|
||||
});
|
||||
})
|
||||
|
||||
},
|
||||
checkAccount: function(context) {
|
||||
UserService.getTokenFromStorage();
|
||||
return new Promise((resolve, reject) => {
|
||||
UserService.me().then((res) => {
|
||||
console.log("GET USER DATA");
|
||||
context.commit('setMe', res.data.data)
|
||||
}, (res) => {
|
||||
context.commit('setMe', false)
|
||||
console.log("DONT GET USER DATA");
|
||||
console.log(res.response.data)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
});
|
192
src/views/AppDetails.vue
Normal file
192
src/views/AppDetails.vue
Normal file
|
@ -0,0 +1,192 @@
|
|||
<template>
|
||||
<div style="">
|
||||
|
||||
<v-container grid-list-md>
|
||||
<v-layout row wrap>
|
||||
<v-flex md12>
|
||||
<h1>App {{ app.name }}</h1>
|
||||
<v-card class="mx-auto" flat style="margin-top: 10px;">
|
||||
<v-tabs
|
||||
background-color="white"
|
||||
color="fff"
|
||||
left
|
||||
|
||||
>
|
||||
<v-tab>Overview</v-tab>
|
||||
<v-tab>API Access</v-tab>
|
||||
<v-tab>Settings</v-tab>
|
||||
<v-tab disabled>Users</v-tab>
|
||||
|
||||
<v-tab-item :key="1" :transition="false" :reverse-transition="false" >
|
||||
<v-container style="padding-right: 0px; padding-left:0px;">
|
||||
<img :src="imageUrl" style="float: right;width: 100px;">
|
||||
<b>Description</b><br>
|
||||
{{ app.description }}<br><br>
|
||||
<a :href="app.url">{{ app.url }}</a>
|
||||
</v-container>
|
||||
|
||||
</v-tab-item>
|
||||
<v-tab-item :key="2" :transition="false" :reverse-transition="false">
|
||||
<v-container style="padding-right: 0px; padding-left:0px;">
|
||||
<h2>oAuth Token</h2>
|
||||
<p>
|
||||
Here are the oAuth API-Keys. You use this Keys to start the oAuth authorization work flow.
|
||||
</p>
|
||||
<v-text-field
|
||||
label="API Key"
|
||||
:value="app.apiKey"
|
||||
hint="You can't edit this"
|
||||
></v-text-field>
|
||||
<v-text-field
|
||||
label="API Secret"
|
||||
:value="app.apiSecret"
|
||||
hint="You can't edit this"
|
||||
></v-text-field>
|
||||
<br>
|
||||
<h2>API Access</h2>
|
||||
<p>
|
||||
You can access the API to get informations about this APP with the following API Credentials:
|
||||
<v-text-field
|
||||
label="API Token"
|
||||
value=""
|
||||
disabled
|
||||
></v-text-field>
|
||||
<v-text-field
|
||||
label="Refresh Token"
|
||||
value=""
|
||||
disabled
|
||||
></v-text-field>
|
||||
<h2>Development Access</h2>
|
||||
<p>
|
||||
To test the App you can use the following Developer Access and Refresh token, they are connected to your user.
|
||||
<v-text-field
|
||||
label="Access Token"
|
||||
value=""
|
||||
disabled
|
||||
></v-text-field>
|
||||
<v-text-field
|
||||
label="Refresh Token"
|
||||
value=""
|
||||
disabled
|
||||
></v-text-field>
|
||||
</p>
|
||||
</v-container>
|
||||
</v-tab-item>
|
||||
<v-tab-item :key="3" :transition="false" :reverse-transition="false">
|
||||
<v-container style="padding-right: 0px; padding-left:0px;">
|
||||
<v-layout>
|
||||
<v-flex md8>
|
||||
<v-text-field
|
||||
label="App Name"
|
||||
:value="app.name"
|
||||
></v-text-field>
|
||||
<v-text-field
|
||||
label="URL"
|
||||
:value="app.url"
|
||||
></v-text-field>
|
||||
<v-textarea
|
||||
label="Description"
|
||||
:value="app.description"
|
||||
|
||||
></v-textarea>
|
||||
<v-text-field
|
||||
label="Direct Login URL"
|
||||
:value="app.directUrl"
|
||||
hint="URL to login with this oAuth Provider"
|
||||
></v-text-field>
|
||||
<v-checkbox
|
||||
v-model="app.properties.testingWarning"
|
||||
label="Testing Warning"
|
||||
disabled
|
||||
></v-checkbox>
|
||||
<v-checkbox
|
||||
v-model="app.properties.untrustedWarning"
|
||||
label="Untrusted Warning"
|
||||
disabled
|
||||
></v-checkbox>
|
||||
<v-checkbox
|
||||
v-model="app.properties.autoAccept"
|
||||
label="Auto Accept"
|
||||
disabled
|
||||
></v-checkbox>
|
||||
<v-checkbox
|
||||
v-model="app.properties.showOnWebpage"
|
||||
label="Show on Webpage"
|
||||
disabled
|
||||
></v-checkbox>
|
||||
<v-checkbox
|
||||
v-model="app.properties.stopAutoRedirect"
|
||||
label="Stop Auto Redirect"
|
||||
disabled
|
||||
></v-checkbox>
|
||||
<v-checkbox
|
||||
v-model="app.properties.hideInAppList"
|
||||
label="Hide in App List"
|
||||
disabled
|
||||
></v-checkbox>
|
||||
<v-checkbox
|
||||
v-model="app.properties.userCantRemoveApp"
|
||||
label="Disabled user possible to remove App-Access"
|
||||
disabled
|
||||
></v-checkbox>
|
||||
|
||||
|
||||
|
||||
</v-flex>
|
||||
<v-flex md4>
|
||||
IMAGE
|
||||
</v-flex>
|
||||
</v-layout>
|
||||
</v-container>
|
||||
</v-tab-item>
|
||||
<v-tab-item :key="4" :transition="false" :reverse-transition="false">
|
||||
<v-container style="padding-right: 0px; padding-left:0px;">
|
||||
|
||||
</v-container>
|
||||
</v-tab-item>
|
||||
|
||||
</v-tabs>
|
||||
</v-card>
|
||||
</v-flex>
|
||||
|
||||
|
||||
|
||||
</v-layout>
|
||||
</v-container>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ServerService from '../services/Server'
|
||||
import UserService from '../services/User'
|
||||
import LoginComponent from '../components/Login'
|
||||
import AppService from '../services/Apps'
|
||||
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
app: null,
|
||||
imageUrl: ''
|
||||
}
|
||||
},
|
||||
components: {
|
||||
"Login": LoginComponent
|
||||
},
|
||||
methods: {
|
||||
|
||||
},
|
||||
mounted: function() {
|
||||
AppService.getApp(this.$route.params.id).then((res) => {
|
||||
this.app = res.data.data;
|
||||
})
|
||||
this.imageUrl = AppService.getAppImage(this.$route.params.id);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
89
src/views/Dashboard.vue
Normal file
89
src/views/Dashboard.vue
Normal file
|
@ -0,0 +1,89 @@
|
|||
<template>
|
||||
<div style="">
|
||||
<v-container grid-list-md>
|
||||
<v-layout row wrap>
|
||||
<v-flex md12>
|
||||
<h1>Dashboard</h1>
|
||||
<br><br>
|
||||
Hello {{$store.getters.getMe["username"]}},<br>
|
||||
soon here will be an Dashboard.
|
||||
</v-flex>
|
||||
|
||||
|
||||
</v-layout>
|
||||
</v-container>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ServerService from '../services/Server'
|
||||
import UserService from '../services/User'
|
||||
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
nameBig: '',
|
||||
nameSmall: '',
|
||||
username: '',
|
||||
password: '',
|
||||
errorMessage: ''
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
'login': function () {
|
||||
UserService.login(this.username, this.password).then((res) => {
|
||||
this.errorMessage = '';
|
||||
UserService.setAccessToken(res.data.data["access_token"]);
|
||||
console.log("Login ok, dispatch event");
|
||||
this.$store.dispatch('checkAccount');
|
||||
}, (res) => {
|
||||
this.errorMessage = res.response.data.msg;
|
||||
});
|
||||
}
|
||||
},
|
||||
mounted: function() {
|
||||
this.nameBig = this.$store.getters.getSettingValue("name_big");
|
||||
this.nameSmall = this.$store.getters.getSettingValue("name_small");
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.header {
|
||||
background-image: url('~@/assets/manhattan-407703_1920.jpg');
|
||||
background-repeat: no-repeat;
|
||||
margin-top: -100px;
|
||||
height: 30vh;
|
||||
text-align: center;
|
||||
}
|
||||
.header h1{
|
||||
padding-top: 200px;
|
||||
font-size: 56px !important;
|
||||
font-weight: 400;
|
||||
line-height: 32px !important;
|
||||
letter-spacing: normal !important;
|
||||
}
|
||||
.header h1 .small{
|
||||
font-weight: 300 !important;
|
||||
}
|
||||
.header h2{
|
||||
padding-top: 30px;
|
||||
font-size: 34px !important;
|
||||
font-weight: 300;
|
||||
line-height: 32px !important;
|
||||
letter-spacing: normal !important;
|
||||
}
|
||||
h1{
|
||||
font-weight: 300;
|
||||
line-height: 32px !important;
|
||||
letter-spacing: normal !important;
|
||||
}
|
||||
h2{
|
||||
font-weight: 300;
|
||||
line-height: 32px !important;
|
||||
letter-spacing: normal !important;
|
||||
}
|
||||
</style>
|
70
src/views/ListApps.vue
Normal file
70
src/views/ListApps.vue
Normal file
|
@ -0,0 +1,70 @@
|
|||
<template>
|
||||
<div style="">
|
||||
<v-container grid-list-md>
|
||||
<v-layout row wrap>
|
||||
<v-flex md12>
|
||||
<h1>Apps</h1>
|
||||
<br><br>
|
||||
<p>Here you can Administrate your apps</p>
|
||||
</v-flex>
|
||||
</v-layout>
|
||||
<v-layout row wrap>
|
||||
<v-flex md4 text-xs-center v-for="(item, index) in apps">
|
||||
<v-card>
|
||||
<v-layout>
|
||||
<v-flex xs5>
|
||||
<v-img
|
||||
:src="getImageUrl(item.id)"
|
||||
height="125px"
|
||||
contain
|
||||
></v-img>
|
||||
</v-flex>
|
||||
<v-flex xs7>
|
||||
<v-card-title primary-title>
|
||||
<div>
|
||||
<div class="headline">{{ item.name }}</div>
|
||||
<div>{{ item.description }}</div>
|
||||
</div>
|
||||
</v-card-title>
|
||||
</v-flex>
|
||||
</v-layout>
|
||||
<v-divider light></v-divider>
|
||||
<v-card-actions class="pa-3">
|
||||
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn icon>
|
||||
<v-icon @click="$router.push({name: 'appDetails', params: {id: item.id}})">settings</v-icon>
|
||||
</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-flex>
|
||||
</v-layout>
|
||||
</v-container>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import AppService from '../services/Apps'
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
apps: []
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getImageUrl: function(id) {
|
||||
return AppService.getAppImage(id); // "https://account.keks.cloud/gui/apps/"+id+"/icon";
|
||||
}
|
||||
},
|
||||
mounted: function() {
|
||||
AppService.listApps().then((res) => {
|
||||
this.apps = res.data.data;
|
||||
console.log(this.apps);
|
||||
});
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
100
src/views/Login.vue
Normal file
100
src/views/Login.vue
Normal file
|
@ -0,0 +1,100 @@
|
|||
<template>
|
||||
<div style="">
|
||||
<div class="header">
|
||||
</div>
|
||||
<v-container grid-list-md>
|
||||
<v-layout row wrap>
|
||||
<v-flex md4></v-flex>
|
||||
<v-flex md4 v-if="!$store.state.loggedIn">
|
||||
<Login></Login>
|
||||
</v-flex>
|
||||
<v-flex md4 v-if="$store.state.loggedIn">
|
||||
<p>Hallo {{$store.getters.getMe["username"]}}, du bist bereits eingeloggt.</p>
|
||||
</v-flex>
|
||||
|
||||
|
||||
</v-layout>
|
||||
</v-container>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ServerService from '../services/Server'
|
||||
import UserService from '../services/User'
|
||||
import LoginComponent from '../components/Login'
|
||||
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
nameBig: '',
|
||||
nameSmall: '',
|
||||
username: '',
|
||||
password: '',
|
||||
errorMessage: ''
|
||||
}
|
||||
},
|
||||
components: {
|
||||
"Login": LoginComponent
|
||||
},
|
||||
methods: {
|
||||
'login': function () {
|
||||
UserService.login(this.username, this.password).then((res) => {
|
||||
this.errorMessage = '';
|
||||
UserService.setAccessToken(res.data.data["access_token"]);
|
||||
console.log("Login ok, dispatch event");
|
||||
this.$store.dispatch('checkAccount');
|
||||
}, (res) => {
|
||||
this.errorMessage = res.response.data.msg;
|
||||
});
|
||||
}
|
||||
},
|
||||
mounted: function() {
|
||||
console.log("REDIRECT: "+this.$store.state.redirectIfLoggedIn)
|
||||
if(this.$store.state.loggedIn == true && this.$store.state.redirectIfLoggedIn != null) {
|
||||
this.$router.push(this.$store.state.redirectIfLoggedIn);
|
||||
}
|
||||
this.nameBig = this.$store.getters.getSettingValue("name_big");
|
||||
this.nameSmall = this.$store.getters.getSettingValue("name_small");
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.header {
|
||||
background-image: url('~@/assets/manhattan-407703_1920.jpg');
|
||||
background-repeat: no-repeat;
|
||||
margin-top: -100px;
|
||||
height: 30vh;
|
||||
text-align: center;
|
||||
}
|
||||
.header h1{
|
||||
padding-top: 200px;
|
||||
font-size: 56px !important;
|
||||
font-weight: 400;
|
||||
line-height: 32px !important;
|
||||
letter-spacing: normal !important;
|
||||
}
|
||||
.header h1 .small{
|
||||
font-weight: 300 !important;
|
||||
}
|
||||
.header h2{
|
||||
padding-top: 30px;
|
||||
font-size: 34px !important;
|
||||
font-weight: 300;
|
||||
line-height: 32px !important;
|
||||
letter-spacing: normal !important;
|
||||
}
|
||||
h1{
|
||||
font-weight: 300;
|
||||
line-height: 32px !important;
|
||||
letter-spacing: normal !important;
|
||||
}
|
||||
h2{
|
||||
font-weight: 300;
|
||||
line-height: 32px !important;
|
||||
letter-spacing: normal !important;
|
||||
}
|
||||
</style>
|
141
src/views/OAuthPermission.vue
Normal file
141
src/views/OAuthPermission.vue
Normal file
|
@ -0,0 +1,141 @@
|
|||
<template>
|
||||
<div style="">
|
||||
<div class="header">
|
||||
</div>
|
||||
<v-container grid-list-md>
|
||||
<v-layout row wrap>
|
||||
<v-flex md4></v-flex>
|
||||
<v-flex md4 v-if="!$store.state.loggedIn">
|
||||
<Login loginToService="true" serviceName="Jenkins" @loggedIn="getAppData();"></Login>
|
||||
</v-flex>
|
||||
<v-flex md4 v-if="$store.state.loggedIn && app != null">
|
||||
<h1>Login to {{ app.name }}</h1>
|
||||
<p>{{ app.description }}</p>
|
||||
<hr>
|
||||
<div style="margin-top:20px;margin-bottom:20px;">
|
||||
This App get the following permissions:<br /><br />
|
||||
<ul>
|
||||
<li v-if="app.access.read_profile">Read your Profile information</li>
|
||||
<li v-if="app.access.update_profile">>Update your Profile information</li>
|
||||
|
||||
<li v-if="app.access.read_apps">>Read your App information</li>
|
||||
<li v-if="app.access.update_apps">>Update your App information</li>
|
||||
|
||||
<li v-if="app.access.read_access">>Read your Access information</li>
|
||||
<li v-if="app.access.update_access">>Update your Access information</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<v-btn color="success" @click="allowAccess()" :disabled="disabledLoginButton" style="width: 100%;">Login to {{ app.name }}</v-btn>
|
||||
<br><br>
|
||||
|
||||
<a :href="app.url">Go to App-Webpage</a>
|
||||
</v-flex>
|
||||
|
||||
</v-layout>
|
||||
</v-container>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ServerService from '../services/Server'
|
||||
import UserService from '../services/User'
|
||||
import LoginComponent from '../components/Login'
|
||||
import AppsService from '../services/Apps'
|
||||
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
nameBig: '',
|
||||
nameSmall: '',
|
||||
username: '',
|
||||
password: '',
|
||||
errorMessage: '',
|
||||
app: null,
|
||||
disabledLoginButton: true,
|
||||
appId: null
|
||||
}
|
||||
},
|
||||
components: {
|
||||
'Login': LoginComponent
|
||||
},
|
||||
methods: {
|
||||
getAppData: function () {
|
||||
AppsService.getAppByKey(this.$route.query.client_id).then((res) => {
|
||||
this.appId = res.data.data[0].id
|
||||
AppsService.getAccess(res.data.data[0].id).then((access) => {
|
||||
if(access.data.data.status == "allowed") {
|
||||
if(res.data.data[0].properties.stopAutoRedirect) {
|
||||
this.disabledLoginButton = false;
|
||||
console.log("Disabled Auto redirect");
|
||||
} else {
|
||||
this.allowAccess();
|
||||
}
|
||||
console.log("ALLOWED");
|
||||
} else {
|
||||
this.disabledLoginButton = false;
|
||||
}
|
||||
console.log("Access Data", res.data);
|
||||
});
|
||||
console.log("App Data", res.data);
|
||||
this.app = res.data.data[0];
|
||||
});
|
||||
},
|
||||
allowAccess: function () {
|
||||
console.log(this.$route.query);
|
||||
AppsService.allowAccess(this.appId, this.$route.query.redirect_uri, this.$route.query.scope).then((res) => {
|
||||
console.log("App Access", res);
|
||||
location.href=res.data.data.redirectUrl
|
||||
});
|
||||
}
|
||||
|
||||
},
|
||||
mounted: function() {
|
||||
|
||||
this.nameBig = this.$store.getters.getSettingValue("name_big");
|
||||
this.nameSmall = this.$store.getters.getSettingValue("name_small");
|
||||
this.getAppData();
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.header {
|
||||
background-image: url('~@/assets/manhattan-407703_1920.jpg');
|
||||
background-repeat: no-repeat;
|
||||
margin-top: -100px;
|
||||
height: 30vh;
|
||||
text-align: center;
|
||||
}
|
||||
.header h1{
|
||||
padding-top: 200px;
|
||||
font-size: 56px !important;
|
||||
font-weight: 400;
|
||||
line-height: 32px !important;
|
||||
letter-spacing: normal !important;
|
||||
}
|
||||
.header h1 .small{
|
||||
font-weight: 300 !important;
|
||||
}
|
||||
.header h2{
|
||||
padding-top: 30px;
|
||||
font-size: 34px !important;
|
||||
font-weight: 300;
|
||||
line-height: 32px !important;
|
||||
letter-spacing: normal !important;
|
||||
}
|
||||
h1{
|
||||
font-weight: 300;
|
||||
line-height: 32px !important;
|
||||
letter-spacing: normal !important;
|
||||
}
|
||||
h2{
|
||||
font-weight: 300;
|
||||
line-height: 32px !important;
|
||||
letter-spacing: normal !important;
|
||||
}
|
||||
</style>
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<div style="">
|
||||
<div class="header">
|
||||
<div class="headerStartpage">
|
||||
<h1>{{ nameBig }}<span class="small">{{ nameSmall }}</span></h1>
|
||||
<h2>{{ slogen }}</h2>
|
||||
</div>
|
||||
|
@ -154,7 +154,6 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import ServerService from '../services/Server'
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
|
@ -177,25 +176,24 @@
|
|||
</script>
|
||||
|
||||
<style>
|
||||
.header {
|
||||
.headerStartpage {
|
||||
background-image: url('~@/assets/manhattan-407703_1920.jpg');
|
||||
background-repeat: no-repeat;
|
||||
margin-top: -100px;
|
||||
height: 45vh;
|
||||
height:90vh;
|
||||
text-align: center;
|
||||
}
|
||||
.header h1{
|
||||
.headerStartpage h1{
|
||||
padding-top: 200px;
|
||||
font-size: 56px !important;
|
||||
font-weight: 400;
|
||||
line-height: 32px !important;
|
||||
letter-spacing: normal !important;
|
||||
}
|
||||
.header h1 .small{
|
||||
.headerStartpage h1 .small{
|
||||
font-weight: 300 !important;
|
||||
}
|
||||
.header h2{
|
||||
.headerStartpage h2{
|
||||
padding-top: 30px;
|
||||
font-size: 34px !important;
|
||||
font-weight: 300;
|
Reference in a new issue