release v2.0.0 #4
|
@ -24,5 +24,6 @@
|
||||||
"sortAttributes": false
|
"sortAttributes": false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"vetur.format.defaultFormatter.ts": "prettier-tslint"
|
"vetur.format.defaultFormatter.ts": "prettier-tslint",
|
||||||
|
"typescript.format.enable": false
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,6 @@ export default defineComponent({
|
||||||
name: 'EmptyParent',
|
name: 'EmptyParent',
|
||||||
setup() {
|
setup() {
|
||||||
return {};
|
return {};
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -49,18 +49,14 @@ export default defineComponent({
|
||||||
if (props.title.includes('loadFromStore')) {
|
if (props.title.includes('loadFromStore')) {
|
||||||
const startIndex = props.title.indexOf('(') + 1;
|
const startIndex = props.title.indexOf('(') + 1;
|
||||||
const endIndex = props.title.indexOf(')');
|
const endIndex = props.title.indexOf(')');
|
||||||
const substring = props.title
|
const substring = props.title.substring(startIndex, endIndex).replace(/"/g, '');
|
||||||
.substring(startIndex, endIndex)
|
|
||||||
.replace(/"/g, '');
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
||||||
return <string>root.$store.getters[substring];
|
return <string>root.$store.getters[substring];
|
||||||
}
|
}
|
||||||
return props.title;
|
return props.title;
|
||||||
});
|
});
|
||||||
|
|
||||||
const isGranted = computed(() =>
|
const isGranted = computed(() => hasPermissions(props.permissions || [], root.$store));
|
||||||
hasPermissions(props.permissions || [], root.$store)
|
|
||||||
);
|
|
||||||
|
|
||||||
return { realTitle: title, isGranted };
|
return { realTitle: title, isGranted };
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,9 +22,7 @@ export default defineComponent({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
setup(props, { root }) {
|
setup(props, { root }) {
|
||||||
const isGranted = computed(() =>
|
const isGranted = computed(() => hasPermissions(props.permissions || [], root.$store));
|
||||||
hasPermissions(props.permissions || [], root.$store)
|
|
||||||
);
|
|
||||||
return { isGranted };
|
return { isGranted };
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -49,18 +49,18 @@ export default defineComponent({
|
||||||
name: 'IsoDateInput',
|
name: 'IsoDateInput',
|
||||||
props: {
|
props: {
|
||||||
value: {
|
value: {
|
||||||
required: true,
|
required: true
|
||||||
},
|
},
|
||||||
label: {},
|
label: {},
|
||||||
readonly: {
|
readonly: {
|
||||||
default: false,
|
default: false
|
||||||
},
|
},
|
||||||
type: {
|
type: {
|
||||||
default: 'date',
|
default: 'date',
|
||||||
validator: function(value: string) {
|
validator: function(value: string) {
|
||||||
return ['date', 'time', 'datetime'].indexOf(value) !== -1;
|
return ['date', 'time', 'datetime'].indexOf(value) !== -1;
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
setup(props: Props, { emit }: { emit: any }) {
|
setup(props: Props, { emit }: { emit: any }) {
|
||||||
function getDateTime() {
|
function getDateTime() {
|
||||||
|
@ -183,8 +183,8 @@ export default defineComponent({
|
||||||
rules,
|
rules,
|
||||||
timeChanged,
|
timeChanged,
|
||||||
placeholder,
|
placeholder,
|
||||||
dateTimeChanged,
|
dateTimeChanged
|
||||||
};
|
};
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -112,23 +112,23 @@ const links = [
|
||||||
name: 'about',
|
name: 'about',
|
||||||
title: 'Über Flaschengeist',
|
title: 'Über Flaschengeist',
|
||||||
link: 'about',
|
link: 'about',
|
||||||
icon: 'mdi-information',
|
icon: 'mdi-information'
|
||||||
},
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
const shortcuts = [
|
const shortcuts = [
|
||||||
{
|
{
|
||||||
link: 'about',
|
link: 'about',
|
||||||
icon: 'mdi-information',
|
icon: 'mdi-information'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
link: 'user',
|
link: 'user',
|
||||||
icon: 'mdi-account',
|
icon: 'mdi-account'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
link: 'user-plugin1',
|
link: 'user-plugin1',
|
||||||
icon: 'mdi-account-plus',
|
icon: 'mdi-account-plus'
|
||||||
},
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
declare module 'vue/types/vue' {
|
declare module 'vue/types/vue' {
|
||||||
|
@ -146,7 +146,7 @@ export default defineComponent({
|
||||||
const leftDrawerOpen = ref(
|
const leftDrawerOpen = ref(
|
||||||
computed({
|
computed({
|
||||||
get: () => (leftDrawer.value || Screen.gt.sm ? true : false),
|
get: () => (leftDrawer.value || Screen.gt.sm ? true : false),
|
||||||
set: (val: boolean) => (leftDrawer.value = val),
|
set: (val: boolean) => (leftDrawer.value = val)
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
const leftDrawerMini = ref(false);
|
const leftDrawerMini = ref(false);
|
||||||
|
@ -177,9 +177,7 @@ export default defineComponent({
|
||||||
|
|
||||||
function logout() {
|
function logout() {
|
||||||
Loading.show({ message: 'Session wird abgemeldet' });
|
Loading.show({ message: 'Session wird abgemeldet' });
|
||||||
(<Store<StateInterface>>ctx.root.$store)
|
(<Store<StateInterface>>ctx.root.$store).dispatch('session/logout').finally(() => {
|
||||||
.dispatch('session/logout')
|
|
||||||
.finally(() => {
|
|
||||||
Loading.hide();
|
Loading.hide();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -191,8 +189,8 @@ export default defineComponent({
|
||||||
links,
|
links,
|
||||||
pluginChildLinks,
|
pluginChildLinks,
|
||||||
shortcuts,
|
shortcuts,
|
||||||
logout,
|
logout
|
||||||
};
|
};
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -49,6 +49,6 @@ import ShortCutLink from 'components/navigation/ShortCutLink.vue';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'OutLayout',
|
name: 'OutLayout',
|
||||||
components: { ShortCutLink },
|
components: { ShortCutLink }
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -4,11 +4,7 @@
|
||||||
style="grid-auto-rows: 1fr;"
|
style="grid-auto-rows: 1fr;"
|
||||||
class="fit row justify-around items-start q-col-gutter-sm"
|
class="fit row justify-around items-start q-col-gutter-sm"
|
||||||
>
|
>
|
||||||
<div
|
<div v-for="(item, index) in widgets" :key="index" class="col-4 full-height col-sm-6 col-xs-12">
|
||||||
v-for="(item, index) in widgets"
|
|
||||||
:key="index"
|
|
||||||
class="col-4 full-height col-sm-6 col-xs-12"
|
|
||||||
>
|
|
||||||
<component v-bind:is="item" />
|
<component v-bind:is="item" />
|
||||||
</div>
|
</div>
|
||||||
</q-page>
|
</q-page>
|
||||||
|
@ -25,15 +21,14 @@ export default defineComponent({
|
||||||
const widgets = ref<Array<AsyncComponentPromise>>([]);
|
const widgets = ref<Array<AsyncComponentPromise>>([]);
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
root.$flaschengeistPlugins.widgets.forEach((widget) => {
|
root.$flaschengeistPlugins.widgets.forEach(widget => {
|
||||||
if (hasPermissions(widget.permissions, root.$store))
|
if (hasPermissions(widget.permissions, root.$store)) widgets.value.push(widget.widget);
|
||||||
widgets.value.push(widget.widget);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
widgets,
|
widgets
|
||||||
};
|
};
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -12,14 +12,16 @@
|
||||||
fill="white"
|
fill="white"
|
||||||
>
|
>
|
||||||
<g>
|
<g>
|
||||||
<circle
|
<circle cx="87.493" cy="25.907" r="25.907" />
|
||||||
cx="87.493"
|
<path
|
||||||
cy="25.907"
|
d="m194.386,209.531l-42.802-36.895c-1.825-1.573-4.001-2.683-6.345-3.237l-72.533-17.136 47.755,.703v-34.439l-46.525-26.18 50.36,14.829c4.016,1.182 8.356,0.276 11.564-2.414l38.264-32.093c1.1-0.923 2.001-1.994 2.698-3.161 2.656-4.442 2.36-10.26-1.154-14.449-4.437-5.29-12.32-5.981-17.61-1.544l-33.127,27.785-45.605-13.428 41.402,1.292 16.027-13.442-6.021-2.955-3.631,3.945-18.134,2.86h-37.216c-9.665,0-17.501,7.835-17.501,17.501v90.395l.029-.024c0.252,6.569 4.819,12.433 11.527,14.019l68.966,16.292 40.024,34.501c2.834,2.442 6.318,3.639 9.787,3.639 4.213,0 8.402-1.765 11.368-5.206 5.41-6.278 4.708-15.75-1.567-21.158z"
|
||||||
r="25.907"
|
/>
|
||||||
|
<path
|
||||||
|
d="m233.888,50.21l-43.49-21.349c-2.17-1.065-4.545-1.612-6.94-1.612-0.861,0-1.724,0.071-2.581,0.213l-13.243,2.2-24.213-11.886c-6.197-3.043-13.688-0.485-16.728,5.713-3.042,6.197-0.484,13.687 5.713,16.729l14.402,7.069 3.539-2.969c4.405-3.694 9.994-5.729 15.738-5.729 7.266,0 14.11,3.192 18.777,8.756 6.702,7.991 7.61,19.371 2.258,28.32-0.529,0.884-1.127,1.717-1.759,2.523l28.035,13.762c0.916,0.45 1.914,0.664 2.967,0.664 5.79,0 13.263-6.495 18.05-16.247 5.66-11.524 5.424-23.236-0.525-26.157z"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="m102.363,202.426l2.531,6.9-13.835,65.324c-1.716,8.105 3.463,16.065 11.567,17.782 1.048,0.222 2.092,0.328 3.122,0.328 6.936-0.001 13.165-4.839 14.66-11.896l14.265-67.357-5.513-4.752-26.797-6.329z"
|
||||||
/>
|
/>
|
||||||
<path d="m194.386,209.531l-42.802-36.895c-1.825-1.573-4.001-2.683-6.345-3.237l-72.533-17.136 47.755,.703v-34.439l-46.525-26.18 50.36,14.829c4.016,1.182 8.356,0.276 11.564-2.414l38.264-32.093c1.1-0.923 2.001-1.994 2.698-3.161 2.656-4.442 2.36-10.26-1.154-14.449-4.437-5.29-12.32-5.981-17.61-1.544l-33.127,27.785-45.605-13.428 41.402,1.292 16.027-13.442-6.021-2.955-3.631,3.945-18.134,2.86h-37.216c-9.665,0-17.501,7.835-17.501,17.501v90.395l.029-.024c0.252,6.569 4.819,12.433 11.527,14.019l68.966,16.292 40.024,34.501c2.834,2.442 6.318,3.639 9.787,3.639 4.213,0 8.402-1.765 11.368-5.206 5.41-6.278 4.708-15.75-1.567-21.158z" />
|
|
||||||
<path d="m233.888,50.21l-43.49-21.349c-2.17-1.065-4.545-1.612-6.94-1.612-0.861,0-1.724,0.071-2.581,0.213l-13.243,2.2-24.213-11.886c-6.197-3.043-13.688-0.485-16.728,5.713-3.042,6.197-0.484,13.687 5.713,16.729l14.402,7.069 3.539-2.969c4.405-3.694 9.994-5.729 15.738-5.729 7.266,0 14.11,3.192 18.777,8.756 6.702,7.991 7.61,19.371 2.258,28.32-0.529,0.884-1.127,1.717-1.759,2.523l28.035,13.762c0.916,0.45 1.914,0.664 2.967,0.664 5.79,0 13.263-6.495 18.05-16.247 5.66-11.524 5.424-23.236-0.525-26.157z" />
|
|
||||||
<path d="m102.363,202.426l2.531,6.9-13.835,65.324c-1.716,8.105 3.463,16.065 11.567,17.782 1.048,0.222 2.092,0.328 3.122,0.328 6.936-0.001 13.165-4.839 14.66-11.896l14.265-67.357-5.513-4.752-26.797-6.329z" />
|
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
|
@ -27,7 +29,8 @@
|
||||||
Der Admin is über's Kabel gestolpert!
|
Der Admin is über's Kabel gestolpert!
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
Aktuell kann der Backend Server nicht erreicht werden, wir versuchen es in {{reload}} Sekunden erneut.
|
Aktuell kann der Backend Server nicht erreicht werden, wir versuchen es in
|
||||||
|
{{ reload }} Sekunden erneut.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -49,6 +52,6 @@ export default defineComponent({
|
||||||
}, 1000);
|
}, 1000);
|
||||||
onUnmounted(() => clearInterval(ival));
|
onUnmounted(() => clearInterval(ival));
|
||||||
return { reload };
|
return { reload };
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -2,12 +2,26 @@
|
||||||
<div class="fullscreen bg-blue text-white text-center q-pa-md flex flex-center">
|
<div class="fullscreen bg-blue text-white text-center q-pa-md flex flex-center">
|
||||||
<div>
|
<div>
|
||||||
<div>
|
<div>
|
||||||
<svg style="max-width: 400px;" version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 292.761 292.761" xmlns:xlink="http://www.w3.org/1999/xlink" enable-background="new 0 0 292.761 292.761" fill="white">
|
<svg
|
||||||
|
style="max-width: 400px;"
|
||||||
|
version="1.1"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 292.761 292.761"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
enable-background="new 0 0 292.761 292.761"
|
||||||
|
fill="white"
|
||||||
|
>
|
||||||
<g>
|
<g>
|
||||||
<circle cx="87.493" cy="25.907" r="25.907" />
|
<circle cx="87.493" cy="25.907" r="25.907" />
|
||||||
<path d="m194.386,209.531l-42.802-36.895c-1.825-1.573-4.001-2.683-6.345-3.237l-72.533-17.136 47.755,.703v-34.439l-46.525-26.18 50.36,14.829c4.016,1.182 8.356,0.276 11.564-2.414l38.264-32.093c1.1-0.923 2.001-1.994 2.698-3.161 2.656-4.442 2.36-10.26-1.154-14.449-4.437-5.29-12.32-5.981-17.61-1.544l-33.127,27.785-45.605-13.428 41.402,1.292 16.027-13.442-6.021-2.955-3.631,3.945-18.134,2.86h-37.216c-9.665,0-17.501,7.835-17.501,17.501v90.395l.029-.024c0.252,6.569 4.819,12.433 11.527,14.019l68.966,16.292 40.024,34.501c2.834,2.442 6.318,3.639 9.787,3.639 4.213,0 8.402-1.765 11.368-5.206 5.41-6.278 4.708-15.75-1.567-21.158z"/>
|
<path
|
||||||
<path d="m233.888,50.21l-43.49-21.349c-2.17-1.065-4.545-1.612-6.94-1.612-0.861,0-1.724,0.071-2.581,0.213l-13.243,2.2-24.213-11.886c-6.197-3.043-13.688-0.485-16.728,5.713-3.042,6.197-0.484,13.687 5.713,16.729l14.402,7.069 3.539-2.969c4.405-3.694 9.994-5.729 15.738-5.729 7.266,0 14.11,3.192 18.777,8.756 6.702,7.991 7.61,19.371 2.258,28.32-0.529,0.884-1.127,1.717-1.759,2.523l28.035,13.762c0.916,0.45 1.914,0.664 2.967,0.664 5.79,0 13.263-6.495 18.05-16.247 5.66-11.524 5.424-23.236-0.525-26.157z"/>
|
d="m194.386,209.531l-42.802-36.895c-1.825-1.573-4.001-2.683-6.345-3.237l-72.533-17.136 47.755,.703v-34.439l-46.525-26.18 50.36,14.829c4.016,1.182 8.356,0.276 11.564-2.414l38.264-32.093c1.1-0.923 2.001-1.994 2.698-3.161 2.656-4.442 2.36-10.26-1.154-14.449-4.437-5.29-12.32-5.981-17.61-1.544l-33.127,27.785-45.605-13.428 41.402,1.292 16.027-13.442-6.021-2.955-3.631,3.945-18.134,2.86h-37.216c-9.665,0-17.501,7.835-17.501,17.501v90.395l.029-.024c0.252,6.569 4.819,12.433 11.527,14.019l68.966,16.292 40.024,34.501c2.834,2.442 6.318,3.639 9.787,3.639 4.213,0 8.402-1.765 11.368-5.206 5.41-6.278 4.708-15.75-1.567-21.158z"
|
||||||
<path d="m102.363,202.426l2.531,6.9-13.835,65.324c-1.716,8.105 3.463,16.065 11.567,17.782 1.048,0.222 2.092,0.328 3.122,0.328 6.936-0.001 13.165-4.839 14.66-11.896l14.265-67.357-5.513-4.752-26.797-6.329z"/>
|
/>
|
||||||
|
<path
|
||||||
|
d="m233.888,50.21l-43.49-21.349c-2.17-1.065-4.545-1.612-6.94-1.612-0.861,0-1.724,0.071-2.581,0.213l-13.243,2.2-24.213-11.886c-6.197-3.043-13.688-0.485-16.728,5.713-3.042,6.197-0.484,13.687 5.713,16.729l14.402,7.069 3.539-2.969c4.405-3.694 9.994-5.729 15.738-5.729 7.266,0 14.11,3.192 18.777,8.756 6.702,7.991 7.61,19.371 2.258,28.32-0.529,0.884-1.127,1.717-1.759,2.523l28.035,13.762c0.916,0.45 1.914,0.664 2.967,0.664 5.79,0 13.263-6.495 18.05-16.247 5.66-11.524 5.424-23.236-0.525-26.157z"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="m102.363,202.426l2.531,6.9-13.835,65.324c-1.716,8.105 3.463,16.065 11.567,17.782 1.048,0.222 2.092,0.328 3.122,0.328 6.936-0.001 13.165-4.839 14.66-11.896l14.265-67.357-5.513-4.752-26.797-6.329z"
|
||||||
|
/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
|
@ -15,7 +29,8 @@
|
||||||
Der Admin war betrunken!!
|
Der Admin war betrunken!!
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
Einige Plugins konnten nicht geladen werden.<br />Sollte diese Seite jemals auftauchen, kontaktiere einen nüchternen Admin.
|
Einige Plugins konnten nicht geladen werden.<br />Sollte diese Seite jemals auftauchen,
|
||||||
|
kontaktiere einen nüchternen Admin.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -26,9 +41,7 @@ import {defineComponent} from '@vue/composition-api';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'PluginError.vue'
|
name: 'PluginError.vue'
|
||||||
})
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped></style>
|
||||||
|
|
||||||
</style>
|
|
||||||
|
|
|
@ -17,15 +17,13 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12 text-center q-ma-sm" style="max-width: 600px;">
|
<div class="col-12 text-center q-ma-sm" style="max-width: 600px;">
|
||||||
Flaschengeist ist ein dynamischen Managementsystem für Studentenclubs.
|
Flaschengeist ist ein dynamischen Managementsystem für Studentenclubs. Es ermöglicht unter
|
||||||
Es ermöglicht unter anderem die Mitgliederverwaltung, Dienstverwaltung,
|
anderem die Mitgliederverwaltung, Dienstverwaltung, Arbeitsgruppenverwaltung und vieles
|
||||||
Arbeitsgruppenverwaltung und vieles meher. Es kann fast alles ermöglich
|
meher. Es kann fast alles ermöglich werden, wenn ein Plugin dafür geschrieben wird. Jeder
|
||||||
werden, wenn ein Plugin dafür geschrieben wird. Jeder Club hat die
|
Club hat die Möglichkeit sein eigenes Flaschengeist zu hosten. Ziel ist später
|
||||||
Möglichkeit sein eigenes Flaschengeist zu hosten. Ziel ist später
|
|
||||||
Clubübergreifend dezentralisiert miteinander zu arbeiten.
|
Clubübergreifend dezentralisiert miteinander zu arbeiten.
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<q-separator />
|
<q-separator />
|
||||||
<div class="col-12 text-h6 q-pa-sm" v-if="$route.name == 'about'">
|
<div class="col-12 text-h6 q-pa-sm" v-if="$route.name == 'about'">
|
||||||
Geladene Plugins:
|
Geladene Plugins:
|
||||||
|
@ -49,9 +47,7 @@
|
||||||
Entwickler:
|
Entwickler:
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div class="fit row inline wrap justify-around items-start content-start">
|
||||||
class="fit row inline wrap justify-around items-start content-start"
|
|
||||||
>
|
|
||||||
<developer
|
<developer
|
||||||
v-for="(developer, index) in developers"
|
v-for="(developer, index) in developers"
|
||||||
:key="'dev' + index"
|
:key="'dev' + index"
|
||||||
|
|
|
@ -1,24 +1,33 @@
|
||||||
<template>
|
<template>
|
||||||
<q-card>
|
<q-card v-bind:class="{ 'bg-grey': isReversed }">
|
||||||
<q-card-actions align="right">
|
<q-card-section class="row items-start justify-between">
|
||||||
|
<div class="col text-center">
|
||||||
|
<div
|
||||||
|
v-bind:class="{ 'text-negative': isNegative() }"
|
||||||
|
class="text-weight-bold"
|
||||||
|
style="font-size: 2em"
|
||||||
|
>
|
||||||
|
<span v-if="isNegative()">-</span>{{ transaction.amount.toFixed(2) }} €
|
||||||
|
</div>
|
||||||
|
<div>{{ text }}</div>
|
||||||
|
<div>{{ timeStr }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="col" style="text-align: right">
|
||||||
<q-btn
|
<q-btn
|
||||||
:color="color()"
|
color="negative"
|
||||||
|
aria-label="Reverse transaction"
|
||||||
icon="mdi-trash-can"
|
icon="mdi-trash-can"
|
||||||
aria-label="Löschen"
|
square
|
||||||
:disable="disabled()"
|
:disable="!canReverse"
|
||||||
@click="reverse(transaction)"
|
@click="reverse"
|
||||||
/>
|
/>
|
||||||
</q-card-actions>
|
</div>
|
||||||
<q-card-section>
|
|
||||||
<span>{{ timeStr }}: {{ transaction.amount }}</span>
|
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
</q-card>
|
</q-card>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
// TODO: Better styling
|
import { ref, computed, defineComponent, onUnmounted, onMounted } from '@vue/composition-api';
|
||||||
|
|
||||||
import { ref, computed, defineComponent, onUnmounted } from '@vue/composition-api';
|
|
||||||
import { hasPermission } from 'src/utils/permission';
|
import { hasPermission } from 'src/utils/permission';
|
||||||
import { formatDateTime } from 'src/utils/datetime';
|
import { formatDateTime } from 'src/utils/datetime';
|
||||||
import { StateInterfaceBalance } from 'src/plugins/balance/store/balance';
|
import { StateInterfaceBalance } from 'src/plugins/balance/store/balance';
|
||||||
|
@ -30,36 +39,60 @@ interface Props {
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'Transaction',
|
name: 'Transaction',
|
||||||
props: ['transaction'],
|
props: {
|
||||||
|
transaction: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: { transaction: 'refreshText' },
|
||||||
setup(props: Props, { root, emit }) {
|
setup(props: Props, { root, emit }) {
|
||||||
const now = ref(Date.now());
|
const now = ref(Date.now());
|
||||||
const ival = setInterval(() => (now.value = Date.now()), 1000);
|
const ival = setInterval(() => (now.value = Date.now()), 1000);
|
||||||
const store: Store<StateInterfaceBalance> = <Store<StateInterfaceBalance>>root.$store;
|
const store: Store<StateInterfaceBalance> = <Store<StateInterfaceBalance>>root.$store;
|
||||||
|
const text = ref('');
|
||||||
|
|
||||||
onUnmounted(() => clearInterval(ival));
|
onUnmounted(() => clearInterval(ival));
|
||||||
|
onMounted(() => refreshText());
|
||||||
|
|
||||||
function canReverse(transaction: FG.Transaction) {
|
const isNegative = () => props.transaction.sender_id === store.state.user.currentUser?.userid;
|
||||||
return (
|
|
||||||
hasPermission('balance_reversal', store) ||
|
const refreshText = async () => {
|
||||||
(transaction.sender_id === store.state.user.currentUser?.userid &&
|
if (isNegative()) {
|
||||||
Date.now() - transaction.time.getTime() < 10000)
|
text.value = 'Anschreiben';
|
||||||
|
if (props.transaction.receiver_id !== null) {
|
||||||
|
const user = <FG.User>await store.dispatch('user/getUser', {
|
||||||
|
userid: props.transaction.receiver_id
|
||||||
|
});
|
||||||
|
text.value = `Gesendet an ${user.display_name}`;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
text.value = 'Gutschrift';
|
||||||
|
if (props.transaction.sender_id !== null) {
|
||||||
|
const user = <FG.User>await store.dispatch('user/getUser', {
|
||||||
|
userid: props.transaction.sender_id
|
||||||
|
});
|
||||||
|
text.value = `Bekommen von ${user.display_name}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const isReversed = computed(() => props.transaction.reversal != undefined);
|
||||||
|
|
||||||
|
const canReverse = computed(
|
||||||
|
() =>
|
||||||
|
!isReversed.value &&
|
||||||
|
(hasPermission('balance_reversal', store) ||
|
||||||
|
(props.transaction.sender_id === store.state.user.currentUser?.userid &&
|
||||||
|
now.value - props.transaction.time.getTime() < 10000))
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
function color() {
|
function reverse() {
|
||||||
return canReverse(props.transaction) ? 'negative' : 'grey';
|
if (canReverse.value)
|
||||||
}
|
|
||||||
|
|
||||||
function disabled() {
|
|
||||||
return !canReverse(props.transaction);
|
|
||||||
}
|
|
||||||
|
|
||||||
function reverse(transaction: FG.Transaction) {
|
|
||||||
if (canReverse(transaction))
|
|
||||||
store
|
store
|
||||||
.dispatch('balance/revert', transaction)
|
.dispatch('balance/revert', props.transaction)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
emit('reversed', transaction.id);
|
emit('update:transaction', props.transaction);
|
||||||
})
|
})
|
||||||
.catch(error => console.log(error));
|
.catch(error => console.log(error));
|
||||||
}
|
}
|
||||||
|
@ -70,7 +103,7 @@ export default defineComponent({
|
||||||
return formatDateTime(props.transaction.time, elapsed > 12 * 60 * 60, true, true) + ' Uhr';
|
return formatDateTime(props.transaction.time, elapsed > 12 * 60 * 60, true, true) + ' Uhr';
|
||||||
});
|
});
|
||||||
|
|
||||||
return { timeStr, disabled, color, reverse };
|
return { timeStr, reverse, isNegative, text, refreshText, canReverse, isReversed };
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -56,8 +56,9 @@
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
</q-card>
|
</q-card>
|
||||||
</div>
|
</div>
|
||||||
<div v-for="(transaction, index) in transactions" v-bind:key="index" class="col-sm-4 col-xs-6">
|
<div v-for="(transaction, index) in transactions" v-bind:key="index" class="col-md-4 col-sm-6">
|
||||||
<Transaction :transaction="transaction" @reversed="reversed" />
|
<!-- TODO: In Vue3 use v-model:transaction="..." -->
|
||||||
|
<Transaction :transaction.sync="transactions[index]" />
|
||||||
</div>
|
</div>
|
||||||
</q-page>
|
</q-page>
|
||||||
</template>
|
</template>
|
||||||
|
@ -80,7 +81,7 @@ export default defineComponent({
|
||||||
|
|
||||||
const amount = ref<number>(0);
|
const amount = ref<number>(0);
|
||||||
const showAddShortcut = ref(false);
|
const showAddShortcut = ref(false);
|
||||||
const transactions = ref<FG.Transaction[]>([]);
|
const transactions = computed(() => store.state.balance.transactions.slice().reverse());
|
||||||
const user = ref(store.state.user.currentUser);
|
const user = ref(store.state.user.currentUser);
|
||||||
const shortCuts = ref(store.state.balance.shortcuts);
|
const shortCuts = ref(store.state.balance.shortcuts);
|
||||||
|
|
||||||
|
@ -89,7 +90,7 @@ export default defineComponent({
|
||||||
);
|
);
|
||||||
|
|
||||||
function addShortcut() {
|
function addShortcut() {
|
||||||
void store.dispatch('balance/addShortcut', amount.value * -1);
|
if (amount.value != 0) void store.dispatch('balance/addShortcut', amount.value * -1);
|
||||||
}
|
}
|
||||||
function removeShortcut(shortcut: number) {
|
function removeShortcut(shortcut: number) {
|
||||||
void store.dispatch('balance/removeShortcut', shortcut);
|
void store.dispatch('balance/removeShortcut', shortcut);
|
||||||
|
@ -100,19 +101,9 @@ export default defineComponent({
|
||||||
function changeBalance(amount: number) {
|
function changeBalance(amount: number) {
|
||||||
store
|
store
|
||||||
.dispatch('balance/changeBalance', { amount: amount, user: user.value?.userid })
|
.dispatch('balance/changeBalance', { amount: amount, user: user.value?.userid })
|
||||||
.then((transaction: FG.Transaction) => {
|
|
||||||
if (transactions.value.length > 5) transactions.value.pop();
|
|
||||||
transaction.time = new Date(transaction.time);
|
|
||||||
transactions.value.unshift(transaction);
|
|
||||||
console.log(transactions.value);
|
|
||||||
})
|
|
||||||
.catch(err => console.log(err));
|
.catch(err => console.log(err));
|
||||||
}
|
}
|
||||||
|
|
||||||
function reversed(id: number) {
|
|
||||||
transactions.value = transactions.value.filter(t => t.id != id);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
user,
|
user,
|
||||||
addShortcut,
|
addShortcut,
|
||||||
|
@ -123,7 +114,6 @@ export default defineComponent({
|
||||||
amount,
|
amount,
|
||||||
showSelector,
|
showSelector,
|
||||||
shortCuts,
|
shortCuts,
|
||||||
reversed,
|
|
||||||
userUpdated
|
userUpdated
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,12 @@ export default defineComponent({
|
||||||
align: 'left',
|
align: 'left',
|
||||||
sortable: true
|
sortable: true
|
||||||
},
|
},
|
||||||
{ name: 'balance', label: 'Kontostand', field: 'balance' },
|
{
|
||||||
|
name: 'balance',
|
||||||
|
label: 'Kontostand',
|
||||||
|
field: 'balance',
|
||||||
|
format: (val: number) => val.toFixed(2)
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'limit',
|
name: 'limit',
|
||||||
label: 'Limit',
|
label: 'Limit',
|
||||||
|
|
|
@ -3,10 +3,7 @@
|
||||||
<q-page padding v-if="checkMain">
|
<q-page padding v-if="checkMain">
|
||||||
<q-card>
|
<q-card>
|
||||||
<q-card-section>
|
<q-card-section>
|
||||||
<q-list
|
<q-list v-for="(mainRoute, index) in mainRoutes" :key="'mainRoute' + index">
|
||||||
v-for="(mainRoute, index) in mainRoutes"
|
|
||||||
:key="'mainRoute' + index"
|
|
||||||
>
|
|
||||||
<essential-link
|
<essential-link
|
||||||
v-for="(route, index2) in mainRoute.children"
|
v-for="(route, index2) in mainRoute.children"
|
||||||
:key="'route' + index2"
|
:key="'route' + index2"
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
</q-card>
|
</q-card>
|
||||||
</div>
|
</div>
|
||||||
<div v-for="(transaction, index) in transactions" v-bind:key="index" class="col-sm-4 col-xs-6">
|
<div v-for="(transaction, index) in transactions" v-bind:key="index" class="col-sm-4 col-xs-6">
|
||||||
<Transaction :transaction="transaction" @reversed="reversed" />
|
<Transaction :transaction.sync="transactions[index]" />
|
||||||
</div>
|
</div>
|
||||||
</q-page>
|
</q-page>
|
||||||
</template>
|
</template>
|
||||||
|
@ -56,7 +56,7 @@ export default defineComponent({
|
||||||
const sender = ref(store.state.user.currentUser);
|
const sender = ref(store.state.user.currentUser);
|
||||||
const receiver = ref<FG.User | undefined>(undefined);
|
const receiver = ref<FG.User | undefined>(undefined);
|
||||||
const amount = ref<number>(0);
|
const amount = ref<number>(0);
|
||||||
const transactions = ref<FG.Transaction[]>([]);
|
const transactions = computed(() => store.state.balance.transactions.slice().reverse());
|
||||||
|
|
||||||
const sendDisabled = computed(() => {
|
const sendDisabled = computed(() => {
|
||||||
return !(
|
return !(
|
||||||
|
@ -75,10 +75,6 @@ export default defineComponent({
|
||||||
receiver.value = selectedUser;
|
receiver.value = selectedUser;
|
||||||
}
|
}
|
||||||
|
|
||||||
function reversed(id: number) {
|
|
||||||
transactions.value = transactions.value.filter(value => value.id != id);
|
|
||||||
}
|
|
||||||
|
|
||||||
function sendAmount() {
|
function sendAmount() {
|
||||||
store
|
store
|
||||||
.dispatch('balance/changeBalance', {
|
.dispatch('balance/changeBalance', {
|
||||||
|
@ -86,11 +82,6 @@ export default defineComponent({
|
||||||
sender: sender.value?.userid,
|
sender: sender.value?.userid,
|
||||||
user: receiver.value?.userid
|
user: receiver.value?.userid
|
||||||
})
|
})
|
||||||
.then((transaction: FG.Transaction) => {
|
|
||||||
if (transactions.value.length > 5) transactions.value.pop();
|
|
||||||
transaction.time = new Date(transaction.time);
|
|
||||||
transactions.value.unshift(transaction);
|
|
||||||
})
|
|
||||||
.catch(err => console.log(err));
|
.catch(err => console.log(err));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,8 +94,7 @@ export default defineComponent({
|
||||||
showSelector,
|
showSelector,
|
||||||
senderUpdated,
|
senderUpdated,
|
||||||
receiverUpdated,
|
receiverUpdated,
|
||||||
sendDisabled,
|
sendDisabled
|
||||||
reversed
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -16,6 +16,7 @@ export interface UserBalance extends BalanceResponse {
|
||||||
export interface BalanceInterface {
|
export interface BalanceInterface {
|
||||||
balances: Map<string, UserBalance>;
|
balances: Map<string, UserBalance>;
|
||||||
shortcuts: Array<number>;
|
shortcuts: Array<number>;
|
||||||
|
transactions: Array<FG.Transaction>;
|
||||||
loading: number;
|
loading: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,6 +27,7 @@ export interface StateInterfaceBalance extends StateInterface {
|
||||||
const state: BalanceInterface = {
|
const state: BalanceInterface = {
|
||||||
balances: new Map<string, UserBalance>(),
|
balances: new Map<string, UserBalance>(),
|
||||||
shortcuts: [],
|
shortcuts: [],
|
||||||
|
transactions: [],
|
||||||
loading: 0
|
loading: 0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -53,6 +55,15 @@ const mutations: MutationTree<BalanceInterface> = {
|
||||||
},
|
},
|
||||||
setShortcuts(state, data: Array<number>) {
|
setShortcuts(state, data: Array<number>) {
|
||||||
state.shortcuts.splice(0, state.shortcuts.length, ...data);
|
state.shortcuts.splice(0, state.shortcuts.length, ...data);
|
||||||
|
},
|
||||||
|
addTransaction(state, data: FG.Transaction) {
|
||||||
|
state.transactions.push(data);
|
||||||
|
},
|
||||||
|
reverseTransaction(state, data: { transaction: FG.Transaction; reversal: FG.Transaction }) {
|
||||||
|
const idx = state.transactions.findIndex(value => value.id === data.transaction.id);
|
||||||
|
data.transaction.reversal = data.reversal;
|
||||||
|
if (idx > -1) state.transactions[idx] = data.transaction;
|
||||||
|
else state.transactions.push(data.transaction);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -111,8 +122,11 @@ const actions: ActionTree<BalanceInterface, StateInterface> = {
|
||||||
})
|
})
|
||||||
.finally(() => commit('setLoading', false));
|
.finally(() => commit('setLoading', false));
|
||||||
},
|
},
|
||||||
revert({ dispatch }, transaction: FG.Transaction) {
|
revert({ dispatch, commit }, transaction: FG.Transaction) {
|
||||||
return axios.delete(`/balance/${transaction.id}`).then(() => {
|
return axios
|
||||||
|
.delete(`/balance/${transaction.id}`)
|
||||||
|
.then((response: AxiosResponse<FG.Transaction>) => {
|
||||||
|
commit('reverseTransaction', { transaction: transaction, reversal: response.data });
|
||||||
dispatch('getBalance').catch(err => console.warn(err));
|
dispatch('getBalance').catch(err => console.warn(err));
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -121,6 +135,9 @@ const actions: ActionTree<BalanceInterface, StateInterface> = {
|
||||||
return axios
|
return axios
|
||||||
.put(`/users/${data.user}/balance`, data)
|
.put(`/users/${data.user}/balance`, data)
|
||||||
.then((response: AxiosResponse<FG.Transaction>) => {
|
.then((response: AxiosResponse<FG.Transaction>) => {
|
||||||
|
const transaction = response.data;
|
||||||
|
transaction.time = new Date(transaction.time);
|
||||||
|
commit('addTransaction', transaction);
|
||||||
commit(state.balances.has(data.user) ? 'changeBalance' : 'setBalance', {
|
commit(state.balances.has(data.user) ? 'changeBalance' : 'setBalance', {
|
||||||
userid: data.user,
|
userid: data.user,
|
||||||
amount: data.amount
|
amount: data.amount
|
||||||
|
@ -130,12 +147,12 @@ const actions: ActionTree<BalanceInterface, StateInterface> = {
|
||||||
userid: data.sender,
|
userid: data.sender,
|
||||||
amount: -1 * data.amount
|
amount: -1 * data.amount
|
||||||
});
|
});
|
||||||
return response.data;
|
return transaction;
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
|
console.debug(err);
|
||||||
// Maybe Balance changed
|
// Maybe Balance changed
|
||||||
dispatch('getBalance').catch(err => console.warn(err));
|
return dispatch('getBalance', data.sender ? data.sender : data.user);
|
||||||
console.warn(err);
|
|
||||||
})
|
})
|
||||||
.finally(() => commit('setLoading', false));
|
.finally(() => commit('setLoading', false));
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,16 +5,10 @@
|
||||||
Benutzereinstellungen
|
Benutzereinstellungen
|
||||||
</div>
|
</div>
|
||||||
<div class="col-xs-12 col-sm-6 q-pa-sm">
|
<div class="col-xs-12 col-sm-6 q-pa-sm">
|
||||||
<UserSelector
|
<UserSelector :user="user" @update:user="userUpdated" />
|
||||||
:user="user"
|
|
||||||
@update:user="userUpdated"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
<MainUserSettings
|
<MainUserSettings :user="user" @update:user="updateUser" />
|
||||||
:user="user"
|
|
||||||
@update:user="updateUser"
|
|
||||||
/>
|
|
||||||
</q-card>
|
</q-card>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -39,7 +33,7 @@ export default defineComponent({
|
||||||
};
|
};
|
||||||
|
|
||||||
function updateUser(value: FG.User) {
|
function updateUser(value: FG.User) {
|
||||||
store.dispatch('user/updateUser', value).catch((error) => {
|
store.dispatch('user/updateUser', value).catch(error => {
|
||||||
console.warn(error);
|
console.warn(error);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -47,9 +41,9 @@ export default defineComponent({
|
||||||
return {
|
return {
|
||||||
user,
|
user,
|
||||||
userUpdated,
|
userUpdated,
|
||||||
updateUser,
|
updateUser
|
||||||
};
|
};
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -9,12 +9,16 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-8">
|
<div class="col-8">
|
||||||
<span class="text-h6">Hallo {{ name }}</span><br />
|
<span class="text-h6">Hallo {{ name }}</span
|
||||||
|
><br />
|
||||||
<span v-if="hasBirthday">Herzlichen Glückwunsch zum Geburtstag!<br /></span>
|
<span v-if="hasBirthday">Herzlichen Glückwunsch zum Geburtstag!<br /></span>
|
||||||
<span v-if="birthday.length > 0">Heute <span v-if="birthday.length === 1">hat </span><span v-else>haben </span><span
|
<span v-if="birthday.length > 0"
|
||||||
v-for="(user, index) in birthday"
|
>Heute <span v-if="birthday.length === 1">hat </span><span v-else>haben </span
|
||||||
v-bind:key="index"
|
><span v-for="(user, index) in birthday" v-bind:key="index"
|
||||||
>{{user.display_name}}<span v-if="index < (birthday.length-1)">, </span></span> Geburtstag.</span>
|
>{{ user.display_name }}<span v-if="index < birthday.length - 1">, </span></span
|
||||||
|
>
|
||||||
|
Geburtstag.</span
|
||||||
|
>
|
||||||
<span v-else>Heute stehen keine Geburtstage an</span>
|
<span v-else>Heute stehen keine Geburtstage an</span>
|
||||||
</div>
|
</div>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
|
@ -22,12 +26,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import {
|
import { computed, defineComponent, onMounted, ref } from '@vue/composition-api';
|
||||||
computed,
|
|
||||||
defineComponent,
|
|
||||||
onMounted,
|
|
||||||
ref,
|
|
||||||
} from '@vue/composition-api';
|
|
||||||
import { Store } from 'vuex';
|
import { Store } from 'vuex';
|
||||||
import { StateInterface } from 'src/store';
|
import { StateInterface } from 'src/store';
|
||||||
|
|
||||||
|
@ -57,10 +56,10 @@ export default defineComponent({
|
||||||
const birthday = computed(() =>
|
const birthday = computed(() =>
|
||||||
store.state.user.users
|
store.state.user.users
|
||||||
.filter(userHasBirthday)
|
.filter(userHasBirthday)
|
||||||
.filter((user) => user.userid !== store.state.user.currentUser?.userid)
|
.filter(user => user.userid !== store.state.user.currentUser?.userid)
|
||||||
);
|
);
|
||||||
|
|
||||||
return { avatarLink, name, hasBirthday, birthday };
|
return { avatarLink, name, hasBirthday, birthday };
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -2,9 +2,7 @@
|
||||||
<div>
|
<div>
|
||||||
<q-card class="col-12">
|
<q-card class="col-12">
|
||||||
<q-form @submit="save" @reset="reset">
|
<q-form @submit="save" @reset="reset">
|
||||||
<q-card-section
|
<q-card-section class="fit row justify-start content-center items-center">
|
||||||
class="fit row justify-start content-center items-center"
|
|
||||||
>
|
|
||||||
<span class="col-xs-12 col-sm-6 text-center text-h6">
|
<span class="col-xs-12 col-sm-6 text-center text-h6">
|
||||||
Rollen und Berechtigungen
|
Rollen und Berechtigungen
|
||||||
</span>
|
</span>
|
||||||
|
@ -26,17 +24,9 @@
|
||||||
/>
|
/>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
<q-separator />
|
<q-separator />
|
||||||
<q-card-section
|
<q-card-section v-if="role" class="fit row justify-start content-center items-center">
|
||||||
v-if="role"
|
|
||||||
class="fit row justify-start content-center items-center"
|
|
||||||
>
|
|
||||||
<q-scroll-area style="height: 20em; width: 100%">
|
<q-scroll-area style="height: 20em; width: 100%">
|
||||||
<q-input
|
<q-input filled v-model="newRoleName" label="neuer Name" v-if="role.id != -1" />
|
||||||
filled
|
|
||||||
v-model="newRoleName"
|
|
||||||
label="neuer Name"
|
|
||||||
v-if="role.id != -1"
|
|
||||||
/>
|
|
||||||
<q-option-group
|
<q-option-group
|
||||||
:value="role.permissions"
|
:value="role.permissions"
|
||||||
@input="updatePermissions"
|
@input="updatePermissions"
|
||||||
|
@ -57,12 +47,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import {
|
import { computed, defineComponent, ref, onBeforeMount } from '@vue/composition-api';
|
||||||
computed,
|
|
||||||
defineComponent,
|
|
||||||
ref,
|
|
||||||
onBeforeMount,
|
|
||||||
} from '@vue/composition-api';
|
|
||||||
import { Store } from 'vuex';
|
import { Store } from 'vuex';
|
||||||
import { StateInterface } from 'src/store';
|
import { StateInterface } from 'src/store';
|
||||||
|
|
||||||
|
@ -72,10 +57,10 @@ export default defineComponent({
|
||||||
const store = <Store<StateInterface>>root.$store;
|
const store = <Store<StateInterface>>root.$store;
|
||||||
|
|
||||||
onBeforeMount(() => {
|
onBeforeMount(() => {
|
||||||
store.dispatch('user/getRoles').catch((error) => {
|
store.dispatch('user/getRoles').catch(error => {
|
||||||
console.warn(error);
|
console.warn(error);
|
||||||
});
|
});
|
||||||
store.dispatch('user/getPermissions').catch((error) => {
|
store.dispatch('user/getPermissions').catch(error => {
|
||||||
console.warn(error);
|
console.warn(error);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -83,20 +68,17 @@ export default defineComponent({
|
||||||
const role = ref<FG.Role | null>(null);
|
const role = ref<FG.Role | null>(null);
|
||||||
const roles = computed(() => store.state.user.roles);
|
const roles = computed(() => store.state.user.roles);
|
||||||
const permissions = computed(() =>
|
const permissions = computed(() =>
|
||||||
store.state.user.permissions.map((perm) => {
|
store.state.user.permissions.map(perm => {
|
||||||
return {
|
return {
|
||||||
value: perm,
|
value: perm,
|
||||||
label: perm,
|
label: perm
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
const newRoleName = ref<string>('');
|
const newRoleName = ref<string>('');
|
||||||
|
|
||||||
function createRole(
|
function createRole(name: string, done: (arg0: string, arg1: string) => void): void {
|
||||||
name: string,
|
|
||||||
done: (arg0: string, arg1: string) => void
|
|
||||||
): void {
|
|
||||||
role.value = { name: name, permissions: [], id: -1 };
|
role.value = { name: name, permissions: [], id: -1 };
|
||||||
done(name, 'add-unique');
|
done(name, 'add-unique');
|
||||||
}
|
}
|
||||||
|
@ -116,16 +98,14 @@ export default defineComponent({
|
||||||
role.value = {
|
role.value = {
|
||||||
id: rl.id,
|
id: rl.id,
|
||||||
name: rl.name,
|
name: rl.name,
|
||||||
permissions: Array.from(rl.permissions),
|
permissions: Array.from(rl.permissions)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function save() {
|
function save() {
|
||||||
if (role.value) {
|
if (role.value) {
|
||||||
if (role.value.id === -1)
|
if (role.value.id === -1)
|
||||||
void store
|
void store.dispatch('user/newRole', role.value).then((createdRole: FG.Role) => {
|
||||||
.dispatch('user/newRole', role.value)
|
|
||||||
.then((createdRole: FG.Role) => {
|
|
||||||
console.log(createdRole);
|
console.log(createdRole);
|
||||||
role.value = createdRole;
|
role.value = createdRole;
|
||||||
});
|
});
|
||||||
|
@ -139,9 +119,7 @@ export default defineComponent({
|
||||||
|
|
||||||
function reset() {
|
function reset() {
|
||||||
if (role.value && role.value.id !== -1) {
|
if (role.value && role.value.id !== -1) {
|
||||||
const original = roles.value.find(
|
const original = roles.value.find(value => value.name === role.value?.name);
|
||||||
(value) => value.name === role.value?.name
|
|
||||||
);
|
|
||||||
if (original) updateRole(original);
|
if (original) updateRole(original);
|
||||||
} else {
|
} else {
|
||||||
role.value = null;
|
role.value = null;
|
||||||
|
@ -156,7 +134,7 @@ export default defineComponent({
|
||||||
store
|
store
|
||||||
.dispatch('user/deleteRole', role.value)
|
.dispatch('user/deleteRole', role.value)
|
||||||
.then(() => (role.value = null))
|
.then(() => (role.value = null))
|
||||||
.catch((error) => console.warn(error));
|
.catch(error => console.warn(error));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -172,8 +150,8 @@ export default defineComponent({
|
||||||
reset,
|
reset,
|
||||||
removeRole,
|
removeRole,
|
||||||
remove,
|
remove,
|
||||||
newRoleName,
|
newRoleName
|
||||||
};
|
};
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -16,30 +16,42 @@
|
||||||
{{ session.platform }}
|
{{ session.platform }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row" v-if="!isEdit">
|
||||||
<div class="col-xs-12 col-sm-6">
|
<div class="col-xs-12 col-sm-6">
|
||||||
Lebenszeit:
|
Lebenszeit:
|
||||||
{{ session.lifetime }}
|
{{ session.lifetime }}
|
||||||
</div>
|
</div>
|
||||||
<div class="col-xs-12 col-sm-6">
|
<div class="col-xs-12 col-sm-6">Läuft aus: {{ session.expires | dateTime(true) }}</div>
|
||||||
Läuft aus: {{ session.expires | dateTime(true) }}
|
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row q-my-sm" v-else>
|
||||||
|
<q-input
|
||||||
|
class="col-xs-12 col-sm-6 q-px-sm"
|
||||||
|
v-model="computedLifetime"
|
||||||
|
type="number"
|
||||||
|
label="Zeit"
|
||||||
|
filled
|
||||||
|
/>
|
||||||
|
<q-select
|
||||||
|
class="col-xs-12 col-sm-6 q-px-sm"
|
||||||
|
:options="options"
|
||||||
|
v-model="option"
|
||||||
|
filled
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</q-card-section>
|
</q-card-section>
|
||||||
<q-card-actions align="right">
|
<q-card-actions align="right" v-if="!isEdit">
|
||||||
<q-btn
|
<q-btn flat round dense icon="mdi-pencil" @click="edit(true)" />
|
||||||
flat
|
<q-btn flat round dense icon="mdi-delete" @click="deleteSession(session.token)" />
|
||||||
round
|
</q-card-actions>
|
||||||
dense
|
<q-card-actions align="right" v-else>
|
||||||
icon="mdi-delete"
|
<q-btn flat dense label="Abbrechen" @click="edit(false)" />
|
||||||
@click="deleteSession(session.token)"
|
<q-btn flat dense label="Speichern" @click="save" />
|
||||||
/>
|
|
||||||
</q-card-actions>
|
</q-card-actions>
|
||||||
</q-card>
|
</q-card>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from '@vue/composition-api';
|
import { defineComponent, ref, computed } from '@vue/composition-api';
|
||||||
import { Store } from 'vuex';
|
import { Store } from 'vuex';
|
||||||
import { StateInterface } from 'src/store';
|
import { StateInterface } from 'src/store';
|
||||||
|
|
||||||
|
@ -47,12 +59,14 @@ export default defineComponent({
|
||||||
name: 'Sessions',
|
name: 'Sessions',
|
||||||
props: {
|
props: {
|
||||||
session: {
|
session: {
|
||||||
required: true
|
required: true,
|
||||||
}
|
|
||||||
},
|
},
|
||||||
setup(_, { root }) {
|
},
|
||||||
|
setup(props: {session: FG.Session}, { root }) {
|
||||||
const store = <Store<StateInterface>>root.$store;
|
const store = <Store<StateInterface>>root.$store;
|
||||||
|
const options = ref(['Minuten', 'Stunden', 'Tage']);
|
||||||
|
const option = ref<string>(options.value[0]);
|
||||||
|
const lifetime = ref(0);
|
||||||
function getBrowserIcon(browser: string) {
|
function getBrowserIcon(browser: string) {
|
||||||
return browser == 'firefox'
|
return browser == 'firefox'
|
||||||
? 'mdi-firefox'
|
? 'mdi-firefox'
|
||||||
|
@ -78,7 +92,7 @@ export default defineComponent({
|
||||||
}
|
}
|
||||||
|
|
||||||
function deleteSession(token: string) {
|
function deleteSession(token: string) {
|
||||||
store.dispatch('session/deleteSession', token).catch(error => {
|
store.dispatch('session/deleteSession', token).catch((error) => {
|
||||||
console.warn(error);
|
console.warn(error);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -86,12 +100,67 @@ export default defineComponent({
|
||||||
return store.state.session.currentSession?.token === token;
|
return store.state.session.currentSession?.token === token;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isEdit = ref(false);
|
||||||
|
|
||||||
|
const computedLifetime = computed({
|
||||||
|
get: () => {
|
||||||
|
switch (option.value) {
|
||||||
|
case options.value[0]:
|
||||||
|
return (lifetime.value / 60).toFixed(2);
|
||||||
|
case options.value[1]:
|
||||||
|
return (lifetime.value / (60 * 60)).toFixed(2);
|
||||||
|
case options.value[2]:
|
||||||
|
return (lifetime.value / (60 * 60 * 24)).toFixed(2);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
set: (val) => {
|
||||||
|
if (val) {
|
||||||
|
switch (option.value) {
|
||||||
|
case options.value[0]:
|
||||||
|
lifetime.value = parseFloat(val) * 60;
|
||||||
|
break;
|
||||||
|
case options.value[1]:
|
||||||
|
lifetime.value = parseFloat(val) * 60 * 60;
|
||||||
|
break;
|
||||||
|
case options.value[2]:
|
||||||
|
lifetime.value = parseFloat(val) * 60 * 60 * 24;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
function edit(value: boolean) {
|
||||||
|
lifetime.value = props.session.lifetime;
|
||||||
|
isEdit.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
function save() {
|
||||||
|
console.log(lifetime.value);
|
||||||
|
isEdit.value = false;
|
||||||
|
void store
|
||||||
|
.dispatch(
|
||||||
|
'session/updateSession',
|
||||||
|
{lifetime: lifetime.value, token: props.session.token}
|
||||||
|
)
|
||||||
|
.catch((error) => {
|
||||||
|
console.log(error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
getBrowserIcon,
|
getBrowserIcon,
|
||||||
getPlatformIcon,
|
getPlatformIcon,
|
||||||
isThisSession,
|
isThisSession,
|
||||||
deleteSession
|
deleteSession,
|
||||||
|
isEdit,
|
||||||
|
edit,
|
||||||
|
options,
|
||||||
|
option,
|
||||||
|
lifetime,
|
||||||
|
computedLifetime,
|
||||||
|
save,
|
||||||
};
|
};
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<q-tabs
|
<q-tabs v-model="tab" v-if="$q.screen.gt.sm">
|
||||||
v-model="tab"
|
|
||||||
v-if="$q.screen.gt.sm"
|
|
||||||
>
|
|
||||||
<q-tab
|
<q-tab
|
||||||
v-for="(tabindex, index) in tabs"
|
v-for="(tabindex, index) in tabs"
|
||||||
:key="'tab' + index"
|
:key="'tab' + index"
|
||||||
|
@ -11,23 +8,10 @@
|
||||||
:label="tabindex.label"
|
:label="tabindex.label"
|
||||||
/>
|
/>
|
||||||
</q-tabs>
|
</q-tabs>
|
||||||
<div
|
<div class="fit row justify-end" v-else>
|
||||||
class="fit row justify-end"
|
<q-btn flat round icon="mdi-menu" @click="showDrawer = !showDrawer" />
|
||||||
v-else
|
|
||||||
>
|
|
||||||
<q-btn
|
|
||||||
flat
|
|
||||||
round
|
|
||||||
icon="mdi-menu"
|
|
||||||
@click="showDrawer = !showDrawer"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<q-drawer
|
<q-drawer side="right" v-model="showDrawer" @click="showDrawer = !showDrawer" behavior="mobile">
|
||||||
side="right"
|
|
||||||
v-model="showDrawer"
|
|
||||||
@click="showDrawer = !showDrawer"
|
|
||||||
behavior="mobile"
|
|
||||||
>
|
|
||||||
<q-list v-model="tab">
|
<q-list v-model="tab">
|
||||||
<q-item
|
<q-item
|
||||||
v-for="(tabindex, index) in tabs"
|
v-for="(tabindex, index) in tabs"
|
||||||
|
@ -40,10 +24,7 @@
|
||||||
</q-item>
|
</q-item>
|
||||||
</q-list>
|
</q-list>
|
||||||
</q-drawer>
|
</q-drawer>
|
||||||
<q-page
|
<q-page padding class="fit row justify-center content-start items-start q-gutter-sm">
|
||||||
padding
|
|
||||||
class="fit row justify-center content-start items-start q-gutter-sm"
|
|
||||||
>
|
|
||||||
<q-tab-panels
|
<q-tab-panels
|
||||||
v-model="tab"
|
v-model="tab"
|
||||||
style="background-color: transparent;"
|
style="background-color: transparent;"
|
||||||
|
@ -81,9 +62,7 @@ export default defineComponent({
|
||||||
setup(_, { root }) {
|
setup(_, { root }) {
|
||||||
const store = <Store<StateInterface>>root.$store;
|
const store = <Store<StateInterface>>root.$store;
|
||||||
|
|
||||||
const canEditRoles = computed(() =>
|
const canEditRoles = computed(() => hasPermission(PERMISSIONS.ROLES_EDIT, store));
|
||||||
hasPermission(PERMISSIONS.ROLES_EDIT, store)
|
|
||||||
);
|
|
||||||
|
|
||||||
interface Tab {
|
interface Tab {
|
||||||
name: string;
|
name: string;
|
||||||
|
@ -93,7 +72,7 @@ export default defineComponent({
|
||||||
const tabs: Tab[] = [
|
const tabs: Tab[] = [
|
||||||
{ name: 'user', label: 'Mitglieder' },
|
{ name: 'user', label: 'Mitglieder' },
|
||||||
{ name: 'newUser', label: 'Neues Mitglied' },
|
{ name: 'newUser', label: 'Neues Mitglied' },
|
||||||
{ name: 'roles', label: 'Rollen' },
|
{ name: 'roles', label: 'Rollen' }
|
||||||
];
|
];
|
||||||
|
|
||||||
const drawer = ref<boolean>(false);
|
const drawer = ref<boolean>(false);
|
||||||
|
@ -104,7 +83,7 @@ export default defineComponent({
|
||||||
},
|
},
|
||||||
set: (val: boolean) => {
|
set: (val: boolean) => {
|
||||||
drawer.value = val;
|
drawer.value = val;
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const tab = ref<string>('user');
|
const tab = ref<string>('user');
|
||||||
|
@ -113,8 +92,8 @@ export default defineComponent({
|
||||||
canEditRoles,
|
canEditRoles,
|
||||||
showDrawer,
|
showDrawer,
|
||||||
tab,
|
tab,
|
||||||
tabs,
|
tabs
|
||||||
};
|
};
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -3,10 +3,7 @@
|
||||||
<q-page padding v-if="checkMain">
|
<q-page padding v-if="checkMain">
|
||||||
<q-card>
|
<q-card>
|
||||||
<q-card-section>
|
<q-card-section>
|
||||||
<q-list
|
<q-list v-for="(mainRoute, index) in mainRoutes" :key="'mainRoute' + index">
|
||||||
v-for="(mainRoute, index) in mainRoutes"
|
|
||||||
:key="'mainRoute' + index"
|
|
||||||
>
|
|
||||||
<essential-link
|
<essential-link
|
||||||
v-for="(route, index2) in mainRoute.children"
|
v-for="(route, index2) in mainRoute.children"
|
||||||
:key="'route' + index2"
|
:key="'route' + index2"
|
||||||
|
|
|
@ -14,12 +14,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import {
|
import { computed, defineComponent, onBeforeMount, ref } from '@vue/composition-api';
|
||||||
computed,
|
|
||||||
defineComponent,
|
|
||||||
onBeforeMount,
|
|
||||||
ref
|
|
||||||
} from '@vue/composition-api';
|
|
||||||
import Sessions from '../components/settings/Sessions.vue';
|
import Sessions from '../components/settings/Sessions.vue';
|
||||||
import MainUserSettings from '../components/settings/MainUserSettings.vue';
|
import MainUserSettings from '../components/settings/MainUserSettings.vue';
|
||||||
import { Store } from 'vuex';
|
import { Store } from 'vuex';
|
||||||
|
@ -40,9 +35,7 @@ export default defineComponent({
|
||||||
|
|
||||||
const currentUser = ref(<FG.User>store.state.user.currentUser);
|
const currentUser = ref(<FG.User>store.state.user.currentUser);
|
||||||
const sessions = computed(() => store.state.session.sessions);
|
const sessions = computed(() => store.state.session.sessions);
|
||||||
const loading = computed(
|
const loading = computed(() => store.state.session.loading || store.state.user.loading > 0);
|
||||||
() => store.state.session.loading || store.state.user.loading > 0
|
|
||||||
);
|
|
||||||
function updateUser(value: FG.User) {
|
function updateUser(value: FG.User) {
|
||||||
store.dispatch('user/updateUser', value).catch(error => {
|
store.dispatch('user/updateUser', value).catch(error => {
|
||||||
console.warn(error);
|
console.warn(error);
|
||||||
|
|
|
@ -25,7 +25,7 @@ function loadCurrentSession() {
|
||||||
const state: SessionInterface = {
|
const state: SessionInterface = {
|
||||||
sessions: [],
|
sessions: [],
|
||||||
currentSession: loadCurrentSession() || undefined,
|
currentSession: loadCurrentSession() || undefined,
|
||||||
loading: false
|
loading: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
const mutations: MutationTree<SessionInterface> = {
|
const mutations: MutationTree<SessionInterface> = {
|
||||||
|
@ -42,7 +42,13 @@ const mutations: MutationTree<SessionInterface> = {
|
||||||
},
|
},
|
||||||
setLoading(state, value: boolean) {
|
setLoading(state, value: boolean) {
|
||||||
state.loading = value;
|
state.loading = value;
|
||||||
|
},
|
||||||
|
updateSession(state, session: FG.Session) {
|
||||||
|
const index = state.sessions.findIndex((x) => x.token == session.token);
|
||||||
|
if (index > -1) {
|
||||||
|
state.sessions[index] = session;
|
||||||
}
|
}
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const actions: ActionTree<SessionInterface, StateInterface> = {
|
const actions: ActionTree<SessionInterface, StateInterface> = {
|
||||||
|
@ -59,7 +65,7 @@ const actions: ActionTree<SessionInterface, StateInterface> = {
|
||||||
commit('setCurrentSession', response.data.session);
|
commit('setCurrentSession', response.data.session);
|
||||||
commit('user/setCurrentUser', response.data.user, { root: true });
|
commit('user/setCurrentUser', response.data.user, { root: true });
|
||||||
commit('user/setCurrentPermissions', response.data.permissions, {
|
commit('user/setCurrentPermissions', response.data.permissions, {
|
||||||
root: true
|
root: true,
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch((error: AxiosError) => {
|
.catch((error: AxiosError) => {
|
||||||
|
@ -72,7 +78,7 @@ const actions: ActionTree<SessionInterface, StateInterface> = {
|
||||||
*/
|
*/
|
||||||
logout({ dispatch, rootState }) {
|
logout({ dispatch, rootState }) {
|
||||||
if (rootState.session.currentSession) {
|
if (rootState.session.currentSession) {
|
||||||
dispatch('deleteSession', rootState.session.currentSession.token).catch(error => {
|
dispatch('deleteSession', rootState.session.currentSession.token).catch((error) => {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
void dispatch('clearCurrent', false);
|
void dispatch('clearCurrent', false);
|
||||||
});
|
});
|
||||||
|
@ -91,7 +97,7 @@ const actions: ActionTree<SessionInterface, StateInterface> = {
|
||||||
if (token === rootState.session.currentSession?.token) {
|
if (token === rootState.session.currentSession?.token) {
|
||||||
void dispatch('clearCurrent', false);
|
void dispatch('clearCurrent', false);
|
||||||
} else {
|
} else {
|
||||||
dispatch('getSessions').catch(error => {
|
dispatch('getSessions').catch((error) => {
|
||||||
throw error;
|
throw error;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -110,7 +116,7 @@ const actions: ActionTree<SessionInterface, StateInterface> = {
|
||||||
void Router.push({
|
void Router.push({
|
||||||
name: 'login',
|
name: 'login',
|
||||||
query: redirect ? { redirect: Router.currentRoute.fullPath } : {},
|
query: redirect ? { redirect: Router.currentRoute.fullPath } : {},
|
||||||
params: { logout: 'true' }
|
params: { logout: 'true' },
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
commit('clearCurrentSession');
|
commit('clearCurrentSession');
|
||||||
commit('user/clearCurrentUser', null, { root: true });
|
commit('user/clearCurrentUser', null, { root: true });
|
||||||
|
@ -126,7 +132,7 @@ const actions: ActionTree<SessionInterface, StateInterface> = {
|
||||||
axios
|
axios
|
||||||
.get('/auth')
|
.get('/auth')
|
||||||
.then((response: AxiosResponse<FG.Session[]>) => {
|
.then((response: AxiosResponse<FG.Session[]>) => {
|
||||||
response.data.forEach(session => {
|
response.data.forEach((session) => {
|
||||||
session.expires = new Date(session.expires);
|
session.expires = new Date(session.expires);
|
||||||
});
|
});
|
||||||
commit('setSessions', response.data);
|
commit('setSessions', response.data);
|
||||||
|
@ -137,13 +143,29 @@ const actions: ActionTree<SessionInterface, StateInterface> = {
|
||||||
commit('setCurrentSession', currentSession);
|
commit('setCurrentSession', currentSession);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch((error) => {
|
||||||
throw error;
|
throw error;
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
commit('setLoading', false);
|
commit('setLoading', false);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
updateSession({ commit, state }, data: { lifetime: number; token: string }) {
|
||||||
|
commit('setLoading', true);
|
||||||
|
axios
|
||||||
|
.put(`auth/${data.token}`, { value: data.lifetime })
|
||||||
|
.then((response: AxiosResponse<FG.Session>) => {
|
||||||
|
response.data.expires = new Date(response.data.expires);
|
||||||
|
if (state.currentSession?.token == response.data.token) {
|
||||||
|
commit('setCurrentSession', response.data);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => console.log(err))
|
||||||
|
.finally(() => {
|
||||||
|
commit('setLoading', false);
|
||||||
|
});
|
||||||
|
console.log('updateSession', data);
|
||||||
|
},
|
||||||
requestPasswordReset({}, data) {
|
requestPasswordReset({}, data) {
|
||||||
return axios.post('/auth/reset', data);
|
return axios.post('/auth/reset', data);
|
||||||
},
|
},
|
||||||
|
@ -151,7 +173,7 @@ const actions: ActionTree<SessionInterface, StateInterface> = {
|
||||||
return axios.post('/auth/reset', data).catch((error: AxiosError) => {
|
return axios.post('/auth/reset', data).catch((error: AxiosError) => {
|
||||||
return Promise.reject(error.response);
|
return Promise.reject(error.response);
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const getters: GetterTree<SessionInterface, StateInterface> = {
|
const getters: GetterTree<SessionInterface, StateInterface> = {
|
||||||
|
@ -163,7 +185,7 @@ const getters: GetterTree<SessionInterface, StateInterface> = {
|
||||||
},
|
},
|
||||||
loading(state) {
|
loading(state) {
|
||||||
return state.loading;
|
return state.loading;
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const sessions: Module<SessionInterface, StateInterface> = {
|
const sessions: Module<SessionInterface, StateInterface> = {
|
||||||
|
@ -171,7 +193,7 @@ const sessions: Module<SessionInterface, StateInterface> = {
|
||||||
state,
|
state,
|
||||||
mutations,
|
mutations,
|
||||||
actions,
|
actions,
|
||||||
getters
|
getters,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default sessions;
|
export default sessions;
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||||
import { Module, MutationTree, ActionTree, GetterTree } from 'vuex';
|
import { Module, MutationTree, ActionTree, GetterTree } from 'vuex';
|
||||||
import { StateInterface } from 'src/store';
|
import { StateInterface } from 'src/store';
|
||||||
import { axios } from 'boot/axios';
|
import { axios } from 'boot/axios';
|
||||||
|
@ -48,6 +49,11 @@ const mutations: MutationTree<UserStateInterface> = {
|
||||||
setUsers(state, data: FG.User[]) {
|
setUsers(state, data: FG.User[]) {
|
||||||
state.users = data;
|
state.users = data;
|
||||||
},
|
},
|
||||||
|
setUser(state, data: FG.User) {
|
||||||
|
const index = state.users.findIndex(x => x.userid === data.userid);
|
||||||
|
if (index > -1) state.users[index] = data;
|
||||||
|
else state.users.push(data);
|
||||||
|
},
|
||||||
setRoles(state, data: FG.Role[]) {
|
setRoles(state, data: FG.Role[]) {
|
||||||
state.roles = data;
|
state.roles = data;
|
||||||
},
|
},
|
||||||
|
@ -221,10 +227,26 @@ const actions: ActionTree<UserStateInterface, StateInterface> = {
|
||||||
commit('setPermissions', response.data);
|
commit('setPermissions', response.data);
|
||||||
})
|
})
|
||||||
.finally(() => commit('setLoading', false));
|
.finally(() => commit('setLoading', false));
|
||||||
|
},
|
||||||
|
getUser({ commit, getters }, data: { userid: string; force?: boolean }) {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
||||||
|
const user = <FG.User | undefined>getters['getUser'](data.userid);
|
||||||
|
if (user === undefined || data.force === true) {
|
||||||
|
return axios.get(`/users/${data.userid}`).then((response: AxiosResponse<FG.User>) => {
|
||||||
|
commit('setUser', response.data);
|
||||||
|
return response.data;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return Promise.resolve(user);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const getters: GetterTree<UserStateInterface, StateInterface> = {
|
const getters: GetterTree<UserStateInterface, StateInterface> = {
|
||||||
|
getUser: state => (userid: string) => {
|
||||||
|
const user = state.users.filter(usr => usr.userid === userid);
|
||||||
|
return user.length > 0 ? user[0] : undefined;
|
||||||
|
},
|
||||||
currentUser({ currentUser }) {
|
currentUser({ currentUser }) {
|
||||||
return currentUser;
|
return currentUser;
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue