8 Commits

Author SHA1 Message Date
Adrian Zürcher
d57ee4c1e7 fix event not working issue close #1 2025-11-06 09:08:01 +01:00
Adrian Zürcher
9866cc3ffd fix event edit not working closes #3 2025-11-05 11:30:56 +01:00
6ec42c6c75 database removed 2025-11-05 11:26:51 +01:00
Adrian Zürcher
7b760afeb3 remove permission object 2025-11-04 15:32:02 +01:00
Adrian Zürcher
21dcf1a476 remove id from table 2025-11-04 15:31:36 +01:00
Adrian Zürcher
35d1a0f734 change wrong permissions 2025-11-04 15:31:21 +01:00
Adrian Zürcher
effbb61707 fix reference problem so value changes only after saving 2025-11-04 15:30:58 +01:00
Adrian Zürcher
7eb5ab9ab2 add env files for dev and production 2025-11-04 15:30:17 +01:00
18 changed files with 64 additions and 53 deletions

1
.env.development Normal file
View File

@@ -0,0 +1 @@
VITE_API_URL= https://localhost:9500/api

1
.env.production Normal file
View File

@@ -0,0 +1 @@
VITE_API_URL= https://members.tecamino.com/api

1
.gitignore vendored
View File

@@ -36,6 +36,7 @@ yarn-error.log*
# local .db files # local .db files
*.db *.db
*.dba
# local .log files # local .log files
*.log *.log

View File

@@ -4,7 +4,7 @@ go 1.24.5
require ( require (
gitea.tecamino.com/paadi/access-handler v1.0.12 gitea.tecamino.com/paadi/access-handler v1.0.12
gitea.tecamino.com/paadi/memberDB v1.0.11 gitea.tecamino.com/paadi/memberDB v1.0.14
gitea.tecamino.com/paadi/tecamino-dbm v0.1.1 gitea.tecamino.com/paadi/tecamino-dbm v0.1.1
gitea.tecamino.com/paadi/tecamino-logger v0.2.1 gitea.tecamino.com/paadi/tecamino-logger v0.2.1
github.com/gin-contrib/cors v1.7.6 github.com/gin-contrib/cors v1.7.6

View File

@@ -2,8 +2,8 @@ gitea.tecamino.com/paadi/access-handler v1.0.12 h1:lSmW0YrBJJvCqCg0ukTJHlFUNwd7q
gitea.tecamino.com/paadi/access-handler v1.0.12/go.mod h1:w71lpnuu5MgAWG3oiI9vsY2dWi4njF/iPrM/xV/dbBQ= gitea.tecamino.com/paadi/access-handler v1.0.12/go.mod h1:w71lpnuu5MgAWG3oiI9vsY2dWi4njF/iPrM/xV/dbBQ=
gitea.tecamino.com/paadi/dbHandler v1.0.4 h1:ctnaec0GDdtw3gRQdUISVDYLJ9x+vt50VW41OemfhD4= gitea.tecamino.com/paadi/dbHandler v1.0.4 h1:ctnaec0GDdtw3gRQdUISVDYLJ9x+vt50VW41OemfhD4=
gitea.tecamino.com/paadi/dbHandler v1.0.4/go.mod h1:y/xn/POJg1DO++67uKvnO23lJQgh+XFQq7HZCS9Getw= gitea.tecamino.com/paadi/dbHandler v1.0.4/go.mod h1:y/xn/POJg1DO++67uKvnO23lJQgh+XFQq7HZCS9Getw=
gitea.tecamino.com/paadi/memberDB v1.0.11 h1:Mwo86NVe7sLReRf+R4Z6hRxeEIgjjq6EPyiL1L1TlrA= gitea.tecamino.com/paadi/memberDB v1.0.14 h1:HO8YmVv9BmOguLMiubFABlQEnR3J+Qy46RwQQTXuWRs=
gitea.tecamino.com/paadi/memberDB v1.0.11/go.mod h1:iLm7nunVRzqJK8CV4PJVuWIhgPlQjNIaeOkmtfK5fMg= gitea.tecamino.com/paadi/memberDB v1.0.14/go.mod h1:iLm7nunVRzqJK8CV4PJVuWIhgPlQjNIaeOkmtfK5fMg=
gitea.tecamino.com/paadi/tecamino-dbm v0.1.1 h1:vAq7mwUxlxJuLzCQSDMrZCwo8ky5usWi9Qz+UP+WnkI= gitea.tecamino.com/paadi/tecamino-dbm v0.1.1 h1:vAq7mwUxlxJuLzCQSDMrZCwo8ky5usWi9Qz+UP+WnkI=
gitea.tecamino.com/paadi/tecamino-dbm v0.1.1/go.mod h1:+tmf1rjPaKEoNeUcr1vdtoFIFweNG3aUGevDAl3NMBk= gitea.tecamino.com/paadi/tecamino-dbm v0.1.1/go.mod h1:+tmf1rjPaKEoNeUcr1vdtoFIFweNG3aUGevDAl3NMBk=
gitea.tecamino.com/paadi/tecamino-logger v0.2.1 h1:sQTBKYPdzn9mmWX2JXZBtGBvNQH7cuXIwsl4TD0aMgE= gitea.tecamino.com/paadi/tecamino-logger v0.2.1 h1:sQTBKYPdzn9mmWX2JXZBtGBvNQH7cuXIwsl4TD0aMgE=

View File

@@ -133,6 +133,7 @@ func main() {
auth.POST("/members/import/csv", dbHandler.ImportCSV) auth.POST("/members/import/csv", dbHandler.ImportCSV)
auth.POST("/events/add", dbHandler.StartNewEvent) auth.POST("/events/add", dbHandler.StartNewEvent)
auth.POST("/events/edit", dbHandler.UpdateEvent)
auth.POST("/events/add/attendees", dbHandler.AddNewAttendees) auth.POST("/events/add/attendees", dbHandler.AddNewAttendees)
auth.POST("/events/delete/attendees", dbHandler.DeleteAttendee) auth.POST("/events/delete/attendees", dbHandler.DeleteAttendee)
auth.POST("/events/delete", dbHandler.DeleteEvent) auth.POST("/events/delete", dbHandler.DeleteEvent)

Binary file not shown.

View File

@@ -3,12 +3,11 @@ import type { AxiosError, AxiosInstance, AxiosRequestConfig, AxiosResponse } fro
import axios from 'axios'; import axios from 'axios';
import { useLogin } from 'src/vueLib/login/useLogin'; import { useLogin } from 'src/vueLib/login/useLogin';
const host = window.location.hostname; const host = import.meta.env.VITE_API_URL;
export const portApp = 9500;
// Create axios instance // Create axios instance
export const appApi: AxiosInstance = axios.create({ export const appApi: AxiosInstance = axios.create({
baseURL: `https://${host}:${portApp}/api`, baseURL: host,
timeout: 10000, timeout: 10000,
withCredentials: true, withCredentials: true,
}); });

View File

@@ -3,22 +3,22 @@
<div class="row justify-center"> <div class="row justify-center">
<q-select <q-select
autofocus autofocus
class="q-ml-md col-6"
:label="$t('event')" :label="$t('event')"
filled filled
:options="events" :options="events"
option-label="name" option-label="name"
option-value="id" option-value="id"
v-model="selected" v-model="selected"
@keyup.enter="save" @keyup.enter="addAttendees"
map-options map-options
emit-value emit-value
></q-select> ></q-select>
</div> </div>
<div class="row justify-center"> <div class="row justify-center">
<q-btn class="q-ma-md" color="primary" no-caps @click="save">{{ $t('save') }}</q-btn> <q-btn class="q-ma-md" color="primary" no-caps @click="addAttendees">{{ localTitle }}</q-btn>
</div> </div>
</DialogFrame> </DialogFrame>
<EditAllDialog ref="newEventRef" v-on:update="(val) => resolveNewEvent(val)"></EditAllDialog>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
@@ -29,13 +29,15 @@ import { useNotify } from 'src/vueLib/general/useNotify';
import { i18n } from 'src/boot/lang'; import { i18n } from 'src/boot/lang';
import type { Event, Events } from 'src/vueLib/models/event'; import type { Event, Events } from 'src/vueLib/models/event';
import type { Members } from 'src/vueLib/models/member'; import type { Members } from 'src/vueLib/models/member';
import EditAllDialog from 'src/components/EventEditAllDialog.vue';
import { useAttendeesTable } from 'src/vueLib/tables/attendees/AttendeesTable'; import { useAttendeesTable } from 'src/vueLib/tables/attendees/AttendeesTable';
import { useEventTable } from 'src/vueLib/tables/events/EventsTable'; import { useEventTable } from 'src/vueLib/tables/events/EventsTable';
const dialog = ref(); const dialog = ref();
const newEventRef = ref();
const localTitle = ref(''); const localTitle = ref('');
const events = ref<Events>([{ id: -1, name: i18n.global.t('add'), attendees: [] }]); const events = ref<Events>([{ id: -1, name: i18n.global.t('addNewEvent'), attendees: [] }]);
const selected = ref<Event>({ id: -1, name: i18n.global.t('add'), attendees: [] }); const selected = ref<Event>({ id: -1, name: i18n.global.t('addNewEvent'), attendees: [] });
const localMembers = ref<Members>([]); const localMembers = ref<Members>([]);
const { updateAttendees } = useAttendeesTable(); const { updateAttendees } = useAttendeesTable();
const { updateEvents } = useEventTable(); const { updateEvents } = useEventTable();
@@ -57,7 +59,7 @@ function open(title: string, members: Members) {
localTitle.value = title; localTitle.value = title;
localMembers.value = members; localMembers.value = members;
events.value = [{ id: -1, name: i18n.global.t('add'), attendees: [] }]; events.value = [{ id: -1, name: i18n.global.t('addNewEvent'), attendees: [] }];
appApi appApi
.get('events') .get('events')
.then((resp) => { .then((resp) => {
@@ -69,23 +71,44 @@ function open(title: string, members: Members) {
dialog.value?.open(); dialog.value?.open();
} }
async function save() { async function addAttendees() {
await appApi const payload = {
.post(props.endpoint, { id: Number(selected.value),
id: selected.value,
attendees: localMembers.value, attendees: localMembers.value,
}) };
if (selected.value.id == -1) {
const event = await addNewEvent();
NotifyResponse(i18n.global.t('eventAdded') + ': ' + event.name);
payload.id = event.id;
}
console.log(56, payload);
await appApi
.post(props.endpoint, payload)
.then(() => { .then(() => {
emit('update-event', localMembers.value); emit('update-event', localMembers.value);
NotifyResponse(i18n.global.t('eventAdded')); if (localMembers.value.length > 1) {
NotifyResponse(i18n.global.t('attendeesAdded'));
} else {
NotifyResponse(i18n.global.t('attendeeAdded'));
}
dialog.value.close(); dialog.value.close();
}) })
.catch((err) => { .catch((err) => {
NotifyResponse(err, 'error'); NotifyResponse(err, 'error');
}); });
await updateAttendees(); await updateAttendees();
updateEvents(); updateEvents();
} }
let resolveNewEvent!: (value: Event) => void;
function addNewEvent(): Promise<Event> {
newEventRef.value?.open(null);
return new Promise((resolve) => {
resolveNewEvent = resolve;
});
}
defineExpose({ open }); defineExpose({ open });
</script> </script>

View File

@@ -49,8 +49,8 @@ function open(Event: Event | null) {
} }
if (Event !== null) { if (Event !== null) {
localEvent.value = Event; localEvent.value = { ...Event };
newEvent.value = false; newEvent.value = Event.id === 0;
} else { } else {
localEvent.value = { localEvent.value = {
id: 0, id: 0,
@@ -68,15 +68,17 @@ async function save() {
if (!valid) return; if (!valid) return;
let query = 'events/edit?id=' + localEvent.value.id; let query = 'events/edit';
let payload = JSON.stringify([localEvent.value]);
if (newEvent.value) { if (newEvent.value) {
query = 'events/add?name=' + localEvent.value.name; query = 'events/add?name=' + localEvent.value.name;
payload = JSON.stringify(localEvent.value);
} }
appApi appApi
.post(query, JSON.stringify(localEvent.value)) .post(query, payload)
.then(() => { .then((resp) => {
emit('update'); emit('update', resp.data.data);
dialog.value.close(); dialog.value.close();
}) })
.catch((err) => NotifyResponse(err, 'error')); .catch((err) => NotifyResponse(err, 'error'));

View File

@@ -132,7 +132,7 @@ function open(member: Member | null) {
} }
if (member !== null) { if (member !== null) {
localMember.value = member; localMember.value = { ...member };
newMember.value = false; newMember.value = false;
} else { } else {
localMember.value = { localMember.value = {

View File

@@ -60,7 +60,7 @@ function open(role: Role | null, typ?: 'permissions') {
showRoleField.value = typ !== 'permissions'; showRoleField.value = typ !== 'permissions';
if (role !== null) { if (role !== null) {
localRole.value = role; localRole.value = { ...role };
localRole.value.permissions = role.permissions || defaultPermissions; localRole.value.permissions = role.permissions || defaultPermissions;
newRole.value = false; newRole.value = false;
} else { } else {
@@ -80,7 +80,7 @@ function save() {
if (newRole.value) { if (newRole.value) {
query = 'roles/add'; query = 'roles/add';
update = false; update = false;
localRole.value.permissions = defaultPermissions; localRole.value.permissions = localRole.value.permissions ?? defaultPermissions;
} }
appApi appApi

View File

@@ -149,7 +149,7 @@ async function open(user: User | null) {
} }
if (user !== null) { if (user !== null) {
localUser.value = user; localUser.value = { ...user };
newUser.value = false; newUser.value = false;
} else { } else {
localUser.value = { localUser.value = {

View File

@@ -8,7 +8,7 @@
<p class="text-bold text-h6 text-primary q-pa-md">{{ $t('general') }}</p> <p class="text-bold text-h6 text-primary q-pa-md">{{ $t('general') }}</p>
<div class="row"> <div class="row">
<q-input <q-input
:readonly="!user.isPermittedTo('userSettings', 'write')" :readonly="!user.isPermittedTo('settings', 'write')"
:class="[ :class="[
colorGroup ? 'col-md-4' : 'col-md-3', colorGroup ? 'col-md-4' : 'col-md-3',
colorGroup ? 'col-md-6' : 'col-md-6', colorGroup ? 'col-md-6' : 'col-md-6',
@@ -25,7 +25,7 @@
<p class="text-bold text-h6 text-primary q-pa-md">{{ $t('database') }}</p> <p class="text-bold text-h6 text-primary q-pa-md">{{ $t('database') }}</p>
<div class="row"> <div class="row">
<q-input <q-input
:readonly="!user.isPermittedTo('userSettings', 'write')" :readonly="!user.isPermittedTo('settings', 'write')"
:class="[ :class="[
colorGroup ? 'col-md-4' : 'col-md-3', colorGroup ? 'col-md-4' : 'col-md-3',
colorGroup ? 'col-md-6' : 'col-md-6', colorGroup ? 'col-md-6' : 'col-md-6',
@@ -55,7 +55,7 @@
<div class="col-12 col-sm-6 col-md-3 q-px-md"> <div class="col-12 col-sm-6 col-md-3 q-px-md">
<p class="text-center text-bold text-h6 text-primary">{{ $t('primaryColor') }}</p> <p class="text-center text-bold text-h6 text-primary">{{ $t('primaryColor') }}</p>
<q-color <q-color
:disable="!user.isPermittedTo('userSettings', 'write')" :disable="!user.isPermittedTo('settings', 'write')"
bordered bordered
class="q-mx-md" class="q-mx-md"
v-model="settings.primaryColor" v-model="settings.primaryColor"
@@ -75,7 +75,7 @@
{{ $t('primaryColorText') }} {{ $t('primaryColorText') }}
</p> </p>
<q-color <q-color
:disable="!user.isPermittedTo('userSettings', 'write')" :disable="!user.isPermittedTo('settings', 'write')"
bordered bordered
class="q-mx-md" class="q-mx-md"
v-model="settings.primaryColorText" v-model="settings.primaryColorText"
@@ -86,7 +86,7 @@
{{ $t('secondaryColor') }} {{ $t('secondaryColor') }}
</p> </p>
<q-color <q-color
:disable="!user.isPermittedTo('userSettings', 'write')" :disable="!user.isPermittedTo('settings', 'write')"
class="q-mx-md" class="q-mx-md"
v-model="settings.secondaryColor" v-model="settings.secondaryColor"
></q-color> ></q-color>
@@ -105,14 +105,14 @@
{{ $t('secondaryColorText') }} {{ $t('secondaryColorText') }}
</p> </p>
<q-color <q-color
:disable="!user.isPermittedTo('userSettings', 'write')" :disable="!user.isPermittedTo('settings', 'write')"
class="q-mx-md" class="q-mx-md"
v-model="settings.secondaryColorText" v-model="settings.secondaryColorText"
></q-color> ></q-color>
</div> </div>
</div> </div>
<q-btn <q-btn
:disable="!user.isPermittedTo('userSettings', 'write')" :disable="!user.isPermittedTo('settings', 'write')"
class="q-my-md q-mx-md" class="q-my-md q-mx-md"
color="secondary" color="secondary"
dense dense

View File

@@ -2,7 +2,6 @@
<q-card> <q-card>
<q-card bordered v-for="(permission, index) in localPermission" v-bind:key="index"> <q-card bordered v-for="(permission, index) in localPermission" v-bind:key="index">
<q-card-section class="text-center"> <q-card-section class="text-center">
{{ permission }}
<div class="text-h7 text-bold text-primary">{{ $t(permission.name) }}</div> <div class="text-h7 text-bold text-primary">{{ $t(permission.name) }}</div>
</q-card-section> </q-card-section>
<q-separator></q-separator> <q-separator></q-separator>

View File

@@ -125,7 +125,7 @@
</div> </div>
<EditOneDialog <EditOneDialog
ref="editOneDialog" ref="editOneDialog"
endpoint="Events/edit" endpoint="events/edit"
query-id query-id
v-on:update="updateEvents" v-on:update="updateEvents"
></EditOneDialog> ></EditOneDialog>

View File

@@ -17,14 +17,6 @@ export function useRoleTable() {
}); });
const columns = computed(() => [ const columns = computed(() => [
{
name: 'id',
align: 'left' as const,
label: 'Id',
field: 'id',
sortable: true,
style: 'width: 50px; max-width: 50px;',
},
{ {
name: 'role', name: 'role',
align: 'left' as const, align: 'left' as const,

View File

@@ -15,14 +15,6 @@ export function useUserTable() {
}); });
const columns = computed(() => [ const columns = computed(() => [
{
name: 'id',
align: 'left' as const,
label: 'Id',
field: 'id',
sortable: true,
style: 'width: 50px; max-width: 50px;',
},
{ {
name: 'user', name: 'user',
align: 'left' as const, align: 'left' as const,