export results added, models updates

This commit is contained in:
Tykayn 2021-04-26 11:27:44 +02:00 committed by tykayn
parent 078f63f742
commit 1e90d92ab9
7 changed files with 201 additions and 29 deletions

View File

@ -3,7 +3,8 @@ import { User } from './user.model';
export class Choice { export class Choice {
constructor( constructor(
public label: string, public id: number,
public name: string,
public imageUrl?: string, public imageUrl?: string,
public participants: Map<Answer, Set<User>> = new Map<Answer, Set<User>>([ public participants: Map<Answer, Set<User>> = new Map<Answer, Set<User>>([
[Answer.YES, new Set<User>()], [Answer.YES, new Set<User>()],

View File

@ -1,11 +1,16 @@
export class Comment { import { User } from './user.model';
constructor(public author: string, public content: string, public dateCreated: Date) {}
public static sortChronologically(a: Comment, b: Comment): number { export class Comment {
if (a.dateCreated < b.dateCreated) { constructor(public owner: User, public text: string, public pseudo: string, public created_at: string) {}
public static sortChronologically(first: Comment, second: Comment): number {
const a = new Date(first.created_at);
const b = new Date(second.created_at);
if (a < b) {
return -1; return -1;
} }
if (a.dateCreated > b.dateCreated) { if (a > b) {
return 1; return 1;
} }
return 0; return 0;

View File

@ -8,9 +8,14 @@ import { User } from './user.model';
export class Poll { export class Poll {
constructor( constructor(
public owner: User = new User(), public owner: User = new User(),
public urlPublic: string = '',
public slug: string = '', public slug: string = '',
public id: number = 0,
public default_expiracy_days_from_now: number = 60,
public title: string = 'mon titre', public title: string = 'mon titre',
public kind: string,
public description?: string, public description?: string,
public custom_url?: string,
public expiracy_date?: string, public expiracy_date?: string,
public creation_date?: string, public creation_date?: string,
public creatorPseudo?: string, public creatorPseudo?: string,
@ -21,18 +26,13 @@ export class Poll {
public comments: Comment[] = [], public comments: Comment[] = [],
public choices: Choice[] = [], public choices: Choice[] = [],
public votes = [], public votes = [],
public stacks_of_votes = [],
public allowed_answers = [],
public modification_policy = [],
public dateChoices: Choice[] = [], // sets of days as strings, config to set identical time for days in a special days poll public dateChoices: Choice[] = [], // sets of days as strings, config to set identical time for days in a special days poll
public timeChoices: Choice[] = [] // ranges of time expressed as strings public timeChoices: Choice[] = [] // ranges of time expressed as strings
) {} ) {}
public getAdministrationUrl(): string {
return `${environment.api.baseHref}/administration/polls/${this.slug}`;
}
public getParticipationUrl(): string {
return `${environment.api.baseHref}/participation/polls/${this.slug}`;
}
public static adaptFromLocalJsonServer( public static adaptFromLocalJsonServer(
item: Pick<Poll, 'owner' | 'title' | 'description' | 'slug' | 'configuration' | 'comments' | 'choices'> item: Pick<Poll, 'owner' | 'title' | 'description' | 'slug' | 'configuration' | 'comments' | 'choices'>
): Poll { ): Poll {
@ -58,4 +58,12 @@ export class Poll {
// }) // })
); );
} }
public getAdministrationUrl(): string {
return `${environment.api.baseHref}/administration/polls/${this.slug}`;
}
public getParticipationUrl(): string {
return `${environment.api.baseHref}/participation/polls/${this.slug}`;
}
} }

View File

@ -12,6 +12,40 @@
</div> </div>
</article> </article>
<!-- actions-->
<div id="export_and_share">
<div class="sharing" *ngIf="poll">
<h3 class="margin-top-x8">
Partager le sondage
<i class="fa fa-share" aria-hidden="true"></i>
</h3>
<p class="nobold text-14" for="copyLink">
Pour partager le sondage, vous pouvez diffuser ce lien :
<a href="{{ poll.urlPublic }}">
{{ poll.urlPublic }}
</a>
</p>
<app-copy-text [textToCopy]="poll.urlPublic"></app-copy-text>
<h3 class="margin-top-x6 margin-btm-x3">
Exporter/Imprimer
</h3>
<button class="export export-csv" (click)="exportCSV()">
<i class="fa fa-file-calc-o" aria-hidden="true"></i>
Exporter en .csv
</button>
<button class="btn btn--primary" (click)="exportJson()">
<i class="fa fa-file-archive-o" aria-hidden="true"></i>
export json
</button>
<button class="export export-print" (click)="print()">
<i class="fa fa-print"></i>
Imprimer le sondage
</button>
</div>
</div>
<!-- affichage des possibilités de réponse --> <!-- affichage des possibilités de réponse -->
<div class="columns"> <div class="columns">
<div class="column"> <div class="column">
@ -39,21 +73,39 @@
Detailed Detailed
</button> </button>
</div> </div>
<!-- <app-poll-results-compact *ngIf="isCompactMode" [poll]="poll"></app-poll-results-compact>--> <app-poll-results-compact *ngIf="isCompactMode" [poll]="poll"></app-poll-results-compact>
<!-- <app-poll-results-detailed *ngIf="!isCompactMode" [poll]="poll"></app-poll-results-detailed>--> <app-poll-results-detailed *ngIf="!isCompactMode" [poll]="poll"></app-poll-results-detailed>
<!-- comments-->
</div> </div>
</div> </div>
<div class="columns">
<div class="column">
<app-comments [poll]="poll"></app-comments>
</div>
</div>
<div class="bar-votestack">
<button
class="btn btn-block submit-votestack"
(click)="addVoteStack()"
[disabled]="!myTempVoteStack"
[ngClass]="{ 'btn--primary': myTempVoteStack }"
*ngIf="!myVoteStack || !myVoteStack.id"
>
<i class="fa fa-paper-plane" aria-hidden="true"></i> Envoyer
</button>
<button
class="btn btn--primary btn-block submit-votestack update"
(click)="updateVote(myVoteStack)"
*ngIf="myVoteStack && myVoteStack.id"
>
<i class="fa fa-edit" aria-hidden="true"></i> Mettre à jour
</button>
</div>
<footer class="card-footer" *ngIf="!isArchived"> <footer class="card-footer" *ngIf="!isArchived">
TODO links TODO links
</footer> </footer>
</div> </div>
</div> </div>
</div> </div>
<div class="columns">
<div class="column">
<app-comments [poll]="poll"></app-comments>
</div>
</div>
</section> </section>

View File

@ -5,6 +5,8 @@ import { Poll } from '../../core/models/poll.model';
import { ModalService } from '../../core/services/modal.service'; import { ModalService } from '../../core/services/modal.service';
import { PollService } from '../../core/services/poll.service'; import { PollService } from '../../core/services/poll.service';
import { DateService } from '../../core/services/date.service'; import { DateService } from '../../core/services/date.service';
import { PollUtilities } from '../old-stuff/config/PollUtilities';
import { Comment } from '../../core/models/comment.model';
@Component({ @Component({
selector: 'app-consultation', selector: 'app-consultation',
@ -18,10 +20,18 @@ export class ConsultationComponent implements OnInit, OnDestroy {
public passHash: string; public passHash: string;
public fetching = true; public fetching = true;
public isArchived: boolean; public isArchived: boolean;
public myVoteStack: any = {
id: '',
};
public myTempVoteStack: any = {
id: '',
};
private routeSubscription: Subscription; private routeSubscription: Subscription;
constructor( constructor(
private router: Router, private router: Router,
private utils: PollUtilities,
private _Activatedroute: ActivatedRoute, private _Activatedroute: ActivatedRoute,
public pollService: PollService, public pollService: PollService,
public dateService: DateService, public dateService: DateService,
@ -58,4 +68,97 @@ export class ConsultationComponent implements OnInit, OnDestroy {
this.routeSubscription.unsubscribe(); this.routeSubscription.unsubscribe();
} }
} }
updateVote(myVoteStack: boolean) {
alert('TODO');
}
addVoteStack() {
alert('TODO');
}
/**
* export all the poll data available to the public as a CSV single file
*/
exportCSV() {
let rows = [];
const now = new Date();
const headers = [
['export de sondage Framadate ', this.poll.custom_url],
['le', now.toISOString()],
[this.poll.id, this.poll.title, this.poll.custom_url, this.poll.creation_date],
['pseudo'],
];
const listOfChoices = ['choices : '];
this.poll.choices.map((choice) => {
listOfChoices.push(choice.name);
});
listOfChoices.push('pseudo');
this.poll.stacks_of_votes.map((voteStack) => {
const voteStackInArray = [voteStack.pseudo];
const keysVotes = Object.keys(voteStack.votes);
keysVotes.map((id) => {
voteStackInArray.push(voteStack.votes[id].value ? voteStack.votes[id].value : '');
});
rows.push(voteStackInArray);
});
const headersComments = [['comments'], ['pseudo', 'text', 'creation_date']];
const comments = [];
this.poll.comments.map((item: Comment) => {
comments.push([item.pseudo, item.text, new Date(item.created_at), '\n']);
});
headers.push(listOfChoices);
rows = [headers, listOfChoices, rows, headersComments, comments];
const convertedCsv = rows
.map((elem) => {
console.log('elem', elem);
return elem
.map((item) => {
console.log('item', item);
if (typeof item === typeof Array) {
return item.join('\n');
}
return item;
})
.join('\n');
})
.join('\n');
console.log('rows', rows);
console.log('convertedCsv', convertedCsv);
const csvContent = 'data:text/csv;charset=utf-8,' + convertedCsv;
console.log('csvContent', csvContent);
const encodedUri = encodeURI(csvContent);
const link = document.createElement('a');
link.setAttribute('href', encodedUri);
const exportFileName =
(this.poll.urlPublic ? this.poll.urlPublic : this.utils.makeSlug(this.poll)) +
'_export_' +
new Date() +
'.csv';
link.setAttribute('download', exportFileName);
document.body.appendChild(link); // Required for FF
link.click(); // This will download the data file named "my_data.csv".
}
exportJson() {
this.download('export_poll_' + this.pollSlug + '.json', JSON.stringify(this.poll));
}
download(filename, text) {
const element = document.createElement('a');
element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text));
element.setAttribute('download', filename);
element.style.display = 'none';
document.body.appendChild(element);
element.click();
document.body.removeChild(element);
}
} }

View File

@ -1,6 +1,7 @@
import { HttpHeaders } from '@angular/common/http'; import { HttpHeaders } from '@angular/common/http';
import { PollConfig } from './PollConfig'; import { PollConfig } from './PollConfig';
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { Poll } from '../../../core/models/poll.model';
@Injectable({ @Injectable({
providedIn: 'root', providedIn: 'root',
@ -22,16 +23,18 @@ export class PollUtilities {
* make a uniq slug for the current poll creation * make a uniq slug for the current poll creation
* @param str * @param str
*/ */
makeSlug(config: PollConfig) { makeSlug(config: Poll) {
let str = ''; let str = '';
const creation = new Date(config.creation_date);
str = str =
config.creationDate.getFullYear() + creation.getFullYear() +
'_' + '_' +
(config.creationDate.getMonth() + 1) + (creation.getMonth() + 1) +
'_' + '_' +
config.creationDate.getDate() + creation.getDate() +
'_' + '_' +
config.myName + config.creatorPseudo +
'_' + '_' +
config.title; config.title;
str = str.replace(/^\s+|\s+$/g, ''); // trim str = str.replace(/^\s+|\s+$/g, ''); // trim

View File

@ -4,7 +4,7 @@
</button> </button>
<button class="btn btn--primary" (click)="config.exportJson()" *ngIf="config.isAdmin"> <button class="btn btn--primary" (click)="config.exportJson()" *ngIf="config.isAdmin">
<i class="fa fa-file-archive-o" aria-hidden="true"></i> <i class="fa fa-file-archive-o" aria-hidden="true"></i>
export CSV export json
</button> </button>
<div class="loading" *ngIf="config.loading"> <div class="loading" *ngIf="config.loading">