Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
483d6b1
add types
YankinA Oct 15, 2025
b9d08a5
AccessDialog
YankinA Oct 28, 2025
a493146
add MultiSelectInputInput
YankinA Oct 30, 2025
48a0959
add access dialog func and component
YankinA Nov 5, 2025
a25d23b
add new access roles translations
YankinA Nov 6, 2025
3d903e5
adding renderSubject prop for custom subject rendering
YankinA Nov 7, 2025
ea355a9
add invite types
YankinA Nov 9, 2025
04f2872
refactor organization manager actions and update invitation types
YankinA Nov 10, 2025
efa2dab
add displayName property to SubjectClaims interface and export invita…
YankinA Nov 11, 2025
6c025f5
implement invitation management features including resend and delete …
YankinA Nov 11, 2025
9e5bc17
add EnableNewAccessDialog feature and integrate into useActions
YankinA Nov 12, 2025
48ddffb
Merge branch 'main' into CHARTS-11939-access-dialog
YankinA Nov 12, 2025
e03605e
Update locale and add updateAccessBindings action to organization man…
YankinA Nov 13, 2025
6b8d805
add description invitation sending in IAM access dialog
YankinA Nov 13, 2025
4153569
Add optional iconSlot property to AclSubjectProps type
YankinA Nov 13, 2025
07bcd61
Remove MultiSelectInput component
YankinA Nov 14, 2025
420887a
Refactor access dialog handling to support new access dialog feature …
YankinA Nov 17, 2025
6b9def7
Add new localization keys for author and public access features
YankinA Nov 20, 2025
faeacb8
Remove unused OpenAccessDialog type
YankinA Nov 25, 2025
4a5d280
move AclSubjectSelect to extensions
YankinA Nov 25, 2025
848e274
Remove AclSubjectSelect from regestry
YankinA Nov 26, 2025
382d424
Merge branch 'main' into CHARTS-11939-access-dialog
YankinA Nov 26, 2025
4fa0051
Fix merge
YankinA Nov 26, 2025
cc49287
Remove keys from i18n
YankinA Nov 27, 2025
526439a
rename 'canUpdate' to 'canUpdateAccessBindings'
YankinA Nov 28, 2025
b427809
fix displayName type
YankinA Nov 30, 2025
e0b06bf
fix after review
YankinA Dec 3, 2025
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
3 changes: 3 additions & 0 deletions src/i18n-keysets/component.iam-access-dialog/en.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"action_add": "Add",
"action_add-user": "Add user",
"action_cancel": "Cancel",
"action_choose-user": "Select user",
Expand All @@ -7,6 +8,7 @@
"action_revoke-access": "Revoke role",
"action_save": "Save",
"button_bindings-list-retry": "Reload list",
"label_access": "Access rights",
"label_access_error": "Insufficient rights",
"label_all": "All",
"label_groups": "Groups",
Expand All @@ -21,6 +23,7 @@
"role_admin": "Admin",
"role_editor": "Editor",
"role_limited-viewer": "Limited viewer",
"role_limited-viewer-hint": "Unlike 'Viewer', it doesn't grant access to view datasets and connections",
"role_viewer": "Viewer",
"section_direct_accesses": "Direct permissions",
"section_inherited_accesses": "Inherited permissions",
Expand Down
3 changes: 3 additions & 0 deletions src/i18n-keysets/component.iam-access-dialog/ru.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"action_add": "Добавить",
"action_add-user": "Добавить пользователя",
"action_cancel": "Отменить",
"action_choose-user": "Выбрать пользователя",
Expand All @@ -7,6 +8,7 @@
"action_revoke-access": "Отозвать роль",
"action_save": "Сохранить",
"button_bindings-list-retry": "Обновить список",
"label_access": "Права доступа",
"label_access_error": "Недостаточно прав",
"label_all": "Все",
"label_groups": "Группы",
Expand All @@ -21,6 +23,7 @@
"role_admin": "Администрирование",
"role_editor": "Редактирование",
"role_limited-viewer": "Ограниченный просмотр",
"role_limited-viewer-hint": "В отличие от просмотра, не даёт доступ просмотру датасетов и подключений",
"role_viewer": "Просмотр",
"section_direct_accesses": "Прямые права",
"section_inherited_accesses": "Наследуемые права",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import {Feature} from '../../../../shared';
import {createFeatureConfig} from '../utils';

export default createFeatureConfig({
name: Feature.EnableNewAccessDialog,
state: {
development: false,
production: false,
},
});
11 changes: 11 additions & 0 deletions src/shared/schema/extensions/actions/iam-access-dialog.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import {createAction} from '../../gateway-utils';
import type {GetDatalensOperationResponse} from '../../us/types/operations';
import type {
BatchListAccessBindingsArgs,
BatchListAccessBindingsResponse,
BatchListMembersArgs,
BatchListMembersResponse,
GetClaimsArgs,
Expand Down Expand Up @@ -40,4 +42,13 @@ export const iamAccessDialogActions = {
batchListMembers: createAction<BatchListMembersResponse, BatchListMembersArgs>(async () => {
return {members: [], nextPageToken: ''};
}),
batchListAccessBindings: createAction<
BatchListAccessBindingsResponse,
BatchListAccessBindingsArgs
>(async () => {
return {
subjectsWithBindings: [],
nextPageToken: '',
};
}),
};
41 changes: 41 additions & 0 deletions src/shared/schema/extensions/types/iam-access-dialog.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type {Lang} from '../../..';

export enum AccessServiceResourceType {
Organization = 'organization-manager.organization',
Collection = 'datalens.collection',
Workbook = 'datalens.workbook',
}
Expand All @@ -20,6 +21,7 @@ export enum SubjectType {
}

export enum ClaimsSubjectType {
Unspecified = 'SUBJECT_TYPE_UNSPECIFIED',
UserAccount = 'USER_ACCOUNT',
Group = 'GROUP',
Invitee = 'INVITEE',
Expand Down Expand Up @@ -108,6 +110,7 @@ export interface SubjectClaims {
pictureData?: string;
picture?: string;
idpType?: string | null;
displayName?: string;
}

export type SubjectDetails = {
Expand All @@ -132,3 +135,41 @@ export type BatchListMembersResponse = {
members: SubjectClaims[];
nextPageToken: string;
};

export interface BatchListAccessBindingsResponse {
subjectsWithBindings: SubjectWithBindings[];
nextPageToken: string;
}

export interface SubjectWithBindings {
subjectClaims: SubjectClaims;
accessBindings: InheritedAccessBindings[];
inheritedAccessBindings: InheritedAccessBindings[];
}

export interface InheritedAccessBindings {
roleId: string;
inheritedFrom: AccessBindingsResource | null;
}

export interface AccessBindingsResource {
id: string;
type: string;
}

export type BatchListAccessBindingsArgs = {
resourcePath: AccessBindingsResource[];
getInheritedBindings?: boolean;
filter?: string;
pageSize?: number;
pageToken?: string;
};

export enum ResourceType {
Collection = 'collection',
Workbook = 'workbook',
}

export type UpdateAccessBindingsRequest = {
accessBindingDeltas: AccessBindingDelta[];
};
1 change: 1 addition & 0 deletions src/shared/schema/extensions/types/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './iam-access-dialog';
export * from './invitations';
72 changes: 72 additions & 0 deletions src/shared/schema/extensions/types/invitations.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import {ResourceType} from './iam-access-dialog';

Check failure on line 1 in src/shared/schema/extensions/types/invitations.ts

View workflow job for this annotation

GitHub Actions / Lint, Typecheck, Unit tests

All imports in the declaration are only used as types. Use `import type`

export type Invite = {
invitee: {
email: string;
};
};

export type InviteUsersRequest = {
invitations: Invite[];
};

export type InviteUsersWithAccessRequest = InviteUsersRequest & {
resourceType: ResourceType;
resourceId: string;
roleId: string;
};

export type InviteUsersResponse = {
validInvitations: InviteRespone[];
invalidInvitations: InviteRespone[];
};

export type InviteRespone = Invite & {
invitationId: string;
status: InviteStatus;
createdAt: string;
inviteeId: string;
subjectId: string;
};

export type DeleteInvitationRequest = {
invitationId: string;
};

export enum InviteStatus {
Creating = 'CREATING',
Pending = 'PENDING',
Accepted = 'ACCEPTED',
Rejected = 'REJECTED',
}

export type ListOrganizationInvitationsRequest = {
status: InviteStatus;
filter?: string | undefined;
pageSize?: number | undefined;
pageToken?: string;
};

export type ListOrganizationInvitationsResponse = {
invitations: Invitation[];
nextPageToken: string;
};

export type Invitation = Invite & {
id: string;
status: InviteStatus;
inviteeId: string;
subjectId: string;
};

export interface ResendInvitationRequest {
invitationId: string;
notAfter?: InvitationTimestamp;
}
export interface ResendInvitationResponse {
invitationId: string;
organizationId: string;
email: string;
}

export type InvitationTimestamp = {seconds: string; nanos?: number};
3 changes: 3 additions & 0 deletions src/shared/types/feature.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,12 +98,15 @@ export enum Feature {
EnableSharedEntries = 'EnableSharedEntries',

EnableMobileFixedHeader = 'EnableMobileFixedHeader',

/** enabled redesign/moving to drawers existing settings */
EnableCommonChartDashSettings = 'EnableCommonChartDashSettings',
/** enables new dash & widgets settings */
EnableNewDashSettings = 'EnableNewDashSettings',
/** Shows updated settings page */
EnableNewServiceSettings = 'EnableNewServiceSettings',
/** Enable new access dialog (AccessDialog) */
EnableNewAccessDialog = 'EnableNewAccessDialog',
}

export type FeatureConfig = Record<string, boolean>;
8 changes: 8 additions & 0 deletions src/ui/components/AccessDialog/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import type {AccessDialogProps} from 'ui/registry/units/common/types/components/AccessDialog';

export const DIALOG_ACCESS = Symbol('DIALOG_ACCESS');

export type OpenDialogAccessDialogArgs = {
id: typeof DIALOG_ACCESS;
props: AccessDialogProps;
};
Original file line number Diff line number Diff line change
Expand Up @@ -12,36 +12,54 @@ import './AuthorSection.scss';
const b = block('dl-dialog-public-author-section');
const i18n = I18n.keyset('component.dialog-switch-public.view');

type Props = {
export type AuthorSectionProps = {
validationErrors: ValidationErrors;
className?: string;
scope: 'widget' | 'dash';
authorData: EntryAuthorData;
progress: boolean;
disabled: boolean;
onChange: ({link, text}: {link?: string; text?: string}) => void;
showWarning?: boolean;
linkLabel?: string;
textLabel?: string;
};

function AuthorSection(props: Props) {
const {className, authorData, disabled, onChange, scope, validationErrors} = props;
function AuthorSection(props: AuthorSectionProps) {
const {
className,
authorData,
disabled,
onChange,
scope,
validationErrors,
showWarning = true,
linkLabel = i18n('label_author-link'),
textLabel = i18n('label_author-text'),
} = props;

return (
<div className={b(null, className)}>
<div className={b('title')}>{i18n('section_author')}</div>
<div className={b('description')}>
{i18n('label_author-description', {subject: i18n(`label_author-subject-${scope}`)})}
</div>

{showWarning && (
<React.Fragment>
<div className={b('title')}>{i18n('section_author')}</div>
<div className={b('description')}>
{i18n('label_author-description', {
subject: i18n(`label_author-subject-${scope}`),
})}
</div>
</React.Fragment>
)}
<div className={b('form')}>
<FormRow label={i18n('label_author-text')} className={b('form-row')}>
<FormRow label={textLabel} className={b('form-row')}>
<TextInput
error={validationErrors.text ?? false}
value={authorData.text}
disabled={disabled}
onUpdate={(value) => onChange({text: value})}
></TextInput>
</FormRow>
<FormRow label={i18n('label_author-link')} className={b('form-row')}>
<FormRow label={linkLabel} className={b('form-row')}>
<TextInput
error={validationErrors.link ?? false}
value={authorData.link}
Expand Down
4 changes: 2 additions & 2 deletions src/ui/components/IamAccessDialog/AccessList/AccessList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ export const AccessList = React.memo<Props>(
return isLoadingInherited && inheritedAccesses?.length === 0 ? (
<SmartLoader size="m" showAfter={0} />
) : (
<>
<React.Fragment>
<InheritedAccessesTable data={inheritedAccesses} />

{footerInheritedAccessesTable}
Expand All @@ -187,7 +187,7 @@ export const AccessList = React.memo<Props>(
}}
/>
)}
</>
</React.Fragment>
);
};

Expand Down
2 changes: 2 additions & 0 deletions src/ui/registry/units/common/components-map.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {makeDefaultEmpty} from '../../components/DefaultEmpty';

import {Example} from './components/Example/Example';
import {EXAMPLE_COMPONENT} from './constants/components';
import type {AccessDialogProps} from './types/components/AccessDialog';
import type {AccessRightsProps} from './types/components/AccessRights';
import type {AccessRightsUrlOpenProps} from './types/components/AccessRightsUrlOpen';
import type {AclSubjectProps} from './types/components/AclSubject';
Expand Down Expand Up @@ -66,4 +67,5 @@ export const commonComponentsMap = {
WorkbookEntriesTableTabs: makeDefaultEmpty<WorkbookEntriesTableTabsProps>(),
WorkbookEntryExtended: makeDefaultEmpty<WorkbookEntriesTableTabsProps>(),
DialogEntryDescription: makeDefaultEmpty<DialogEntryDescriptionProps>(),
AccessDialog: makeDefaultEmpty<AccessDialogProps>(),
} as const;
9 changes: 9 additions & 0 deletions src/ui/registry/units/common/types/components/AccessDialog.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export type AccessDialogProps = {
entryId?: string;
workbookId?: string;
collectionId?: string;
resourceTitle?: string;
canUpdateAccessBindings: boolean;
onClose?: () => void;
defaultTab?: string;
};
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
export type UseSubjectsListId = {type: 'organizationId' | 'cloudId'; id: string | undefined};
export type UseSubjectsListId = {
type: 'organizationId' | 'cloudId';
id: string | undefined;
title: string | undefined;
};
3 changes: 3 additions & 0 deletions src/ui/store/actions/openDialogTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ import type {OpenDialogExportWorkbookArgs} from 'ui/components/CollectionsStruct
import type {OpenDialogDefaultArgs} from 'ui/components/DialogDefault/DialogDefault';
import type {OpenDialogCreatePublicGalleryWorkbookArgs} from 'ui/components/CollectionsStructure/CreatePublicGalleryWorkbookDialog';
import type {OpenDialogEntryDescriptionArgs} from 'ui/components/DialogEntryDescription/DialogEntryDescriptionWrapper';
import type {OpenDialogAccessDialogArgs} from 'ui/components/AccessDialog';
import type {OpenDialogSharedEntryBindingArgs} from 'ui/components/DialogSharedEntryBindings/DialogSharedEntryBindings';
import type {OpenDialogSharedEntryUnbindArgs} from 'ui/components/DialogSharedEntryUnbind/DialogSharedEntryUnbind';
import type {OpenDialogSharedEntryPermissionsArgs} from 'ui/components/DialogSharedEntryPermissions/DialogSharedEntryPermissions';
Expand Down Expand Up @@ -125,6 +126,8 @@ export type OpenDialogArgs<T = unknown> =
| OpenDialogExportWorkbookArgs
| OpenDialogDefaultArgs
| OpenDialogCreatePublicGalleryWorkbookArgs
| OpenDialogEntryDescriptionArgs
| OpenDialogAccessDialogArgs
| OpenDialogSharedEntryBindingArgs
| OpenDialogSharedEntryUnbindArgs
| OpenDialogSharedEntryPermissionsArgs
Expand Down
Loading
Loading