diff --git a/client/src/app/core/services/collectionStringModelMapper.service.ts b/client/src/app/core/services/collectionStringModelMapper.service.ts
index 67c78922f..58dfa9e06 100644
--- a/client/src/app/core/services/collectionStringModelMapper.service.ts
+++ b/client/src/app/core/services/collectionStringModelMapper.service.ts
@@ -1,4 +1,4 @@
-import { ModelConstructor, BaseModel } from '../../shared/models/base.model';
+import { ModelConstructor, BaseModel } from '../../shared/models/base/base-model';
/**
* Registeres the mapping of collection strings <--> actual types. Every Model should register itself here.
diff --git a/client/src/app/core/services/data-send.service.ts b/client/src/app/core/services/data-send.service.ts
index 4321ec527..0b0d3c3f5 100644
--- a/client/src/app/core/services/data-send.service.ts
+++ b/client/src/app/core/services/data-send.service.ts
@@ -1,6 +1,6 @@
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
-import { BaseModel } from '../../shared/models/base.model';
+import { BaseModel } from '../../shared/models/base/base-model';
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';
diff --git a/client/src/app/core/services/data-store.service.ts b/client/src/app/core/services/data-store.service.ts
index c5c67383d..063703330 100644
--- a/client/src/app/core/services/data-store.service.ts
+++ b/client/src/app/core/services/data-store.service.ts
@@ -1,7 +1,7 @@
import { Injectable } from '@angular/core';
import { Observable, Subject } from 'rxjs';
-import { BaseModel, ModelConstructor } from 'app/shared/models/base.model';
+import { BaseModel, ModelConstructor } from '../../shared/models/base/base-model';
import { CacheService } from './cache.service';
import { CollectionStringModelMapperService } from './collectionStringModelMapper.service';
diff --git a/client/src/app/shared/components/search-value-selector/search-value-selector.component.html b/client/src/app/shared/components/search-value-selector/search-value-selector.component.html
index 318af3f1b..cfedb9bfb 100644
--- a/client/src/app/shared/components/search-value-selector/search-value-selector.component.html
+++ b/client/src/app/shared/components/search-value-selector/search-value-selector.component.html
@@ -2,7 +2,7 @@
- {{selectedItem.toString()}}
+ {{selectedItem.getTitle(translate)}}
diff --git a/client/src/app/shared/components/search-value-selector/search-value-selector.component.ts b/client/src/app/shared/components/search-value-selector/search-value-selector.component.ts
index b33d464f8..c7f24ab38 100644
--- a/client/src/app/shared/components/search-value-selector/search-value-selector.component.ts
+++ b/client/src/app/shared/components/search-value-selector/search-value-selector.component.ts
@@ -2,8 +2,9 @@ import { Component, OnInit, Input, ViewChild } from '@angular/core';
import { FormControl, FormGroup } from '@angular/forms';
import { ReplaySubject, Subject } from 'rxjs';
import { MatSelect } from '@angular/material';
-import { SelectorItem } from './search-value-selector.interfaces';
import { takeUntil } from 'rxjs/operators';
+import { Displayable } from '../../models/base/displayable';
+import { TranslateService } from '@ngx-translate/core';
/**
* Reusable Searchable Value Selector
@@ -27,17 +28,6 @@ import { takeUntil } from 'rxjs/operators';
*
* ```
*
- * ### Declaration of a Selector provided as `[InputListValues]=myListValues`:
- *
- * Every Class that enherits of BaseModel implements the SelectorItem Interface and can
- * therefore be used directly in the Selector Component.
- *
- * ```ts
- * import { SelectorItem } from '../../shared/components/search-value-selector/search-value-selector.interfaces';
- *
- * const myListValues: SelectorItem[];
- * myListValues = this.DS.get(User);
- * ```
*/
@Component({
@@ -60,7 +50,7 @@ export class SearchValueSelectorComponent implements OnInit {
/**
* List of the filtered content, when entering somithing in the search bar
*/
- public filteredItems: ReplaySubject = new ReplaySubject(1);
+ public filteredItems: ReplaySubject = new ReplaySubject(1);
/**
* Decide if this should be a single or multi-select-field
@@ -72,7 +62,7 @@ export class SearchValueSelectorComponent implements OnInit {
* The Input List Values
*/
@Input()
- public InputListValues: SelectorItem[];
+ public InputListValues: Displayable[];
/**
* Placeholder of the List
@@ -115,7 +105,7 @@ export class SearchValueSelectorComponent implements OnInit {
/**
* Empty constructor
*/
- public constructor() {}
+ public constructor(public translate: TranslateService) {}
/**
* onInit with filter ans subscription on filter
@@ -164,7 +154,7 @@ export class SearchValueSelectorComponent implements OnInit {
* places, but can't reflect the changes in both places. Until this can be done this will be unused code
* @param item the selected item to be removed
*/
- public remove(item: SelectorItem): void {
+ public remove(item: Displayable): void {
const myArr = this.thisSelector.value;
const index = myArr.indexOf(item, 0);
// my model was the form according to fix
diff --git a/client/src/app/shared/components/search-value-selector/search-value-selector.interfaces.ts b/client/src/app/shared/components/search-value-selector/search-value-selector.interfaces.ts
deleted file mode 100644
index f60236209..000000000
--- a/client/src/app/shared/components/search-value-selector/search-value-selector.interfaces.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-/**
- * Inteface for the Multi-Value-Selector Component to display and use
- * the given values.
- */
-export interface SelectorItem {
- /**
- * translates the displayable part of the function to a String
- */
- toString(): string;
-}
diff --git a/client/src/app/shared/models/agenda/item.ts b/client/src/app/shared/models/agenda/item.ts
index 6c7931ae0..46faac9ad 100644
--- a/client/src/app/shared/models/agenda/item.ts
+++ b/client/src/app/shared/models/agenda/item.ts
@@ -1,6 +1,10 @@
-import { BaseModel } from '../base.model';
+import { ProjectableBaseModel } from '../base/projectable-base-model';
import { Speaker } from './speaker';
+/**
+ * The representation of the content object for agenda items. The unique combination
+ * of the collection and id is given.
+ */
interface ContentObject {
id: number;
collection: string;
@@ -10,11 +14,11 @@ interface ContentObject {
* Representations of agenda Item
* @ignore
*/
-export class Item extends BaseModel {
+export class Item extends ProjectableBaseModel {
public id: number;
public item_number: string;
public title: string;
- public list_view_title: string;
+ public title_with_type: string;
public comment: string;
public closed: boolean;
public type: number;
@@ -30,6 +34,23 @@ export class Item extends BaseModel {
super('agenda/item', input);
}
+ // Note: This has to be used in the agenda repository
+ /*public get contentObject(): AgendaBaseModel {
+ const contentObject = this.DS.get(this.content_object.collection, this.content_object.id);
+ if (!contentObject) {
+ return null;
+ }
+ if (contentObject instanceof AgendaBaseModel) {
+ return contentObject as AgendaBaseModel;
+ } else {
+ throw new Error(
+ `The content object (${this.content_object.collection}, ${this.content_object.id}) of item ${
+ this.id
+ } is not a BaseProjectableModel.`
+ );
+ }
+ }*/
+
public deserialize(input: any): void {
Object.assign(this, input);
@@ -40,9 +61,32 @@ export class Item extends BaseModel {
}
}
- public toString(): string {
+ // The repository has to check for the content object and choose which title to use.
+ // The code below is belongs to the repository
+ public getTitle(): string {
+ /*const contentObject: AgendaBaseModel = this.contentObject;
+ if (contentObject) {
+ return contentObject.getAgendaTitle();
+ } else {
+ return this.title;
+ }*/
return this.title;
}
+
+ // Same here. See comment for getTitle()
+ public getListTitle(): string {
+ /*const contentObject: AgendaBaseModel = this.contentObject;
+ if (contentObject) {
+ return contentObject.getAgendaTitleWithType();
+ } else {
+ return this.title_with_type;
+ }*/
+ return this.title_with_type;
+ }
+
+ public getProjectorTitle(): string {
+ return this.getListTitle();
+ }
}
-BaseModel.registerCollectionElement('agenda/item', Item);
+ProjectableBaseModel.registerCollectionElement('agenda/item', Item);
diff --git a/client/src/app/shared/models/agenda/speaker.ts b/client/src/app/shared/models/agenda/speaker.ts
index c1e53d0a8..0348a3e1d 100644
--- a/client/src/app/shared/models/agenda/speaker.ts
+++ b/client/src/app/shared/models/agenda/speaker.ts
@@ -1,4 +1,4 @@
-import { Deserializer } from '../deserializer.model';
+import { Deserializer } from '../base/deserializer';
/**
* Representation of a speaker in an agenda item
diff --git a/client/src/app/shared/models/assignments/assignment-user.ts b/client/src/app/shared/models/assignments/assignment-user.ts
index 092f86c32..f2904552a 100644
--- a/client/src/app/shared/models/assignments/assignment-user.ts
+++ b/client/src/app/shared/models/assignments/assignment-user.ts
@@ -1,4 +1,4 @@
-import { Deserializer } from '../deserializer.model';
+import { Deserializer } from '../base/deserializer';
/**
* Content of the 'assignment_related_users' property
diff --git a/client/src/app/shared/models/assignments/assignment.ts b/client/src/app/shared/models/assignments/assignment.ts
index aa9260d5a..fd86b28da 100644
--- a/client/src/app/shared/models/assignments/assignment.ts
+++ b/client/src/app/shared/models/assignments/assignment.ts
@@ -1,12 +1,12 @@
-import { BaseModel } from '../base.model';
import { AssignmentUser } from './assignment-user';
import { Poll } from './poll';
+import { AgendaBaseModel } from '../base/agenda-base-model';
/**
* Representation of an assignment.
* @ignore
*/
-export class Assignment extends BaseModel {
+export class Assignment extends AgendaBaseModel {
public id: number;
public title: string;
public description: string;
@@ -19,7 +19,7 @@ export class Assignment extends BaseModel {
public tags_id: number[];
public constructor(input?: any) {
- super('assignments/assignment', input);
+ super('assignments/assignment', 'Assignment', input);
}
public get candidateIds(): number[] {
@@ -48,9 +48,13 @@ export class Assignment extends BaseModel {
}
}
- public toString(): string {
+ public getTitle(): string {
return this.title;
}
+
+ public getDetailStateURL(): string {
+ return 'TODO';
+ }
}
-BaseModel.registerCollectionElement('assignments/assignment', Assignment);
+AgendaBaseModel.registerCollectionElement('assignments/assignment', Assignment);
diff --git a/client/src/app/shared/models/assignments/poll-option.ts b/client/src/app/shared/models/assignments/poll-option.ts
index 5329f73ad..ddbc21cf7 100644
--- a/client/src/app/shared/models/assignments/poll-option.ts
+++ b/client/src/app/shared/models/assignments/poll-option.ts
@@ -1,4 +1,4 @@
-import { Deserializer } from '../deserializer.model';
+import { Deserializer } from '../base/deserializer';
/**
* Representation of a poll option
diff --git a/client/src/app/shared/models/assignments/poll.ts b/client/src/app/shared/models/assignments/poll.ts
index 1375cd4a3..9ec0ab57b 100644
--- a/client/src/app/shared/models/assignments/poll.ts
+++ b/client/src/app/shared/models/assignments/poll.ts
@@ -1,5 +1,5 @@
import { PollOption } from './poll-option';
-import { Deserializer } from '../deserializer.model';
+import { Deserializer } from '../base/deserializer';
/**
* Content of the 'polls' property of assignments
diff --git a/client/src/app/shared/models/base/agenda-base-model.ts b/client/src/app/shared/models/base/agenda-base-model.ts
new file mode 100644
index 000000000..755a7bfa7
--- /dev/null
+++ b/client/src/app/shared/models/base/agenda-base-model.ts
@@ -0,0 +1,37 @@
+import { AgendaInformation } from './agenda-information';
+import { ProjectableBaseModel } from './projectable-base-model';
+
+/**
+ * A base model for models, that can be content objects in the agenda. Provides title and navigation
+ * information for the agenda.
+ */
+export abstract class AgendaBaseModel extends ProjectableBaseModel implements AgendaInformation {
+ protected verboseName: string;
+
+ /**
+ * A Model that inherits from this class should provide a verbose name. It's used by creating
+ * the agenda title with type.
+ * @param collectionString
+ * @param verboseName
+ * @param input
+ */
+ protected constructor(collectionString: string, verboseName: string, input?: any) {
+ super(collectionString, input);
+ this.verboseName = verboseName;
+ }
+
+ public getAgendaTitle(): string {
+ return this.getTitle();
+ }
+
+ public getAgendaTitleWithType(): string {
+ // Return the agenda title with the model's verbose name appended
+ return this.getAgendaTitle() + ' (' + this.verboseName + ')';
+ }
+
+ /**
+ * Should return the URL to the detail view. Used for the agenda, that the
+ * user can navigate to the content object.
+ */
+ public abstract getDetailStateURL(): string;
+}
diff --git a/client/src/app/shared/models/base/agenda-information.ts b/client/src/app/shared/models/base/agenda-information.ts
new file mode 100644
index 000000000..832f1bd45
--- /dev/null
+++ b/client/src/app/shared/models/base/agenda-information.ts
@@ -0,0 +1,19 @@
+/**
+ * An Interface for all extra information needed for content objects of items.
+ */
+export interface AgendaInformation {
+ /**
+ * Should return the title for the agenda list view.
+ */
+ getAgendaTitle(): string;
+
+ /**
+ * Should return the title for the list of speakers view.
+ */
+ getAgendaTitleWithType(): string;
+
+ /**
+ * Get the url for the detail view, so in the agenda the user can navigate to it.
+ */
+ getDetailStateURL(): string;
+}
diff --git a/client/src/app/shared/models/base.model.ts b/client/src/app/shared/models/base/base-model.ts
similarity index 82%
rename from client/src/app/shared/models/base.model.ts
rename to client/src/app/shared/models/base/base-model.ts
index a2372807d..ddc7fab76 100644
--- a/client/src/app/shared/models/base.model.ts
+++ b/client/src/app/shared/models/base/base-model.ts
@@ -1,7 +1,7 @@
import { OpenSlidesComponent } from 'app/openslides.component';
-import { Deserializable } from './deserializable.model';
-import { CollectionStringModelMapperService } from '../../core/services/collectionStringModelMapper.service';
-import { SelectorItem } from '../components/search-value-selector/search-value-selector.interfaces';
+import { Deserializable } from './deserializable';
+import { CollectionStringModelMapperService } from '../../../core/services/collectionStringModelMapper.service';
+import { Displayable } from './displayable';
export interface ModelConstructor {
new (...args: any[]): T;
@@ -10,7 +10,7 @@ export interface ModelConstructor {
/**
* Abstract parent class to set rules and functions for all models.
*/
-export abstract class BaseModel extends OpenSlidesComponent implements Deserializable, SelectorItem {
+export abstract class BaseModel extends OpenSlidesComponent implements Deserializable, Displayable {
/**
* Register the collection string to the type.
* @param collectionString
@@ -56,10 +56,16 @@ export abstract class BaseModel extends OpenSlidesComponent implements Deseriali
}
});
}
- /**
- * force children to have a toString() method
- */
- public abstract toString(): string;
+
+ public abstract getTitle(): string;
+
+ public getListTitle(): string {
+ return this.getTitle();
+ }
+
+ public toString(): string {
+ return this.getTitle();
+ }
/**
* returns the collectionString.
diff --git a/client/src/app/shared/models/deserializable.model.ts b/client/src/app/shared/models/base/deserializable.ts
similarity index 100%
rename from client/src/app/shared/models/deserializable.model.ts
rename to client/src/app/shared/models/base/deserializable.ts
diff --git a/client/src/app/shared/models/deserializer.model.ts b/client/src/app/shared/models/base/deserializer.ts
similarity index 95%
rename from client/src/app/shared/models/deserializer.model.ts
rename to client/src/app/shared/models/base/deserializer.ts
index 33d50ef2a..a21b40373 100644
--- a/client/src/app/shared/models/deserializer.model.ts
+++ b/client/src/app/shared/models/base/deserializer.ts
@@ -1,4 +1,4 @@
-import { Deserializable } from './deserializable.model';
+import { Deserializable } from './deserializable';
/**
* Abstract base class for a basic implementation of Deserializable.
diff --git a/client/src/app/shared/models/base/displayable.ts b/client/src/app/shared/models/base/displayable.ts
new file mode 100644
index 000000000..9be35f9f4
--- /dev/null
+++ b/client/src/app/shared/models/base/displayable.ts
@@ -0,0 +1,14 @@
+/**
+ * Every displayble object should have the given functions to give the object's title.
+ */
+export interface Displayable {
+ /**
+ * Should return the title. Alway used except for list view, the agenda and in the projector.
+ */
+ getTitle(): string;
+
+ /**
+ * Should return the title for the list view.
+ */
+ getListTitle(): string;
+}
diff --git a/client/src/app/shared/models/base/projectable-base-model.ts b/client/src/app/shared/models/base/projectable-base-model.ts
new file mode 100644
index 000000000..fc10e11d3
--- /dev/null
+++ b/client/src/app/shared/models/base/projectable-base-model.ts
@@ -0,0 +1,17 @@
+import { BaseModel } from './base-model';
+import { Projectable } from './projectable';
+
+export abstract class ProjectableBaseModel extends BaseModel implements Projectable {
+ protected constructor(collectionString: string, input?: any) {
+ super(collectionString, input);
+ }
+
+ /**
+ * This is a Dummy, which should be changed if the projector gets implemented.
+ */
+ public project(): void {}
+
+ public getProjectorTitle(): string {
+ return this.getTitle();
+ }
+}
diff --git a/client/src/app/shared/models/base/projectable.ts b/client/src/app/shared/models/base/projectable.ts
new file mode 100644
index 000000000..d2f002f76
--- /dev/null
+++ b/client/src/app/shared/models/base/projectable.ts
@@ -0,0 +1,14 @@
+/**
+ * Interface for every model, that should be projectable.
+ */
+export interface Projectable {
+ /**
+ * Should return the title for the projector.
+ */
+ getProjectorTitle(): string;
+
+ /**
+ * Dummy. I don't know how the projctor system will be, so this function may change
+ */
+ project(): void;
+}
diff --git a/client/src/app/shared/models/core/chat-message.ts b/client/src/app/shared/models/core/chat-message.ts
index d254692f3..146186195 100644
--- a/client/src/app/shared/models/core/chat-message.ts
+++ b/client/src/app/shared/models/core/chat-message.ts
@@ -1,4 +1,4 @@
-import { BaseModel } from '../base.model';
+import { BaseModel } from '../base/base-model';
/**
* Representation of chat messages.
@@ -14,8 +14,8 @@ export class ChatMessage extends BaseModel {
super('core/chat-message', input);
}
- public toString(): string {
- return this.message;
+ public getTitle(): string {
+ return 'Chatmessage';
}
}
diff --git a/client/src/app/shared/models/core/config.ts b/client/src/app/shared/models/core/config.ts
index 51e174ca3..2899902b6 100644
--- a/client/src/app/shared/models/core/config.ts
+++ b/client/src/app/shared/models/core/config.ts
@@ -1,4 +1,4 @@
-import { BaseModel } from '../base.model';
+import { BaseModel } from '../base/base-model';
/**
* Representation of a config variable
@@ -13,7 +13,7 @@ export class Config extends BaseModel {
super('core/config', input);
}
- public toString(): string {
+ public getTitle(): string {
return this.key;
}
}
diff --git a/client/src/app/shared/models/core/countdown.ts b/client/src/app/shared/models/core/countdown.ts
index 8aafcd3f4..06245258e 100644
--- a/client/src/app/shared/models/core/countdown.ts
+++ b/client/src/app/shared/models/core/countdown.ts
@@ -1,10 +1,10 @@
-import { BaseModel } from '../base.model';
+import { ProjectableBaseModel } from '../base/projectable-base-model';
/**
* Representation of a countdown
* @ignore
*/
-export class Countdown extends BaseModel {
+export class Countdown extends ProjectableBaseModel {
public id: number;
public description: string;
public default_time: number;
@@ -15,9 +15,9 @@ export class Countdown extends BaseModel {
super('core/countdown');
}
- public toString(): string {
+ public getTitle(): string {
return this.description;
}
}
-BaseModel.registerCollectionElement('core/countdown', Countdown);
+ProjectableBaseModel.registerCollectionElement('core/countdown', Countdown);
diff --git a/client/src/app/shared/models/core/projector-message.ts b/client/src/app/shared/models/core/projector-message.ts
index b5b59db7b..a49dcf79e 100644
--- a/client/src/app/shared/models/core/projector-message.ts
+++ b/client/src/app/shared/models/core/projector-message.ts
@@ -1,10 +1,10 @@
-import { BaseModel } from '../base.model';
+import { ProjectableBaseModel } from '../base/projectable-base-model';
/**
* Representation of a projector message.
* @ignore
*/
-export class ProjectorMessage extends BaseModel {
+export class ProjectorMessage extends ProjectableBaseModel {
public id: number;
public message: string;
@@ -12,9 +12,9 @@ export class ProjectorMessage extends BaseModel {
super('core/projector-message', input);
}
- public toString(): string {
- return this.message;
+ public getTitle(): string {
+ return 'Projectormessage';
}
}
-BaseModel.registerCollectionElement('core/projector-message', ProjectorMessage);
+ProjectableBaseModel.registerCollectionElement('core/projector-message', ProjectorMessage);
diff --git a/client/src/app/shared/models/core/projector.ts b/client/src/app/shared/models/core/projector.ts
index 7af72f9f0..d2b692469 100644
--- a/client/src/app/shared/models/core/projector.ts
+++ b/client/src/app/shared/models/core/projector.ts
@@ -1,4 +1,4 @@
-import { BaseModel } from '../base.model';
+import { BaseModel } from '../base/base-model';
/**
* Representation of a projector. Has the nested property "projectiondefaults"
@@ -19,7 +19,7 @@ export class Projector extends BaseModel {
super('core/projector', input);
}
- public toString(): string {
+ public getTitle(): string {
return this.name;
}
}
diff --git a/client/src/app/shared/models/core/tag.ts b/client/src/app/shared/models/core/tag.ts
index 7447b06f8..44e0fd75a 100644
--- a/client/src/app/shared/models/core/tag.ts
+++ b/client/src/app/shared/models/core/tag.ts
@@ -1,4 +1,4 @@
-import { BaseModel } from '../base.model';
+import { BaseModel } from '../base/base-model';
/**
* Representation of a tag.
@@ -12,7 +12,7 @@ export class Tag extends BaseModel {
super('core/tag', input);
}
- public toString(): string {
+ public getTitle(): string {
return this.name;
}
}
diff --git a/client/src/app/shared/models/mediafiles/file.ts b/client/src/app/shared/models/mediafiles/file.ts
index 8ac48c45d..e9a7f812b 100644
--- a/client/src/app/shared/models/mediafiles/file.ts
+++ b/client/src/app/shared/models/mediafiles/file.ts
@@ -1,4 +1,4 @@
-import { Deserializer } from '../deserializer.model';
+import { Deserializer } from '../base/deserializer';
/**
* The name and the type of a mediaFile.
diff --git a/client/src/app/shared/models/mediafiles/mediafile.ts b/client/src/app/shared/models/mediafiles/mediafile.ts
index bb5b63145..dfe9c941f 100644
--- a/client/src/app/shared/models/mediafiles/mediafile.ts
+++ b/client/src/app/shared/models/mediafiles/mediafile.ts
@@ -1,11 +1,11 @@
-import { BaseModel } from '../base.model';
import { File } from './file';
+import { ProjectableBaseModel } from '../base/projectable-base-model';
/**
* Representation of MediaFile. Has the nested property "File"
* @ignore
*/
-export class Mediafile extends BaseModel {
+export class Mediafile extends ProjectableBaseModel {
public id: number;
public title: string;
public mediafile: File;
@@ -24,9 +24,9 @@ export class Mediafile extends BaseModel {
this.mediafile = new File(input.mediafile);
}
- public toString(): string {
+ public getTitle(): string {
return this.title;
}
}
-BaseModel.registerCollectionElement('amediafiles/mediafile', Mediafile);
+ProjectableBaseModel.registerCollectionElement('amediafiles/mediafile', Mediafile);
diff --git a/client/src/app/shared/models/motions/category.ts b/client/src/app/shared/models/motions/category.ts
index ed7243086..d772a8925 100644
--- a/client/src/app/shared/models/motions/category.ts
+++ b/client/src/app/shared/models/motions/category.ts
@@ -1,4 +1,4 @@
-import { BaseModel } from '../base.model';
+import { BaseModel } from '../base/base-model';
/**
* Representation of a motion category. Has the nested property "File"
@@ -13,7 +13,7 @@ export class Category extends BaseModel {
super('motions/category', input);
}
- public toString(): string {
+ public getTitle(): string {
return this.prefix + ' - ' + this.name;
}
}
diff --git a/client/src/app/shared/models/motions/motion-block.ts b/client/src/app/shared/models/motions/motion-block.ts
index dc11f8606..da2eb781f 100644
--- a/client/src/app/shared/models/motions/motion-block.ts
+++ b/client/src/app/shared/models/motions/motion-block.ts
@@ -1,22 +1,25 @@
-import { BaseModel } from '../base.model';
-import { Item } from '../agenda/item';
+import { AgendaBaseModel } from '../base/agenda-base-model';
/**
* Representation of a motion block.
* @ignore
*/
-export class MotionBlock extends BaseModel {
+export class MotionBlock extends AgendaBaseModel {
public id: number;
public title: string;
public agenda_item_id: number;
public constructor(input?: any) {
- super('motions/motion-block', input);
+ super('motions/motion-block', 'Motion block', input);
}
- public toString(): string {
+ public getTitle(): string {
return this.title;
}
+
+ public getDetailStateURL(): string {
+ return 'TODO';
+ }
}
-BaseModel.registerCollectionElement('motions/motion-block', MotionBlock);
+AgendaBaseModel.registerCollectionElement('motions/motion-block', MotionBlock);
diff --git a/client/src/app/shared/models/motions/motion-change-reco.ts b/client/src/app/shared/models/motions/motion-change-reco.ts
index a46e05996..a562f7b36 100644
--- a/client/src/app/shared/models/motions/motion-change-reco.ts
+++ b/client/src/app/shared/models/motions/motion-change-reco.ts
@@ -1,4 +1,4 @@
-import { BaseModel } from '../base.model';
+import { BaseModel } from '../base/base-model';
/**
* Representation of a motion change recommendation.
@@ -19,8 +19,8 @@ export class MotionChangeReco extends BaseModel {
super('motions/motion-change-recommendation', input);
}
- public toString(): string {
- return this.text;
+ public getTitle(): string {
+ return 'Changerecommendation';
}
}
diff --git a/client/src/app/shared/models/motions/motion-comment-section.ts b/client/src/app/shared/models/motions/motion-comment-section.ts
index 81e178e7c..24fff9c02 100644
--- a/client/src/app/shared/models/motions/motion-comment-section.ts
+++ b/client/src/app/shared/models/motions/motion-comment-section.ts
@@ -1,4 +1,4 @@
-import { BaseModel } from '../base.model';
+import { BaseModel } from '../base/base-model';
/**
* Representation of a motion category. Has the nested property "File"
@@ -14,7 +14,7 @@ export class MotionCommentSection extends BaseModel {
super('motions/motion-comment-section', input);
}
- public toString(): string {
+ public getTitle(): string {
return this.name;
}
}
diff --git a/client/src/app/shared/models/motions/motion-comment.ts b/client/src/app/shared/models/motions/motion-comment.ts
index 78447574b..69c1379ee 100644
--- a/client/src/app/shared/models/motions/motion-comment.ts
+++ b/client/src/app/shared/models/motions/motion-comment.ts
@@ -1,4 +1,4 @@
-import { Deserializer } from '../deserializer.model';
+import { Deserializer } from '../base/deserializer';
/**
* Representation of a Motion Comment.
diff --git a/client/src/app/shared/models/motions/motion-log.ts b/client/src/app/shared/models/motions/motion-log.ts
index 952f00cec..1dc1fd15d 100644
--- a/client/src/app/shared/models/motions/motion-log.ts
+++ b/client/src/app/shared/models/motions/motion-log.ts
@@ -1,4 +1,4 @@
-import { Deserializer } from '../deserializer.model';
+import { Deserializer } from '../base/deserializer';
/**
* Representation of a Motion Log.
diff --git a/client/src/app/shared/models/motions/motion-submitter.ts b/client/src/app/shared/models/motions/motion-submitter.ts
index 50422eec9..d5bb9e8ac 100644
--- a/client/src/app/shared/models/motions/motion-submitter.ts
+++ b/client/src/app/shared/models/motions/motion-submitter.ts
@@ -1,4 +1,4 @@
-import { Deserializer } from '../deserializer.model';
+import { Deserializer } from '../base/deserializer';
import { User } from '../users/user';
/**
diff --git a/client/src/app/shared/models/motions/motion.ts b/client/src/app/shared/models/motions/motion.ts
index 99f3b5e5e..9779caa2a 100644
--- a/client/src/app/shared/models/motions/motion.ts
+++ b/client/src/app/shared/models/motions/motion.ts
@@ -1,9 +1,9 @@
-import { BaseModel } from '../base.model';
import { MotionSubmitter } from './motion-submitter';
import { MotionLog } from './motion-log';
import { Category } from './category';
import { MotionComment } from './motion-comment';
import { Workflow } from './workflow';
+import { AgendaBaseModel } from '../base/agenda-base-model';
/**
* Representation of Motion.
@@ -12,7 +12,7 @@ import { Workflow } from './workflow';
*
* @ignore
*/
-export class Motion extends BaseModel {
+export class Motion extends AgendaBaseModel {
public id: number;
public identifier: string;
public title: string;
@@ -36,12 +36,12 @@ export class Motion extends BaseModel {
public recommendation_extension: string;
public tags_id: number[];
public attachments_id: number[];
- public polls: BaseModel[];
+ public polls: Object[];
public agenda_item_id: number;
public log_messages: MotionLog[];
public constructor(input?: any) {
- super('motions/motion', input);
+ super('motions/motion', 'Motion', input);
}
/**
@@ -62,13 +62,32 @@ export class Motion extends BaseModel {
.map((submitter: MotionSubmitter) => submitter.user_id);
}
- /**
- * returns the Motion name
- */
- public toString(): string {
+ public getTitle(): string {
return this.title;
}
+ public getAgendaTitle(): string {
+ // if the identifier is set, the title will be 'Motion '.
+ if (this.identifier) {
+ return 'Motion ' + this.identifier;
+ } else {
+ return this.getTitle();
+ }
+ }
+
+ public getAgendaTitleWithType(): string {
+ // Append the verbose name only, if not the special format 'Motion ' is used.
+ if (this.identifier) {
+ return 'Motion ' + this.identifier;
+ } else {
+ return this.getTitle() + ' (' + this.verboseName + ')';
+ }
+ }
+
+ public getDetailStateURL(): string {
+ return 'TODO';
+ }
+
public deserialize(input: any): void {
Object.assign(this, input);
@@ -91,6 +110,6 @@ export class Motion extends BaseModel {
/**
* Hack to get them loaded at last
*/
-BaseModel.registerCollectionElement('motions/motion', Motion);
-BaseModel.registerCollectionElement('motions/category', Category);
-BaseModel.registerCollectionElement('motions/workflow', Workflow);
+AgendaBaseModel.registerCollectionElement('motions/motion', Motion);
+AgendaBaseModel.registerCollectionElement('motions/category', Category);
+AgendaBaseModel.registerCollectionElement('motions/workflow', Workflow);
diff --git a/client/src/app/shared/models/motions/workflow-state.ts b/client/src/app/shared/models/motions/workflow-state.ts
index 99bf6f27d..75e9c5d13 100644
--- a/client/src/app/shared/models/motions/workflow-state.ts
+++ b/client/src/app/shared/models/motions/workflow-state.ts
@@ -1,4 +1,4 @@
-import { Deserializer } from '../deserializer.model';
+import { Deserializer } from '../base/deserializer';
import { Workflow } from './workflow';
/**
diff --git a/client/src/app/shared/models/motions/workflow.ts b/client/src/app/shared/models/motions/workflow.ts
index ba54d6193..8e8f30ac7 100644
--- a/client/src/app/shared/models/motions/workflow.ts
+++ b/client/src/app/shared/models/motions/workflow.ts
@@ -1,4 +1,4 @@
-import { BaseModel } from '../base.model';
+import { BaseModel } from '../base/base-model';
import { WorkflowState } from './workflow-state';
/**
@@ -54,7 +54,7 @@ export class Workflow extends BaseModel {
}
}
- public toString(): string {
+ public getTitle(): string {
return this.name;
}
}
diff --git a/client/src/app/shared/models/topics/topic.ts b/client/src/app/shared/models/topics/topic.ts
index 71b1671d0..96a228a3a 100644
--- a/client/src/app/shared/models/topics/topic.ts
+++ b/client/src/app/shared/models/topics/topic.ts
@@ -1,10 +1,10 @@
-import { BaseModel } from '../base.model';
+import { AgendaBaseModel } from '../base/agenda-base-model';
/**
* Representation of a topic.
* @ignore
*/
-export class Topic extends BaseModel {
+export class Topic extends AgendaBaseModel {
public id: number;
public title: string;
public text: string;
@@ -12,12 +12,21 @@ export class Topic extends BaseModel {
public agenda_item_id: number;
public constructor(input?: any) {
- super('topics/topic', input);
+ super('topics/topic', 'Topic', input);
}
- public toString(): string {
+ public getTitle(): string {
return this.title;
}
+
+ public getAgendaTitleWithType(): string {
+ // Do not append ' (Topic)' to the title.
+ return this.getAgendaTitle();
+ }
+
+ public getDetailStateURL(): string {
+ return 'TODO';
+ }
}
-BaseModel.registerCollectionElement('topics/topic', Topic);
+AgendaBaseModel.registerCollectionElement('topics/topic', Topic);
diff --git a/client/src/app/shared/models/users/group.ts b/client/src/app/shared/models/users/group.ts
index fed9c4df4..4b52724d6 100644
--- a/client/src/app/shared/models/users/group.ts
+++ b/client/src/app/shared/models/users/group.ts
@@ -1,4 +1,4 @@
-import { BaseModel } from '../base.model';
+import { BaseModel } from '../base/base-model';
/**
* Representation of user group.
@@ -13,7 +13,7 @@ export class Group extends BaseModel {
super('users/group', input);
}
- public toString(): string {
+ public getTitle(): string {
return this.name;
}
}
diff --git a/client/src/app/shared/models/users/personal-note.ts b/client/src/app/shared/models/users/personal-note.ts
index 48510110c..a9a0bd434 100644
--- a/client/src/app/shared/models/users/personal-note.ts
+++ b/client/src/app/shared/models/users/personal-note.ts
@@ -1,5 +1,4 @@
-import { BaseModel } from '../base.model';
-import { User } from './user';
+import { BaseModel } from '../base/base-model';
/**
* Representation of users personal note.
@@ -14,8 +13,8 @@ export class PersonalNote extends BaseModel {
super('users/personal-note', input);
}
- public toString(): string {
- return this.notes.toString();
+ public getTitle(): string {
+ return 'Personal note';
}
}
diff --git a/client/src/app/shared/models/users/user.ts b/client/src/app/shared/models/users/user.ts
index b6fd2c3e3..c49b7ae7f 100644
--- a/client/src/app/shared/models/users/user.ts
+++ b/client/src/app/shared/models/users/user.ts
@@ -1,10 +1,10 @@
-import { BaseModel } from '../base.model';
+import { ProjectableBaseModel } from '../base/projectable-base-model';
/**
* Representation of a user in contrast to the operator.
* @ignore
*/
-export class User extends BaseModel {
+export class User extends ProjectableBaseModel {
public id: number;
public username: string;
public title: string;
@@ -77,9 +77,13 @@ export class User extends BaseModel {
return shortName.trim();
}
- public toString(): string {
+ public getTitle(): string {
+ return this.full_name;
+ }
+
+ public getListViewTitle(): string {
return this.short_name;
}
}
-BaseModel.registerCollectionElement('users/user', User);
+ProjectableBaseModel.registerCollectionElement('users/user', User);
diff --git a/client/src/app/site/base-repository.ts b/client/src/app/site/base-repository.ts
index 75f15ef90..25d0d2998 100644
--- a/client/src/app/site/base-repository.ts
+++ b/client/src/app/site/base-repository.ts
@@ -1,7 +1,7 @@
import { OpenSlidesComponent } from '../openslides.component';
import { BehaviorSubject, Observable } from 'rxjs';
import { BaseViewModel } from './base-view-model';
-import { BaseModel, ModelConstructor } from '../shared/models/base.model';
+import { BaseModel, ModelConstructor } from '../shared/models/base/base-model';
import { CollectionStringModelMapperService } from '../core/services/collectionStringModelMapper.service';
import { DataStoreService } from '../core/services/data-store.service';
diff --git a/client/src/app/site/base-view-model.ts b/client/src/app/site/base-view-model.ts
index 5f1749184..7e71b7662 100644
--- a/client/src/app/site/base-view-model.ts
+++ b/client/src/app/site/base-view-model.ts
@@ -1,39 +1,19 @@
-import { TranslateService } from '@ngx-translate/core';
-import { BaseModel } from '../shared/models/base.model';
+import { BaseModel } from '../shared/models/base/base-model';
+import { Displayable } from '../shared/models/base/displayable';
/**
* Base class for view models. alls view models should have titles.
*/
-export abstract class BaseViewModel {
+export abstract class BaseViewModel implements Displayable {
public abstract updateValues(update: BaseModel): void;
- /**
- * Should return the title for the detail view.
- * @param translate
- */
- public abstract getTitle(translate: TranslateService): string;
+ public abstract getTitle(): string;
- /**
- * Should return the title for the list view.
- * @param translate
- */
- public getListTitle(translate: TranslateService): string {
- return this.getTitle(translate);
+ public getListTitle(): string {
+ return this.getTitle();
}
- /**
- * Should return the title for the projector.
- * @param translate
- */
- public getProjector(translate: TranslateService): string {
- return this.getTitle(translate);
- }
-
- /**
- * Should return the title for the agenda list view.
- * @param translate
- */
- public getAgendaTitle(translate: TranslateService): string {
- return this.getTitle(translate);
+ public toString(): string {
+ return this.getTitle();
}
}
diff --git a/client/src/app/site/motions/components/motion-detail/motion-detail.component.html b/client/src/app/site/motions/components/motion-detail/motion-detail.component.html
index fe3978d7a..d445f640b 100644
--- a/client/src/app/site/motions/components/motion-detail/motion-detail.component.html
+++ b/client/src/app/site/motions/components/motion-detail/motion-detail.component.html
@@ -153,8 +153,8 @@
Submitters
-
- - {{submitters}}
+
+ - {{submitter.full_name}}
@@ -169,8 +169,8 @@
Supporters
-
- - {{supporters}}
+
+ - {{supporter.full_name}}
diff --git a/client/src/app/site/motions/models/view-motion.ts b/client/src/app/site/motions/models/view-motion.ts
index 0149b4f55..66671ea25 100644
--- a/client/src/app/site/motions/models/view-motion.ts
+++ b/client/src/app/site/motions/models/view-motion.ts
@@ -3,7 +3,7 @@ import { Category } from '../../../shared/models/motions/category';
import { User } from '../../../shared/models/users/user';
import { Workflow } from '../../../shared/models/motions/workflow';
import { WorkflowState } from '../../../shared/models/motions/workflow-state';
-import { BaseModel } from '../../../shared/models/base.model';
+import { BaseModel } from '../../../shared/models/base/base-model';
import { BaseViewModel } from '../../base-view-model';
import { TranslateService } from '@ngx-translate/core';
diff --git a/openslides/agenda/models.py b/openslides/agenda/models.py
index a6d5a161d..45ecae422 100644
--- a/openslides/agenda/models.py
+++ b/openslides/agenda/models.py
@@ -296,14 +296,14 @@ class Item(RESTModelMixin, models.Model):
'method on your related model.')
@property
- def list_view_title(self):
+ def title_with_type(self):
"""
- Return get_agenda_list_view_title() from the content_object.
+ Return get_agenda_title_with_type() from the content_object.
"""
try:
- return self.content_object.get_agenda_list_view_title()
+ return self.content_object.get_agenda_title_with_type()
except AttributeError:
- raise NotImplementedError('You have to provide a get_agenda_list_view_title '
+ raise NotImplementedError('You have to provide a get_agenda_title_with_type '
'method on your related model.')
def is_internal(self):
diff --git a/openslides/agenda/serializers.py b/openslides/agenda/serializers.py
index 13dfebc63..edcb49ea1 100644
--- a/openslides/agenda/serializers.py
+++ b/openslides/agenda/serializers.py
@@ -45,7 +45,7 @@ class ItemSerializer(ModelSerializer):
'id',
'item_number',
'title',
- 'list_view_title',
+ 'title_with_type',
'comment',
'closed',
'type',
diff --git a/openslides/assignments/models.py b/openslides/assignments/models.py
index aa387e25b..b970f8e56 100644
--- a/openslides/assignments/models.py
+++ b/openslides/assignments/models.py
@@ -338,16 +338,17 @@ class Assignment(RESTModelMixin, models.Model):
agenda_item_update_information: Dict[str, Any] = {}
def get_agenda_title(self):
+ """
+ Returns the title for the agenda.
+ """
return str(self)
- def get_agenda_list_view_title(self):
+ def get_agenda_title_with_type(self):
"""
- Return a title string for the agenda list view.
-
- Contains agenda item number, title and assignment verbose name.
+ Return a title for the agenda with the appended assignment verbose name.
Note: It has to be the same return value like in JavaScript.
"""
- return '%s (%s)' % (self.title, _(self._meta.verbose_name))
+ return '%s (%s)' % (self.get_agenda_title(), _(self._meta.verbose_name))
@property
def agenda_item(self):
diff --git a/openslides/motions/models.py b/openslides/motions/models.py
index 0223d624d..c38392080 100644
--- a/openslides/motions/models.py
+++ b/openslides/motions/models.py
@@ -436,26 +436,30 @@ class Motion(RESTModelMixin, models.Model):
def get_agenda_title(self):
"""
- Return a simple title string for the agenda.
+ Return the title string for the agenda.
- Returns only the motion title so that you have only agenda item number
- and title in the agenda.
- """
- return str(self)
-
- def get_agenda_list_view_title(self):
- """
- Return a title string for the agenda list view.
-
- Returns only the motion title so that you have agenda item number,
- title and motion identifier in the agenda.
+ If the identifier is given, the title consists of the motion verbose name
+ and the identifier.
Note: It has to be the same return value like in JavaScript.
"""
if self.identifier:
- string = '%s %s' % (_(self._meta.verbose_name), self.identifier)
+ title = '%s %s' % (_(self._meta.verbose_name), self.identifier)
else:
- string = '%s (%s)' % (_(self._meta.verbose_name), self.title)
- return string
+ title = self.title
+ return title
+
+ def get_agenda_title_with_type(self):
+ """
+ Return a title for the agenda with the type or the modified title if the
+ identifier is set..
+
+ Note: It has to be the same return value like in JavaScript.
+ """
+ if self.identifier:
+ title = '%s %s' % (_(self._meta.verbose_name), self.identifier)
+ else:
+ title = '%s (%s)' % (self.title, _(self._meta.verbose_name))
+ return title
@property
def agenda_item(self):
@@ -781,6 +785,7 @@ class MotionBlock(RESTModelMixin, models.Model):
agenda_items = GenericRelation(Item, related_name='topics')
class Meta:
+ verbose_name = ugettext_noop('Motion block')
default_permissions = ()
def __str__(self):
@@ -821,8 +826,8 @@ class MotionBlock(RESTModelMixin, models.Model):
def get_agenda_title(self):
return self.title
- def get_agenda_list_view_title(self):
- return self.title
+ def get_agenda_title_with_type(self):
+ return '%s (%s)' % (self.get_agenda_title(), _(self._meta.verbose_name))
class MotionLog(RESTModelMixin, models.Model):
diff --git a/openslides/topics/models.py b/openslides/topics/models.py
index ecee8331f..ff9185bc3 100644
--- a/openslides/topics/models.py
+++ b/openslides/topics/models.py
@@ -78,7 +78,13 @@ class Topic(RESTModelMixin, models.Model):
return self.agenda_item.pk
def get_agenda_title(self):
+ """
+ Returns the title for the agenda.
+ """
return self.title
- def get_agenda_list_view_title(self):
- return self.title
+ def get_agenda_title_with_type(self):
+ """
+ Returns the agenda title. Topicy should not get a type postfix.
+ """
+ return self.get_agenda_title()
diff --git a/tests/integration/agenda/test_viewset.py b/tests/integration/agenda/test_viewset.py
index 678aa49c9..9a44ad069 100644
--- a/tests/integration/agenda/test_viewset.py
+++ b/tests/integration/agenda/test_viewset.py
@@ -69,7 +69,7 @@ class RetrieveItem(TestCase):
'content_object',)))
forbidden_keys = (
'item_number',
- 'list_view_title',
+ 'title_with_type',
'comment',
'closed',
'type',