From 3306e7c29d4f811a6ba624595457768e8c237bcc Mon Sep 17 00:00:00 2001 From: tykayn <15d65f2f-0b14-4f70-bf34-e130180ed62b@users.tedomum.net> Date: Mon, 9 Nov 2020 11:32:12 +0100 Subject: [PATCH] reuse automatic slug from poll config in form --- doc/cadrage/backend-api-endpoints-doc.txt | 63 +++++++++++-------- src/app/core/services/api.service.ts | 48 ++++++++++---- src/app/core/services/poll.service.ts | 35 +++++++++++ src/app/core/services/uuid.service.ts | 10 +++ .../administration.component.html | 8 +-- .../administration.component.ts | 4 +- .../administration/form/form.component.html | 8 +++ .../administration/form/form.component.ts | 7 +++ 8 files changed, 133 insertions(+), 50 deletions(-) diff --git a/doc/cadrage/backend-api-endpoints-doc.txt b/doc/cadrage/backend-api-endpoints-doc.txt index 65f3afa5..e805c7d1 100644 --- a/doc/cadrage/backend-api-endpoints-doc.txt +++ b/doc/cadrage/backend-api-endpoints-doc.txt @@ -1,32 +1,41 @@ // TODO: File to be deleted : just temporary documentation of backend API endpoints -/** - * - * -------------------------- -------- -------- ------ ------------------------------------------------ - Name Method Scheme Host Path - -------------------------- -------- -------- ------ ------------------------------------------------ -_twig_error_test ANY ANY ANY /_error/{code}.{_format} -admin_homepage_get_default GET ANY ANY /admin/ -admin_homepage_clean_expired_polls GET ANY ANY /admin/polls/clean/{token} -api_get_poll_comment GET ANY ANY /polls/{id}/comments -api_new_comment POST ANY ANY /polls/{id}/comments -api_poll_comments_delete DELETE ANY ANY /polls/{id}/comments -user_homepageget_default GET ANY ANY /users/ -user_homepage_polls_send_by_email GET ANY ANY /users/{email}/polls/send-by-email -api_get_all_polls GET ANY ANY /polls/ -api_get_poll GET ANY ANY /polls/{id} -api_update_poll PUT ANY ANY /polls/{id}/{token} -api_new_poll POST ANY ANY /polls/ -api_test-mail-polls GET ANY ANY /polls/mail/test-mail-polls/{emailChoice} -api_poll_delete DELETE ANY ANY /polls/{id} -api_check_slug_is_unique GET ANY ANY /polls/slugs/{slug} -api_get_admin_config GET ANY ANY /polls/admin/{token} -api_new_vote_stack POST ANY ANY /polls/{id}/votes -api_update_vote_stack PATCH ANY ANY /votes-stacks/{id}/token/{modifierToken} -api_poll_votes_delete DELETE ANY ANY /polls/{id}/votes/{accessToken} -app.swagger GET ANY ANY /api/doc.json - -------------------------- -------- -------- ------ ------------------------------------------------ - */ + ------------------------------------------ ---------- -------- ------ ------------------------------------------------ + Name Method Scheme Host Path + ------------------------------------------ ---------- -------- ------ ------------------------------------------------ + _twig_error_test ANY ANY ANY /_error/{code}.{_format} + admin_homepage_get_default GET ANY ANY /admin/ + admin_homepage_clean_expired_polls GET ANY ANY /admin/polls/clean/{token} + admin_homepage_migrate_framadate GET ANY ANY /admin/polls/migrate + api_get_poll_comment GET ANY ANY /api/v1/poll/{id}/comments + api_new_comment POST ANY ANY /api/v1/poll/{id}/comment + api_poll_comments_delete DELETE ANY ANY /api/v1/poll/{id}/comments + api_page_home GET ANY ANY /page/ + user_homepageget_default GET ANY ANY /user/ + user_homepage_polls_send_by_email GET ANY ANY /user/{email}/polls/send-by-email + poll_index GET ANY ANY /poll/ + poll_new GET|POST ANY ANY /poll/new + poll_show GET ANY ANY /poll/{id} + poll_edit GET|POST ANY ANY /poll/{id}/edit + poll_delete DELETE ANY ANY /poll/{id} + api_new_vote_stack POST ANY ANY /api/v1/poll/{id}/answer + api_update_vote_stack PATCH ANY ANY /api/v1/vote-stack/{id}/token/{modifierToken} + api_poll_votes_delete DELETE ANY ANY /api/v1/poll/{id}/votes/{accessToken} + api_get_all_polls GET ANY ANY /api/v1/poll/ + api_get_poll GET ANY ANY /api/v1/poll/{id} + api_update_poll PUT ANY ANY /api/v1/poll/{id}/{token} + api_new_poll POST ANY ANY /api/v1/poll/ + api_test-mail-poll GET ANY ANY /api/v1/poll/mail/test-mail-poll/{emailChoice} + api_poll_delete DELETE ANY ANY /api/v1/poll/{id} + api_check_slug_is_unique GET ANY ANY /api/v1/poll/slug/{slug} + api_get_admin_config GET ANY ANY /api/v1/poll/admin/{token} + overblog_graphql_endpoint ANY ANY ANY /api/graphql/ + overblog_graphql_batch_endpoint ANY ANY ANY /api/graphql/batch + overblog_graphql_multiple_endpoint ANY ANY ANY /api/graphql/graphql/{schemaName} + overblog_graphql_batch_multiple_endpoint ANY ANY ANY /api/graphql/graphql/{schemaName}/batch + app.swagger GET ANY ANY /api/doc.json + ------------------------------------------ ---------- -------- ------ ------------------------------------------------ + /** * WANTED CHANGES (seraf) diff --git a/src/app/core/services/api.service.ts b/src/app/core/services/api.service.ts index 3eb8604d..a67823a9 100644 --- a/src/app/core/services/api.service.ts +++ b/src/app/core/services/api.service.ts @@ -4,6 +4,7 @@ import { environment } from 'src/environments/environment'; import { Answer } from '../enums/answer.enum'; import { Poll } from '../models/poll.model'; +import { HttpHeaders } from '@angular/common/http'; @Injectable({ providedIn: 'root', @@ -32,7 +33,7 @@ export class ApiService { try { return await this.axiosInstance.post(`${this.pollsEndpoint}`, poll); } catch (error) { - this.handleError(error); + ApiService.handleError(error); } } @@ -49,7 +50,7 @@ export class ApiService { response, }); } catch (error) { - this.handleError(error); + ApiService.handleError(error); } } @@ -57,7 +58,7 @@ export class ApiService { try { return await this.axiosInstance.post(`${this.pollsEndpoint}/${slug}${this.commentsEndpoint}`, comment); } catch (error) { - this.handleError(error); + ApiService.handleError(error); } } @@ -70,7 +71,7 @@ export class ApiService { const response: AxiosResponse = await this.axiosInstance.get(`${this.pollsEndpoint}`); return response?.data; } catch (error) { - this.handleError(error); + ApiService.handleError(error); } } @@ -101,7 +102,7 @@ export class ApiService { if (error.response?.status === 404) { return undefined; } else { - this.handleError(error); + ApiService.handleError(error); } } } @@ -119,7 +120,7 @@ export class ApiService { if (error.response?.status === 404) { return true; } else { - this.handleError(error); + ApiService.handleError(error); } } } @@ -131,7 +132,7 @@ export class ApiService { `${this.usersEndpoint}/${email}${this.usersPollsEndpoint}${this.usersPollsSendEmailEndpoint}` ); } catch (error) { - this.handleError(error); + ApiService.handleError(error); } } @@ -145,7 +146,7 @@ export class ApiService { ); return response?.data; } catch (error) { - this.handleError(error); + ApiService.handleError(error); } } @@ -160,7 +161,7 @@ export class ApiService { answer, }); } catch (error) { - this.handleError(error); + ApiService.handleError(error); } } @@ -172,7 +173,7 @@ export class ApiService { const response: AxiosResponse = await this.axiosInstance.delete(`${this.pollsEndpoint}/${slug}`); return response?.status === 204; } catch (error) { - this.handleError(error); + ApiService.handleError(error); } } @@ -183,7 +184,7 @@ export class ApiService { ); return response?.status === 204; } catch (error) { - this.handleError(error); + ApiService.handleError(error); } } @@ -194,14 +195,35 @@ export class ApiService { ); return response?.status === 204; } catch (error) { - this.handleError(error); + ApiService.handleError(error); } } ///////////////////// // PRIVATE METHODS // ///////////////////// - private handleError(error): void { + /** + * prepare headers like the charset and json type for any call to the backend + * @param bodyContent? + */ + private makeHeaders(bodyContent?: any) { + const headerDict = { + Charset: 'UTF-8', + 'Content-Type': 'application/json', + Accept: 'application/json', + 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS', + 'Access-Control-Allow-Origin': '*', + }; + + const requestOptions = { + headers: new HttpHeaders(headerDict), + body: bodyContent, + }; + + return requestOptions; + } + + private static handleError(error): void { if (error.response) { // The request was made and the server responded with a status code // that falls out of the range of 2xx diff --git a/src/app/core/services/poll.service.ts b/src/app/core/services/poll.service.ts index c9ccf6af..ece2f551 100644 --- a/src/app/core/services/poll.service.ts +++ b/src/app/core/services/poll.service.ts @@ -11,6 +11,7 @@ import { ToastService } from './toast.service'; import { UserService } from './user.service'; import { UuidService } from './uuid.service'; import { Form } from '@angular/forms'; +import { PollConfig } from '../../features/old-stuff/config/PollConfig'; @Injectable({ providedIn: 'root', @@ -60,6 +61,40 @@ export class PollService implements Resolve { this._poll.next(poll); } + /** + * make a uniq slug for the current poll creation + * @param config + */ + makeSlug(config: Poll): string { + let str = ''; + str = + config.configuration.dateCreated.getFullYear() + + '_' + + (config.configuration.dateCreated.getMonth() + 1) + + '_' + + config.configuration.dateCreated.getDate() + + '_' + + config.owner.pseudo + + '_' + + config.title; + str = str.replace(/^\s+|\s+$/g, ''); // trim + str = str.toLowerCase(); + + // remove accents, swap ñ for n, etc + const from = 'àáäâèéëêìíïîòóöôùúüûñç·/_,:;'; + const to = 'aaaaeeeeiiiioooouuuunc------'; + for (let i = 0, l = from.length; i < l; i++) { + str = str.replace(new RegExp(from.charAt(i), 'g'), to.charAt(i)); + } + + str = str + .replace(/[^a-z0-9 -]/g, '') // remove invalid chars + .replace(/\s+/g, '-') // collapse whitespace and replace by - + .replace(/-+/g, '-'); // collapse dashes + + return str + '-' + this.uuidService.getUUID(); + } + public async saveCurrentPoll(): Promise { const pollUrl: string = await this.apiService.createPoll(this._poll.getValue()); // TODO: Maybe handle the url to update currentPoll according to backend response diff --git a/src/app/core/services/uuid.service.ts b/src/app/core/services/uuid.service.ts index b32516e8..38bc8a5f 100644 --- a/src/app/core/services/uuid.service.ts +++ b/src/app/core/services/uuid.service.ts @@ -10,4 +10,14 @@ export class UuidService { public getUUID(): string { return this.uid(); } + /** + * generate unique id to have a default url for future poll + */ + getLongUUID(): string { + return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { + const r = (Math.random() * 16) | 0, + v = c == 'x' ? r : (r & 0x3) | 0x8; + return v.toString(16); + }); + } } diff --git a/src/app/features/administration/administration.component.html b/src/app/features/administration/administration.component.html index b6389629..e11070e8 100644 --- a/src/app/features/administration/administration.component.html +++ b/src/app/features/administration/administration.component.html @@ -1,10 +1,4 @@ - - - - - - -
+
diff --git a/src/app/features/administration/administration.component.ts b/src/app/features/administration/administration.component.ts index bf69d01c..5111b2e2 100644 --- a/src/app/features/administration/administration.component.ts +++ b/src/app/features/administration/administration.component.ts @@ -5,7 +5,6 @@ import { Subscription } from 'rxjs'; import { Poll } from '../../core/models/poll.model'; import { ModalService } from '../../core/services/modal.service'; import { UserService } from '../../core/services/user.service'; -import { SettingsComponent } from '../../shared/components/settings/settings.component'; @Component({ selector: 'app-administration', @@ -13,8 +12,7 @@ import { SettingsComponent } from '../../shared/components/settings/settings.com styleUrls: ['./administration.component.scss'], }) export class AdministrationComponent implements OnInit, OnDestroy { - public poll: Poll; - public form: Object; + public poll: Poll = new Poll(); private routeSubscription: Subscription; constructor(private route: ActivatedRoute, private userService: UserService, private modalService: ModalService) {} diff --git a/src/app/features/administration/form/form.component.html b/src/app/features/administration/form/form.component.html index 7f35dcb9..9b101d49 100644 --- a/src/app/features/administration/form/form.component.html +++ b/src/app/features/administration/form/form.component.html @@ -12,6 +12,14 @@ Enregistrer le sondage + + +
+ {{ poll.slug }} +
le formulaire est invalide
diff --git a/src/app/features/administration/form/form.component.ts b/src/app/features/administration/form/form.component.ts index 31254e40..dae7ffea 100644 --- a/src/app/features/administration/form/form.component.ts +++ b/src/app/features/administration/form/form.component.ts @@ -306,4 +306,11 @@ export class FormComponent implements OnInit { elem.focus(); } } + + /** + * set the poll slug from other data of the poll + */ + automaticSlug() { + this.poll.slug = this.pollService.makeSlug(this.poll); + } }