mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 10:58:30 -05:00
Fix accessibility issues with Manage Access dialog (#8586)
* Fix accessibility issues with Manage Access dialog * implement more property interfaces * Fix lgtm errors * Simplify condition
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
|
||||
import { IconPathHelper, IconPath } from '../iconHelper';
|
||||
import { groupBy } from '../util/arrays';
|
||||
import * as loc from '../localizedConstants';
|
||||
|
||||
/**
|
||||
* The permission status of an HDFS path - this consists of :
|
||||
@@ -353,17 +354,17 @@ export function parseAclPermissionFromOctal(octal: string): { sticky: boolean, o
|
||||
};
|
||||
}
|
||||
|
||||
export function getImageForType(type: AclType | PermissionType): IconPath {
|
||||
export function getImageForType(type: AclType | PermissionType): { iconPath: IconPath, title: string } {
|
||||
switch (type) {
|
||||
case AclType.user:
|
||||
case PermissionType.owner:
|
||||
return IconPathHelper.user;
|
||||
return { iconPath: IconPathHelper.user, title: loc.owner };
|
||||
case AclType.group:
|
||||
case PermissionType.group:
|
||||
case PermissionType.other:
|
||||
return IconPathHelper.group;
|
||||
return { iconPath: IconPathHelper.group, title: loc.group };
|
||||
}
|
||||
return { dark: '', light: '' };
|
||||
return { iconPath: { dark: '', light: '' }, title: '' };
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import * as azdata from 'azdata';
|
||||
import { HdfsModel } from '../hdfsModel';
|
||||
import { IFileSource } from '../../objectExplorerNodeProvider/fileSources';
|
||||
import { PermissionStatus, AclEntry, AclType, getImageForType, AclEntryScope, AclEntryPermission } from '../../hdfs/aclEntry';
|
||||
import { PermissionStatus, AclEntry, AclType, getImageForType, AclEntryScope, AclEntryPermission, PermissionType } from '../../hdfs/aclEntry';
|
||||
import { cssStyles } from './uiConstants';
|
||||
import * as loc from '../../localizedConstants';
|
||||
import { HdfsError } from '../webhdfs';
|
||||
@@ -15,13 +15,10 @@ import { IconPathHelper } from '../../iconHelper';
|
||||
import { HdfsFileType } from '../fileStatus';
|
||||
|
||||
const permissionsTypeIconColumnWidth = 35;
|
||||
const permissionsNameColumnWidth = 250;
|
||||
const permissionsInheritColumnWidth = 50;
|
||||
const permissionsReadColumnWidth = 50;
|
||||
const permissionsWriteColumnWidth = 50;
|
||||
const permissionsExecuteColumnWidth = 50;
|
||||
const permissionsDeleteColumnWidth = 50;
|
||||
|
||||
const permissionsCheckboxColumnWidth = 50;
|
||||
|
||||
const permissionsRowHeight = 35;
|
||||
const locationLabelHeight = 23; // Fits the text size without too much white space
|
||||
|
||||
@@ -38,8 +35,9 @@ export class ManageAccessDialog {
|
||||
|
||||
private hdfsModel: HdfsModel;
|
||||
private viewInitialized: boolean = false;
|
||||
|
||||
private modelInitialized: boolean = false;
|
||||
private modelBuilder: azdata.ModelBuilder;
|
||||
private rootContainer: azdata.FlexContainer;
|
||||
private rootLoadingComponent: azdata.LoadingComponent;
|
||||
private stickyCheckbox: azdata.CheckBoxComponent;
|
||||
private inheritDefaultsCheckbox: azdata.CheckBoxComponent;
|
||||
@@ -48,7 +46,6 @@ export class ManageAccessDialog {
|
||||
private addUserOrGroupInput: azdata.InputBoxComponent;
|
||||
private dialog: azdata.window.Dialog;
|
||||
private applyRecursivelyButton: azdata.window.Button;
|
||||
private defaultSectionComponents: azdata.Component[] = [];
|
||||
private posixPermissionCheckboxesMapping: PermissionCheckboxesMapping[] = [];
|
||||
private namedSectionInheritCheckboxes: azdata.CheckBoxComponent[] = [];
|
||||
private addUserOrGroupSelectedType: AclType;
|
||||
@@ -86,133 +83,15 @@ export class ManageAccessDialog {
|
||||
tab.registerContent(async (modelView: azdata.ModelView) => {
|
||||
this.modelBuilder = modelView.modelBuilder;
|
||||
|
||||
const rootContainer = modelView.modelBuilder.flexContainer()
|
||||
this.rootContainer = modelView.modelBuilder.flexContainer()
|
||||
.withLayout({ flexFlow: 'column', width: '100%', height: '100%' })
|
||||
.component();
|
||||
|
||||
this.rootLoadingComponent = modelView.modelBuilder.loadingComponent().withItem(rootContainer).component();
|
||||
this.rootLoadingComponent = modelView.modelBuilder.loadingComponent().withItem(this.rootContainer).component();
|
||||
|
||||
// We nest the content inside another container for the margins - getting them on the root container isn't supported
|
||||
const contentContainer = modelView.modelBuilder.flexContainer()
|
||||
.withLayout({ flexFlow: 'column', width: '100%', height: '100%' })
|
||||
.component();
|
||||
rootContainer.addItem(contentContainer, { CSSStyles: { 'margin-left': '20px', 'margin-right': '20px' } });
|
||||
|
||||
const locationContainer = modelView.modelBuilder.flexContainer().withLayout({ flexFlow: 'row', alignItems: 'center' }).component();
|
||||
|
||||
const locationLabel = modelView.modelBuilder.text()
|
||||
.withProperties<azdata.TextComponentProperties>({
|
||||
value: loc.locationTitle,
|
||||
CSSStyles: { ...cssStyles.titleCss }
|
||||
}).component();
|
||||
|
||||
const pathLabel = modelView.modelBuilder.text()
|
||||
.withProperties<azdata.TextComponentProperties>({
|
||||
value: this.hdfsPath,
|
||||
title: this.hdfsPath,
|
||||
height: locationLabelHeight,
|
||||
CSSStyles: { 'user-select': 'text', 'overflow': 'hidden', 'text-overflow': 'ellipsis', ...cssStyles.titleCss }
|
||||
}).component();
|
||||
|
||||
locationContainer.addItem(locationLabel,
|
||||
{
|
||||
flex: '0 0 auto',
|
||||
CSSStyles: { 'margin-bottom': '5px' }
|
||||
});
|
||||
locationContainer.addItem(pathLabel,
|
||||
{
|
||||
flex: '1 1 auto',
|
||||
CSSStyles: { 'border': '1px solid #ccc', 'padding': '5px', 'margin-left': '10px', 'min-height': `${locationLabelHeight}px` }
|
||||
});
|
||||
|
||||
contentContainer.addItem(locationContainer, { flex: '0 0 auto', CSSStyles: { 'margin-top': '20px' } });
|
||||
|
||||
// =====================
|
||||
// = Permissions Title =
|
||||
// =====================
|
||||
const permissionsTitle = modelView.modelBuilder.text()
|
||||
.withProperties<azdata.TextComponentProperties>({ value: loc.permissionsHeader })
|
||||
.component();
|
||||
contentContainer.addItem(permissionsTitle, { CSSStyles: { 'margin-top': '15px', ...cssStyles.titleCss } });
|
||||
|
||||
// =============================
|
||||
// = POSIX permissions section =
|
||||
// =============================
|
||||
|
||||
const posixPermissionsContainer = this.createPermissionsHeaderRow(modelView.modelBuilder, '', /*includeInherit*/false, /*includeStickyAndInherit*/true);
|
||||
contentContainer.addItem(posixPermissionsContainer, { CSSStyles: { ...cssStyles.tableHeaderLayoutCss } });
|
||||
|
||||
// Empty initially - this is going to eventually be populated with the owner/owning/other group permissions
|
||||
this.posixPermissionsContainer = modelView.modelBuilder.flexContainer().withLayout({ flexFlow: 'column' }).component();
|
||||
contentContainer.addItem(this.posixPermissionsContainer, { flex: '0 0 auto', CSSStyles: { 'margin-bottom': '20px' } });
|
||||
|
||||
// ===========================
|
||||
// = Add User Or Group Input =
|
||||
// ===========================
|
||||
|
||||
const addUserOrGroupTitle = modelView.modelBuilder.text()
|
||||
.withProperties<azdata.TextComponentProperties>({ value: loc.addUserOrGroupHeader, CSSStyles: { 'margin-block-start': '0px', 'margin-block-end': '10px' } })
|
||||
.component();
|
||||
contentContainer.addItem(addUserOrGroupTitle, { CSSStyles: { 'margin-top': '15px', ...cssStyles.titleCss } });
|
||||
|
||||
const typeContainer = modelView.modelBuilder.flexContainer().withProperties({ flexFlow: 'row' }).component();
|
||||
const aclEntryTypeGroup = 'aclEntryType';
|
||||
const userTypeButton = this.createRadioButton(modelView.modelBuilder, loc.userLabel, aclEntryTypeGroup, AclType.user);
|
||||
const groupTypeButton = this.createRadioButton(modelView.modelBuilder, loc.groupLabel, aclEntryTypeGroup, AclType.group);
|
||||
userTypeButton.checked = true;
|
||||
this.addUserOrGroupSelectedType = AclType.user;
|
||||
|
||||
typeContainer.addItems([userTypeButton, groupTypeButton], { flex: '0 0 auto' });
|
||||
contentContainer.addItem(typeContainer, { flex: '0 0 auto', CSSStyles: { 'margin-bottom': '5px' } });
|
||||
const addUserOrGroupInputRow = modelView.modelBuilder.flexContainer().withLayout({ flexFlow: 'row' }).component();
|
||||
|
||||
this.addUserOrGroupInput = modelView.modelBuilder.inputBox()
|
||||
.withProperties<azdata.InputBoxProperties>({
|
||||
inputType: 'text',
|
||||
placeHolder: loc.enterNamePlaceholder,
|
||||
width: 250,
|
||||
stopEnterPropagation: true
|
||||
})
|
||||
.component();
|
||||
this.addUserOrGroupInput.onEnterKeyPressed((value: string) => {
|
||||
this.hdfsModel.createAndAddAclEntry(value, this.addUserOrGroupSelectedType);
|
||||
this.addUserOrGroupInput.value = '';
|
||||
});
|
||||
const addUserOrGroupButton = modelView.modelBuilder.button().withProperties<azdata.ButtonProperties>({ label: loc.addLabel, width: 75 }).component();
|
||||
addUserOrGroupButton.onDidClick(() => {
|
||||
this.hdfsModel.createAndAddAclEntry(this.addUserOrGroupInput.value, this.addUserOrGroupSelectedType);
|
||||
this.addUserOrGroupInput.value = '';
|
||||
});
|
||||
addUserOrGroupButton.enabled = false; // Init to disabled since we don't have any name entered in yet
|
||||
this.addUserOrGroupInput.onTextChanged(() => {
|
||||
if (this.addUserOrGroupInput.value === '') {
|
||||
addUserOrGroupButton.enabled = false;
|
||||
} else {
|
||||
addUserOrGroupButton.enabled = true;
|
||||
}
|
||||
});
|
||||
|
||||
addUserOrGroupInputRow.addItem(this.addUserOrGroupInput, { flex: '0 0 auto' });
|
||||
addUserOrGroupInputRow.addItem(addUserOrGroupButton, { flex: '0 0 auto', CSSStyles: { 'margin-left': '20px' } });
|
||||
|
||||
contentContainer.addItem(addUserOrGroupInputRow, { flex: '0 0 auto', CSSStyles: { 'margin-bottom': '20px' } });
|
||||
|
||||
// =================================================
|
||||
// = Named Users and Groups permissions header row =
|
||||
// =================================================
|
||||
|
||||
const namedUsersAndGroupsPermissionsHeaderRow = this.createPermissionsHeaderRow(modelView.modelBuilder, loc.namedUsersAndGroupsHeader, /*includeInherit*/true, /*includeStickyAndInherit*/false);
|
||||
contentContainer.addItem(namedUsersAndGroupsPermissionsHeaderRow, { CSSStyles: { ...cssStyles.tableHeaderLayoutCss } });
|
||||
|
||||
// Empty initially - this is eventually going to be populated with the ACL entries set for this path
|
||||
this.namedUsersAndGroupsPermissionsContainer = modelView.modelBuilder.flexContainer()
|
||||
.withLayout({ flexFlow: 'column' })
|
||||
.component();
|
||||
contentContainer.addItem(this.namedUsersAndGroupsPermissionsContainer, { flex: '1', CSSStyles: { 'overflow': 'scroll', 'min-height': '200px' } });
|
||||
|
||||
this.viewInitialized = true;
|
||||
this.handlePermissionStatusUpdated(this.hdfsModel.permissionStatus);
|
||||
await modelView.initializeModel(this.rootLoadingComponent);
|
||||
this.modelInitialized = true;
|
||||
this.handlePermissionStatusUpdated(this.hdfsModel.permissionStatus);
|
||||
this.addUserOrGroupInput.focus();
|
||||
});
|
||||
this.dialog.content = [tab];
|
||||
@@ -222,34 +101,228 @@ export class ManageAccessDialog {
|
||||
azdata.window.openDialog(this.dialog);
|
||||
}
|
||||
|
||||
private initializeView(permissionStatus: PermissionStatus): void {
|
||||
// We nest the content inside another container for the margins - getting them on the root container isn't supported
|
||||
const contentContainer = this.modelBuilder.flexContainer()
|
||||
.withLayout({ flexFlow: 'column', width: '100%', height: '100%' })
|
||||
.component();
|
||||
this.rootContainer.addItem(contentContainer, { CSSStyles: { 'margin-left': '20px', 'margin-right': '20px' } });
|
||||
|
||||
const locationContainer = this.modelBuilder.flexContainer().withLayout({ flexFlow: 'row', alignItems: 'center' }).component();
|
||||
|
||||
const locationLabel = this.modelBuilder.text()
|
||||
.withProperties<azdata.TextComponentProperties>({
|
||||
value: loc.locationTitle,
|
||||
CSSStyles: { ...cssStyles.titleCss }
|
||||
}).component();
|
||||
|
||||
const pathLabel = this.modelBuilder.text()
|
||||
.withProperties<azdata.TextComponentProperties>({
|
||||
value: this.hdfsPath,
|
||||
title: this.hdfsPath,
|
||||
height: locationLabelHeight,
|
||||
CSSStyles: { 'user-select': 'text', 'overflow': 'hidden', 'text-overflow': 'ellipsis', ...cssStyles.titleCss }
|
||||
}).component();
|
||||
|
||||
locationContainer.addItem(locationLabel,
|
||||
{
|
||||
flex: '0 0 auto',
|
||||
CSSStyles: { 'margin-bottom': '5px' }
|
||||
});
|
||||
locationContainer.addItem(pathLabel,
|
||||
{
|
||||
flex: '1 1 auto',
|
||||
CSSStyles: { 'border': '1px solid #ccc', 'padding': '5px', 'margin-left': '10px', 'min-height': `${locationLabelHeight}px` }
|
||||
});
|
||||
|
||||
contentContainer.addItem(locationContainer, { flex: '0 0 auto', CSSStyles: { 'margin-top': '20px' } });
|
||||
|
||||
// =====================
|
||||
// = Permissions Title =
|
||||
// =====================
|
||||
const permissionsTitle = this.modelBuilder.text()
|
||||
.withProperties<azdata.TextComponentProperties>({ value: loc.permissionsHeader })
|
||||
.component();
|
||||
contentContainer.addItem(permissionsTitle, { CSSStyles: { 'margin-top': '15px', ...cssStyles.titleCss } });
|
||||
|
||||
// ====================
|
||||
// = Inherit Defaults =
|
||||
// ====================
|
||||
|
||||
// Defaults are only settable for directories
|
||||
if (this.hdfsModel.fileStatus.type === HdfsFileType.Directory) {
|
||||
contentContainer.addItem(this.createInheritDefaultsCheckbox());
|
||||
}
|
||||
|
||||
// ==========
|
||||
// = Sticky =
|
||||
// ==========
|
||||
this.stickyCheckbox = this.modelBuilder.checkBox()
|
||||
.withProperties<azdata.CheckBoxProperties>({
|
||||
width: checkboxSize,
|
||||
height: checkboxSize,
|
||||
checked: permissionStatus.stickyBit,
|
||||
label: loc.stickyLabel
|
||||
}).component();
|
||||
this.stickyCheckbox.onChanged(() => {
|
||||
this.hdfsModel.permissionStatus.stickyBit = this.stickyCheckbox.checked;
|
||||
});
|
||||
contentContainer.addItem(this.stickyCheckbox);
|
||||
|
||||
// =============================
|
||||
// = POSIX permissions section =
|
||||
// =============================
|
||||
|
||||
const posixPermissionsSectionHeaderRow = this.createPermissionsSectionHeaderRow(0, 0);
|
||||
contentContainer.addItem(posixPermissionsSectionHeaderRow, { CSSStyles: { ...cssStyles.tableHeaderLayoutCss } });
|
||||
|
||||
this.posixPermissionsContainer = this.modelBuilder.flexContainer().withLayout({ flexFlow: 'column' }).component();
|
||||
contentContainer.addItem(this.posixPermissionsContainer, { flex: '0 0 auto', CSSStyles: { 'margin-bottom': '20px' } });
|
||||
|
||||
// ===========================
|
||||
// = Add User Or Group Input =
|
||||
// ===========================
|
||||
|
||||
const addUserOrGroupTitle = this.modelBuilder.text()
|
||||
.withProperties<azdata.TextComponentProperties>({ value: loc.addUserOrGroupHeader, CSSStyles: { 'margin-block-start': '0px', 'margin-block-end': '10px' } })
|
||||
.component();
|
||||
contentContainer.addItem(addUserOrGroupTitle, { CSSStyles: { 'margin-top': '15px', ...cssStyles.titleCss } });
|
||||
|
||||
const typeContainer = this.modelBuilder.flexContainer().withProperties({ flexFlow: 'row' }).component();
|
||||
const aclEntryTypeGroup = 'aclEntryType';
|
||||
const userTypeButton = this.createRadioButton(this.modelBuilder, loc.userLabel, aclEntryTypeGroup, AclType.user);
|
||||
const groupTypeButton = this.createRadioButton(this.modelBuilder, loc.groupLabel, aclEntryTypeGroup, AclType.group);
|
||||
userTypeButton.checked = true;
|
||||
this.addUserOrGroupSelectedType = AclType.user;
|
||||
|
||||
typeContainer.addItems([userTypeButton, groupTypeButton], { flex: '0 0 auto' });
|
||||
contentContainer.addItem(typeContainer, { flex: '0 0 auto', CSSStyles: { 'margin-bottom': '5px' } });
|
||||
const addUserOrGroupInputRow = this.modelBuilder.flexContainer().withLayout({ flexFlow: 'row' }).component();
|
||||
|
||||
this.addUserOrGroupInput = this.modelBuilder.inputBox()
|
||||
.withProperties<azdata.InputBoxProperties>({
|
||||
inputType: 'text',
|
||||
placeHolder: loc.enterNamePlaceholder,
|
||||
width: 250,
|
||||
stopEnterPropagation: true
|
||||
})
|
||||
.component();
|
||||
this.addUserOrGroupInput.onEnterKeyPressed((value: string) => {
|
||||
this.hdfsModel.createAndAddAclEntry(value, this.addUserOrGroupSelectedType);
|
||||
this.addUserOrGroupInput.value = '';
|
||||
});
|
||||
const addUserOrGroupButton = this.modelBuilder.button().withProperties<azdata.ButtonProperties>({ label: loc.addLabel, width: 75 }).component();
|
||||
addUserOrGroupButton.onDidClick(() => {
|
||||
this.hdfsModel.createAndAddAclEntry(this.addUserOrGroupInput.value, this.addUserOrGroupSelectedType);
|
||||
this.addUserOrGroupInput.value = '';
|
||||
});
|
||||
addUserOrGroupButton.enabled = false; // Init to disabled since we don't have any name entered in yet
|
||||
this.addUserOrGroupInput.onTextChanged(() => {
|
||||
addUserOrGroupButton.enabled = this.addUserOrGroupInput.value !== '';
|
||||
});
|
||||
|
||||
addUserOrGroupInputRow.addItem(this.addUserOrGroupInput, { flex: '0 0 auto' });
|
||||
addUserOrGroupInputRow.addItem(addUserOrGroupButton, { flex: '0 0 auto', CSSStyles: { 'margin-left': '20px' } });
|
||||
|
||||
contentContainer.addItem(addUserOrGroupInputRow, { flex: '0 0 auto', CSSStyles: { 'margin-bottom': '20px' } });
|
||||
|
||||
// =================================================
|
||||
// = Named Users and Groups permissions header row =
|
||||
// =================================================
|
||||
|
||||
const namedUsersAndGroupsSectionsHeaderRow = this.createPermissionsSectionHeaderRow(permissionsDeleteColumnWidth, permissionsCheckboxColumnWidth);
|
||||
contentContainer.addItem(namedUsersAndGroupsSectionsHeaderRow, { CSSStyles: { ...cssStyles.tableHeaderLayoutCss } });
|
||||
|
||||
this.namedUsersAndGroupsPermissionsContainer = this.modelBuilder.flexContainer()
|
||||
.withLayout({ flexFlow: 'column' })
|
||||
.component();
|
||||
contentContainer.addItem(this.namedUsersAndGroupsPermissionsContainer, { flex: '1', CSSStyles: { 'overflow': 'scroll', 'min-height': '200px' } });
|
||||
this.viewInitialized = true;
|
||||
}
|
||||
|
||||
private handlePermissionStatusUpdated(permissionStatus: PermissionStatus): void {
|
||||
if (!permissionStatus || !this.viewInitialized) {
|
||||
if (!permissionStatus || !this.modelInitialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If this is the first time go through and create the UI components now that we have a model to use
|
||||
if (!this.viewInitialized) {
|
||||
this.initializeView(permissionStatus);
|
||||
}
|
||||
|
||||
this.stickyCheckbox.checked = permissionStatus.stickyBit;
|
||||
this.inheritDefaultsCheckbox.checked =
|
||||
!permissionStatus.owner.getPermission(AclEntryScope.default) &&
|
||||
!permissionStatus.group.getPermission(AclEntryScope.default) &&
|
||||
!permissionStatus.other.getPermission(AclEntryScope.default);
|
||||
// Update display status for headers for the Default section - you can't set Default ACLs for non-directories so we just hide that column
|
||||
this.defaultSectionComponents.forEach(component => component.display = this.hdfsModel.fileStatus.type === HdfsFileType.Directory ? '' : 'none');
|
||||
if (this.hdfsModel.fileStatus.type === HdfsFileType.Directory) {
|
||||
this.inheritDefaultsCheckbox.checked =
|
||||
!permissionStatus.owner.getPermission(AclEntryScope.default) &&
|
||||
!permissionStatus.group.getPermission(AclEntryScope.default) &&
|
||||
!permissionStatus.other.getPermission(AclEntryScope.default);
|
||||
}
|
||||
|
||||
this.applyRecursivelyButton.hidden = this.hdfsModel.fileStatus.type !== HdfsFileType.Directory;
|
||||
this.inheritDefaultsCheckbox.display = this.hdfsModel.fileStatus.type === HdfsFileType.Directory ? '' : 'none';
|
||||
// POSIX permission owner/group/other
|
||||
const ownerPermissionsRow = this.createPermissionsRow(this.modelBuilder, permissionStatus.owner, /*includeDelete*/false, /*includeInherit*/false);
|
||||
const owningGroupPermissionsRow = this.createPermissionsRow(this.modelBuilder, permissionStatus.group, /*includeDelete*/false, /*includeInherit*/false);
|
||||
const otherPermissionsRow = this.createPermissionsRow(this.modelBuilder, permissionStatus.other, /*includeDelete*/false, /*includeInherit*/false);
|
||||
|
||||
this.posixPermissionsContainer.clearItems();
|
||||
this.posixPermissionsContainer.addItems([ownerPermissionsRow, owningGroupPermissionsRow, otherPermissionsRow], { CSSStyles: { 'border-bottom': cssStyles.tableBorderCss, 'border-top': cssStyles.tableBorderCss, 'margin-right': '14px' } });
|
||||
|
||||
const posixPermissionData = [permissionStatus.owner, permissionStatus.group, permissionStatus.other].map(aclEntry => {
|
||||
return this.createPermissionsTableRow(aclEntry, false/*includeDelete*/, false/*includeInherit*/);
|
||||
});
|
||||
|
||||
const posixPermissionsNamesColumnWidth = 800 + (this.hdfsModel.fileStatus.type === HdfsFileType.Directory ? 0 : permissionsCheckboxColumnWidth * 3);
|
||||
const namedUsersAndGroupsPermissionsNamesColumnWidth = 700 + (this.hdfsModel.fileStatus.type === HdfsFileType.Directory ? 0 : permissionsCheckboxColumnWidth * 3);
|
||||
|
||||
// Default set of columns that are always shown
|
||||
let posixPermissionsColumns = [
|
||||
this.createTableColumn('', loc.userOrGroupIcon, permissionsCheckboxColumnWidth, azdata.DeclarativeDataType.component),
|
||||
this.createTableColumn('', loc.defaultUserAndGroups, posixPermissionsNamesColumnWidth, azdata.DeclarativeDataType.string),
|
||||
this.createTableColumn(loc.readHeader, `${loc.accessHeader} ${loc.readHeader}`, permissionsCheckboxColumnWidth, azdata.DeclarativeDataType.component),
|
||||
this.createTableColumn(loc.writeHeader, `${loc.accessHeader} ${loc.writeHeader}`, permissionsCheckboxColumnWidth, azdata.DeclarativeDataType.component),
|
||||
this.createTableColumn(loc.executeHeader, `${loc.accessHeader} ${loc.executeHeader}`, permissionsCheckboxColumnWidth, azdata.DeclarativeDataType.component)];
|
||||
let namedUsersAndGroupsColumns = [
|
||||
this.createTableColumn('', loc.userOrGroupIcon, 50, azdata.DeclarativeDataType.component),
|
||||
this.createTableColumn(loc.namedUsersAndGroupsHeader, loc.namedUsersAndGroupsHeader, namedUsersAndGroupsPermissionsNamesColumnWidth, azdata.DeclarativeDataType.string),
|
||||
this.createTableColumn(loc.readHeader, `${loc.accessHeader} ${loc.readHeader}`, permissionsCheckboxColumnWidth, azdata.DeclarativeDataType.component),
|
||||
this.createTableColumn(loc.writeHeader, `${loc.accessHeader} ${loc.writeHeader}`, permissionsCheckboxColumnWidth, azdata.DeclarativeDataType.component),
|
||||
this.createTableColumn(loc.executeHeader, `${loc.accessHeader} ${loc.executeHeader}`, permissionsCheckboxColumnWidth, azdata.DeclarativeDataType.component)];
|
||||
|
||||
// Additional columns that are only shown for directories
|
||||
if (this.hdfsModel.fileStatus.type === HdfsFileType.Directory) {
|
||||
posixPermissionsColumns = posixPermissionsColumns.concat([
|
||||
this.createTableColumn(loc.readHeader, `${loc.defaultHeader} ${loc.readHeader}`, permissionsCheckboxColumnWidth, azdata.DeclarativeDataType.component),
|
||||
this.createTableColumn(loc.writeHeader, `${loc.defaultHeader} ${loc.writeHeader}`, permissionsCheckboxColumnWidth, azdata.DeclarativeDataType.component),
|
||||
this.createTableColumn(loc.executeHeader, `${loc.defaultHeader} ${loc.executeHeader}`, permissionsCheckboxColumnWidth, azdata.DeclarativeDataType.component)
|
||||
]);
|
||||
namedUsersAndGroupsColumns = namedUsersAndGroupsColumns.concat([
|
||||
this.createTableColumn(loc.inheritDefaultsLabel, loc.inheritDefaultsLabel, permissionsCheckboxColumnWidth, azdata.DeclarativeDataType.component),
|
||||
this.createTableColumn(loc.readHeader, `${loc.defaultHeader} ${loc.readHeader}`, permissionsCheckboxColumnWidth, azdata.DeclarativeDataType.component),
|
||||
this.createTableColumn(loc.writeHeader, `${loc.defaultHeader} ${loc.writeHeader}`, permissionsCheckboxColumnWidth, azdata.DeclarativeDataType.component),
|
||||
this.createTableColumn(loc.executeHeader, `${loc.defaultHeader} ${loc.executeHeader}`, permissionsCheckboxColumnWidth, azdata.DeclarativeDataType.component),
|
||||
]);
|
||||
}
|
||||
namedUsersAndGroupsColumns.push(this.createTableColumn('', loc.deleteTitle, permissionsDeleteColumnWidth, azdata.DeclarativeDataType.component));
|
||||
|
||||
const posixPermissionsTable = this.modelBuilder.declarativeTable()
|
||||
.withProperties<azdata.DeclarativeTableProperties>(
|
||||
{
|
||||
columns: posixPermissionsColumns,
|
||||
data: posixPermissionData
|
||||
}).component();
|
||||
|
||||
this.posixPermissionsContainer.addItem(posixPermissionsTable, { CSSStyles: { 'margin-right': '12px' } });
|
||||
|
||||
this.namedUsersAndGroupsPermissionsContainer.clearItems();
|
||||
// Named users and groups
|
||||
permissionStatus.aclEntries.forEach(entry => {
|
||||
const namedEntryRow = this.createPermissionsRow(this.modelBuilder, entry, /*includeDelete*/true, /*includeInherit*/true);
|
||||
this.namedUsersAndGroupsPermissionsContainer.addItem(namedEntryRow, { CSSStyles: { 'border-bottom': cssStyles.tableBorderCss, 'border-top': cssStyles.tableBorderCss } });
|
||||
|
||||
const namedUsersAndGroupsData = permissionStatus.aclEntries.map(aclEntry => {
|
||||
return this.createPermissionsTableRow(aclEntry, true/*includeDelete*/, this.hdfsModel.fileStatus.type === HdfsFileType.Directory/*includeInherit*/);
|
||||
});
|
||||
|
||||
const namedUsersAndGroupsTable = this.modelBuilder.declarativeTable()
|
||||
.withProperties<azdata.DeclarativeTableProperties>(
|
||||
{
|
||||
columns: namedUsersAndGroupsColumns,
|
||||
data: namedUsersAndGroupsData
|
||||
}).component();
|
||||
|
||||
this.namedUsersAndGroupsPermissionsContainer.addItem(namedUsersAndGroupsTable);
|
||||
|
||||
this.rootLoadingComponent.loading = false;
|
||||
}
|
||||
|
||||
@@ -261,117 +334,138 @@ export class ManageAccessDialog {
|
||||
return button;
|
||||
}
|
||||
|
||||
private createPermissionsRow(builder: azdata.ModelBuilder, entry: AclEntry, includeDelete: boolean, includeInherit: boolean): azdata.FlexContainer {
|
||||
const rowContainer = builder.flexContainer().withLayout({ flexFlow: 'row', height: permissionsRowHeight }).component();
|
||||
private createTableColumn(header: string, ariaLabel: string, width: number, type: azdata.DeclarativeDataType): azdata.DeclarativeTableColumn {
|
||||
return {
|
||||
displayName: header,
|
||||
ariaLabel: ariaLabel,
|
||||
valueType: type,
|
||||
isReadOnly: true,
|
||||
width: width,
|
||||
headerCssStyles: {
|
||||
'border': 'none',
|
||||
'background-color': '#FFFFFF',
|
||||
'padding': '0px',
|
||||
...cssStyles.permissionsTableHeaderCss
|
||||
},
|
||||
rowCssStyles: {
|
||||
'border-top': 'solid 1px #ccc',
|
||||
'border-bottom': 'solid 1px #ccc',
|
||||
'border-left': 'none',
|
||||
'border-right': 'none',
|
||||
'padding': '0px'
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// Icon
|
||||
const iconCell = builder.image()
|
||||
private createImageComponent(type: AclType | PermissionType): azdata.ImageComponent {
|
||||
const imageProperties = getImageForType(type);
|
||||
return this.modelBuilder.image()
|
||||
.withProperties<azdata.ImageComponentProperties>({
|
||||
iconPath: getImageForType(entry.type),
|
||||
iconPath: imageProperties.iconPath,
|
||||
width: permissionsTypeIconColumnWidth,
|
||||
height: permissionsRowHeight,
|
||||
iconWidth: 20,
|
||||
iconHeight: 20
|
||||
})
|
||||
.component();
|
||||
rowContainer.addItem(iconCell, { flex: '0 0 auto' });
|
||||
iconHeight: 20,
|
||||
title: imageProperties.title
|
||||
}).component();
|
||||
}
|
||||
|
||||
// Name
|
||||
const nameCell = builder.text().withProperties({ value: entry.displayName }).component();
|
||||
rowContainer.addItem(nameCell);
|
||||
|
||||
// Access - Read
|
||||
const accessReadComponents = createCheckbox(builder, entry.getPermission(AclEntryScope.access).read, true, permissionsReadColumnWidth, permissionsRowHeight, `${loc.accessHeader} ${loc.readHeader}`);
|
||||
rowContainer.addItem(accessReadComponents.container, { flex: '0 0 auto' });
|
||||
private createPermissionsTableRow(aclEntry: AclEntry, includeDelete: boolean, includeInherit: boolean): any[] {
|
||||
// Access Read
|
||||
const accessReadComponents = createCheckbox(this.modelBuilder, aclEntry.getPermission(AclEntryScope.access).read, true, permissionsCheckboxColumnWidth, permissionsRowHeight, `${loc.accessHeader} ${loc.readHeader}`);
|
||||
accessReadComponents.checkbox.onChanged(() => {
|
||||
entry.getPermission(AclEntryScope.access).read = accessReadComponents.checkbox.checked;
|
||||
aclEntry.getPermission(AclEntryScope.access).read = accessReadComponents.checkbox.checked;
|
||||
});
|
||||
|
||||
// Access - Write
|
||||
const accessWriteComponents = createCheckbox(builder, entry.getPermission(AclEntryScope.access).write, true, permissionsWriteColumnWidth, permissionsRowHeight, `${loc.accessHeader} ${loc.writeHeader}`);
|
||||
rowContainer.addItem(accessWriteComponents.container, { flex: '0 0 auto' });
|
||||
// Access Write
|
||||
const accessWriteComponents = createCheckbox(this.modelBuilder, aclEntry.getPermission(AclEntryScope.access).write, true, permissionsCheckboxColumnWidth, permissionsRowHeight, `${loc.accessHeader} ${loc.writeHeader}`);
|
||||
accessWriteComponents.checkbox.onChanged(() => {
|
||||
entry.getPermission(AclEntryScope.access).write = accessWriteComponents.checkbox.checked;
|
||||
aclEntry.getPermission(AclEntryScope.access).write = accessWriteComponents.checkbox.checked;
|
||||
});
|
||||
|
||||
// Access - Execute
|
||||
const accessExecuteComponents = createCheckbox(builder, entry.getPermission(AclEntryScope.access).execute, true, permissionsExecuteColumnWidth, permissionsRowHeight, `${loc.accessHeader} ${loc.executeHeader}`);
|
||||
rowContainer.addItem(accessExecuteComponents.container, { flex: '0 0 auto', CSSStyles: { 'border-right': this.hdfsModel.fileStatus.type === HdfsFileType.Directory ? cssStyles.tableBorderCss : '' } });
|
||||
// Access Execute
|
||||
const accessExecuteComponents = createCheckbox(this.modelBuilder, aclEntry.getPermission(AclEntryScope.access).execute, true, permissionsCheckboxColumnWidth, permissionsRowHeight, `${loc.accessHeader} ${loc.executeHeader}`);
|
||||
accessExecuteComponents.checkbox.onChanged(() => {
|
||||
entry.getPermission(AclEntryScope.access).execute = accessExecuteComponents.checkbox.checked;
|
||||
aclEntry.getPermission(AclEntryScope.access).execute = accessExecuteComponents.checkbox.checked;
|
||||
});
|
||||
|
||||
const permissionsCheckboxesMapping: PermissionCheckboxesMapping = {
|
||||
model: entry,
|
||||
model: aclEntry,
|
||||
access: { read: accessReadComponents.checkbox, write: accessWriteComponents.checkbox, execute: accessExecuteComponents.checkbox },
|
||||
default: { read: undefined, write: undefined, execute: undefined }
|
||||
};
|
||||
|
||||
// Only directories can set ACL defaults so we hide the column for non-directories
|
||||
let row = [
|
||||
this.createImageComponent(aclEntry.type),
|
||||
aclEntry.displayName,
|
||||
accessReadComponents.container,
|
||||
accessWriteComponents.container,
|
||||
accessExecuteComponents.container
|
||||
];
|
||||
|
||||
// Default permissions can only be set on directories
|
||||
if (this.hdfsModel.fileStatus.type === HdfsFileType.Directory) {
|
||||
const defaultPermission = aclEntry.getPermission(AclEntryScope.default);
|
||||
|
||||
const defaultPermission = entry.getPermission(AclEntryScope.default);
|
||||
// Default Read
|
||||
const defaultReadCheckboxComponents = createCheckbox(this.modelBuilder, defaultPermission && defaultPermission.read, !!defaultPermission, permissionsCheckboxColumnWidth, permissionsRowHeight, `${loc.defaultHeader} ${loc.readHeader}`);
|
||||
defaultReadCheckboxComponents.checkbox.onChanged(() => {
|
||||
aclEntry.getPermission(AclEntryScope.default).read = defaultReadCheckboxComponents.checkbox.checked;
|
||||
});
|
||||
|
||||
const defaultReadComponents = createCheckbox(builder, defaultPermission && defaultPermission.read, !!defaultPermission, permissionsReadColumnWidth, permissionsRowHeight, `${loc.defaultHeader} ${loc.readHeader}`);
|
||||
const defaultWriteComponents = createCheckbox(builder, defaultPermission && defaultPermission.write, !!defaultPermission, permissionsWriteColumnWidth, permissionsRowHeight, `${loc.defaultHeader} ${loc.writeHeader}`);
|
||||
const defaultExecuteComponents = createCheckbox(builder, defaultPermission && defaultPermission.execute, !!defaultPermission, permissionsExecuteColumnWidth, permissionsRowHeight, `${loc.defaultHeader} ${loc.executeHeader}`);
|
||||
permissionsCheckboxesMapping.default = { read: defaultReadComponents.checkbox, write: defaultWriteComponents.checkbox, execute: defaultExecuteComponents.checkbox };
|
||||
// Default Write
|
||||
const defaultWriteCheckboxComponents = createCheckbox(this.modelBuilder, defaultPermission && defaultPermission.write, !!defaultPermission, permissionsCheckboxColumnWidth, permissionsRowHeight, `${loc.defaultHeader} ${loc.writeHeader}`);
|
||||
defaultWriteCheckboxComponents.checkbox.onChanged(() => {
|
||||
aclEntry.getPermission(AclEntryScope.default).write = defaultWriteCheckboxComponents.checkbox.checked;
|
||||
});
|
||||
|
||||
// Default Execute
|
||||
const defaultExecuteCheckboxComponents = createCheckbox(this.modelBuilder, defaultPermission && defaultPermission.execute, !!defaultPermission, permissionsCheckboxColumnWidth, permissionsRowHeight, `${loc.defaultHeader} ${loc.executeHeader}`);
|
||||
defaultExecuteCheckboxComponents.checkbox.onChanged(() => {
|
||||
aclEntry.getPermission(AclEntryScope.default).execute = defaultExecuteCheckboxComponents.checkbox.checked;
|
||||
});
|
||||
|
||||
permissionsCheckboxesMapping.default = { read: defaultReadCheckboxComponents.checkbox, write: defaultWriteCheckboxComponents.checkbox, execute: defaultExecuteCheckboxComponents.checkbox };
|
||||
|
||||
// Default - Inherit
|
||||
if (includeInherit) {
|
||||
const defaultInheritComponents = createCheckbox(builder, !defaultPermission, !this.inheritDefaultsCheckbox.checked, permissionsInheritColumnWidth, permissionsRowHeight, loc.inheritDefaultsLabel);
|
||||
defaultInheritComponents.checkbox.onChanged(() => {
|
||||
defaultReadComponents.checkbox.enabled = !defaultInheritComponents.checkbox.checked;
|
||||
defaultWriteComponents.checkbox.enabled = !defaultInheritComponents.checkbox.checked;
|
||||
defaultExecuteComponents.checkbox.enabled = !defaultInheritComponents.checkbox.checked;
|
||||
if (defaultInheritComponents.checkbox.checked) {
|
||||
entry.removePermission(AclEntryScope.default);
|
||||
defaultReadComponents.checkbox.checked = false;
|
||||
defaultWriteComponents.checkbox.checked = false;
|
||||
defaultExecuteComponents.checkbox.checked = false;
|
||||
const inheritCheckboxComponents = createCheckbox(this.modelBuilder, !defaultPermission, !this.inheritDefaultsCheckbox.checked, permissionsCheckboxColumnWidth, permissionsRowHeight, loc.inheritDefaultsLabel);
|
||||
inheritCheckboxComponents.checkbox.onChanged(() => {
|
||||
defaultReadCheckboxComponents.checkbox.enabled = !inheritCheckboxComponents.checkbox.checked;
|
||||
defaultWriteCheckboxComponents.checkbox.enabled = !inheritCheckboxComponents.checkbox.checked;
|
||||
defaultExecuteCheckboxComponents.checkbox.enabled = !inheritCheckboxComponents.checkbox.checked;
|
||||
if (inheritCheckboxComponents.checkbox.checked) {
|
||||
aclEntry.removePermission(AclEntryScope.default);
|
||||
defaultReadCheckboxComponents.checkbox.checked = false;
|
||||
defaultWriteCheckboxComponents.checkbox.checked = false;
|
||||
defaultExecuteCheckboxComponents.checkbox.checked = false;
|
||||
} else {
|
||||
// Default to the access settings - this is what HDFS does if you don't
|
||||
// specify the complete set of default ACLs for owner, owning group and other
|
||||
const accessRead = accessReadComponents.checkbox.checked;
|
||||
const accessWrite = accessWriteComponents.checkbox.checked;
|
||||
const accessExecute = accessExecuteComponents.checkbox.checked;
|
||||
defaultReadComponents.checkbox.checked = accessRead;
|
||||
defaultWriteComponents.checkbox.checked = accessWrite;
|
||||
defaultExecuteComponents.checkbox.checked = accessExecute;
|
||||
entry.addPermission(AclEntryScope.default,
|
||||
defaultReadCheckboxComponents.checkbox.checked = accessRead;
|
||||
defaultWriteCheckboxComponents.checkbox.checked = accessWrite;
|
||||
defaultExecuteCheckboxComponents.checkbox.checked = accessExecute;
|
||||
aclEntry.addPermission(AclEntryScope.default,
|
||||
new AclEntryPermission(accessRead, accessWrite, accessExecute));
|
||||
}
|
||||
});
|
||||
this.namedSectionInheritCheckboxes.push(defaultInheritComponents.checkbox);
|
||||
rowContainer.addItem(defaultInheritComponents.container, { flex: '0 0 auto', CSSStyles: { 'border-right': cssStyles.tableBorderCss } });
|
||||
this.namedSectionInheritCheckboxes.push(inheritCheckboxComponents.checkbox);
|
||||
row.push(inheritCheckboxComponents.container);
|
||||
}
|
||||
|
||||
this.posixPermissionCheckboxesMapping.push(permissionsCheckboxesMapping);
|
||||
|
||||
// Default - Read
|
||||
rowContainer.addItem(defaultReadComponents.container, { flex: '0 0 auto' });
|
||||
defaultReadComponents.checkbox.onChanged(() => {
|
||||
entry.getPermission(AclEntryScope.default).read = defaultReadComponents.checkbox.checked;
|
||||
});
|
||||
|
||||
// Default - Write
|
||||
rowContainer.addItem(defaultWriteComponents.container, { flex: '0 0 auto' });
|
||||
defaultWriteComponents.checkbox.onChanged(() => {
|
||||
entry.getPermission(AclEntryScope.default).write = defaultWriteComponents.checkbox.checked;
|
||||
});
|
||||
|
||||
// Default - Execute
|
||||
rowContainer.addItem(defaultExecuteComponents.container, { flex: '0 0 auto' });
|
||||
defaultExecuteComponents.checkbox.onChanged(() => {
|
||||
entry.getPermission(AclEntryScope.default).execute = defaultExecuteComponents.checkbox.checked;
|
||||
});
|
||||
row = row.concat([
|
||||
defaultReadCheckboxComponents.container,
|
||||
defaultWriteCheckboxComponents.container,
|
||||
defaultExecuteCheckboxComponents.container
|
||||
]);
|
||||
}
|
||||
|
||||
this.posixPermissionCheckboxesMapping.push(permissionsCheckboxesMapping);
|
||||
|
||||
const deleteContainer = builder.flexContainer().withLayout({ width: permissionsDeleteColumnWidth, height: permissionsRowHeight }).component();
|
||||
|
||||
if (includeDelete) {
|
||||
const deleteButton = builder.button()
|
||||
const deleteButton = this.modelBuilder.button()
|
||||
.withProperties<azdata.ButtonProperties>(
|
||||
{
|
||||
label: '',
|
||||
@@ -381,164 +475,125 @@ export class ManageAccessDialog {
|
||||
height: 20
|
||||
})
|
||||
.component();
|
||||
deleteButton.onDidClick(() => { this.hdfsModel.deleteAclEntry(entry); });
|
||||
deleteContainer.addItem(deleteButton);
|
||||
deleteButton.onDidClick(() => { this.hdfsModel.deleteAclEntry(aclEntry); });
|
||||
row.push(deleteButton);
|
||||
}
|
||||
rowContainer.addItem(deleteContainer, { flex: '0 0 auto', CSSStyles: { 'margin-top': '7px', 'margin-left': '5px' } });
|
||||
|
||||
return rowContainer;
|
||||
return row;
|
||||
}
|
||||
|
||||
private createInheritDefaultsCheckbox(): azdata.CheckBoxComponent {
|
||||
this.inheritDefaultsCheckbox = this.modelBuilder.checkBox()
|
||||
.withProperties<azdata.CheckBoxProperties>({
|
||||
width: checkboxSize,
|
||||
height: checkboxSize,
|
||||
checked: false, // Will be set when we get the model update
|
||||
label: loc.inheritDefaultsLabel
|
||||
})
|
||||
.component();
|
||||
|
||||
this.inheritDefaultsCheckbox.onChanged(() => {
|
||||
if (this.inheritDefaultsCheckbox.checked) {
|
||||
this.namedSectionInheritCheckboxes.forEach(c => {
|
||||
c.enabled = false;
|
||||
c.checked = true;
|
||||
});
|
||||
} else {
|
||||
this.namedSectionInheritCheckboxes.forEach(c => {
|
||||
c.enabled = true;
|
||||
c.checked = false;
|
||||
});
|
||||
}
|
||||
// Go through each of the rows for owner/owning group/other and update
|
||||
// their checkboxes based on the new value of the inherit checkbox
|
||||
this.posixPermissionCheckboxesMapping.forEach(m => {
|
||||
m.default.read.enabled = !this.inheritDefaultsCheckbox.checked;
|
||||
m.default.write.enabled = !this.inheritDefaultsCheckbox.checked;
|
||||
m.default.execute.enabled = !this.inheritDefaultsCheckbox.checked;
|
||||
if (this.inheritDefaultsCheckbox.checked) {
|
||||
m.model.removePermission(AclEntryScope.default);
|
||||
m.default.read.checked = false;
|
||||
m.default.write.checked = false;
|
||||
m.default.execute.checked = false;
|
||||
} else {
|
||||
// Default to the access settings - this is what HDFS does if you don't
|
||||
// specify the complete set of default ACLs for owner, owning group and other
|
||||
const accessRead = m.access.read.checked;
|
||||
const accessWrite = m.access.write.checked;
|
||||
const accessExecute = m.access.execute.checked;
|
||||
m.default.read.checked = accessRead;
|
||||
m.default.write.checked = accessWrite;
|
||||
m.default.execute.checked = accessExecute;
|
||||
m.model.addPermission(AclEntryScope.default, new AclEntryPermission(accessRead, accessWrite, accessExecute));
|
||||
}
|
||||
});
|
||||
});
|
||||
return this.inheritDefaultsCheckbox;
|
||||
}
|
||||
/**
|
||||
* Creates the header row for the permissions tables. This contains headers for the name and read/write/execute for the
|
||||
* access section. If the path is for a directory then a default section is included for specifying default permissions.
|
||||
* @param modelBuilder The builder used to create the model components
|
||||
* @param nameColumnText The text to display for the name column
|
||||
* @param rightSpacerWidth The amount of space to include on the right to correctly align the headers with the
|
||||
* @param middleSpacerWidth The amount of space to include between the text to correctly align the headers with the table sections
|
||||
*/
|
||||
private createPermissionsHeaderRow(modelBuilder: azdata.ModelBuilder, nameColumnText: string, includeInherit: boolean, includeStickyAndInherit: boolean): azdata.FlexContainer {
|
||||
const rowsContainer = modelBuilder.flexContainer().withLayout({ flexFlow: 'column' }).component();
|
||||
|
||||
private createPermissionsSectionHeaderRow(rightSpacerWidth: number, middleSpacerWidth: number): azdata.FlexContainer {
|
||||
// Section Headers
|
||||
const sectionHeaderContainer = modelBuilder.flexContainer().withLayout({ flexFlow: 'row', justifyContent: 'flex-end' }).component();
|
||||
|
||||
if (includeStickyAndInherit) {
|
||||
this.inheritDefaultsCheckbox = modelBuilder.checkBox()
|
||||
.withProperties<azdata.CheckBoxProperties>({
|
||||
width: checkboxSize,
|
||||
height: checkboxSize,
|
||||
checked: false, // Will be set when we get the model update
|
||||
label: loc.inheritDefaultsLabel
|
||||
})
|
||||
.component();
|
||||
|
||||
this.inheritDefaultsCheckbox.onChanged(() => {
|
||||
if (this.inheritDefaultsCheckbox.checked) {
|
||||
this.namedSectionInheritCheckboxes.forEach(c => {
|
||||
c.enabled = false;
|
||||
c.checked = true;
|
||||
});
|
||||
} else {
|
||||
this.namedSectionInheritCheckboxes.forEach(c => {
|
||||
c.enabled = true;
|
||||
c.checked = false;
|
||||
});
|
||||
}
|
||||
// Go through each of the rows for owner/owning group/other and update
|
||||
// their checkboxes based on the new value of the inherit checkbox
|
||||
this.posixPermissionCheckboxesMapping.forEach(m => {
|
||||
m.default.read.enabled = !this.inheritDefaultsCheckbox.checked;
|
||||
m.default.write.enabled = !this.inheritDefaultsCheckbox.checked;
|
||||
m.default.execute.enabled = !this.inheritDefaultsCheckbox.checked;
|
||||
if (this.inheritDefaultsCheckbox.checked) {
|
||||
m.model.removePermission(AclEntryScope.default);
|
||||
m.default.read.checked = false;
|
||||
m.default.write.checked = false;
|
||||
m.default.execute.checked = false;
|
||||
} else {
|
||||
// Default to the access settings - this is what HDFS does if you don't
|
||||
// specify the complete set of default ACLs for owner, owning group and other
|
||||
const accessRead = m.access.read.checked;
|
||||
const accessWrite = m.access.write.checked;
|
||||
const accessExecute = m.access.execute.checked;
|
||||
m.default.read.checked = accessRead;
|
||||
m.default.write.checked = accessWrite;
|
||||
m.default.execute.checked = accessExecute;
|
||||
m.model.addPermission(AclEntryScope.default, new AclEntryPermission(accessRead, accessWrite, accessExecute));
|
||||
}
|
||||
});
|
||||
});
|
||||
this.defaultSectionComponents.push(this.inheritDefaultsCheckbox);
|
||||
sectionHeaderContainer.addItem(this.inheritDefaultsCheckbox);
|
||||
}
|
||||
const sectionHeaderContainer = this.modelBuilder.flexContainer().withLayout({ flexFlow: 'row', justifyContent: 'flex-end' }).component();
|
||||
|
||||
// Access
|
||||
const accessSectionHeader = modelBuilder.text()
|
||||
const accessSectionHeader = this.modelBuilder.text()
|
||||
.withProperties<azdata.TextComponentProperties>({
|
||||
value: loc.accessHeader,
|
||||
ariaHidden: true,
|
||||
CSSStyles: {
|
||||
'width': `${permissionsReadColumnWidth + permissionsWriteColumnWidth + permissionsExecuteColumnWidth}px`,
|
||||
'min-width': `${permissionsReadColumnWidth + permissionsWriteColumnWidth + permissionsExecuteColumnWidth}px`,
|
||||
// This covers 3 checkbox columns
|
||||
'width': `${permissionsCheckboxColumnWidth * 3}px`,
|
||||
'min-width': `${permissionsCheckboxColumnWidth * 3}px`,
|
||||
...cssStyles.permissionsTableHeaderCss
|
||||
}
|
||||
})
|
||||
.component();
|
||||
sectionHeaderContainer.addItem(accessSectionHeader, { flex: '0 0 auto' });
|
||||
|
||||
// Default
|
||||
const defaultSectionHeader = modelBuilder.text()
|
||||
.withProperties<azdata.TextComponentProperties>({
|
||||
value: loc.defaultHeader,
|
||||
CSSStyles: {
|
||||
'width': `${permissionsReadColumnWidth + permissionsWriteColumnWidth + permissionsExecuteColumnWidth}px`,
|
||||
'min-width': `${permissionsReadColumnWidth + permissionsWriteColumnWidth + permissionsExecuteColumnWidth}px`,
|
||||
...cssStyles.permissionsTableHeaderCss
|
||||
}
|
||||
})
|
||||
.component();
|
||||
sectionHeaderContainer.addItem(defaultSectionHeader, { flex: '0 0 auto' });
|
||||
this.defaultSectionComponents.push(defaultSectionHeader);
|
||||
// Only show default section for directories
|
||||
if (this.hdfsModel.fileStatus.type === HdfsFileType.Directory) {
|
||||
// Middle spacer
|
||||
const middleSpacer = this.modelBuilder.text().withProperties({ CSSStyles: { 'width': `${middleSpacerWidth}px`, 'min-width': `${middleSpacerWidth}px` } }).component();
|
||||
sectionHeaderContainer.addItem(middleSpacer, { flex: '0 0 auto' });
|
||||
|
||||
// Delete - just used as a spacer
|
||||
const deleteSectionHeader = modelBuilder.text().component();
|
||||
sectionHeaderContainer.addItem(deleteSectionHeader, { CSSStyles: { 'width': `${permissionsDeleteColumnWidth}px`, 'min-width': `${permissionsDeleteColumnWidth}px` } });
|
||||
|
||||
rowsContainer.addItem(sectionHeaderContainer);
|
||||
|
||||
// Table headers
|
||||
const headerRowContainer = modelBuilder.flexContainer().withLayout({ flexFlow: 'row' }).component();
|
||||
|
||||
if (includeStickyAndInherit) {
|
||||
// Sticky
|
||||
this.stickyCheckbox = modelBuilder.checkBox()
|
||||
.withProperties<azdata.CheckBoxProperties>({
|
||||
width: checkboxSize,
|
||||
height: checkboxSize,
|
||||
checked: false, // Will be set when we get the model update
|
||||
label: loc.stickyLabel
|
||||
// Default
|
||||
const defaultSectionHeader = this.modelBuilder.text()
|
||||
.withProperties<azdata.TextComponentProperties>({
|
||||
value: loc.defaultHeader,
|
||||
ariaHidden: true,
|
||||
CSSStyles: {
|
||||
// This covers 3 checkbox columns
|
||||
'width': `${permissionsCheckboxColumnWidth * 3}px`,
|
||||
'min-width': `${permissionsCheckboxColumnWidth * 3}px`,
|
||||
...cssStyles.permissionsTableHeaderCss
|
||||
}
|
||||
})
|
||||
.component();
|
||||
this.stickyCheckbox.onChanged(() => {
|
||||
this.hdfsModel.permissionStatus.stickyBit = this.stickyCheckbox.checked;
|
||||
});
|
||||
headerRowContainer.addItem(this.stickyCheckbox);
|
||||
sectionHeaderContainer.addItem(defaultSectionHeader, { flex: '0 0 auto' });
|
||||
}
|
||||
|
||||
// Name
|
||||
const nameCell = modelBuilder.text().withProperties<azdata.TextComponentProperties>({ value: nameColumnText }).component();
|
||||
headerRowContainer.addItem(nameCell, { flex: '1 1 auto', CSSStyles: { 'width': `${permissionsNameColumnWidth}px`, 'min-width': `${permissionsNameColumnWidth}px`, ...cssStyles.tableHeaderCss } });
|
||||
// Right spacer
|
||||
const rightSpacer = this.modelBuilder.text().withProperties({ CSSStyles: { 'width': `${rightSpacerWidth}px`, 'min-width': `${rightSpacerWidth}px` } }).component();
|
||||
sectionHeaderContainer.addItem(rightSpacer, { flex: '0 0 auto' });
|
||||
|
||||
// Access Permissions Group
|
||||
const accessReadCell = modelBuilder.text().withProperties<azdata.TextComponentProperties>({ value: loc.readHeader, CSSStyles: { ...cssStyles.permissionsTableHeaderCss } }).component();
|
||||
headerRowContainer.addItem(accessReadCell, { CSSStyles: { 'width': `${permissionsReadColumnWidth}px`, 'min-width': `${permissionsReadColumnWidth}px` } });
|
||||
const accessWriteCell = modelBuilder.text().withProperties<azdata.TextComponentProperties>({ value: loc.writeHeader, CSSStyles: { ...cssStyles.permissionsTableHeaderCss } }).component();
|
||||
headerRowContainer.addItem(accessWriteCell, { CSSStyles: { 'width': `${permissionsWriteColumnWidth}px`, 'min-width': `${permissionsWriteColumnWidth}px` } });
|
||||
const accessExecuteCell = modelBuilder.text().withProperties<azdata.TextComponentProperties>({ value: loc.executeHeader, CSSStyles: { ...cssStyles.permissionsTableHeaderCss } }).component();
|
||||
headerRowContainer.addItem(accessExecuteCell, { CSSStyles: { 'width': `${permissionsExecuteColumnWidth}px`, 'min-width': `${permissionsExecuteColumnWidth}px`, 'margin-right': '5px' } });
|
||||
// Default Permissions Group
|
||||
const defaultPermissionsHeadersContainer = modelBuilder.flexContainer().withLayout({ flexFlow: 'row' }).component();
|
||||
if (includeInherit) {
|
||||
const inheritCell = modelBuilder.text().withProperties<azdata.TextComponentProperties>({ value: loc.inheritDefaultsLabel, CSSStyles: { ...cssStyles.permissionsTableHeaderCss } }).component();
|
||||
defaultPermissionsHeadersContainer.addItem(inheritCell, { CSSStyles: { 'width': `${permissionsInheritColumnWidth}px`, 'min-width': `${permissionsInheritColumnWidth}px` } });
|
||||
}
|
||||
const defaultReadCell = modelBuilder.text().withProperties<azdata.TextComponentProperties>({ value: loc.readHeader, CSSStyles: { ...cssStyles.permissionsTableHeaderCss } }).component();
|
||||
defaultPermissionsHeadersContainer.addItem(defaultReadCell, { CSSStyles: { 'width': `${permissionsReadColumnWidth}px`, 'min-width': `${permissionsReadColumnWidth}px` } });
|
||||
const defaultWriteCell = modelBuilder.text().withProperties<azdata.TextComponentProperties>({ value: loc.writeHeader, CSSStyles: { ...cssStyles.permissionsTableHeaderCss } }).component();
|
||||
defaultPermissionsHeadersContainer.addItem(defaultWriteCell, { CSSStyles: { 'width': `${permissionsWriteColumnWidth}px`, 'min-width': `${permissionsWriteColumnWidth}px` } });
|
||||
const defaultExecuteCell = modelBuilder.text().withProperties<azdata.TextComponentProperties>({ value: loc.executeHeader, CSSStyles: { ...cssStyles.permissionsTableHeaderCss } }).component();
|
||||
defaultPermissionsHeadersContainer.addItem(defaultExecuteCell, { CSSStyles: { 'width': `${permissionsExecuteColumnWidth}px`, 'min-width': `${permissionsExecuteColumnWidth}px` } });
|
||||
headerRowContainer.addItem(defaultPermissionsHeadersContainer, { flex: '0 0 auto' });
|
||||
this.defaultSectionComponents.push(defaultPermissionsHeadersContainer);
|
||||
|
||||
// Delete
|
||||
const deleteCell = modelBuilder.text().component();
|
||||
headerRowContainer.addItem(deleteCell, { CSSStyles: { 'width': `${permissionsDeleteColumnWidth}px`, 'min-width': `${permissionsDeleteColumnWidth}px` } });
|
||||
|
||||
rowsContainer.addItem(headerRowContainer);
|
||||
|
||||
return rowsContainer;
|
||||
return sectionHeaderContainer;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a checkbox to be hosted inside of a table cell
|
||||
* @param builder The ModelBuilder used to create the components
|
||||
* @param checked Whether the checkbox is initially checked or not
|
||||
* @param enabled Whether the checkbox is initially enabled or not
|
||||
* @param containerWidth The width of the container holding the checkbox
|
||||
* @param containerHeight The height of the container holding the checkbox
|
||||
* @param ariaLabel The aria label to apply to the checkbox
|
||||
*/
|
||||
function createCheckbox(builder: azdata.ModelBuilder, checked: boolean, enabled: boolean, containerWidth: number, containerHeight: number, ariaLabel: string): { container: azdata.FlexContainer, checkbox: azdata.CheckBoxComponent } {
|
||||
const checkbox = builder.checkBox()
|
||||
.withProperties<azdata.CheckBoxProperties>({
|
||||
@@ -556,5 +611,4 @@ function createCheckbox(builder: azdata.ModelBuilder, checked: boolean, enabled:
|
||||
container: container,
|
||||
checkbox: checkbox
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -9,7 +9,5 @@ export namespace cssStyles {
|
||||
export const tableHeaderCss = { 'font-weight': 'bold', 'text-transform': 'uppercase', 'font-size': '10px', 'user-select': 'text' };
|
||||
export const permissionsTableHeaderCss = { ...tableHeaderCss, 'text-align': 'center' };
|
||||
export const permissionCheckboxCss = { 'margin-top': '5px', 'margin-left': '13px' };
|
||||
// The Named users/groups section potentially has a scrollbar so we shift all the other parts over so the columns still align correctly
|
||||
export const scrollbarMarginGapCss = { 'margin-right': '17px' };
|
||||
export const tableHeaderLayoutCss = { 'padding-left': '10px', 'box-sizing': 'border-box', 'user-select': 'text', ...cssStyles.scrollbarMarginGapCss };
|
||||
export const tableHeaderLayoutCss = { 'padding-left': '10px', 'box-sizing': 'border-box', 'user-select': 'text', 'margin-right': '12px' };
|
||||
}
|
||||
|
||||
@@ -15,6 +15,8 @@ export const manageAccessTitle = localize('mssql.manageAccessTitle', "Manage Acc
|
||||
export const locationTitle = localize('mssql.locationTitle', "Location : ");
|
||||
export const permissionsHeader = localize('mssql.permissionsTitle', "Permissions");
|
||||
export const ownerPostfix = localize('mssql.ownerPostfix', " - Owner");
|
||||
export const owner = localize('mssql.owner', "Owner");
|
||||
export const group = localize('mssql.group', "Group");
|
||||
export const owningGroupPostfix = localize('mssql.owningGroupPostfix', " - Owning Group");
|
||||
export const everyoneName = localize('mssql.everyone', "Everyone else");
|
||||
export const userLabel = localize('mssql.userLabel', "User");
|
||||
@@ -31,6 +33,8 @@ export const addUserOrGroupHeader = localize('mssql.addUserOrGroup', "Add User o
|
||||
export const enterNamePlaceholder = localize('mssql.enterNamePlaceholder', "Enter name");
|
||||
export const addLabel = localize('mssql.addLabel', "Add");
|
||||
export const namedUsersAndGroupsHeader = localize('mssql.namedUsersAndGroups', "Named Users and Groups");
|
||||
export const defaultUserAndGroups = localize('mssql.defaultUserAndGroups', "Default User and Groups");
|
||||
export const userOrGroupIcon = localize('mssql.userOrGroupIcon', "User or Group Icon");
|
||||
export const applyText = localize('mssql.apply', "Apply");
|
||||
export const applyRecursivelyText = localize('mssql.applyRecursively', "Apply Recursively");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user