diff --git a/frontend/config/webpack.config.dev.js b/frontend/config/webpack.config.dev.js
index 037270d9db..f6739e5e91 100644
--- a/frontend/config/webpack.config.dev.js
+++ b/frontend/config/webpack.config.dev.js
@@ -213,6 +213,11 @@ module.exports = {
require.resolve('./polyfills'),
require.resolve('react-dev-utils/webpackHotDevClient'),
paths.appSrc + "/pages/search",
+ ],
+ appDTable: [
+ require.resolve('./polyfills'),
+ require.resolve('react-dev-utils/webpackHotDevClient'),
+ paths.appSrc + "/app-dtable",
]
},
diff --git a/frontend/config/webpack.config.prod.js b/frontend/config/webpack.config.prod.js
index 3c5c7f590f..77cb530de1 100644
--- a/frontend/config/webpack.config.prod.js
+++ b/frontend/config/webpack.config.prod.js
@@ -90,7 +90,8 @@ module.exports = {
sysAdmin: [require.resolve('./polyfills'), paths.appSrc + "/pages/sys-admin"],
viewDataGrid: [require.resolve('./polyfills'), paths.appSrc + "/view-file-dtable.js"],
viewCdoc: [require.resolve('./polyfills'), paths.appSrc + "/view-file-cdoc.js"],
- search: [require.resolve('./polyfills'), paths.appSrc + "/pages/search"]
+ search: [require.resolve('./polyfills'), paths.appSrc + "/pages/search"],
+ appDTable: [require.resolve('./polyfills'), paths.appSrc + "/app-dtable"],
},
output: {
diff --git a/frontend/src/app-dtable.js b/frontend/src/app-dtable.js
new file mode 100644
index 0000000000..4b1c1775b3
--- /dev/null
+++ b/frontend/src/app-dtable.js
@@ -0,0 +1,46 @@
+import React from 'react';
+import ReactDOM from 'react-dom';
+import SidePanel from './pages/dtable/side-panel';
+import MainPanel from './pages/dtable/main-panel';
+
+import './css/layout.css';
+import './css/side-panel.css';
+import './css/dtable.css';
+
+class AppDTable extends React.Component {
+
+ constructor(props) {
+ super(props);
+ this.state = {
+ currentTab: 'dtable',
+ }
+ }
+
+ componentDidMount() {
+ const seletedTabs = ['apps', 'templetes'];
+ let paths = location.href.split('/');
+ let tab = paths[paths.indexOf('dtable') + 1];
+ let currentTab = seletedTabs.indexOf(tab) > -1 ? tab : 'dtable';
+ this.setState({currentTab: currentTab});
+ }
+
+ onTabClick = (tab) => {
+ if (tab !== this.state.currentTab) {
+ this.setState({currentTab: tab});
+ }
+ }
+
+ render() {
+ return (
+
+
- {this.state.isTableRenaming &&
+ {this.state.isTableRenaming && (
- }
- {!this.state.isTableRenaming &&
-
{table.name}
- }
+ )}
+ {!this.state.isTableRenaming &&
{table.name}}
- {this.state.active &&
+ {this.state.active && (
- {gettext('Rename')}
- {gettext('Delete')}
- {gettext('Share')}
+ {gettext('Rename')}
+ {gettext('Delete')}
+ {gettext('Share')}
- }
- {this.state.isTableDeleting &&
-
- }
- {this.state.isTableSharing &&
-
- }
+ )}
);
}
}
-ListTableItem.propTypes = propTypes;
+DTableItemCommon.propTypes = propTypes;
-export default ListTableItem;
+export default DTableItemCommon;
diff --git a/frontend/src/pages/dtable/share-table-item.js b/frontend/src/pages/dtable/dtable-item-shared.js
similarity index 75%
rename from frontend/src/pages/dtable/share-table-item.js
rename to frontend/src/pages/dtable/dtable-item-shared.js
index 9696abe0db..4bd111a7e8 100644
--- a/frontend/src/pages/dtable/share-table-item.js
+++ b/frontend/src/pages/dtable/dtable-item-shared.js
@@ -1,15 +1,15 @@
-import React, {Component} from 'react';
+import React from 'react';
import PropTypes from 'prop-types';
-import {gettext, siteRoot} from '../../utils/constants';
-import '../../css/dtable-page.css';
+const gettext = window.gettext;
+const { siteRoot } = window.app.config;
-const shareTableItemPropTypes = {
+const propTypes = {
table: PropTypes.object.isRequired,
leaveShareTable: PropTypes.func.isRequired,
};
-class ShareTableItem extends Component {
+class DTableItemShared extends React.Component {
constructor(props) {
super(props);
@@ -18,23 +18,20 @@ class ShareTableItem extends Component {
};
}
+
+ onMouseEnter = () => {
+ this.setState({active: true});
+ };
+
+ onMouseLeave = () => {
+ this.setState({active: false});
+ };
+
onLeaveShareTableSubmit = () => {
let table = this.props.table;
this.props.leaveShareTable(table);
};
-
- onMouseEnter = () => {
- this.setState({
- active: true
- });
- };
-
- onMouseLeave = () => {
- this.setState({
- active: false
- });
- };
-
+
render() {
let table = this.props.table;
let tableHref = siteRoot + 'workspace/' + table.workspace_id + '/dtable/' + table.name + '/';
@@ -59,6 +56,6 @@ class ShareTableItem extends Component {
}
}
-ShareTableItem.propTypes = shareTableItemPropTypes;
+DTableItemShared.propTypes = propTypes;
-export default ShareTableItem;
\ No newline at end of file
+export default DTableItemShared;
diff --git a/frontend/src/pages/dtable/dtable-workspace-common.js b/frontend/src/pages/dtable/dtable-workspace-common.js
new file mode 100644
index 0000000000..15c5694b12
--- /dev/null
+++ b/frontend/src/pages/dtable/dtable-workspace-common.js
@@ -0,0 +1,192 @@
+import React, { Fragment } from 'react';
+import PropTypes from 'prop-types';
+import { seafileAPI } from '../../utils/seafile-api';
+import Loading from '../../components/loading';
+import DTableItemCommon from './dtable-item-common';
+import CreateTableDialog from '../../components/dialog/create-table-dialog';
+import DeleteTableDialog from '../../components/dialog/delete-table-dialog';
+import ShareTableDialog from '../../components/dialog/share-table-dialog';
+
+const gettext = window.gettext;
+
+const propTypes = {
+ workspace: PropTypes.object.isRequired,
+};
+
+class DTableWorkspaceCommon extends React.Component {
+
+ constructor(props) {
+ super(props);
+ this.state = {
+ tableList: [],
+ isDataLoading: true,
+ isItemFreezed: false,
+ isShowCreateDialog: false,
+ isShowDeleteDialog: false,
+ isShowSharedDialog: false,
+ currentTable: null,
+ }
+ }
+
+ componentDidMount() {
+ let workspace = this.props.workspace;
+ let tableList = workspace.table_list;
+ this.setState({
+ tableList: tableList,
+ isDataLoading: false,
+ });
+ }
+
+ componentWillReceiveProps(nextProps) {
+ if (nextProps.workspace !== this.props.workspace) {
+ let workspace = nextProps.workspace;
+ let tableList = workspace.table_list;
+ this.setState({tableList: tableList});
+ }
+ }
+
+ onFreezedItem = () => {
+ this.setState({isItemFreezed: true});
+ }
+
+ onUnfreezedItem = () => {
+ this.setState({isItemFreezed: false});
+ }
+
+ onCreateTableToggle = () => {
+ this.setState({isShowCreateDialog: !this.state.isShowCreateDialog});
+ }
+
+ onDeleteTableToggle = (table) => {
+ this.setState({
+ isShowDeleteDialog: !this.state.isShowDeleteDialog,
+ currentTable: table
+ });
+ this.onUnfreezedItem();
+ }
+
+ onDeleteTableSubmit = () => {
+ let tableName = this.state.currentTable.name;
+ this.deleteTable(tableName);
+ this.onDeleteTableToggle();
+ }
+
+ onShareTableToggle = (table) => {
+ this.setState({
+ isShowSharedDialog: !this.state.isShowSharedDialog,
+ currentTable: table
+ });
+ this.onUnfreezedItem();
+ }
+
+ onCreateTable = (tableName, owner) => {
+ seafileAPI.createTable(tableName, owner).then((res) => {
+ this.state.tableList.push(res.data.table);
+ this.setState({
+ tableList: this.state.tableList
+ });
+ }).catch((error) => {
+ if(error.response) {
+ this.setState({errorMsg: gettext('Error')});
+ }
+ });
+
+ this.onCreateTableToggle();
+ }
+
+ deleteTable = (tableName) => {
+ let workspaceID = this.props.workspace.id;
+ seafileAPI.deleteTable(workspaceID, tableName).then(() => {
+ let tableList = this.state.tableList.filter(table => {
+ return table.name !== tableName;
+ });
+ this.setState({tableList: tableList});
+ }).catch((error) => {
+ if(error.response) {
+ this.setState({errorMsg: gettext('Error')});
+ }
+ });
+ }
+
+ renameTable = (oldTableName, newTableName) => {
+ let workspaceID = this.props.workspace.id;
+ seafileAPI.renameTable(workspaceID, oldTableName, newTableName).then((res) => {
+ let tableList = this.state.tableList.map((table) => {
+ if (table.name === oldTableName) {
+ table = res.data.table;
+ }
+ return table;
+ });
+ this.setState({tableList: tableList});
+ }).catch((error) => {
+ if(error.response) {
+ this.setState({errorMsg: gettext('Error')});
+ }
+ });
+ }
+
+ render() {
+ let { isDataLoading } = this.state;
+ if (isDataLoading) {
+ return
+ }
+
+ let { workspace } = this.props;
+ let { tableList, isItemFreezed } = this.state;
+ let isPersonal = workspace.owner_type === 'Personal';
+
+ return (
+
+
+
{isPersonal ? gettext('My Tables') : workspace.owner_name}
+
+ {tableList.map((table, index) => {
+ return (
+
+ );
+ })}
+
+
+
+ {this.state.isShowCreateDialog && (
+
+ )}
+ {this.state.isShowDeleteDialog && (
+
+ )}
+ {this.state.isShowSharedDialog &&
+
+ }
+
+ );
+ }
+}
+
+
+DTableWorkspaceCommon.propTypes = propTypes;
+
+export default DTableWorkspaceCommon;
diff --git a/frontend/src/pages/dtable/dtable-workspace-shared.js b/frontend/src/pages/dtable/dtable-workspace-shared.js
new file mode 100644
index 0000000000..3965c65246
--- /dev/null
+++ b/frontend/src/pages/dtable/dtable-workspace-shared.js
@@ -0,0 +1,78 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import DTableItemShared from './dtable-item-shared';
+import Loading from '../../components/loading';
+import { seafileAPI } from '../../utils/seafile-api';
+
+const gettext = window.gettext;
+const username = window.app.pageOptions.username;
+
+const propTypes = {
+ tableList: PropTypes.array.isRequired,
+};
+
+class DTableWorkspaceShared extends React.Component {
+
+ constructor(props) {
+ super(props);
+ this.state = {
+ isDataLoading: true,
+ tableList: [],
+ };
+ }
+
+ componentDidMount() {
+ let tableList = this.props.tableList;
+ this.setState({
+ isDataLoading: false,
+ tableList: tableList,
+ });
+ }
+
+ leaveShareTable = (table) => {
+ let email = username;
+ let tableName = table.name;
+ let workspaceID = table.workspace_id;
+ seafileAPI.deleteTableShare(workspaceID, tableName, email).then(() => {
+ let tableList = this.state.tableList.filter(table => {
+ return table.name !== tableName;
+ });
+ this.setState({tableList: tableList});
+ }).catch((error) => {
+ if(error.response) {
+ this.setState({errorMsg: gettext('Error')});
+ } else {
+ this.setState({
+ errorMsg: gettext('Please check the network.')
+ });
+ }
+ });
+ }
+
+ render() {
+ if (this.state.isDataLoading) {
+ return
+ }
+
+ if (!this.state.tableList.length) {
+ return "";
+ }
+
+ return (
+
+
{gettext('Shared with me')}
+
+ {this.state.tableList.map((table, index) => {
+ return (
+
+ );
+ })}
+
+
+ );
+ }
+}
+
+DTableWorkspaceShared.propTypes = propTypes;
+
+export default DTableWorkspaceShared;
diff --git a/frontend/src/pages/dtable/dtable.js b/frontend/src/pages/dtable/dtable.js
deleted file mode 100644
index 8a0e8e60d7..0000000000
--- a/frontend/src/pages/dtable/dtable.js
+++ /dev/null
@@ -1,228 +0,0 @@
-import React, { Component, Fragment } from 'react';
-import PropTypes from 'prop-types';
-import MediaQuery from 'react-responsive';
-import { Button } from 'reactstrap';
-import { seafileAPI } from '../../utils/seafile-api';
-import { gettext, username } from '../../utils/constants';
-import CommonToolbar from '../../components/toolbar/common-toolbar';
-import Loading from '../../components/loading';
-import CreateTableDialog from '../../components/dialog/create-table-dialog';
-import ShareTableItem from './share-table-item';
-import Workspace from './workspace';
-
-import '../../css/dtable-page.css';
-
-const propTypes = {
- onShowSidePanel: PropTypes.func.isRequired,
- onSearchedClick: PropTypes.func.isRequired,
-};
-
-class DTable extends Component {
-
- constructor(props) {
- super(props);
- this.state = {
- loading: true,
- shareTableLoading: true,
- errorMsg: '',
- workspaceList: [],
- shareTableList: [],
- isShowAddDTableDialog: false,
- currentWorkspace: null,
- };
- }
-
- componentDidMount() {
- this.listWorkspaces();
- this.listSharedTables();
- }
-
- onAddDTable = () => {
- this.setState({ isShowAddDTableDialog: !this.state.isShowAddDTableDialog });
- }
-
- newDtable = () => {
- if (this.state.currentWorkspace) {
- this.setState({ currentWorkspace: null });
- }
- this.onAddDTable();
- }
-
- setCurrentWorkspace = (currentWorkspace) => {
- this.setState({ currentWorkspace: currentWorkspace });
- }
-
- createDTable = (tableName, owner) => {
- seafileAPI.createTable(tableName, owner).then(() => {
- this.listWorkspaces();
- }).catch((error) => {
- if(error.response) {
- this.setState({errorMsg: gettext('Error')});
- }
- });
- this.onAddDTable();
- }
-
- listWorkspaces = () => {
- seafileAPI.listWorkspaces().then((res) => {
- this.setState({
- loading: false,
- workspaceList: res.data.workspace_list,
- });
- }).catch((error) => {
- if (error.response) {
- this.setState({
- loading: false,
- errorMsg: gettext('Error')
- });
- } else {
- this.setState({
- loading: false,
- errorMsg: gettext('Please check the network.')
- });
- }
- });
- }
-
- listSharedTables = () => {
- seafileAPI.listSharedTables().then((res) => {
- this.setState({
- shareTableLoading: false,
- shareTableList: res.data.table_list,
- });
- }).catch((error) => {
- if (error.response) {
- this.setState({
- shareTableLoading: false,
- errorMsg: gettext('Error')
- });
- } else {
- this.setState({
- shareTableLoading: false,
- errorMsg: gettext('Please check the network.')
- });
- }
- });
- }
-
- leaveShareTable = (table) => {
- let email = username;
- let tableName = table.name;
- let workspaceID = table.workspace_id;
- seafileAPI.deleteTableShare(workspaceID, tableName, email).then(() => {
- let shareTableList = this.state.shareTableList.filter(table => {
- return table.name !== tableName;
- });
- this.setState({shareTableList: shareTableList});
- }).catch((error) => {
- if(error.response) {
- this.setState({errorMsg: gettext('Error')});
- } else {
- this.setState({
- errorMsg: gettext('Please check the network.')
- });
- }
- });
- }
-
- renderShareTablePanel = () => {
- return (
-
-
{gettext('Shared with me')}
-
- {this.state.shareTableList.map((table, index) => {
- return (
-
- );
- })}
-
-
- );
- }
-
- render() {
- const { workspaceList, loading } = this.state;
-
- let personalWorkspaceList = workspaceList.filter(workspace => {
- return workspace.owner_type === 'Personal';
- });
- let personalWorkspaceMessage = personalWorkspaceList[0];
- let groupWorkspaceList = workspaceList.filter(workspace => {
- return workspace.owner_type === 'Group';
- });
-
- if (loading) {
- return(
);
- }
-
- return (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
DTable
-
-
- {this.state.errorMsg &&
-
{this.state.errorMsg}
- }
-
- {(!this.state.shareTableLoading && this.state.shareTableList.length > 0) &&
- this.renderShareTablePanel()
- }
- {
- groupWorkspaceList.map((workspace, index) => {
- return (
-
- );
- })
- }
- {this.state.isShowAddDTableDialog &&
-
-
-
- }
-
-
-
-
- );
- }
-}
-
-DTable.propTypes = propTypes;
-
-export default DTable;
diff --git a/frontend/src/pages/dtable/main-panel-apps.js b/frontend/src/pages/dtable/main-panel-apps.js
new file mode 100644
index 0000000000..1173bdc7f5
--- /dev/null
+++ b/frontend/src/pages/dtable/main-panel-apps.js
@@ -0,0 +1,19 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+
+const propTypes = {
+
+};
+
+class MainPanelApps extends React.Component {
+
+ render() {
+ return (
+
apps
+ );
+ }
+}
+
+MainPanelApps.propTypes = propTypes;
+
+export default MainPanelApps;
diff --git a/frontend/src/pages/dtable/main-panel-dtables.js b/frontend/src/pages/dtable/main-panel-dtables.js
new file mode 100644
index 0000000000..2e266841d6
--- /dev/null
+++ b/frontend/src/pages/dtable/main-panel-dtables.js
@@ -0,0 +1,139 @@
+import React, { Fragment } from 'react';
+import PropTypes from 'prop-types';
+import Loading from '../../components/loading';
+import { gettext } from '../../utils/constants';
+import { seafileAPI } from '../../utils/seafile-api';
+import Workspace from './model/workspace';
+import DTableWorkspaceCommon from './dtable-workspace-common';
+import DTableWorkspaceShared from './dtable-workspace-shared';
+import CreateTableDialog from '../../components/dialog/create-table-dialog';
+
+const propTypes = {
+
+};
+
+class MainPanelDTables extends React.Component {
+
+ constructor(props) {
+ super(props);
+ this.state = {
+ errorMsg: null,
+ workspaceList: [],
+ sharedTableList: [],
+ isWorkspaceListLoading: true,
+ isSharedTableListLoading: true,
+ isShowCreateDialog: false
+ }
+ }
+
+ componentDidMount() {
+ this.loadWorkspaceList();
+ this.loadSharedTableList();
+ }
+
+ loadWorkspaceList = () => {
+ seafileAPI.listWorkspaces().then((res) => {
+ let workspaceList = res.data.workspace_list.map(item => {
+ return new Workspace(item);
+ });
+ this.setState({
+ isWorkspaceListLoading: false,
+ workspaceList: workspaceList,
+ });
+ }).catch((error) => {
+ this.errorCallbackHandle(error);
+ });
+ }
+
+ loadSharedTableList = () => {
+ seafileAPI.listSharedTables().then((res) => {
+ this.setState({
+ isSharedTableListLoading: false,
+ sharedTableList: res.data.table_list,
+ });
+ }).catch((error) => {
+ this.errorCallbackHandle(error);
+ });
+ }
+
+ errorCallbackHandle = (error) => {
+ if (error.response) {
+ this.setState({
+ loading: false,
+ errorMsg: gettext('Error')
+ });
+ } else {
+ this.setState({
+ loading: false,
+ errorMsg: gettext('Please check the network.')
+ });
+ }
+ }
+
+ onCreateTableToggle = () => {
+ this.setState({isShowCreateDialog: !this.state.isShowCreateDialog});
+ }
+
+ onCreateTable = (tableName, owner) => {
+ seafileAPI.createTable(tableName, owner).then(() => {
+ this.loadWorkspaceList();
+ }).catch((error) => {
+ if(error.response) {
+ this.setState({errorMsg: gettext('Error')});
+ }
+ });
+
+ this.onCreateTableToggle();
+ }
+
+ render() {
+ let { isWorkspaceListLoading, isSharedTableListLoading } = this.state;
+ if (isWorkspaceListLoading || isSharedTableListLoading) {
+ return
+ }
+
+ let { workspaceList, sharedTableList } = this.state;
+ let personalWorkspace = workspaceList.find(workspace => {
+ return workspace.owner_type === 'Personal';
+ });
+
+ let groupWorkspaceList = workspaceList.filter(workspace => {
+ return workspace.owner_type === 'Group';
+ });
+
+ return (
+
+
+
+
DTable
+
+ {this.state.errorMsg &&
+
{this.state.errorMsg}
+ }
+ {!this.state.errorMsg && (
+
+
+
+ {groupWorkspaceList.length > 0 && groupWorkspaceList.map((workspace, index) => {
+ return ()
+ })}
+
+
+ )}
+
+
+
+ {this.state.isShowCreateDialog && (
+
+ )}
+
+ );
+ }
+}
+
+MainPanelDTables.propTypes = propTypes;
+
+export default MainPanelDTables;
diff --git a/frontend/src/pages/dtable/main-panel-templetes.js b/frontend/src/pages/dtable/main-panel-templetes.js
new file mode 100644
index 0000000000..daf60f505b
--- /dev/null
+++ b/frontend/src/pages/dtable/main-panel-templetes.js
@@ -0,0 +1,19 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+
+const propTypes = {
+
+};
+
+class MainPanelTempletes extends React.Component {
+
+ render() {
+ return (
+
templetes
+ );
+ }
+}
+
+MainPanelTempletes.propTypes = propTypes;
+
+export default MainPanelTempletes;
diff --git a/frontend/src/pages/dtable/main-panel.js b/frontend/src/pages/dtable/main-panel.js
new file mode 100644
index 0000000000..18f333b4ef
--- /dev/null
+++ b/frontend/src/pages/dtable/main-panel.js
@@ -0,0 +1,40 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { Router } from '@reach/router'
+import MainPanelDTables from './main-panel-dtables';
+import MainPanelApps from './main-panel-apps';
+import MainPanelTempletes from './main-panel-templetes';
+
+
+const siteRoot = window.app.config.siteRoot;
+
+
+const propTypes = {
+
+};
+
+class MainPanel extends React.Component {
+
+ render() {
+ return (
+
+
+
+
Search
+
Notification
+
+
+
+
+
+
+
+
+
+ );
+ }
+}
+
+MainPanel.propTypes = propTypes;
+
+export default MainPanel;
diff --git a/frontend/src/pages/dtable/model/workspace.js b/frontend/src/pages/dtable/model/workspace.js
new file mode 100644
index 0000000000..84360665e2
--- /dev/null
+++ b/frontend/src/pages/dtable/model/workspace.js
@@ -0,0 +1,12 @@
+class Workspace {
+
+ constructor(obj) {
+ this.id = obj.id || '';
+ this.owner_name = obj.owner_name || '';
+ this.owner_type = obj.owner_type || '';
+ this.table_list = obj.table_list || [];
+ }
+
+}
+
+export default Workspace;
\ No newline at end of file
diff --git a/frontend/src/pages/dtable/side-panel.js b/frontend/src/pages/dtable/side-panel.js
new file mode 100644
index 0000000000..a79a9090be
--- /dev/null
+++ b/frontend/src/pages/dtable/side-panel.js
@@ -0,0 +1,63 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { Link } from '@reach/router';
+
+const gettext = window.gettext;
+const siteRoot = window.app.config.siteRoot;
+
+const propTypes = {
+ currentTab: PropTypes.string.isRequired,
+ onTabClick: PropTypes.func.isRequired,
+};
+
+class SidePanel extends React.Component {
+
+ onTabClick = (tab) => {
+ this.props.onTabClick(tab);
+ }
+
+ getActiveClass = (tab) => {
+ return this.props.currentTab === tab ? 'active' : '';
+ }
+
+ render() {
+
+ return (
+
+
+
+ DTable
+
+
+
+
{gettext('Main')}
+
+ -
+
+
+ {gettext('DTable')}
+
+
+ -
+
+
+ {gettext('Apps')}
+
+
+ -
+
+
+ {gettext('Templetes')}
+
+
+
+
+
+
+ );
+ }
+}
+
+SidePanel.propTypes = propTypes;
+
+export default SidePanel;
diff --git a/frontend/src/pages/dtable/workspace.js b/frontend/src/pages/dtable/workspace.js
deleted file mode 100644
index 886846575f..0000000000
--- a/frontend/src/pages/dtable/workspace.js
+++ /dev/null
@@ -1,122 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import { seafileAPI } from '../../utils/seafile-api';
-import { gettext } from '../../utils/constants';
-import ListTableItem from './list-table-item';
-
-const propTypes = {
- workspace: PropTypes.object.isRequired,
- setCurrentWorkspace: PropTypes.func.isRequired,
- onAddDTable: PropTypes.func.isRequired,
-};
-
-class Workspace extends React.Component {
-
- constructor(props) {
- super(props);
- this.state = {
- tableList: props.workspace.table_list,
- errorMsg: '',
- isItemFreezed: false,
- };
- }
-
- componentWillReceiveProps(nextProps) {
- if (nextProps.workspace.table_list !== this.props.workspace.table_list) {
- this.setState({
- tableList: nextProps.workspace.table_list
- });
- }
- }
-
- onFreezedItem = () => {
- this.setState({isItemFreezed: true});
- }
-
- onUnfreezedItem = () => {
- this.setState({isItemFreezed: false});
- }
-
- renameTable = (oldTableName, newTableName) => {
- let workspaceID = this.props.workspace.id;
- seafileAPI.renameTable(workspaceID, oldTableName, newTableName).then((res) => {
- let tableList = this.state.tableList.map((table) => {
- if (table.name === oldTableName) {
- table = res.data.table;
- }
- return table;
- });
- this.setState({tableList: tableList});
- }).catch((error) => {
- if(error.response) {
- this.setState({errorMsg: gettext('Error')});
- }
- });
- }
-
- deleteTable = (tableName) => {
- let workspaceID = this.props.workspace.id;
- seafileAPI.deleteTable(workspaceID, tableName).then(() => {
- let tableList = this.state.tableList.filter(table => {
- return table.name !== tableName;
- });
- this.setState({tableList: tableList});
- }).catch((error) => {
- if(error.response) {
- this.setState({errorMsg: gettext('Error')});
- }
- });
- }
-
- addTable = (e) => {
- e.preventDefault();
- this.props.setCurrentWorkspace(this.props.workspace);
- this.props.onAddDTable();
- }
-
- render() {
- let workspace = this.props.workspace;
- let isPersonal = workspace.owner_type === 'Personal';
- let { tableList, isItemFreezed } = this.state;
-
- return(
-
-
0 ? '' : 'table-heading-border'}`}>{isPersonal ? gettext('My Tables') : workspace.owner_name}
- {tableList.length > 0 ?
-
- {tableList.map((table, index) => {
- return (
-
- );
- })}
-
-
- :
-
-
- {gettext('No Tables')} |
-
-
- }
-
- );
- }
-
-}
-
-Workspace.propTypes = propTypes;
-
-export default Workspace;
\ No newline at end of file
diff --git a/media/css/seahub_react.css b/media/css/seahub_react.css
index 5afb8190de..86d8b55251 100644
--- a/media/css/seahub_react.css
+++ b/media/css/seahub_react.css
@@ -579,6 +579,37 @@ ul,ol,li {
padding:12px;
}
+.side-nav-link {
+ display: flex;
+ margin: 24px 12px;
+ color: #FFFFFF;
+ border-radius: 0.25rem;
+ background-color: #FEAC74;
+}
+
+.side-nav-link:hover {
+ background-color: #F3985A;
+ cursor: pointer;
+}
+
+.side-nav-link .link-icon {
+ padding: 0 0.5rem;
+ font-size: 1.5rem;
+}
+
+.side-nav-link .link-icon.icon-right {
+ display: flex;
+ align-items: center;
+ font-size: 1rem;
+}
+
+.side-nav-link .link-text {
+ display: flex;
+ flex: 1;
+ align-items: center;
+ padding-left: 0.25rem;
+}
+
.side-nav-footer {
display:flex;
flex-shrink:0;
diff --git a/seahub/templates/react_dtable.html b/seahub/templates/react_dtable.html
new file mode 100644
index 0000000000..677c146db2
--- /dev/null
+++ b/seahub/templates/react_dtable.html
@@ -0,0 +1,55 @@
+{% load seahub_tags i18n staticfiles %}
+{% load render_bundle from webpack_loader %}
+
+
+
+
+
DTable
+
+
+
+
+
+
+
+
+
+
+{% render_bundle 'appDTable' 'css' %}
+{% if branding_css != '' %}
{% endif %}
+{% if enable_branding_css %}
{% endif %}
+
+
+
+
+
+
+
+
+{% render_bundle 'commons' %}
+{% render_bundle 'appDTable' 'js' %}
+
+
+
diff --git a/seahub/urls.py b/seahub/urls.py
index 85470677bd..ba2761557f 100644
--- a/seahub/urls.py
+++ b/seahub/urls.py
@@ -237,7 +237,9 @@ urlpatterns = [
url(r'^my-libs/deleted/$', react_fake_view, name="my_libs_deleted"),
url(r'^org/$', react_fake_view, name="org"),
url(r'^invitations/$', react_fake_view, name="invitations"),
- url(r'^dtable/$', react_fake_view, name='dtable'),
+ url(r'^dtable/$', dtable_fake_view, name='dtable'),
+ url(r'^dtable/apps/$', dtable_fake_view, name='dtable'),
+ url(r'^dtable/templetes/$', dtable_fake_view, name='dtable'),
### Ajax ###
url(r'^ajax/repo/(?P
[-0-9a-f]{36})/dirents/$', get_dirents, name="get_dirents"),
diff --git a/seahub/views/__init__.py b/seahub/views/__init__.py
index d1e76a2723..25b347fc48 100644
--- a/seahub/views/__init__.py
+++ b/seahub/views/__init__.py
@@ -1269,3 +1269,7 @@ def react_fake_view(request, **kwargs):
'folder_perm_enabled': folder_perm_enabled,
'file_audit_enabled' : FILE_AUDIT_ENABLED
})
+
+@login_required
+def dtable_fake_view(request, **kwargs):
+ return render(request, 'react_dtable.html')