Skip to content

Commit

Permalink
Address #2
Browse files Browse the repository at this point in the history
  • Loading branch information
TobiasDeBruijn committed Sep 5, 2024
1 parent 3204d5c commit e6fbebe
Show file tree
Hide file tree
Showing 6 changed files with 133 additions and 51 deletions.
11 changes: 6 additions & 5 deletions frontend/src/layouts/AuthorizedAdminMiddleware.vue
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
<template>
<v-app>
<v-main v-if="error != null">
<v-alert
v-if="error != null"
icon="mdi-alert-circle-outline"
title="Login failed"
<MaterialBanner
:text="error"
icon="mdi-alert-circle-outline"
type="error"
title="Login"
@close="error = null"
/>
</v-main>

Expand All @@ -24,6 +24,7 @@ import {defineComponent} from "vue";
import RouterView from "./components/RouterView.vue";
import AppBar from "./components/AppBar.vue";
import {checkLogin} from "@/layouts/authorized";
import MaterialBanner from "@/views/components/MaterialBanner.vue";
interface Data {
error: string | null,
Expand All @@ -32,7 +33,7 @@ interface Data {
}
export default defineComponent({
components: {AppBar, RouterView},
components: {MaterialBanner, AppBar, RouterView},
data(): Data {
return {
error: null,
Expand Down
11 changes: 6 additions & 5 deletions frontend/src/layouts/AuthorizedMiddleware.vue
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
<template>
<v-app>
<v-main v-if="error != null">
<v-alert
v-if="error != null"
icon="mdi-alert-circle-outline"
title="Login failed"
<MaterialBanner
:text="error"
icon="mdi-alert-circle-outline"
type="error"
title="Login"
@close="error = null"
/>
</v-main>

Expand All @@ -24,6 +24,7 @@ import {defineComponent} from "vue";
import RouterView from "./components/RouterView.vue";
import AppBar from "./components/AppBar.vue";
import {checkLogin} from "@/layouts/authorized";
import MaterialBanner from "@/views/components/MaterialBanner.vue";
interface Data {
error: string | null,
Expand All @@ -32,7 +33,7 @@ interface Data {
}
export default defineComponent({
components: {AppBar, RouterView},
components: {MaterialBanner, AppBar, RouterView},
data(): Data {
return {
error: null,
Expand Down
7 changes: 4 additions & 3 deletions frontend/src/plugins/locales/locale.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,17 @@ export interface Locale {
title: string;
subtitle: string;
message: string;
toBoard: string;
toAdvisors: string;
selectAdvisors: string;
toReceivers: string;
selectReceivers: string;
allowContact: string;
contactEmail: string;
contactEmailExplanation: string;
submit: string;
required: string;
invalidEmail: string;
invalid: string;
selectRecipient: string;
board: string;
},
success: string;
}
Expand Down
13 changes: 7 additions & 6 deletions frontend/src/plugins/locales/nl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const NL: Locale = {
home: {
welcome: {
title: "Welkom bij het anonieme meldpunt van Sticky",
subtitle: "Je kunt hier volledig annoniem een melding maken van ongewenst gedrag en sexueel wangedrag. Je kunt deze melding versturen aan het bestuur of (een van de) vertrouwenscontactpersonen, dat is aan jou. Ook kun je er voor kiezen dat er contact met je mogen worden opgenomen als je graag terugkoppeling wilt, uiteraard is dit niet verplicht."
subtitle: "Je kunt hier volledig annoniem een melding maken van ongewenst gedrag en sexueel wangedrag. Je kunt deze melding versturen aan het bestuur of (een van de) vertrouwenscontactpersonen, dat is aan jou. Ook kun je er voor kiezen dat er contact met je mag worden opgenomen als je graag terugkoppeling wilt, uiteraard is dit niet verplicht."
},
form: {
title: "Omschrijving van je melding",
Expand All @@ -16,12 +16,13 @@ const NL: Locale = {
invalidEmail: "Het opgegeven email adres is ongeldig",
required: "Vereist",
submit: "Melding versturen",
toAdvisors: "Wil je dat jouw bericht naar de vertrouwenscontactpersonen wordt verstuurd? Zo ja, selecteer welke",
toBoard: "Wil je dat jouw bericht naar het bestuur wordt verstuurd?",
selectAdvisors: "Selecteer vertrouwenscontactpersonen",
toReceivers: "Aan wie wil je dat jouw bericht wordt verstuurd?",
selectReceivers: "Selecteer..",
allowContact: "Wil je dat we contact met je opnemen naar aanleiding van je melding?",
contactEmail: "Email adres",
contactEmailExplanation: "Wil je dat er contact met je wordt opgenomen naar aanleiding van je melding? Zo ja, geef hier een email adres waarop je de terugkoppeling wilt ontvangen. Laat het veld leeg als je de melding volledig anoniem wilt houden",
selectRecipient: "Je melding heeft ten minste één ontvanger nodig."
contactEmailExplanation: "Geef hier een email adres waarop je de terugkoppeling wilt ontvangen. Laat het veld leeg als je de melding volledig anoniem wilt houden",
selectRecipient: "Je melding heeft ten minste één ontvanger nodig.",
board: "Het bestuur"
},
success: "Je melding is verzonden en wordt in behandeling genomen"
}
Expand Down
94 changes: 62 additions & 32 deletions frontend/src/views/HomeView.vue
Original file line number Diff line number Diff line change
@@ -1,23 +1,19 @@
<template>
<v-container>
<v-alert
v-if="error != null"
class="mt-2"
icon="mdi-alert-circle-outline"
title="Error"
<MaterialBanner
:text="error"
icon="mdi-alert-circle-outline"
type="error"
@click:close="error = null"
title="Error"
@close="error = null"
/>

<v-alert
v-if="success != null"
class="mt-2"
icon="mdi-send-check"
<MaterialBanner
title="Success"
:text="success"
type="success"
@click:close="success = null"
icon="mdi-send-check"
@close="success = null"
/>

<v-card>
Expand All @@ -44,37 +40,40 @@
<v-row align="center">
<v-col>
<p class="mb-2">
{{ $t('home.form.toBoard') }}
{{ $t('home.form.toReceivers') }}:
</p>
</v-col>
<v-col>
<v-checkbox
v-model="report.toBoard"
<v-select
v-model="report.toReceivers"
:label="$t('home.form.selectReceivers')"
:items="receivers"
return-object
multiple
color="primary"
item-title="name"
/>
</v-col>
</v-row>

<v-row align="center">
<v-col>
<p class="mb-2">
{{ $t('home.form.toAdvisors') }}:
{{ $t('home.form.allowContact') }}
</p>
</v-col>
<v-col>
<v-select
v-model="report.toAdvisors"
:label="$t('home.form.selectAdvisors')"
:items="advisors"
return-object
multiple
<v-checkbox
v-model="report.allowContact"
color="primary"
item-title="name"
/>
</v-col>
</v-row>

<v-row align="center">
<v-row
v-if="report.allowContact"
align="center"
>
<v-col>
<p class="mb-2">
{{ $t('home.form.contactEmailExplanation') }}:
Expand Down Expand Up @@ -112,39 +111,62 @@ import {defineComponent} from "vue";
import {ConfidentialAdvisor} from "@/scripts/config";
import {InputValidationRules} from "@/main";
import {Report} from "@/scripts/report"
import MaterialBanner from "@/views/components/MaterialBanner.vue"
interface Data {
error: string | null,
success: string | null,
report: {
valid: boolean,
message: string | null,
toBoard: boolean,
toAdvisors: ConfidentialAdvisor[],
toReceivers: Receiver[],
allowContact: boolean,
contactEmail: string | null,
loading: boolean,
},
advisors: ConfidentialAdvisor[],
receivers: Receiver[],
rules: {
required: InputValidationRules,
optionalEmail: InputValidationRules,
}
}
export class Receiver {
name: string;
inner: BoardReceiver | AdvisorReceiver;
receiverType: ReceiverType;
constructor(name: string, inner: BoardReceiver | AdvisorReceiver, receiverType: ReceiverType) {
this.name = name;
this.inner = inner;
this.receiverType = receiverType;
}
}
enum ReceiverType {
BOARD,
ADVISOR
}
class BoardReceiver {}
class AdvisorReceiver extends ConfidentialAdvisor {}
export default defineComponent({
components: {MaterialBanner},
data(): Data {
return {
error: null,
success: null,
report: {
valid: true,
message: null,
toBoard: false,
toAdvisors: [],
toReceivers: [],
allowContact: false,
contactEmail: null,
loading: false,
},
advisors: [],
receivers: [],
rules: {
required: [
v => !!v || this.$t("home.form.required")
Expand All @@ -166,21 +188,29 @@ export default defineComponent({
return;
}
this.advisors = r.unwrap();
this.receivers = r.unwrap().map(advisor => new Receiver(advisor.name, advisor, ReceiverType.ADVISOR));
this.receivers.push(new Receiver(this.$t('home.form.board'), new BoardReceiver(), ReceiverType.BOARD));
},
async submitForm() {
if(!this.report.valid) {
this.error = this.$t("home.form.invalid");
return;
}
if(this.report.toAdvisors.length == 0 && !this.report.toBoard) {
if(this.report.toReceivers.length == 0) {
this.error = this.$t("home.form.selectRecipient");
return;
}
const toAdvisors = this.report.toReceivers
.filter(v => v.receiverType == ReceiverType.ADVISOR)
.map(v => v.inner);
const toBoard = this.report.toReceivers
.filter(v => v.receiverType == ReceiverType.BOARD)
.length > 0;
this.report.loading = true;
const r = await Report.report(this.report.message!, this.report.toBoard, this.report.toAdvisors, this.report.contactEmail);
const r = await Report.report(this.report.message!, toBoard, toAdvisors, this.report.contactEmail);
this.report.loading = false;
if(r.isErr()) {
Expand Down
48 changes: 48 additions & 0 deletions frontend/src/views/components/MaterialBanner.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<template>
<v-alert
v-if="text != null"
class="mt-2"
:icon="icon"
:title="title"
:text="text"
:type="type"
@click:close="$emit('close')"
/>
</template>

<script lang="ts">
import {defineComponent} from "vue";
export default defineComponent({
props: {
icon: {
type: String,
required: true,
},
title: {
type: String,
required: true,
},
type: {
type: String,
required: true,
},
text: {
type: String,
required: false,
default: undefined,
}
},
emits: [
'close'
],
watch: {
text(val?: string) {
if(val) {
setTimeout(() => this.$emit('close'), 5000);
}
}
}
})
</script>

0 comments on commit e6fbebe

Please sign in to comment.