tachybase_todo/packages/client/src/resource.ts
chenos c1b560e928
feat: rename resourceKey & associatedKey to resourceIndex & associatedIndex (#126)
* resourceIndex & associatedIndex

* resourceIndex & associatedIndex
2021-12-04 16:28:52 +08:00

199 lines
5.1 KiB
TypeScript

import { RequestMethod } from 'umi-request';
import { request as req } from './schemas';
export interface ResourceOptions {
resourceName: string;
associatedIndex?: any;
associatedName?: string;
resourceIndex?: any;
}
export interface GetOptions {
resourceIndex?: any;
defaultAppends?: any[];
appends?: string[];
}
export interface SaveOptions {
resourceIndex?: any;
}
export interface ListOptions {
defaultFilter?: any;
filter?: any;
pageSize?: number;
defaultAppends?: any[];
appends?: string[];
perPage?: number;
}
export class Resource {
public options: ResourceOptions;
public request: RequestMethod;
constructor(options: string | ResourceOptions, request?: any) {
if (typeof options === 'string') {
this.options = { resourceName: options };
} else {
this.options = options;
}
this.request = request || req;
}
sort(options) {
const { resourceName } = this.options;
const { resourceIndex, target, field = 'sort' } = options;
return this.request(`${resourceName}:sort/${resourceIndex}`, {
method: 'post',
data: {
target,
field,
},
});
}
list(options: ListOptions = {}) {
const {
defaultAppends = [],
appends = [],
defaultFilter,
filter,
pageSize,
...others
} = options;
const { associatedIndex, associatedName, resourceName } = this.options;
let url = `${resourceName}:list`;
if (associatedName && associatedIndex) {
url = `${associatedName}/${associatedIndex}/${resourceName}:list`;
}
return this.request(url, {
method: 'get',
params: {
filter: decodeURIComponent(
JSON.stringify({ and: [defaultFilter, filter].filter(Boolean) }),
),
'fields[appends]': defaultAppends.concat(appends).join(','),
perPage: pageSize,
...others,
},
});
}
get(options: GetOptions = {}) {
const resourceIndex = options.resourceIndex || this.options.resourceIndex;
const { resourceName } = this.options;
if (!resourceIndex) {
return Promise.resolve({ data: {} });
}
const { defaultAppends = [], appends = [], ...others } = options;
return this.request(`${resourceName}:get/${resourceIndex}`, {
params: {
...others,
'fields[appends]': defaultAppends.concat(appends).join(','),
},
});
}
create(values: any) {
const { associatedIndex, associatedName, resourceName } = this.options;
let url = `${resourceName}:create`;
if (associatedIndex && associatedName) {
url = `${associatedName}/${associatedIndex}/${url}`;
}
return this.request(url, {
method: 'post',
data: values,
});
}
save(values: any, options: SaveOptions = {}) {
const resourceIndex = options.resourceIndex || this.options.resourceIndex;
const { associatedIndex, associatedName, resourceName } = this.options;
let url = `${resourceName}:${
resourceIndex ? `update/${resourceIndex}` : 'create'
}`;
if (associatedIndex && associatedName) {
url = `${associatedName}/${associatedIndex}/${url}`;
}
return this.request(url, {
method: 'post',
data: values,
});
}
export(options: any) {
const { resourceName } = this.options;
const { columns, ...others } = options;
const url = `${resourceName}:export`;
return this.request(url, {
method: 'post',
params: {
columns: JSON.stringify(columns),
...others,
},
parseResponse: false,
responseType: 'blob',
}).then(async (response: Response) => {
const filename = decodeURI(
response.headers
.get('Content-Disposition')
.replace('attachment; filename=', ''),
);
// ReadableStream
let res = new Response(response.body);
let blob = await res.blob();
let url = URL.createObjectURL(blob);
let a = document.createElement('a');
a.style.display = 'none';
a.href = url;
a.download = filename;
document.body.appendChild(a);
a.click();
// cleanup
URL.revokeObjectURL(url);
document.body.removeChild(a);
a = null;
blob = null;
url = null;
res = null;
});
}
destroy(filter: any) {
const { resourceName } = this.options;
const url = `${resourceName}:destroy`;
return this.request(url, {
method: 'get',
params: {
filter,
},
});
}
toggle(options?: any) {
const { associatedIndex, associatedName, resourceName } = this.options;
const { resourceIndex } = options;
let url = `${associatedName}/${associatedIndex}/${resourceName}:toggle/${resourceIndex}`;
return this.request(url, {
method: 'post',
});
}
static make(
options: null | string | Resource | ResourceOptions,
request?: any,
): Resource | null {
if (typeof options === 'string') {
return new this({ resourceName: options }, request);
}
if (options instanceof Resource) {
return options;
}
if (typeof options === 'object' && options.resourceName) {
return new this(options, request);
}
console.warn('resource 初始化参数错误');
return null;
}
}