calls in administration page to delete things

This commit is contained in:
Baptiste Lemoine 2020-01-16 14:37:11 +01:00
parent ce4c3cb000
commit bae3f19af2
10 changed files with 352 additions and 170 deletions

View File

@ -44,12 +44,14 @@ import {BrowserAnimationsModule} from "@angular/platform-browser/animations";
import {ConfigService} from "./services/config.service"; import {ConfigService} from "./services/config.service";
import {PollService} from "./services/poll.service"; import {PollService} from "./services/poll.service";
import {ToastModule} from 'primeng/toast'; import {ToastModule} from 'primeng/toast';
import {MessageModule, MessageService} from "primeng"; import {ConfirmationService, MessageModule, MessageService} from "primeng";
import {PollDisplayComponent} from './pages/poll-display/poll-display.component'; import {PollDisplayComponent} from './pages/poll-display/poll-display.component';
import {VotingComponent} from './pages/voting/voting.component'; import {VotingComponent} from './pages/voting/voting.component';
import {VotingCommentComponent} from './pages/voting/voting-comment/voting-comment.component'; import {VotingCommentComponent} from './pages/voting/voting-comment/voting-comment.component';
import {ResettableInputDirective} from './ui/directives/resettable-input.directive'; import {ResettableInputDirective} from './ui/directives/resettable-input.directive';
import {ClipboardModule} from "ngx-clipboard"; import {ClipboardModule} from "ngx-clipboard";
import {ErasableInputComponent} from './ui/erasable-input/erasable-input.component';
import {ConfirmDialogModule} from 'primeng/confirmdialog';
export class MyMissingTranslationHandler implements MissingTranslationHandler { export class MyMissingTranslationHandler implements MissingTranslationHandler {
handle(params: MissingTranslationHandlerParams) { handle(params: MissingTranslationHandlerParams) {
@ -92,9 +94,11 @@ export function HttpLoaderFactory(http: HttpClient) {
VotingComponent, VotingComponent,
VotingCommentComponent, VotingCommentComponent,
ResettableInputDirective, ResettableInputDirective,
ErasableInputComponent,
], ],
imports: [ imports: [
ConfirmDialogModule,
ClipboardModule, ClipboardModule,
CommonModule, CommonModule,
BrowserModule, BrowserModule,
@ -119,7 +123,7 @@ export function HttpLoaderFactory(http: HttpClient) {
FormsModule, FormsModule,
RouterModule.forRoot(Routes) RouterModule.forRoot(Routes)
], ],
providers: [TranslateService, ConfigService, PollService, MessageService], providers: [TranslateService, ConfigService, PollService, MessageService, ConfirmationService],
bootstrap: [AppComponent] bootstrap: [AppComponent]
}) })
export class AppModule { export class AppModule {

View File

@ -1,164 +1,193 @@
<form> <form>
<h1>Nom du sondage</h1> <h1>Nom du sondage</h1>
<!--Infos--> <!--Infos-->
<h2>{{"admin.info_section_title"|translate}}</h2> <h2>{{"admin.info_section_title"|translate}}</h2>
<label for="title"> <label for="title">
{{"admin.choose_title"|translate}} {{"admin.choose_title"|translate}}
</label> </label>
<input type="text" name="title"> <input type="text" name="title">
<label for="desc"> <label for="desc">
{{"admin.description"|translate}} {{"admin.description"|translate}}
</label> </label>
<textarea name="desc"> </textarea> <textarea name="desc"> </textarea>
<label for="name"> <label for="name">
{{"creation.name"|translate}} {{"creation.name"|translate}}
</label> </label>
<input type="text" name="name"> <input type="text" name="name">
<!--Params--> <!--Params-->
<h2>{{"admin.settings_section_title"|translate}}</h2> <h2>{{"admin.settings_section_title"|translate}}</h2>
<h3>{{"visibility.title"|translate}}</h3> <h3>{{"visibility.title"|translate}}</h3>
<section class="row"> <section class="row">
<label for="answer-visible"> <label for="answer-visible">
{{"visibility.visibility_want"|translate}} {{"visibility.visibility_want"|translate}}
</label> </label>
<select name="answer-visible"> <select name="answer-visible">
<option value="all" selected> <option value="all" selected>
{{"visibility.visibility_link"|translate}} {{"visibility.visibility_link"|translate}}
</option> </option>
<option value="per"> <option value="per">
{{"visibility.visibility_nobody"|translate}} {{"visibility.visibility_nobody"|translate}}
</option> </option>
</select> </select>
<label for="answer-visible"> <label for="answer-visible">
{{"visibility.visibility_see"|translate}} {{"visibility.visibility_see"|translate}}
</label> </label>
</section> </section>
<h3>{{"visibility.votes"|translate}}</h3> <h3>{{"visibility.votes"|translate}}</h3>
<section> <section>
<label for="vote-date"> <label for="vote-date">
{{"visibility.archiving"|translate}} {{"visibility.archiving"|translate}}
</label> </label>
<input type="date" name="vote-date"> <input type="date" name="vote-date">
</section> </section>
<section> <section>
<label for="alter-vote"> <label for="alter-vote">
{{"visibility.archiving_start"|translate}} {{"visibility.archiving_start"|translate}}
</label> </label>
<select name="alter-vote"> <select name="alter-vote">
<option value="yes" selected> <option value="yes" selected>
{{"visibility.archiving_can"|translate}} {{"visibility.archiving_can"|translate}}
</option> </option>
<option value="no"> <option value="no">
{{"visibility.archiving_can_not"|translate}} {{"visibility.archiving_can_not"|translate}}
</option> </option>
</select> </select>
<label for="type-vote"> <label for="type-vote">
{{"visibility.archiving_end"|translate}} {{"visibility.archiving_end"|translate}}
</label> </label>
<select name="type-vote"> <select name="type-vote">
<option value="solo" selected> <option value="solo" selected>
{{"visibility.modfiy_their"|translate}} {{"visibility.modfiy_their"|translate}}
</option> </option>
<option value="all"> <option value="all">
{{"visibility.modfiy_everyone"|translate}} {{"visibility.modfiy_everyone"|translate}}
</option> </option>
</select> </select>
</section> </section>
<label for="del-vote"> <label for="del-vote">
{{"admin.votes_deletion_desc"|translate}} {{"admin.votes_deletion_desc"|translate}}
</label> </label>
<input class="btn btn--alert btn--outline" type="submit" <button class="btn btn--alert btn--outline"
name="del-vote" value="{{'admin.votes_deletion_btn'|translate}}"> (click)="config.deleteVotes()"
>
<i class="fa fa-trash"></i>
{{'admin.votes_deletion_btn'|translate}}
<i class="fa fa-object-group"></i></button>
<h3>{{"admin.comments_deletion_title"|translate}}</h3> <h3>{{"admin.comments_deletion_title"|translate}}</h3>
<label for="del-com"> <label for="del-com">
{{"admin.comments_deletion_desc"|translate}} {{"admin.comments_deletion_desc"|translate}}
</label> </label>
<input class="btn btn--alert btn--outline" type="submit"
name="del-com" value="{{'admin.comments_deletion_btn'|translate}}">
<h3>{{"admin.archiving_title"|translate}}</h3> <button class="btn btn--alert btn--outline"
<section class="row"> (click)="config.deleteComments()"
<label for="arch"> >
{{"admin.archiving_desc"|translate}} <i class="fa fa-trash"></i>
</label>
<input type="date" name="arch">
</section>
<h3>{{"visibility.access"|translate}}</h3> {{'admin.comments_deletion_btn'|translate}}
<section class="row"> <i class="fa fa-comments-o"></i></button>
<label for="password">Je</label>
<select name="password">
<option value="yes" selected>
{{"visibility.access_want_yes"|translate}}
</option>
<option value="no">
{{"visibility.access_want_no"|translate}}
</option>
</select>
<label for="alter-vote">
{{"visibility.access_protect"|translate}}
</label>
</section>
<h3>{{"admin.deletion"|translate}}</h3> <h3>{{"admin.archiving_title"|translate}}</h3>
<label for="del"> {{"admin.deletion_desc"|translate}} </label> <section class="row">
<input class="btn btn--alert" type="submit" <label for="arch">
name="del" value="{{'admin.deletion_btn'|translate}}"> {{"admin.archiving_desc"|translate}}
</label>
<input type="date" name="arch">
</section>
<!-- Access link --> <h3>{{"visibility.access"|translate}}</h3>
<h2>{{"admin.link"|translate}}</h2> <section class="row">
<h3>{{"admin.link_admin"|translate}}</h3> <label for="password">Je</label>
<select name="password">
<option value="yes" selected>
{{"visibility.access_want_yes"|translate}}
</option>
<option value="no">
{{"visibility.access_want_no"|translate}}
</option>
</select>
<label for="alter-vote">
{{"visibility.access_protect"|translate}}
</label>
</section>
<label for="copy-link-admin"> <h3>{{"admin.deletion"|translate}}</h3>
{{"admin.link_admin_desc"|translate}} <label for="del"> {{"admin.deletion_desc"|translate}} </label>
https://framadate.org/urladmindusondage <input class="btn btn--alert" type="submit"
</label> name="del" value="{{'admin.deletion_btn'|translate}}">
<input class="btn btn--mini" type="submit" name="copy-link-admin"
value="{{'admin.copy_link'|translate}}">
<a href="#" class="next">{{"admin.link_admin_btn"|translate}}</a>
<h3>{{"admin.polled_people"|translate}}</h3> <!-- Access link -->
<label for="copy-link"> <h2>{{"admin.link"|translate}}</h2>
{{"admin.polled_people_desc"|translate}} <h3>{{"admin.link_admin"|translate}}</h3>
https://framadate.org/urladmindusondage</label>
<input class="btn btn--mini" type="submit" name="copy-link"
value="{{'admin.copy_link'|translate}}">
<a href="#" class="next">{{"admin.polled_people_btn"|translate}}</a>
<h3>{{"admin.email_links"|translate}}</h3> <label for="copy-link-admin">
<label for="mail">{{"admin.email_links_desc"|translate}}</label> {{"admin.link_admin_desc"|translate}}
<input type="email" name="mail"> https://framadate.org/urladmindusondage
<input class="btn btn--mini" type="submit" name="send-mail" </label>
value="{{'admin.email_links_btn'|translate}}"> <input class="btn btn--mini" type="submit" name="copy-link-admin"
value="{{'admin.copy_link'|translate}}">
<a href="#" class="next">{{"admin.link_admin_btn"|translate}}</a>
<section class="deletion"> <h3>{{"admin.polled_people"|translate}}</h3>
{{"admin.deletion"|translate}} <label for="copy-link">
{{"admin.deletion_desc"|translate}} {{"admin.polled_people_desc"|translate}}
{{"admin.deletion_btn"|translate}} {{config.urlPublic}}</label>
</section> <input class="btn btn--mini" type="submit" name="copy-link"
value="{{'admin.copy_link'|translate}}">
<a href="#" class="next">{{"admin.polled_people_btn"|translate}}</a>
<section class="links"> <h3>{{"admin.email_links"|translate}}</h3>
{{"admin.link"|translate}} <label for="mail">{{"admin.email_links_desc"|translate}}</label>
{{"admin.link_admin"|translate}} <input type="email" name="mail">
{{"admin.link_admin_desc"|translate}} <input class="btn btn--mini" type="submit" name="send-mail"
{{"admin.link_admin_btn"|translate}} value="{{'admin.email_links_btn'|translate}}">
{{"admin.copy_link"|translate}}
{{"admin.polled_people"|translate}} <section class="deletion">
{{"admin.polled_people_desc"|translate}} <h2>
{{"admin.polled_people_btn"|translate}}
{{"admin.email_links"|translate}} {{"admin.deletion"|translate}}
{{"admin.email_links_desc"|translate}} </h2>
{{"admin.email_links_key"|translate}} {{"admin.deletion_desc"|translate}}
{{"admin.email_links_btn"|translate}} <button class="btn btn--danger" (click)="config.deletePoll()">
</section> <i class="fa fa-trash"></i>
<i class="fa fa-warning"></i>
{{"admin.deletion_btn"|translate}}
</button>
<button class="btn btn--danger" (click)="config.deleteComments()">
<i class="fa fa-trash"></i>
<i class="fa fa-warning"></i>
{{"admin.comments_deletion_btn"|translate}}
</button>
<button class="btn btn--danger" (click)="config.deleteVotes()">
<i class="fa fa-trash"></i>
<i class="fa fa-warning"></i>
{{"admin.votes_btn_votes"|translate}}
</button>
</section>
<section class="links">
{{"admin.link"|translate}}
{{"admin.link_admin"|translate}}
{{"admin.link_admin_desc"|translate}}
{{"admin.link_admin_btn"|translate}}
{{"admin.copy_link"|translate}}
{{"admin.polled_people"|translate}}
{{"admin.polled_people_desc"|translate}}
{{"admin.polled_people_btn"|translate}}
{{"admin.email_links"|translate}}
{{"admin.email_links_desc"|translate}}
{{"admin.email_links_key"|translate}}
{{"admin.email_links_btn"|translate}}
</section>
</form> </form>
<p-confirmDialog header="Confirmation" icon="pi pi-exclamation-triangle"></p-confirmDialog>

View File

@ -8,7 +8,7 @@ import {ConfigService} from '../../services/config.service';
}) })
export class AdminComponent implements OnInit { export class AdminComponent implements OnInit {
constructor() { } constructor(private config : ConfigService) { }
ngOnInit() { ngOnInit() {
} }

View File

@ -86,6 +86,7 @@
required="required" required="required"
type="email" type="email"
/> />
<framadate-erasable-input [(inputModel)]="config.myEmail"></framadate-erasable-input>
</div> </div>
<button <button

View File

@ -2,7 +2,8 @@ import {Injectable} from '@angular/core';
import {PollConfig} from '../config/PollConfig'; import {PollConfig} from '../config/PollConfig';
import {HttpClient, HttpHeaders} from "@angular/common/http"; import {HttpClient, HttpHeaders} from "@angular/common/http";
import {environment} from "../../environments/environment"; import {environment} from "../../environments/environment";
import {MessageService} from 'primeng/api'; import {ConfirmationService, MessageService} from 'primeng/api';
import {Router} from "@angular/router";
/** /**
* le service transverse à chaque page qui permet de syncroniser la configuration de sondage souhaitée * le service transverse à chaque page qui permet de syncroniser la configuration de sondage souhaitée
@ -18,7 +19,10 @@ export class ConfigService extends PollConfig {
constructor(private http: HttpClient, constructor(private http: HttpClient,
private messageService: MessageService) { private messageService: MessageService,
private router: Router,
private confirmationService: ConfirmationService,
) {
super(); super();
} }
@ -191,6 +195,10 @@ export class ConfigService extends PollConfig {
findLocalStorageData() { findLocalStorageData() {
// TODO check if the person has a key to retrieve her polls // TODO check if the person has a key to retrieve her polls
if (localStorage) {
console.log('localStorage', localStorage)
}
} }
@ -280,28 +288,6 @@ export class ConfigService extends PollConfig {
); );
} }
/**
* UPDATE
* /api/v1/poll/{id}/vote
* @param voteStack
*/
updatePoll(voteStack: any) {
this.http.put(
`${this.baseHref}/poll/${this.pollId}`,
voteStack,
this.makeHeaders()
)
.subscribe((res: any) => {
this.messageService.add({
severity: 'success',
summary: 'Sondage mis à jour',
});
this.myPolls = res;
}, (e) => {
this.handleError(e)
}
);
}
/** /**
* POST * POST
@ -370,4 +356,104 @@ export class ConfigService extends PollConfig {
* administrator calls * administrator calls
*/ */
deleteComments() {
// prompt for confirmation
this.confirmationService.confirm({
message: 'Are you sure that you want to completely delete the comments of this poll (' + this.title + ') permanentely?',
accept: () => {
this.http.delete(
`${this.baseHref}/poll/${this.pollId}/comments`,
this.makeHeaders())
.subscribe((res: any) => {
this.messageService.add({
severity: 'success',
summary: 'Commentaires bien supprimés',
detail: 'Commentaires du sondage "' + this.title + '" supprimé'
});
}, (e) => {
this.handleError(e)
}
);
}
});
}
deleteVotes() {
// prompt for confirmation
this.confirmationService.confirm({
message: 'Are you sure that you want to completely delete the votes of this poll (' + this.title + ') permanentely?',
accept: () => {
this.http.delete(
`${this.baseHref}/poll/${this.pollId}/votes`,
this.makeHeaders())
.subscribe((res: any) => {
this.messageService.add({
severity: 'success',
summary: 'Votes bien supprimés',
detail: 'Votes du sondage "' + this.title + '" supprimé'
});
}, (e) => {
this.handleError(e)
}
);
}
});
}
deletePoll() {
if (!this.pollId) {
this.messageService.add({
summary: 'this poll is not administrable, it has no ID',
severity: 'warning'
});
return;
}
let self = this;
// prompt for confirmation
this.confirmationService.confirm({
message: 'Are you sure that you want to completely delete this poll (' + self.title + ') and all is data permanentely?',
accept: () => {
this.http.delete(
`${this.baseHref}/poll/${this.pollId}`,
this.makeHeaders())
.subscribe((res: any) => {
this.messageService.add({
severity: 'success',
summary: 'Sondage bien supprimé',
detail: 'sondage "' + this.title + '" supprimé'
});
this.router.navigate(['home']);
}, (e) => {
this.handleError(e)
}
);
}
});
}
/**
* UPDATE
* /api/v1/poll/{id}/vote
* @param voteStack
*/
updatePoll(voteStack: any) {
this.http.put(
`${this.baseHref}/poll/${this.pollId}`,
voteStack,
this.makeHeaders()
)
.subscribe((res: any) => {
this.messageService.add({
severity: 'success',
summary: 'Sondage mis à jour',
});
this.myPolls = res;
}, (e) => {
this.handleError(e)
}
);
}
} }

View File

@ -1,5 +1,8 @@
import {Directive} from '@angular/core'; import {Directive} from '@angular/core';
/**
* add a button on an input which deletes its value
*/
@Directive({ @Directive({
selector: '[framadateResettableInput]' selector: '[framadateResettableInput]'
}) })

View File

@ -0,0 +1,3 @@
<button class="erase" (click)="eraseInput()">
<i class="fa fa-times"></i>
</button>

View File

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ErasableInputComponent } from './erasable-input.component';
describe('ErasableInputComponent', () => {
let component: ErasableInputComponent;
let fixture: ComponentFixture<ErasableInputComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ ErasableInputComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ErasableInputComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,31 @@
import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
@Component({
selector: 'framadate-erasable-input',
templateUrl: './erasable-input.component.html',
styleUrls: ['./erasable-input.component.scss']
})
export class ErasableInputComponent implements OnInit {
@Output() inputModelChange = new EventEmitter();
@Input() get inputModel() {
return this.inputModel;
}
set inputModel(val) {
// this.inputModel = val;
}
constructor() {
}
ngOnInit() {
}
eraseInput() {
this.inputModel = '';
this.inputModelChange.emit(this.inputModel);
}
}