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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
|
@ -131,4 +131,61 @@ export class TreeService {
|
||||
const tree = this.makeTree(items, weightKey, parentIdKey);
|
||||
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>
|
||||
</button>
|
||||
<button mat-menu-item (click)="multiselectWrapper(multiselectService.moveToItem(selectedRows))">
|
||||
<!-- TODO: Not implemented yet -->
|
||||
<mat-icon>sort</mat-icon>
|
||||
<span translate>Move to agenda item</span>
|
||||
</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 *ngIf="perms.isAllowed('manage')">
|
||||
<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 { Identifiable } from 'app/shared/models/base/identifiable';
|
||||
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.
|
||||
@ -37,6 +38,7 @@ export class MotionMultiselectService {
|
||||
* @param agendaRepo
|
||||
* @param motionBlockRepo
|
||||
* @param httpService
|
||||
* @param treeService
|
||||
*/
|
||||
public constructor(
|
||||
private repo: MotionRepositoryService,
|
||||
@ -49,7 +51,8 @@ export class MotionMultiselectService {
|
||||
private tagRepo: TagRepositoryService,
|
||||
private agendaRepo: ItemRepositoryService,
|
||||
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