feat: improve export plugin

This commit is contained in:
chenos 2021-08-13 09:57:21 +08:00
parent 4139fc8cf6
commit a7040efe63
12 changed files with 784 additions and 4 deletions

View File

@ -45,6 +45,7 @@ const plugins = [
'@nocobase/plugin-action-logs',
// '@nocobase/plugin-file-manager',
'@nocobase/plugin-permissions',
'@nocobase/plugin-export',
// '@nocobase/plugin-automations',
// '@nocobase/plugin-china-region',
];

View File

@ -33,12 +33,14 @@
"html-react-parser": "^1.2.7",
"lodash": "^4.17.21",
"monaco-editor": "^0.25.2",
"react-big-calendar": "^0.33.6",
"react-dnd": "^14.0.2",
"react-dnd-html5-backend": "^14.0.0",
"react-dnd-preview": "^6.0.2",
"react-dnd-touch-backend": "^14.0.0",
"react-helmet": "^6.1.0",
"react-hooks-global-state": "^1.0.1",
"react-modal-hook": "^3.0.0",
"umi-request": "^1.3.5"
}
}

View File

@ -99,6 +99,40 @@ export class Resource {
});
}
export(options: any) {
const { resourceName } = this.options;
const { columns, ...others } = options;
const url = `${resourceName}:export`;
return 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`;

View File

@ -220,6 +220,52 @@ const useTableDestroyAction = () => {
};
};
const useTableExportAction = () => {
const {
resource,
field,
service,
selectedRowKeys,
setSelectedRowKeys,
refresh,
schema,
props: { refreshRequestOnChange, rowKey },
} = useTable();
const ctx = useContext(TableRowContext);
const actionField = useField();
const fieldNames = actionField.componentProps.fieldNames || [];
const { getField } = useCollectionContext();
const columns = fieldNames
.map((name) => {
const f = getField(name);
return {
title: f?.uiSchema.title,
name,
sort: f?.sort,
};
})
.sort((a, b) => a.sort - b.sort);
return {
async run() {
const rowKeys = selectedRowKeys || [];
const { filter = {}, ...others } = service.params[0];
if (rowKeys.length) {
filter[`${rowKey}.in`] = rowKeys;
}
await resource.export({
...others,
columns,
perPage: -1,
page: 1,
filter,
});
},
};
};
const useTableRowRecord = () => {
const ctx = useContext(TableRowContext);
return ctx.record;
@ -817,7 +863,24 @@ function generateActionSchema(type) {
fieldNames: [],
},
},
export: {},
export: {
key: uid(),
type: 'void',
name: uid(),
title: '导出',
'x-align': 'right',
'x-decorator': 'AddNew.Displayed',
'x-decorator-props': {
displayName: 'export',
},
'x-action-type': 'export',
'x-component': 'Action',
'x-designable-bar': 'Table.ExportActionDesignableBar',
'x-component-props': {
fieldNames: [],
useAction: '{{ Table.useTableExportAction }}',
},
},
create: {
key: uid(),
type: 'void',
@ -993,7 +1056,7 @@ function AddActionButton() {
<Menu.ItemGroup title={'操作展示'}>
{[
{ title: '筛选', name: 'filter' },
// { title: '导出', name: 'export' },
{ title: '导出', name: 'export' },
{ title: '新增', name: 'create' },
{ title: '删除', name: 'destroy' },
].map((item) => (
@ -1394,6 +1457,124 @@ Table.Filter.DesignableBar = () => {
);
};
Table.ExportActionDesignableBar = () => {
const { schema, remove, refresh, insertAfter } = useDesignable();
const [visible, setVisible] = useState(false);
const displayed = useDisplayedMapContext();
const { fields } = useCollectionContext();
const field = useField();
let fieldNames = field.componentProps.fieldNames || [];
if (fieldNames.length === 0) {
fieldNames = fields.map((field) => field.name);
}
return (
<div className={cls('designable-bar', { active: visible })}>
<span
onClick={(e) => {
e.stopPropagation();
}}
className={cls('designable-bar-actions', { active: visible })}
>
<DragHandle />
<Dropdown
trigger={['click']}
visible={visible}
onVisibleChange={(visible) => {
setVisible(visible);
}}
overlay={
<Menu>
<Menu.ItemGroup title={'导出字段'}>
{fields.map((collectionField) => (
<SwitchMenuItem
title={collectionField?.uiSchema?.title}
checked={fieldNames.includes(collectionField.name)}
onChange={async (checked) => {
if (checked) {
fieldNames.push(collectionField.name);
} else {
const index = fieldNames.indexOf(collectionField.name);
if (index > -1) {
fieldNames.splice(index, 1);
}
}
console.log({ fieldNames, field });
schema['x-component-props']['fieldNames'] = fieldNames;
field.componentProps.fieldNames = fieldNames;
updateSchema(schema);
}}
/>
))}
</Menu.ItemGroup>
<Menu.Divider />
<Menu.Item
onClick={async (e) => {
const values = await FormDialog('修改名称和图标', () => {
return (
<FormLayout layout={'vertical'}>
<SchemaField
schema={{
type: 'object',
properties: {
title: {
type: 'string',
title: '按钮名称',
required: true,
'x-decorator': 'FormItem',
'x-component': 'Input',
},
icon: {
type: 'string',
title: '按钮图标',
'x-decorator': 'FormItem',
'x-component': 'IconPicker',
},
},
}}
/>
</FormLayout>
);
}).open({
initialValues: {
title: schema['title'],
icon: schema['x-component-props']?.['icon'],
},
});
schema['title'] = values.title;
schema['x-component-props']['icon'] = values.icon;
field.componentProps.icon = values.icon;
field.title = values.title;
updateSchema(schema);
refresh();
}}
>
</Menu.Item>
<Menu.Divider />
<Menu.Item
onClick={async () => {
const displayName =
schema?.['x-decorator-props']?.['displayName'];
const data = remove();
await removeSchema(data);
if (displayName) {
displayed.remove(displayName);
}
setVisible(false);
}}
>
</Menu.Item>
</Menu>
}
>
<MenuOutlined />
</Dropdown>
</span>
</div>
);
};
Table.Operation = observer((props: any) => {
const { designable, schema } = useDesignable();
return (
@ -2094,6 +2275,7 @@ Table.useTableFilterAction = useTableFilterAction;
Table.useTableCreateAction = useTableCreateAction;
Table.useTableUpdateAction = useTableUpdateAction;
Table.useTableDestroyAction = useTableDestroyAction;
Table.useTableExportAction = useTableExportAction;
Table.useTableIndex = useTableIndex;
Table.useTableRowRecord = useTableRowRecord;
Table.SimpleDesignableBar = SimpleDesignableBar;

View File

@ -0,0 +1,7 @@
node_modules
*.log
docs
__tests__
tsconfig.json
src
.fatherrc.ts

View File

@ -0,0 +1,19 @@
{
"name": "@nocobase/plugin-export",
"version": "0.4.0-alpha.7",
"main": "lib/index.js",
"license": "MIT",
"devDependencies": {
"@types/node-xlsx": "^0.15.1"
},
"dependencies": {
"@nocobase/actions": "^0.4.0-alpha.7",
"@nocobase/database": "^0.4.0-alpha.7",
"@nocobase/resourcer": "^0.4.0-alpha.7",
"node-xlsx": "^0.16.1"
},
"peerDependencies": {
"@nocobase/plugin-collections": "*",
"@nocobase/plugin-permissions": "*"
}
}

View File

@ -0,0 +1,70 @@
import xlsx from 'node-xlsx';
import { actions } from '@nocobase/actions';
import render from '../renders';
async function _export(ctx: actions.Context, next: actions.Next) {
let { columns } = ctx.action.params;
if (typeof columns === 'string') {
columns = JSON.parse(columns);
}
ctx.action.mergeParams({
'fields[appends]': columns.map((column: any) => column.name).join(','),
}, {
payload: 'replace',
});
console.log({ columns });
await actions.common.list(ctx, async () => {
const {
db,
action: {
params: {
resourceName
}
},
body,
} = ctx;
const table = db.getTable(resourceName);
const tableOptions = table.getOptions();
let fields = body.rows.length
? Object.keys(body.rows[0].get())
.map(key => tableOptions.fields.find(({ name }) => name === key))
.filter(item => item && !item.developerMode)
.sort((a, b) => a.sort - b.sort)
: [];
if (columns && columns.length) {
fields = columns.map(column => {
const field = table.getField(column.name);
return {
...field.options,
...column,
};
});
}
const { rows, ranges } = render({
fields,
data: body.rows
}, ctx);
ctx.body = xlsx.build([{
name: tableOptions.title,
data: rows,
options: {
'!merges': ranges
}
}]);
ctx.set({
'Content-Type': 'application/octet-stream',
// to avoid "invalid character" error in header (RFC)
'Content-Disposition': `attachment; filename=${encodeURI(tableOptions.title||tableOptions.name)}.xlsx`
});
});
await next();
}
export default _export;

View File

@ -0,0 +1,162 @@
import * as renders from './renders';
function getInterfaceRender(name: string): Function {
return renders[name] || renders._;
}
function renderHeader(params, ctx) {
const {
fields,
headers = [],
rowIndex = 0
} = params;
let { colIndex = 0 } = params;
if (!headers[rowIndex]) {
headers.push([]);
}
const row = headers[rowIndex];
fields.forEach((field, i) => {
const nextColIndex = colIndex + i;
row.push({
field,
rowIndex,
colIndex: nextColIndex
});
if (field.interface === 'subTable') {
const subTable = ctx.db.getTable(field.target);
const subFields = subTable.getOptions().fields.filter(field => Boolean(field.__index));
renderHeader({
fields: subFields,
headers,
rowIndex: rowIndex + 1,
colIndex: nextColIndex
}, ctx);
colIndex += subFields.length;
}
});
Object.assign(params, { headers });
}
function renderRows({ fields, data }, ctx) {
return data.reduce((result, row) => {
const thisRow = [];
const rowIndex = 0;
let colOffset = 0;
fields.forEach((field, i) => {
if (!thisRow[rowIndex]) {
thisRow.push([]);
}
const cells = thisRow[rowIndex];
if (field.interface !== 'subTable') {
const render = getInterfaceRender(field.interface);
cells.push({
value: render(field, row),
rowIndex: result.length + rowIndex,
colIndex: i + colOffset
});
return;
}
const subTable = ctx.db.getTable(field.target);
const subFields = subTable.getOptions().fields.filter(item => Boolean(item.__index));
const subRows = renderRows({ fields: subFields, data: row.get(field.name) || [] }, ctx);
// const { rows: subRowGroups } = subTableRows;
subRows.forEach((cells, j) => {
const subRowIndex = rowIndex + j;
if (!thisRow[subRowIndex]) {
thisRow.push([]);
}
const subCells = thisRow[subRowIndex];
subCells.push(...cells.map(cell => ({
...cell,
rowIndex: result.length + subRowIndex,
colIndex: cell.colIndex + i
})));
});
colOffset += subFields.length;
});
thisRow.forEach((cells) => {
cells.forEach(cell => {
const relRowIndex = cell.rowIndex - result.length;
Object.assign(cell, {
rowSpan: relRowIndex >= thisRow.length - 1
|| thisRow[relRowIndex + 1].find(item => item.colIndex === cell.colIndex)
? 1
: thisRow.length - relRowIndex
});
});
});
return result.concat(thisRow);
}, []);
}
export default function({ fields, data }, ctx) {
const headers = [];
renderHeader({
fields,
headers
}, ctx);
const ranges = [];
// 计算全表最大的列索引(由于无论如何最大列都是单个单元格,所以等价于长度)
const maxColIndex = Math.max(...headers.map(row => row[row.length - 1].colIndex));
// 遍历所有单元格,计算需要合并的坐标范围
headers.forEach((row, rowIndex) => {
row.forEach((cell, cellIndex) => {
// 跨行合并的行数为
cell.rowSpan = cell.rowIndex >= headers.length - 1
|| headers[cell.rowIndex + 1].find(item => item.colIndex === cell.colIndex)
? 1
: headers.length - cell.rowIndex;
const nextCell = headers.slice(0, rowIndex + 1)
.map(r => r.find(item => item.colIndex > cell.colIndex))
.filter(c => Boolean(c))
.reduce((min, c) => min && Math.min(min.colIndex, c.colIndex) === min.colIndex ? min : c, null);
cell.colSpan = nextCell
? nextCell.colIndex - cell.colIndex
: maxColIndex - cell.colIndex + 1;
if (cell.rowSpan > 1 || cell.colSpan > 1) {
ranges.push({
s: { c: cell.colIndex, r: cell.rowIndex },
e: { c: cell.colIndex + cell.colSpan - 1, r: cell.rowIndex + cell.rowSpan - 1 }
});
}
});
});
const rows = renderRows({ fields, data }, ctx)
.map(row => {
const cells = Array(maxColIndex).fill(null);
row.forEach(cell => {
cells.splice(cell.colIndex, 1, cell.value);
if (cell.rowSpan > 1) {
ranges.push({
s: { c: cell.colIndex, r: cell.rowIndex + headers.length },
e: { c: cell.colIndex, r: cell.rowIndex + cell.rowSpan - 1 + headers.length }
});
}
});
return cells;
});
return {
rows: [
...headers.map(row => {
// 补齐无数据单元格,以供合并
const cells = Array(maxColIndex).fill(null);
row.forEach(cell => cells.splice(cell.colIndex, 1, cell.field.title))
return cells;
}),
...rows
],
ranges
};
}

View File

@ -0,0 +1,60 @@
import moment from 'moment';
export function _(field, row) {
return row.get(field.name);
}
export function datetime(field, row) {
const value = row.get(field.name);
return moment(value).format(field.showTime ? `${field.dateFormat} ${field.timeFormat}` : field.dateFormat);
}
export function percent(field, row) {
const value = row.get(field.name);
return value && `${value}%`;
}
export function boolean(field, row) {
const value = row.get(field.name);
// TODO(feature): i18n
return value ? '是' : '否';
}
export function select(field, row) {
const value = row.get(field.name);
const option = field.dataSource.find(item => item.value === value);
return option && option.label;
}
export function multipleSelect(field, row) {
const values = row.get(field.name);
return values && values.map(value => {
const option = field.dataSource.find(item => item.value === value);
return option && option.label;
});
}
export const radio = select;
export const checkboxes = multipleSelect;
export function subTable(field, row) {
// TODO: need title field to be defined
return (row.get(field.name) || []).map(item => item[field.sourceKey]);
}
export function linkTo(field, row) {
return (row.get(field.name) || []).map(item => item[field.labelField]);
}
export function attachment(field, row) {
return (row.get(field.name) || []).map(item => item[field.url]).join(' ');
}
export function chinaRegion(field, row) {
const value = row.get(field.name);
const values = (Array.isArray(value) ? value : [value]).sort((a, b) =>
a.level !== b.level ? a.level - b.level : a.sort - b.sort,
);
return values.map(item => item.name).join('/');
}

View File

@ -0,0 +1,28 @@
import Resourcer from '@nocobase/resourcer';
import _export from './actions/export';
export const ACTION_NAME_EXPORT = 'export';
export default async function (options = {}) {
const resourcer: Resourcer = this.resourcer;
resourcer.registerActionHandler(ACTION_NAME_EXPORT, _export);
// TODO(temp): 继承 list 权限的临时写法
resourcer.use(async (ctx, next) => {
if (ctx.action.params.actionName === ACTION_NAME_EXPORT) {
ctx.action.mergeParams({
actionName: 'list'
});
console.log('action name in export has been rewritten to:', ctx.action.params.actionName);
const permissionPlugin = ctx.app.getPluginInstance('@nocobase/plugin-permissions');
if (permissionPlugin) {
return permissionPlugin.middleware(ctx, next);
}
}
await next();
});
}

View File

@ -20,7 +20,9 @@ export default {
const app = new Application(options);
app.use(bodyParser());
app.use(cors());
app.use(cors({
exposeHeaders: ['content-disposition'],
}));
app.resourcer.registerActionHandlers({ ...actions.common, ...actions.associate });

215
yarn.lock
View File

@ -1695,6 +1695,13 @@
dependencies:
regenerator-runtime "^0.13.4"
"@babel/runtime@^7.14.6", "@babel/runtime@^7.6.3", "@babel/runtime@^7.8.7":
version "7.15.3"
resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.15.3.tgz#2e1c2880ca118e5b2f9988322bd8a7656a32502b"
integrity sha512-OvwMLqNXkCXSz1kSm58sEsNuhqOx/fKpnUnKnFB5v8uDda5bLNEHNgKPvhDN6IU0LDcnHQ90LlJ0Q6jnyBSIBA==
dependencies:
regenerator-runtime "^0.13.4"
"@babel/template@^7.10.4", "@babel/template@^7.12.7", "@babel/template@^7.14.5", "@babel/template@^7.3.3", "@babel/template@^7.4.0", "@babel/template@^7.4.4":
version "7.14.5"
resolved "https://registry.npmjs.org/@babel/template/-/template-7.14.5.tgz#a9bc9d8b33354ff6e55a9c60d1109200a68974f4"
@ -3258,6 +3265,11 @@
dependencies:
"@octokit/openapi-types" "^7.3.2"
"@popperjs/core@^2.5.3":
version "2.9.3"
resolved "https://registry.npmjs.org/@popperjs/core/-/core-2.9.3.tgz#8b68da1ebd7fc603999cf6ebee34a4899a14b88e"
integrity sha512-xDu17cEfh7Kid/d95kB6tZsLOmSWKCZKtprnhVepjsSaCij+lM3mItSJDuuHDMbCWTh8Ejmebwb+KONcCJ0eXQ==
"@qixian.cs/path-to-regexp@^6.1.0":
version "6.1.0"
resolved "https://registry.npmjs.org/@qixian.cs/path-to-regexp/-/path-to-regexp-6.1.0.tgz#6b84ad01596332aba95fa29d2e70104698cd5c45"
@ -3278,6 +3290,13 @@
resolved "https://registry.npmjs.org/@react-dnd/shallowequal/-/shallowequal-2.0.0.tgz#a3031eb54129f2c66b2753f8404266ec7bf67f0a"
integrity sha512-Pc/AFTdwZwEKJxFJvlxrSmGe/di+aAOBn60sremrpLo6VI/6cmiUYNNwlI5KNYttg7uypzA3ILPMPgxB2GYZEg==
"@restart/hooks@^0.3.25":
version "0.3.27"
resolved "https://registry.npmjs.org/@restart/hooks/-/hooks-0.3.27.tgz#91f356d66d4699a8cd8b3d008402708b6a9dc505"
integrity sha512-s984xV/EapUIfkjlf8wz9weP2O9TNKR96C68FfMEy2bE69+H4cNv3RD4Mf97lW7Htt7PjZrYTjSC8f3SB9VCXw==
dependencies:
dequal "^2.0.2"
"@rollup/plugin-babel@5.2.1":
version "5.2.1"
resolved "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.2.1.tgz#20fc8f8864dc0eaa1c5578408459606808f72924"
@ -3779,6 +3798,11 @@
dependencies:
"@types/node" "*"
"@types/node-xlsx@^0.15.1":
version "0.15.2"
resolved "https://registry.npmjs.org/@types/node-xlsx/-/node-xlsx-0.15.2.tgz#1371c4af8fe2b6626253f8b85719adfe88355b20"
integrity sha512-rG1SmpWvSkse23rL/5bgej5yQ2y+WoWMrKE3iE4upuHWQwzdLCYEkrwr1pMZDx642R/tJCDGGUig7U/cT24Ecg==
"@types/node@*", "@types/node@>= 8":
version "15.12.2"
resolved "https://registry.npmjs.org/@types/node/-/node-15.12.2.tgz#1f2b42c4be7156ff4a6f914b2fb03d05fa84e38d"
@ -3892,7 +3916,7 @@
"@types/history" "*"
"@types/react" "*"
"@types/react@*", "@types/react@^16.9.43", "@types/react@^17.0.0":
"@types/react@*", "@types/react@>=16.9.11", "@types/react@^16.9.43", "@types/react@^17.0.0":
version "17.0.11"
resolved "https://registry.npmjs.org/@types/react/-/react-17.0.11.tgz#67fcd0ddbf5a0b083a0f94e926c7d63f3b836451"
integrity sha512-yFRQbD+whVonItSk7ZzP/L+gPTJVBkL/7shLEF+i9GC/1cV3JmUxEQz6+9ylhUpWSDuqo1N9qEvqS6vTj4USUA==
@ -3943,6 +3967,11 @@
resolved "https://registry.npmjs.org/@types/unist/-/unist-2.0.3.tgz#9c088679876f374eb5983f150d4787aa6fb32d7e"
integrity sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ==
"@types/warning@^3.0.0":
version "3.0.0"
resolved "https://registry.npmjs.org/@types/warning/-/warning-3.0.0.tgz#0d2501268ad8f9962b740d387c4654f5f8e23e52"
integrity sha1-DSUBJorY+ZYrdA04fEZU9fjiPlI=
"@types/yargs-parser@*":
version "20.2.0"
resolved "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-20.2.0.tgz#dd3e6699ba3237f0348cd085e4698780204842f9"
@ -4520,6 +4549,14 @@ address@>=0.0.1, address@^1.0.0:
resolved "https://registry.npmjs.org/address/-/address-1.1.2.tgz#bf1116c9c758c51b7a933d296b72c221ed9428b6"
integrity sha512-aT6camzM4xEA54YVJYSqxz1kv4IHnQZRtThJJHhUMRExaU5spC7jX5ugSwTaTgJliIgs4VhZOk7htClvQ/LmRA==
adler-32@~1.2.0:
version "1.2.0"
resolved "https://registry.npmjs.org/adler-32/-/adler-32-1.2.0.tgz#6a3e6bf0a63900ba15652808cb15c6813d1a5f25"
integrity sha1-aj5r8KY5ALoVZSgIyxXGgT0aXyU=
dependencies:
exit-on-epipe "~1.0.1"
printj "~1.1.0"
agent-base@4, agent-base@^4.3.0:
version "4.3.0"
resolved "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee"
@ -5670,6 +5707,11 @@ buffer-from@1.x, buffer-from@^1.0.0:
resolved "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==
buffer-from@^1.1.1:
version "1.1.2"
resolved "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5"
integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==
buffer-writer@2.0.0:
version "2.0.0"
resolved "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz#ce7eb81a38f7829db09c873f2fbb792c0c98ec04"
@ -5925,6 +5967,15 @@ center-align@^0.1.1:
align-text "^0.1.3"
lazy-cache "^1.0.3"
cfb@^1.1.4:
version "1.2.0"
resolved "https://registry.npmjs.org/cfb/-/cfb-1.2.0.tgz#6a4d0872b525ed60349e1ef51fb4b0bf73eca9a8"
integrity sha512-sXMvHsKCICVR3Naq+J556K+ExBo9n50iKl6LGarlnvuA2035uMlGA/qVrc0wQtow5P1vJEw9UyrKLCbtIKz+TQ==
dependencies:
adler-32 "~1.2.0"
crc-32 "~1.2.0"
printj "~1.1.2"
chalk@2.4.2, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.3.1, chalk@^2.3.2, chalk@^2.4.1, chalk@^2.4.2:
version "2.4.2"
resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
@ -6224,6 +6275,11 @@ cloneable-readable@^1.0.0:
process-nextick-args "^2.0.0"
readable-stream "^2.3.5"
clsx@^1.0.4:
version "1.1.1"
resolved "https://registry.npmjs.org/clsx/-/clsx-1.1.1.tgz#98b3134f9abbdf23b2663491ace13c5c03a73188"
integrity sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA==
co-body@^6.0.0:
version "6.1.0"
resolved "https://registry.npmjs.org/co-body/-/co-body-6.1.0.tgz#d87a8efc3564f9bfe3aced8ef5cd04c7a8766547"
@ -6258,6 +6314,14 @@ code-point-at@^1.0.0:
resolved "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=
codepage@~1.14.0:
version "1.14.0"
resolved "https://registry.npmjs.org/codepage/-/codepage-1.14.0.tgz#8cbe25481323559d7d307571b0fff91e7a1d2f99"
integrity sha1-jL4lSBMjVZ19MHVxsP/5HnodL5k=
dependencies:
commander "~2.14.1"
exit-on-epipe "~1.0.1"
collect-v8-coverage@^1.0.0:
version "1.0.1"
resolved "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz#cc2c8e94fc18bbdffe64d6534570c8a673b27f59"
@ -6351,6 +6415,16 @@ commander@^2.19.0, commander@^2.20.0:
resolved "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
commander@~2.14.1:
version "2.14.1"
resolved "https://registry.npmjs.org/commander/-/commander-2.14.1.tgz#2235123e37af8ca3c65df45b026dbd357b01b9aa"
integrity sha512-+YR16o3rK53SmWHU3rEM3tPAh2rwb1yPcQX5irVn7mb0gXbwuCCrnkbV5+PBfETdfg1vui07nM6PCG1zndcjQw==
commander@~2.17.1:
version "2.17.1"
resolved "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf"
integrity sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==
commondir@^1.0.1:
version "1.0.1"
resolved "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
@ -6709,6 +6783,14 @@ cosmiconfig@^7.0.0:
path-type "^4.0.0"
yaml "^1.10.0"
crc-32@~1.2.0:
version "1.2.0"
resolved "https://registry.npmjs.org/crc-32/-/crc-32-1.2.0.tgz#cb2db6e29b88508e32d9dd0ec1693e7b41a18208"
integrity sha512-1uBwHxF+Y/4yF5G48fwnKq6QsIXheor3ZLPT80yGBV1oEUwpPojlEhQbWKVw1VwcTQyMGHK1/XMmTjmlsmTTGA==
dependencies:
exit-on-epipe "~1.0.1"
printj "~1.1.0"
create-ecdh@^4.0.0:
version "4.0.4"
resolved "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e"
@ -7157,6 +7239,11 @@ data-urls@^2.0.0:
whatwg-mimetype "^2.3.0"
whatwg-url "^8.0.0"
date-arithmetic@^4.1.0:
version "4.1.0"
resolved "https://registry.npmjs.org/date-arithmetic/-/date-arithmetic-4.1.0.tgz#e5d6434e9deb71f79760a37b729e4a515e730ddf"
integrity sha512-QWxYLR5P/6GStZcdem+V1xoto6DMadYWpMXU82ES3/RfR3Wdwr3D0+be7mgOJ+Ov0G9D5Dmb9T17sNLQYj9XOg==
date-fns@^2.0.1:
version "2.23.0"
resolved "https://registry.nlark.com/date-fns/download/date-fns-2.23.0.tgz?cache=0&sync_timestamp=1627020353586&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fdate-fns%2Fdownload%2Fdate-fns-2.23.0.tgz#4e886c941659af0cf7b30fafdd1eaa37e88788a9"
@ -7388,6 +7475,11 @@ deprecation@^2.0.0, deprecation@^2.3.1:
resolved "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz#6368cbdb40abf3373b525ac87e4a260c3a700919"
integrity sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==
dequal@^2.0.2:
version "2.0.2"
resolved "https://registry.npmjs.org/dequal/-/dequal-2.0.2.tgz#85ca22025e3a87e65ef75a7a437b35284a7e319d"
integrity sha512-q9K8BlJVxK7hQYqa6XISGmBZbtQQWVXSrRrWreHC94rMt1QL/Impruc+7p2CYSYuVIUr+YCt6hjrs1kkdJRTug==
des.js@^1.0.0:
version "1.0.1"
resolved "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843"
@ -7520,6 +7612,14 @@ dom-align@1.x, dom-align@^1.7.0:
resolved "https://registry.npmjs.org/dom-align/-/dom-align-1.12.2.tgz#0f8164ebd0c9c21b0c790310493cd855892acd4b"
integrity sha512-pHuazgqrsTFrGU2WLDdXxCFabkdQDx72ddkraZNih1KsMcN5qsRSTR9O4VJRlwTPCPb5COYg3LOfiMHHcPInHg==
dom-helpers@^5.1.0, dom-helpers@^5.2.0:
version "5.2.1"
resolved "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz#d9400536b2bf8225ad98fe052e029451ac40e902"
integrity sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==
dependencies:
"@babel/runtime" "^7.8.7"
csstype "^3.0.2"
dom-serializer@0:
version "0.2.2"
resolved "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz#1afb81f533717175d478655debc5e332d9f9bb51"
@ -8373,6 +8473,11 @@ exenv@^1.2.0:
resolved "https://registry.npmjs.org/exenv/-/exenv-1.2.2.tgz#2ae78e85d9894158670b03d47bec1f03bd91bb9d"
integrity sha1-KueOhdmJQVhnCwPUe+wfA72Ru50=
exit-on-epipe@~1.0.1:
version "1.0.1"
resolved "https://registry.npmjs.org/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz#0bdd92e87d5285d267daa8171d0eb06159689692"
integrity sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw==
exit@^0.1.2:
version "0.1.2"
resolved "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c"
@ -8590,6 +8695,11 @@ fecha@~4.2.0:
resolved "https://registry.npmjs.org/fecha/-/fecha-4.2.1.tgz#0a83ad8f86ef62a091e22bb5a039cd03d23eecce"
integrity sha512-MMMQ0ludy/nBs1/o0zVOiKTpG7qMbonKUzjJgQFEuvq6INZ1OraKPRAWkBq5vlKLOUMpmNYG1JoN3oDPUQ9m3Q==
fflate@^0.3.8:
version "0.3.11"
resolved "https://registry.npmjs.org/fflate/-/fflate-0.3.11.tgz#2c440d7180fdeb819e64898d8858af327b042a5d"
integrity sha512-Rr5QlUeGN1mbOHlaqcSYMKVpPbgLy0AWT/W0EHxA6NGI12yO1jpoui2zBBvU2G824ltM6Ut8BFgfHSBGfkmS0A==
figgy-pudding@^3.4.1, figgy-pudding@^3.5.1:
version "3.5.2"
resolved "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz#b4eee8148abb01dcf1d1ac34367d59e12fa61d6e"
@ -8797,6 +8907,11 @@ formstream@^1.1.0:
mime "^2.5.2"
pause-stream "~0.0.11"
frac@~1.1.2:
version "1.1.2"
resolved "https://registry.npmjs.org/frac/-/frac-1.1.2.tgz#3d74f7f6478c88a1b5020306d747dc6313c74d0b"
integrity sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==
fragment-cache@^0.2.1:
version "0.2.1"
resolved "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19"
@ -12098,6 +12213,11 @@ locate-path@^5.0.0:
dependencies:
p-locate "^4.1.0"
lodash-es@^4.17.11:
version "4.17.21"
resolved "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee"
integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==
lodash._reinterpolate@^3.0.0:
version "3.0.0"
resolved "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d"
@ -13297,6 +13417,15 @@ node-schedule@^2.0.0:
long-timeout "0.1.1"
sorted-array-functions "^1.3.0"
node-xlsx@^0.16.1:
version "0.16.2"
resolved "https://registry.npmjs.org/node-xlsx/-/node-xlsx-0.16.2.tgz#40f580187eae0e032cac96e958e97cb6ceca09f6"
integrity sha512-ZT3Y4Zg2BFC2UWdp9B/6x3GqrFL0Bf0cXKy9IyhcwlKbcDAf5GuPAPSqrWFQK68NIpfTNA1Kr/NNjpwYxUgHTA==
dependencies:
"@babel/runtime" "^7.14.6"
buffer-from "^1.1.1"
xlsx "^0.17.0"
nodemon@^2.0.12:
version "2.0.12"
resolved "https://registry.npmjs.org/nodemon/-/nodemon-2.0.12.tgz#5dae4e162b617b91f1873b3bfea215dd71e144d5"
@ -15098,6 +15227,11 @@ pretty-format@^26.6.2:
ansi-styles "^4.0.0"
react-is "^17.0.1"
printj@~1.1.0, printj@~1.1.2:
version "1.1.2"
resolved "https://registry.npmjs.org/printj/-/printj-1.1.2.tgz#d90deb2975a8b9f600fb3a1c94e3f4c53c78a222"
integrity sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ==
prism-react-renderer@^1.1.1:
version "1.2.1"
resolved "https://registry.npmjs.org/prism-react-renderer/-/prism-react-renderer-1.2.1.tgz#392460acf63540960e5e3caa699d851264e99b89"
@ -15880,6 +16014,23 @@ react-attr-converter@^0.3.1:
resolved "https://registry.npmjs.org/react-attr-converter/-/react-attr-converter-0.3.1.tgz#4a2abf6d907b7ddae4d862dfec80e489ce41ad6e"
integrity sha512-dSxo2Mn6Zx4HajeCeQNLefwEO4kNtV/0E682R1+ZTyFRPqxDa5zYb5qM/ocqw9Bxr/kFQO0IUiqdV7wdHw+Cdg==
react-big-calendar@^0.33.6:
version "0.33.6"
resolved "https://registry.npmjs.org/react-big-calendar/-/react-big-calendar-0.33.6.tgz#87594b4ce54b4f3cc7f69d52f2d34ddf6b2eb00b"
integrity sha512-4crVUE1W7+zIUfbfrXxd9nDOVktwn8M8Ffrjd39r9zFIveZu1zhrWwi+qqu46EQw2xRnb+mFx+mcwUozkqYlkA==
dependencies:
"@babel/runtime" "^7.1.5"
clsx "^1.0.4"
date-arithmetic "^4.1.0"
dom-helpers "^5.1.0"
invariant "^2.2.4"
lodash "^4.17.11"
lodash-es "^4.17.11"
memoize-one "^5.1.1"
prop-types "^15.7.2"
react-overlays "^4.1.1"
uncontrollable "^7.0.0"
react-dnd-html5-backend@^14.0.0:
version "14.0.0"
resolved "https://registry.npmjs.org/react-dnd-html5-backend/-/react-dnd-html5-backend-14.0.0.tgz#28d660a2ad1e07447c34a65cd25f7de8f1657194"
@ -15990,6 +16141,11 @@ react-lifecycles-compat@^3.0.4:
resolved "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362"
integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==
react-modal-hook@^3.0.0:
version "3.0.0"
resolved "https://registry.npmjs.org/react-modal-hook/-/react-modal-hook-3.0.0.tgz#24b2ff2acf288ef25c11e4fb11b329458a823ea3"
integrity sha512-mNkJwgEtOoIabuILlWnGAto993WVkimZASBWk/rAGZ6tNIqjx4faQtNdr/X31vw+QGfKhspXc4vPi1jbfkk2Yg==
react-native-swipeout@^2.2.2:
version "2.3.6"
resolved "https://registry.npmjs.org/react-native-swipeout/-/react-native-swipeout-2.3.6.tgz#47dac8a835825cf3f2eef9e495574a3d9ab6d3fa"
@ -15999,6 +16155,20 @@ react-native-swipeout@^2.2.2:
prop-types "^15.5.10"
react-tween-state "^0.1.5"
react-overlays@^4.1.1:
version "4.1.1"
resolved "https://registry.npmjs.org/react-overlays/-/react-overlays-4.1.1.tgz#0060107cbe1c5171a744ccda3fbf0556d064bc5f"
integrity sha512-WtJifh081e6M24KnvTQoNjQEpz7HoLxqt8TwZM7LOYIkYJ8i/Ly1Xi7RVte87ZVnmqQ4PFaFiNHZhSINPSpdBQ==
dependencies:
"@babel/runtime" "^7.12.1"
"@popperjs/core" "^2.5.3"
"@restart/hooks" "^0.3.25"
"@types/warning" "^3.0.0"
dom-helpers "^5.2.0"
prop-types "^15.7.2"
uncontrollable "^7.0.0"
warning "^4.0.3"
react-property@1.0.1:
version "1.0.1"
resolved "https://registry.npmjs.org/react-property/-/react-property-1.0.1.tgz#4ae4211557d0a0ae050a71aa8ad288c074bea4e6"
@ -17685,6 +17855,13 @@ sqlstring@^2.3.2:
resolved "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.2.tgz#cdae7169389a1375b18e885f2e60b3e460809514"
integrity sha512-vF4ZbYdKS8OnoJAWBmMxCQDkiEBkGQYU7UZPtL8flbDRSNkhaXvRJ279ZtI6M+zDaQovVU4tuRgzK5fVhvFAhg==
ssf@~0.11.2:
version "0.11.2"
resolved "https://registry.npmjs.org/ssf/-/ssf-0.11.2.tgz#0b99698b237548d088fc43cdf2b70c1a7512c06c"
integrity sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==
dependencies:
frac "~1.1.2"
sshpk@^1.7.0:
version "1.16.1"
resolved "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877"
@ -18911,6 +19088,16 @@ unc-path-regex@^0.1.2:
resolved "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz#e73dd3d7b0d7c5ed86fbac6b0ae7d8c6a69d50fa"
integrity sha1-5z3T17DXxe2G+6xrCufYxqadUPo=
uncontrollable@^7.0.0:
version "7.2.1"
resolved "https://registry.npmjs.org/uncontrollable/-/uncontrollable-7.2.1.tgz#1fa70ba0c57a14d5f78905d533cf63916dc75738"
integrity sha512-svtcfoTADIB0nT9nltgjujTi7BzVmwjZClOmskKu/E8FW9BXzg9os8OLr4f8Dlnk0rYWJIWr4wv9eKUXiQvQwQ==
dependencies:
"@babel/runtime" "^7.6.3"
"@types/react" ">=16.9.11"
invariant "^2.2.4"
react-lifecycles-compat "^3.0.4"
undefsafe@^2.0.3:
version "2.0.3"
resolved "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.3.tgz#6b166e7094ad46313b2202da7ecc2cd7cc6e7aae"
@ -19658,11 +19845,21 @@ wkx@^0.5.0:
dependencies:
"@types/node" "*"
wmf@~1.0.1:
version "1.0.2"
resolved "https://registry.npmjs.org/wmf/-/wmf-1.0.2.tgz#7d19d621071a08c2bdc6b7e688a9c435298cc2da"
integrity sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw==
word-wrap@^1.2.3, word-wrap@~1.2.3:
version "1.2.3"
resolved "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c"
integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==
word@~0.3.0:
version "0.3.0"
resolved "https://registry.npmjs.org/word/-/word-0.3.0.tgz#8542157e4f8e849f4a363a288992d47612db9961"
integrity sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA==
wordwrap@0.0.2:
version "0.0.2"
resolved "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f"
@ -19785,6 +19982,22 @@ xdg-basedir@^4.0.0:
resolved "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13"
integrity sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==
xlsx@^0.17.0:
version "0.17.0"
resolved "https://registry.npmjs.org/xlsx/-/xlsx-0.17.0.tgz#028176a0140967dcee1817d221678461e47481c8"
integrity sha512-bZ36FSACiAyjoldey1+7it50PMlDp1pcAJrZKcVZHzKd8BC/z6TQ/QAN8onuqcepifqSznR6uKnjPhaGt6ig9A==
dependencies:
adler-32 "~1.2.0"
cfb "^1.1.4"
codepage "~1.14.0"
commander "~2.17.1"
crc-32 "~1.2.0"
exit-on-epipe "~1.0.1"
fflate "^0.3.8"
ssf "~0.11.2"
wmf "~1.0.1"
word "~0.3.0"
xml-name-validator@^3.0.0:
version "3.0.0"
resolved "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a"