diff --git a/package-lock.json b/package-lock.json
index e07dba4df..7b4fb8fd3 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -23,7 +23,7 @@
"@ngneat/input-mask": "^6.1.0",
"@sentry/angular": "^10.68.0",
"@tailwindcss/postcss": "^4.3.1",
- "@vality/domain-proto": "^2.0.2-6e28041.0",
+ "@vality/domain-proto": "^2.0.2-8d6174b.0",
"@vality/fistful-proto": "^2.0.1-360c737.0",
"@vality/machinegun-proto": "^1.0.1-273f2f3.0",
"@vality/magista-proto": "^2.0.2-bd58cea.0",
@@ -5750,9 +5750,9 @@
]
},
"node_modules/@vality/domain-proto": {
- "version": "2.0.2-6e28041.0",
- "resolved": "https://registry.npmjs.org/@vality/domain-proto/-/domain-proto-2.0.2-6e28041.0.tgz",
- "integrity": "sha512-rYC60Set3hpQcktjAL+rKRfRz1u0FHCUTSokHbJuIN6QsbS5p7Jo2GqyPOw5yKy7Rpaiv9JtKmGUi0TRlql5DQ==",
+ "version": "2.0.2-8d6174b.0",
+ "resolved": "https://registry.npmjs.org/@vality/domain-proto/-/domain-proto-2.0.2-8d6174b.0.tgz",
+ "integrity": "sha512-F2TdNS2VHVhTot+xA8UV2vJMESgopQnxRNYNIxleytyCg6ebzzb+/ihrHqxQc/1/eBtgG2qagTzr9376+FT2eA==",
"license": "Apache-2.0"
},
"node_modules/@vality/fistful-proto": {
diff --git a/package.json b/package.json
index c64f4fbea..674675521 100644
--- a/package.json
+++ b/package.json
@@ -38,7 +38,7 @@
"@ngneat/input-mask": "^6.1.0",
"@sentry/angular": "^10.68.0",
"@tailwindcss/postcss": "^4.3.1",
- "@vality/domain-proto": "^2.0.2-6e28041.0",
+ "@vality/domain-proto": "^2.0.2-8d6174b.0",
"@vality/fistful-proto": "^2.0.1-360c737.0",
"@vality/machinegun-proto": "^1.0.1-273f2f3.0",
"@vality/magista-proto": "^2.0.2-bd58cea.0",
diff --git a/projects/matez/src/lib/components/value/value.component.html b/projects/matez/src/lib/components/value/value.component.html
index d49f5f1b5..9dc177eef 100644
--- a/projects/matez/src/lib/components/value/value.component.html
+++ b/projects/matez/src/lib/components/value/value.component.html
@@ -1,110 +1,114 @@
-@if (!value() && lazyValue() && !lazyVisible()) {
-
-} @else {
- @if (value$ | async; as v) {
-
- @if (v.prefix) {
-
- }
-
+ @if (lazyValue() && !lazyVisible()) {
+
+ }
+ @if (v.error) {
+
error
+ }
+ @if (v.prefix) {
+
+ }
+
+ @if (v.template) {
+
+ } @else {
+ @if (v.color) {
+
+
+
} @else {
- @if (v.color) {
-
-
-
+
+ }
+
+
+ @if (v.tooltip) {
+
+
+
} @else {
-
+
+
+
}
+
-
- @if (v.tooltip) {
-
-
-
- } @else {
-
-
-
+
+ @switch (v.type) {
+ @case ('menu') {
+
}
-
-
-
- @switch (v.type) {
- @case ('menu') {
-
- }
- @case ('toggle') {
-
- }
- @default {
- @let valueText = valueText$ | async;
- @if (inProgress$ | async) {
-
- } @else if (valueText) {
-
- } @else if (v.error) {
- error
- } @else if (emptySymbol) {
- {{
- emptySymbol
- }}
- }
+ @case ('toggle') {
+
+ }
+ @default {
+ @let valueText = valueText$ | async;
+ @if (inProgress$ | async) {
+
+ } @else if (valueText) {
+
+ } @else if (emptySymbol) {
+ {{ emptySymbol }}
}
}
-
- }
+ }
+
+ }
- @if (v.description) {
-
- }
-
- @if (v.postfix) {
-
+ @if (v.description) {
+
}
- } @else {
-
- }
+ @if (v.postfix) {
+
+ }
+
+} @else if (lazyValue() && !lazyVisible()) {
+
+} @else {
+
}
diff --git a/projects/matez/src/lib/components/value/value.component.ts b/projects/matez/src/lib/components/value/value.component.ts
index da162ec48..ce3b000a6 100644
--- a/projects/matez/src/lib/components/value/value.component.ts
+++ b/projects/matez/src/lib/components/value/value.component.ts
@@ -65,8 +65,17 @@ export class ValueComponent {
@Input() highlight?: string | null;
- value$ = combineLatest([toObservable(this.value), toObservable(this.lazyValue)]).pipe(
- switchMap(([value, lazyValue]) => (isObservable(lazyValue) ? lazyValue : of(value))),
+ value$ = combineLatest([
+ toObservable(this.value),
+ toObservable(this.lazyValue),
+ toObservable(this.lazyVisible),
+ ]).pipe(
+ switchMap(([value, lazyValue, lazyVisible]) => {
+ if (lazyVisible && isObservable(lazyValue)) {
+ return lazyValue;
+ }
+ return of(value);
+ }),
shareReplay({ refCount: true, bufferSize: 1 }),
);
valueText$ = this.value$.pipe(
diff --git a/src/api/org-management/utils/member-roles.ts b/src/api/org-management/utils/member-roles.ts
index 282d5b57c..d2262c841 100644
--- a/src/api/org-management/utils/member-roles.ts
+++ b/src/api/org-management/utils/member-roles.ts
@@ -3,6 +3,7 @@ import uniq from 'lodash-es/uniq';
import { domain } from '@vality/org-management-proto/admin_management';
import { ROLE_PRIORITY, sortRoleIds } from '../constants';
+import { SCOPES, ScopeId } from '../types';
export { ROLE_PRIORITY, sortRoleIds };
@@ -11,6 +12,10 @@ export interface RoleLike {
scope?: domain.RoleScope;
}
+export function getRoleScopes(roleId?: string): readonly ScopeId[] {
+ return roleId === 'WalletManager' ? ['Wallet'] : SCOPES;
+}
+
export function isWalletRole(role: RoleLike): boolean {
return role.scope?.scope_id === 'Wallet' || role.role_id === 'WalletManager';
}
diff --git a/src/app/organizations/components/create-organization-dialog/create-organization-dialog.component.html b/src/app/organizations/components/create-organization-dialog/create-organization-dialog.component.html
index cae1621c6..345446f19 100644
--- a/src/app/organizations/components/create-organization-dialog/create-organization-dialog.component.html
+++ b/src/app/organizations/components/create-organization-dialog/create-organization-dialog.component.html
@@ -4,7 +4,7 @@
@if (!partyId) {
}
-
+
diff --git a/src/app/organizations/components/create-organization-dialog/create-organization-dialog.component.ts b/src/app/organizations/components/create-organization-dialog/create-organization-dialog.component.ts
index ad110bd5b..dbb032acb 100644
--- a/src/app/organizations/components/create-organization-dialog/create-organization-dialog.component.ts
+++ b/src/app/organizations/components/create-organization-dialog/create-organization-dialog.component.ts
@@ -15,6 +15,7 @@ import { domain } from '@vality/org-management-proto/admin_management';
import { ThriftOrganizationManagementService } from '~/api/services';
import { MerchantFieldModule } from '~/components/merchant-field';
+import { UserFieldComponent } from '~/components/user-field';
export interface CreateOrganizationDialogData {
partyId?: domain.PartyID;
@@ -36,6 +37,7 @@ interface CreateOrganizationModel {
MerchantFieldModule,
InputFieldModule,
FormField,
+ UserFieldComponent,
],
changeDetection: ChangeDetectionStrategy.OnPush,
templateUrl: './create-organization-dialog.component.html',
diff --git a/src/app/organizations/components/organizations-list/organizations-list.component.html b/src/app/organizations/components/organizations-list/organizations-list.component.html
index e2f682dfd..51d70adfa 100644
--- a/src/app/organizations/components/organizations-list/organizations-list.component.html
+++ b/src/app/organizations/components/organizations-list/organizations-list.component.html
@@ -5,11 +5,7 @@
-
+
({ value: org.owner_id }),
+ cell: (org) => ({ value: '', description: org.owner_id }),
+ lazyCell: (org) =>
+ this.organizationsService.GetUser(org.owner_id).pipe(
+ map((res) => ({
+ value: res.email,
+ description: org.owner_id,
+ })),
+ catchError((err) => {
+ this.log.error(err);
+ return of({ value: '', description: org.owner_id, error: err });
+ }),
+ ),
},
{
field: 'status',
diff --git a/src/app/parties/party/members/components/manage-roles-dialog/manage-roles-dialog.component.spec.ts b/src/app/parties/party/members/components/manage-roles-dialog/manage-roles-dialog.component.spec.ts
index 85cd01944..76f35223e 100644
--- a/src/app/parties/party/members/components/manage-roles-dialog/manage-roles-dialog.component.spec.ts
+++ b/src/app/parties/party/members/components/manage-roles-dialog/manage-roles-dialog.component.spec.ts
@@ -259,6 +259,42 @@ describe('ManageRolesDialogComponent', () => {
expect(service.RemoveMemberRole).not.toHaveBeenCalled();
});
+ it('restricts WalletManager scope to only Wallet and displays wallets in catalog', async () => {
+ await openRole('WalletManager');
+ panel()
+ .querySelector(
+ '[data-assignment-form] v-select-field:nth-of-type(1) .ng-select-control',
+ )
+ .click();
+ await fixture.whenStable();
+ const scopeOptions = Array.from(
+ document.querySelectorAll('.ng-select-option'),
+ ).map((item) => item.textContent.trim());
+ expect(scopeOptions).toEqual(['Wallet']);
+ document.body.click();
+ await fixture.whenStable();
+
+ panel()
+ .querySelector(
+ '[data-assignment-form] v-select-field:nth-of-type(2) .ng-select-control',
+ )
+ .click();
+ await fixture.whenStable();
+ const resourceOptions = Array.from(
+ document.querySelectorAll('.ng-select-option'),
+ ).map((item) => item.textContent.trim());
+ expect(resourceOptions).toEqual(['Wallet 1']);
+ document.body.click();
+ await fixture.whenStable();
+
+ await selectOption('resource', 'Wallet 1');
+ await assign();
+ expect(service.AssignMemberRole).toHaveBeenCalledExactlyOnceWith('org-1', 'user-1', {
+ role_id: 'WalletManager',
+ scope: { scope_id: 'Wallet', resource_id: 'wallet-1' },
+ });
+ });
+
it('omits scope for organization-wide access and uses the returned ID for removal', async () => {
await openRole('Administrator');
await assign();
diff --git a/src/app/parties/party/members/utils/member-roles.spec.ts b/src/app/parties/party/members/utils/member-roles.spec.ts
index 779634c8a..ba5238838 100644
--- a/src/app/parties/party/members/utils/member-roles.spec.ts
+++ b/src/app/parties/party/members/utils/member-roles.spec.ts
@@ -3,6 +3,7 @@ import { domain } from '@vality/org-management-proto/admin_management';
import {
getGeneralRoleIds,
getRoleIds,
+ getRoleScopes,
getWalletRoleIds,
isWalletRole,
sortRoleIds,
@@ -130,4 +131,16 @@ describe('member-roles utils', () => {
]);
});
});
+
+ describe('getRoleScopes', () => {
+ it('should return only Wallet scope for WalletManager', () => {
+ expect(getRoleScopes('WalletManager')).toEqual(['Wallet']);
+ });
+
+ it('should return all scopes for other roles or undefined', () => {
+ expect(getRoleScopes('Manager')).toEqual(['Shop', 'Wallet']);
+ expect(getRoleScopes('Administrator')).toEqual(['Shop', 'Wallet']);
+ expect(getRoleScopes()).toEqual(['Shop', 'Wallet']);
+ });
+ });
});
diff --git a/src/components/member-roles-manager/member-role-panel/member-role-panel.component.html b/src/components/member-roles-manager/member-role-panel/member-role-panel.component.html
index 3d47a5162..27919abef 100644
--- a/src/components/member-roles-manager/member-role-panel/member-role-panel.component.html
+++ b/src/components/member-roles-manager/member-role-panel/member-role-panel.component.html
@@ -50,7 +50,7 @@ Assign role
diff --git a/src/components/member-roles-manager/member-role-panel/member-role-panel.component.ts b/src/components/member-roles-manager/member-role-panel/member-role-panel.component.ts
index 8b06dc2b8..73150b30d 100644
--- a/src/components/member-roles-manager/member-role-panel/member-role-panel.component.ts
+++ b/src/components/member-roles-manager/member-role-panel/member-role-panel.component.ts
@@ -4,8 +4,8 @@ import {
computed,
effect,
input,
+ linkedSignal,
output,
- signal,
} from '@angular/core';
import { FormField, disabled, form } from '@angular/forms/signals';
import { MatButtonModule } from '@angular/material/button';
@@ -15,7 +15,7 @@ import { MatIconModule } from '@angular/material/icon';
import { Option, SelectFieldModule } from '@vality/matez';
import { domain } from '@vality/org-management-proto/admin_management';
-import { SCOPES, ScopeId } from '~/api/org-management';
+import { SCOPES, ScopeId, getRoleScopes } from '~/api/org-management';
@Component({
selector: 'cc-member-role-panel',
@@ -51,9 +51,15 @@ export class MemberRolePanelComponent {
});
}
- newRole = signal({ scopeId: SCOPES[0] as ScopeId, resourceId: '' });
+ scopes = computed(() => getRoleScopes(this.roleId()));
+ scopeOptions = computed(() =>
+ this.scopes().map((scopeId) => ({ label: scopeId, value: scopeId })),
+ );
+ newRole = linkedSignal(() => ({
+ scopeId: this.scopes()[0] as ScopeId,
+ resourceId: '',
+ }));
control = form(this.newRole, (path) => disabled(path, () => this.disabled()));
- scopeOptions = SCOPES.map((scopeId) => ({ label: scopeId, value: scopeId }));
request = computed(() => {
const { scopeId, resourceId } = this.newRole();
return {