Handling of titles, projection and content objects in items
Restructure the titles for motion, motion-block, assignment and topic. Less possibilities for more clear code. Added mote base models enabling functionalities of projection and being a content object for items
This commit is contained in:
parent
68b39ee8f4
commit
1ee76de417
@ -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.
|
||||
|
@ -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';
|
||||
|
||||
|
@ -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';
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
<mat-select [formControl]="formControl" placeholder="{{listname}}" multiple="{{multiple}}" #thisSelector>
|
||||
<ngx-mat-select-search [formControl]="filterControl"></ngx-mat-select-search>
|
||||
<mat-option *ngFor="let selectedItem of filteredItems | async" [value]="selectedItem">
|
||||
{{selectedItem.toString()}}
|
||||
{{selectedItem.getTitle(translate)}}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
@ -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';
|
||||
* </os-search-value-selector>
|
||||
* ```
|
||||
*
|
||||
* ### 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<SelectorItem[]> = new ReplaySubject<SelectorItem[]>(1);
|
||||
public filteredItems: ReplaySubject<Displayable[]> = new ReplaySubject<Displayable[]>(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
|
||||
|
@ -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;
|
||||
}
|
@ -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<BaseModel>(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);
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Deserializer } from '../deserializer.model';
|
||||
import { Deserializer } from '../base/deserializer';
|
||||
|
||||
/**
|
||||
* Representation of a speaker in an agenda item
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Deserializer } from '../deserializer.model';
|
||||
import { Deserializer } from '../base/deserializer';
|
||||
|
||||
/**
|
||||
* Content of the 'assignment_related_users' property
|
||||
|
@ -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);
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Deserializer } from '../deserializer.model';
|
||||
import { Deserializer } from '../base/deserializer';
|
||||
|
||||
/**
|
||||
* Representation of a poll option
|
||||
|
@ -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
|
||||
|
37
client/src/app/shared/models/base/agenda-base-model.ts
Normal file
37
client/src/app/shared/models/base/agenda-base-model.ts
Normal file
@ -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;
|
||||
}
|
19
client/src/app/shared/models/base/agenda-information.ts
Normal file
19
client/src/app/shared/models/base/agenda-information.ts
Normal file
@ -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;
|
||||
}
|
@ -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<T extends BaseModel> {
|
||||
new (...args: any[]): T;
|
||||
@ -10,7 +10,7 @@ export interface ModelConstructor<T extends BaseModel> {
|
||||
/**
|
||||
* 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.
|
@ -1,4 +1,4 @@
|
||||
import { Deserializable } from './deserializable.model';
|
||||
import { Deserializable } from './deserializable';
|
||||
|
||||
/**
|
||||
* Abstract base class for a basic implementation of Deserializable.
|
14
client/src/app/shared/models/base/displayable.ts
Normal file
14
client/src/app/shared/models/base/displayable.ts
Normal file
@ -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;
|
||||
}
|
17
client/src/app/shared/models/base/projectable-base-model.ts
Normal file
17
client/src/app/shared/models/base/projectable-base-model.ts
Normal file
@ -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();
|
||||
}
|
||||
}
|
14
client/src/app/shared/models/base/projectable.ts
Normal file
14
client/src/app/shared/models/base/projectable.ts
Normal file
@ -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;
|
||||
}
|
@ -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';
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Deserializer } from '../deserializer.model';
|
||||
import { Deserializer } from '../base/deserializer';
|
||||
|
||||
/**
|
||||
* The name and the type of a mediaFile.
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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';
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Deserializer } from '../deserializer.model';
|
||||
import { Deserializer } from '../base/deserializer';
|
||||
|
||||
/**
|
||||
* Representation of a Motion Comment.
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Deserializer } from '../deserializer.model';
|
||||
import { Deserializer } from '../base/deserializer';
|
||||
|
||||
/**
|
||||
* Representation of a Motion Log.
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Deserializer } from '../deserializer.model';
|
||||
import { Deserializer } from '../base/deserializer';
|
||||
import { User } from '../users/user';
|
||||
|
||||
/**
|
||||
|
@ -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 <identifier>'.
|
||||
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 <identifier>' 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);
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Deserializer } from '../deserializer.model';
|
||||
import { Deserializer } from '../base/deserializer';
|
||||
import { Workflow } from './workflow';
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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';
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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';
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -153,8 +153,8 @@
|
||||
</div>
|
||||
<div *ngIf="!editMotion || !newMotion">
|
||||
<h3 translate>Submitters</h3>
|
||||
<ul *ngFor="let submitters of motion.submitters">
|
||||
<li>{{submitters}}</li>
|
||||
<ul *ngFor="let submitter of motion.submitters">
|
||||
<li>{{submitter.full_name}}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
@ -169,8 +169,8 @@
|
||||
</div>
|
||||
<div *ngIf="!editMotion && motion.hasSupporters()">
|
||||
<h3 translate>Supporters</h3>
|
||||
<ul *ngFor="let supporters of motion.supporters">
|
||||
<li>{{supporters}}</li>
|
||||
<ul *ngFor="let supporter of motion.supporters">
|
||||
<li>{{supporter.full_name}}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -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';
|
||||
|
||||
|
@ -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):
|
||||
|
@ -45,7 +45,7 @@ class ItemSerializer(ModelSerializer):
|
||||
'id',
|
||||
'item_number',
|
||||
'title',
|
||||
'list_view_title',
|
||||
'title_with_type',
|
||||
'comment',
|
||||
'closed',
|
||||
'type',
|
||||
|
@ -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):
|
||||
|
@ -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):
|
||||
|
@ -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()
|
||||
|
@ -69,7 +69,7 @@ class RetrieveItem(TestCase):
|
||||
'content_object',)))
|
||||
forbidden_keys = (
|
||||
'item_number',
|
||||
'list_view_title',
|
||||
'title_with_type',
|
||||
'comment',
|
||||
'closed',
|
||||
'type',
|
||||
|
Loading…
Reference in New Issue
Block a user