Compare commits
10 Commits
5371f784fb
...
cd7784e04f
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cd7784e04f | ||
|
|
3a85d2c196 | ||
|
|
428ab06fcc | ||
|
|
3534b9fb8d | ||
|
|
7f33499459 | ||
|
|
fdb7eae847 | ||
|
|
360fa51607 | ||
|
|
bda4b0489b | ||
|
|
decf693f4f | ||
|
|
39a28cbd14 |
@@ -1,32 +1,82 @@
|
||||
import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
|
||||
import User from 'App/Models/User'
|
||||
import Database from '@ioc:Adonis/Lucid/Database'
|
||||
import { schema, rules } from '@ioc:Adonis/Core/Validator'
|
||||
|
||||
export default class UsersController {
|
||||
public async index({ inertia, bouncer }: HttpContextContract) {
|
||||
|
||||
await bouncer.with('UserPolicy').authorize('index')
|
||||
|
||||
const users = await Database
|
||||
|
||||
const users = await Database
|
||||
.from('users')
|
||||
.select('id', 'username', 'is_admin')
|
||||
|
||||
return inertia.render('Users/Index', { users })
|
||||
}
|
||||
|
||||
public async create({ auth, inertia }: HttpContextContract) {
|
||||
if(auth.user?.isAdmin) {
|
||||
inertia.render('Users/Create')
|
||||
} else {
|
||||
|
||||
public async create({ inertia, bouncer }: HttpContextContract) {
|
||||
await bouncer
|
||||
.with('UserPolicy')
|
||||
.authorize('create')
|
||||
|
||||
return inertia.render('Users/Create')
|
||||
}
|
||||
|
||||
public async store({ bouncer, inertia, request }: HttpContextContract) {
|
||||
await bouncer
|
||||
.with('UserPolicy')
|
||||
.authorize('store')
|
||||
|
||||
const newUserSchema = schema.create({
|
||||
username: schema.string(
|
||||
{ trim: true },
|
||||
[
|
||||
rules.unique({ table: 'users', column: 'username' })
|
||||
]
|
||||
),
|
||||
is_admin: schema.boolean(),
|
||||
password: schema.string([
|
||||
rules.confirmed("passwordRepeat")
|
||||
]),
|
||||
password_repeat: schema.string(),
|
||||
})
|
||||
console.log(request.body())
|
||||
|
||||
const payload = await request.validate({ schema: newUserSchema })
|
||||
console.log(payload)
|
||||
|
||||
if(request.qs().validate) {
|
||||
console.log("darf ich jetzt einen user erstellen?")
|
||||
await User.create({
|
||||
username: payload.username,
|
||||
isAdmin: payload.is_admin,
|
||||
password: payload.password,
|
||||
})
|
||||
|
||||
return inertia.render('Users')
|
||||
}
|
||||
}
|
||||
|
||||
public async store({}: HttpContextContract) {}
|
||||
public async show({ bouncer, params, inertia }: HttpContextContract) {
|
||||
const queriedUser: User = await User.findByOrFail('id', params.id)
|
||||
|
||||
await bouncer
|
||||
.with('UserPolicy')
|
||||
.authorize('show', queriedUser)
|
||||
|
||||
public async show({}: HttpContextContract) {}
|
||||
return inertia.render('Users/Show', { user: queriedUser })
|
||||
}
|
||||
|
||||
public async edit({}: HttpContextContract) {}
|
||||
public async edit({ bouncer, params, inertia }: HttpContextContract) {
|
||||
const queriedUser: User = await User.findByOrFail('id', params.id)
|
||||
|
||||
await bouncer
|
||||
.with("UserPolicy")
|
||||
.authorize('edit', queriedUser)
|
||||
|
||||
return inertia.render("Users/Edit", { user: queriedUser })
|
||||
}
|
||||
|
||||
public async update({}: HttpContextContract) {}
|
||||
|
||||
|
||||
@@ -5,10 +5,18 @@ export default class UserPolicy extends BasePolicy {
|
||||
public async index(user: User) {
|
||||
return user.isAdmin
|
||||
}
|
||||
|
||||
public async create(user: User) {
|
||||
return user.isAdmin
|
||||
}
|
||||
|
||||
public async show(user: User, query: User) {
|
||||
return user.isAdmin || user.id === query.id
|
||||
}
|
||||
|
||||
public async edit(user: User, query: User) {
|
||||
return user.isAdmin || user.id === query.id
|
||||
}
|
||||
|
||||
public async update(user: User, query: User) {
|
||||
return user.isAdmin || user.id === query.id
|
||||
|
||||
3
components.d.ts
vendored
3
components.d.ts
vendored
@@ -8,10 +8,13 @@ export {}
|
||||
declare module 'vue' {
|
||||
export interface GlobalComponents {
|
||||
NButton: typeof import('naive-ui')['NButton']
|
||||
NCheckbox: typeof import('naive-ui')['NCheckbox']
|
||||
NDataTable: typeof import('naive-ui')['NDataTable']
|
||||
NForm: typeof import('naive-ui')['NForm']
|
||||
NFormItem: typeof import('naive-ui')['NFormItem']
|
||||
NInput: typeof import('naive-ui')['NInput']
|
||||
NMenu: typeof import('naive-ui')['NMenu']
|
||||
NMessageProvider: typeof import('naive-ui')['NMessageProvider']
|
||||
NText: typeof import('naive-ui')['NText']
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@ import { InertiaConfig } from '@ioc:EidelLev/Inertia';
|
||||
export const inertia: InertiaConfig = {
|
||||
view: 'app',
|
||||
ssr: {
|
||||
enabled: true,
|
||||
autoreload: process.env.NODE_ENV === 'development',
|
||||
enabled: false,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"entrypoints": {
|
||||
"ssr": {
|
||||
"js": [
|
||||
"auto/ssr.js"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"ssr/ssr.js": "autossr.js"
|
||||
}
|
||||
1701
inertia/ssr/ssr.js
1701
inertia/ssr/ssr.js
File diff suppressed because one or more lines are too long
15713
package-lock.json
generated
15713
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -44,6 +44,7 @@
|
||||
"@japa/preset-adonis": "^1.2.0",
|
||||
"@japa/runner": "^2.5.1",
|
||||
"@symfony/webpack-encore": "^4.1.1",
|
||||
"@types/node": "^20.4.1",
|
||||
"@types/proxy-addr": "^2.0.0",
|
||||
"@types/source-map-support": "^0.5.6",
|
||||
"@vicons/material": "^0.12.0",
|
||||
@@ -77,15 +78,11 @@
|
||||
"@eidellev/inertia-adonisjs": "^8.0.1",
|
||||
"@inertiajs/vue3": "^1.0.9",
|
||||
"@vue/compiler-sfc": "^3.3.4",
|
||||
"@vue/server-renderer": "^3.3.4",
|
||||
"@vue/tsconfig": "^0.1.3",
|
||||
"luxon": "^3.3.0",
|
||||
"proxy-addr": "^2.0.7",
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"source-map-support": "^0.5.21",
|
||||
"sqlite3": "^5.1.6",
|
||||
"ts-loader": "^9.4.4",
|
||||
"vue": "^3.3.4",
|
||||
"webpack-node-externals": "^3.0.0"
|
||||
"vue": "^3.3.4"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<LoginLayout>
|
||||
<LoginLayout class="w-3/5 h-3/4">
|
||||
<MainNav />
|
||||
<slot></slot>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import LoginLayout from '@/layouts/LoginLayout'
|
||||
import MainNav from '@/components/MainNav'
|
||||
import LoginLayout from '@/layouts/LoginLayout.vue'
|
||||
import MainNav from '@/components/MainNav.vue'
|
||||
|
||||
</script>
|
||||
@@ -1,10 +1,13 @@
|
||||
<template>
|
||||
<main class="bg-slate-100 flex justify-center h-screen">
|
||||
<div class="m-auto bg-white p-4 border rounded space-y-4 drop-shadow">
|
||||
<div class="m-auto bg-white p-4 border rounded drop-shadow" :class="class">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</main>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
<script setup>
|
||||
|
||||
defineProps(['class'])
|
||||
|
||||
</script>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import '../css/app.css'
|
||||
import { createApp, h } from "vue";
|
||||
import { createInertiaApp, Link } from "@inertiajs/vue3";
|
||||
import '../css/app.css'
|
||||
|
||||
createInertiaApp({
|
||||
resolve: (name) => require(`./pages/${name}`),
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
<script setup>
|
||||
import { useMessage } from 'naive-ui'
|
||||
import { onUpdated, onMounted } from 'vue'
|
||||
|
||||
@@ -15,13 +15,13 @@
|
||||
displayNewMessages(props.messages)
|
||||
})
|
||||
|
||||
function displayNewMessages(messages: any) {
|
||||
function displayNewMessages(messages) {
|
||||
|
||||
let output: Array<Object> = []
|
||||
let output = []
|
||||
|
||||
output = flattenObject(removeValidationErrors(messages))
|
||||
|
||||
output?.forEach((item: any) => {
|
||||
output?.forEach((item) => {
|
||||
for (let key in item) {
|
||||
switch (key){
|
||||
case 'error':
|
||||
@@ -52,24 +52,24 @@
|
||||
})
|
||||
}
|
||||
|
||||
function removeValidationErrors(input: any) {
|
||||
function removeValidationErrors(input) {
|
||||
|
||||
if(input === null || !input.hasOwnProperty("errors")) return input
|
||||
|
||||
const { errors: _, ...output } = (input as any)
|
||||
const { errors: _, ...output } = (input)
|
||||
return output
|
||||
}
|
||||
|
||||
function flattenObject(input: Object) {
|
||||
function flattenObject(input) {
|
||||
if (input === null) return input
|
||||
|
||||
return Object.values(input).map((value) => Object.entries(value)).flat().reduce((acc: Array<Object>, [key, value]) => {
|
||||
return Object.values(input).map((value) => Object.entries(value)).flat().reduce((acc, [key, value]) => {
|
||||
acc.push({[key]: value});
|
||||
return acc;
|
||||
}, []);
|
||||
}
|
||||
|
||||
function translateError(errorMsg: string) {
|
||||
function translateError(errorMsg) {
|
||||
switch(errorMsg.split(":")[0]) {
|
||||
case 'E_INVALID_AUTH_PASSWORD':
|
||||
return "Falsches Passwort eingegeben."
|
||||
|
||||
@@ -1,41 +1,46 @@
|
||||
<template>
|
||||
<n-menu
|
||||
<div class="flex justify-center">
|
||||
<n-menu
|
||||
v-model:value="activeKey"
|
||||
mode="horizontal"
|
||||
:options="menuOptions"
|
||||
class="-mx-4"
|
||||
/>
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { MenuOption } from 'naive-ui'
|
||||
<script setup>
|
||||
import { renderIcon } from '@/util'
|
||||
import { NIcon } from 'naive-ui'
|
||||
import { Link, usePage } from '@inertiajs/vue3'
|
||||
import { h, ref } from 'vue';
|
||||
import { NIcon } from 'naive-ui'
|
||||
import {
|
||||
GroupsFilled as Users,
|
||||
EventNoteFilled as Events,
|
||||
LogOutFilled as Logout
|
||||
LogOutFilled as Logout,
|
||||
SettingsRound as Settings,
|
||||
PersonRound as Profile,
|
||||
} from '@vicons/material'
|
||||
|
||||
const isAdmin: boolean = (usePage().props.isAdmin as boolean)
|
||||
const activeKey = ref<string>((usePage().props.request as any)?.url)
|
||||
const activeKey= ref(usePage().props.request?.url)
|
||||
const user = usePage().props.user
|
||||
|
||||
const menuOptions = []
|
||||
|
||||
const menuOptions: MenuOption[] = []
|
||||
menuOptions.push({
|
||||
label: () =>
|
||||
h(
|
||||
Link, {
|
||||
href: "/events",
|
||||
methode: "get"
|
||||
method: "get"
|
||||
},
|
||||
() => "Veranstaltungen"
|
||||
),
|
||||
key: '/events',
|
||||
icon: renderIcon(Events)
|
||||
icon: () => { return renderIcon(Events) }
|
||||
})
|
||||
|
||||
if(isAdmin) menuOptions.push({
|
||||
if(user.is_admin) menuOptions.push({
|
||||
label: () =>
|
||||
h(
|
||||
Link, {
|
||||
@@ -45,12 +50,28 @@
|
||||
() => "Benutzer"
|
||||
),
|
||||
key: '/users',
|
||||
icon: renderIcon(Users)
|
||||
icon: () => { return renderIcon(Users) }
|
||||
})
|
||||
|
||||
menuOptions.push({
|
||||
label: () =>
|
||||
h(
|
||||
label: "Einstellungen",
|
||||
key: "einstellungen",
|
||||
icon: () => { return renderIcon(Settings) },
|
||||
children: [{
|
||||
label: () => h(
|
||||
Link, {
|
||||
href: "/users/"+user.id,
|
||||
method: "get",
|
||||
as: "button"
|
||||
},
|
||||
() => "Mein Profil"
|
||||
),
|
||||
key: 'profile',
|
||||
icon: () => { return renderIcon(Profile) }
|
||||
|
||||
},
|
||||
{
|
||||
label: () => h(
|
||||
Link, {
|
||||
href: "/logout",
|
||||
method: "post",
|
||||
@@ -59,14 +80,15 @@
|
||||
() => "Abmelden"
|
||||
),
|
||||
key: '/logout',
|
||||
icon: renderIcon(Logout)
|
||||
icon: () => { return renderIcon(Logout) }
|
||||
}]
|
||||
})
|
||||
|
||||
|
||||
|
||||
function renderIcon(icon: any) {
|
||||
/*function renderIcon(icon) {
|
||||
return () => h(NIcon, null, { default: () => h(icon) })
|
||||
|
||||
}
|
||||
}*/
|
||||
|
||||
</script>
|
||||
110
resources/js/components/Users/UserForm.vue
Normal file
110
resources/js/components/Users/UserForm.vue
Normal file
@@ -0,0 +1,110 @@
|
||||
<template>
|
||||
<n-form
|
||||
:model="userModel"
|
||||
:rules="rules"
|
||||
label-placement="left"
|
||||
require-mark-placement="right-hanging"
|
||||
label-width="auto"
|
||||
@submit.prevent="$emit('submit')"
|
||||
>
|
||||
<n-form-item label="Benutzername" path="username">
|
||||
<n-input
|
||||
v-model:value="userModel.username"
|
||||
/>
|
||||
</n-form-item>
|
||||
|
||||
<n-form-item label="Ist Admin?" path="is_admin">
|
||||
<n-checkbox v-model:checked="userModel.is_admin" />
|
||||
</n-form-item>
|
||||
|
||||
<n-form-item label="Passwort" path="password">
|
||||
<n-input
|
||||
type="password"
|
||||
show-password-on="mouseclick"
|
||||
placeholder="Passwort"
|
||||
v-model:value="userModel.password"
|
||||
@input="handlePasswordInput"
|
||||
/>
|
||||
</n-form-item>
|
||||
|
||||
<n-form-item label="Password wiederholen" path="password_repeat" ref="passwordRepeatRef">
|
||||
<n-input
|
||||
type="password"
|
||||
:disabled="!userModel.password"
|
||||
show-password-on="mouseclick"
|
||||
placeholder="Passwort wiederholen"
|
||||
v-model:value="userModel.password_repeat"
|
||||
/>
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
<n-button
|
||||
@click="validate"
|
||||
>
|
||||
validate
|
||||
</n-button>
|
||||
<div>
|
||||
{{ userModel }}
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { router } from '@inertiajs/vue3';
|
||||
import { reactive, ref } from 'vue'
|
||||
|
||||
const props = defineProps(['userModel'])
|
||||
const emit = defineEmits(['validateUsername'])
|
||||
|
||||
const passwordRepeatRef = ref(null)
|
||||
|
||||
const rules = {
|
||||
username: [{
|
||||
required: true,
|
||||
message: "Benutzername ist erforderlich",
|
||||
}],
|
||||
password: [{
|
||||
required: true,
|
||||
message: "Passwort ist erforderlich",
|
||||
}],
|
||||
password_repeat: [{
|
||||
required: true,
|
||||
message: "Wiederholtes Passwort ist erforderlich",
|
||||
trigger: ["input", "blur"],
|
||||
},{
|
||||
validator: passwordStartsWith,
|
||||
message: "Passwörter stimmen nicht überein",
|
||||
trigger: "input",
|
||||
},{
|
||||
validator: passwordSame,
|
||||
message: "Passwörter stimmen nicht überein",
|
||||
trigger: ["blur", "password-input"],
|
||||
}]
|
||||
}
|
||||
|
||||
function passwordStartsWith(rule, value) {
|
||||
return !!props.userModel.password && props.userModel.password.startsWith(value) && props.userModel.password.length >= value.length;
|
||||
}
|
||||
|
||||
function passwordSame(rule, value) {
|
||||
return value === props.userModel.password;
|
||||
}
|
||||
|
||||
function usernameUnique(rule, value) {
|
||||
}
|
||||
|
||||
function validate() {
|
||||
console.log("vue validate")
|
||||
|
||||
router.post('/users?validate=true', {
|
||||
username: props.userModel.username,
|
||||
is_admin: props.userModel.is_admin,
|
||||
password: props.userModel.password,
|
||||
password_repeat: props.userModel.password_repeat,
|
||||
} )
|
||||
}
|
||||
|
||||
function handlePasswordInput() {
|
||||
if(props.userModel.password_repeat) {
|
||||
passwordRepeatRef.value?.validate({ trigger: "password-input" })
|
||||
}
|
||||
}
|
||||
</script>
|
||||
29
resources/js/components/Users/UserNav.vue
Normal file
29
resources/js/components/Users/UserNav.vue
Normal file
@@ -0,0 +1,29 @@
|
||||
<template>
|
||||
<div class="flex justify-between mb-4">
|
||||
<n-button
|
||||
:renderIcon="() => { return renderIcon(Back)}"
|
||||
@click="$emit('clickBack')"
|
||||
>
|
||||
Zurück
|
||||
</n-button>
|
||||
|
||||
<n-button
|
||||
secondary
|
||||
type="primary"
|
||||
:renderIcon="() => { return renderIcon(Save) }"
|
||||
@click="$emit('clickSave')"
|
||||
>
|
||||
Speichern
|
||||
</n-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { renderIcon } from '@/util'
|
||||
import {
|
||||
ArrowBackRound as Back,
|
||||
SaveRound as Save,
|
||||
} from '@vicons/material'
|
||||
|
||||
|
||||
</script>
|
||||
@@ -9,7 +9,7 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
<script setup>
|
||||
import BELayout from '@/layouts/BELayout.vue'
|
||||
import FlashMessages from '@/components/FlashMessages.vue'
|
||||
|
||||
@@ -17,9 +17,7 @@ defineOptions({
|
||||
layout: BELayout
|
||||
})
|
||||
|
||||
const props = defineProps({
|
||||
flashMessages: Object
|
||||
})
|
||||
const props = defineProps(['flashMessages'])
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
@@ -12,15 +12,12 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import FlashMessages from '@/components/FlashMessages.vue'
|
||||
|
||||
const props = defineProps({
|
||||
test: String,
|
||||
flashMessages: Object
|
||||
})
|
||||
const props = defineProps(['test', 'flashMessages'])
|
||||
|
||||
const helloWorld = ref<String>("helloWorld")
|
||||
const helloWorld = ref("helloWorld")
|
||||
|
||||
</script>
|
||||
@@ -37,7 +37,6 @@
|
||||
|
||||
<div class="flex justify-center">
|
||||
<n-button
|
||||
class="bg-[#18A058]"
|
||||
type="success"
|
||||
@click="onClickLogin"
|
||||
:disabled="!form.password || !form.username"
|
||||
@@ -46,10 +45,9 @@
|
||||
</n-form>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import { router } from '@inertiajs/vue3'
|
||||
import type { FormInst } from 'naive-ui'
|
||||
import LoginLayout from '@/layouts/LoginLayout.vue'
|
||||
import FlashMessages from '@/components/FlashMessages.vue'
|
||||
|
||||
@@ -61,7 +59,7 @@
|
||||
password: '',
|
||||
})
|
||||
|
||||
const formRef = ref<FormInst | null>(null)
|
||||
const formRef = ref(null)
|
||||
|
||||
const rules = ref({
|
||||
username: {
|
||||
|
||||
@@ -1,3 +1,33 @@
|
||||
<template>
|
||||
<UserNav
|
||||
@clickBack="() => { router.get('/users') }"
|
||||
/>
|
||||
|
||||
<UserForm
|
||||
:userModel="form"
|
||||
|
||||
/>
|
||||
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import BELayout from '@/layouts/BELayout.vue'
|
||||
import UserForm from '@/components/Users/UserForm.vue'
|
||||
import UserNav from '@/components/Users/UserNav.vue'
|
||||
|
||||
import { router, useForm } from '@inertiajs/vue3'
|
||||
import { renderIcon } from '@/util'
|
||||
import {
|
||||
ArrowBackRound as Back,
|
||||
SaveRound as Save
|
||||
} from '@vicons/material'
|
||||
|
||||
defineOptions({ layout: BELayout })
|
||||
|
||||
const form = useForm({
|
||||
username: null,
|
||||
password: null,
|
||||
is_admin: false,
|
||||
password_repeat: null,
|
||||
})
|
||||
</script>
|
||||
68
resources/js/pages/Users/Edit.vue
Normal file
68
resources/js/pages/Users/Edit.vue
Normal file
@@ -0,0 +1,68 @@
|
||||
<template>
|
||||
<UserNav
|
||||
@clickBack="() => { router.get('/users') }"
|
||||
/>
|
||||
|
||||
<n-form
|
||||
:model="userModel"
|
||||
label-placement="left"
|
||||
require-mark-placement="right-hanging"
|
||||
label-width="auto"
|
||||
>
|
||||
<n-form-item label="ID" path="id">
|
||||
<n-text>{{ userModel.id }}</n-text>
|
||||
</n-form-item>
|
||||
<n-form-item label="Benutzername" path="username">
|
||||
<n-input
|
||||
class="align-middle"
|
||||
v-model:value="userModel.username"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item label="Ist Admin?" path="is_admin">
|
||||
<n-checkbox v-model:checked="userModel.is_admin"/>
|
||||
</n-form-item>
|
||||
<n-form-item label="Passwort" path="password">
|
||||
<n-input
|
||||
type="password"
|
||||
show-password-on="mouseclick"
|
||||
placeholder="Passwort"
|
||||
v-model:value="userModel.password"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item label="Passwort wiederholen" path="password_repeat">
|
||||
<n-input
|
||||
type="password"
|
||||
show-password-on="mouseclick"
|
||||
placeholder="Passwort wiederholen"
|
||||
v-model:value="userModel.password_repeat"
|
||||
/>
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
|
||||
{{ userModel }}
|
||||
|
||||
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
|
||||
import BELayout from '@/layouts/BELayout.vue'
|
||||
import UserNav from '@/components/Users/UserNav.vue'
|
||||
|
||||
import { router } from '@inertiajs/vue3'
|
||||
import { renderIcon } from '@/util'
|
||||
import { h, reactive } from 'vue'
|
||||
import { NIcon } from 'naive-ui'
|
||||
import {
|
||||
ArrowBackFilled as Back
|
||||
} from '@vicons/material'
|
||||
|
||||
defineOptions({
|
||||
layout: BELayout
|
||||
})
|
||||
|
||||
const props = defineProps(['user'])
|
||||
|
||||
const userModel = reactive(props.user)
|
||||
|
||||
</script>
|
||||
@@ -3,25 +3,99 @@
|
||||
<FlashMessages
|
||||
:messages="props.flashMessages"
|
||||
/>
|
||||
</n-message-provider>
|
||||
<div>
|
||||
Bin in Users
|
||||
</div>
|
||||
<div>
|
||||
{{ users }}
|
||||
</div>
|
||||
</n-message-provider>
|
||||
<div class="flex flex-row-reverse mb-2">
|
||||
<n-button
|
||||
class="items-end"
|
||||
secondary
|
||||
type="primary"
|
||||
:renderIcon="() => { return renderIcon(Plus) }"
|
||||
:onClick="() => { router.get('/users/create') }"
|
||||
>
|
||||
Neuer Benutzer</n-button>
|
||||
</div>
|
||||
<n-data-table
|
||||
:columns="columns"
|
||||
:data="users"
|
||||
row-class-name="group"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
<script setup>
|
||||
|
||||
import { h } from 'vue'
|
||||
import BELayout from '@/layouts/BELayout.vue'
|
||||
import FlashMessages from '@/components/FlashMessages.vue'
|
||||
import { NIcon, NButton } from 'naive-ui'
|
||||
import { router } from '@inertiajs/vue3'
|
||||
|
||||
import {
|
||||
AdminPanelSettingsFilled as Admin,
|
||||
EditRound as Edit,
|
||||
DeleteRound as Delete,
|
||||
PlusRound as Plus,
|
||||
} from '@vicons/material'
|
||||
|
||||
defineOptions({ layout: BELayout })
|
||||
|
||||
const props = defineProps({
|
||||
users: Object,
|
||||
flashMessages: Object
|
||||
})
|
||||
const props = defineProps(['users', 'flashMessages'])
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: "Admin",
|
||||
key: "is_admin",
|
||||
align: "center",
|
||||
render (row) {
|
||||
if(row.is_admin) {
|
||||
return renderIcon(Admin, "align-middle")
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "Benutzername",
|
||||
key: "username",
|
||||
},
|
||||
{
|
||||
title: "Aktionen",
|
||||
key: "actions",
|
||||
className: "space-x-4",
|
||||
render(row) {
|
||||
let arr = []
|
||||
arr[0] = h(
|
||||
NButton,
|
||||
{
|
||||
class: "invisible group-hover:visible align-middle",
|
||||
circle: true,
|
||||
onClick: () => { clickEdit(row.id) },
|
||||
renderIcon: () => { return renderIcon(Edit) },
|
||||
},
|
||||
)
|
||||
arr[1] = h(
|
||||
NButton,
|
||||
{
|
||||
class: "invisible group-hover:visible align-middle",
|
||||
secondary: true,
|
||||
circle: true,
|
||||
type: "error",
|
||||
onClick: () => { clickDelete(row.id) },
|
||||
renderIcon: () => { return renderIcon(Delete) },
|
||||
},
|
||||
)
|
||||
return arr
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
function clickEdit(id){
|
||||
router.get('users/'+id+'/edit')
|
||||
}
|
||||
|
||||
function clickDelete(id){
|
||||
console.log("Delete clicked: "+id)
|
||||
}
|
||||
|
||||
function renderIcon(icon, className = "") {
|
||||
return h(NIcon, { component: icon, class: className, size: 20 })
|
||||
}
|
||||
|
||||
</script>
|
||||
11
resources/js/pages/Users/Show.vue
Normal file
11
resources/js/pages/Users/Show.vue
Normal file
@@ -0,0 +1,11 @@
|
||||
<template>
|
||||
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import BELayout from '@/layouts/BELayout.vue'
|
||||
|
||||
defineOptions({ layout: BELayout })
|
||||
|
||||
|
||||
</script>
|
||||
@@ -1,16 +0,0 @@
|
||||
import { createSSRApp, h } from 'vue';
|
||||
import { renderToString } from '@vue/server-renderer';
|
||||
import { createInertiaApp } from '@inertiajs/vue3';
|
||||
|
||||
export default function render(page) {
|
||||
return createInertiaApp({
|
||||
page,
|
||||
render: renderToString,
|
||||
resolve: (name) => require(`./pages/${name}`),
|
||||
setup({ app, props, plugin }) {
|
||||
return createSSRApp({
|
||||
render: () => h(app, props),
|
||||
}).use(plugin);
|
||||
},
|
||||
});
|
||||
}
|
||||
6
resources/js/util/index.js
Normal file
6
resources/js/util/index.js
Normal file
@@ -0,0 +1,6 @@
|
||||
import { h } from "vue"
|
||||
import { NIcon } from 'naive-ui'
|
||||
|
||||
export function renderIcon(icon, className = "", size = 20) {
|
||||
return h(NIcon, { component: icon, class: className, size: size })
|
||||
}
|
||||
@@ -9,7 +9,7 @@
|
||||
@entryPointScripts('app')
|
||||
|
||||
<title>enzos-events</title>
|
||||
@inertiaHead
|
||||
<meta name="naive-ui-style" />
|
||||
</head>
|
||||
<body>
|
||||
@inertia
|
||||
|
||||
@@ -8,11 +8,11 @@
|
||||
|
|
||||
*/
|
||||
|
||||
import Inertia from '@ioc:EidelLev/Inertia';
|
||||
import Inertia from '@ioc:EidelLev/Inertia'
|
||||
|
||||
Inertia.share({
|
||||
errors: ({ session }) => session.flashMessages.get('errors'),
|
||||
request: ({ request }) => request,
|
||||
isAdmin: ({ auth }) => auth.user?.isAdmin,
|
||||
user: ({ auth }) => auth.user,
|
||||
flashMessages: ({ session }) => session.flashMessages.all(),
|
||||
}).version(() => Inertia.manifestFile('public/assets/manifest.json'));
|
||||
}).version(() => Inertia.manifestFile('public/assets/manifest.json'))
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
],
|
||||
"compilerOptions": {
|
||||
"outDir": "build",
|
||||
"allowJs": true,
|
||||
"rootDir": "./",
|
||||
"sourceMap": true,
|
||||
"paths": {
|
||||
@@ -35,7 +36,8 @@
|
||||
"@eidellev/inertia-adonisjs",
|
||||
"@adonisjs/lucid",
|
||||
"@adonisjs/auth",
|
||||
"@adonisjs/bouncer"
|
||||
"@adonisjs/bouncer",
|
||||
"node"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
{
|
||||
// tsconfig.vue.json
|
||||
|
||||
"extends": "@vue/tsconfig/tsconfig.json",
|
||||
"include": [
|
||||
"./resources/js/**/*"
|
||||
],
|
||||
"compilerOptions": {
|
||||
"paths": {
|
||||
"@/*": ["./resources/js/"]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
const { join } = require('path')
|
||||
const { join, resolve } = require('path')
|
||||
const Encore = require('@symfony/webpack-encore')
|
||||
const Components = require('unplugin-vue-components/webpack')
|
||||
const { NaiveUiResolver } = require('unplugin-vue-components/resolvers')
|
||||
@@ -47,7 +47,7 @@ Encore.setPublicPath('/assets')
|
||||
| entrypoints.
|
||||
|
|
||||
*/
|
||||
Encore.addEntry('app', './resources/js/app.ts')
|
||||
Encore.addEntry('app', './resources/js/app.js')
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
@@ -187,10 +187,8 @@ Encore.enableVueLoader(() => {}, {
|
||||
version: 3,
|
||||
runtimeCompilerBuild: false,
|
||||
useJsx: false
|
||||
}).enableTypeScriptLoader(config => {
|
||||
config.configFile = 'tsconfig.vue.json'
|
||||
}).addAliases({
|
||||
'@': join(__dirname, 'resources/js')
|
||||
'@': join(__dirname, 'resources/js'),
|
||||
}).configureDefinePlugin(options => {
|
||||
options['__VUE_OPTIONS_API__'] = true
|
||||
options['__VUE_PROD_DEVTOOLS__'] = false
|
||||
|
||||
@@ -1,208 +0,0 @@
|
||||
const { join } = require('path')
|
||||
const Encore = require('@symfony/webpack-encore')
|
||||
const Components = require('unplugin-vue-components/webpack')
|
||||
const { NaiveUiResolver } = require('unplugin-vue-components/resolvers')
|
||||
const nodeExternals = require('webpack-node-externals')
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Encore runtime environment
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
if (!Encore.isRuntimeEnvironmentConfigured()) {
|
||||
Encore.configureRuntimeEnvironment(process.env.NODE_ENV || 'dev')
|
||||
}
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Output path
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The output path for writing the compiled files. It should always
|
||||
| be inside the public directory, so that AdonisJS can serve it.
|
||||
|
|
||||
*/
|
||||
Encore.setOutputPath('./inertia/ssr')
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Public URI
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The public URI to access the static files. It should always be
|
||||
| relative from the "public" directory.
|
||||
|
|
||||
*/
|
||||
Encore.setPublicPath('/ssr')
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Entrypoints
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Entrypoints are script files that boots your frontend application. Ideally
|
||||
| a single entrypoint is used by majority of applications. However, feel
|
||||
| free to add more (if required).
|
||||
|
|
||||
| Also, make sure to read the docs on "Assets bundler" to learn more about
|
||||
| entrypoints.
|
||||
|
|
||||
*/
|
||||
Encore.addEntry('ssr', './resources/js/ssr.js')
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Isolated entrypoints
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Treat each entry point and its dependencies as its own isolated module.
|
||||
|
|
||||
*/
|
||||
Encore.disableSingleRuntimeChunk()
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Cleanup output folder
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| It is always nice to cleanup the build output before creating a build. It
|
||||
| will ensure that all unused files from the previous build are removed.
|
||||
|
|
||||
*/
|
||||
Encore.cleanupOutputBeforeBuild()
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Assets versioning
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Enable assets versioning to leverage lifetime browser and CDN cache
|
||||
|
|
||||
*/
|
||||
Encore.enableVersioning(Encore.isProduction())
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Configure dev server
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here we configure the dev server to enable live reloading for edge templates.
|
||||
| Remember edge templates are not processed by Webpack and hence we need
|
||||
| to watch them explicitly and livereload the browser.
|
||||
|
|
||||
*/
|
||||
Encore.configureDevServerOptions((options) => {
|
||||
/**
|
||||
* Normalize "options.static" property to an array
|
||||
*/
|
||||
if (!options.static) {
|
||||
options.static = []
|
||||
} else if (!Array.isArray(options.static)) {
|
||||
options.static = [options.static]
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable live reload and add views directory
|
||||
*/
|
||||
options.liveReload = true
|
||||
options.static.push({
|
||||
directory: join(__dirname, './resources/views'),
|
||||
watch: true,
|
||||
})
|
||||
})
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| CSS precompilers support
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Uncomment one of the following lines of code to enable support for your
|
||||
| favorite CSS precompiler
|
||||
|
|
||||
*/
|
||||
// Encore.enableSassLoader()
|
||||
// Encore.enableLessLoader()
|
||||
// Encore.enableStylusLoader()
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| CSS loaders
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Uncomment one of the following line of code to enable support for
|
||||
| PostCSS or CSS.
|
||||
|
|
||||
*/
|
||||
Encore.enablePostCssLoader()
|
||||
// Encore.configureCssLoader(() => {})
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Enable Vue loader
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Uncomment the following lines of code to enable support for vue. Also make
|
||||
| sure to install the required dependencies.
|
||||
|
|
||||
*/
|
||||
Encore.enableVueLoader(() => {}, {
|
||||
version: 3,
|
||||
runtimeCompilerBuild: false,
|
||||
useJsx: false,
|
||||
}).enableTypeScriptLoader(config => {
|
||||
config.configFile = 'tsconfig.vue.json'
|
||||
}).addAliases({
|
||||
'@': join(__dirname, 'resources/js')
|
||||
}).configureDefinePlugin(options => {
|
||||
options['__VUE_OPTIONS_API__'] = true
|
||||
options['__VUE_PROD_DEVTOOLS__'] = false
|
||||
}).addPlugin( Components({
|
||||
resolvers: [NaiveUiResolver()]
|
||||
}))
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Configure logging
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| To keep the terminal clean from unnecessary info statements , we only
|
||||
| log warnings and errors. If you want all the logs, you can change
|
||||
| the level to "info".
|
||||
|
|
||||
*/
|
||||
const config = Encore.getWebpackConfig()
|
||||
config.infrastructureLogging = {
|
||||
level: 'warn',
|
||||
}
|
||||
config.stats = 'errors-warnings'
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| SSR Config
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
*/
|
||||
//config.externals = [require('webpack-node-externals')()]
|
||||
config.externals = [
|
||||
nodeExternals({
|
||||
allowlist: ['@inertiajs/core', '@inertiajs/vue3'],
|
||||
}),
|
||||
]
|
||||
config.externalsPresets = { node: true }
|
||||
config.output = {
|
||||
libraryTarget: 'commonjs2',
|
||||
filename: 'ssr.js',
|
||||
path: join(__dirname, './inertia/ssr'),
|
||||
}
|
||||
config.experiments = { outputModule: true }
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Export config
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Export config for webpack to do its job
|
||||
|
|
||||
*/
|
||||
|
||||
module.exports = config
|
||||
Reference in New Issue
Block a user