forked from geolba/tethys.backend
- add AvatarController.ts
- adapted menu.ts, NavBar.vue, NavBarItem.vue for highlighting active nav item - NavBarItemLabel.vue for app menu highlighting - adapted routes.ts - adapted app.edge for new favicon - adapted LayoutAuthenticated.vue (:showAsideMenu="false") for showing AsideMenu optional - new material icons: BriefcaseCheck.vue, SwapHorizontal.vue, AccountGroup.vue, Lock.vue - started with FirstRunWizard
This commit is contained in:
parent
ae0c471e93
commit
cefd9081ae
65
app/Controllers/Http/Api/AvatarController.ts
Normal file
65
app/Controllers/Http/Api/AvatarController.ts
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext';
|
||||||
|
import { StatusCodes } from 'http-status-codes';
|
||||||
|
// import * as fs from 'fs';
|
||||||
|
// import * as path from 'path';
|
||||||
|
|
||||||
|
const prefixes = ['von', 'van'];
|
||||||
|
|
||||||
|
// node ace make:controller Author
|
||||||
|
export default class AvatarController {
|
||||||
|
public async generateAvatar({ request, response }: HttpContextContract) {
|
||||||
|
try {
|
||||||
|
const { name, background, textColor, size } = request.only(['name', 'background', 'textColor', 'size']);
|
||||||
|
|
||||||
|
// Generate initials
|
||||||
|
// const initials = name
|
||||||
|
// .split(' ')
|
||||||
|
// .map((part) => part.charAt(0).toUpperCase())
|
||||||
|
// .join('');
|
||||||
|
const initials = this.getInitials(name);
|
||||||
|
|
||||||
|
// Define SVG content with dynamic values for initials, background color, text color, and size
|
||||||
|
const svgContent = `
|
||||||
|
<svg width="${size || 50}" height="${size || 50}" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<rect width="100%" height="100%" fill="#${background || '7F9CF5'}"/>
|
||||||
|
<text x="50%" y="50%" dominant-baseline="middle" text-anchor="middle" font-weight="bold" font-family="Arial, sans-serif" font-size="${
|
||||||
|
(size / 100) * 40 || 25
|
||||||
|
}" fill="#${textColor || 'ffffff'}">${initials}</text>
|
||||||
|
</svg>
|
||||||
|
`;
|
||||||
|
|
||||||
|
// Set response headers for SVG content
|
||||||
|
response.header('Content-type', 'image/svg+xml');
|
||||||
|
response.header('Cache-Control', 'no-cache');
|
||||||
|
response.header('Pragma', 'no-cache');
|
||||||
|
response.header('Expires', '0');
|
||||||
|
|
||||||
|
return response.send(svgContent);
|
||||||
|
} catch (error) {
|
||||||
|
return response.status(StatusCodes.OK).json({ error: error.message });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private getInitials(name) {
|
||||||
|
const parts = name.split(' ');
|
||||||
|
let initials = '';
|
||||||
|
|
||||||
|
if (parts.length >= 2) {
|
||||||
|
const firstName = parts[0];
|
||||||
|
const lastName = parts[parts.length - 1];
|
||||||
|
|
||||||
|
const firstInitial = firstName.charAt(0).toUpperCase();
|
||||||
|
const lastInitial = lastName.charAt(0).toUpperCase();
|
||||||
|
|
||||||
|
if (prefixes.includes(lastName.toLowerCase()) && lastName === lastName.toUpperCase()) {
|
||||||
|
initials = firstInitial + lastName.charAt(1).toUpperCase();
|
||||||
|
} else {
|
||||||
|
initials = firstInitial + lastInitial;
|
||||||
|
}
|
||||||
|
} else if (parts.length === 1) {
|
||||||
|
initials = parts[0].substring(0, 2).toUpperCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
return initials;
|
||||||
|
}
|
||||||
|
}
|
BIN
public/favicon.png
Normal file
BIN
public/favicon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
96
resources/js/Components/FirstrunWizard/components/Card.vue
Normal file
96
resources/js/Components/FirstrunWizard/components/Card.vue
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
<!--
|
||||||
|
- @copyright Copyright (c) 2023 Marco Ambrosini <marcoambrosini@proton.me>
|
||||||
|
-
|
||||||
|
- @author Simon Lindner <szaimen@e.mail.de>
|
||||||
|
- @author Marco Ambrosini <marcoambrosini@proton.me>
|
||||||
|
-
|
||||||
|
- @license GNU AGPL version 3 or any later version
|
||||||
|
-
|
||||||
|
- This program is free software: you can redistribute it and/or modify
|
||||||
|
- it under the terms of the GNU Affero General Public License as
|
||||||
|
- published by the Free Software Foundation, either version 3 of the
|
||||||
|
- License, or (at your option) any later version.
|
||||||
|
-
|
||||||
|
- This program is distributed in the hope that it will be useful,
|
||||||
|
- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
- GNU Affero General Public License for more details.
|
||||||
|
-
|
||||||
|
- You should have received a copy of the GNU Affero General Public License
|
||||||
|
- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
-
|
||||||
|
-->
|
||||||
|
<template>
|
||||||
|
<element :is="isLink ? 'a' : 'div'" :href="href || undefined" class="card" :class="{ 'card--link': isLink }"
|
||||||
|
:target="!isLink ? undefined : '_blank'" :rel="!isLink ? undefined : 'noreferrer'">
|
||||||
|
<div v-if="!isLink" class="card__icon">
|
||||||
|
<slot />
|
||||||
|
</div>
|
||||||
|
<div class="card__text">
|
||||||
|
<h3 class="card__heading">
|
||||||
|
{{ title }}
|
||||||
|
</h3>
|
||||||
|
<p>{{ subtitle }}</p>
|
||||||
|
</div>
|
||||||
|
</element>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'Card',
|
||||||
|
|
||||||
|
props: {
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
href: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
|
||||||
|
subtitle: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
isLink() {
|
||||||
|
return this.href !== ''
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="css" scoped>
|
||||||
|
.card {
|
||||||
|
display: flex;
|
||||||
|
max-width: 250px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
height: fit-content;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card__icon {
|
||||||
|
display: flex;
|
||||||
|
flex: 0 0 44px;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card__heading {
|
||||||
|
font-weight: bold;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card--link {
|
||||||
|
box-shadow: 0px 0px 10px 0px var(--color-box-shadow);
|
||||||
|
border-radius: var(--border-radius-large);
|
||||||
|
padding: calc(var(--default-grid-baseline) * 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.card--link:focus-visible {
|
||||||
|
outline: 2px solid var(--color-main-text);
|
||||||
|
box-shadow: 0 0 0 4px var(--color-main-background);
|
||||||
|
}
|
||||||
|
</style>
|
56
resources/js/Components/FirstrunWizard/components/Page1.vue
Normal file
56
resources/js/Components/FirstrunWizard/components/Page1.vue
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
<template>
|
||||||
|
<div class="page__wrapper">
|
||||||
|
<div class="page__scroller first-page">
|
||||||
|
<h2 class="page__heading">
|
||||||
|
{{ t('firstrunwizard', 'A collaboration platform that puts you in control') }}
|
||||||
|
</h2>
|
||||||
|
<div class="page__content">
|
||||||
|
<Card :title="t('firstrunwizard', 'Privacy')"
|
||||||
|
:subtitle="t('firstrunwizard', 'Host your data and files where you decide.')">
|
||||||
|
<Lock :size="20" />
|
||||||
|
</Card>
|
||||||
|
<Card :title="t('firstrunwizard', 'Productivity')"
|
||||||
|
:subtitle="t('firstrunwizard', 'Collaborate and communicate across any platform.')">
|
||||||
|
<BriefcaseCheck :size="20" />
|
||||||
|
</Card>
|
||||||
|
<Card :title="t('firstrunwizard', 'Interoperability')"
|
||||||
|
:subtitle="t('firstrunwizard', 'Import and export anything you want with open standards.')">
|
||||||
|
<SwapHorizontal :size="20" />
|
||||||
|
</Card>
|
||||||
|
<Card :title="t('firstrunwizard', 'Community')"
|
||||||
|
:subtitle="t('firstrunwizard', 'Enjoy constant improvements from a thriving open-source community.')">
|
||||||
|
<AccountGroup :size="20" />
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Card from './Card.vue'
|
||||||
|
|
||||||
|
import Lock from 'vue-material-design-icons/Lock.vue'
|
||||||
|
import BriefcaseCheck from 'vue-material-design-icons/BriefcaseCheck.vue'
|
||||||
|
import SwapHorizontal from 'vue-material-design-icons/SwapHorizontal.vue'
|
||||||
|
import AccountGroup from 'vue-material-design-icons/AccountGroup.vue'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'Page1',
|
||||||
|
|
||||||
|
components: {
|
||||||
|
Card,
|
||||||
|
Lock,
|
||||||
|
BriefcaseCheck,
|
||||||
|
SwapHorizontal,
|
||||||
|
AccountGroup,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="css" scoped>
|
||||||
|
/* @import "pageStyles"; */
|
||||||
|
|
||||||
|
.first-page {
|
||||||
|
margin-top: 100px;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,31 @@
|
||||||
|
.page {
|
||||||
|
&__wrapper {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
min-height: min(520px, 50vh);
|
||||||
|
}
|
||||||
|
|
||||||
|
&__scroller {
|
||||||
|
overflow-y: scroll;
|
||||||
|
margin-top: calc(var(--default-grid-baseline) * 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
&__heading {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__subtitle {
|
||||||
|
max-width: 450px;
|
||||||
|
margin: auto;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__content {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: calc(var(--default-grid-baseline) * 6);
|
||||||
|
justify-content: center;
|
||||||
|
margin: calc(var(--default-grid-baseline) * 10) 0;
|
||||||
|
}
|
||||||
|
}
|
31
resources/js/Components/Icons/AccountGroup.vue
Normal file
31
resources/js/Components/Icons/AccountGroup.vue
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
<template>
|
||||||
|
<span v-bind="$attrs" :aria-hidden="!title" :aria-label="title" class="material-design-icon account-group-icon"
|
||||||
|
role="img" @click="$emit('click', $event)">
|
||||||
|
<svg :fill="fillColor" class="material-design-icon__svg" :width="size" :height="size" viewBox="0 0 24 24">
|
||||||
|
<path
|
||||||
|
d="M12,5.5A3.5,3.5 0 0,1 15.5,9A3.5,3.5 0 0,1 12,12.5A3.5,3.5 0 0,1 8.5,9A3.5,3.5 0 0,1 12,5.5M5,8C5.56,8 6.08,8.15 6.53,8.42C6.38,9.85 6.8,11.27 7.66,12.38C7.16,13.34 6.16,14 5,14A3,3 0 0,1 2,11A3,3 0 0,1 5,8M19,8A3,3 0 0,1 22,11A3,3 0 0,1 19,14C17.84,14 16.84,13.34 16.34,12.38C17.2,11.27 17.62,9.85 17.47,8.42C17.92,8.15 18.44,8 19,8M5.5,18.25C5.5,16.18 8.41,14.5 12,14.5C15.59,14.5 18.5,16.18 18.5,18.25V20H5.5V18.25M0,20V18.5C0,17.11 1.89,15.94 4.45,15.6C3.86,16.28 3.5,17.22 3.5,18.25V20H0M24,20H20.5V18.25C20.5,17.22 20.14,16.28 19.55,15.6C22.11,15.94 24,17.11 24,18.5V20Z">
|
||||||
|
<title v-if="title">{{ title }}</title>
|
||||||
|
</path>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: "AccountGroupIcon",
|
||||||
|
emits: ['click'],
|
||||||
|
props: {
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
},
|
||||||
|
fillColor: {
|
||||||
|
type: String,
|
||||||
|
default: "currentColor"
|
||||||
|
},
|
||||||
|
size: {
|
||||||
|
type: Number,
|
||||||
|
default: 24
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
31
resources/js/Components/Icons/BriefcaseCheck.vue
Normal file
31
resources/js/Components/Icons/BriefcaseCheck.vue
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
<template>
|
||||||
|
<span v-bind="$attrs" :aria-hidden="!title" :aria-label="title" class="material-design-icon briefcase-check-icon"
|
||||||
|
role="img" @click="$emit('click', $event)">
|
||||||
|
<svg :fill="fillColor" class="material-design-icon__svg" :width="size" :height="size" viewBox="0 0 24 24">
|
||||||
|
<path
|
||||||
|
d="M10,2H14A2,2 0 0,1 16,4V6H20A2,2 0 0,1 22,8V19A2,2 0 0,1 20,21H4A2,2 0 0,1 2,19V8A2,2 0 0,1 4,6H8V4A2,2 0 0,1 10,2M14,6V4H10V6H14M10.5,17.5L17.09,10.91L15.68,9.5L10.5,14.67L8.41,12.59L7,14L10.5,17.5Z">
|
||||||
|
<title v-if="title">{{ title }}</title>
|
||||||
|
</path>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: "BriefcaseCheckIcon",
|
||||||
|
emits: ['click'],
|
||||||
|
props: {
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
},
|
||||||
|
fillColor: {
|
||||||
|
type: String,
|
||||||
|
default: "currentColor"
|
||||||
|
},
|
||||||
|
size: {
|
||||||
|
type: Number,
|
||||||
|
default: 24
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
31
resources/js/Components/Icons/Lock.vue
Normal file
31
resources/js/Components/Icons/Lock.vue
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
<template>
|
||||||
|
<span v-bind="$attrs" :aria-hidden="!title" :aria-label="title" class="material-design-icon lock-icon" role="img"
|
||||||
|
@click="$emit('click', $event)">
|
||||||
|
<svg :fill="fillColor" class="material-design-icon__svg" :width="size" :height="size" viewBox="0 0 24 24">
|
||||||
|
<path
|
||||||
|
d="M12,17A2,2 0 0,0 14,15C14,13.89 13.1,13 12,13A2,2 0 0,0 10,15A2,2 0 0,0 12,17M18,8A2,2 0 0,1 20,10V20A2,2 0 0,1 18,22H6A2,2 0 0,1 4,20V10C4,8.89 4.9,8 6,8H7V6A5,5 0 0,1 12,1A5,5 0 0,1 17,6V8H18M12,3A3,3 0 0,0 9,6V8H15V6A3,3 0 0,0 12,3Z">
|
||||||
|
<title v-if="title">{{ title }}</title>
|
||||||
|
</path>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: "LockIcon",
|
||||||
|
emits: ['click'],
|
||||||
|
props: {
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
},
|
||||||
|
fillColor: {
|
||||||
|
type: String,
|
||||||
|
default: "currentColor"
|
||||||
|
},
|
||||||
|
size: {
|
||||||
|
type: Number,
|
||||||
|
default: 24
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
30
resources/js/Components/Icons/SwapHorizontal.vue
Normal file
30
resources/js/Components/Icons/SwapHorizontal.vue
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
<template>
|
||||||
|
<span v-bind="$attrs" :aria-hidden="!title" :aria-label="title" class="material-design-icon swap-horizontal-icon"
|
||||||
|
role="img" @click="$emit('click', $event)">
|
||||||
|
<svg :fill="fillColor" class="material-design-icon__svg" :width="size" :height="size" viewBox="0 0 24 24">
|
||||||
|
<path d="M21,9L17,5V8H10V10H17V13M7,11L3,15L7,19V16H14V14H7V11Z">
|
||||||
|
<title v-if="title">{{ title }}</title>
|
||||||
|
</path>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: "SwapHorizontalIcon",
|
||||||
|
emits: ['click'],
|
||||||
|
props: {
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
},
|
||||||
|
fillColor: {
|
||||||
|
type: String,
|
||||||
|
default: "currentColor"
|
||||||
|
},
|
||||||
|
size: {
|
||||||
|
type: Number,
|
||||||
|
default: 24
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -19,12 +19,15 @@ import {
|
||||||
mdiCloudDownloadOutline,
|
mdiCloudDownloadOutline,
|
||||||
mdiCloud,
|
mdiCloud,
|
||||||
mdiCrop,
|
mdiCrop,
|
||||||
mdiAccount,
|
mdiAccountCog,
|
||||||
mdiCogOutline,
|
mdiFormatListGroup ,
|
||||||
mdiEmail,
|
mdiFormatListNumbered,
|
||||||
|
// mdiEmail,
|
||||||
mdiLogout,
|
mdiLogout,
|
||||||
mdiGithub,
|
mdiGithub,
|
||||||
mdiThemeLightDark,
|
mdiThemeLightDark,
|
||||||
|
mdiViewDashboard,
|
||||||
|
mdiMapSearch
|
||||||
} from '@mdi/js';
|
} from '@mdi/js';
|
||||||
import NavBarItem from '@/Components/NavBarItem.vue';
|
import NavBarItem from '@/Components/NavBarItem.vue';
|
||||||
import NavBarItemLabel from '@/Components/NavBarItemLabel.vue';
|
import NavBarItemLabel from '@/Components/NavBarItemLabel.vue';
|
||||||
|
@ -32,20 +35,25 @@ import NavBarMenu from '@/Components/NavBarMenu.vue';
|
||||||
import BaseDivider from '@/Components/BaseDivider.vue';
|
import BaseDivider from '@/Components/BaseDivider.vue';
|
||||||
import UserAvatarCurrentUser from '@/Components/UserAvatarCurrentUser.vue';
|
import UserAvatarCurrentUser from '@/Components/UserAvatarCurrentUser.vue';
|
||||||
import BaseIcon from '@/Components/BaseIcon.vue';
|
import BaseIcon from '@/Components/BaseIcon.vue';
|
||||||
import NavBarSearch from '@/Components/NavBarSearch.vue';
|
// import NavBarSearch from '@/Components/NavBarSearch.vue';
|
||||||
import { stardust } from '@eidellev/adonis-stardust/client';
|
import { stardust } from '@eidellev/adonis-stardust/client';
|
||||||
import type { User } from '@/Dataset';
|
import type { User } from '@/Dataset';
|
||||||
|
// import FirstrunWizard from '@/Components/FirstrunWizard/FirstrunWizard.vue'
|
||||||
|
import Lock from 'vue-material-design-icons/Lock.vue'
|
||||||
|
// import BriefcaseCheck from 'vue-material-design-icons/BriefcaseCheck.vue'
|
||||||
|
// import SwapHorizontal from 'vue-material-design-icons/SwapHorizontal.vue'
|
||||||
|
// import AccountGroup from 'vue-material-design-icons/AccountGroup.vue'
|
||||||
|
|
||||||
// const mainStore = MainService();
|
// const mainStore = MainService();
|
||||||
// const userName = computed(() =>mainStore.userName);
|
// const userName = computed(() =>mainStore.userName);
|
||||||
|
|
||||||
const styleService = StyleService();
|
const styleService = StyleService();
|
||||||
// const props = defineProps({
|
const props = defineProps({
|
||||||
// user: {
|
showBurger: {
|
||||||
// type: Object,
|
type: Boolean,
|
||||||
// default: () => ({}),
|
default: true // Set default value to true
|
||||||
// }
|
}
|
||||||
// });
|
});
|
||||||
// const userName = computed(() => usePage().props.user.login)
|
// const userName = computed(() => usePage().props.user.login)
|
||||||
|
|
||||||
const user: ComputedRef<User> = computed(() => {
|
const user: ComputedRef<User> = computed(() => {
|
||||||
|
@ -80,32 +88,41 @@ const logout = async () => {
|
||||||
// router.post(route('logout'));
|
// router.post(route('logout'));
|
||||||
await router.post(stardust.route('logout'));
|
await router.post(stardust.route('logout'));
|
||||||
};
|
};
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<nav class="top-0 left-0 right-0 fixed bg-gray-50 h-14 z-40 w-screen transition-position xl:pl-60 lg:w-auto dark:bg-slate-800">
|
<nav class="text-base top-0 left-0 right-0 fixed bg-gray-50 h-14 z-40 w-screen transition-position lg:w-auto dark:bg-slate-800"
|
||||||
|
:class="{ 'xl:pl-60': props.showBurger == true }">
|
||||||
<div class="flex lg:items-stretch" :class="containerMaxW">
|
<div class="flex lg:items-stretch" :class="containerMaxW">
|
||||||
<div class="flex-1 items-stretch flex h-14">
|
<div class="flex-1 items-stretch flex h-14">
|
||||||
<NavBarItem type="flex lg:hidden" @click.prevent="layoutStore.asideMobileToggle()">
|
<NavBarItem type="flex lg:hidden" @click.prevent="layoutStore.asideMobileToggle()" v-if="props.showBurger">
|
||||||
<BaseIcon :path="layoutStore.isAsideMobileExpanded ? mdiBackburger : mdiForwardburger" size="24" />
|
<BaseIcon :path="layoutStore.isAsideMobileExpanded ? mdiBackburger : mdiForwardburger" size="24" />
|
||||||
</NavBarItem>
|
</NavBarItem>
|
||||||
<NavBarItem type="hidden lg:flex xl:hidden" @click.prevent="menuOpenLg">
|
<NavBarItem type="hidden lg:flex xl:hidden" @click.prevent="menuOpenLg" v-if="props.showBurger">
|
||||||
<BaseIcon :path="mdiMenu" size="24" />
|
<BaseIcon :path="mdiMenu" size="24" />
|
||||||
</NavBarItem>
|
</NavBarItem>
|
||||||
<NavBarItem>
|
<NavBarItem route-name="apps.dashboard">
|
||||||
<NavBarSearch />
|
<NavBarItemLabel :icon="mdiViewDashboard" label="Dashboard" size="22" is-hover-label-only route-name="apps.dashboard" />
|
||||||
</NavBarItem>
|
</NavBarItem>
|
||||||
|
<NavBarItem route-name="apps.map">
|
||||||
|
<NavBarItemLabel :icon="mdiMapSearch" label="Map" size="22" is-hover-label-only route-name="apps.map" />
|
||||||
|
</NavBarItem>
|
||||||
|
<!-- <NavBarItem>
|
||||||
|
<NavBarSearch />
|
||||||
|
</NavBarItem> -->
|
||||||
</div>
|
</div>
|
||||||
<div class="flex-none items-stretch flex h-14 lg:hidden">
|
<div class="flex-none items-stretch flex h-14 lg:hidden">
|
||||||
<NavBarItem @click.prevent="menuNavBarToggle">
|
<NavBarItem @click.prevent="menuNavBarToggle">
|
||||||
<BaseIcon :path="isMenuNavBarActive ? mdiClose : mdiDotsVertical" size="24" />
|
<BaseIcon :path="isMenuNavBarActive ? mdiClose : mdiDotsVertical" size="24" />
|
||||||
</NavBarItem>
|
</NavBarItem>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div class="absolute w-screen top-14 left-0 bg-gray-50 shadow lg:w-auto lg:items-stretch lg:flex lg:grow lg:static lg:border-b-0 lg:overflow-visible lg:shadow-none dark:bg-slate-800"
|
||||||
class="absolute w-screen top-14 left-0 bg-gray-50 shadow lg:w-auto lg:items-stretch lg:flex lg:grow lg:static lg:border-b-0 lg:overflow-visible lg:shadow-none dark:bg-slate-800"
|
:class="[isMenuNavBarActive ? 'block' : 'hidden']">
|
||||||
:class="[isMenuNavBarActive ? 'block' : 'hidden']"
|
<div
|
||||||
>
|
class="max-h-screen-menu overflow-y-auto lg:overflow-visible lg:flex lg:items-stretch lg:justify-end lg:ml-auto">
|
||||||
<div class="max-h-screen-menu overflow-y-auto lg:overflow-visible lg:flex lg:items-stretch lg:justify-end lg:ml-auto">
|
|
||||||
|
<!-- help menu -->
|
||||||
<NavBarMenu>
|
<NavBarMenu>
|
||||||
<NavBarItemLabel :icon="mdiMenu" label="Help menu" />
|
<NavBarItemLabel :icon="mdiMenu" label="Help menu" />
|
||||||
<template #dropdown>
|
<template #dropdown>
|
||||||
|
@ -125,23 +142,29 @@ const logout = async () => {
|
||||||
</template>
|
</template>
|
||||||
</NavBarMenu>
|
</NavBarMenu>
|
||||||
|
|
||||||
|
<!-- personal menu -->
|
||||||
<NavBarMenu>
|
<NavBarMenu>
|
||||||
<NavBarItemLabel v-bind:label="user.login">
|
<NavBarItemLabel v-bind:label="`hello ${user.login}`">
|
||||||
<UserAvatarCurrentUser class="w-6 h-6 mr-3 inline-flex" />
|
<UserAvatarCurrentUser class="w-6 h-6 mr-3 inline-flex" />
|
||||||
</NavBarItemLabel>
|
</NavBarItemLabel>
|
||||||
|
|
||||||
<template #dropdown>
|
<template #dropdown>
|
||||||
<!-- <NavBarItem> -->
|
<!-- <NavBarItem> -->
|
||||||
<!-- <NavBarItem route-name="admin.account.info"> -->
|
<!-- <NavBarItem route-name="admin.account.info"> -->
|
||||||
<NavBarItem :route-name="'settings.user'">
|
<NavBarItem :route-name="'settings.user'">
|
||||||
<NavBarItemLabel :icon="mdiAccount" label="My Profile" />
|
<NavBarItemLabel :icon="mdiAccountCog" label="User Settings" />
|
||||||
</NavBarItem>
|
</NavBarItem>
|
||||||
<NavBarItem v-if="userHasRoles(['moderator', 'administrator'])" :route-name="'settings'">
|
<NavBarItem v-if="userHasRoles(['administrator'])" :route-name="'settings.overview'">
|
||||||
<NavBarItemLabel :icon="mdiCogOutline" label="Settings" />
|
<NavBarItemLabel :icon="mdiFormatListGroup" label="Administration" />
|
||||||
</NavBarItem>
|
</NavBarItem>
|
||||||
<NavBarItem>
|
<NavBarItem v-if="userHasRoles(['submitter'])" :route-name="'dataset.list'">
|
||||||
|
<NavBarItemLabel :icon="mdiFormatListNumbered" label="Submitter Setup" />
|
||||||
|
</NavBarItem>
|
||||||
|
<NavBarItem v-if="userHasRoles(['editor'])" :route-name="'editor.dataset.list'">
|
||||||
|
<NavBarItemLabel :icon="mdiFormatListNumbered" label="Editor Setup" />
|
||||||
|
</NavBarItem>
|
||||||
|
<!-- <NavBarItem>
|
||||||
<NavBarItemLabel :icon="mdiEmail" label="Messages" />
|
<NavBarItemLabel :icon="mdiEmail" label="Messages" />
|
||||||
</NavBarItem>
|
</NavBarItem> -->
|
||||||
<BaseDivider nav-bar />
|
<BaseDivider nav-bar />
|
||||||
<NavBarItem @click="logout">
|
<NavBarItem @click="logout">
|
||||||
<NavBarItemLabel :icon="mdiLogout" label="Log Out" />
|
<NavBarItemLabel :icon="mdiLogout" label="Log Out" />
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<script setup>
|
<script lang="ts" setup>
|
||||||
import { StyleService } from '@/Stores/style';
|
import { StyleService } from '@/Stores/style';
|
||||||
// import { Link } from '@inertiajs/vue3'
|
// import { Link } from '@inertiajs/vue3'
|
||||||
import { Link } from '@inertiajs/vue3';
|
import { Link } from '@inertiajs/vue3';
|
||||||
|
@ -28,6 +28,10 @@ const props = defineProps({
|
||||||
isDesktopIconOnly: Boolean,
|
isDesktopIconOnly: Boolean,
|
||||||
dropdown: Boolean,
|
dropdown: Boolean,
|
||||||
active: Boolean,
|
active: Boolean,
|
||||||
|
underline: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const is = computed(() => {
|
const is = computed(() => {
|
||||||
|
@ -44,20 +48,50 @@ const is = computed(() => {
|
||||||
|
|
||||||
const styleStore = StyleService();
|
const styleStore = StyleService();
|
||||||
|
|
||||||
const activeColor = props.activeColor ?? `${styleStore.navBarItemLabelActiveColorStyle} dark:text-slate-400`;
|
// const activeColor = props.activeColor ?? `${styleStore.navBarItemLabelActiveColorStyle} dark:text-slate-400`;
|
||||||
|
|
||||||
const activeClass = computed(
|
|
||||||
// () => props.routeName && route().current(props.routeName) == true ? props.activeColor : null
|
// const active = computed(() => {
|
||||||
() => (props.routeName && stardust.isCurrent(props.routeName) ? props.activeColor : null),
|
// if (props.routeName && stardust.isCurrent(props.routeName)) {
|
||||||
);
|
// return true;
|
||||||
|
// }
|
||||||
|
// else {
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
|
const activeClass = computed(() => {
|
||||||
|
if (props.routeName && stardust.isCurrent(props.routeName)) {
|
||||||
|
// console.log(props.item.route);
|
||||||
|
const activeCls = [
|
||||||
|
styleStore.navBarItemLabelActiveColorStyle,
|
||||||
|
'dark:text-slate-400'
|
||||||
|
];
|
||||||
|
|
||||||
|
if (props.underline) {
|
||||||
|
activeCls.push('app-menu-entry__active');
|
||||||
|
}
|
||||||
|
|
||||||
|
// return `${styleStore.navBarItemLabelActiveColorStyle} dark:text-slate-400 app-menu-entry__active`;
|
||||||
|
return activeCls;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// const activeClass = computed(
|
||||||
|
// // () => props.routeName && route().current(props.routeName) == true ? props.activeColor : null
|
||||||
|
// () => (props.routeName && stardust.isCurrent(props.routeName) ? props.activeColor : null),
|
||||||
|
// );
|
||||||
// const itemRoute = computed(() => (props.routeName ? stardust.route(props.routeName): ''));
|
// const itemRoute = computed(() => (props.routeName ? stardust.route(props.routeName): ''));
|
||||||
|
|
||||||
const componentClass = computed(() => {
|
const componentClass = computed(() => {
|
||||||
const base = [
|
const base = [
|
||||||
props.type,
|
props.type,
|
||||||
props.active
|
`${styleStore.navBarItemLabelStyle} dark:text-white dark:hover:text-slate-400 ${styleStore.navBarItemLabelHoverStyle}`,
|
||||||
? activeColor
|
// props.active
|
||||||
: `${styleStore.navBarItemLabelStyle} dark:text-white dark:hover:text-slate-400 ${styleStore.navBarItemLabelHoverStyle}`,
|
// ? activeColor
|
||||||
|
// : `${styleStore.navBarItemLabelStyle} dark:text-white dark:hover:text-slate-400 ${styleStore.navBarItemLabelHoverStyle}`,
|
||||||
];
|
];
|
||||||
|
|
||||||
if (props.type === 'block') {
|
if (props.type === 'block') {
|
||||||
|
@ -79,12 +113,31 @@ const componentClass = computed(() => {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<component
|
<component :is="is" class="items-center grow-0 shrink-0 relative cursor-pointer" :class="[componentClass, activeClass]"
|
||||||
:is="is"
|
:href="routeName ? stardust.route(props.routeName, [props.param]) : href">
|
||||||
class="items-center grow-0 shrink-0 relative cursor-pointer"
|
|
||||||
:class="[componentClass, activeClass]"
|
|
||||||
:href="routeName ? stardust.route(props.routeName, [props.param]) : href"
|
|
||||||
>
|
|
||||||
<slot />
|
<slot />
|
||||||
</component>
|
</component>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<style lang="css" scoped>
|
||||||
|
.app-menu-entry__active {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-menu-entry__active::before {
|
||||||
|
content: "___";
|
||||||
|
position: absolute;
|
||||||
|
pointer-events: none;
|
||||||
|
/* border-bottom-color: var(--color-main-background); */
|
||||||
|
/* transform: translateX(-50%); */
|
||||||
|
width: 100%;
|
||||||
|
/* height: 5px; */
|
||||||
|
border-radius: 3px;
|
||||||
|
background-color: var(--color-primary-element-text);
|
||||||
|
/* left: 50%; */
|
||||||
|
bottom: 6px;
|
||||||
|
display: block;
|
||||||
|
transition: all 0.1s ease-in-out;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -1,7 +1,9 @@
|
||||||
<script setup>
|
<script lang="ts" setup>
|
||||||
import BaseIcon from '@/Components/BaseIcon.vue';
|
import BaseIcon from '@/Components/BaseIcon.vue';
|
||||||
|
import { computed } from 'vue';
|
||||||
|
import { stardust } from '@eidellev/adonis-stardust/client';
|
||||||
|
|
||||||
defineProps({
|
const props = defineProps({
|
||||||
icon: {
|
icon: {
|
||||||
type: String,
|
type: String,
|
||||||
default: null,
|
default: null,
|
||||||
|
@ -10,12 +12,90 @@ defineProps({
|
||||||
type: String,
|
type: String,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
|
size: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: 16,
|
||||||
|
},
|
||||||
isDesktopIconOnly: Boolean,
|
isDesktopIconOnly: Boolean,
|
||||||
|
isHoverLabelOnly: Boolean,
|
||||||
|
routeName: {
|
||||||
|
type: String,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const active = computed(() => {
|
||||||
|
if (props.routeName && stardust.isCurrent(props.routeName)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const componentClass = computed(() => {
|
||||||
|
const base = [
|
||||||
|
// props.type,
|
||||||
|
'flex',
|
||||||
|
];
|
||||||
|
if (props.isHoverLabelOnly ) {
|
||||||
|
base.push(' flex-col items-center');
|
||||||
|
}
|
||||||
|
|
||||||
|
return base;
|
||||||
|
});
|
||||||
|
|
||||||
|
const labelClass = computed(() => {
|
||||||
|
const base = [
|
||||||
|
// props.type,
|
||||||
|
'transition',
|
||||||
|
];
|
||||||
|
|
||||||
|
if (props.isDesktopIconOnly && props.icon) {
|
||||||
|
base.push('lg:hidden');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (props.isHoverLabelOnly && active.value == false) {
|
||||||
|
base.push('hidden');
|
||||||
|
} else if(props.isHoverLabelOnly && active.value == true) {
|
||||||
|
base.push('display-block');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return base;
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<slot />
|
<div :class="componentClass">
|
||||||
<BaseIcon v-if="icon" :path="icon" class="transition-colors" />
|
<slot />
|
||||||
<span class="px-2 transition-colors" :class="{ 'lg:hidden': isDesktopIconOnly && icon }">{{ label }}</span>
|
<BaseIcon v-if="icon" :path="props.icon" class="transition-colors" :size="props.size" />
|
||||||
|
<!-- <span class="px-2 transition-colors" :class="{ 'lg:hidden': isDesktopIconOnly && props.icon }">{{ props.label }}</span> -->
|
||||||
|
<span class="px-2 transition-colors" :class="labelClass">{{ props.label }}</span>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<!-- <style lang="css" scoped>
|
||||||
|
.app-menu-entry__active {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-menu-entry__active::before {
|
||||||
|
/* content: "___"; */
|
||||||
|
position: absolute;
|
||||||
|
pointer-events: none;
|
||||||
|
/* border-bottom-color: var(--color-main-background); */
|
||||||
|
/* transform: translateX(-50%); */
|
||||||
|
width: 100%;
|
||||||
|
/* height: 5px; */
|
||||||
|
border-radius: 3px;
|
||||||
|
border-bottom: 2px;
|
||||||
|
/* background-color: var(--color-primary-element-text); */
|
||||||
|
/* left: 50%; */
|
||||||
|
bottom: 6px;
|
||||||
|
display: block;
|
||||||
|
transition: all 0.1s ease-in-out;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
</style> -->
|
||||||
|
|
|
@ -19,19 +19,97 @@ const props = defineProps({
|
||||||
const avatar = computed(
|
const avatar = computed(
|
||||||
// () => props.avatar ?? `https://avatars.dicebear.com/api/${props.api}/${props.username?.replace(/[^a-z0-9]+/i, '-')}.svg`
|
// () => props.avatar ?? `https://avatars.dicebear.com/api/${props.api}/${props.username?.replace(/[^a-z0-9]+/i, '-')}.svg`
|
||||||
|
|
||||||
() => props.avatar ?? `https://avatars.dicebear.com/api/initials/${props.username}.svg`,
|
// () => props.avatar ?? `https://avatars.dicebear.com/api/initials/${props.username}.svg`,
|
||||||
|
|
||||||
// () => {
|
() => {
|
||||||
|
const initials = props.username
|
||||||
|
.split(' ')
|
||||||
|
.map((part) => part.charAt(0).toUpperCase())
|
||||||
|
.join('');
|
||||||
|
|
||||||
// return props.avatar ?? `https://www.gravatar.com/avatar/${props.username}?s=50`;
|
return props.avatar ?? generateAvatarUrl(props.username);
|
||||||
// }
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const username = computed(() => props.username);
|
const username = computed(() => props.username);
|
||||||
|
|
||||||
|
const darkenColor = (color) => {
|
||||||
|
// Convert hex to RGB
|
||||||
|
const r = parseInt(color.slice(0, 2), 16);
|
||||||
|
const g = parseInt(color.slice(2, 4), 16);
|
||||||
|
const b = parseInt(color.slice(4, 6), 16);
|
||||||
|
|
||||||
|
// Calculate darker color by reducing 20% of each RGB component
|
||||||
|
const darkerR = Math.round(r * 0.6);
|
||||||
|
const darkerG = Math.round(g * 0.6);
|
||||||
|
const darkerB = Math.round(b * 0.6);
|
||||||
|
|
||||||
|
// Convert back to hex
|
||||||
|
const darkerColor = ((darkerR << 16) + (darkerG << 8) + darkerB).toString(16);
|
||||||
|
|
||||||
|
return darkerColor.padStart(6, '0'); // Ensure it's 6 digits
|
||||||
|
};
|
||||||
|
|
||||||
|
const getRandomColor = () => {
|
||||||
|
return Math.floor(Math.random() * 16777215).toString(16);
|
||||||
|
};
|
||||||
|
|
||||||
|
const adjustOpacity = (hexColor, opacity) => {
|
||||||
|
// Remove # if present
|
||||||
|
hexColor = hexColor.replace('#', '');
|
||||||
|
// Convert hex to RGB
|
||||||
|
// const r = parseInt(hexColor.slice(0, 2), 16);
|
||||||
|
// const g = parseInt(hexColor.slice(2, 4), 16);
|
||||||
|
// const b = parseInt(hexColor.slice(4, 6), 16);
|
||||||
|
|
||||||
|
// const r = parseInt(hexColor.slice(1, 3), 16);
|
||||||
|
// const g = parseInt(hexColor.slice(3, 5), 16);
|
||||||
|
// const b = parseInt(hexColor.slice(5, 7), 16);
|
||||||
|
const [r, g, b] = hexColor.match(/\w\w/g).map(x => parseInt(x, 16));
|
||||||
|
|
||||||
|
return `rgba(${r},${g},${b},${opacity})`;
|
||||||
|
};
|
||||||
|
|
||||||
|
const lightenColor = (hexColor, percent) => {
|
||||||
|
let r = parseInt(hexColor.substring(0, 2), 16);
|
||||||
|
let g = parseInt(hexColor.substring(2, 4), 16);
|
||||||
|
let b = parseInt(hexColor.substring(4, 6), 16);
|
||||||
|
|
||||||
|
r = Math.floor(r * (100 + percent) / 100);
|
||||||
|
g = Math.floor(g * (100 + percent) / 100);
|
||||||
|
b = Math.floor(b * (100 + percent) / 100);
|
||||||
|
|
||||||
|
r = (r < 255) ? r : 255;
|
||||||
|
g = (g < 255) ? g : 255;
|
||||||
|
b = (b < 255) ? b : 255;
|
||||||
|
|
||||||
|
const lighterHex = ((r << 16) | (g << 8) | b).toString(16);
|
||||||
|
|
||||||
|
return lighterHex.padStart(6, '0');
|
||||||
|
};
|
||||||
|
|
||||||
|
// backgroundColor = '7F9CF5',
|
||||||
|
const generateAvatarUrl = (name) => {
|
||||||
|
const initials = name
|
||||||
|
.split(' ')
|
||||||
|
.map((part) => part.charAt(0).toUpperCase())
|
||||||
|
.join('');
|
||||||
|
|
||||||
|
const originalColor = getRandomColor();
|
||||||
|
|
||||||
|
const backgroundColor = lightenColor(originalColor, 60); // Lighten by 20%
|
||||||
|
|
||||||
|
const textColor = darkenColor(originalColor);
|
||||||
|
|
||||||
|
// const avatarUrl = `https://ui-avatars.com/api/?name=${initials}&size=50&background=${backgroundColor}&color=${textColor}`;
|
||||||
|
const avatarUrl = `/api/avatar?name=${name}&size=50&background=${backgroundColor}&textColor=${textColor}`;
|
||||||
|
return avatarUrl;
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<img :src="avatar" :alt="username" class="rounded-full block h-auto w-full max-w-full bg-gray-100 dark:bg-slate-800" />
|
<img :src="avatar" :alt="username"
|
||||||
|
class="rounded-full block h-auto w-full max-w-full bg-gray-100 dark:bg-slate-800" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -10,27 +10,33 @@ const styleService = StyleService();
|
||||||
|
|
||||||
const layoutService = LayoutService();
|
const layoutService = LayoutService();
|
||||||
|
|
||||||
// defineProps({
|
const props = defineProps({
|
||||||
// user: {
|
showAsideMenu: {
|
||||||
// type: Object,
|
type: Boolean,
|
||||||
// default: () => ({}),
|
default: true // Set default value to true
|
||||||
// }
|
}
|
||||||
// });
|
// user: {
|
||||||
|
// type: Object,
|
||||||
|
// default: () => ({}),
|
||||||
|
// }
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div :class="{
|
||||||
:class="{
|
'dark': styleService.darkMode,
|
||||||
'dark': styleService.darkMode,
|
'overflow-hidden lg:overflow-visible': layoutService.isAsideMobileExpanded,
|
||||||
'overflow-hidden lg:overflow-visible': layoutService.isAsideMobileExpanded,
|
}">
|
||||||
}"
|
<div :class="{
|
||||||
>
|
'ml-60 lg:ml-0': layoutService.isAsideMobileExpanded,
|
||||||
<div
|
'xl:pl-60': props.showAsideMenu==true }"
|
||||||
:class="{ 'ml-60 lg:ml-0': layoutService.isAsideMobileExpanded }"
|
class="pt-14 min-h-screen w-screen transition-position lg:w-auto bg-gray-50 dark:bg-slate-800 dark:text-slate-100">
|
||||||
class="pt-14 xl:pl-60 min-h-screen w-screen transition-position lg:w-auto bg-gray-50 dark:bg-slate-800 dark:text-slate-100"
|
<NavBar :class="{ 'ml-60 lg:ml-0': layoutService.isAsideMobileExpanded }" :showBurger="props.showAsideMenu" />
|
||||||
>
|
<!-- Conditionally render AsideMenu based on showAsideMenu prop -->
|
||||||
<NavBar :class="{ 'ml-60 lg:ml-0': layoutService.isAsideMobileExpanded }" />
|
<template v-if="showAsideMenu">
|
||||||
<AsideMenu />
|
<AsideMenu />
|
||||||
|
</template>
|
||||||
|
<!-- slot for main content -->
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
<FooterBar />
|
<FooterBar />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -28,7 +28,7 @@ const form = useForm({
|
||||||
});
|
});
|
||||||
|
|
||||||
const submit = async () => {
|
const submit = async () => {
|
||||||
await form.post(stardust.route('role.store'), form);
|
await form.post(stardust.route('settings.role.store'), form);
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ const submit = async () => {
|
||||||
<SectionMain>
|
<SectionMain>
|
||||||
<SectionTitleLineWithButton :icon="mdiAccountKey" title="Add role" main>
|
<SectionTitleLineWithButton :icon="mdiAccountKey" title="Add role" main>
|
||||||
<BaseButton
|
<BaseButton
|
||||||
:route-name="stardust.route('role.index')"
|
:route-name="stardust.route('settings.role.index')"
|
||||||
:icon="mdiArrowLeftBoldOutline"
|
:icon="mdiArrowLeftBoldOutline"
|
||||||
label="Back"
|
label="Back"
|
||||||
color="white"
|
color="white"
|
||||||
|
|
|
@ -37,7 +37,7 @@ const form = useForm({
|
||||||
|
|
||||||
const submit = async () => {
|
const submit = async () => {
|
||||||
// await Inertia.post(stardust.route('user.store'), form);
|
// await Inertia.post(stardust.route('user.store'), form);
|
||||||
await form.put(stardust.route('role.update', [props.role.id]), form);
|
await form.put(stardust.route('settings.role.update', [props.role.id]), form);
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ const submit = async () => {
|
||||||
<SectionMain>
|
<SectionMain>
|
||||||
<SectionTitleLineWithButton :icon="mdiAccountKey" title="Update role" main>
|
<SectionTitleLineWithButton :icon="mdiAccountKey" title="Update role" main>
|
||||||
<BaseButton
|
<BaseButton
|
||||||
:route-name="stardust.route('role.index')"
|
:route-name="stardust.route('settings.role.index')"
|
||||||
:icon="mdiArrowLeftBoldOutline"
|
:icon="mdiArrowLeftBoldOutline"
|
||||||
label="Back"
|
label="Back"
|
||||||
color="white"
|
color="white"
|
||||||
|
|
|
@ -47,7 +47,7 @@ const formDelete = useForm({});
|
||||||
// function destroy(id) {
|
// function destroy(id) {
|
||||||
// const destroy = async (id) => {
|
// const destroy = async (id) => {
|
||||||
// if (confirm('Are you sure you want to delete?')) {
|
// if (confirm('Are you sure you want to delete?')) {
|
||||||
// await formDelete.delete(stardust.route('role.destroy', [id]));
|
// await formDelete.delete(stardust.route('settings.role.destroy', [id]));
|
||||||
// }
|
// }
|
||||||
// };
|
// };
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@ const destroy = (id, e) => {
|
||||||
|
|
||||||
const onConfirm = async (id) => {
|
const onConfirm = async (id) => {
|
||||||
// let id = 6;
|
// let id = 6;
|
||||||
await formDelete.delete(stardust.route('role.destroy', [id]));
|
await formDelete.delete(stardust.route('settings.role.destroy', [id]));
|
||||||
deleteId.value = null;
|
deleteId.value = null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -90,7 +90,7 @@ const onCancel = (id) => {
|
||||||
<SectionTitleLineWithButton :icon="mdiAccountKey" title="Roles" main>
|
<SectionTitleLineWithButton :icon="mdiAccountKey" title="Roles" main>
|
||||||
<BaseButton
|
<BaseButton
|
||||||
v-if="can.create"
|
v-if="can.create"
|
||||||
:route-name="stardust.route('role.create')"
|
:route-name="stardust.route('settings.role.create')"
|
||||||
:icon="mdiPlus"
|
:icon="mdiPlus"
|
||||||
label="Add"
|
label="Add"
|
||||||
color="info"
|
color="info"
|
||||||
|
@ -139,7 +139,7 @@ const onCancel = (id) => {
|
||||||
<tr v-for="role in roles" :key="role.id">
|
<tr v-for="role in roles" :key="role.id">
|
||||||
<td data-label="Name">
|
<td data-label="Name">
|
||||||
<Link
|
<Link
|
||||||
:href="stardust.route('role.show', [role.id])"
|
:href="stardust.route('settings.role.show', [role.id])"
|
||||||
class="no-underline hover:underline text-cyan-600 dark:text-cyan-400"
|
class="no-underline hover:underline text-cyan-600 dark:text-cyan-400"
|
||||||
>
|
>
|
||||||
{{ role.name }}
|
{{ role.name }}
|
||||||
|
@ -152,7 +152,7 @@ const onCancel = (id) => {
|
||||||
<BaseButtons type="justify-start lg:justify-end" no-wrap>
|
<BaseButtons type="justify-start lg:justify-end" no-wrap>
|
||||||
<BaseButton
|
<BaseButton
|
||||||
v-if="can.edit"
|
v-if="can.edit"
|
||||||
:route-name="stardust.route('role.edit', [role.id])"
|
:route-name="stardust.route('settings.role.edit', [role.id])"
|
||||||
color="info"
|
color="info"
|
||||||
:icon="mdiSquareEditOutline"
|
:icon="mdiSquareEditOutline"
|
||||||
small
|
small
|
||||||
|
|
|
@ -30,7 +30,7 @@ const props = defineProps({
|
||||||
<SectionMain>
|
<SectionMain>
|
||||||
<SectionTitleLineWithButton :icon="mdiAccountKey" title="View role" main>
|
<SectionTitleLineWithButton :icon="mdiAccountKey" title="View role" main>
|
||||||
<BaseButton
|
<BaseButton
|
||||||
:route-name="stardust.route('role.index')"
|
:route-name="stardust.route('settings.role.index')"
|
||||||
:icon="mdiArrowLeftBoldOutline"
|
:icon="mdiArrowLeftBoldOutline"
|
||||||
label="Back"
|
label="Back"
|
||||||
color="white"
|
color="white"
|
||||||
|
|
|
@ -34,7 +34,7 @@ const form = useForm({
|
||||||
});
|
});
|
||||||
|
|
||||||
const submit = async () => {
|
const submit = async () => {
|
||||||
await router.post(stardust.route('user.store'), form);
|
await router.post(stardust.route('settings.user.store'), form);
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ const submit = async () => {
|
||||||
<SectionMain>
|
<SectionMain>
|
||||||
<SectionTitleLineWithButton :icon="mdiAccountKey" title="Add user" main>
|
<SectionTitleLineWithButton :icon="mdiAccountKey" title="Add user" main>
|
||||||
<BaseButton
|
<BaseButton
|
||||||
:route-name="stardust.route('user.index')"
|
:route-name="stardust.route('settings.user.index')"
|
||||||
:icon="mdiArrowLeftBoldOutline"
|
:icon="mdiArrowLeftBoldOutline"
|
||||||
label="Back"
|
label="Back"
|
||||||
color="modern"
|
color="modern"
|
||||||
|
@ -52,7 +52,7 @@ const submit = async () => {
|
||||||
small
|
small
|
||||||
/>
|
/>
|
||||||
</SectionTitleLineWithButton>
|
</SectionTitleLineWithButton>
|
||||||
<!-- @submit.prevent="form.post(stardust.route('user.store'))" -->
|
<!-- @submit.prevent="form.post(stardust.route('settings.user.store'))" -->
|
||||||
<CardBox form @submit.prevent="submit()">
|
<CardBox form @submit.prevent="submit()">
|
||||||
<FormField label="Login" :class="{ 'text-red-400': errors.login }">
|
<FormField label="Login" :class="{ 'text-red-400': errors.login }">
|
||||||
<FormControl v-model="form.login" type="text" placeholder="Enter Login" :errors="errors.login">
|
<FormControl v-model="form.login" type="text" placeholder="Enter Login" :errors="errors.login">
|
||||||
|
|
|
@ -44,7 +44,7 @@ const form = useForm({
|
||||||
|
|
||||||
const submit = async () => {
|
const submit = async () => {
|
||||||
// await Inertia.post(stardust.route('user.store'), form);
|
// await Inertia.post(stardust.route('user.store'), form);
|
||||||
await router.put(stardust.route('user.update', [props.user.id]), form);
|
await router.put(stardust.route('settings.user.update', [props.user.id]), form);
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ const submit = async () => {
|
||||||
<SectionMain>
|
<SectionMain>
|
||||||
<SectionTitleLineWithButton :icon="mdiAccountKey" title="Update user" main>
|
<SectionTitleLineWithButton :icon="mdiAccountKey" title="Update user" main>
|
||||||
<BaseButton
|
<BaseButton
|
||||||
:route-name="stardust.route('user.index')"
|
:route-name="stardust.route('settings.user.index')"
|
||||||
:icon="mdiArrowLeftBoldOutline"
|
:icon="mdiArrowLeftBoldOutline"
|
||||||
label="Back"
|
label="Back"
|
||||||
color="white"
|
color="white"
|
||||||
|
|
|
@ -66,7 +66,7 @@ const destroy = async (id) => {
|
||||||
<SectionTitleLineWithButton :icon="mdiAccountKey" title="Tethys Users" main>
|
<SectionTitleLineWithButton :icon="mdiAccountKey" title="Tethys Users" main>
|
||||||
<BaseButton
|
<BaseButton
|
||||||
v-if="can.create"
|
v-if="can.create"
|
||||||
:route-name="stardust.route('user.create')"
|
:route-name="stardust.route('settings.user.create')"
|
||||||
:icon="mdiPlus"
|
:icon="mdiPlus"
|
||||||
label="Add"
|
label="Add"
|
||||||
color="modern"
|
color="modern"
|
||||||
|
@ -80,7 +80,7 @@ const destroy = async (id) => {
|
||||||
</NotificationBar>
|
</NotificationBar>
|
||||||
<!-- <NotificationBar color="success" :icon="mdiAlertBoxOutline">{{ users.meta }}</NotificationBar> -->
|
<!-- <NotificationBar color="success" :icon="mdiAlertBoxOutline">{{ users.meta }}</NotificationBar> -->
|
||||||
<CardBox class="mb-6" has-table>
|
<CardBox class="mb-6" has-table>
|
||||||
<form @submit.prevent="form.get(stardust.route('user.index'))">
|
<form @submit.prevent="form.get(stardust.route('settings.user.index'))">
|
||||||
<div class="py-2 flex">
|
<div class="py-2 flex">
|
||||||
<div class="flex pl-4">
|
<div class="flex pl-4">
|
||||||
<input
|
<input
|
||||||
|
@ -113,7 +113,7 @@ const destroy = async (id) => {
|
||||||
<tr v-for="user in users.data" :key="user.id">
|
<tr v-for="user in users.data" :key="user.id">
|
||||||
<td data-label="Login">
|
<td data-label="Login">
|
||||||
<Link
|
<Link
|
||||||
v-bind:href="stardust.route('user.show', [user.id])"
|
v-bind:href="stardust.route('settings.user.show', [user.id])"
|
||||||
class="no-underline hover:underline text-cyan-600 dark:text-cyan-400"
|
class="no-underline hover:underline text-cyan-600 dark:text-cyan-400"
|
||||||
>
|
>
|
||||||
{{ user.login }}
|
{{ user.login }}
|
||||||
|
@ -127,7 +127,7 @@ const destroy = async (id) => {
|
||||||
<BaseButtons type="justify-start lg:justify-end" no-wrap>
|
<BaseButtons type="justify-start lg:justify-end" no-wrap>
|
||||||
<BaseButton
|
<BaseButton
|
||||||
v-if="can.edit"
|
v-if="can.edit"
|
||||||
:route-name="stardust.route('user.edit', [user.id])"
|
:route-name="stardust.route('settings.user.edit', [user.id])"
|
||||||
color="info"
|
color="info"
|
||||||
:icon="mdiSquareEditOutline"
|
:icon="mdiSquareEditOutline"
|
||||||
small
|
small
|
||||||
|
|
|
@ -30,7 +30,7 @@ defineProps({
|
||||||
<SectionMain>
|
<SectionMain>
|
||||||
<SectionTitleLineWithButton :icon="mdiAccountKey" title="View user" main>
|
<SectionTitleLineWithButton :icon="mdiAccountKey" title="View user" main>
|
||||||
<BaseButton
|
<BaseButton
|
||||||
:route-name="stardust.route('user.index')"
|
:route-name="stardust.route('settings.user.index')"
|
||||||
:icon="mdiArrowLeftBoldOutline"
|
:icon="mdiArrowLeftBoldOutline"
|
||||||
label="Back"
|
label="Back"
|
||||||
color="white"
|
color="white"
|
||||||
|
|
|
@ -57,7 +57,7 @@ const datasets = computed(() => mainService.datasets);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<LayoutAuthenticated>
|
<LayoutAuthenticated :showAsideMenu="false">
|
||||||
<Head title="Dashboard" />
|
<Head title="Dashboard" />
|
||||||
|
|
||||||
<!-- <section class="p-6" v-bind:class="containerMaxW"> -->
|
<!-- <section class="p-6" v-bind:class="containerMaxW"> -->
|
||||||
|
|
|
@ -76,7 +76,7 @@ const getRowClass = (dataset) => {
|
||||||
|
|
||||||
<!-- table -->
|
<!-- table -->
|
||||||
<CardBox class="mb-6" has-table>
|
<CardBox class="mb-6" has-table>
|
||||||
<div v-if="props.datasets && props.datasets.length > 0">
|
<div v-if="props.datasets.data.length > 0">
|
||||||
<table class="pure-table">
|
<table class="pure-table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
import { Head } from '@inertiajs/vue3';
|
import { Head } from '@inertiajs/vue3';
|
||||||
import { ref, Ref } from 'vue';
|
import { ref, Ref } from 'vue';
|
||||||
import { mdiChartTimelineVariant } from '@mdi/js';
|
import { mdiChartTimelineVariant } from '@mdi/js';
|
||||||
import LayoutGuest from '@/Layouts/LayoutGuest.vue';
|
import LayoutAuthenticated from '@/Layouts/LayoutAuthenticated.vue';
|
||||||
import SectionMain from '@/Components/SectionMain.vue';
|
import SectionMain from '@/Components/SectionMain.vue';
|
||||||
import BaseButton from '@/Components/BaseButton.vue';
|
import BaseButton from '@/Components/BaseButton.vue';
|
||||||
import SectionTitleLineWithButton from '@/Components/SectionTitleLineWithButton.vue';
|
import SectionTitleLineWithButton from '@/Components/SectionTitleLineWithButton.vue';
|
||||||
|
@ -47,7 +47,7 @@ const mapOptions: MapOptions = {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<LayoutGuest>
|
<LayoutAuthenticated :showAsideMenu="false">
|
||||||
<Head title="Map" />
|
<Head title="Map" />
|
||||||
|
|
||||||
<!-- <section class="p-6" v-bind:class="containerMaxW"> -->
|
<!-- <section class="p-6" v-bind:class="containerMaxW"> -->
|
||||||
|
@ -99,5 +99,5 @@ const mapOptions: MapOptions = {
|
||||||
</div>
|
</div>
|
||||||
</SectionMain>
|
</SectionMain>
|
||||||
<!-- </section> -->
|
<!-- </section> -->
|
||||||
</LayoutGuest>
|
</LayoutAuthenticated>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -101,7 +101,7 @@ const getRowClass = (dataset) => {
|
||||||
<tbody class="bg-white divide-y divide-gray-200">
|
<tbody class="bg-white divide-y divide-gray-200">
|
||||||
<tr v-for="dataset in props.datasets.data" :key="dataset.id" :class="getRowClass(dataset)">
|
<tr v-for="dataset in props.datasets.data" :key="dataset.id" :class="getRowClass(dataset)">
|
||||||
<td data-label="Login" class="py-4 whitespace-nowrap text-gray-700 dark:text-white">
|
<td data-label="Login" class="py-4 whitespace-nowrap text-gray-700 dark:text-white">
|
||||||
<!-- <Link v-bind:href="stardust.route('user.show', [user.id])"
|
<!-- <Link v-bind:href="stardust.route('settings.user.show', [user.id])"
|
||||||
class="no-underline hover:underline text-cyan-600 dark:text-cyan-400">
|
class="no-underline hover:underline text-cyan-600 dark:text-cyan-400">
|
||||||
{{ user.login }}
|
{{ user.login }}
|
||||||
</Link> -->
|
</Link> -->
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import {
|
import {
|
||||||
mdiMonitor,
|
// mdiMonitor,
|
||||||
mdiGithub,
|
mdiGithub,
|
||||||
mdiAccountEye,
|
mdiAccountEye,
|
||||||
mdiAccountGroup,
|
mdiAccountGroup,
|
||||||
|
@ -7,13 +7,15 @@ import {
|
||||||
mdiPublish,
|
mdiPublish,
|
||||||
mdiAccountArrowUp,
|
mdiAccountArrowUp,
|
||||||
mdiFormatListNumbered,
|
mdiFormatListNumbered,
|
||||||
mdiLock
|
mdiLock,
|
||||||
|
mdiFormatListGroup,
|
||||||
|
mdiShieldCrownOutline,
|
||||||
} from '@mdi/js';
|
} from '@mdi/js';
|
||||||
|
|
||||||
export default [
|
export default [
|
||||||
{
|
{
|
||||||
// route: 'dataset.create',
|
// route: 'dataset.create',
|
||||||
icon: mdiAccountArrowUp,
|
icon: mdiAccountEdit ,
|
||||||
label: 'Personal',
|
label: 'Personal',
|
||||||
// roles: ['submitter'],
|
// roles: ['submitter'],
|
||||||
isOpen: true,
|
isOpen: true,
|
||||||
|
@ -30,11 +32,11 @@ export default [
|
||||||
// },
|
// },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
route: 'apps.dashboard',
|
// route: 'apps.dashboard',
|
||||||
icon: mdiMonitor,
|
// icon: mdiMonitor,
|
||||||
label: 'Dashboard',
|
// label: 'Dashboard',
|
||||||
},
|
// },
|
||||||
// {
|
// {
|
||||||
// route: 'permission.index',
|
// route: 'permission.index',
|
||||||
// icon: mdiAccountKey,
|
// icon: mdiAccountKey,
|
||||||
|
@ -46,23 +48,33 @@ export default [
|
||||||
// label: 'Roles'
|
// label: 'Roles'
|
||||||
// },
|
// },
|
||||||
{
|
{
|
||||||
route: 'user.index',
|
icon: mdiShieldCrownOutline,
|
||||||
icon: mdiAccountGroup,
|
label: 'Administration',
|
||||||
label: 'Users',
|
|
||||||
roles: ['administrator'],
|
roles: ['administrator'],
|
||||||
|
isOpen: true,
|
||||||
|
permanent: true,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
route: 'settings.overview',
|
||||||
|
icon: mdiFormatListGroup,
|
||||||
|
label: 'Overview',
|
||||||
|
roles: ['administrator'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
route: 'settings.user.index',
|
||||||
|
icon: mdiAccountGroup,
|
||||||
|
label: 'Users',
|
||||||
|
roles: ['administrator'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
route: 'settings.role.index',
|
||||||
|
icon: mdiAccountEye,
|
||||||
|
label: 'Roles',
|
||||||
|
roles: ['administrator'],
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{
|
|
||||||
route: 'role.index',
|
|
||||||
icon: mdiAccountEye,
|
|
||||||
label: 'Roles',
|
|
||||||
roles: ['administrator'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
href: '/oai',
|
|
||||||
icon: mdiAccountEye,
|
|
||||||
label: 'OAI',
|
|
||||||
target: '_blank',
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
// route: 'dataset.create',
|
// route: 'dataset.create',
|
||||||
icon: mdiAccountArrowUp,
|
icon: mdiAccountArrowUp,
|
||||||
|
@ -112,4 +124,10 @@ export default [
|
||||||
label: 'Gitea',
|
label: 'Gitea',
|
||||||
target: '_blank',
|
target: '_blank',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
href: '/oai',
|
||||||
|
icon: mdiAccountEye,
|
||||||
|
label: 'OAI',
|
||||||
|
target: '_blank',
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
|
@ -3,7 +3,9 @@
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<link rel="icon" type="image/png" href="/favicon.ico">
|
{{-- <link rel="icon" type="image/png" href="/favicon.ico"> --}}
|
||||||
|
<link rel="icon" type="image/png" href="/favicon.png">
|
||||||
|
{{-- <link rel="icon" href="/apps/theming/favicon/settings?v=ad28c447"> --}}
|
||||||
|
|
||||||
@routes
|
@routes
|
||||||
@entryPointStyles('app')
|
@entryPointStyles('app')
|
||||||
|
|
|
@ -54,6 +54,10 @@ Route.group(() => {
|
||||||
return inertia.render('Dashboard');
|
return inertia.render('Dashboard');
|
||||||
}).as('dashboard');
|
}).as('dashboard');
|
||||||
|
|
||||||
|
Route.get('/map', async ({ inertia }) => {
|
||||||
|
return inertia.render('Map');
|
||||||
|
}).as('map');
|
||||||
|
|
||||||
Route.get('/', async ({ inertia }) => {
|
Route.get('/', async ({ inertia }) => {
|
||||||
const users = await User.query().orderBy('login');
|
const users = await User.query().orderBy('login');
|
||||||
return inertia.render('App', {
|
return inertia.render('App', {
|
||||||
|
@ -85,9 +89,7 @@ Route.group(() => {
|
||||||
.as('apps')
|
.as('apps')
|
||||||
.middleware('auth');
|
.middleware('auth');
|
||||||
|
|
||||||
Route.get('/map', async ({ inertia }) => {
|
|
||||||
return inertia.render('Map');
|
|
||||||
}).as('map');
|
|
||||||
|
|
||||||
// Route.on("/login").render("signin");
|
// Route.on("/login").render("signin");
|
||||||
Route.get('/app/login', async ({ inertia }) => {
|
Route.get('/app/login', async ({ inertia }) => {
|
||||||
|
@ -104,7 +106,8 @@ Route.post('/signout', 'Auth/AuthController.logout').as('logout');
|
||||||
Route.group(() => {
|
Route.group(() => {
|
||||||
Route.get('/settings', async ({ inertia }) => {
|
Route.get('/settings', async ({ inertia }) => {
|
||||||
return inertia.render('Admin/Settings');
|
return inertia.render('Admin/Settings');
|
||||||
}).as('settings');
|
|
||||||
|
}).as('overview');
|
||||||
|
|
||||||
Route.get('/user', 'UsersController.index').as('user.index').middleware(['can:user-list']);
|
Route.get('/user', 'UsersController.index').as('user.index').middleware(['can:user-list']);
|
||||||
Route.get('/user/create', 'UsersController.create').as('user.create').middleware(['can:user-create']);
|
Route.get('/user/create', 'UsersController.create').as('user.create').middleware(['can:user-create']);
|
||||||
|
@ -137,6 +140,7 @@ Route.group(() => {
|
||||||
})
|
})
|
||||||
.namespace('App/Controllers/Http/Admin')
|
.namespace('App/Controllers/Http/Admin')
|
||||||
.prefix('admin')
|
.prefix('admin')
|
||||||
|
.as('settings')
|
||||||
// .middleware(['auth', 'can:dataset-list,dataset-publish']);
|
// .middleware(['auth', 'can:dataset-list,dataset-publish']);
|
||||||
.middleware(['auth', 'is:administrator,moderator']);
|
.middleware(['auth', 'is:administrator,moderator']);
|
||||||
|
|
||||||
|
@ -189,7 +193,7 @@ Route.group(() => {
|
||||||
.middleware(['auth', 'can:dataset-delete']);
|
.middleware(['auth', 'can:dataset-delete']);
|
||||||
|
|
||||||
Route.get('/person', 'PersonController.index').as('person.index').middleware(['auth']);
|
Route.get('/person', 'PersonController.index').as('person.index').middleware(['auth']);
|
||||||
// Route.get('/user/:id/edit', 'UsersController.edit').as('user.edit').where('id', Route.matchers.number());
|
// Route.get('/user/:id/edit', 'UsersController.edit').as('settings.user.edit').where('id', Route.matchers.number());
|
||||||
// Route.put('/user/:id/update', 'UsersController.update').as('user.update').where('id', Route.matchers.number());
|
// Route.put('/user/:id/update', 'UsersController.update').as('user.update').where('id', Route.matchers.number());
|
||||||
// Route.delete('/user/:id', 'UsersController.destroy').as('user.destroy').where('id', Route.matchers.number());
|
// Route.delete('/user/:id', 'UsersController.destroy').as('user.destroy').where('id', Route.matchers.number());
|
||||||
// Route.resource('user', 'DatasetController');
|
// Route.resource('user', 'DatasetController');
|
||||||
|
|
|
@ -18,6 +18,8 @@ Route.group(() => {
|
||||||
Route.get('/years', 'HomeController.findYears');
|
Route.get('/years', 'HomeController.findYears');
|
||||||
|
|
||||||
Route.get('/download/:id', 'FileController.findOne').as('file.findOne');
|
Route.get('/download/:id', 'FileController.findOne').as('file.findOne');
|
||||||
|
|
||||||
|
Route.get('/avatar/:name/:background?/:textColor?/:size?', 'AvatarController.generateAvatar')
|
||||||
});
|
});
|
||||||
// .middleware("auth:api");
|
// .middleware("auth:api");
|
||||||
})
|
})
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 119 KiB |
Loading…
Reference in New Issue
Block a user