From 74647dc75d0631ec731edb8aff73da930a67cee3 Mon Sep 17 00:00:00 2001 From: FinnStutzenstein Date: Fri, 19 Jul 2019 13:43:33 +0200 Subject: [PATCH 1/2] sorting of motion comment sections --- ...tion-comment-section-repository.service.ts | 17 +++++ .../models/motions/motion-comment-section.ts | 1 + .../models/view-motion-comment-section.ts | 4 ++ .../0029_motioncommentsection_weight.py | 16 +++++ openslides/motions/models.py | 5 ++ openslides/motions/serializers.py | 3 +- openslides/motions/views.py | 36 +++++++++- tests/integration/motions/test_viewset.py | 71 +++++++++++++++++++ 8 files changed, 151 insertions(+), 2 deletions(-) create mode 100644 openslides/motions/migrations/0029_motioncommentsection_weight.py diff --git a/client/src/app/core/repositories/motions/motion-comment-section-repository.service.ts b/client/src/app/core/repositories/motions/motion-comment-section-repository.service.ts index a0c528341..dc57fdfa7 100644 --- a/client/src/app/core/repositories/motions/motion-comment-section-repository.service.ts +++ b/client/src/app/core/repositories/motions/motion-comment-section-repository.service.ts @@ -54,6 +54,14 @@ export class MotionCommentSectionRepositoryService extends BaseRepository< private http: HttpService ) { super(DS, dataSend, mapperService, viewModelStoreService, translate, MotionCommentSection, [Group]); + + this.viewModelSortFn = (a: ViewMotionCommentSection, b: ViewMotionCommentSection) => { + if (a.weight === b.weight) { + return a.id - b.id; + } else { + return a.weight - b.weight; + } + }; } public getTitle = (titleInformation: MotionCommentSectionTitleInformation) => { @@ -109,4 +117,13 @@ export class MotionCommentSectionRepositoryService extends BaseRepository< private async deleteComment(motion: ViewMotion, section: ViewMotionCommentSection): Promise { return await this.http.delete(`/rest/motions/motion/${motion.id}/manage_comments/`, { section_id: section.id }); } + + /** + * Sort all comment sections. All sections must be given excatly once. + */ + public async sortCommentSections(sections: ViewMotionCommentSection[]): Promise { + return await this.http.post('/rest/motions/motion-comment-section', { + ids: sections.map(section => section.id) + }); + } } 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 0e4a3d304..715cee484 100644 --- a/client/src/app/shared/models/motions/motion-comment-section.ts +++ b/client/src/app/shared/models/motions/motion-comment-section.ts @@ -11,6 +11,7 @@ export class MotionCommentSection extends BaseModel { public name: string; public read_groups_id: number[]; public write_groups_id: number[]; + public weight: number; public constructor(input?: any) { super(MotionCommentSection.COLLECTIONSTRING, input); diff --git a/client/src/app/site/motions/models/view-motion-comment-section.ts b/client/src/app/site/motions/models/view-motion-comment-section.ts index d14b2a7f1..6de22db6f 100644 --- a/client/src/app/site/motions/models/view-motion-comment-section.ts +++ b/client/src/app/site/motions/models/view-motion-comment-section.ts @@ -48,6 +48,10 @@ export class ViewMotionCommentSection extends BaseViewModel, , ...] } + """ + # Check request data format + ids = request.data.get("ids") + if not isinstance(ids, list): + raise ValidationError({"detail": "ids must be a list"}) + for id in ids: + if not isinstance(id, int): + raise ValidationError({"detail": "every id must be an int"}) + + # Validate, that every id is given exactly once. + ids_set = set(ids) + if len(ids_set) != len(ids): + raise ValidationError({"detail": "only unique ids are expected"}) + db_ids_set = set( + list(MotionCommentSection.objects.all().values_list(flat=True)) + ) + if ids_set != db_ids_set: + raise ValidationError({"detail": "every id must be given"}) + + # Ids are ok. + preserved = Case(*[When(pk=pk, then=pos) for pos, pk in enumerate(ids)]) + queryset = MotionCommentSection.objects.filter(pk__in=ids).order_by(preserved) + for index, section in enumerate(queryset): + section.weight = index + 1 + section.save() + + return Response() + class StatuteParagraphViewSet(ModelViewSet): """ diff --git a/tests/integration/motions/test_viewset.py b/tests/integration/motions/test_viewset.py index 2e60d00e2..7fccf8487 100644 --- a/tests/integration/motions/test_viewset.py +++ b/tests/integration/motions/test_viewset.py @@ -1331,6 +1331,77 @@ class TestMotionCommentSection(TestCase): self.assertEqual(MotionCommentSection.objects.count(), 1) +class TestMotionCommentSectionSorting(TestCase): + """ + Tests sorting of comment sections. + """ + + def setUp(self): + self.client = APIClient() + self.client.login(username="admin", password="admin") + self.section1 = MotionCommentSection(name="test_name_hponzp Date: Mon, 22 Jul 2019 15:46:26 +0200 Subject: [PATCH 2/2] Add motion comment section sort view --- ...tion-comment-section-repository.service.ts | 2 +- ...motion-comment-section-list.component.html | 14 +++++ ...motion-comment-section-list.component.scss | 0 ...ion-comment-section-list.component.spec.ts | 0 .../motion-comment-section-list.component.ts | 0 ...motion-comment-section-sort.component.html | 13 +++++ ...motion-comment-section-sort.component.scss | 0 ...ion-comment-section-sort.component.spec.ts | 26 +++++++++ .../motion-comment-section-sort.component.ts | 58 +++++++++++++++++++ .../motion-comment-section-routing.module.ts | 8 ++- .../motion-comment-section.module.ts | 5 +- 11 files changed, 121 insertions(+), 5 deletions(-) rename client/src/app/site/motions/modules/motion-comment-section/{ => components/motion-comment-section-list}/motion-comment-section-list.component.html (94%) rename client/src/app/site/motions/modules/motion-comment-section/{ => components/motion-comment-section-list}/motion-comment-section-list.component.scss (100%) rename client/src/app/site/motions/modules/motion-comment-section/{ => components/motion-comment-section-list}/motion-comment-section-list.component.spec.ts (100%) rename client/src/app/site/motions/modules/motion-comment-section/{ => components/motion-comment-section-list}/motion-comment-section-list.component.ts (100%) create mode 100644 client/src/app/site/motions/modules/motion-comment-section/components/motion-comment-section-sort/motion-comment-section-sort.component.html create mode 100644 client/src/app/site/motions/modules/motion-comment-section/components/motion-comment-section-sort/motion-comment-section-sort.component.scss create mode 100644 client/src/app/site/motions/modules/motion-comment-section/components/motion-comment-section-sort/motion-comment-section-sort.component.spec.ts create mode 100644 client/src/app/site/motions/modules/motion-comment-section/components/motion-comment-section-sort/motion-comment-section-sort.component.ts diff --git a/client/src/app/core/repositories/motions/motion-comment-section-repository.service.ts b/client/src/app/core/repositories/motions/motion-comment-section-repository.service.ts index dc57fdfa7..dd17723b1 100644 --- a/client/src/app/core/repositories/motions/motion-comment-section-repository.service.ts +++ b/client/src/app/core/repositories/motions/motion-comment-section-repository.service.ts @@ -122,7 +122,7 @@ export class MotionCommentSectionRepositoryService extends BaseRepository< * Sort all comment sections. All sections must be given excatly once. */ public async sortCommentSections(sections: ViewMotionCommentSection[]): Promise { - return await this.http.post('/rest/motions/motion-comment-section', { + return await this.http.post('/rest/motions/motion-comment-section/sort/', { ids: sections.map(section => section.id) }); } diff --git a/client/src/app/site/motions/modules/motion-comment-section/motion-comment-section-list.component.html b/client/src/app/site/motions/modules/motion-comment-section/components/motion-comment-section-list/motion-comment-section-list.component.html similarity index 94% rename from client/src/app/site/motions/modules/motion-comment-section/motion-comment-section-list.component.html rename to client/src/app/site/motions/modules/motion-comment-section/components/motion-comment-section-list/motion-comment-section-list.component.html index 0aa69809f..1ff2f71a2 100644 --- a/client/src/app/site/motions/modules/motion-comment-section/motion-comment-section-list.component.html +++ b/client/src/app/site/motions/modules/motion-comment-section/components/motion-comment-section-list/motion-comment-section-list.component.html @@ -3,6 +3,13 @@

Comment fields

+ + +
@@ -139,3 +146,10 @@ + + + + diff --git a/client/src/app/site/motions/modules/motion-comment-section/motion-comment-section-list.component.scss b/client/src/app/site/motions/modules/motion-comment-section/components/motion-comment-section-list/motion-comment-section-list.component.scss similarity index 100% rename from client/src/app/site/motions/modules/motion-comment-section/motion-comment-section-list.component.scss rename to client/src/app/site/motions/modules/motion-comment-section/components/motion-comment-section-list/motion-comment-section-list.component.scss diff --git a/client/src/app/site/motions/modules/motion-comment-section/motion-comment-section-list.component.spec.ts b/client/src/app/site/motions/modules/motion-comment-section/components/motion-comment-section-list/motion-comment-section-list.component.spec.ts similarity index 100% rename from client/src/app/site/motions/modules/motion-comment-section/motion-comment-section-list.component.spec.ts rename to client/src/app/site/motions/modules/motion-comment-section/components/motion-comment-section-list/motion-comment-section-list.component.spec.ts diff --git a/client/src/app/site/motions/modules/motion-comment-section/motion-comment-section-list.component.ts b/client/src/app/site/motions/modules/motion-comment-section/components/motion-comment-section-list/motion-comment-section-list.component.ts similarity index 100% rename from client/src/app/site/motions/modules/motion-comment-section/motion-comment-section-list.component.ts rename to client/src/app/site/motions/modules/motion-comment-section/components/motion-comment-section-list/motion-comment-section-list.component.ts diff --git a/client/src/app/site/motions/modules/motion-comment-section/components/motion-comment-section-sort/motion-comment-section-sort.component.html b/client/src/app/site/motions/modules/motion-comment-section/components/motion-comment-section-sort/motion-comment-section-sort.component.html new file mode 100644 index 000000000..d13edc176 --- /dev/null +++ b/client/src/app/site/motions/modules/motion-comment-section/components/motion-comment-section-sort/motion-comment-section-sort.component.html @@ -0,0 +1,13 @@ + + +
+

Sort Comments

+
+
+ + + + + + + diff --git a/client/src/app/site/motions/modules/motion-comment-section/components/motion-comment-section-sort/motion-comment-section-sort.component.scss b/client/src/app/site/motions/modules/motion-comment-section/components/motion-comment-section-sort/motion-comment-section-sort.component.scss new file mode 100644 index 000000000..e69de29bb diff --git a/client/src/app/site/motions/modules/motion-comment-section/components/motion-comment-section-sort/motion-comment-section-sort.component.spec.ts b/client/src/app/site/motions/modules/motion-comment-section/components/motion-comment-section-sort/motion-comment-section-sort.component.spec.ts new file mode 100644 index 000000000..a2d0bde5b --- /dev/null +++ b/client/src/app/site/motions/modules/motion-comment-section/components/motion-comment-section-sort/motion-comment-section-sort.component.spec.ts @@ -0,0 +1,26 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { MotionCommentSectionSortComponent } from './motion-comment-section-sort.component'; +import { E2EImportsModule } from 'e2e-imports.module'; + +describe('MotionCommentSectionSortComponent', () => { + let component: MotionCommentSectionSortComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [E2EImportsModule], + declarations: [MotionCommentSectionSortComponent] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(MotionCommentSectionSortComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/client/src/app/site/motions/modules/motion-comment-section/components/motion-comment-section-sort/motion-comment-section-sort.component.ts b/client/src/app/site/motions/modules/motion-comment-section/components/motion-comment-section-sort/motion-comment-section-sort.component.ts new file mode 100644 index 000000000..f5b604f88 --- /dev/null +++ b/client/src/app/site/motions/modules/motion-comment-section/components/motion-comment-section-sort/motion-comment-section-sort.component.ts @@ -0,0 +1,58 @@ +import { Component, OnInit } from '@angular/core'; +import { Title } from '@angular/platform-browser'; +import { MatSnackBar } from '@angular/material'; + +import { TranslateService } from '@ngx-translate/core'; + +import { BaseViewComponent } from 'app/site/base/base-view'; +import { MotionCommentSectionRepositoryService } from 'app/core/repositories/motions/motion-comment-section-repository.service'; +import { ViewMotionCommentSection } from 'app/site/motions/models/view-motion-comment-section'; + +/** + * Sorting view for motion comments + */ +@Component({ + selector: 'os-motion-comment-section-sort', + templateUrl: './motion-comment-section-sort.component.html', + styleUrls: ['./motion-comment-section-sort.component.scss'] +}) +export class MotionCommentSectionSortComponent extends BaseViewComponent implements OnInit { + /** + * Holds the models + */ + public comments: ViewMotionCommentSection[]; + + /** + * Constructor + * + * @param title Title service + * @param translate Translate service + * @param snackBar Snack bar + * @param repo Motion comment repository service + */ + public constructor( + title: Title, + translate: TranslateService, // protected required for ng-translate-extract + snackBar: MatSnackBar, + private repo: MotionCommentSectionRepositoryService + ) { + super(title, translate, snackBar); + super.setTitle('Sort comments'); + } + + /** + * Get the view models from the repo + */ + public ngOnInit(): void { + this.repo.getViewModelListObservable().subscribe(comments => (this.comments = comments)); + } + + /** + * Executed if the sorting changes + * + * @param commentsInOrder + */ + public onSortingChange(commentsInOrder: ViewMotionCommentSection[]): void { + this.repo.sortCommentSections(commentsInOrder).then(null, this.raiseError); + } +} diff --git a/client/src/app/site/motions/modules/motion-comment-section/motion-comment-section-routing.module.ts b/client/src/app/site/motions/modules/motion-comment-section/motion-comment-section-routing.module.ts index 914a92a0c..e31328b1b 100644 --- a/client/src/app/site/motions/modules/motion-comment-section/motion-comment-section-routing.module.ts +++ b/client/src/app/site/motions/modules/motion-comment-section/motion-comment-section-routing.module.ts @@ -1,9 +1,13 @@ import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; -import { MotionCommentSectionListComponent } from './motion-comment-section-list.component'; +import { MotionCommentSectionListComponent } from './components/motion-comment-section-list/motion-comment-section-list.component'; +import { MotionCommentSectionSortComponent } from './components/motion-comment-section-sort/motion-comment-section-sort.component'; -const routes: Routes = [{ path: '', component: MotionCommentSectionListComponent, pathMatch: 'full' }]; +const routes: Routes = [ + { path: '', component: MotionCommentSectionListComponent, pathMatch: 'full' }, + { path: 'sort', component: MotionCommentSectionSortComponent } +]; @NgModule({ imports: [RouterModule.forChild(routes)], diff --git a/client/src/app/site/motions/modules/motion-comment-section/motion-comment-section.module.ts b/client/src/app/site/motions/modules/motion-comment-section/motion-comment-section.module.ts index ad7b85c27..fb703e038 100644 --- a/client/src/app/site/motions/modules/motion-comment-section/motion-comment-section.module.ts +++ b/client/src/app/site/motions/modules/motion-comment-section/motion-comment-section.module.ts @@ -3,10 +3,11 @@ import { CommonModule } from '@angular/common'; import { MotionCommentSectionRoutingModule } from './motion-comment-section-routing.module'; import { SharedModule } from 'app/shared/shared.module'; -import { MotionCommentSectionListComponent } from './motion-comment-section-list.component'; +import { MotionCommentSectionListComponent } from './components/motion-comment-section-list/motion-comment-section-list.component'; +import { MotionCommentSectionSortComponent } from './components/motion-comment-section-sort/motion-comment-section-sort.component'; @NgModule({ - declarations: [MotionCommentSectionListComponent], + declarations: [MotionCommentSectionListComponent, MotionCommentSectionSortComponent], imports: [CommonModule, MotionCommentSectionRoutingModule, SharedModule] }) export class MotionCommentSectionModule {}