Merge pull request #4253 from MaximilianKrambach/sortMotionCallList
bulk move motions in call list
This commit is contained in:
commit
7dd086eacf
@ -319,6 +319,19 @@ export class MotionRepositoryService extends BaseRepository<ViewMotion, Motion>
|
|||||||
await this.httpService.post(url, data);
|
await this.httpService.post(url, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends the changed nodes to the server, with only the top nodes being submitted.
|
||||||
|
*
|
||||||
|
* @param data The reordered data from the sorting, as list of ViewMotions
|
||||||
|
* @param parent a parent id
|
||||||
|
*/
|
||||||
|
public async sortMotionBranches(data: ViewMotion[], parent?: number): Promise<void> {
|
||||||
|
const url = '/rest/motions/motion/sort/';
|
||||||
|
const nodes = data.map(motion => ({ id: motion.id }));
|
||||||
|
const params = parent ? { nodes: nodes, parent_id: parent } : { nodes: nodes };
|
||||||
|
await this.httpService.post(url, params);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Supports the motion
|
* Supports the motion
|
||||||
*
|
*
|
||||||
|
@ -131,4 +131,61 @@ export class TreeService {
|
|||||||
const tree = this.makeTree(items, weightKey, parentIdKey);
|
const tree = this.makeTree(items, weightKey, parentIdKey);
|
||||||
return this.traverseTree(tree);
|
return this.traverseTree(tree);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reduce a list of items to nodes independent from each other in a given
|
||||||
|
* branch of a tree
|
||||||
|
*
|
||||||
|
* @param branch the tree to traverse
|
||||||
|
* @param items the items to check
|
||||||
|
* @returns the selection of items that belong to different branches
|
||||||
|
*/
|
||||||
|
private getTopItemsFromBranch<T extends Identifiable & Displayable>(branch: OSTreeNode<T>, items: T[]): T[] {
|
||||||
|
const item = items.find(i => branch.item.id === i.id);
|
||||||
|
if (item) {
|
||||||
|
return [item];
|
||||||
|
} else if (!branch.children) {
|
||||||
|
return [];
|
||||||
|
} else {
|
||||||
|
return [].concat(...branch.children.map(child => this.getTopItemsFromBranch(child, items)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reduce a list of items to nodes independent from each other in a given tree
|
||||||
|
*
|
||||||
|
* @param tree the tree to traverse
|
||||||
|
* @param items the items to check
|
||||||
|
* @returns the selection of items that belong to different branches
|
||||||
|
*/
|
||||||
|
public getTopItemsFromTree<T extends Identifiable & Displayable>(tree: OSTreeNode<T>[], items: T[]): T[] {
|
||||||
|
let results: T[] = [];
|
||||||
|
tree.forEach(branch => {
|
||||||
|
const i = this.getTopItemsFromBranch(branch, items);
|
||||||
|
if (i.length) {
|
||||||
|
results = results.concat(i);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return all items not being hierarchically dependant on the items in the input arrray
|
||||||
|
*
|
||||||
|
* @param tree
|
||||||
|
* @param items
|
||||||
|
* @returns all items that are neither in the input nor dependants of items in the input
|
||||||
|
*/
|
||||||
|
public getTreeWithoutSelection<T extends Identifiable & Displayable>(tree: OSTreeNode<T>[], items: T[]): T[] {
|
||||||
|
let result: T[] = [];
|
||||||
|
tree.forEach(branch => {
|
||||||
|
if (!items.find(i => i.id === branch.item.id)) {
|
||||||
|
result.push(branch.item);
|
||||||
|
if (branch.children) {
|
||||||
|
result = result.concat(this.getTreeWithoutSelection(branch.children, items));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -248,10 +248,13 @@
|
|||||||
<span translate>Add/remove tags</span>
|
<span translate>Add/remove tags</span>
|
||||||
</button>
|
</button>
|
||||||
<button mat-menu-item (click)="multiselectWrapper(multiselectService.moveToItem(selectedRows))">
|
<button mat-menu-item (click)="multiselectWrapper(multiselectService.moveToItem(selectedRows))">
|
||||||
<!-- TODO: Not implemented yet -->
|
|
||||||
<mat-icon>sort</mat-icon>
|
<mat-icon>sort</mat-icon>
|
||||||
<span translate>Move to agenda item</span>
|
<span translate>Move to agenda item</span>
|
||||||
</button>
|
</button>
|
||||||
|
<button mat-menu-item (click)="multiselectWrapper(multiselectService.bulkMoveItems(selectedRows))">
|
||||||
|
<mat-icon>format_indent_increase</mat-icon>
|
||||||
|
<span translate>Move in call list</span>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="perms.isAllowed('manage')">
|
<div *ngIf="perms.isAllowed('manage')">
|
||||||
<mat-divider></mat-divider>
|
<mat-divider></mat-divider>
|
||||||
|
@ -15,6 +15,7 @@ import { ItemRepositoryService } from 'app/core/repositories/agenda/item-reposit
|
|||||||
import { Displayable } from 'app/site/base/displayable';
|
import { Displayable } from 'app/site/base/displayable';
|
||||||
import { Identifiable } from 'app/shared/models/base/identifiable';
|
import { Identifiable } from 'app/shared/models/base/identifiable';
|
||||||
import { MotionBlockRepositoryService } from 'app/core/repositories/motions/motion-block-repository.service';
|
import { MotionBlockRepositoryService } from 'app/core/repositories/motions/motion-block-repository.service';
|
||||||
|
import { TreeService } from 'app/core/ui-services/tree.service';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contains all multiselect actions for the motion list view.
|
* Contains all multiselect actions for the motion list view.
|
||||||
@ -37,6 +38,7 @@ export class MotionMultiselectService {
|
|||||||
* @param agendaRepo
|
* @param agendaRepo
|
||||||
* @param motionBlockRepo
|
* @param motionBlockRepo
|
||||||
* @param httpService
|
* @param httpService
|
||||||
|
* @param treeService
|
||||||
*/
|
*/
|
||||||
public constructor(
|
public constructor(
|
||||||
private repo: MotionRepositoryService,
|
private repo: MotionRepositoryService,
|
||||||
@ -49,7 +51,8 @@ export class MotionMultiselectService {
|
|||||||
private tagRepo: TagRepositoryService,
|
private tagRepo: TagRepositoryService,
|
||||||
private agendaRepo: ItemRepositoryService,
|
private agendaRepo: ItemRepositoryService,
|
||||||
private motionBlockRepo: MotionBlockRepositoryService,
|
private motionBlockRepo: MotionBlockRepositoryService,
|
||||||
private httpService: HttpService
|
private httpService: HttpService,
|
||||||
|
private treeService: TreeService
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -247,4 +250,37 @@ export class MotionMultiselectService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggers the selected motions to be moved in the call-list (sort_parent, weight)
|
||||||
|
* as children or as following after a selected motion.
|
||||||
|
*
|
||||||
|
* @param motions The motions to move
|
||||||
|
*/
|
||||||
|
public async bulkMoveItems(motions: ViewMotion[]): Promise<void> {
|
||||||
|
const title = this.translate.instant('This will assign the selected motions as belonging to:');
|
||||||
|
const options = ['Set as parent', 'Insert after'];
|
||||||
|
const allMotions = this.repo.getViewModelList();
|
||||||
|
const tree = this.treeService.makeTree(allMotions, 'weight', 'sort_parent_id');
|
||||||
|
const itemsToMove = this.treeService.getTopItemsFromTree(tree, motions);
|
||||||
|
const selectableItems = this.treeService.getTreeWithoutSelection(tree, motions);
|
||||||
|
|
||||||
|
const selectedChoice = await this.choiceService.open(title, selectableItems, false, options);
|
||||||
|
if (selectedChoice) {
|
||||||
|
if (selectedChoice.action === options[0]) {
|
||||||
|
// set choice as parent
|
||||||
|
this.repo.sortMotionBranches(itemsToMove, selectedChoice.items as number);
|
||||||
|
} else if (selectedChoice.action === options[1]) {
|
||||||
|
// insert after chosen
|
||||||
|
const olderSibling = this.repo.getViewModel(selectedChoice.items as number);
|
||||||
|
const parentId = olderSibling ? olderSibling.sort_parent_id : null;
|
||||||
|
const siblings = this.repo.getViewModelList().filter(motion => motion.sort_parent_id === parentId);
|
||||||
|
const idx = siblings.findIndex(sib => sib.id === olderSibling.id);
|
||||||
|
const before = siblings.slice(0, idx + 1);
|
||||||
|
const after = siblings.slice(idx + 1);
|
||||||
|
const sum = [].concat(before, itemsToMove, after);
|
||||||
|
this.repo.sortMotionBranches(sum, parentId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user