diff --git a/client/src/app/shared/models/agenda/item.ts b/client/src/app/shared/models/agenda/item.ts
index bef67ef1f..e08e46081 100644
--- a/client/src/app/shared/models/agenda/item.ts
+++ b/client/src/app/shared/models/agenda/item.ts
@@ -62,14 +62,15 @@ export class Item extends ProjectableBaseModel {
}
/**
- * Return the type as string
+ * Gets the string representation of the item type
+ * @returns The visibility for this item, as defined in {@link itemVisibilityChoices}
*/
public get verboseType(): string {
- if (this.type) {
- return itemVisibilityChoices.find(visibilityType => visibilityType.key === this.type).name;
- } else {
+ if (!this.type) {
return '';
}
+ const type = itemVisibilityChoices.find(choice => choice.key === this.type);
+ return type ? type.name : '';
}
public getTitle(): string {
diff --git a/client/src/app/shared/models/base/agenda-base-model.ts b/client/src/app/shared/models/base/agenda-base-model.ts
index 38abdb1c4..09819069c 100644
--- a/client/src/app/shared/models/base/agenda-base-model.ts
+++ b/client/src/app/shared/models/base/agenda-base-model.ts
@@ -33,11 +33,20 @@ export abstract class AgendaBaseModel extends ProjectableBaseModel implements Ag
return this.getAgendaTitle() + ' (' + this.getVerboseName() + ')';
}
+ /**
+ * @returns the (optional) descriptive text to be exported in the CSV.
+ * May be overridden by inheriting classes
+ */
+ public getCSVExportText(): string {
+ return '';
+ }
+
/**
* Should return a string representation of the object, so there can be searched for.
*/
public abstract formatForSearch(): SearchRepresentation;
+
/**
* Should return the URL to the detail view. Used for the agenda, that the
* user can navigate to the content object.
diff --git a/client/src/app/shared/models/topics/topic.ts b/client/src/app/shared/models/topics/topic.ts
index f935455c6..33b03fad7 100644
--- a/client/src/app/shared/models/topics/topic.ts
+++ b/client/src/app/shared/models/topics/topic.ts
@@ -37,4 +37,12 @@ export class Topic extends AgendaBaseModel {
public getDetailStateURL(): string {
return `/agenda/topics/${this.id}`;
}
+
+ /**
+ * Returns the text to be inserted in csv exports
+ * @override
+ */
+ public getCSVExportText(): string {
+ return this.text;
+ }
}
diff --git a/client/src/app/site/agenda/components/agenda-list/agenda-list.component.html b/client/src/app/site/agenda/components/agenda-list/agenda-list.component.html
index 7fb15ed2a..b056f42c4 100644
--- a/client/src/app/site/agenda/components/agenda-list/agenda-list.component.html
+++ b/client/src/app/site/agenda/components/agenda-list/agenda-list.component.html
@@ -103,6 +103,10 @@
Numbering
+
diff --git a/client/src/app/site/agenda/components/agenda-list/agenda-list.component.ts b/client/src/app/site/agenda/components/agenda-list/agenda-list.component.ts
index e6d134581..55093befc 100644
--- a/client/src/app/site/agenda/components/agenda-list/agenda-list.component.ts
+++ b/client/src/app/site/agenda/components/agenda-list/agenda-list.component.ts
@@ -8,6 +8,8 @@ import { ViewItem } from '../../models/view-item';
import { ListViewBaseComponent } from 'app/site/base/list-view-base';
import { AgendaRepositoryService } from '../../services/agenda-repository.service';
import { PromptService } from '../../../../core/services/prompt.service';
+
+import { AgendaCsvExportService } from '../../services/agenda-csv-export.service';
import { ItemInfoDialogComponent } from '../item-info-dialog/item-info-dialog.component';
import { ViewportService } from 'app/core/services/viewport.service';
import { DurationService } from 'app/site/core/services/duration.service';
@@ -47,6 +49,7 @@ export class AgendaListComponent extends ListViewBaseComponent impleme
* @param config read out config values
* @param vp determine the viewport
* @param durationService Converts numbers to readable duration strings
+ * @param csvExport Handles the exporting into csv
*/
public constructor(
titleService: Title,
@@ -59,7 +62,8 @@ export class AgendaListComponent extends ListViewBaseComponent impleme
private dialog: MatDialog,
private config: ConfigService,
public vp: ViewportService,
- public durationService: DurationService
+ public durationService: DurationService,
+ private csvExport: AgendaCsvExportService
) {
super(titleService, translate, matSnackBar);
@@ -213,4 +217,11 @@ export class AgendaListComponent extends ListViewBaseComponent impleme
}
return list;
}
+
+ /**
+ * Export all items as CSV
+ */
+ public csvExportItemList(): void {
+ this.csvExport.exportItemList(this.dataSource.data);
+ }
}
diff --git a/client/src/app/site/agenda/models/view-item.ts b/client/src/app/site/agenda/models/view-item.ts
index b82dc8c4f..3c4be1932 100644
--- a/client/src/app/site/agenda/models/view-item.ts
+++ b/client/src/app/site/agenda/models/view-item.ts
@@ -34,17 +34,22 @@ export class ViewItem extends BaseViewModel {
return this.item ? this.item.type : null;
}
- public get verboseType(): string {
- return this.item.verboseType;
- }
-
- public get comment(): string {
- return this.item ? this.item.comment : null;
- }
-
public get closed(): boolean {
return this.item ? this.item.closed : null;
}
+ public get comment(): string {
+ if (this.item && this.item.comment) {
+ return this.item.comment;
+ }
+ return '';
+ }
+
+ public get verboseType() : string {
+ if (this.item && this.item.verboseType) {
+ return this.item.verboseType;
+ }
+ return '';
+ }
public constructor(item: Item, contentObject: AgendaBaseModel) {
super();
diff --git a/client/src/app/site/agenda/services/agenda-csv-export.service.spec.ts b/client/src/app/site/agenda/services/agenda-csv-export.service.spec.ts
new file mode 100644
index 000000000..5720f7837
--- /dev/null
+++ b/client/src/app/site/agenda/services/agenda-csv-export.service.spec.ts
@@ -0,0 +1,20 @@
+import { TestBed, inject } from '@angular/core/testing';
+
+import { E2EImportsModule } from 'e2e-imports.module';
+import { AgendaCsvExportService } from './agenda-csv-export.service';
+
+describe('AgendaCsvExportService', () => {
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ imports: [E2EImportsModule],
+ providers: [AgendaCsvExportService]
+ });
+ });
+
+ it('should be created', inject(
+ [AgendaCsvExportService],
+ (service: AgendaCsvExportService) => {
+ expect(service).toBeTruthy();
+ }
+ ));
+});
diff --git a/client/src/app/site/agenda/services/agenda-csv-export.service.ts b/client/src/app/site/agenda/services/agenda-csv-export.service.ts
new file mode 100644
index 000000000..cbf9aaec7
--- /dev/null
+++ b/client/src/app/site/agenda/services/agenda-csv-export.service.ts
@@ -0,0 +1,41 @@
+import { Injectable } from '@angular/core';
+
+import { TranslateService } from '@ngx-translate/core';
+
+import { CsvExportService } from 'app/core/services/csv-export.service';
+import { ViewItem } from '../models/view-item';
+
+/**
+ * Exports CSVs for Agendas. Collect all CSV types here to have them in one place.
+ */
+@Injectable({
+ providedIn: 'root'
+})
+export class AgendaCsvExportService {
+
+ /**
+ * Does nothing.
+ *
+ * @param csvExport CsvExportService
+ * @param translate TranslateService
+ */
+ public constructor(private csvExport: CsvExportService, private translate: TranslateService) {}
+
+ /**
+ * Export all Agendas as CSV
+ *
+ * @param Agendas Agendas to export
+ */
+ public exportItemList(items: ViewItem[]): void {
+ this.csvExport.export(items,
+ [
+ { label: 'Title', map: viewItem => viewItem.getTitle() },
+ { label: 'Text', map: viewItem => viewItem.contentObject ? viewItem.contentObject.getCSVExportText() : '' },
+ { label: 'Duration', property: 'duration' },
+ { label: 'Comment', property: 'comment' },
+ { label: 'Item type', property: 'verboseType' }
+ ],
+ this.translate.instant('Agenda') + '.csv'
+ );
+ }
+}