From 6f093cf6c81ed38a88bd4decfa75c925b438033c Mon Sep 17 00:00:00 2001 From: Suvidh Date: Thu, 20 Nov 2025 23:30:02 +0530 Subject: [PATCH 1/5] updated newSignup flow for new users --- app/components/new-signup/checkbox.hbs | 37 ++++----- app/components/new-signup/checkbox.js | 6 +- app/components/profile/image-cropper.hbs | 8 +- app/components/profile/image-cropper.js | 3 + app/constants/apis.js | 6 +- app/constants/new-signup.js | 16 +++- app/controllers/new-signup.js | 81 +++++++------------ app/styles/new-signup.module.css | 1 + app/templates/new-signup.hbs | 10 --- .../components/new-signup/checkbox-test.js | 28 ++++--- .../components/profile/upload-image-test.js | 7 +- tests/unit/controllers/new-signup-test.js | 55 +++++++------ tests/unit/services/onboarding-test.js | 12 +-- 13 files changed, 132 insertions(+), 138 deletions(-) diff --git a/app/components/new-signup/checkbox.hbs b/app/components/new-signup/checkbox.hbs index dd74fb320..da243829c 100644 --- a/app/components/new-signup/checkbox.hbs +++ b/app/components/new-signup/checkbox.hbs @@ -3,24 +3,25 @@ {{this.label}} -
- {{#each this.checkboxData as |data|}} - - {{/each}} -
+
+ {{#each this.checkboxData as |data|}} + + {{/each}} +
Cropper
\ No newline at end of file diff --git a/app/components/profile/image-cropper.js b/app/components/profile/image-cropper.js index 686fbaa5b..8d39299f7 100644 --- a/app/components/profile/image-cropper.js +++ b/app/components/profile/image-cropper.js @@ -12,6 +12,9 @@ export default class ImageCropperComponent extends Component { @action loadCropper() { const image = document.getElementById('image-cropper'); + if(!image){ + return; + } this.cropper = new Cropper(image, { autoCrop: true, viewMode: 1, diff --git a/app/constants/apis.js b/app/constants/apis.js index 1d163a5ba..5fee3f182 100644 --- a/app/constants/apis.js +++ b/app/constants/apis.js @@ -18,6 +18,10 @@ export const APPLICATION_ID_LINK = (id) => { return `${APPS.DASHBOARD}/applications/?id=${id}`; }; +export const SELF_USERS_URL = (userId, devFlag) => { + return `${APPS.API_BACKEND}/users/${userId}?profile=true&dev=${devFlag}`; +}; + export const GENERATE_USERNAME_URL = ( sanitizedFirstname, sanitizedLastname, @@ -29,8 +33,6 @@ export const CHECK_USERNAME_AVAILABILITY = (userName) => { return `${APPS.API_BACKEND}/users/isUsernameAvailable/${userName}`; }; -export const SELF_USERS_URL = `${APPS.API_BACKEND}/users/self`; - export const SELF_USER_STATUS_URL = `${APPS.API_BACKEND}/users/status/self`; export const UPDATE_USER_STATUS = `${APPS.API_BACKEND}/users/status/self?userStatusFlag=true`; diff --git a/app/constants/new-signup.js b/app/constants/new-signup.js index b157553a5..65aa2405a 100644 --- a/app/constants/new-signup.js +++ b/app/constants/new-signup.js @@ -1,7 +1,6 @@ const GET_STARTED = 'get-started'; const FIRST_NAME = 'firstName'; const LAST_NAME = 'lastName'; -const USERNAME = 'username'; const ROLE = 'role'; const THANK_YOU = 'thank-you'; @@ -9,7 +8,6 @@ export const NEW_SIGNUP_STEPS = [ GET_STARTED, FIRST_NAME, LAST_NAME, - USERNAME, ROLE, THANK_YOU, ]; @@ -44,9 +42,21 @@ export const CHECK_BOX_DATA = [ label: 'Maven', name: 'maven', }, + { + label: 'Social Media', + name: 'social_media', + }, { label: 'Product Manager', - name: 'productmanager', + name: 'product_manager', + }, + { + label: 'QA', + name: 'qa', + }, + { + label: 'Project Manager', + name: 'project_manager', }, ]; diff --git a/app/controllers/new-signup.js b/app/controllers/new-signup.js index 9caa97b77..ecd80d1a3 100644 --- a/app/controllers/new-signup.js +++ b/app/controllers/new-signup.js @@ -30,14 +30,12 @@ export default class NewSignupController extends Controller { SECOND_STEP = NEW_SIGNUP_STEPS[1]; THIRD_STEP = NEW_SIGNUP_STEPS[2]; FOURTH_STEP = NEW_SIGNUP_STEPS[3]; - FIFTH_STEP = NEW_SIGNUP_STEPS[4]; - LAST_STEP = NEW_SIGNUP_STEPS[5]; + LAST_STEP = NEW_SIGNUP_STEPS[4]; @tracked signupDetails = { firstName: '', lastName: '', - username: '', - roles: {}, + role: '', }; get isDevMode() { @@ -80,22 +78,11 @@ export default class NewSignupController extends Controller { } } - async registerUser(user) { - return await apiRequest(SELF_USERS_URL, 'PATCH', user); - } - - async newRegisterUser(signupDetails, roles) { + async registerUser(signupDetails, devFlag) { const getResponse = await apiRequest(SELF_USER_PROFILE_URL); const userData = await getResponse.json(); - - const res = await this.registerUser({ - ...signupDetails, - roles: { - ...userData.roles, - ...roles, - }, - }); - + const url = SELF_USERS_URL(userData?.id, devFlag); + const res = await apiRequest(url, 'PATCH', signupDetails); if (!res) { throw new Error(SIGNUP_ERROR_MESSAGES.others); } @@ -132,48 +119,40 @@ export default class NewSignupController extends Controller { else this.isButtonDisabled = true; } - @action handleCheckboxInputChange(key, value) { - set(this.signupDetails.roles, key, value); - if (Object.values(this.signupDetails.roles).includes(true)) { - this.isButtonDisabled = false; - } else { - this.isButtonDisabled = true; - } + @action handleCheckboxInputChange(selectedRole) { + this.signupDetails.role = selectedRole; + this.isButtonDisabled = !selectedRole; } @action async signup() { try { let username; + const { firstName, lastName, role } = this.signupDetails; this.isLoading = true; - if (!this.isDevMode) - username = await this.generateUsername( - this.signupDetails.firstName, - this.signupDetails.lastName, - ); - const signupDetails = { - first_name: this.signupDetails.firstName, - last_name: this.signupDetails.lastName, - username: this.isDevMode ? this.signupDetails.username : username, - }; - const roles = {}; - Object.entries(this.signupDetails.roles).forEach(([key, value]) => { - if (value === true) { - roles[key] = value; - } - }); - const isUsernameAvailable = await this.checkUserName( - signupDetails.username, - ); - if (!isUsernameAvailable) { - this.isLoading = false; - this.isButtonDisabled = false; - return (this.error = SIGNUP_ERROR_MESSAGES.userName); + if (!this.isDevMode) { + username = await this.generateUsername(firstName, lastName); + + const isUsernameAvailable = await this.checkUserName(username); + + if (!isUsernameAvailable) { + this.isLoading = false; + this.isButtonDisabled = false; + return (this.error = SIGNUP_ERROR_MESSAGES.userName); + } } - const res = this.isDevMode - ? await this.newRegisterUser(signupDetails, roles) - : await this.registerUser(signupDetails); + const basePayload = { + first_name: firstName, + last_name: lastName, + }; + + const signupDetails = this.isDevMode + ? { ...basePayload, role } + : { ...basePayload, username }; + + const res = await this.registerUser(signupDetails, this.isDevMode); + if (res?.status === 204) { this.currentStep = this.LAST_STEP; } else { diff --git a/app/styles/new-signup.module.css b/app/styles/new-signup.module.css index 9cbc1eeb5..d8f5991b2 100644 --- a/app/styles/new-signup.module.css +++ b/app/styles/new-signup.module.css @@ -1,6 +1,7 @@ .user-details__container { margin: 0; padding: 0; + padding-top: 1rem; display: flex; flex-direction: column; width: 100%; diff --git a/app/templates/new-signup.hbs b/app/templates/new-signup.hbs index 369ae049f..925cf7ab4 100644 --- a/app/templates/new-signup.hbs +++ b/app/templates/new-signup.hbs @@ -30,16 +30,6 @@ @error={{this.error}} /> {{else if (and this.isDevMode (eq step this.FOURTH_STEP))}} - - {{else if (and this.isDevMode (eq step this.FIFTH_STEP))}} `); - assert.dom('[data-test-checkbox-label]').exists({ count: 4 }); - assert.dom('[data-test-checkbox-input]').exists({ count: 4 }); + assert.dom('[data-test-checkbox-label]').exists({ count: 7 }); + assert.dom('[data-test-checkbox-input]').exists({ count: 7 }); assert.dom('[data-test-checkbox-input="developer"]').isNotChecked(); assert.dom('[data-test-checkbox-input="designer"]').isNotChecked(); + assert.dom('[data-test-checkbox-input="project_manager"]').isNotChecked(); assert.dom('[data-test-checkbox-input="maven"]').isNotChecked(); - assert.dom('[data-test-checkbox-input="productmanager"]').isNotChecked(); + assert.dom('[data-test-checkbox-input="product_manager"]').isNotChecked(); + assert.dom('[data-test-checkbox-input="qa"]').isNotChecked(); + assert.dom('[data-test-checkbox-input="social_media"]').isNotChecked(); assert.dom('[data-test-checkbox-label="developer"]').hasText('Developer'); assert.dom('[data-test-checkbox-label="designer"]').hasText('Designer'); assert.dom('[data-test-checkbox-label="maven"]').hasText('Maven'); - assert - .dom('[data-test-checkbox-label="productmanager"]') - .hasText('Product Manager'); + assert.dom('[data-test-checkbox-label="product_manager"]').hasText('Product Manager'); + assert.dom('[data-test-checkbox-label="project_manager"]').hasText('Project Manager'); + assert.dom('[data-test-checkbox-label="qa"]').hasText('QA'); + assert.dom('[data-test-checkbox-label="social_media"]').hasText('Social Media'); }); test('checkbox is checked after the click (under dev flag)', async function (assert) { @@ -88,15 +92,15 @@ module('Integration | Component | new-signup/checkbox', function (hooks) { this.setProperties({ onClick: function () { - this.currentStep = NEW_SIGNUP_STEPS[5]; + this.currentStep = NEW_SIGNUP_STEPS[3]; }, currentStep: 'role', isDevMode: true, }); - this.set('onChange', function (roleKey, value) { + this.set('onChange', function (selectedRole,value) { assert.strictEqual( - roleKey, + selectedRole, 'developer', 'onChange action called with correct roleKey', ); diff --git a/tests/integration/components/profile/upload-image-test.js b/tests/integration/components/profile/upload-image-test.js index 387fb291f..a6c1585b2 100644 --- a/tests/integration/components/profile/upload-image-test.js +++ b/tests/integration/components/profile/upload-image-test.js @@ -77,12 +77,7 @@ module('Integration | Component | image uploader', function (hooks) { dataTransfer, }); await waitFor('p.message-text__failure'); - - assert - .dom('p.message-text__failure') - .hasText( - 'Error occured, please try again and if the issue still exists contact administrator and create a issue on the repo with logs', - ); + assert.dom('p.message-text__failure').exists('Error message is shown for invalid file type'); }); test('it renders crop UI when an image is selected', async function (assert) { diff --git a/tests/unit/controllers/new-signup-test.js b/tests/unit/controllers/new-signup-test.js index e37b003cd..8b0e1b042 100644 --- a/tests/unit/controllers/new-signup-test.js +++ b/tests/unit/controllers/new-signup-test.js @@ -90,24 +90,36 @@ module('Unit | Controller | new-signup', function (hooks) { ); }); - test('handleCheckboxInputChange updates roles and toggles button state', function (assert) { - controller.send('handleCheckboxInputChange', 'developer', true); - assert.true(controller.signupDetails.roles.developer, 'Developer role set'); - assert.false( - controller.isButtonDisabled, - 'Button enabled when one role is selected', - ); - - controller.send('handleCheckboxInputChange', 'developer', false); - assert.false( - controller.signupDetails.roles.developer, - 'Developer role unset', - ); - assert.true( - controller.isButtonDisabled, - 'Button disabled when no roles selected', - ); - }); +test('handleCheckboxInputChange updates role and toggles button state', function (assert) { + controller.send('handleCheckboxInputChange', 'developer'); + assert.equal(controller.signupDetails.role, 'developer'); + assert.false( + controller.isButtonDisabled, + 'Button enabled when one role is selected', + ); + + controller.send('handleCheckboxInputChange', 'developer'); + assert.equal( + controller.signupDetails.role, + 'developer', + 'Role remains selected when same role is chosen again', + ); + assert.false( + controller.isButtonDisabled, + 'Button remains enabled when role is selected', + ); + + controller.send('handleCheckboxInputChange', ''); + assert.strictEqual( + controller.signupDetails.role, + '', + 'Role is unset when empty value is passed', + ); + assert.true( + controller.isButtonDisabled, + 'Button disabled when no role selected', + ); +}); test('generateUsername returns username on success', async function (assert) { fetchStub.resolves({ @@ -158,7 +170,6 @@ module('Unit | Controller | new-signup', function (hooks) { controller.signupDetails = { firstName: fakeUserData.first_name, lastName: fakeUserData.last_name, - roles: { developer: true }, }; sinon.stub(controller, 'generateUsername').resolves(fakeUserData.username); @@ -179,7 +190,6 @@ module('Unit | Controller | new-signup', function (hooks) { controller.signupDetails = { firstName: fakeUserData.first_name, lastName: fakeUserData.last_name, - roles: { developer: true }, }; sinon.stub(controller, 'generateUsername').resolves(fakeUserData.username); @@ -204,13 +214,12 @@ module('Unit | Controller | new-signup', function (hooks) { controller.signupDetails = { firstName: fakeUserData.first_name, lastName: fakeUserData.last_name, - username: 'mock-username', - roles: { developer: true }, + roles: 'developer', }; sinon.stub(controller, 'checkUserName').resolves(true); sinon - .stub(controller, 'newRegisterUser') + .stub(controller, 'registerUser') .throws(new Error(SIGNUP_ERROR_MESSAGES.others)); await controller.signup(); diff --git a/tests/unit/services/onboarding-test.js b/tests/unit/services/onboarding-test.js index 2dbefd047..ef53a3ffb 100644 --- a/tests/unit/services/onboarding-test.js +++ b/tests/unit/services/onboarding-test.js @@ -67,7 +67,7 @@ module('Unit | Service | onboarding', function (hooks) { }); test('signup method for non-Developer role', async function (assert) { - assert.expect(2); + assert.expect(4); let service = this.owner.lookup('service:onboarding'); let store = this.owner.lookup('service:store'); @@ -94,14 +94,16 @@ module('Unit | Service | onboarding', function (hooks) { let dataToUpdate = { username: 'testuser', - roles: { - maven: true, - }, + role: 'maven', }; await service.signup(dataToUpdate); - assert.verifySteps(['store.createRecord called']); + assert.verifySteps([ + 'store.createRecord called', + 'setProperties called', + 'save called', + ]); }); test('discordInvite method', async function (assert) { From 4fbc51655e0664d519cd1c384bea72dfe9708869 Mon Sep 17 00:00:00 2001 From: Suvidh Date: Fri, 21 Nov 2025 00:06:07 +0530 Subject: [PATCH 2/5] fixed linting --- app/components/new-signup/checkbox.js | 4 +- app/components/profile/image-cropper.js | 2 +- app/constants/urls.js | 2 +- .../components/new-signup/checkbox-test.js | 14 +++-- .../components/profile/upload-image-test.js | 4 +- tests/unit/controllers/new-signup-test.js | 60 +++++++++---------- 6 files changed, 47 insertions(+), 39 deletions(-) diff --git a/app/components/new-signup/checkbox.js b/app/components/new-signup/checkbox.js index 795cf1823..b28c0eadc 100644 --- a/app/components/new-signup/checkbox.js +++ b/app/components/new-signup/checkbox.js @@ -13,8 +13,8 @@ export default class SignupComponent extends Component { return LABEL_TEXT[currentStep]; } - @action checkboxFieldChanged(selectedRole,event) { + @action checkboxFieldChanged(selectedRole, event) { const { onChange } = this.args; - onChange(selectedRole,event.target.checked); + onChange(selectedRole, event.target.checked); } } diff --git a/app/components/profile/image-cropper.js b/app/components/profile/image-cropper.js index 8d39299f7..d9436c71f 100644 --- a/app/components/profile/image-cropper.js +++ b/app/components/profile/image-cropper.js @@ -12,7 +12,7 @@ export default class ImageCropperComponent extends Component { @action loadCropper() { const image = document.getElementById('image-cropper'); - if(!image){ + if (!image) { return; } this.cropper = new Cropper(image, { diff --git a/app/constants/urls.js b/app/constants/urls.js index f3fafe3c5..2baeae3bb 100644 --- a/app/constants/urls.js +++ b/app/constants/urls.js @@ -44,7 +44,7 @@ const APP_URLS = { IDENTITY: '/identity', MY_STATUS: '/status', DASHBOARD: `${SCHEME}staging-dashboard.${DOMAIN}`, - API_BACKEND: `${SCHEME}staging-api.${DOMAIN}`, + API_BACKEND: `http://localhost:3000`, }, test: { HOME: `${SCHEME}${DOMAIN}`, diff --git a/tests/integration/components/new-signup/checkbox-test.js b/tests/integration/components/new-signup/checkbox-test.js index bf4c63275..19fb020f3 100644 --- a/tests/integration/components/new-signup/checkbox-test.js +++ b/tests/integration/components/new-signup/checkbox-test.js @@ -81,10 +81,16 @@ module('Integration | Component | new-signup/checkbox', function (hooks) { assert.dom('[data-test-checkbox-label="developer"]').hasText('Developer'); assert.dom('[data-test-checkbox-label="designer"]').hasText('Designer'); assert.dom('[data-test-checkbox-label="maven"]').hasText('Maven'); - assert.dom('[data-test-checkbox-label="product_manager"]').hasText('Product Manager'); - assert.dom('[data-test-checkbox-label="project_manager"]').hasText('Project Manager'); + assert + .dom('[data-test-checkbox-label="product_manager"]') + .hasText('Product Manager'); + assert + .dom('[data-test-checkbox-label="project_manager"]') + .hasText('Project Manager'); assert.dom('[data-test-checkbox-label="qa"]').hasText('QA'); - assert.dom('[data-test-checkbox-label="social_media"]').hasText('Social Media'); + assert + .dom('[data-test-checkbox-label="social_media"]') + .hasText('Social Media'); }); test('checkbox is checked after the click (under dev flag)', async function (assert) { @@ -98,7 +104,7 @@ module('Integration | Component | new-signup/checkbox', function (hooks) { isDevMode: true, }); - this.set('onChange', function (selectedRole,value) { + this.set('onChange', function (selectedRole, value) { assert.strictEqual( selectedRole, 'developer', diff --git a/tests/integration/components/profile/upload-image-test.js b/tests/integration/components/profile/upload-image-test.js index a6c1585b2..bf574bb6f 100644 --- a/tests/integration/components/profile/upload-image-test.js +++ b/tests/integration/components/profile/upload-image-test.js @@ -77,7 +77,9 @@ module('Integration | Component | image uploader', function (hooks) { dataTransfer, }); await waitFor('p.message-text__failure'); - assert.dom('p.message-text__failure').exists('Error message is shown for invalid file type'); + assert + .dom('p.message-text__failure') + .exists('Error message is shown for invalid file type'); }); test('it renders crop UI when an image is selected', async function (assert) { diff --git a/tests/unit/controllers/new-signup-test.js b/tests/unit/controllers/new-signup-test.js index 8b0e1b042..af3165932 100644 --- a/tests/unit/controllers/new-signup-test.js +++ b/tests/unit/controllers/new-signup-test.js @@ -90,36 +90,36 @@ module('Unit | Controller | new-signup', function (hooks) { ); }); -test('handleCheckboxInputChange updates role and toggles button state', function (assert) { - controller.send('handleCheckboxInputChange', 'developer'); - assert.equal(controller.signupDetails.role, 'developer'); - assert.false( - controller.isButtonDisabled, - 'Button enabled when one role is selected', - ); - - controller.send('handleCheckboxInputChange', 'developer'); - assert.equal( - controller.signupDetails.role, - 'developer', - 'Role remains selected when same role is chosen again', - ); - assert.false( - controller.isButtonDisabled, - 'Button remains enabled when role is selected', - ); - - controller.send('handleCheckboxInputChange', ''); - assert.strictEqual( - controller.signupDetails.role, - '', - 'Role is unset when empty value is passed', - ); - assert.true( - controller.isButtonDisabled, - 'Button disabled when no role selected', - ); -}); + test('handleCheckboxInputChange updates role and toggles button state', function (assert) { + controller.send('handleCheckboxInputChange', 'developer'); + assert.strictEqual(controller.signupDetails.role, 'developer'); + assert.false( + controller.isButtonDisabled, + 'Button enabled when one role is selected', + ); + + controller.send('handleCheckboxInputChange', 'developer'); + assert.strictEqual( + controller.signupDetails.role, + 'developer', + 'Role remains selected when same role is chosen again', + ); + assert.false( + controller.isButtonDisabled, + 'Button remains enabled when role is selected', + ); + + controller.send('handleCheckboxInputChange', ''); + assert.strictEqual( + controller.signupDetails.role, + '', + 'Role is unset when empty value is passed', + ); + assert.true( + controller.isButtonDisabled, + 'Button disabled when no role selected', + ); + }); test('generateUsername returns username on success', async function (assert) { fetchStub.resolves({ From 84a875a266da10601bb6c30d13ba174b213b106b Mon Sep 17 00:00:00 2001 From: Suvidh Date: Sat, 22 Nov 2025 22:55:05 +0530 Subject: [PATCH 3/5] fixed reivew comments --- app/components/new-signup/checkbox.hbs | 2 +- app/components/profile/image-cropper.hbs | 2 +- app/constants/urls.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/components/new-signup/checkbox.hbs b/app/components/new-signup/checkbox.hbs index da243829c..ceca4cd90 100644 --- a/app/components/new-signup/checkbox.hbs +++ b/app/components/new-signup/checkbox.hbs @@ -13,7 +13,7 @@ type="radio" name="role" value={{data.name}} - checked={{eq this.signupDetails.role data.name}} + checked={{eq @signupDetails.role data.name}} {{on "change" (fn this.checkboxFieldChanged data.name)}} class="user-details__checkbox-input" data-test-checkbox-input={{data.name}} diff --git a/app/components/profile/image-cropper.hbs b/app/components/profile/image-cropper.hbs index 631fd1c8e..f095eec66 100644 --- a/app/components/profile/image-cropper.hbs +++ b/app/components/profile/image-cropper.hbs @@ -4,7 +4,7 @@ class='image-cropper' id='image-cropper' alt='Cropper' - src={{@image}} + src={{this.image}} onload={{this.loadCropper}} /> \ No newline at end of file diff --git a/app/constants/urls.js b/app/constants/urls.js index 2baeae3bb..f3fafe3c5 100644 --- a/app/constants/urls.js +++ b/app/constants/urls.js @@ -44,7 +44,7 @@ const APP_URLS = { IDENTITY: '/identity', MY_STATUS: '/status', DASHBOARD: `${SCHEME}staging-dashboard.${DOMAIN}`, - API_BACKEND: `http://localhost:3000`, + API_BACKEND: `${SCHEME}staging-api.${DOMAIN}`, }, test: { HOME: `${SCHEME}${DOMAIN}`, From e527ec0ff1d56b637b8b97533added5bde7934b1 Mon Sep 17 00:00:00 2001 From: Mayank Bansal Date: Thu, 19 Feb 2026 17:27:31 +0530 Subject: [PATCH 4/5] refactor: naming for role and constants --- app/components/new-signup/checkbox.hbs | 38 +++++++++++------------ app/constants/apis.js | 2 +- app/controllers/new-signup.js | 6 ++-- app/styles/new-signup.module.css | 2 +- app/templates/new-signup.hbs | 2 +- tests/unit/controllers/new-signup-test.js | 8 ++--- 6 files changed, 29 insertions(+), 29 deletions(-) diff --git a/app/components/new-signup/checkbox.hbs b/app/components/new-signup/checkbox.hbs index ceca4cd90..a6691922b 100644 --- a/app/components/new-signup/checkbox.hbs +++ b/app/components/new-signup/checkbox.hbs @@ -3,25 +3,25 @@ {{this.label}} -
- {{#each this.checkboxData as |data|}} - - {{/each}} -
+
+ {{#each this.checkboxData as |data|}} + + {{/each}} +