592 lines
14 KiB
JavaScript
592 lines
14 KiB
JavaScript
// Copyright 2021 99cloud
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
import { get } from 'lodash';
|
|
import { action, observable } from 'mobx';
|
|
import client from 'client';
|
|
import List from './base-list';
|
|
import globalProjectMapStore from './project';
|
|
import globalRootStore from './root';
|
|
|
|
export default class BaseStore {
|
|
list = new List();
|
|
|
|
@observable
|
|
detail = {};
|
|
|
|
@observable
|
|
isLoading = true;
|
|
|
|
@observable
|
|
isSubmitting = false;
|
|
|
|
get client() {
|
|
return {};
|
|
}
|
|
|
|
get skylineClient() {
|
|
return client.skyline;
|
|
}
|
|
|
|
get responseKey() {
|
|
return this.client.responseKey;
|
|
}
|
|
|
|
get listResponseKey() {
|
|
return `${this.responseKey}s`;
|
|
}
|
|
|
|
get needGetProject() {
|
|
return true;
|
|
}
|
|
|
|
get currentUser() {
|
|
return globalRootStore.user || {};
|
|
}
|
|
|
|
get currentProjectId() {
|
|
return globalRootStore.projectId;
|
|
}
|
|
|
|
get hasAdminRole() {
|
|
return globalRootStore.hasAdminRole;
|
|
}
|
|
|
|
get enableBilling() {
|
|
return globalRootStore.enableBilling;
|
|
}
|
|
|
|
get mapper() {
|
|
// update response items;
|
|
return (data) => data;
|
|
// return ObjectMapper[this.module] || (data => data);
|
|
}
|
|
|
|
get mapperBeforeFetchProject() {
|
|
return (data) => data;
|
|
}
|
|
|
|
get filterByApi() {
|
|
return false;
|
|
}
|
|
|
|
get paramsFunc() {
|
|
if (this.filterByApi) {
|
|
return (params) => params;
|
|
}
|
|
return (params) => {
|
|
const reservedKeys = [
|
|
'all_data',
|
|
'all_projects',
|
|
'device_id',
|
|
'network_id',
|
|
'floating_network_id',
|
|
'start_at_gt',
|
|
'start_at_lt',
|
|
'binary',
|
|
'fixed_ip_address',
|
|
'device_owner',
|
|
'project_id',
|
|
'type',
|
|
'sort',
|
|
'security_group_id',
|
|
'id',
|
|
'security_group_id',
|
|
'owner_id',
|
|
'status',
|
|
'fingerprint',
|
|
'resource_types',
|
|
'floating_ip_address',
|
|
'uuid',
|
|
'loadbalancer_id',
|
|
'ikepolicy_id',
|
|
'ipsecpolicy_id',
|
|
'endpoint_id',
|
|
'peer_ep_group_id',
|
|
'local_ep_group_id',
|
|
'vpnservice_id',
|
|
];
|
|
const newParams = {};
|
|
Object.keys(params).forEach((key) => {
|
|
if (reservedKeys.indexOf(key) >= 0) {
|
|
newParams[key] = params[key];
|
|
}
|
|
});
|
|
return newParams;
|
|
};
|
|
}
|
|
|
|
get paramsFuncPage() {
|
|
return (params) => {
|
|
const { current, withPrice, ...rest } = params;
|
|
return rest;
|
|
};
|
|
}
|
|
|
|
get listFilterByProject() {
|
|
// use it for nuetron apois
|
|
return false;
|
|
}
|
|
|
|
get fetchListByLimit() {
|
|
return false;
|
|
}
|
|
|
|
get markerKey() {
|
|
return 'id';
|
|
}
|
|
|
|
get listWithDetail() {
|
|
return false;
|
|
}
|
|
|
|
get isSubResource() {
|
|
return false;
|
|
}
|
|
|
|
getFatherResourceId = (params) => params.id;
|
|
|
|
detailFetchByClient(resourceParams, params) {
|
|
const { id } = resourceParams;
|
|
if (!this.isSubResource) {
|
|
return this.client.show(id, params);
|
|
}
|
|
const fatherId = this.getFatherResourceId(resourceParams);
|
|
return this.client.show(fatherId, id, params);
|
|
}
|
|
|
|
listFetchByClient(params, originParams) {
|
|
if (!this.isSubResource) {
|
|
return this.listWithDetail
|
|
? this.client.listDetail(params)
|
|
: this.client.list(params);
|
|
}
|
|
const fatherId = this.getFatherResourceId(originParams);
|
|
return this.client.list(fatherId, params);
|
|
}
|
|
|
|
getItemProjectId(item) {
|
|
return (
|
|
item.project_id ||
|
|
item.tenant_id ||
|
|
item.owner ||
|
|
item.owner_id ||
|
|
item.tenant ||
|
|
item.fingerprint
|
|
);
|
|
}
|
|
|
|
itemInCurrentProject = (item, all_projects) => {
|
|
// use for neutron resource in admin project
|
|
if (all_projects) {
|
|
return true;
|
|
}
|
|
const itemProject = globalProjectMapStore.getItemProjectId(item);
|
|
const { shared, visibility, is_public } = item;
|
|
return (
|
|
itemProject === this.currentProjectId ||
|
|
is_public ||
|
|
shared ||
|
|
visibility === 'public'
|
|
);
|
|
};
|
|
|
|
@action
|
|
setModule(module) {
|
|
this.module = module;
|
|
}
|
|
|
|
@action
|
|
submitting = (promise) => {
|
|
this.isSubmitting = true;
|
|
|
|
setTimeout(() => {
|
|
promise
|
|
.catch(() => {})
|
|
.finally(() => {
|
|
this.isSubmitting = false;
|
|
});
|
|
}, 500);
|
|
|
|
return promise;
|
|
};
|
|
|
|
// eslint-disable-next-line no-unused-vars
|
|
async listDidFetch(items, allProjects, filters) {
|
|
return items;
|
|
}
|
|
|
|
// eslint-disable-next-line no-unused-vars
|
|
async detailDidFetch(item, all_projects, params) {
|
|
return item;
|
|
}
|
|
|
|
async listDidFetchProject(items, all_projects) {
|
|
if (!this.needGetProject) {
|
|
return items;
|
|
}
|
|
if (!all_projects || !this.hasAdminRole) {
|
|
return items;
|
|
}
|
|
const projectIds = [];
|
|
items.forEach((item) => {
|
|
const projectId = globalProjectMapStore.getItemProjectId(item);
|
|
const projectName = globalProjectMapStore.getItemProjectName(item);
|
|
if (!projectName && projectId && projectIds.indexOf(projectId) < 0) {
|
|
projectIds.push(projectId);
|
|
}
|
|
});
|
|
if (projectIds.length === 0) {
|
|
return items;
|
|
}
|
|
try {
|
|
const results = await Promise.all(
|
|
projectIds.map((id) => globalProjectMapStore.fetchProjectDetail({ id }))
|
|
);
|
|
items.forEach((item) => {
|
|
const projectId = globalProjectMapStore.getItemProjectId(item);
|
|
if (projectId && projectIds.indexOf(projectId) >= 0) {
|
|
const project = results.find((it) => it.id === projectId);
|
|
item.project_name = project ? project.name || '-' : '-';
|
|
}
|
|
});
|
|
} catch (e) {
|
|
return items;
|
|
}
|
|
|
|
return items;
|
|
}
|
|
|
|
updateMarkerParams = (limit, marker) => {
|
|
return {
|
|
limit,
|
|
marker,
|
|
};
|
|
};
|
|
|
|
async requestListByMarker(params, limit, marker) {
|
|
const markerParams = this.updateMarkerParams(limit, marker);
|
|
const newParams = {
|
|
...params,
|
|
...markerParams,
|
|
};
|
|
return this.listFetchByClient(newParams);
|
|
}
|
|
|
|
async requestListAllByLimit(params, limit) {
|
|
let marker = '';
|
|
let hasNext = true;
|
|
let datas = [];
|
|
while (hasNext) {
|
|
// eslint-disable-next-line no-await-in-loop
|
|
const result = await this.requestListByMarker(params, limit, marker);
|
|
const data = this.getListDataFromResult(result);
|
|
datas = [...datas, ...data];
|
|
if (data.length >= limit) {
|
|
marker = this.parseMarker(data, result, datas);
|
|
if (!marker) {
|
|
// eslint-disable-next-line no-console
|
|
console.log('parse marker error!');
|
|
hasNext = false;
|
|
}
|
|
} else {
|
|
hasNext = false;
|
|
}
|
|
}
|
|
return datas;
|
|
}
|
|
|
|
async requestListAll(params, originParams) {
|
|
const result = await this.listFetchByClient(params, originParams);
|
|
return this.getListDataFromResult(result);
|
|
}
|
|
|
|
async requestList(params, originParams) {
|
|
const datas = !this.fetchListByLimit
|
|
? await this.requestListAll(params, originParams)
|
|
: await this.requestListAllByLimit(params, 100);
|
|
return datas;
|
|
}
|
|
|
|
// eslint-disable-next-line no-unused-vars
|
|
async requestListByPage(params, page, originParams) {
|
|
const datas = await this.listFetchByClient(params, originParams);
|
|
return datas;
|
|
}
|
|
|
|
// eslint-disable-next-line no-unused-vars
|
|
updateUrl = (url, params) => url;
|
|
|
|
// eslint-disable-next-line no-unused-vars
|
|
updateParamsSortPage = (params, sortKey, sortOrder) => {};
|
|
|
|
// eslint-disable-next-line no-unused-vars
|
|
updateParamsSort = (params, sortKey, sortOrder) => {};
|
|
|
|
@action
|
|
async pureFetchList({
|
|
limit,
|
|
page,
|
|
sortKey,
|
|
sortOrder,
|
|
conditions,
|
|
timeFilter,
|
|
...filters
|
|
} = {}) {
|
|
// todo: no page, no limit, fetch all
|
|
const { tab, all_projects, ...rest } = filters;
|
|
const params = { ...rest };
|
|
if (all_projects) {
|
|
if (!this.listFilterByProject) {
|
|
params.all_projects = true;
|
|
}
|
|
}
|
|
const allData = await this.requestList(params, {});
|
|
return allData;
|
|
}
|
|
|
|
@action
|
|
async fetchList({
|
|
limit,
|
|
page,
|
|
sortKey,
|
|
sortOrder,
|
|
conditions,
|
|
timeFilter,
|
|
...filters
|
|
} = {}) {
|
|
this.list.isLoading = true;
|
|
// todo: no page, no limit, fetch all
|
|
const { tab, all_projects, ...rest } = filters;
|
|
const params = { ...rest };
|
|
if (all_projects) {
|
|
if (!this.listFilterByProject) {
|
|
params.all_projects = true;
|
|
}
|
|
}
|
|
const newParams = this.paramsFunc(params);
|
|
const allData = await this.requestList(newParams, filters);
|
|
const allDataNew = allData.map((it) =>
|
|
this.mapperBeforeFetchProject(it, filters)
|
|
);
|
|
const data = allDataNew.filter((item) => {
|
|
if (!this.listFilterByProject) {
|
|
return true;
|
|
}
|
|
return this.itemInCurrentProject(item, all_projects);
|
|
});
|
|
// const items = data.map(this.mapper);
|
|
let newData = await this.listDidFetchProject(data, all_projects);
|
|
try {
|
|
newData = await this.listDidFetch(newData, all_projects, filters);
|
|
} catch (e) {
|
|
// eslint-disable-next-line no-console
|
|
console.log(e);
|
|
}
|
|
newData = newData.map(this.mapper);
|
|
this.list.update({
|
|
data: newData,
|
|
total: newData.length || 0,
|
|
limit: Number(limit) || 10,
|
|
page: Number(page) || 1,
|
|
sortKey,
|
|
sortOrder,
|
|
filters,
|
|
timeFilter,
|
|
isLoading: false,
|
|
...(this.list.silent ? {} : { selectedRowKeys: [] }),
|
|
});
|
|
|
|
return newData;
|
|
}
|
|
|
|
// eslint-disable-next-line no-unused-vars
|
|
parseMarker(datas, result, allDatas) {
|
|
return datas.length === 0
|
|
? ''
|
|
: get(datas[datas.length - 1], this.markerKey);
|
|
}
|
|
|
|
@action
|
|
updateMarker(datas, page, result, allDatas) {
|
|
const marker = this.parseMarker(datas, result, allDatas);
|
|
if (page === 1) {
|
|
this.list.markers = [marker];
|
|
} else {
|
|
this.list.markers[page - 1] = marker;
|
|
}
|
|
}
|
|
|
|
getMarker(page) {
|
|
return page === 1 ? '' : this.list.markers[page - 2];
|
|
}
|
|
|
|
getDetailParams = () => undefined;
|
|
|
|
getListDataFromResult = (result) =>
|
|
this.listResponseKey ? get(result, this.listResponseKey, []) : result;
|
|
|
|
// eslint-disable-next-line no-unused-vars
|
|
async getCountForPage(newParams, all_projects, newDatas) {
|
|
return {};
|
|
}
|
|
|
|
// eslint-disable-next-line no-unused-vars
|
|
getOtherInfo = (result) => {};
|
|
|
|
@action
|
|
async fetchListByPage({
|
|
limit = 10,
|
|
page = 1,
|
|
sortKey,
|
|
sortOrder,
|
|
conditions,
|
|
timeFilter,
|
|
...filters
|
|
} = {}) {
|
|
this.list.isLoading = true;
|
|
// todo: no page, no limit, fetch all
|
|
const { tab, all_projects, ...rest } = filters;
|
|
const params = { limit, ...rest };
|
|
this.updateParamsSortPage(params, sortKey, sortOrder);
|
|
if (all_projects) {
|
|
if (!this.listFilterByProject) {
|
|
params.all_projects = true;
|
|
}
|
|
}
|
|
|
|
const marker = this.getMarker(page);
|
|
if (marker) {
|
|
params.marker = marker;
|
|
}
|
|
const newParams = this.paramsFuncPage(params, all_projects);
|
|
const result = await this.requestListByPage(newParams, page, filters);
|
|
const allData = this.getListDataFromResult(result);
|
|
this.updateMarker(allData, page, result, allData);
|
|
const allDataNew = allData.map(this.mapperBeforeFetchProject);
|
|
let newData = await this.listDidFetchProject(allDataNew, all_projects);
|
|
newData = await this.listDidFetch(newData, all_projects, filters);
|
|
newData = newData.map(this.mapper);
|
|
let count;
|
|
let total;
|
|
if (result.count || result.total) {
|
|
count = result.count || result.total;
|
|
} else {
|
|
const totalResult = await this.getCountForPage(
|
|
newParams,
|
|
newData,
|
|
all_projects,
|
|
result,
|
|
params
|
|
);
|
|
const { count: retCount, total: retTotal } = totalResult;
|
|
count = retCount;
|
|
total = retTotal;
|
|
}
|
|
const others = this.getOtherInfo(result);
|
|
this.list.update({
|
|
data: newData,
|
|
limit: Number(limit) || 10,
|
|
page: Number(page) || 1,
|
|
sortKey,
|
|
sortOrder,
|
|
filters,
|
|
timeFilter,
|
|
isLoading: false,
|
|
total: count || total,
|
|
...(this.list.silent ? {} : { selectedRowKeys: [] }),
|
|
...others,
|
|
});
|
|
|
|
return newData;
|
|
}
|
|
|
|
@action
|
|
async fetchDetail({ all_projects, silent, ...rest }) {
|
|
if (!silent) {
|
|
this.isLoading = true;
|
|
}
|
|
const result = await this.detailFetchByClient(
|
|
rest,
|
|
this.getDetailParams({ all_projects })
|
|
);
|
|
const originData = get(result, this.responseKey) || result;
|
|
const item = this.mapperBeforeFetchProject(originData, rest, true);
|
|
try {
|
|
const newItem = await this.detailDidFetch(item, all_projects, rest);
|
|
const detail = this.mapper(newItem);
|
|
this.detail = detail;
|
|
} catch (e) {
|
|
// eslint-disable-next-line no-console
|
|
console.log(e);
|
|
this.detail = item;
|
|
}
|
|
this.isLoading = false;
|
|
return this.detail;
|
|
}
|
|
|
|
@action
|
|
setSelectRowKeys(key, selectedRowKeys) {
|
|
this[key] && this[key].selectedRowKeys.replace(selectedRowKeys);
|
|
}
|
|
|
|
@action
|
|
create(data) {
|
|
const body = {};
|
|
body[this.responseKey] = data;
|
|
return this.submitting(this.client.create(body));
|
|
}
|
|
|
|
@action
|
|
edit({ id }, newObject) {
|
|
const body = {};
|
|
body[this.responseKey] = newObject;
|
|
return this.submitting(this.client.update(id, body));
|
|
}
|
|
|
|
@action
|
|
update({ id }, newObject) {
|
|
const body = {};
|
|
body[this.responseKey] = newObject;
|
|
return this.submitting(this.client.update(id, body));
|
|
}
|
|
|
|
@action
|
|
patch({ id }, newObject) {
|
|
return this.submitting(this.client.patch(id, newObject));
|
|
}
|
|
|
|
@action
|
|
delete = ({ id }) => this.submitting(this.client.delete(id));
|
|
|
|
@action
|
|
batchDelete(rowKeys) {
|
|
return this.submitting(
|
|
Promise.all(
|
|
rowKeys.map((name) => {
|
|
const item = this.list.data.find((_item) => _item.name === name);
|
|
const { id } = item;
|
|
return this.client.delete(id);
|
|
})
|
|
)
|
|
);
|
|
}
|
|
|
|
@action
|
|
clearData() {
|
|
this.list.reset();
|
|
this.detail = {};
|
|
}
|
|
}
|