Skip to content

Commit

Permalink
feat: add data-export and improve the module structure for vaccinatio…
Browse files Browse the repository at this point in the history
…n reports
  • Loading branch information
mad-nuts committed Feb 25, 2022
1 parent 0c98c3d commit a8bc079
Show file tree
Hide file tree
Showing 20 changed files with 317 additions and 85 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,18 @@
<template>
<v-dialog v-model="dialog" max-width="500">
<template v-slot:activator="scope">
<slot name="activator" v-bind="scope" />
<template v-slot:activator="{ on, attrs }">
<slot name="activator" v-bind="{ on, attrs }">
<v-btn
v-on="on"
v-bind="attrs"
color="white"
:disabled="disabled"
data-test="export-dialog.activator"
>
Exportformat wählen
</v-btn>
</slot>
<slot name="activator.prepend" />
</template>
<v-card data-test="export-dialog">
<v-card-title> {{ title }} </v-card-title>
Expand All @@ -22,6 +33,7 @@
icon
@click="$emit(item.csv.action)"
:data-test="item.csv.test"
:disabled="disabled"
>
<v-icon> mdi-download </v-icon>
</v-btn>
Expand All @@ -32,6 +44,7 @@
icon
@click="$emit(item.xlsx.action)"
:data-test="item.xlsx.test"
:disabled="disabled"
>
<v-icon> mdi-download </v-icon>
</v-btn>
Expand All @@ -54,32 +67,36 @@
import { Component, Vue } from "vue-property-decorator";
import { PropType } from "vue";
export interface DataExportFormat {
interface DataExportAction {
action: string;
test: string;
}
export interface DataExportItem {
export interface DataExportFormat {
label: string;
csv?: DataExportFormat;
xlsx?: DataExportFormat;
csv?: DataExportAction;
xlsx?: DataExportAction;
}
const ExportDialogProps = Vue.extend({
const DataExportDialogProps = Vue.extend({
inheritAttrs: false,
props: {
title: {
type: String,
default: "Daten exportieren",
},
items: {
type: Array as PropType<DataExportItem[]>,
type: Array as PropType<DataExportFormat[]>,
default: () => [],
},
disabled: {
type: Boolean,
default: false,
},
},
});
@Component
export default class ExportDialog extends ExportDialogProps {
export default class DataExportDialog extends DataExportDialogProps {
dialog = false;
}
</script>
35 changes: 35 additions & 0 deletions iris-client-fe/src/components/data-export/data-export-label.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<script lang="ts">
/* eslint-disable @typescript-eslint/no-explicit-any */
import { Component, Vue } from "vue-property-decorator";
import { getExportLabel } from "@/utils/data-export/common";
import { PropType } from "vue";
const DataExportLabelProps = Vue.extend({
inheritAttrs: false,
props: {
selected: {
type: Number,
default: 0,
},
total: {
type: Number,
default: 0,
},
label: {
type: Array as PropType<string[] | null>,
default: null,
},
},
render() {
const defaultSlot = this.$scopedSlots.default;
if (!defaultSlot) return;
return defaultSlot({
exportLabel: getExportLabel(this.selected, this.total, this.label),
}) as any;
},
});
@Component({
name: "data-export-label",
})
export default class DataExportLabel extends DataExportLabelProps {}
</script>
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import asyncAction from "@/utils/asyncAction";
import {
normalizePageVaccinationReport,
normalizeVaccinationReportDetails,
} from "@/modules/vaccination-report/normalizer";
} from "@/modules/vaccination-report/services/normalizer";

const fetchPageVaccinationReport = () => {
const action = async (query: DataQuery) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
<template>
<data-export-label
:selected="selection.length"
:total="total"
:label="['Mitarbeiterdaten']"
#default="{ exportLabel }"
>
<data-export-dialog
:title="exportLabel"
:disabled="selection.length <= 0"
:items="exportFormatList"
@export-csv-standard="exportStandard('csv')"
@export-xlsx-standard="exportStandard('xlsx')"
>
<template #activator.prepend>
<v-btn
color="primary"
:disabled="selection.length <= 0"
data-test="export.default"
@click="exportStandard('csv')"
>
{{ exportLabel }}
</v-btn>
</template>
</data-export-dialog>
</data-export-label>
</template>

<script lang="ts">
import { Component, Vue } from "vue-property-decorator";
import { PropType } from "vue";
import { VaccinationReportDetails } from "@/api";
import InfoGrid from "@/components/info-grid.vue";
import DataExportLabel from "@/components/data-export/data-export-label.vue";
import DataExportDialog, {
DataExportFormat,
} from "@/components/data-export/data-export-dialog.vue";
import { ExportFileType } from "@/utils/data-export/data-export";
import { getFormattedDate } from "@/utils/date";
import { VREmployeeTableRow } from "@/modules/vaccination-report/views/details/vaccination-report-details.view.vue";
import exportStandard from "@/modules/vaccination-report/views/details/modules/data-export/services/exportStandard";
const VaccinationReportDataExportProps = Vue.extend({
inheritAttrs: false,
props: {
report: {
type: Object as PropType<VaccinationReportDetails | null>,
default: null,
},
selection: {
type: Array as PropType<VREmployeeTableRow[]>,
default: () => [],
},
total: {
type: Number,
default: 0,
},
},
});
@Component({
components: {
DataExportDialog,
DataExportLabel,
InfoGrid,
},
})
export default class VaccinationReportDataExport extends VaccinationReportDataExportProps {
exportFormatList: DataExportFormat[] = [
{
label: "Standard",
csv: {
action: "export-csv-standard",
test: "export.csv.standard",
},
xlsx: {
action: "export-xlsx-standard",
test: "export.xlsx.standard",
},
},
];
exportStandard(type: ExportFileType): void {
const fileName = [
this.report?.facility?.name || "Export",
getFormattedDate(new Date(), "YYYY-MM-DD_HHmm"),
].join("_");
const exporter =
type === "xlsx" ? exportStandard.exportXlsx : exportStandard.exportCsv;
exporter(this.selection, fileName);
}
}
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import dataExport, { Row } from "@/utils/data-export/data-export";
import { composeAddressHeader } from "@/utils/data-export/common";

const getHeaders = () => {
return [
{
text: "Vorname",
value: "firstName",
},
{
text: "Nachname",
value: "lastName",
},
composeAddressHeader(),
{
text: "Erreger",
value: "vaccination",
},
{
text: "Impfstatus",
value: "vaccinationStatus",
},
];
};

const exportCsv = (
rows: Row[],
fileName: string,
quoted?: boolean
): Promise<unknown> => {
const headers = getHeaders();
return dataExport.exportCsv(headers, rows, {
fileName,
quoted: quoted !== false,
});
};

const exportXlsx = (rows: Row[], fileName: string) => {
const headers = getHeaders();
return dataExport.exportXlsx(headers, rows, { fileName });
};

const exportStandard = {
exportCsv,
exportXlsx,
};

export default exportStandard;
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,15 @@
<v-card-text>
<vaccination-report-facility-info :facility="facility" />
<info-grid :content="dateInfo" />
<btn-toggle-select
class="my-5"
:select-options="statusSelectOptions"
v-model="status"
/>
<div class="my-6">
<span class="mr-3">
<strong>Status:</strong>
</span>
<btn-toggle-select
:select-options="statusSelectOptions"
v-model="status"
/>
</div>
<search-field :debounce="0" v-model="search" />
<sortable-data-table
v-model="selection"
Expand All @@ -34,6 +38,12 @@
</v-card-text>
<v-card-actions>
<v-btn text @click="goBack"> Zurück </v-btn>
<v-spacer />
<vaccination-report-data-export
:report="vaccinationReport"
:selection="selection"
:total="tableRows.length"
/>
</v-card-actions>
</v-card>
</template>
Expand All @@ -44,29 +54,32 @@ import DataQueryHandler from "@/components/pageable/data-query-handler.vue";
import SearchField from "@/components/pageable/search-field.vue";
import SortableDataTable from "@/components/sortable-data-table.vue";
import ErrorMessageAlert from "@/components/error-message-alert.vue";
import { vaccinationReportApi } from "@/modules/vaccination-report/api";
import { vaccinationReportApi } from "@/modules/vaccination-report/services/api";
import { VaccinationStatus, VREmployee } from "@/api";
import { getFormattedAddress } from "@/utils/address";
import IrisDataTable from "@/components/iris-data-table.vue";
import HistoryBack from "@/mixins/HistoryBack";
import vaccinationReportConstants from "@/modules/vaccination-report/constants";
import vaccinationReportConstants from "@/modules/vaccination-report/services/constants";
import InfoGrid from "@/components/info-grid.vue";
import { getFormattedDate } from "@/utils/date";
import { getEnumKeys } from "@/utils/data";
import BtnToggleSelect from "@/components/btn-toggle-select.vue";
import VaccinationReportFacilityInfo from "@/modules/vaccination-report/components/vaccination-report-facility-info.vue";
import VaccinationReportFacilityInfo from "@/modules/vaccination-report/views/details/components/vaccination-report-facility-info.vue";
import VaccinationReportDataExport from "@/modules/vaccination-report/views/details/modules/data-export/components/vaccination-report-data-export.vue";
type TableRow = {
export type VREmployeeTableRow = {
id: number | string;
lastName: string;
firstName: string;
address: string;
vaccination: string;
vaccinationStatus: string;
raw: VREmployee;
};
@Component({
components: {
VaccinationReportDataExport,
VaccinationReportFacilityInfo,
BtnToggleSelect,
InfoGrid,
Expand Down Expand Up @@ -97,8 +110,8 @@ export default class VaccinationReportDetailsView extends Mixins(
get filteredTableRows() {
return this.tableRows;
}
get tableRows(): TableRow[] {
const employees: VREmployee[] = this.vrApi.state.result?.employees || [];
get tableRows(): VREmployeeTableRow[] {
const employees: VREmployee[] = this.vaccinationReport?.employees || [];
return employees.map((employee, index) => {
return {
id: index,
Expand All @@ -109,15 +122,20 @@ export default class VaccinationReportDetailsView extends Mixins(
vaccinationStatus: vaccinationReportConstants.getStatusName(
employee.vaccinationStatus
),
raw: employee,
};
});
}
get vaccinationReport() {
return this.vrApi.state.result;
}
get facility() {
return this.vrApi.state.result?.facility;
return this.vaccinationReport?.facility;
}
get dateInfo() {
const reportedAt = this.vrApi.state.result?.reportedAt;
return [[["Meldung vom", getFormattedDate(reportedAt)]]];
return [
[["Meldung vom", getFormattedDate(this.vaccinationReport?.reportedAt)]],
];
}
get statusSelectOptions() {
return getEnumKeys(VaccinationStatus).map((key) => {
Expand All @@ -128,7 +146,7 @@ export default class VaccinationReportDetailsView extends Mixins(
});
}
getStatusColor = vaccinationReportConstants.getStatusColor;
dataTableFilter(value: TableRow) {
dataTableFilter(value: VREmployeeTableRow) {
if (this.status) {
const statusName = vaccinationReportConstants.getStatusName(this.status);
return value.vaccinationStatus === statusName;
Expand Down
Loading

0 comments on commit a8bc079

Please sign in to comment.