mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-03 07:55:36 +00:00
Dtable homepage (#4120)
* dtable homepage * style * add search dtable * warning * logo url * dtable-logo
This commit is contained in:
@@ -7,13 +7,6 @@
|
|||||||
height: 50px;
|
height: 50px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dtable-header .dtable-logo {
|
|
||||||
padding-right: 6px;
|
|
||||||
font-size: 36px;
|
|
||||||
line-height: 36px;
|
|
||||||
color: #FEAC74;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dtable-header .dtable-text {
|
.dtable-header .dtable-text {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -23,6 +16,10 @@
|
|||||||
|
|
||||||
.dtable-side-nav {
|
.dtable-side-nav {
|
||||||
padding: 12px;
|
padding: 12px;
|
||||||
|
flex: auto;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dtable-nav-title {
|
.dtable-nav-title {
|
||||||
@@ -69,14 +66,17 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.dtable-header .common-toolbar>div {
|
.dtable-header .common-toolbar>div {
|
||||||
padding-right: 1rem;
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
margin-left: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dtable-center .cur-view-title {
|
.dtable-center .cur-view-header {
|
||||||
line-height: 50px;
|
line-height: 50px;
|
||||||
font-size: 1.5rem;
|
font-size: 1.5rem;
|
||||||
padding-left: 12px;
|
padding: 0 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dtable-center .cur-view-header .cur-view-title {
|
||||||
border-bottom: 1px solid #eee;
|
border-bottom: 1px solid #eee;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,6 +154,7 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
min-height: 0;
|
||||||
}
|
}
|
||||||
.workspace .table-item-container .table-item {
|
.workspace .table-item-container .table-item {
|
||||||
width: 48%;
|
width: 48%;
|
||||||
@@ -178,6 +179,7 @@
|
|||||||
width: 15%;
|
width: 15%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
.workspace .table-item .table-dropdown-menu .table-dropdown-menu-icon {
|
.workspace .table-item .table-dropdown-menu .table-dropdown-menu-icon {
|
||||||
width: 24px;
|
width: 24px;
|
||||||
|
@@ -27,7 +27,7 @@ class DTableWorkspaceCommon extends React.Component {
|
|||||||
isShowSharedDialog: false,
|
isShowSharedDialog: false,
|
||||||
isShowAPITokenDialog: false,
|
isShowAPITokenDialog: false,
|
||||||
currentTable: null,
|
currentTable: null,
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
@@ -138,7 +138,7 @@ class DTableWorkspaceCommon extends React.Component {
|
|||||||
render() {
|
render() {
|
||||||
let { isDataLoading } = this.state;
|
let { isDataLoading } = this.state;
|
||||||
if (isDataLoading) {
|
if (isDataLoading) {
|
||||||
return <Loading />
|
return <Loading />;
|
||||||
}
|
}
|
||||||
|
|
||||||
let { workspace } = this.props;
|
let { workspace } = this.props;
|
||||||
|
@@ -51,11 +51,11 @@ class DTableWorkspaceShared extends React.Component {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
if (this.state.isDataLoading) {
|
if (this.state.isDataLoading) {
|
||||||
return <Loading />
|
return <Loading />;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.state.tableList.length) {
|
if (!this.state.tableList.length) {
|
||||||
return "";
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@@ -23,7 +23,7 @@ class MainPanelDTables extends React.Component {
|
|||||||
isWorkspaceListLoading: true,
|
isWorkspaceListLoading: true,
|
||||||
isSharedTableListLoading: true,
|
isSharedTableListLoading: true,
|
||||||
isShowCreateDialog: false
|
isShowCreateDialog: false
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
@@ -89,7 +89,7 @@ class MainPanelDTables extends React.Component {
|
|||||||
render() {
|
render() {
|
||||||
let { isWorkspaceListLoading, isSharedTableListLoading } = this.state;
|
let { isWorkspaceListLoading, isSharedTableListLoading } = this.state;
|
||||||
if (isWorkspaceListLoading || isSharedTableListLoading) {
|
if (isWorkspaceListLoading || isSharedTableListLoading) {
|
||||||
return <Loading />
|
return <Loading />;
|
||||||
}
|
}
|
||||||
|
|
||||||
let { workspaceList, sharedTableList } = this.state;
|
let { workspaceList, sharedTableList } = this.state;
|
||||||
@@ -104,8 +104,10 @@ class MainPanelDTables extends React.Component {
|
|||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<div className="main-panel-center dtable-center">
|
<div className="main-panel-center dtable-center">
|
||||||
<div className="main-panel-container d-flex flex-1 flex-column">
|
<div className="cur-view-container d-flex flex-1 flex-column">
|
||||||
|
<div className="cur-view-header">
|
||||||
<div className="cur-view-title">DTable</div>
|
<div className="cur-view-title">DTable</div>
|
||||||
|
</div>
|
||||||
<div className="cur-view-content">
|
<div className="cur-view-content">
|
||||||
{this.state.errorMsg &&
|
{this.state.errorMsg &&
|
||||||
<p className="error text-center">{this.state.errorMsg}</p>
|
<p className="error text-center">{this.state.errorMsg}</p>
|
||||||
@@ -115,7 +117,7 @@ class MainPanelDTables extends React.Component {
|
|||||||
<DTableWorkspaceCommon workspace={personalWorkspace} />
|
<DTableWorkspaceCommon workspace={personalWorkspace} />
|
||||||
<DTableWorkspaceShared tableList={sharedTableList} />
|
<DTableWorkspaceShared tableList={sharedTableList} />
|
||||||
{groupWorkspaceList.length > 0 && groupWorkspaceList.map((workspace, index) => {
|
{groupWorkspaceList.length > 0 && groupWorkspaceList.map((workspace, index) => {
|
||||||
return (<DTableWorkspaceCommon key={index} workspace={workspace} />)
|
return (<DTableWorkspaceCommon key={index} workspace={workspace} />);
|
||||||
})}
|
})}
|
||||||
<button className="btn btn-secondary dtable-add-btn mb-4" onClick={this.onCreateTableToggle}>{gettext('New DTable')}</button>
|
<button className="btn btn-secondary dtable-add-btn mb-4" onClick={this.onCreateTableToggle}>{gettext('New DTable')}</button>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
|
@@ -1,10 +1,14 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { Router } from '@reach/router'
|
import { Router } from '@reach/router';
|
||||||
|
import Notification from '../../components/common/notification';
|
||||||
|
import Account from '../../components/common/account';
|
||||||
|
import Search from './search/search';
|
||||||
import MainPanelDTables from './main-panel-dtables';
|
import MainPanelDTables from './main-panel-dtables';
|
||||||
import MainPanelApps from './main-panel-apps';
|
import MainPanelApps from './main-panel-apps';
|
||||||
import MainPanelTempletes from './main-panel-templetes';
|
import MainPanelTempletes from './main-panel-templetes';
|
||||||
|
|
||||||
|
import '../../css/search.css';
|
||||||
|
|
||||||
const siteRoot = window.app.config.siteRoot;
|
const siteRoot = window.app.config.siteRoot;
|
||||||
|
|
||||||
@@ -15,14 +19,25 @@ const propTypes = {
|
|||||||
|
|
||||||
class MainPanel extends React.Component {
|
class MainPanel extends React.Component {
|
||||||
|
|
||||||
|
onSearchedClick = (item) => {
|
||||||
|
let url = siteRoot + 'workspace/' + item.workspace_id + '/dtable/' + item.name + '/';
|
||||||
|
window.open(url)
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
|
||||||
|
let searchPlaceholder = this.props.searchPlaceholder || 'Search Dtables';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="main-panel">
|
<div className="main-panel">
|
||||||
<div className="main-panel-north dtable-header">
|
<div className="main-panel-north dtable-header">
|
||||||
<div className="common-toolbar">
|
<div className="common-toolbar">
|
||||||
<div className="search" title={'Search'}>Search</div>
|
<Search
|
||||||
<div className="notification" title={'Notification'}>Notification</div>
|
placeholder={searchPlaceholder}
|
||||||
<div className="avatar" title={'Avatar'}></div>
|
onSearchedClick={this.onSearchedClick}
|
||||||
|
/>
|
||||||
|
<Notification />
|
||||||
|
<Account />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Router className="reach-router">
|
<Router className="reach-router">
|
||||||
|
33
frontend/src/pages/dtable/search/search-result-item.js
Normal file
33
frontend/src/pages/dtable/search/search-result-item.js
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
const propTypes = {
|
||||||
|
item: PropTypes.object.isRequired,
|
||||||
|
onItemClickHandler: PropTypes.func.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
class SearchResultItem extends React.Component {
|
||||||
|
|
||||||
|
onClickHandler = () => {
|
||||||
|
var item = this.props.item;
|
||||||
|
this.props.onItemClickHandler(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
let item = this.props.item;
|
||||||
|
return (
|
||||||
|
<li className="search-result-item" onClick={this.onClickHandler}>
|
||||||
|
<span className="sf3-font sf3-font-table"></span>
|
||||||
|
<div className="item-content">
|
||||||
|
<div className="item-name ellipsis">{item.name}</div>
|
||||||
|
{/* <div className="item-link ellipsis">{item.repo_name}/{item.link_content}</div> */}
|
||||||
|
{/* <div className="item-text ellipsis" dangerouslySetInnerHTML={{__html: item.content}}></div> */}
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SearchResultItem.propTypes = propTypes;
|
||||||
|
|
||||||
|
export default SearchResultItem;
|
272
frontend/src/pages/dtable/search/search.js
Normal file
272
frontend/src/pages/dtable/search/search.js
Normal file
@@ -0,0 +1,272 @@
|
|||||||
|
import React, { Component, Fragment } from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import MediaQuery from 'react-responsive';
|
||||||
|
import { seafileAPI } from '../../../utils/seafile-api';
|
||||||
|
import { gettext, siteRoot, username } from '../../../utils/constants';
|
||||||
|
import SearchResultItem from './search-result-item';
|
||||||
|
import More from '../../../components/more';
|
||||||
|
import Workspace from '../model/workspace';
|
||||||
|
|
||||||
|
const propTypes = {
|
||||||
|
isPublic: PropTypes.bool,
|
||||||
|
repoID: PropTypes.string,
|
||||||
|
placeholder: PropTypes.string,
|
||||||
|
onSearchedClick: PropTypes.func.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
class Search extends Component {
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
width: 'default',
|
||||||
|
value: '',
|
||||||
|
resultItems: [],
|
||||||
|
isMaskShow: false,
|
||||||
|
isResultShow: false,
|
||||||
|
isResultGetted: false,
|
||||||
|
isCloseShow: false,
|
||||||
|
isSearchInputShow: false, // for mobile
|
||||||
|
};
|
||||||
|
this.inputValue = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
onFocusHandler = () => {
|
||||||
|
this.setState({
|
||||||
|
width: '30rem',
|
||||||
|
isMaskShow: true,
|
||||||
|
isCloseShow: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onCloseHandler = () => {
|
||||||
|
this.resetToDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
onItemClickHandler = (item) => {
|
||||||
|
this.resetToDefault();
|
||||||
|
this.props.onSearchedClick(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
onChangeHandler = (event) => {
|
||||||
|
let _this = this;
|
||||||
|
this.setState({value: event.target.value});
|
||||||
|
let newValue = event.target.value;
|
||||||
|
if (this.inputValue === newValue.trim()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
this.inputValue = newValue.trim();
|
||||||
|
|
||||||
|
if (this.inputValue === '' || _this.getValueLength(this.inputValue) < 3) {
|
||||||
|
this.setState({
|
||||||
|
isResultShow: false,
|
||||||
|
isResultGetted: false
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
let queryData = {
|
||||||
|
q: newValue,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (this.timer) {
|
||||||
|
clearTimeout(this.timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.timer = setTimeout(_this.getSearchResult(queryData), 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
getSearchResult(queryData) {
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
isResultShow: true,
|
||||||
|
isResultGetted: false
|
||||||
|
});
|
||||||
|
|
||||||
|
this.sendRequest(queryData);
|
||||||
|
}
|
||||||
|
|
||||||
|
sendRequest(queryData) { //search dtable
|
||||||
|
seafileAPI.listWorkspaces().then((res) => {
|
||||||
|
let workspaceList = res.data.workspace_list.filter(item => {
|
||||||
|
return new Workspace(item);
|
||||||
|
});
|
||||||
|
let dtableNameList = [];
|
||||||
|
workspaceList.forEach(dtable => {
|
||||||
|
let resultData = dtable.table_list.filter(item => {
|
||||||
|
return item.name.indexOf(queryData.q) > -1;
|
||||||
|
});
|
||||||
|
if (resultData.length > 0) {
|
||||||
|
dtableNameList.push(...resultData);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.setState({
|
||||||
|
resultItems: dtableNameList,
|
||||||
|
isResultGetted: true,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
getValueLength(str) {
|
||||||
|
var i = 0, code, len = 0;
|
||||||
|
for (; i < str.length; i++) {
|
||||||
|
code = str.charCodeAt(i);
|
||||||
|
if (code == 10) { //solve enter problem
|
||||||
|
len += 2;
|
||||||
|
} else if (code < 0x007f) {
|
||||||
|
len += 1;
|
||||||
|
} else if (code >= 0x0080 && code <= 0x07ff) {
|
||||||
|
len += 2;
|
||||||
|
} else if (code >= 0x0800 && code <= 0xffff) {
|
||||||
|
len += 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
resetToDefault() {
|
||||||
|
this.inputValue = null;
|
||||||
|
this.setState({
|
||||||
|
width: '',
|
||||||
|
value: '',
|
||||||
|
isMaskShow: false,
|
||||||
|
isCloseShow: false,
|
||||||
|
isResultShow: false,
|
||||||
|
isResultGetted: false,
|
||||||
|
resultItems: [],
|
||||||
|
isSearchInputShow: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onShowMore = () => {
|
||||||
|
let repoID = this.props.repoID;
|
||||||
|
let newValue = this.state.value;
|
||||||
|
let queryData = {
|
||||||
|
q: newValue,
|
||||||
|
search_repo: repoID ? repoID : 'all',
|
||||||
|
search_ftypes: 'all',
|
||||||
|
};
|
||||||
|
let params = '';
|
||||||
|
for (let key in queryData) {
|
||||||
|
params += key + '=' + queryData[key] + '&';
|
||||||
|
}
|
||||||
|
window.location = siteRoot + 'search/?' + params.slice(0, params.length - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderSearchResult() {
|
||||||
|
if (!this.state.isResultShow) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!this.state.isResultGetted || this.getValueLength(this.inputValue) < 3) {
|
||||||
|
return (
|
||||||
|
<span className="loading-icon loading-tip"></span>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (!this.state.resultItems.length) {
|
||||||
|
return (
|
||||||
|
<div className="search-result-none">{gettext('No results matching.')}</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
let isShowMore = this.state.resultItems.length >= 5 ? true : false;
|
||||||
|
return (
|
||||||
|
<ul className="search-result-list">
|
||||||
|
{this.state.resultItems.map(item => {
|
||||||
|
return (
|
||||||
|
<SearchResultItem
|
||||||
|
key={item.id}
|
||||||
|
item={item}
|
||||||
|
onItemClickHandler={this.onItemClickHandler}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
{isShowMore && <More onShowMore={this.onShowMore}/>}
|
||||||
|
</ul>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
onSearchToggle = () => {
|
||||||
|
this.setState({
|
||||||
|
isSearchInputShow: !this.state.isSearchInputShow,
|
||||||
|
isMaskShow: !this.state.isMaskShow,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onSearchPage = () => {
|
||||||
|
window.location.href = siteRoot + 'search/';
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
let width = this.state.width !== 'default' ? this.state.width : '';
|
||||||
|
let style = {'width': width};
|
||||||
|
return (
|
||||||
|
<Fragment>
|
||||||
|
<MediaQuery query="(min-width: 768px)">
|
||||||
|
<div className="search">
|
||||||
|
<div className={`search-mask ${this.state.isMaskShow ? '' : 'hide'}`} onClick={this.onCloseHandler}></div>
|
||||||
|
<div className="search-container">
|
||||||
|
<div className="input-icon">
|
||||||
|
<i className="search-icon-left input-icon-addon fas fa-search"></i>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
className="form-control search-input"
|
||||||
|
name="query"
|
||||||
|
placeholder={this.props.placeholder}
|
||||||
|
style={style}
|
||||||
|
value={this.state.value}
|
||||||
|
onFocus={this.onFocusHandler}
|
||||||
|
onChange={this.onChangeHandler}
|
||||||
|
autoComplete="off"
|
||||||
|
/>
|
||||||
|
{(this.state.isCloseShow && username) &&
|
||||||
|
<i className='search-icon-right input-icon-addon fas fa-external-link-alt search-icon-arrow'
|
||||||
|
onClick={this.onSearchPage}></i>
|
||||||
|
}
|
||||||
|
{this.state.isCloseShow && <i className='search-icon-right input-icon-addon fas fa-times' onClick={this.onCloseHandler}></i>}
|
||||||
|
</div>
|
||||||
|
<div className="search-result-container">
|
||||||
|
{this.renderSearchResult()}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</MediaQuery>
|
||||||
|
<MediaQuery query="(max-width: 767.8px)">
|
||||||
|
<div className="search-icon-container">
|
||||||
|
<i className="search-icon fas fa-search" onClick={this.onSearchToggle}></i>
|
||||||
|
</div>
|
||||||
|
{this.state.isSearchInputShow &&
|
||||||
|
<div className="search">
|
||||||
|
<div className={`search-mask ${this.state.isMaskShow ? '' : 'hide'}`} onClick={this.onCloseHandler}></div>
|
||||||
|
<div className="search-container">
|
||||||
|
<div className="input-icon">
|
||||||
|
<i className="search-icon-left input-icon-addon fas fa-search"></i>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
className="form-control search-input"
|
||||||
|
name="query"
|
||||||
|
placeholder={this.props.placeholder}
|
||||||
|
style={style}
|
||||||
|
value={this.state.value}
|
||||||
|
onFocus={this.onFocusHandler}
|
||||||
|
onChange={this.onChangeHandler}
|
||||||
|
autoComplete="off"
|
||||||
|
/>
|
||||||
|
{(this.state.isCloseShow && username) &&
|
||||||
|
<i className='search-icon-right input-icon-addon fas fa-external-link-alt search-icon-arrow'
|
||||||
|
onClick={this.onSearchPage}></i>
|
||||||
|
}
|
||||||
|
{this.state.isCloseShow && <i className='search-icon-right input-icon-addon fas fa-times' onClick={this.onCloseHandler}></i>}
|
||||||
|
</div>
|
||||||
|
<div className="search-result-container">
|
||||||
|
{this.renderSearchResult()}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</MediaQuery>
|
||||||
|
</Fragment>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Search.propTypes = propTypes;
|
||||||
|
|
||||||
|
export default Search;
|
@@ -21,12 +21,13 @@ class SidePanel extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
let imgUrl = siteRoot + 'media/img/dtable-logo.png'
|
||||||
return (
|
return (
|
||||||
<div className="side-panel">
|
<div className="side-panel">
|
||||||
<div className="side-panel-north dtable-header">
|
<div className="side-panel-north dtable-header">
|
||||||
<i className="sf3-font sf3-font-dtable-logo dtable-logo"></i>
|
<div className="dtable-logo">
|
||||||
<span className="dtable-text">DTable</span>
|
<img src={imgUrl} height="32" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="side-panel-center">
|
<div className="side-panel-center">
|
||||||
<div className="dtable-side-nav">
|
<div className="dtable-side-nav">
|
||||||
|
BIN
media/img/dtable-logo.png
Normal file
BIN
media/img/dtable-logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.4 KiB |
@@ -28,6 +28,7 @@
|
|||||||
window.app = {
|
window.app = {
|
||||||
config: {
|
config: {
|
||||||
siteRoot: '{{ SITE_ROOT }}',
|
siteRoot: '{{ SITE_ROOT }}',
|
||||||
|
avatarURL: '{{ avatar_url }}'
|
||||||
},
|
},
|
||||||
pageOptions: {
|
pageOptions: {
|
||||||
server: '{{ service_url }}',
|
server: '{{ service_url }}',
|
||||||
|
Reference in New Issue
Block a user