diff --git a/client/src/app/site/mediafiles/components/mediafile-list/mediafile-list.component.html b/client/src/app/site/mediafiles/components/mediafile-list/mediafile-list.component.html index 85ed20422..04006bf3c 100644 --- a/client/src/app/site/mediafiles/components/mediafile-list/mediafile-list.component.html +++ b/client/src/app/site/mediafiles/components/mediafile-list/mediafile-list.component.html @@ -67,6 +67,14 @@ + + + Projector + + + + + Name diff --git a/client/src/app/site/mediafiles/components/mediafile-list/mediafile-list.component.ts b/client/src/app/site/mediafiles/components/mediafile-list/mediafile-list.component.ts index e954657cf..a1d001196 100644 --- a/client/src/app/site/mediafiles/components/mediafile-list/mediafile-list.component.ts +++ b/client/src/app/site/mediafiles/components/mediafile-list/mediafile-list.component.ts @@ -278,9 +278,12 @@ export class MediafileListComponent extends ListViewBaseComponent * @returns the column definition for the screen size */ public getColumnDefinition(): string[] { - const columns = this.vp.isMobile ? this.displayedColumnsMobile : this.displayedColumnsDesktop; + let columns = this.vp.isMobile ? this.displayedColumnsMobile : this.displayedColumnsDesktop; + if (this.operator.hasPerms('core.can_manage_projector')) { + columns = ['projector'].concat(columns); + } if (this.isMultiSelect) { - return ['selector'].concat(columns); + columns = ['selector'].concat(columns); } return columns; } diff --git a/client/src/app/site/mediafiles/models/view-mediafile.ts b/client/src/app/site/mediafiles/models/view-mediafile.ts index eca665fb2..8745c42e9 100644 --- a/client/src/app/site/mediafiles/models/view-mediafile.ts +++ b/client/src/app/site/mediafiles/models/view-mediafile.ts @@ -3,8 +3,10 @@ import { Mediafile } from 'app/shared/models/mediafiles/mediafile'; import { Searchable } from 'app/site/base/searchable'; import { SearchRepresentation } from 'app/core/ui-services/search.service'; import { ViewUser } from 'app/site/users/models/view-user'; +import { BaseProjectableViewModel } from 'app/site/base/base-projectable-view-model'; +import { ProjectorElementBuildDeskriptor } from 'app/site/base/projectable'; -export class ViewMediafile extends BaseViewModel implements Searchable { +export class ViewMediafile extends BaseProjectableViewModel implements Searchable { public static COLLECTIONSTRING = Mediafile.COLLECTIONSTRING; private _mediafile: Mediafile; @@ -86,6 +88,19 @@ export class ViewMediafile extends BaseViewModel implements Searchable { throw new Error('TODO'); } + public getSlide(): ProjectorElementBuildDeskriptor { + return { + getBasicProjectorElement: () => ({ + name: Mediafile.COLLECTIONSTRING, + id: this.id, + getIdentifiers: () => ['name', 'id'] + }), + slideOptions: [], + projectionDefaultName: 'mediafiles', + getTitle: () => this.getTitle() + }; + } + /** * Determine if the file is an image * diff --git a/client/src/app/slides/all-slide-configurations.ts b/client/src/app/slides/all-slide-configurations.ts index b9e33bbc0..9f4dac2aa 100644 --- a/client/src/app/slides/all-slide-configurations.ts +++ b/client/src/app/slides/all-slide-configurations.ts @@ -45,5 +45,10 @@ export const allSlidesDynamicConfiguration: (SlideDynamicConfiguration & Slide)[ slide: 'assignments/assignment', scaleable: true, scrollable: true + }, + { + slide: 'mediafiles/mediafile', + scaleable: true, + scrollable: true } ]; diff --git a/client/src/app/slides/all-slides.ts b/client/src/app/slides/all-slides.ts index 166afae41..069a88e79 100644 --- a/client/src/app/slides/all-slides.ts +++ b/client/src/app/slides/all-slides.ts @@ -81,5 +81,13 @@ export const allSlides: SlideManifest[] = [ verboseName: 'Election', elementIdentifiers: ['name', 'id'], canBeMappedToModel: true + }, + { + slide: 'mediafiles/mediafile', + path: 'mediafiles/mediafile', + loadChildren: './slides/mediafiles/mediafile/mediafile-slide.module#MediafileSlideModule', + verboseName: 'File', + elementIdentifiers: ['name', 'id'], + canBeMappedToModel: true } ]; diff --git a/client/src/app/slides/mediafiles/mediafile/mediafile-slide-data.ts b/client/src/app/slides/mediafiles/mediafile/mediafile-slide-data.ts new file mode 100644 index 000000000..9705ef8b7 --- /dev/null +++ b/client/src/app/slides/mediafiles/mediafile/mediafile-slide-data.ts @@ -0,0 +1,5 @@ +export interface MediafileSlideData { + path: string; + type: string; + media_url_prefix: string; +} diff --git a/client/src/app/slides/mediafiles/mediafile/mediafile-slide.component.html b/client/src/app/slides/mediafiles/mediafile/mediafile-slide.component.html new file mode 100644 index 000000000..0aeb50f15 --- /dev/null +++ b/client/src/app/slides/mediafiles/mediafile/mediafile-slide.component.html @@ -0,0 +1,5 @@ +
+

{{ data.data.path }}

+

{{ data.data.type }}

+

{{ data.data.media_url_prefix }}

+
diff --git a/client/src/app/slides/mediafiles/mediafile/mediafile-slide.component.scss b/client/src/app/slides/mediafiles/mediafile/mediafile-slide.component.scss new file mode 100644 index 000000000..e69de29bb diff --git a/client/src/app/slides/mediafiles/mediafile/mediafile-slide.component.spec.ts b/client/src/app/slides/mediafiles/mediafile/mediafile-slide.component.spec.ts new file mode 100644 index 000000000..49b245453 --- /dev/null +++ b/client/src/app/slides/mediafiles/mediafile/mediafile-slide.component.spec.ts @@ -0,0 +1,26 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { MediafileSlideComponent } from './mediafile-slide.component'; +import { E2EImportsModule } from '../../../../e2e-imports.module'; + +describe('MediafileSlideComponent', () => { + let component: MediafileSlideComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [E2EImportsModule], + declarations: [MediafileSlideComponent] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(MediafileSlideComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/client/src/app/slides/mediafiles/mediafile/mediafile-slide.component.ts b/client/src/app/slides/mediafiles/mediafile/mediafile-slide.component.ts new file mode 100644 index 000000000..cab715e8b --- /dev/null +++ b/client/src/app/slides/mediafiles/mediafile/mediafile-slide.component.ts @@ -0,0 +1,15 @@ +import { Component } from '@angular/core'; + +import { BaseSlideComponent } from 'app/slides/base-slide-component'; +import { MediafileSlideData } from './mediafile-slide-data'; + +@Component({ + selector: 'os-mediafile-slide', + templateUrl: './mediafile-slide.component.html', + styleUrls: ['./mediafile-slide.component.scss'] +}) +export class MediafileSlideComponent extends BaseSlideComponent { + public constructor() { + super(); + } +} diff --git a/client/src/app/slides/mediafiles/mediafile/mediafile-slide.module.spec.ts b/client/src/app/slides/mediafiles/mediafile/mediafile-slide.module.spec.ts new file mode 100644 index 000000000..dc41d3c1a --- /dev/null +++ b/client/src/app/slides/mediafiles/mediafile/mediafile-slide.module.spec.ts @@ -0,0 +1,13 @@ +import { MediafileSlideModule } from './mediafile-slide.module'; + +describe('MediafileSlideModule', () => { + let usersUserSlideModule: MediafileSlideModule; + + beforeEach(() => { + usersUserSlideModule = new MediafileSlideModule(); + }); + + it('should create an instance', () => { + expect(usersUserSlideModule).toBeTruthy(); + }); +}); diff --git a/client/src/app/slides/mediafiles/mediafile/mediafile-slide.module.ts b/client/src/app/slides/mediafiles/mediafile/mediafile-slide.module.ts new file mode 100644 index 000000000..39935f7f1 --- /dev/null +++ b/client/src/app/slides/mediafiles/mediafile/mediafile-slide.module.ts @@ -0,0 +1,7 @@ +import { NgModule } from '@angular/core'; + +import { makeSlideModule } from 'app/slides/base-slide-module'; +import { MediafileSlideComponent } from './mediafile-slide.component'; + +@NgModule(makeSlideModule(MediafileSlideComponent)) +export class MediafileSlideModule {} diff --git a/openslides/mediafiles/projector.py b/openslides/mediafiles/projector.py index b62104725..c3394deda 100644 --- a/openslides/mediafiles/projector.py +++ b/openslides/mediafiles/projector.py @@ -1,6 +1,10 @@ from typing import Any, Dict -from ..utils.projector import AllData, register_projector_slide +from ..utils.projector import ( + AllData, + ProjectorElementException, + register_projector_slide, +) # Important: All functions have to be prune. This means, that thay can only @@ -13,7 +17,23 @@ def mediafile_slide(all_data: AllData, element: Dict[str, Any]) -> Dict[str, Any """ Slide for Mediafile. """ - return {"error": "TODO"} + mediafile_id = element.get("id") + + if mediafile_id is None: + raise ProjectorElementException("id is required for mediafile slide") + + try: + mediafile = all_data["mediafiles/mediafile"][mediafile_id] + except KeyError: + raise ProjectorElementException( + f"mediafile with id {mediafile_id} does not exist" + ) + + return { + "path": mediafile["mediafile"]["name"], + "type": mediafile["mediafile"]["type"], + "media_url_prefix": mediafile["media_url_prefix"], + } def register_projector_slides() -> None: diff --git a/openslides/motions/projector.py b/openslides/motions/projector.py index 1ae69fb88..f33b607dc 100644 --- a/openslides/motions/projector.py +++ b/openslides/motions/projector.py @@ -55,7 +55,7 @@ def motion_slide(all_data: AllData, element: Dict[str, Any]) -> Dict[str, Any]: motion_id = element.get("id") if motion_id is None: - return {"error": "id is required for motion slide"} + raise ProjectorElementException("id is required for motion slide") try: motion = all_data["motions/motion"][motion_id]