From ffc66c83e81d78bb1c6a037a404bf7ed5f090817 Mon Sep 17 00:00:00 2001 From: rishi-19-04 Date: Sat, 17 Aug 2024 23:52:58 +0530 Subject: [PATCH 1/9] added approve and reject buttons with a feedback box --- app/controllers/intro.js | 16 ++++++++++++++++ app/styles/button.module.css | 31 +++++++++++++++++++++++++++++++ app/styles/feedback.css | 10 ++++++++++ app/templates/intro.hbs | 10 ++++++++++ 4 files changed, 67 insertions(+) create mode 100644 app/styles/feedback.css diff --git a/app/controllers/intro.js b/app/controllers/intro.js index 97daee973..16ae0213e 100644 --- a/app/controllers/intro.js +++ b/app/controllers/intro.js @@ -3,4 +3,20 @@ import { inject as service } from '@ember/service'; export default class IntroController extends Controller { @service login; + @service onboarding; + + @action + async approveAction(){ + alert('Approved') + const inviteLink = await this.onboarding.discordInvite(); + if(inviteLink) { + window.open(`https://${inviteLink}`, '_blank'); + } + } + + @action + rejectAction(){ + alert('Rejected') + } + } diff --git a/app/styles/button.module.css b/app/styles/button.module.css index f3a731174..b175110df 100644 --- a/app/styles/button.module.css +++ b/app/styles/button.module.css @@ -53,3 +53,34 @@ transition: all 0.5s ease; width: 14rem; } + +.action-buttons { + margin-bottom: 20px; +} + +.action-buttons button { + font-size: 18px; + padding: 10px 20px; + border-radius: 5px; + border: none; + cursor: pointer; + margin-right: 10px; +} + +.approve-button { + background-color: #28a745; + color: white; +} + +.reject-button { + background-color: #dc3545; + color: white; +} + +.approve-button:hover { + background-color: #218838; +} + +.reject-button:hover { + background-color: #c82333; +} diff --git a/app/styles/feedback.css b/app/styles/feedback.css new file mode 100644 index 000000000..a5173b156 --- /dev/null +++ b/app/styles/feedback.css @@ -0,0 +1,10 @@ +.comment-box { + width: 100%; + height: 200px; + padding: 15px; + margin-top: 20px; + font-size: 16px; + border-radius: 5px; + border: 1px solid #ccc; + resize: none; +} diff --git a/app/templates/intro.hbs b/app/templates/intro.hbs index 1877043af..2874e055a 100644 --- a/app/templates/intro.hbs +++ b/app/templates/intro.hbs @@ -11,6 +11,16 @@ @data={{this.model}} @isLoading={{this.login.isLoading}} @isSuperUser={{this.login.userData.roles.super_user}} /> + + + + + +
+ + +
+ {{else}} {{/if}} From 6b308a2d22e29528e6a156ea150b78f5846f9f82 Mon Sep 17 00:00:00 2001 From: Achintya-Chatterjee Date: Sun, 18 Aug 2024 02:55:31 +0530 Subject: [PATCH 2/9] feat: Add functionality to generate and display Discord invite link with copy option - Implemented approveAction to generate a Discord invite link for approved users. - Added the invite link display in the template with a button to copy the link to the clipboard. - Styled the Copy Link button and integrated it with existing button styles. - Ensured the invite link opens in a new tab when clicked. --- app/constants/urls.js | 2 +- app/controllers/intro.js | 47 ++++++++++++++++++++++++++------ app/styles/button.module.css | 15 ++++++++++ app/styles/feedback.css | 16 +++++------ app/templates/intro.hbs | 53 ++++++++++++++++++++++++++++-------- package.json | 2 +- 6 files changed, 106 insertions(+), 29 deletions(-) diff --git a/app/constants/urls.js b/app/constants/urls.js index cb7509dc1..89662b4ca 100644 --- a/app/constants/urls.js +++ b/app/constants/urls.js @@ -38,7 +38,7 @@ const APP_URLS = { TASKS: `${SCHEME}staging-my.${DOMAIN}/tasks`, IDENTITY: `${SCHEME}staging-my.${DOMAIN}/identity`, MY_STATUS: `${SCHEME}staging-my.${DOMAIN}`, - API_BACKEND: `http://localhost:3000`, + API_BACKEND: `${SCHEME}staging-api.${DOMAIN}`, }, test: { HOME: `${SCHEME}${DOMAIN}`, diff --git a/app/controllers/intro.js b/app/controllers/intro.js index 16ae0213e..98da398b5 100644 --- a/app/controllers/intro.js +++ b/app/controllers/intro.js @@ -1,22 +1,53 @@ import Controller from '@ember/controller'; import { inject as service } from '@ember/service'; +import { action } from '@ember/object'; export default class IntroController extends Controller { @service login; - @service onboarding; @action - async approveAction(){ - alert('Approved') - const inviteLink = await this.onboarding.discordInvite(); - if(inviteLink) { - window.open(`https://${inviteLink}`, '_blank'); + async approveAction() { + try { + const response = await fetch( + `https://api.realdevsquad.com/discord-actions/invite`, + { + method: 'POST', + credentials: 'include', + }, + ); + + if (response.ok) { + const result = await response.json(); + const inviteLink = result.inviteLink; + + this.model.inviteLink = inviteLink; + + alert('User approved and invite link generated.'); + } else { + const errorData = await response.json(); + alert(`Failed to generate invite link: ${errorData.message}`); + } + } catch (error) { + console.error('Error generating invite link:', error); + alert('An error occurred. Please try again later.'); } } @action - rejectAction(){ - alert('Rejected') + copyToClipboard(link) { + navigator.clipboard + .writeText(link) + .then(() => { + alert('Invite link copied to clipboard!'); + }) + .catch((err) => { + console.error('Failed to copy the text: ', err); + }); } + @action + rejectAction() { + alert('Rejected'); + // logic for rejection + } } diff --git a/app/styles/button.module.css b/app/styles/button.module.css index b175110df..4766b47aa 100644 --- a/app/styles/button.module.css +++ b/app/styles/button.module.css @@ -84,3 +84,18 @@ .reject-button:hover { background-color: #c82333; } + +.copy-button { + background-color: #007bff; + color: white; + font-size: 14px; + padding: 8px 16px; + border-radius: 5px; + border: none; + cursor: pointer; + margin-left: 10px; +} + +.copy-button:hover { + background-color: #0056b3; +} diff --git a/app/styles/feedback.css b/app/styles/feedback.css index a5173b156..486e53d27 100644 --- a/app/styles/feedback.css +++ b/app/styles/feedback.css @@ -1,10 +1,10 @@ .comment-box { - width: 100%; - height: 200px; - padding: 15px; - margin-top: 20px; - font-size: 16px; - border-radius: 5px; - border: 1px solid #ccc; - resize: none; + width: 100%; + height: 200px; + padding: 15px; + margin-top: 20px; + font-size: 16px; + border-radius: 5px; + border: 1px solid #ccc; + resize: none; } diff --git a/app/templates/intro.hbs b/app/templates/intro.hbs index 2874e055a..f12684a16 100644 --- a/app/templates/intro.hbs +++ b/app/templates/intro.hbs @@ -2,24 +2,55 @@
{{#if this.login.isLoading}} -
- +
+
{{else}} {{#if this.login.userData.roles.super_user}} - + @isSuperUser={{this.login.userData.roles.super_user}} + /> - - + {{! Textbox with no limit }} + + - -
- - + {{! Approve/Reject Buttons }} +
+ + +
+ + {{#if this.model.inviteLink}} +
+

Congratulations. You've been approved to join our Discord server + using this link:

+ {{this.model.inviteLink}} +
+ {{/if}} {{else}} diff --git a/package.json b/package.json index 30f6fcc6a..75aa78ca6 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "lint:js:fix": "eslint . --fix", "dev": "concurrently \"npm:dev:*\" --names \"dev:\"", "dev:ember": "ember server -p 4200", - "dev:reverse-ssl": "local-ssl-proxy --source 443 --target 4200", + "dev:reverse-ssl": "local-ssl-proxy --source 443 --target 4200 --hostname dev.realdevsquad.com", "start": "ember serve", "test": "concurrently \"npm:lint\" \"npm:test:*\" --names \"lint,test:\"", "test:ember": "ember test" From 6a41b35203b098a513300d41f5ed2751c186f7ee Mon Sep 17 00:00:00 2001 From: rishi-19-04 Date: Sun, 18 Aug 2024 14:05:26 +0530 Subject: [PATCH 3/9] added the reject and review functionality --- app/constants/urls.js | 2 +- app/controllers/intro.js | 13 +++++- app/templates/intro.hbs | 95 +++++++++++++++++++++++----------------- 3 files changed, 66 insertions(+), 44 deletions(-) diff --git a/app/constants/urls.js b/app/constants/urls.js index 89662b4ca..cb7509dc1 100644 --- a/app/constants/urls.js +++ b/app/constants/urls.js @@ -38,7 +38,7 @@ const APP_URLS = { TASKS: `${SCHEME}staging-my.${DOMAIN}/tasks`, IDENTITY: `${SCHEME}staging-my.${DOMAIN}/identity`, MY_STATUS: `${SCHEME}staging-my.${DOMAIN}`, - API_BACKEND: `${SCHEME}staging-api.${DOMAIN}`, + API_BACKEND: `http://localhost:3000`, }, test: { HOME: `${SCHEME}${DOMAIN}`, diff --git a/app/controllers/intro.js b/app/controllers/intro.js index 98da398b5..9bc439475 100644 --- a/app/controllers/intro.js +++ b/app/controllers/intro.js @@ -1,10 +1,14 @@ import Controller from '@ember/controller'; import { inject as service } from '@ember/service'; +import { tracked } from '@glimmer/tracking'; import { action } from '@ember/object'; export default class IntroController extends Controller { @service login; + @tracked rejectionNote = localStorage.getItem('rejectionNote') || ''; + @tracked isRejected = localStorage.getItem('isRejected') === 'true'; + @action async approveAction() { try { @@ -47,7 +51,12 @@ export default class IntroController extends Controller { @action rejectAction() { - alert('Rejected'); - // logic for rejection + const feedbackNote = document.querySelector('.comment-box').value.trim(); + this.rejectionNote = feedbackNote; + this.isRejected = true; + + // Store in local storage + localStorage.setItem('rejectionNote', feedbackNote); + localStorage.setItem('isRejected', 'true'); } } diff --git a/app/templates/intro.hbs b/app/templates/intro.hbs index f12684a16..4ebb620fa 100644 --- a/app/templates/intro.hbs +++ b/app/templates/intro.hbs @@ -7,53 +7,66 @@
{{else}} {{#if this.login.userData.roles.super_user}} - - - {{! Textbox with no limit }} - - + {{#if this.isRejected}} +
+

Unfortunately, at this time, your application is not approved.

+

{{this.rejectionNote}}

+
+ {{else}} + - {{! Approve/Reject Buttons }} -
- - -
+ + - {{#if this.model.inviteLink}} -
-

Congratulations. You've been approved to join our Discord server - using this link:

- {{this.model.inviteLink}} +
+ class="approve-button" + {{on "click" this.approveAction}} + >Approve +
- {{/if}} + {{#if this.model.inviteLink}} +
+

Congratulations. You've been approved to join our Discord server + using this link:

+ {{this.model.inviteLink}} + +
+ {{/if}} + {{/if}} {{else}} - + {{#if this.isRejected}} +
+

Unfortunately, at this time, your application is not approved.

+

{{this.rejectionNote}}

+
+ {{else}} +
+

Superusers are reviewing your application. Please check again after a few days.

+
+ {{/if}} {{/if}} {{/if}} -
\ No newline at end of file + From 396649ba1b6b39e8f135895642d91a5722feec61 Mon Sep 17 00:00:00 2001 From: Achintya-Chatterjee Date: Sun, 18 Aug 2024 14:39:18 +0530 Subject: [PATCH 4/9] Refactor: Include userId in API call for generating Discord invite link --- app/controllers/intro.js | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/app/controllers/intro.js b/app/controllers/intro.js index 9bc439475..2173b27a2 100644 --- a/app/controllers/intro.js +++ b/app/controllers/intro.js @@ -11,9 +11,16 @@ export default class IntroController extends Controller { @action async approveAction() { + const userId = this.model.userId; + + if (!userId) { + alert('User ID is missing. Unable to generate invite link.'); + return; + } + try { const response = await fetch( - `https://api.realdevsquad.com/discord-actions/invite`, + `https://api.realdevsquad.com/discord/invites?userId=${userId}`, { method: 'POST', credentials: 'include', @@ -27,6 +34,11 @@ export default class IntroController extends Controller { this.model.inviteLink = inviteLink; alert('User approved and invite link generated.'); + } else if (response.status === 409) { + alert('Invite link is already present for this user.'); + } else if (response.status === 403 || response.status === 404) { + const errorData = await response.json(); + alert(`Failed to generate invite link: ${errorData.message}`); } else { const errorData = await response.json(); alert(`Failed to generate invite link: ${errorData.message}`); From 3d78242b29029a07d1c8f3b86e8d8e4a76ee4a46 Mon Sep 17 00:00:00 2001 From: yash raj Date: Sun, 18 Aug 2024 20:04:07 +0530 Subject: [PATCH 5/9] integrate api to approve / reject --- app/constants/application.js | 5 ++ app/controllers/intro.js | 84 ++++++++++------------- app/templates/intro.hbs | 21 ++++-- app/utils/validate-application-details.js | 36 ++++++++++ 4 files changed, 91 insertions(+), 55 deletions(-) create mode 100644 app/constants/application.js create mode 100644 app/utils/validate-application-details.js diff --git a/app/constants/application.js b/app/constants/application.js new file mode 100644 index 000000000..68b23897a --- /dev/null +++ b/app/constants/application.js @@ -0,0 +1,5 @@ +export const APPLICATION_STATUS_TYPES = { + accepted: 'accepted', + rejected: 'rejected', + pending: 'pending', +}; diff --git a/app/controllers/intro.js b/app/controllers/intro.js index 2173b27a2..6c1026328 100644 --- a/app/controllers/intro.js +++ b/app/controllers/intro.js @@ -1,74 +1,60 @@ import Controller from '@ember/controller'; +import { action } from '@ember/object'; import { inject as service } from '@ember/service'; import { tracked } from '@glimmer/tracking'; -import { action } from '@ember/object'; +import { APPS } from '../constants/urls'; +import { validateApplicationDetails } from '../utils/validate-application-details'; +import { APPLICATION_STATUS_TYPES } from '../constants/application'; export default class IntroController extends Controller { @service login; + @tracked remarks = ''; + statusTypes = APPLICATION_STATUS_TYPES; - @tracked rejectionNote = localStorage.getItem('rejectionNote') || ''; - @tracked isRejected = localStorage.getItem('isRejected') === 'true'; + @action + updateRemarks(e) { + const value = e.currentTarget.value; + this.remarks = value; + } @action - async approveAction() { - const userId = this.model.userId; + async approveRejectAction(status) { + const initialApplicationDetails = this.model?.[0]; - if (!userId) { - alert('User ID is missing. Unable to generate invite link.'); + const { isValid, data } = validateApplicationDetails( + initialApplicationDetails, + ); + + if (!isValid || !data) { + alert('Invalid application details.'); return; } + const applicationId = data.id; + const body = { status, feedback: this.remarks }; + try { const response = await fetch( - `https://api.realdevsquad.com/discord/invites?userId=${userId}`, + `${APPS.API_BACKEND}/applications/${applicationId}`, { - method: 'POST', + method: 'PATCH', credentials: 'include', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(body), }, ); - if (response.ok) { - const result = await response.json(); - const inviteLink = result.inviteLink; - - this.model.inviteLink = inviteLink; - - alert('User approved and invite link generated.'); - } else if (response.status === 409) { - alert('Invite link is already present for this user.'); - } else if (response.status === 403 || response.status === 404) { - const errorData = await response.json(); - alert(`Failed to generate invite link: ${errorData.message}`); - } else { - const errorData = await response.json(); - alert(`Failed to generate invite link: ${errorData.message}`); + if (!response.ok || response.status >= 400) { + alert('Failed to update application status.'); + return; } + + alert(`Application ${status.toLowerCase()} successfully.`); } catch (error) { - console.error('Error generating invite link:', error); - alert('An error occurred. Please try again later.'); + alert('Something went wrong, please try again later.'); + console.error('Error :', error); } } - - @action - copyToClipboard(link) { - navigator.clipboard - .writeText(link) - .then(() => { - alert('Invite link copied to clipboard!'); - }) - .catch((err) => { - console.error('Failed to copy the text: ', err); - }); - } - - @action - rejectAction() { - const feedbackNote = document.querySelector('.comment-box').value.trim(); - this.rejectionNote = feedbackNote; - this.isRejected = true; - - // Store in local storage - localStorage.setItem('rejectionNote', feedbackNote); - localStorage.setItem('isRejected', 'true'); - } } diff --git a/app/templates/intro.hbs b/app/templates/intro.hbs index 4ebb620fa..7b13f8134 100644 --- a/app/templates/intro.hbs +++ b/app/templates/intro.hbs @@ -21,21 +21,29 @@
+ {{on + "click" + (fn this.approveRejectAction this.statusTypes.accepted) + }} + >Accept +
@@ -64,9 +72,10 @@ {{else}}
-

Superusers are reviewing your application. Please check again after a few days.

+

Superusers are reviewing your application. Please check again after + a few days.

{{/if}} {{/if}} {{/if}} - + \ No newline at end of file diff --git a/app/utils/validate-application-details.js b/app/utils/validate-application-details.js new file mode 100644 index 000000000..3a47fa42a --- /dev/null +++ b/app/utils/validate-application-details.js @@ -0,0 +1,36 @@ +/** + * Generate application details + * --- + * @param {Object} applicationDetails + * @param {string} applicationDetails.id + * @param {Object} applicationDetails.intro + * @param {string} applicationDetails.intro.funFact + * @param {string} applicationDetails.intro.forFun + * @param {number} applicationDetails.intro.numberOfHours + * @param {string} applicationDetails.intro.whyRds + * @param {string} applicationDetails.intro.introduction + * @param {Object} applicationDetails.biodata + * @param {string} applicationDetails.biodata.firstName + * @param {string} applicationDetails.biodata.lastName + * @param {Object} applicationDetails.location + * @param {string} applicationDetails.location.country + * @param {string} applicationDetails.location.city + * @param {string} applicationDetails.location.state + * @param {string} applicationDetails.foundFrom + * @param {string} applicationDetails.userId + * @param {Object} applicationDetails.professional + * @param {string} applicationDetails.professional.skills + * @param {string} applicationDetails.professional.institution + * @param {string} applicationDetails.status - "accepted" | "rejected" | "pending" + * + * @returns {Object} validateApplicationDetails + * @returns {boolean} validateApplicationDetails.isValid + * @returns {applicationDetails} validateApplicationDetails.data + */ +export const validateApplicationDetails = (applicationDetails) => { + if (!applicationDetails || !applicationDetails.userId) { + return { isValid: false, data: null }; + } + + return { isValid: true, data: applicationDetails }; +}; From 4c86a14266eae0fd48787db827506e261e7e1fa3 Mon Sep 17 00:00:00 2001 From: yash raj Date: Sun, 18 Aug 2024 20:28:35 +0530 Subject: [PATCH 6/9] fix textarea styling --- app/styles/app.css | 1 + app/styles/feedback.css | 26 +++++++++++++++++--------- app/templates/intro.hbs | 18 +++++++++++------- 3 files changed, 29 insertions(+), 16 deletions(-) diff --git a/app/styles/app.css b/app/styles/app.css index 9de6edd71..787e888ce 100644 --- a/app/styles/app.css +++ b/app/styles/app.css @@ -41,6 +41,7 @@ @import url("tooltip.module.css"); @import url("debug.module.css"); @import url("unauthenticated.module.css"); +@import url("feedback.css"); * { margin: 0; diff --git a/app/styles/feedback.css b/app/styles/feedback.css index 486e53d27..33cd066f2 100644 --- a/app/styles/feedback.css +++ b/app/styles/feedback.css @@ -1,10 +1,18 @@ -.comment-box { - width: 100%; - height: 200px; - padding: 15px; - margin-top: 20px; - font-size: 16px; - border-radius: 5px; - border: 1px solid #ccc; - resize: none; +.superuser-feedback { + width: 34rem; + padding: 1rem 0; + display: flex; + flex-direction: column; +} + +.superuser-feedback__label { + display: block; + font-size: 1.25rem; + font-weight: 700; + padding-bottom: 0.5rem; +} + +.superuser-feedback__textarea { + padding: 0.5rem; + border-radius: 0.5rem; } diff --git a/app/templates/intro.hbs b/app/templates/intro.hbs index 7b13f8134..80672508c 100644 --- a/app/templates/intro.hbs +++ b/app/templates/intro.hbs @@ -19,13 +19,17 @@ @isSuperUser={{this.login.userData.roles.super_user}} /> - - +
+ + +
{{else}} {{#if this.login.userData.roles.super_user}} - {{#if this.isRejected}} -
-

Unfortunately, at this time, your application is not approved.

-

{{this.rejectionNote}}

-
- {{else}} - + -
- - -
+
+ + +
-
- +
+ + + +
+ {{#if this.model.inviteLink}} +
+

Congratulations. You've been approved to join our Discord server + using this link:

+ {{this.model.inviteLink}} + class="copy-button" + {{on "click" (fn this.copyToClipboard this.model.inviteLink)}} + >Copy Link
- - {{#if this.model.inviteLink}} -
-

Congratulations. You've been approved to join our Discord server - using this link:

- {{this.model.inviteLink}} - -
- {{/if}} {{/if}} {{else}} - {{#if this.isRejected}} -
-

Unfortunately, at this time, your application is not approved.

-

{{this.rejectionNote}}

-
- {{else}} -
-

Superusers are reviewing your application. Please check again after - a few days.

-
- {{/if}} +
You're not authorized to view this page.
{{/if}} {{/if}} \ No newline at end of file From 247219154020342c60a687210c7d06e429347743 Mon Sep 17 00:00:00 2001 From: Achintya-Chatterjee Date: Mon, 19 Aug 2024 22:32:30 +0530 Subject: [PATCH 8/9] feat: Generate and display Discord invite link upon application acceptance in /intro page - Added functionality to generate Discord invite link when an application is accepted. - Display the invite link to the new user on the /intro page if their application is accepted. - Handle errors and provide feedback via toast notifications. --- app/constants/urls.js | 2 +- app/controllers/intro.js | 59 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 57 insertions(+), 4 deletions(-) diff --git a/app/constants/urls.js b/app/constants/urls.js index cb7509dc1..89662b4ca 100644 --- a/app/constants/urls.js +++ b/app/constants/urls.js @@ -38,7 +38,7 @@ const APP_URLS = { TASKS: `${SCHEME}staging-my.${DOMAIN}/tasks`, IDENTITY: `${SCHEME}staging-my.${DOMAIN}/identity`, MY_STATUS: `${SCHEME}staging-my.${DOMAIN}`, - API_BACKEND: `http://localhost:3000`, + API_BACKEND: `${SCHEME}staging-api.${DOMAIN}`, }, test: { HOME: `${SCHEME}${DOMAIN}`, diff --git a/app/controllers/intro.js b/app/controllers/intro.js index 6c1026328..b8e2b6571 100644 --- a/app/controllers/intro.js +++ b/app/controllers/intro.js @@ -5,16 +5,41 @@ import { tracked } from '@glimmer/tracking'; import { APPS } from '../constants/urls'; import { validateApplicationDetails } from '../utils/validate-application-details'; import { APPLICATION_STATUS_TYPES } from '../constants/application'; +import { TOAST_OPTIONS } from '../constants/toast-options'; export default class IntroController extends Controller { @service login; + @service toast; + @service onboarding; @tracked remarks = ''; + @tracked inviteLink = ''; + @tracked isRejected = false; + @tracked isAccepted = false; + @tracked feedback = ''; statusTypes = APPLICATION_STATUS_TYPES; + constructor() { + super(...arguments); + this.initializeStatusFlags(); + } + + initializeStatusFlags() { + const applicationDetails = this.model?.[0]; + if (applicationDetails) { + this.isRejected = applicationDetails.status === this.statusTypes.rejected; + this.isAccepted = applicationDetails.status === this.statusTypes.accepted; + this.feedback = applicationDetails.feedback; + + if (this.isAccepted) { + this.inviteLink = + this.onboarding.inviteLink || applicationDetails.inviteLink; + } + } + } + @action updateRemarks(e) { - const value = e.currentTarget.value; - this.remarks = value; + this.remarks = e.target.value; } @action @@ -46,15 +71,43 @@ export default class IntroController extends Controller { }, ); - if (!response.ok || response.status >= 400) { + if (!response.ok) { alert('Failed to update application status.'); return; } + if (status === this.statusTypes.accepted) { + this.inviteLink = await this.onboarding.discordInvite(); + this.isAccepted = true; + } else if (status === this.statusTypes.rejected) { + this.isRejected = true; + } + alert(`Application ${status.toLowerCase()} successfully.`); } catch (error) { alert('Something went wrong, please try again later.'); console.error('Error :', error); } } + + @action + copyToClipboard(link) { + navigator.clipboard + .writeText(link) + .then(() => { + this.toast.success( + 'Invite link copied to clipboard!', + 'Success!', + TOAST_OPTIONS, + ); + }) + .catch((err) => { + console.error('Failed to copy the text: ', err); + this.toast.error( + 'Failed to copy the link. Please try again.', + 'Error!', + TOAST_OPTIONS, + ); + }); + } } From 1ecdcda8c3a5402309a99f831298429488567f8c Mon Sep 17 00:00:00 2001 From: Achintya-Chatterjee Date: Tue, 20 Aug 2024 03:45:26 +0530 Subject: [PATCH 9/9] Update intro page logic to handle user-specific access and feedback display - Refactor intro page template to conditionally display content based on user role and application status. - Remove debug information from the intro page view. - Ensure that regular users can only see their own intro data, with appropriate messages for accepted, rejected, and pending statuses. - Allow superusers to review and update application statuses with relevant feedback. --- app/controllers/intro.js | 70 +++++++++++++++++++++++++++++++--------- app/routes/intro.js | 24 ++++++++++---- app/templates/intro.hbs | 49 +++++++++++++++------------- 3 files changed, 98 insertions(+), 45 deletions(-) diff --git a/app/controllers/intro.js b/app/controllers/intro.js index b8e2b6571..d1af9472c 100644 --- a/app/controllers/intro.js +++ b/app/controllers/intro.js @@ -11,29 +11,39 @@ export default class IntroController extends Controller { @service login; @service toast; @service onboarding; + @tracked remarks = ''; @tracked inviteLink = ''; @tracked isRejected = false; @tracked isAccepted = false; + @tracked isPending = false; @tracked feedback = ''; + statusTypes = APPLICATION_STATUS_TYPES; constructor() { super(...arguments); - this.initializeStatusFlags(); + } + + get applicationDetails() { + return this.model?.data?.[0]; } initializeStatusFlags() { - const applicationDetails = this.model?.[0]; - if (applicationDetails) { - this.isRejected = applicationDetails.status === this.statusTypes.rejected; - this.isAccepted = applicationDetails.status === this.statusTypes.accepted; - this.feedback = applicationDetails.feedback; + if (this.applicationDetails) { + const details = this.applicationDetails; + this.isAccepted = details.status === this.statusTypes.accepted; + this.isRejected = details.status === this.statusTypes.rejected; + this.isPending = details.status === this.statusTypes.pending; + this.feedback = details.feedback || ''; if (this.isAccepted) { - this.inviteLink = - this.onboarding.inviteLink || applicationDetails.inviteLink; + this.inviteLink = details.inviteLink || ''; } + } else { + this.isAccepted = false; + this.isRejected = false; + this.isPending = false; } } @@ -44,20 +54,20 @@ export default class IntroController extends Controller { @action async approveRejectAction(status) { - const initialApplicationDetails = this.model?.[0]; + const initialApplicationDetails = this.model; const { isValid, data } = validateApplicationDetails( initialApplicationDetails, ); if (!isValid || !data) { - alert('Invalid application details.'); + console.error('Invalid application details:', initialApplicationDetails); + this.toast.error('Invalid application details.', 'Error!', TOAST_OPTIONS); return; } const applicationId = data.id; const body = { status, feedback: this.remarks }; - try { const response = await fetch( `${APPS.API_BACKEND}/applications/${applicationId}`, @@ -72,21 +82,51 @@ export default class IntroController extends Controller { ); if (!response.ok) { - alert('Failed to update application status.'); + console.error( + 'Failed to update application status. Response:', + response, + ); + this.toast.error( + 'Failed to update application status.', + 'Error!', + TOAST_OPTIONS, + ); return; } if (status === this.statusTypes.accepted) { this.inviteLink = await this.onboarding.discordInvite(); this.isAccepted = true; + this.isRejected = false; + this.isPending = false; } else if (status === this.statusTypes.rejected) { this.isRejected = true; + this.isAccepted = false; + this.isPending = false; + } else if (status === this.statusTypes.pending) { + this.isPending = true; + this.isRejected = false; + this.isAccepted = false; } - alert(`Application ${status.toLowerCase()} successfully.`); + console.log('Updated status flags:', { + isAccepted: this.isAccepted, + isRejected: this.isRejected, + isPending: this.isPending, + }); + + this.toast.success( + `Application ${status.toLowerCase()} successfully.`, + 'Success!', + TOAST_OPTIONS, + ); } catch (error) { - alert('Something went wrong, please try again later.'); - console.error('Error :', error); + console.error('Error updating application status:', error); + this.toast.error( + 'Something went wrong, please try again later.', + 'Error!', + TOAST_OPTIONS, + ); } } diff --git a/app/routes/intro.js b/app/routes/intro.js index be26d66d9..c18d65b17 100644 --- a/app/routes/intro.js +++ b/app/routes/intro.js @@ -13,15 +13,25 @@ export default class IntroRoute extends Route { async model(params) { const userId = params.id; - const response = await fetch(APPLICATION_URL(userId), { - credentials: 'include', - }); + try { + const response = await fetch(APPLICATION_URL(userId), { + credentials: 'include', + }); + if (response.status === 404) { + this.router.transitionTo('/page-not-found'); + return {}; + } - if (response.status === 404) { - this.router.transitionTo('/page-not-found'); + const data = await response.json(); + return data; + } catch (error) { + console.error('Error fetching application data:', error); + return {}; } + } - const data = await response.json(); - return data.data; + setupController(controller, model) { + super.setupController(controller, model); + controller.initializeStatusFlags(); } } diff --git a/app/templates/intro.hbs b/app/templates/intro.hbs index 72b1aa0f1..bce8dcb25 100644 --- a/app/templates/intro.hbs +++ b/app/templates/intro.hbs @@ -1,14 +1,26 @@ -{{page-title "Intro"}} -
{{#if this.login.isLoading}}
- {{else}} - {{#if this.login.userData.roles.super_user}} + {{else if this.applicationDetails}} + {{#if this.isAccepted}} +
+

Congratulations. You've been approved to join our Discord server using this link:

+ {{this.inviteLink}} + +

{{this.feedback}}

+
+ {{else if this.isRejected}} +
+

Unfortunately, at this time, your application is not approved.

+

{{this.feedback}}

+
+ {{else if this.isPending}} +
We are reviewing your application. Please check again here after some time for an update.
+ {{else if this.login.userData.roles.super_user}} @@ -37,26 +49,17 @@ class="reject-button" {{on "click" (fn this.approveRejectAction this.statusTypes.rejected)}} >Reject -
- {{#if this.model.inviteLink}} -
-

Congratulations. You've been approved to join our Discord server - using this link:

- {{this.model.inviteLink}} - -
- {{/if}} + + {{else}}
You're not authorized to view this page.
{{/if}} + {{else}} +
No application details found.
{{/if}} - \ No newline at end of file +