feat: Update share actions && fetch

1. Add public policy check when create public share
2. Add public policy check when edit share
3. Disable actions for public share that do not belong to you
4. Remove update-time info from share detail page
5. Remove update-time info from share group detail page
6. Fix share api fetch: add is_public=true to fetch all data
7. Support share api fetch sorter
8. Support share group api fetch sorter

Change-Id: I737747086900626872df3e566f6e4f21c48893f2
This commit is contained in:
Jingwei.Zhang 2022-05-17 13:22:30 +08:00
parent 020defa50b
commit 3643ca912c
17 changed files with 133 additions and 56 deletions

View File

@ -17,7 +17,8 @@ import { ModalAction } from 'containers/Action';
import globalShareAccessRuleStore from 'stores/manila/share-access-rule';
import { keyValueValidator } from 'pages/share/containers/ShareType/actions/Create';
import KeyValueInput from 'components/FormItem/KeyValueInput';
import { updateAddSelectValueToObj } from 'utils/index';
import { updateAddSelectValueToObj, getOptions } from 'utils/index';
import { shareAccessLevel, shareAccessType } from 'resources/manila/share';
export const metadataFormItem = {
name: 'metadata',
@ -55,37 +56,11 @@ export class Create extends ModalAction {
static allowed = () => Promise.resolve(true);
get typeOptions() {
return [
{
value: 'ip',
label: t('IP'),
},
{
value: 'cert',
label: t('Cert'),
},
{
value: 'user',
label: t('User'),
},
{
value: 'cephx',
label: t('Cephx'),
},
];
return getOptions(shareAccessType);
}
get levelOptions() {
return [
{
value: 'rw',
label: t('Read and write'),
},
{
value: 'ro',
label: t('Read only'),
},
];
return getOptions(shareAccessLevel);
}
get defaultValue() {

View File

@ -15,7 +15,8 @@
import { observer, inject } from 'mobx-react';
import Base from 'containers/List';
import globalShareAccessRuleStore from 'stores/manila/share-access-rule';
import { shareAccessRuleState } from 'resources/manila/share';
import { shareAccessRuleState, shareAccessLevel } from 'resources/manila/share';
import { emptyActionConfig } from 'utils/constants';
import actionConfigs from './actions';
export class ShareAccessRule extends Base {
@ -32,9 +33,14 @@ export class ShareAccessRule extends Base {
}
get actionConfigs() {
return this.isAdminPage
? actionConfigs.actionConfigsAdmin
: actionConfigs.actionConfigs;
if (this.isAdminPage) {
return actionConfigs.actionConfigsAdmin;
}
const { detail: { isMine } = {} } = this.props;
if (isMine) {
return actionConfigs.actionConfigs;
}
return emptyActionConfig;
}
getColumns = () => [
@ -53,6 +59,7 @@ export class ShareAccessRule extends Base {
{
title: t('Access Level'),
dataIndex: 'access_level',
render: (value) => shareAccessLevel[value] || value,
},
{
title: t('State'),

View File

@ -15,6 +15,7 @@
import { observer, inject } from 'mobx-react';
import Base from 'containers/List';
import { ShareMetadataStore } from 'stores/manila/share-metadata';
import { emptyActionConfig } from 'utils/constants';
import actionConfigs from './actions';
export class Metadata extends Base {
@ -42,9 +43,14 @@ export class Metadata extends Base {
];
get actionConfigs() {
return this.isAdminPage
? actionConfigs.actionConfigsAdmin
: actionConfigs.actionConfigs;
if (this.isAdminPage) {
return actionConfigs.actionConfigsAdmin;
}
const { detail: { isMine } = {} } = this.props;
if (isMine) {
return actionConfigs.actionConfigs;
}
return emptyActionConfig;
}
get searchFilters() {

View File

@ -60,11 +60,6 @@ export class Detail extends Base {
dataIndex: 'created_at',
valueRender: 'toLocalTime',
},
{
title: t('Updated'),
dataIndex: 'updated_at',
valueRender: 'toLocalTime',
},
];
}

View File

@ -38,6 +38,7 @@ import { cloneDeep } from 'lodash';
import { idNameColumn } from 'utils/table';
import { extraFormItem } from 'pages/share/containers/ShareType/actions/Create';
import { updateAddSelectValueToObj, getOptions } from 'utils/index';
import { checkPolicyRule } from 'resources/skyline/policy';
export class Create extends FormAction {
static id = 'create';
@ -135,6 +136,14 @@ export class Create extends FormAction {
return [idNameColumn, ...rest];
}
get shareProtocolOptions() {
return getOptions(shareProtocol);
}
checkShowPublic() {
return checkPolicyRule('manila:share:create_public_share');
}
get formItems() {
const { showNetworks = false, shareGroups = [] } = this.state;
const minSize = 1;
@ -175,7 +184,7 @@ export class Create extends FormAction {
label: t('Share Protocol'),
type: 'select',
required: true,
options: getOptions(shareProtocol),
options: this.shareProtocolOptions,
},
{
name: 'size',
@ -183,7 +192,7 @@ export class Create extends FormAction {
type: 'slider-input',
max: this.maxSize,
min: minSize,
description: `${minSize}GB-${this.maxSize}GB`,
description: `${minSize}GiB-${this.maxSize}GiB`,
required: this.quotaIsLimit,
display: this.quotaIsLimit,
},
@ -201,6 +210,7 @@ export class Create extends FormAction {
type: 'check',
content: t('Public'),
tip: t('If set then all tenants will be able to see this share.'),
display: this.checkShowPublic(),
},
{
name: 'shareType',
@ -246,14 +256,24 @@ export class Create extends FormAction {
}
onSubmit = (values) => {
const { shareType, shareNetwork, shareGroup, project, metadata, ...rest } =
values;
const {
shareType,
shareNetwork,
shareGroup,
project,
metadata,
is_public,
...rest
} = values;
const { showNetworks = false } = this.state;
const body = {
...rest,
share_type: shareType.selectedRowKeys[0],
metadata: updateAddSelectValueToObj(metadata),
};
if (this.checkShowPublic() && is_public) {
body.is_public = is_public;
}
const { selectedRowKeys: networkKeys = [] } = shareNetwork || {};
const { selectedRowKeys: groupKeys = [] } = shareGroup || {};
if (showNetworks && networkKeys.length) {

View File

@ -38,5 +38,9 @@ export default class Delete extends ConfirmAction {
policy = 'manila:share:delete';
allowedCheckFunc = (item) => {
return this.isAdminPage || item.isMine;
};
onSubmit = (data) => globalShareStore.delete(data);
}

View File

@ -15,6 +15,7 @@
import { inject, observer } from 'mobx-react';
import { ModalAction } from 'containers/Action';
import globalShareStore from 'stores/manila/share';
import { checkPolicyRule } from 'resources/skyline/policy';
export class Edit extends ModalAction {
static id = 'edit';
@ -33,7 +34,11 @@ export class Edit extends ModalAction {
static policy = 'manila:share:update';
static allowed = () => Promise.resolve(true);
static allowed = (item) => Promise.resolve(item.isMine);
checkShowPublic() {
return checkPolicyRule('manila:share:set_public_share');
}
get formItems() {
return [
@ -54,6 +59,7 @@ export class Edit extends ModalAction {
type: 'check',
content: t('Public'),
tip: t('If set then all tenants will be able to see this share.'),
display: this.checkShowPublic(),
},
];
}
@ -64,7 +70,14 @@ export class Edit extends ModalAction {
onSubmit = (values) => {
const { id } = this.item;
return this.store.update(id, values);
const { is_public, ...rest } = values;
const body = {
...rest,
};
if (this.checkShowPublic()) {
body.is_public = is_public;
}
return this.store.update(id, body);
};
}

View File

@ -36,7 +36,7 @@ export class ExtendShare extends ModalAction {
static policy = 'manila:share:extend';
static allowed = () => Promise.resolve(true);
static allowed = (item) => Promise.resolve(item.isMine);
get tips() {
return t('After the share is expanded, the share cannot be reduced.');

View File

@ -38,7 +38,7 @@ export class ManageAccessRule extends FormAction {
static policy = 'manila:share_access_rule:index';
static allowed = () => Promise.resolve(true);
static allowed = (item) => Promise.resolve(item.isMine);
}
export default inject('rootStore')(observer(ManageAccessRule));

View File

@ -38,7 +38,7 @@ export class ManageMetadata extends FormAction {
static policy = 'manila:share:update_share_metadata';
static allowed = () => Promise.resolve(true);
static allowed = (item) => Promise.resolve(item.isMine);
}
export default inject('rootStore')(observer(ManageMetadata));

View File

@ -20,7 +20,7 @@ import actionConfigs from './actions';
export class Share extends Base {
init() {
this.store = globalShareStore;
this.store = this.inDetailPage ? new ShareStore() : globalShareStore;
this.downloadStore = new ShareStore();
}
@ -56,6 +56,14 @@ export class Share extends Base {
return this.inDetailPage && pathname.includes('share-server');
}
get isSortByBackend() {
return true;
}
get defaultSortKey() {
return 'created_at';
}
updateFetchParamsByPage = (params) => {
const { id, ...rest } = params;
const newParams = { ...rest };
@ -92,20 +100,24 @@ export class Share extends Base {
dataIndex: 'project_name',
isHideable: true,
hidden: !this.isAdminPage,
sortKey: 'project_id',
},
{
title: t('Description'),
dataIndex: 'description',
isHideable: true,
sorter: false,
},
{
title: t('Availability Zone'),
dataIndex: 'availability_zone',
sorter: false,
},
{
title: t('Share Type'),
dataIndex: 'share_type_name',
render: (value, record) => value || record.share_type,
sortKey: 'share_type_id',
},
{
title: t('Size'),
@ -122,6 +134,7 @@ export class Share extends Base {
dataIndex: 'is_public',
isHideable: true,
valueRender: 'yesNo',
sorter: false,
},
{
title: t('Status'),
@ -155,6 +168,7 @@ export class Share extends Base {
});
return link;
},
// sorter: false,
},
{
title: t('Created At'),

View File

@ -59,11 +59,6 @@ export class Detail extends Base {
dataIndex: 'created_at',
valueRender: 'toLocalTime',
},
{
title: t('Updated'),
dataIndex: 'updated_at',
valueRender: 'toLocalTime',
},
];
}

View File

@ -41,6 +41,14 @@ export class ShareGroup extends Base {
return true;
}
get isSortByBackend() {
return true;
}
get defaultSortKey() {
return 'created_at';
}
get actionConfigs() {
return this.isAdminPage
? actionConfigs.actionConfigsAdmin

View File

@ -17,15 +17,18 @@ export const getShareGroupColumns = (self) => {
dataIndex: 'project_name',
isHideable: true,
hidden: !self.isAdminPage,
sortKey: 'project_id',
},
{
title: t('Description'),
dataIndex: 'description',
isHideable: true,
sorter: false,
},
{
title: t('Availability Zone'),
dataIndex: 'availability_zone',
sorter: false,
},
{
title: t('Share Network'),

View File

@ -60,3 +60,15 @@ export const shareAccessRuleState = {
denying: t('Denying'),
applying: t('Applying'),
};
export const shareAccessLevel = {
rw: t('Read and write'),
ro: t('Read only'),
};
export const shareAccessType = {
ip: t('IP'),
cert: t('Cert'),
user: t('User'),
cephx: t('Cephx'),
};

View File

@ -37,6 +37,13 @@ export class ShareGroupStore extends Base {
};
}
updateParamsSortPage = (params, sortKey, sortOrder) => {
if (sortKey && sortOrder) {
params.sort_key = sortKey;
params.sort_dir = sortOrder === 'descend' ? 'desc' : 'asc';
}
};
async detailDidFetch(item, all_projects) {
const { share_network_id, share_group_type_id, share_types } = item;
const shareGroupType = await new ShareGroupTypeStore().fetchDetail({

View File

@ -73,10 +73,28 @@ export class ShareStore extends Base {
all_tenants: all_projects ? 1 : 0,
offset: marker,
limit,
is_public: true,
};
};
}
get mapper() {
return (data) => {
const { project_id } = data;
return {
...data,
isMine: project_id === this.currentProjectId,
};
};
}
updateParamsSortPage = (params, sortKey, sortOrder) => {
if (sortKey && sortOrder) {
params.sort_key = sortKey;
params.sort_dir = sortOrder === 'descend' ? 'desc' : 'asc';
}
};
@action
async fetchAvailableZones() {
const { availability_zones: zones = [] } = await this.zoneClient.list();