Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
be0379c
fix: pom version
vishwab1 Feb 18, 2026
0a5aa58
feat: added facilty hierachy
vishwab1 Feb 25, 2026
6364a81
feat: chnages in work location maping
vishwab1 Feb 26, 2026
f5ea2cc
feat: chnages in work location maping
vishwab1 Feb 26, 2026
9ae4208
fix: modified the work location
vishwab1 Feb 26, 2026
759e88c
fix: corrections
vishwab1 Mar 3, 2026
ff58e10
fix: facilty changes
vishwab1 Mar 6, 2026
860e7c9
fix: facilty hierachy
vishwab1 Mar 18, 2026
f9e439a
fix: inventory
vishwab1 Mar 18, 2026
d854c9c
fix: add missing environment URLs for facility and asha supervisor ma…
vishwab1 Mar 18, 2026
780ca4f
fix: revert Common-UI submodule to main and update pom version to 3.8.1
vishwab1 Mar 19, 2026
7a998d5
fix: revert Common-UI submodule pointer to match main
vishwab1 Mar 19, 2026
e63bb17
fix: align Common-UI submodule with release-3.8.1
vishwab1 Mar 19, 2026
38d0d6b
Merge pull request #131 from PSMRI/vb/3.6.2-wl3
snehar-nd Mar 23, 2026
cefa2f9
fix: added new inventory flow
vishwab1 Mar 26, 2026
d897c2d
Merge remote-tracking branch 'origin/release-3.8.1' into vb/3.6.2-wl4
vishwab1 Mar 26, 2026
c747c4e
Merge pull request #132 from PSMRI/vb/3.6.2-wl4
snehar-nd Mar 26, 2026
1f876b4
Work Location Mapping enhancements for Stop TB, search, and select al…
vishwab1 May 15, 2026
7094d2e
AMM-118: Add employee lock controls in admin UI
Jan 7, 2026
f91c541
Sn/active/deactive (#145)
snehar-nd Jun 30, 2026
6d33b5c
Bump version from 3.8.1 to 3.8.2 (#146)
snehar-nd Jun 30, 2026
3b586dd
fix: amm-2368 item to store mapping issue (#148)
snehar-nd Jul 1, 2026
fcd515f
feat: add nikshay tu/facility/village dropdowns to work location mapping
vishwab1 Jul 10, 2026
aa7c260
fix: add nikshay location urls to prod/ci/test/local environment configs
vishwab1 Jul 10, 2026
fa3b236
fix: send nikshayTUID/nikshayFacilityID on Stop TB work location save
vishwab1 Jul 10, 2026
5f2f9fd
fix: include blockID/blockName in Stop TB work location save
vishwab1 Jul 10, 2026
1c57e12
fix: use Nikshay TU as Block for Stop TB work location save
vishwab1 Jul 14, 2026
23fe641
feat(nikshay): wire work-location-mapping to independent Nikshay hier…
vishwab1 Jul 14, 2026
9e71a58
feat(nikshay): replace AMRIT-district name-matching with dedicated dr…
vishwab1 Jul 14, 2026
73fe180
fix(nikshay): merge State/District back into single AMRIT-sourced fields
vishwab1 Jul 14, 2026
28e379f
fix(nikshay): make District 100% Nikshay-sourced for Stop TB, drop di…
vishwab1 Jul 14, 2026
dbb5356
fix(nikshay): fix Chattisgarh spelling mismatch, make State selection…
vishwab1 Jul 14, 2026
a63f8c2
fix(nikshay): fix Edit-flow district resolution and collapse TU/Facil…
vishwab1 Jul 15, 2026
162b458
fix(nikshay): wire real Edit entry point and fix DistrictID storage
vishwab1 Jul 15, 2026
8e7a62f
feat(nikshay): wire Edit to the new saved-TU/Facility/District endpoint
vishwab1 Jul 15, 2026
de97dcb
fix(nikshay): fix Edit District dropdown source and stop relying on a
vishwab1 Jul 15, 2026
b4eacff
fix(nikshay): route Stop TB Update clicks to updateStopTBWorkLocation
vishwab1 Jul 15, 2026
8992707
fix(nikshay): fix Stop TB update payload shape - was silently saving …
vishwab1 Jul 15, 2026
e170e11
fix(nikshay): switch Stop TB Update to the shared in-place update path
vishwab1 Jul 15, 2026
7ee99e1
feat(nikshay): add Edit District picker for old users, block Villagei…
vishwab1 Jul 15, 2026
5963ebd
feat(nikshay): make Select Block functional, enable Village overwrite…
vishwab1 Jul 15, 2026
152bf2c
feat: add nikshay tu/facility/village dropdowns to work location mapping
vishwab1 Jul 10, 2026
7a92f91
fix: add nikshay location urls to prod/ci/test/local environment configs
vishwab1 Jul 10, 2026
31bb953
fix: default provider Valid Till to 5 years out instead of today
vishwab1 Jul 28, 2026
66c50dd
Merge branch 'vb/merge' into vb/release-3.8.2-merge
vishwab1 Jul 28, 2026
1fde436
Merge pull request #155 from PSMRI/vb/release-3.8.2-merge
snehar-nd Jul 29, 2026
9872814
fix: stop tb village save on create + edit dropdown gaps
vishwab1 Aug 2, 2026
44b976c
fix: scrollable village cell in work location mapping tables
vishwab1 Aug 2, 2026
59e8718
Vb/release 3.8.2 fix (#156)
vishwab1 Aug 3, 2026
e70209e
fix: pre-select Select Block with the saved TU in edit work location …
vishwab1 Aug 7, 2026
91de857
fix: derive Select Block pre-fill from saved blockID, not TU count
vishwab1 Aug 7, 2026
6e4005e
fix: save selectedNikshayBlock's TU as blockID/blockName, not array[0]
vishwab1 Aug 7, 2026
382f1e9
fix: read saved blockID from edit_Details, not the raw-table endpoint
vishwab1 Aug 7, 2026
257d096
Merge pull request #157 from PSMRI/vb/release-block
snehar-nd Aug 10, 2026
e00e03a
fix: unlock button disabled after locking a user account (AMM-2343) (…
snehar-nd Aug 14, 2026
2caf4fc
feat(admin): add Change Username screen under Configuration
Aug 31, 2026
1e1f179
feat(admin): drop Preview Impact from Change Username
Sep 1, 2026
3302d99
feat(admin): make Employee ID optionally updatable on rename
Sep 1, 2026
e61cf07
feat(admin): check new username and employee ID for duplicates as typed
Sep 1, 2026
ae01218
feat(admin): make username and employee ID independently optional
Sep 2, 2026
b60a8f7
feat(admin): send userID with the rename request
Sep 2, 2026
4a1841a
feat(admin): report the employee ID change in the rename result
Sep 2, 2026
26c81bc
feat(admin): drop the per-table row counts from the result
Sep 2, 2026
59e345d
style(admin): remove comments from the Change Username screen
Sep 2, 2026
c1e0e61
style(admin): label the Change Username action Update, in green
Sep 2, 2026
805c212
Merge remote-tracking branch 'origin/main' into feature/edit-employee…
Sep 2, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
.screen-note {
font-size: 12px;
color: rgba(0, 0, 0, 0.6);
margin: 4px 0 0 0;
}

.validation-note {
font-size: 12px;
color: #d32f2f;
margin: 4px 0 0 0;
}

.m-l-10 {
margin-left: 10px;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
<div class="container-fluid">
<div class="row">
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-12">
<h4>Change Username</h4>
<p class="screen-note">
Renaming a user also repoints the Created By and Modified By records
they own. Fill in only what you want to change — leave a field blank to
keep its current value. This cannot be undone.
</p>
</div>

<div class="col-xs-12 col-sm-6 col-md-4 col-lg-3 m-t-10">
<mat-form-field [style.width]="'100%'">
<mat-label>Select User</mat-label>
<mat-select
[(ngModel)]="user"
name="user"
(selectionChange)="onUserChange()"
required
>
<mat-option *ngFor="let item of userNamesList" [value]="item">
{{ item.userName }}
</mat-option>
</mat-select>
</mat-form-field>
</div>

<div class="col-xs-12 col-sm-6 col-md-4 col-lg-3 m-t-10">
<mat-form-field [style.width]="'100%'">
<mat-label>Current Username</mat-label>
<input matInput [value]="user?.userName || ''" disabled />
</mat-form-field>
</div>

<div class="col-xs-12 col-sm-6 col-md-4 col-lg-3 m-t-10">
<mat-form-field [style.width]="'100%'">
<mat-label>New Username</mat-label>
<input
matInput
[(ngModel)]="newUserName"
name="newUserName"
(keyup)="checkUserNameAvailability()"
[maxlength]="effectiveMaxLength"
/>
<mat-hint>Maximum {{ effectiveMaxLength }} characters</mat-hint>
</mat-form-field>
</div>
</div>

<div class="row">
<div class="col-xs-12 col-sm-6 col-md-4 col-lg-3 m-t-10">
<mat-form-field [style.width]="'100%'">
<mat-label>Current Employee ID</mat-label>
<input matInput [value]="currentEmployeeId || 'Not set'" disabled />
</mat-form-field>
</div>

<div class="col-xs-12 col-sm-6 col-md-4 col-lg-3 m-t-10">
<mat-form-field [style.width]="'100%'">
<mat-label>New Employee ID</mat-label>
<input
matInput
[(ngModel)]="newEmployeeId"
name="newEmployeeId"
(keyup)="checkEmployeeIdAvailability()"
[maxlength]="maxEmployeeIdLength"
/>
<mat-hint>Maximum {{ maxEmployeeIdLength }} characters</mat-hint>
</mat-form-field>
</div>
</div>

<div class="row">
<div class="col-xs-12 col-sm-12 col-md-8 col-lg-6 m-t-10">
<mat-checkbox
[(ngModel)]="updateContactFields"
name="updateContactFields"
(ngModelChange)="onSelectionChange()"
>
Also update contact numbers
</mat-checkbox>
<p class="screen-note">
Only tick this where the username is the user's mobile number. It
overwrites Contact No and Emergency Contact No, which limits the new
username to {{ maxContactLength }} characters.
</p>
</div>
</div>

<div class="row" *ngIf="validationMessage && user">
<div class="col-xs-12 col-sm-12">
<p class="validation-note">{{ validationMessage }}</p>
</div>
</div>

<div class="row m-t-10">
<div class="col-xs-12 col-sm-12">
<button
mat-raised-button
class="mat_green"
[disabled]="!canSubmit"
(click)="confirmAndRename()"
>
Update
</button>
</div>
</div>

<div class="row m-t-20" *ngIf="renameResult">
<div class="col-xs-12 col-sm-12">
<h5>Update complete</h5>
<p class="screen-note" *ngIf="renameResult.userNameUpdated">
Username: {{ renameResult.oldUserName }} &rarr;
{{ renameResult.newUserName }}
</p>
<p class="screen-note" *ngIf="renameResult.employeeIdUpdated">
Employee ID: {{ renameResult.oldEmployeeId || "not set" }} &rarr;
{{ renameResult.newEmployeeId }}
</p>
<p class="screen-note" *ngIf="!renameResult.employeeIdUpdated">
Employee ID unchanged ({{ renameResult.oldEmployeeId || "not set" }})
</p>
</div>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,236 @@
/*
* AMRIT – Accessible Medical Records via Integrated Technology
* Integrated EHR (Electronic Health Records) Solution
*
* Copyright (C) "Piramal Swasthya Management and Research Institute"
*
* This file is part of AMRIT.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
import { Component, OnInit } from '@angular/core';
import { ChangeUsernameService } from 'src/app/core/services/ProviderAdminServices/change-username.service';
import { ConfirmationDialogsService } from 'src/app/core/services/dialog/confirmation.service';
import { SessionStorageService } from 'Common-UI/src/registrar/services/session-storage.service';

@Component({
selector: 'app-change-username',
templateUrl: './change-username.component.html',
styleUrls: ['./change-username.component.css'],
})
export class ChangeUsernameComponent implements OnInit {
serviceProviderID: any;
user: any;
newUserName = '';

currentEmployeeId = '';
newEmployeeId = '';

userNamesList: any = [];

updateContactFields = true;

renameResult: any = null;
submitting = false;

userNameTaken = false;
employeeIdTaken = false;

readonly maxUserNameLength = 20;
readonly maxContactLength = 12;
readonly maxEmployeeIdLength = 20;

constructor(
private changeUsernameService: ChangeUsernameService,
private alertService: ConfirmationDialogsService,
readonly sessionstorage: SessionStorageService,
) {}

ngOnInit() {
this.serviceProviderID = this.sessionstorage.getItem('service_providerID');
this.getUserList();
}

getUserList() {
this.changeUsernameService.getUserList(this.serviceProviderID).subscribe(
(response: any) => {
this.userNamesList = response.data;
},
(err: any) => this.alertService.alert(err.errorMessage, 'error'),
);
}

onSelectionChange() {
this.renameResult = null;
}

onUserChange() {
this.onSelectionChange();
this.currentEmployeeId = '';
this.newUserName = '';
this.newEmployeeId = '';
this.userNameTaken = false;
this.employeeIdTaken = false;
if (!this.user) {
return;
}
this.changeUsernameService.getUserDetail(this.user.userName).subscribe(
(response: any) => {
this.currentEmployeeId = response.data?.employeeID || '';
},
(err: any) => this.alertService.alert(err.errorMessage, 'error'),
);
}

checkUserNameAvailability() {
this.onSelectionChange();
this.userNameTaken = false;
const newUserName = (this.newUserName || '').trim();
if (!this.user || !newUserName || newUserName === this.user.userName) {
return;
}
this.changeUsernameService.checkUserAvailability(newUserName).subscribe(
(response: any) => {
this.userNameTaken = response.data?.response === 'userexist';
},
(err: any) => console.log('error', err),
);
}

checkEmployeeIdAvailability() {
this.onSelectionChange();
this.employeeIdTaken = false;
const newEmployeeId = (this.newEmployeeId || '').trim();
if (!newEmployeeId || newEmployeeId === this.currentEmployeeId) {
return;
}
this.changeUsernameService.checkEmpIdAvailability(newEmployeeId).subscribe(
(response: any) => {
this.employeeIdTaken = response.data?.response === 'true';
},
(err: any) => console.log('error', err),
);
}

get effectiveMaxLength(): number {
return this.updateContactFields
? this.maxContactLength
: this.maxUserNameLength;
}

get validationMessage(): string | null {
if (!this.user) {
return 'Select a user';
}
const newUserName = (this.newUserName || '').trim();
const newEmployeeId = (this.newEmployeeId || '').trim();

const userNameChanged = !!newUserName && newUserName !== this.user.userName;
const employeeIdChanged =
!!newEmployeeId && newEmployeeId !== this.currentEmployeeId;

if (!userNameChanged && !employeeIdChanged) {
return 'Enter a new username or a new employee ID';
}
if (userNameChanged) {
if (newUserName.length > this.effectiveMaxLength) {
return this.updateContactFields
? `Maximum ${this.maxContactLength} characters while contact numbers are being updated`
: `Maximum ${this.maxUserNameLength} characters`;
}
if (this.userNameTaken) {
return `Username ${newUserName} is already in use`;
}
}
if (employeeIdChanged) {
if (newEmployeeId.length > this.maxEmployeeIdLength) {
return `Employee ID: maximum ${this.maxEmployeeIdLength} characters`;
}
if (this.employeeIdTaken) {
return `Employee ID ${newEmployeeId} is already in use`;
}
}
return null;
}

get canSubmit(): boolean {
return this.validationMessage === null && !this.submitting;
}

private buildRequest() {
const newUserName = (this.newUserName || '').trim();
const newEmployeeId = (this.newEmployeeId || '').trim();
return {
userID: this.user.userID,
oldUserName: this.user.userName,
newUserName: newUserName || null,
newEmployeeId: newEmployeeId || null,
updateContactFields: this.updateContactFields,
};
}

confirmAndRename() {
if (!this.canSubmit) {
return;
}
const request = this.buildRequest();
this.alertService
.confirm('Confirm', this.confirmMessage(request))
.subscribe((accept: any) => {
if (accept) {
this.rename(request);
}
});
}

private confirmMessage(request: any): string {
const changes: string[] = [];
if (request.newUserName) {
changes.push(
`username from ${request.oldUserName} to ${request.newUserName}`,
);
}
if (request.newEmployeeId) {
changes.push(
`employee ID from ${this.currentEmployeeId || 'not set'} to ${request.newEmployeeId}`,
);
}
const audit = request.newUserName
? ' This also repoints the Created By and Modified By records they own.'
: '';
return `Change ${changes.join(' and ')}?${audit} This cannot be undone.`;
}

private rename(request: any) {
this.submitting = true;
this.changeUsernameService.renameUsername(request).subscribe(
(response: any) => {
this.submitting = false;
this.renameResult = response.data;
this.alertService.alert('Username updated successfully', 'success');
this.newUserName = '';
this.newEmployeeId = '';
this.currentEmployeeId = '';
this.userNameTaken = false;
this.employeeIdTaken = false;
this.user = null;
this.getUserList();
},
(err: any) => {
this.submitting = false;
this.alertService.alert(err.errorMessage, 'error');
},
);
}
}
Loading
Loading