Merge pull request #6186 from tsiegleauq/import-supporter
Add CSV import for supporters
This commit is contained in:
commit
18ffcaca92
@ -32,6 +32,11 @@ export class ImportCreateMotion extends CreateMotion {
|
|||||||
*/
|
*/
|
||||||
public csvSubmitters: CsvMapping[];
|
public csvSubmitters: CsvMapping[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mapping for new/existing supporters.
|
||||||
|
*/
|
||||||
|
public csvSupporters: CsvMapping[];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mapping for new/existing tags.
|
* Mapping for new/existing tags.
|
||||||
*/
|
*/
|
||||||
@ -115,6 +120,30 @@ export class ImportCreateMotion extends CreateMotion {
|
|||||||
return open;
|
return open;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public solveSupporters(supporters: CsvMapping[]): number {
|
||||||
|
let open = 0;
|
||||||
|
const ids: number[] = [];
|
||||||
|
this.csvSupporters.forEach(csvSupporter => {
|
||||||
|
if (csvSupporter.id) {
|
||||||
|
ids.push(csvSupporter.id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!supporters.length) {
|
||||||
|
open += 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const mapped = supporters.find(newSupporter => newSupporter.name === csvSupporter.name);
|
||||||
|
if (mapped) {
|
||||||
|
csvSupporter.id = mapped.id;
|
||||||
|
ids.push(mapped.id);
|
||||||
|
} else {
|
||||||
|
open += 1;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.supporters_id = ids;
|
||||||
|
return open;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function to iterate over the found tags.
|
* Function to iterate over the found tags.
|
||||||
*
|
*
|
||||||
|
@ -18,8 +18,7 @@
|
|||||||
<br />
|
<br />
|
||||||
<div class="code red-warning-text">
|
<div class="code red-warning-text">
|
||||||
<span *ngFor="let header of this.expectedHeader; let last = last">
|
<span *ngFor="let header of this.expectedHeader; let last = last">
|
||||||
<span>{{ header | translate }}</span
|
{{ header | translate }}<span *ngIf="!last">, </span>
|
||||||
><span *ngIf="!last">, </span>
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<ul>
|
<ul>
|
||||||
@ -41,11 +40,7 @@
|
|||||||
<div class="wrapper">
|
<div class="wrapper">
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-label>{{ 'Encoding of the file' | translate }}</mat-label>
|
<mat-label>{{ 'Encoding of the file' | translate }}</mat-label>
|
||||||
<mat-select
|
<mat-select class="selection" (selectionChange)="selectEncoding($event)" [value]="encodings[0].value">
|
||||||
class="selection"
|
|
||||||
(selectionChange)="selectEncoding($event)"
|
|
||||||
[value]="encodings[0].value"
|
|
||||||
>
|
|
||||||
<mat-option *ngFor="let option of encodings" [value]="option.value">
|
<mat-option *ngFor="let option of encodings" [value]="option.value">
|
||||||
{{ option.label | translate }}
|
{{ option.label | translate }}
|
||||||
</mat-option>
|
</mat-option>
|
||||||
@ -220,6 +215,27 @@
|
|||||||
</mat-cell>
|
</mat-cell>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
|
<!-- supporters column -->
|
||||||
|
<ng-container matColumnDef="supporters">
|
||||||
|
<mat-header-cell *matHeaderCellDef>{{ 'Supporters' | translate }}</mat-header-cell>
|
||||||
|
<mat-cell *matCellDef="let entry">
|
||||||
|
<div *ngIf="entry.newEntry?.csvSupporters?.length">
|
||||||
|
<mat-icon
|
||||||
|
color="warn"
|
||||||
|
*ngIf="hasError(entry, 'Supporters')"
|
||||||
|
matTooltip="{{ getVerboseError('Supporters') | translate }}"
|
||||||
|
>
|
||||||
|
warning
|
||||||
|
</mat-icon>
|
||||||
|
<div *ngFor="let supporters of entry.newEntry.csvSupporters">
|
||||||
|
{{ supporters.name }}
|
||||||
|
<mat-icon class="newBadge" color="accent" inline *ngIf="!supporters.id">add</mat-icon>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</mat-cell>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
<!-- category column -->
|
<!-- category column -->
|
||||||
<ng-container matColumnDef="category">
|
<ng-container matColumnDef="category">
|
||||||
<mat-header-cell *matHeaderCellDef>{{ 'Category' | translate }}</mat-header-cell>
|
<mat-header-cell *matHeaderCellDef>{{ 'Category' | translate }}</mat-header-cell>
|
||||||
|
@ -175,6 +175,7 @@ export class MotionCsvExportService {
|
|||||||
const headerRow = [
|
const headerRow = [
|
||||||
'Identifier',
|
'Identifier',
|
||||||
'Submitters',
|
'Submitters',
|
||||||
|
'Supporters',
|
||||||
'Title',
|
'Title',
|
||||||
'Text',
|
'Text',
|
||||||
'Reason',
|
'Reason',
|
||||||
@ -187,6 +188,7 @@ export class MotionCsvExportService {
|
|||||||
[
|
[
|
||||||
'A1',
|
'A1',
|
||||||
'Submitter A',
|
'Submitter A',
|
||||||
|
'Supporter A',
|
||||||
'Title 1',
|
'Title 1',
|
||||||
'Text 1',
|
'Text 1',
|
||||||
'Reason 1',
|
'Reason 1',
|
||||||
@ -195,8 +197,19 @@ export class MotionCsvExportService {
|
|||||||
'Block A',
|
'Block A',
|
||||||
'Last Year Conference A'
|
'Last Year Conference A'
|
||||||
],
|
],
|
||||||
['B1', 'Submitter B', 'Title 2', 'Text 2', 'Reason 2', 'Category B', null, 'Block A', 'Origin B'],
|
[
|
||||||
['C2', null, 'Title 3', 'Text 3', null, null, null, null, null]
|
'B1',
|
||||||
|
'Submitter B',
|
||||||
|
'Supporter B',
|
||||||
|
'Title 2',
|
||||||
|
'Text 2',
|
||||||
|
'Reason 2',
|
||||||
|
'Category B',
|
||||||
|
null,
|
||||||
|
'Block A',
|
||||||
|
'Origin B'
|
||||||
|
],
|
||||||
|
['C2', null, null, 'Title 3', 'Text 3', null, null, null, null, null]
|
||||||
];
|
];
|
||||||
this.csvExport.dummyCSVExport(headerRow, rows, `${this.translate.instant('motions-example')}.csv`);
|
this.csvExport.dummyCSVExport(headerRow, rows, `${this.translate.instant('motions-example')}.csv`);
|
||||||
}
|
}
|
||||||
|
@ -48,6 +48,11 @@ export class MotionImportService extends BaseImportService<Motion> {
|
|||||||
*/
|
*/
|
||||||
public newSubmitters: CsvMapping[] = [];
|
public newSubmitters: CsvMapping[] = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* supporters that need to be created prior to importing
|
||||||
|
*/
|
||||||
|
public newSupporters: CsvMapping[] = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Categories that need to be created prior to importing
|
* Categories that need to be created prior to importing
|
||||||
*/
|
*/
|
||||||
@ -92,6 +97,7 @@ export class MotionImportService extends BaseImportService<Motion> {
|
|||||||
*/
|
*/
|
||||||
public clearData(): void {
|
public clearData(): void {
|
||||||
this.newSubmitters = [];
|
this.newSubmitters = [];
|
||||||
|
this.newSupporters = [];
|
||||||
this.newCategories = [];
|
this.newCategories = [];
|
||||||
this.newMotionBlocks = [];
|
this.newMotionBlocks = [];
|
||||||
this.newTags = [];
|
this.newTags = [];
|
||||||
@ -110,7 +116,10 @@ export class MotionImportService extends BaseImportService<Motion> {
|
|||||||
for (let idx = 0; idx < headerLength; idx++) {
|
for (let idx = 0; idx < headerLength; idx++) {
|
||||||
switch (this.expectedHeader[idx]) {
|
switch (this.expectedHeader[idx]) {
|
||||||
case 'submitters':
|
case 'submitters':
|
||||||
newEntry.csvSubmitters = this.getSubmitters(line[idx]);
|
newEntry.csvSubmitters = this.getUsers(line[idx], 'submitter');
|
||||||
|
break;
|
||||||
|
case 'supporters':
|
||||||
|
newEntry.csvSupporters = this.getUsers(line[idx], 'supporter');
|
||||||
break;
|
break;
|
||||||
case 'category':
|
case 'category':
|
||||||
newEntry.csvCategory = this.getCategory(line[idx]);
|
newEntry.csvCategory = this.getCategory(line[idx]);
|
||||||
@ -150,7 +159,8 @@ export class MotionImportService extends BaseImportService<Motion> {
|
|||||||
public async doImport(): Promise<void> {
|
public async doImport(): Promise<void> {
|
||||||
this.newMotionBlocks = await this.createNewMotionBlocks();
|
this.newMotionBlocks = await this.createNewMotionBlocks();
|
||||||
this.newCategories = await this.createNewCategories();
|
this.newCategories = await this.createNewCategories();
|
||||||
this.newSubmitters = await this.createNewUsers();
|
this.newSubmitters = await this.createNewUsers(this.newSubmitters);
|
||||||
|
this.newSupporters = await this.createNewUsers(this.newSupporters);
|
||||||
this.newTags = await this.createNewTags();
|
this.newTags = await this.createNewTags();
|
||||||
|
|
||||||
for (const entry of this.entries) {
|
for (const entry of this.entries) {
|
||||||
@ -169,12 +179,18 @@ export class MotionImportService extends BaseImportService<Motion> {
|
|||||||
this.updatePreview();
|
this.updatePreview();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const openUsers = (entry.newEntry as ImportCreateMotion).solveSubmitters(this.newSubmitters);
|
const openSubmitters = (entry.newEntry as ImportCreateMotion).solveSubmitters(this.newSubmitters);
|
||||||
if (openUsers) {
|
if (openSubmitters) {
|
||||||
this.setError(entry, 'Submitters');
|
this.setError(entry, 'Submitters');
|
||||||
this.updatePreview();
|
this.updatePreview();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
const openSupporters = (entry.newEntry as ImportCreateMotion).solveSupporters(this.newSupporters);
|
||||||
|
if (openSupporters) {
|
||||||
|
this.setError(entry, 'Supporters');
|
||||||
|
this.updatePreview();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
const openTags = (entry.newEntry as ImportCreateMotion).solveTags(this.newTags);
|
const openTags = (entry.newEntry as ImportCreateMotion).solveTags(this.newTags);
|
||||||
if (openTags) {
|
if (openTags) {
|
||||||
this.setError(entry, 'Tags');
|
this.setError(entry, 'Tags');
|
||||||
@ -191,39 +207,51 @@ export class MotionImportService extends BaseImportService<Motion> {
|
|||||||
* Checks the provided submitter(s) and returns an object with mapping of
|
* Checks the provided submitter(s) and returns an object with mapping of
|
||||||
* existing users and of users that need to be created
|
* existing users and of users that need to be created
|
||||||
*
|
*
|
||||||
* @param submitterlist
|
* @param userList
|
||||||
* @returns a list of submitters mapped with (if already existing) their id
|
* @returns a list of submitters mapped with (if already existing) their id
|
||||||
*/
|
*/
|
||||||
public getSubmitters(submitterlist: string): CsvMapping[] {
|
public getUsers(userList: string, kind: 'submitter' | 'supporter'): CsvMapping[] {
|
||||||
|
console.log('kind: ', kind);
|
||||||
const result: CsvMapping[] = [];
|
const result: CsvMapping[] = [];
|
||||||
if (!submitterlist) {
|
if (!userList) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
const submitterArray = submitterlist.split(','); // TODO fails with 'full name'
|
const userArray = userList.split(','); // TODO fails with 'full name'
|
||||||
for (const submitter of submitterArray) {
|
|
||||||
const existingSubmitters = this.userRepo.getUsersByName(submitter.trim());
|
console.log('userArray: ', userList);
|
||||||
if (!existingSubmitters.length) {
|
for (const user of userArray) {
|
||||||
if (!this.newSubmitters.find(listedSubmitter => listedSubmitter.name === submitter)) {
|
const existingUsers = this.userRepo.getUsersByName(user.trim());
|
||||||
this.newSubmitters.push({ name: submitter });
|
if (!existingUsers.length) {
|
||||||
|
if (kind === 'submitter') {
|
||||||
|
if (!this.newSubmitters.find(listedSubmitter => listedSubmitter.name === user)) {
|
||||||
|
this.newSubmitters.push({ name: user });
|
||||||
|
}
|
||||||
|
result.push({ name: user });
|
||||||
|
} else if (kind === 'supporter') {
|
||||||
|
if (!this.newSupporters.find(listedSupporter => listedSupporter.name === user)) {
|
||||||
|
this.newSupporters.push({ name: user });
|
||||||
|
}
|
||||||
|
result.push({ name: user });
|
||||||
}
|
}
|
||||||
result.push({ name: submitter });
|
|
||||||
}
|
}
|
||||||
if (existingSubmitters.length === 1) {
|
if (existingUsers.length === 1) {
|
||||||
result.push({
|
result.push({
|
||||||
name: existingSubmitters[0].short_name,
|
name: existingUsers[0].short_name,
|
||||||
id: existingSubmitters[0].id
|
id: existingUsers[0].id
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (existingSubmitters.length > 1) {
|
if (existingUsers.length > 1) {
|
||||||
result.push({
|
result.push({
|
||||||
name: submitter,
|
name: user,
|
||||||
multiId: existingSubmitters.map(ex => ex.id)
|
multiId: existingUsers.map(ex => ex.id)
|
||||||
});
|
});
|
||||||
this.matSnackbar.open('TODO: multiple possible users found for this string', 'ok');
|
this.matSnackbar.open('TODO: multiple possible users found for this string', 'ok');
|
||||||
// TODO How to handle several submitters ? Is this possible?
|
// TODO How to handle several submitters ? Is this possible?
|
||||||
// should have some kind of choice dialog there
|
// should have some kind of choice dialog there
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log('res: ', result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -331,9 +359,9 @@ export class MotionImportService extends BaseImportService<Motion> {
|
|||||||
*
|
*
|
||||||
* @returns a promise with list of new Submitters, updated with newly created ids
|
* @returns a promise with list of new Submitters, updated with newly created ids
|
||||||
*/
|
*/
|
||||||
private async createNewUsers(): Promise<CsvMapping[]> {
|
private async createNewUsers(list: CsvMapping[]): Promise<CsvMapping[]> {
|
||||||
const promises: Promise<CsvMapping>[] = [];
|
const promises: Promise<CsvMapping>[] = [];
|
||||||
for (const user of this.newSubmitters) {
|
for (const user of list) {
|
||||||
promises.push(this.userRepo.createFromString(user.name));
|
promises.push(this.userRepo.createFromString(user.name));
|
||||||
}
|
}
|
||||||
return await Promise.all(promises);
|
return await Promise.all(promises);
|
||||||
|
@ -700,7 +700,7 @@ button.mat-menu-item.selected {
|
|||||||
|
|
||||||
.first-column {
|
.first-column {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
min-width: 0px;
|
min-width: 40px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.filter-imports {
|
.filter-imports {
|
||||||
|
Loading…
Reference in New Issue
Block a user