mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-28 16:17:02 +00:00
delete ctable-module (#3842)
This commit is contained in:
@@ -1,26 +0,0 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Button } from 'reactstrap';
|
||||
|
||||
const propTypes = {
|
||||
onSave: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
const { fileName } = window.app.pageOptions;
|
||||
|
||||
class AddHeader extends React.Component {
|
||||
|
||||
render() {
|
||||
let {isContentChanged} = this.props;
|
||||
return (
|
||||
<div id="header">
|
||||
<div className="sf-font">{fileName}</div>
|
||||
<Button color="primary" onClick={this.props.onSave} disabled={!isContentChanged}>保存</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
AddHeader.propTypes = propTypes;
|
||||
|
||||
export default AddHeader;
|
@@ -1,187 +0,0 @@
|
||||
import React from 'react';
|
||||
import isHotkey from 'is-hotkey';
|
||||
import ReactDataGrid from '@seafile/react-data-grid/';
|
||||
import { Menu } from '@seafile/react-data-grid-addons';
|
||||
import { seafileAPI } from '../../utils/seafile-api';
|
||||
import ModalPortal from '../../components/modal-portal';
|
||||
import NewColumnDialog from './new-column-dialog';
|
||||
import GridHeaderContextMenu from './grid-header-contextmenu';
|
||||
import GridContentContextMenu from './grid-content-contextmenu';
|
||||
import DTableStore from './store/dtable-store';
|
||||
|
||||
const { repoID, filePath } = window.app.pageOptions;
|
||||
|
||||
const DEFAULT_DATA = {
|
||||
columns: [
|
||||
{
|
||||
key: 'name',
|
||||
name: 'Name',
|
||||
type: '',
|
||||
width: 80,
|
||||
editable: true,
|
||||
resizable: true
|
||||
}
|
||||
],
|
||||
rows: [{name: 'name_' + 0}]
|
||||
};
|
||||
|
||||
class AppMain extends React.Component {
|
||||
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
this.state = {
|
||||
value: null,
|
||||
isNewColumnDialogShow: false,
|
||||
};
|
||||
this.dTableStore = new DTableStore();
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
|
||||
seafileAPI.getFileDownloadLink(repoID, filePath).then(res => {
|
||||
let url = res.data;
|
||||
seafileAPI.getFileContent(url).then(res => {
|
||||
let data = res.data ? res.data : JSON.stringify(DEFAULT_DATA);
|
||||
let value = this.dTableStore.deseralizeGridData(data);
|
||||
this.setState({value});
|
||||
});
|
||||
});
|
||||
|
||||
document.addEventListener('keydown', this.onHotKey);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
document.removeEventListener('keydown', this.onHotKey);
|
||||
}
|
||||
|
||||
getRowAt = (index) => {
|
||||
if (index < 0 || index > this.getSize()) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return this.state.value.rows[index];
|
||||
};
|
||||
|
||||
getSize = () => {
|
||||
return this.state.value.rows.length;
|
||||
};
|
||||
|
||||
onInsertRow = () => {
|
||||
|
||||
let newRowIndex = this.getSize();
|
||||
let value = this.dTableStore.insertRow(newRowIndex);
|
||||
this.setState({value});
|
||||
|
||||
this.props.onContentChanged();
|
||||
}
|
||||
|
||||
onInsertColumn = () => {
|
||||
this.setState({isNewColumnDialogShow: true});
|
||||
}
|
||||
|
||||
onNewColumn = (columnName, columnType) => {
|
||||
|
||||
let idx = this.state.value.columns.length;
|
||||
let value = this.dTableStore.insertColumn(idx, columnName, columnType);
|
||||
this.setState({value});
|
||||
this.onNewColumnCancel();
|
||||
|
||||
this.props.onContentChanged();
|
||||
}
|
||||
|
||||
onNewColumnCancel = () => {
|
||||
this.setState({isNewColumnDialogShow: false});
|
||||
|
||||
this.props.onContentChanged();
|
||||
}
|
||||
|
||||
onRowDelete = (e, data) => {
|
||||
|
||||
let { rowIdx } = data;
|
||||
let value = this.dTableStore.deleteRow(rowIdx);
|
||||
this.setState({value});
|
||||
|
||||
this.props.onContentChanged();
|
||||
}
|
||||
|
||||
onColumnDelete = (e, data) => {
|
||||
|
||||
let column = data.column;
|
||||
let idx = column.idx - 1;
|
||||
let value = this.dTableStore.deleteColumn(idx);
|
||||
this.setState({value});
|
||||
|
||||
this.props.onContentChanged();
|
||||
}
|
||||
|
||||
onColumnResize = (index, width) => {
|
||||
|
||||
let idx = index - 1;
|
||||
let value = this.dTableStore.resizeColumn(idx, width);
|
||||
this.setState({value});
|
||||
|
||||
this.props.onContentChanged();
|
||||
}
|
||||
|
||||
handleGridRowsUpdated = ({fromRow, updated}) => {
|
||||
let rowIdx = fromRow;
|
||||
let value = this.dTableStore.modifyCell(rowIdx, updated);
|
||||
this.setState({value});
|
||||
|
||||
this.props.onContentChanged();
|
||||
}
|
||||
|
||||
serializeGridData = () => {
|
||||
return this.dTableStore.serializeGridData();
|
||||
}
|
||||
|
||||
onHotKey = (event) => {
|
||||
if (isHotkey('mod+s', event)) {
|
||||
event.preventDefault();
|
||||
this.props.onSave();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
if (!this.state.value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return (
|
||||
<div id="main">
|
||||
<ReactDataGrid
|
||||
ref={ node => this.grid = node }
|
||||
enableCellSelect={true}
|
||||
columns={this.state.value.columns}
|
||||
rowGetter={this.getRowAt}
|
||||
rowsCount={this.getSize()}
|
||||
onGridRowsUpdated={this.handleGridRowsUpdated}
|
||||
enableRowSelect={true}
|
||||
rowHeight={50}
|
||||
minHeight={500}
|
||||
rowScrollTimeout={200}
|
||||
enableInsertColumn={true}
|
||||
enableInsertRow={true}
|
||||
onInsertRow={this.onInsertRow}
|
||||
onInsertColumn={this.onInsertColumn}
|
||||
RowsContainer={Menu.ContextMenuTrigger}
|
||||
headerContextMenu={<GridHeaderContextMenu id="grid-header-contxtmenu" onColumnDelete={this.onColumnDelete} />}
|
||||
contextMenu={<GridContentContextMenu id="grid-content-contxtmenu" onRowDelete={this.onRowDelete} />}
|
||||
onColumnResize={this.onColumnResize}
|
||||
/>
|
||||
{this.state.isNewColumnDialogShow && (
|
||||
<ModalPortal>
|
||||
<NewColumnDialog
|
||||
onNewColumnCancel={this.onNewColumnCancel}
|
||||
onNewColumn={this.onNewColumn}
|
||||
/>
|
||||
</ModalPortal>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default AppMain;
|
@@ -1,33 +0,0 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Menu } from '@seafile/react-data-grid-addons';
|
||||
|
||||
const propTypes = {
|
||||
id: PropTypes.string.isRequired,
|
||||
idx: PropTypes.number,
|
||||
rowIdx: PropTypes.number,
|
||||
onRowDelete: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
class GridContentContextMenu extends React.Component {
|
||||
|
||||
onRowDelete = (e, data) => {
|
||||
if (typeof(this.props.onRowDelete) === 'function') {
|
||||
this.props.onRowDelete(e, data);
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const { idx, id, rowIdx } = this.props;
|
||||
|
||||
return (
|
||||
<Menu.ContextMenu id={id}>
|
||||
<Menu.MenuItem data={{ rowIdx, idx }} onClick={this.onRowDelete}>Delete Row</Menu.MenuItem>
|
||||
</Menu.ContextMenu>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
GridContentContextMenu.propTypes = propTypes;
|
||||
|
||||
export default GridContentContextMenu;
|
@@ -1,33 +0,0 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Menu } from '@seafile/react-data-grid-addons';
|
||||
|
||||
const propTypes = {
|
||||
id: PropTypes.string.isRequired,
|
||||
column: PropTypes.object,
|
||||
onColumnRename: PropTypes.func,
|
||||
};
|
||||
|
||||
class GridHeaderContextMenu extends React.Component {
|
||||
|
||||
onColumnDelete = (e, data) => {
|
||||
if (typeof(this.props.onColumnDelete) === 'function') {
|
||||
this.props.onColumnDelete(e, data);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
let { id, column } = this.props;
|
||||
return (
|
||||
<Menu.ContextMenu id={id}>
|
||||
<Menu.MenuItem data={{ column }} onClick={this.onColumnDelete}>Delete</Menu.MenuItem>
|
||||
</Menu.ContextMenu>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
GridHeaderContextMenu.propTypes = propTypes;
|
||||
|
||||
export default GridHeaderContextMenu;
|
||||
|
||||
|
@@ -1,13 +0,0 @@
|
||||
export default class GridColumn {
|
||||
|
||||
constructor(object) {
|
||||
this.key = object.columnName || object.name;
|
||||
this.name = object.columnName || object.name;
|
||||
this.type = object.columnType || null;
|
||||
this.editor = null;
|
||||
this.editable = object.editable || true;
|
||||
this.width = object.width || 200;
|
||||
this.resizable = object.resizable || true;
|
||||
}
|
||||
|
||||
}
|
@@ -1,7 +0,0 @@
|
||||
export default class GridRow {
|
||||
|
||||
constructor(object) {
|
||||
this.name = object.name || 'name_' + object.newRowIdx;
|
||||
}
|
||||
|
||||
}
|
@@ -1,76 +0,0 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Modal, ModalHeader, ModalBody, ModalFooter, Form, FormGroup, Label, Input, Alert, Button } from 'reactstrap';
|
||||
import { gettext } from '../../utils/constants';
|
||||
|
||||
const propTypes = {
|
||||
onNewColumnCancel: PropTypes.func,
|
||||
onNewColumn: PropTypes.func,
|
||||
};
|
||||
|
||||
class NewCoumnDialog extends React.Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
columnType: 'text',
|
||||
columnName: '',
|
||||
errMessage: '',
|
||||
};
|
||||
}
|
||||
|
||||
handleChange = (event) => {
|
||||
let value = event.target.value.trim();
|
||||
this.setState({columnName: value});
|
||||
}
|
||||
|
||||
onSelectChange = (event) => {
|
||||
let type = event.target.value;
|
||||
this.setState({columnType: type});
|
||||
}
|
||||
|
||||
toggle = () => {
|
||||
this.props.onNewColumnCancel();
|
||||
}
|
||||
|
||||
handleSubmit = () => {
|
||||
let { columnName, columnType } = this.state;
|
||||
if (!columnName) {
|
||||
this.setState({errMessage: gettext('Name is required.')});
|
||||
return;
|
||||
}
|
||||
this.props.onNewColumn(columnName, columnType);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Modal isOpen={true} toggle={this.toggle}>
|
||||
<ModalHeader>New Column</ModalHeader>
|
||||
<ModalBody>
|
||||
<Form>
|
||||
<FormGroup>
|
||||
<Label for="columnName">Name</Label>
|
||||
<Input id="columnName" value={this.state.columnName} innerRef={input => {this.newInput = input;}} onChange={this.handleChange} />
|
||||
</FormGroup>
|
||||
<FormGroup>
|
||||
<Label for="typeSelect">Type</Label>
|
||||
<Input id="typeSelect" type='select' name="select" onChange={this.onSelectChange}>
|
||||
<option vlaue="text">text</option>
|
||||
<option value="number">number</option>
|
||||
</Input>
|
||||
</FormGroup>
|
||||
</Form>
|
||||
{this.state.errMessage && <Alert color="danger" className="mt-2">{this.state.errMessage}</Alert>}
|
||||
</ModalBody>
|
||||
<ModalFooter>
|
||||
<Button color="secondary" onClick={this.toggle}>{gettext('Cancel')}</Button>
|
||||
<Button color="primary" onClick={this.handleSubmit}>{gettext('Submit')}</Button>
|
||||
</ModalFooter>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
NewCoumnDialog.propTypes = propTypes;
|
||||
|
||||
export default NewCoumnDialog;
|
@@ -1,61 +0,0 @@
|
||||
import OperationTypes from './operation-types';
|
||||
import GridColumn from '../model/grid-column';
|
||||
import GridRow from '../model/grid-row';
|
||||
|
||||
function apply(value, op) {
|
||||
|
||||
let { type } = op;
|
||||
let next = value.slice(0); // clone a copy
|
||||
|
||||
switch(type) {
|
||||
case OperationTypes.DELETE_ROW : {
|
||||
let { rowIdx } = op;
|
||||
next.splice(rowIdx, 1);
|
||||
return next;
|
||||
}
|
||||
|
||||
case OperationTypes.INSERT_ROW : {
|
||||
let { newRowIdx } = op;
|
||||
let row = new GridRow({newRowIdx});
|
||||
next.push(row);
|
||||
return next;
|
||||
}
|
||||
|
||||
case OperationTypes.DELETE_COLUMN : {
|
||||
let { idx } = op;
|
||||
next.splice(idx, 1);
|
||||
return next;
|
||||
}
|
||||
|
||||
case OperationTypes.INSERT_COLUMN : {
|
||||
let { idx, columnName, columnType } = op;
|
||||
let column = new GridColumn({idx, columnName, columnType});
|
||||
next.push(column);
|
||||
return next;
|
||||
}
|
||||
|
||||
case OperationTypes.MODIFY_CELL : {
|
||||
let { rowIdx, updated } = op;
|
||||
let updateRow = next[rowIdx];
|
||||
updateRow = Object.assign({}, {...updateRow}, updated); // todo
|
||||
next[rowIdx] = updateRow;
|
||||
return next;
|
||||
}
|
||||
|
||||
case OperationTypes.MODIFY_COLUMN : {
|
||||
let { idx, newColumnName } = op;
|
||||
next[idx]['key'] = newColumnName;
|
||||
next[idx]['name'] = newColumnName;
|
||||
return next;
|
||||
}
|
||||
|
||||
case OperationTypes.RESIZE_COLUMN : {
|
||||
let { idx, width } = op;
|
||||
next[idx].width = width;
|
||||
|
||||
return next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default apply;
|
@@ -1,134 +0,0 @@
|
||||
import Operation from './operation';
|
||||
import OperationTypes from './operation-types';
|
||||
import editorFactory from '../utils/editor-factory';
|
||||
// todo Immutable
|
||||
// Implement the current version with an array
|
||||
|
||||
export default class DTableStore {
|
||||
|
||||
constructor() {
|
||||
this.value = {};
|
||||
this.value.columns = [];
|
||||
this.value.rows = [];
|
||||
this.operations = [];
|
||||
}
|
||||
|
||||
serializeGridData() {
|
||||
|
||||
let value = this.value;
|
||||
let columns = value.columns.map(column => {
|
||||
delete column.editor; // delete editor attr;
|
||||
return column;
|
||||
});
|
||||
|
||||
value.columns = columns;
|
||||
|
||||
return JSON.stringify(value);
|
||||
}
|
||||
|
||||
deseralizeGridData(gridData) {
|
||||
|
||||
gridData = JSON.parse(gridData);
|
||||
let columns = gridData.columns;
|
||||
let rows = gridData.rows;
|
||||
|
||||
columns = columns.map(column => {
|
||||
if (column.type) {
|
||||
let editor = editorFactory.createEditor(column.type);
|
||||
column.editor = editor;
|
||||
}
|
||||
return column;
|
||||
});
|
||||
|
||||
this.value.columns = columns;
|
||||
this.value.rows = rows;
|
||||
|
||||
return this.value;
|
||||
}
|
||||
|
||||
createOperation(op) {
|
||||
return new Operation(op);
|
||||
}
|
||||
|
||||
deleteRow(rowIdx) {
|
||||
let type = OperationTypes.DELETE_ROW;
|
||||
let operation = this.createOperation({type, rowIdx});
|
||||
let next = operation.apply(this.value.rows);
|
||||
|
||||
this.operations.push(operation);
|
||||
this.value.rows = next;
|
||||
|
||||
return this.value;
|
||||
}
|
||||
|
||||
insertRow(newRowIdx) {
|
||||
let type = OperationTypes.INSERT_ROW;
|
||||
let operation = this.createOperation({type, newRowIdx});
|
||||
let next = operation.apply(this.value.rows);
|
||||
|
||||
this.operations.push(operation);
|
||||
this.value.rows = next;
|
||||
|
||||
return this.value;
|
||||
}
|
||||
|
||||
deleteColumn(idx) {
|
||||
let type = OperationTypes.DELETE_COLUMN;
|
||||
let operation = this.createOperation({type, idx});
|
||||
let next = operation.apply(this.value.columns);
|
||||
|
||||
this.operations.push(operation);
|
||||
this.value.columns = next;
|
||||
|
||||
return this.value;
|
||||
}
|
||||
|
||||
insertColumn(idx, columnName, columnType) {
|
||||
let type = OperationTypes.INSERT_COLUMN;
|
||||
let operation = this.createOperation({type, idx, columnName, columnType});
|
||||
let next = operation.apply(this.value.columns);
|
||||
|
||||
this.operations.push(operation);
|
||||
this.value.columns = next;
|
||||
|
||||
let value = this.serializeGridData();
|
||||
this.deseralizeGridData(value);
|
||||
|
||||
return this.value;
|
||||
}
|
||||
|
||||
modifyColumn(idx, oldColumnName, newColumnName) {
|
||||
let type = OperationTypes.MODIFY_COLUMN;
|
||||
let operation = this.createOperation({type, idx, oldColumnName, newColumnName});
|
||||
let next = operation.apply(this.value.columns);
|
||||
|
||||
this.operations.push(operation);
|
||||
this.value.columns = next;
|
||||
|
||||
return this.value;
|
||||
}
|
||||
|
||||
modifyCell(rowIdx, updated) {
|
||||
let type = OperationTypes.MODIFY_CELL;
|
||||
let operation = this.createOperation({type, rowIdx, updated});
|
||||
|
||||
let next = operation.apply(this.value.rows);
|
||||
|
||||
this.operations.push(operation);
|
||||
this.value.rows = next;
|
||||
|
||||
return this.value;
|
||||
}
|
||||
|
||||
resizeColumn(idx, width) {
|
||||
let type = OperationTypes.RESIZE_COLUMN;
|
||||
let operation = this.createOperation({type, idx, width});
|
||||
let next = operation.apply(this.value.columns);
|
||||
|
||||
this.operations.push(operation);
|
||||
this.value.columns = next;
|
||||
|
||||
return this.value;
|
||||
}
|
||||
|
||||
}
|
@@ -1,35 +0,0 @@
|
||||
import Operation from './operation';
|
||||
import OperationTypes from './operation-types';
|
||||
|
||||
function invert(operation) {
|
||||
|
||||
let op = new Operation(operation);
|
||||
let { type } = operation;
|
||||
switch(type) {
|
||||
|
||||
case OperationTypes.DELETE_COLUMN : {
|
||||
op.type = OperationTypes.INSERT_COLUMN;
|
||||
return op;
|
||||
}
|
||||
|
||||
case OperationTypes.INSERT_COLUMN : {
|
||||
op.type = OperationTypes.DELETE_COLUMN;
|
||||
return op;
|
||||
}
|
||||
|
||||
case OperationTypes.DELETE_ROW : {
|
||||
op.type = OperationTypes.INSERT_ROW;
|
||||
return op;
|
||||
}
|
||||
|
||||
case OperationTypes.INSERT_ROW : {
|
||||
op.type = OperationTypes.DELETE_ROW;
|
||||
return op;
|
||||
}
|
||||
|
||||
default :
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
export default invert;
|
@@ -1,13 +0,0 @@
|
||||
const OperationTypes = {
|
||||
DELETE_ROW: 'DELETE_NODE',
|
||||
INSERT_ROW: 'INSERT_ROW',
|
||||
DELETE_COLUMN: 'DELETE_COLUMN',
|
||||
INSERT_COLUMN: 'INSERT_COLUMN',
|
||||
MODIFY_CELL: 'MODIFY_CELL',
|
||||
MODIFY_COLUMN: 'MODIFY_COLUMN',
|
||||
RESIZE_COLUMN: 'RESIZE_COLUMN',
|
||||
};
|
||||
|
||||
export default OperationTypes;
|
||||
|
||||
|
@@ -1,20 +0,0 @@
|
||||
import apply from './apply';
|
||||
import invert from './invert';
|
||||
|
||||
export default class Operation {
|
||||
|
||||
constructor(operation) {
|
||||
this.operation = operation;
|
||||
}
|
||||
|
||||
apply(value) {
|
||||
let next = apply(value, this.operation);
|
||||
return next;
|
||||
}
|
||||
|
||||
invert() {
|
||||
let inverted = invert(this);
|
||||
return inverted;
|
||||
}
|
||||
|
||||
}
|
@@ -1,28 +0,0 @@
|
||||
import React from 'react';
|
||||
import { Editors } from '@seafile/react-data-grid-addons';
|
||||
|
||||
const EDITOR_NUMBER = 'number';
|
||||
const EDITOR_TEXT = 'text';
|
||||
|
||||
class EditorFactory {
|
||||
|
||||
createEditor(editorType) {
|
||||
switch(editorType) {
|
||||
case EDITOR_NUMBER: {
|
||||
return <Editors.NumberEditor />;
|
||||
}
|
||||
|
||||
case EDITOR_TEXT: {
|
||||
return '';
|
||||
}
|
||||
|
||||
default: {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let editorFactory = new EditorFactory();
|
||||
|
||||
export default editorFactory;
|
@@ -1,58 +0,0 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import AppHeader from './pages/data-grid/app-header';
|
||||
import AppMain from './pages/data-grid/app-main';
|
||||
import { seafileAPI } from './utils/seafile-api';
|
||||
import { Utils } from './utils/utils';
|
||||
import { gettext } from './utils/constants';
|
||||
import toaster from './components/toast';
|
||||
|
||||
import './css/layout.css';
|
||||
import './css/file-view-data-grid.css';
|
||||
import './css/react-context-menu.css';
|
||||
|
||||
const { repoID, fileName, filePath } = window.app.pageOptions;
|
||||
|
||||
class ViewFileSDB extends React.Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
isContentChanged: false,
|
||||
};
|
||||
}
|
||||
|
||||
onContentChanged = () => {
|
||||
this.setState({isContentChanged: true});
|
||||
}
|
||||
|
||||
onSave = () => {
|
||||
this.setState({isContentChanged: false});
|
||||
|
||||
let data = this.refs.data_grid.serializeGridData();
|
||||
|
||||
let dirPath = Utils.getDirName(filePath);
|
||||
seafileAPI.getUpdateLink(repoID, dirPath).then(res => {
|
||||
let updateLink = res.data;
|
||||
seafileAPI.updateFile(updateLink, filePath, fileName, JSON.stringify(data)).then(res => {
|
||||
toaster.success(gettext('File saved.'));
|
||||
}).catch(() => {
|
||||
toaster.success(gettext('File save failed.'));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Fragment>
|
||||
<AppHeader onSave={this.onSave} isContentChanged={this.state.isContentChanged} />
|
||||
<AppMain ref="data_grid" onContentChanged={this.onContentChanged} onSave={this.onSave} />
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ReactDOM.render(
|
||||
<ViewFileSDB />,
|
||||
document.getElementById('wrapper')
|
||||
);
|
Reference in New Issue
Block a user