mirror of
https://github.com/anyproto/anytype-ts.git
synced 2025-06-08 05:57:02 +09:00
Merge pull request #664 from anytypeio/feature/599
Feature/599: History
This commit is contained in:
commit
5ccfc3cf71
46 changed files with 870 additions and 159 deletions
5
dist/.gitignore
vendored
5
dist/.gitignore
vendored
|
@ -17,6 +17,11 @@ main.js
|
|||
main.js.map
|
||||
commands.js
|
||||
anytypeHelper*
|
||||
alpha-linux.yml
|
||||
*.snap
|
||||
beta-linux.yml
|
||||
latest-linux.yml
|
||||
linux-unpacked/
|
||||
*.snap
|
||||
*.deb
|
||||
*.rpm
|
17
electron.js
17
electron.js
|
@ -470,25 +470,19 @@ function menuInit () {
|
|||
{
|
||||
label: 'Interface', type: 'checkbox', checked: config.debugUI,
|
||||
click: () => {
|
||||
setConfig({ debugUI: !config.debugUI }, () => {
|
||||
send('toggleDebug', 'ui', config.debugUI);
|
||||
});
|
||||
setConfig({ debugUI: !config.debugUI });
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Middleware', type: 'checkbox', checked: config.debugMW,
|
||||
click: () => {
|
||||
setConfig({ debugMW: !config.debugMW }, () => {
|
||||
send('toggleDebug', 'mw', config.debugMW);
|
||||
});
|
||||
setConfig({ debugMW: !config.debugMW });
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Analytics', type: 'checkbox', checked: config.debugAN,
|
||||
click: () => {
|
||||
setConfig({ debugAN: !config.debugAN }, () => {
|
||||
send('toggleDebug', 'an', config.debugAN);
|
||||
});
|
||||
setConfig({ debugAN: !config.debugAN });
|
||||
}
|
||||
},
|
||||
]
|
||||
|
@ -499,9 +493,7 @@ function menuInit () {
|
|||
},
|
||||
{
|
||||
label: 'Dev Tools', accelerator: 'Alt+CmdOrCtrl+I',
|
||||
click: () => {
|
||||
win.webContents.openDevTools();
|
||||
}
|
||||
click: () => { win.webContents.openDevTools(); }
|
||||
}
|
||||
]
|
||||
});
|
||||
|
@ -524,6 +516,7 @@ function setChannel (channel) {
|
|||
function setConfig (obj, callBack) {
|
||||
config = Object.assign(config, obj);
|
||||
storage.set('config', config, (error) => {
|
||||
send('config', config);
|
||||
if (callBack) {
|
||||
callBack(error);
|
||||
};
|
||||
|
|
3
src/img/arrow/history0.svg
Normal file
3
src/img/arrow/history0.svg
Normal file
|
@ -0,0 +1,3 @@
|
|||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.5303 2.46967C12.2374 2.17678 11.7626 2.17678 11.4697 2.46967L3.93934 10L11.4697 17.5303C11.7626 17.8232 12.2374 17.8232 12.5303 17.5303C12.8232 17.2374 12.8232 16.7626 12.5303 16.4697L6.06066 10L12.5303 3.53033C12.8232 3.23744 12.8232 2.76256 12.5303 2.46967Z" fill="#ACA996"/>
|
||||
</svg>
|
After Width: | Height: | Size: 433 B |
3
src/img/arrow/history1.svg
Normal file
3
src/img/arrow/history1.svg
Normal file
|
@ -0,0 +1,3 @@
|
|||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.5303 2.46967C12.2374 2.17678 11.7626 2.17678 11.4697 2.46967L3.93934 10L11.4697 17.5303C11.7626 17.8232 12.2374 17.8232 12.5303 17.5303C12.8232 17.2374 12.8232 16.7626 12.5303 16.4697L6.06066 10L12.5303 3.53033C12.8232 3.23744 12.8232 2.76256 12.5303 2.46967Z" fill="#2c2b27"/>
|
||||
</svg>
|
After Width: | Height: | Size: 433 B |
3
src/img/arrow/historyList.svg
Normal file
3
src/img/arrow/historyList.svg
Normal file
|
@ -0,0 +1,3 @@
|
|||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.19283 5.1772C8.42714 4.94289 8.80704 4.94289 9.04135 5.1772L13.8656 10.0015L9.04135 14.8257C8.80704 15.06 8.42714 15.06 8.19283 14.8257C7.95851 14.5914 7.95851 14.2115 8.19283 13.9772L12.1686 10.0015L8.19283 6.02573C7.95851 5.79141 7.95851 5.41152 8.19283 5.1772Z" fill="#2C2B27"/>
|
||||
</svg>
|
After Width: | Height: | Size: 437 B |
10
src/img/icon/menu/action/history0.svg
Normal file
10
src/img/icon/menu/action/history0.svg
Normal file
|
@ -0,0 +1,10 @@
|
|||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0)">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M16.75 10C16.75 13.4518 13.9518 16.25 10.5 16.25C8.77411 16.25 7.21161 15.5504 6.08058 14.4194L5.01992 15.4801C6.4224 16.8826 8.3599 17.75 10.5 17.75C14.7802 17.75 18.25 14.2802 18.25 10C18.25 5.71979 14.7802 2.25 10.5 2.25C6.21979 2.25 2.75 5.71979 2.75 10H2.7207V10.16L1.03039 8.46973L-0.0302734 9.53039L3.50006 13.0607L7.03039 9.53039L5.96973 8.46973L4.2207 10.2187V10H4.25C4.25 6.54822 7.04822 3.75 10.5 3.75C13.9518 3.75 16.75 6.54822 16.75 10ZM9.75 10.386V5H11.25V9.61404L14.4359 11.8897L13.5641 13.1103L9.75 10.386Z" fill="#ACA996"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0">
|
||||
<rect width="20" height="20" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 818 B |
|
@ -47,6 +47,11 @@
|
|||
}
|
||||
|
||||
.block > .wrapContent > .children > .block.last { margin: 0px; }
|
||||
|
||||
.block.isReadOnly {
|
||||
.colResize { display: none; }
|
||||
}
|
||||
.block.isReadOnly > .wrapMenu > .icon.dnd { display: none; }
|
||||
|
||||
.block.align0 > .wrapContent { text-align: left; }
|
||||
.block.align1 > .wrapContent { text-align: center; }
|
||||
|
|
|
@ -45,6 +45,9 @@
|
|||
.icon.play:hover { background-color: rgba(255,255,255,0.9); }
|
||||
}
|
||||
.block.blockMedia > .wrapContent > .selectable > .dropTarget { line-height: 0px; }
|
||||
|
||||
.block.blockMedia.isReadOnly > .wrapContent > .selectable > .dropTarget .icon.resize { display: none; }
|
||||
.block.blockMedia.isReadOnly > .wrapContent > .selectable > .dropTarget .icon.play { display: none; }
|
||||
|
||||
.block.blockMedia:hover {
|
||||
.icon.resize { opacity: 1; }
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
.block.blockText {
|
||||
.wrap { flex: auto; position: relative; padding: 0px; width: 100%; }
|
||||
.value { -webkit-user-modify: read-write-plaintext-only; width: 100%; overflow: hidden; }
|
||||
|
||||
.placeHolder {
|
||||
color: $colorDarkGrey; position: absolute; z-index: 0; left: 0px; top: 0px; display: none; overflow: hidden;
|
||||
width: 100%; height: 100%; cursor: text; pointer-events: none;
|
||||
|
@ -71,9 +72,17 @@
|
|||
.marker.check, .marker.toggle {
|
||||
img { width: 100%; height: 100%; }
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
.block.blockText.isReadOnly > .wrapContent > .selectable > .dropTarget .marker.check { cursor: default; }
|
||||
.block.blockText.isReadOnly > .wrapContent > .selectable > .dropTarget .value { min-height: 24px; }
|
||||
.block.blockText.isReadOnly > .wrapContent > .selectable > .dropTarget .placeHolder { display: none; }
|
||||
|
||||
.block.blockText.isReadOnly.code {
|
||||
.select { display: none; }
|
||||
}
|
||||
.block.blockText.isReadOnly.code > .wrapContent > .selectable > .dropTarget { padding: 16px; }
|
||||
|
||||
.block.blockText.isChecked > .wrapContent > .selectable > .dropTarget * { color: $colorDarkGrey !important; }
|
||||
|
||||
|
@ -115,7 +124,7 @@
|
|||
}
|
||||
.select:hover, .select.active { background: none; }
|
||||
}
|
||||
|
||||
|
||||
.block.blockText.paragraph > .wrapContent.bgColor > .selectable > .dropTarget,
|
||||
.block.blockText.header1 > .wrapContent.bgColor > .selectable > .dropTarget,
|
||||
.block.blockText.header2 > .wrapContent.bgColor > .selectable > .dropTarget,
|
||||
|
|
|
@ -81,6 +81,7 @@ body.platformWindows {
|
|||
.through { pointer-events: none; }
|
||||
.rel { position: relative; }
|
||||
.disabled { opacity: 0.5 !important; cursor: default !important; }
|
||||
.readOnly { -webkit-user-modify: read-only !important; }
|
||||
|
||||
.fileWrap { position: relative; overflow: hidden; cursor: pointer; }
|
||||
.fileWrap {
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
.icon.back { margin-right: 8px; }
|
||||
|
||||
.icon.logo {
|
||||
width: 60px; height: 13px; position: absolute; left: 50%; margin-left: -30px; top: 13px; background: url('~img/logo.svg') no-repeat;
|
||||
background-position: center center; cursor: default;
|
||||
width: 60px !important; height: 13px !important; position: absolute; left: 50%; margin-left: -30px; top: 13px; background: url('~img/logo.svg') no-repeat;
|
||||
background-position: center center; background-size: 100% 100% !important;
|
||||
}
|
||||
|
||||
.path { white-space: nowrap; }
|
||||
|
@ -45,34 +45,29 @@
|
|||
.icon.add { background-image: url('~img/icon/header/add.svg'); }
|
||||
.icon.settings { background-image: url('~img/icon/header/settings.svg'); }
|
||||
|
||||
.side.right { position: absolute; top: 5px; right: 6px; }
|
||||
.side { position: absolute; top: 5px; height: 28px; line-height: 28px; }
|
||||
|
||||
.side.left { left: 6px; z-index: 1; }
|
||||
|
||||
.side.center { width: 492px; height: 28px; left: 50%; margin-left: -246px; white-space: nowrap; }
|
||||
|
||||
.side.right { right: 6px; z-index: 1; }
|
||||
.side.right {
|
||||
.icon { margin: 0px; }
|
||||
}
|
||||
}
|
||||
|
||||
.headerMainIndex { height: 38px; background: rgba(44,43,39,0.1); }
|
||||
.headerMainIndex {
|
||||
.header.headerMainIndex { height: 38px; background: rgba(44,43,39,0.1); }
|
||||
.header.headerMainIndex {
|
||||
.icon { width: 40px; height: 28px; background-size: 20px 20px; border-radius: 6px; }
|
||||
.icon:hover { background-color: rgba(0,0,0,0.15); }
|
||||
}
|
||||
|
||||
.headerMainEditSearch { background: #fff; padding: 5px 6px; height: 38px; }
|
||||
.headerMainEditSearch {
|
||||
.header.headerMainEdit { background: #fff; height: 38px; line-height: 20px; }
|
||||
.header.headerMainEdit {
|
||||
.icon { width: 40px; height: 28px; background-size: 20px 20px; border-radius: 6px; }
|
||||
.icon:hover { background-color: #f3f2ec; }
|
||||
|
||||
.mid { width: 492px; height: 28px; position: absolute; left: 50%; margin-left: -246px; top: 5px; white-space: nowrap; }
|
||||
.mid {
|
||||
.icon { margin: 0px; opacity: 0; }
|
||||
.icon.plus {
|
||||
.arrow {
|
||||
width: 8px; height: 8px; background-image: url('~img/icon/header/arrow.svg'); position: absolute; right: -12px;
|
||||
top: 10px; margin: 0px; background-color: none !important; background-size: 100% 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.path {
|
||||
border: 1px solid #fff; border-radius: 6px; display: inline-block; vertical-align: top; height: 28px; margin: 0px 6px;
|
||||
line-height: 24px; width: 400px; text-align: center; transition: $transitionFast; -webkit-app-region: no-drag;
|
||||
|
@ -82,18 +77,53 @@
|
|||
}
|
||||
.path * { pointer-events: all; }
|
||||
|
||||
.side { position: absolute; top: 5px; }
|
||||
.side.left { left: 6px; opacity: 0; transition: $transitionFast; }
|
||||
.side.left { opacity: 0; transition: $transitionFast; }
|
||||
.side.left {
|
||||
.icon { margin: 0px; }
|
||||
.icon.back, .icon.forward { width: 32px; }
|
||||
}
|
||||
|
||||
.side.center {
|
||||
.icon { margin: 0px; opacity: 0; }
|
||||
.icon.plus {
|
||||
.arrow {
|
||||
width: 8px; height: 8px; background-image: url('~img/icon/header/arrow.svg'); position: absolute; right: -12px;
|
||||
top: 10px; margin: 0px; background-color: none !important; background-size: 100% 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.header.headerMainHistory { height: 38px; line-height: 22px; padding: 8px 16px; width: calc(100% - 254px); background: #fff; }
|
||||
.header.headerMainHistory {
|
||||
.side { height: 20px; top: 8px; }
|
||||
.side.center { text-align: center; }
|
||||
.side.right { right: 16px; }
|
||||
|
||||
.side {
|
||||
.item { color: #6c6a5f; transition: $transitionFast; cursor: pointer; height: 20px; line-height: 20px; }
|
||||
.item {
|
||||
.icon.arrow { background-image: url('~img/arrow/history0.svg'); margin: 0px; }
|
||||
}
|
||||
.item.orange { color: #e89d00; font-weight: 500; }
|
||||
|
||||
.item.grey:hover { color: $colorBlack; }
|
||||
.item.orange:hover { color: $colorBlack; }
|
||||
|
||||
.item:hover {
|
||||
.icon.arrow { background-image: url('~img/arrow/history1.svg'); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
body.platformMac {
|
||||
.headerMainEditSearch {
|
||||
.header {
|
||||
.side.left { left: 90px; }
|
||||
}
|
||||
|
||||
.header.headerMainHistory {
|
||||
.side.left { left: 80px; }
|
||||
}
|
||||
}
|
||||
|
||||
html.fullScreen {
|
||||
|
@ -102,9 +132,9 @@ html.fullScreen {
|
|||
}
|
||||
}
|
||||
|
||||
.headerMainEditSearch:hover, .headerMainEditSearch.active {
|
||||
.header.headerMainEdit:hover, .header.headerMainEdit.active {
|
||||
.side.left { opacity: 1; }
|
||||
.mid {
|
||||
.side.center {
|
||||
.icon { opacity: 1; }
|
||||
.icon.dis { opacity: 0.5; }
|
||||
}
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
.inputWithFile {
|
||||
.txt { line-height: 20px; height: 20px; overflow: hidden; width: calc(100% - 26px); vertical-align: top; }
|
||||
.fileWrap { display: inline-block; vertical-align: top; }
|
||||
.fileWrap .border { border-bottom: 1px solid $colorDarkGrey; display: inline-block; line-height: 1; transition: $transitionFast; }
|
||||
.fileWrap:hover .border { cursor: pointer; color: $colorBlack; }
|
||||
.fileWrap .border { border-bottom: 1px solid $colorDarkGrey; display: inline-block; line-height: 1; transition: $transitionFast; cursor: pointer; }
|
||||
.fileWrap:hover .border { color: $colorBlack; }
|
||||
|
||||
.input::placeholder { color: $colorDarkGrey; }
|
||||
.urlToggle { cursor: text; display: inline-block; }
|
||||
|
@ -24,6 +24,12 @@
|
|||
.icon.bookmark { background-image: url('~img/icon/menu/action/block/bookmark0.svg'); }
|
||||
}
|
||||
|
||||
.inputWithFile.isReadOnly {
|
||||
.urlToggle { cursor: default; }
|
||||
.border { border: 0px; cursor: default; }
|
||||
.fileWrap:hover .border { color: $colorDarkGrey; }
|
||||
}
|
||||
|
||||
.inputWithFile.isSmall {
|
||||
.fileWrap { display: block; }
|
||||
.txt { height: 38px; }
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
.icon.undo { background-image: url('~img/icon/menu/action/undo0.svg'); }
|
||||
.icon.redo { background-image: url('~img/icon/menu/action/redo0.svg'); }
|
||||
.icon.print { background-image: url('~img/icon/menu/action/print0.svg'); }
|
||||
.icon.history { background-image: url('~img/icon/menu/action/history0.svg'); }
|
||||
.icon.search { background-image: url('~img/icon/menu/action/search0.svg'); }
|
||||
|
||||
.icon.align.left { background-image: url('~img/icon/menu/align/left.svg'); }
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
.menus {
|
||||
.dimmer { position: fixed; left: 0px; top: 0px; width: 100%; height: 100%; z-index: 102; background: rgba(0,0,0,0); }
|
||||
#menu-polygon { z-index: 1000; position: absolute; }
|
||||
|
||||
.menu * { user-select: none; }
|
||||
|
||||
.menu {
|
||||
border-radius: 8px; color: $colorBlack; position: absolute; z-index: 103; text-align: left;
|
||||
|
|
41
src/scss/page/main/history.scss
Normal file
41
src/scss/page/main/history.scss
Normal file
|
@ -0,0 +1,41 @@
|
|||
@import "~scss/_vars";
|
||||
|
||||
.pageMainHistory * { user-select: none; }
|
||||
.pageMainHistory {
|
||||
#body { overflow: hidden; }
|
||||
.wrapper { padding: 38px 0px 0px 0px; width: calc(100% - 254px); overflow: auto; position: relative; }
|
||||
.loaderWrapper { position: fixed; left: 0px; top: 0px; width: 100%; height: 100%; }
|
||||
|
||||
.list { width: 254px; border-left: 1px solid #dfddd0; z-index: 10; position: relative; background: #fff; overflow: auto; }
|
||||
.list {
|
||||
.section { padding: 11px 16px; }
|
||||
.section {
|
||||
.date { text-transform: uppercase; @include text-very-small; }
|
||||
}
|
||||
.section.fix { position: fixed; right: 0px; top: 0px; background: #fff; width: 253px; }
|
||||
|
||||
.wrap { position: relative; }
|
||||
|
||||
.item { padding: 5px 16px 5px 30px; cursor: pointer; transition: $transitionFast; position: relative; }
|
||||
.item {
|
||||
.name { @include text-small; color: #6c6a5f; @include text-overflow-nw; }
|
||||
.date { @include text-overflow-nw; }
|
||||
.icon.arrow {
|
||||
width: 20px; height: 20px; background-image: url('~img/arrow/historyList.svg'); position: absolute; left: 9px; top: 6px;
|
||||
transition: none;
|
||||
}
|
||||
}
|
||||
.item.expanded {
|
||||
.icon.arrow { transform: rotateZ(90deg); }
|
||||
}
|
||||
|
||||
.children { display: none; transition: $transitionFast; }
|
||||
.children {
|
||||
.item { padding-left: 48px; }
|
||||
}
|
||||
|
||||
.item:hover, .item.active { background: #f3f2ec; }
|
||||
}
|
||||
|
||||
.blockLast { height: 100px; }
|
||||
}
|
|
@ -6,6 +6,8 @@
|
|||
.innerWrap { opacity: 1; transform: scale3d(1,1,1); }
|
||||
.dimmer { opacity: 1; }
|
||||
}
|
||||
|
||||
.popup * { user-select: none; }
|
||||
|
||||
.popup {
|
||||
.innerWrap {
|
||||
|
|
|
@ -42,6 +42,7 @@ import 'scss/component/pin.scss';
|
|||
import 'scss/page/auth.scss';
|
||||
import 'scss/page/main/index.scss';
|
||||
import 'scss/page/main/edit.scss';
|
||||
import 'scss/page/main/history.scss';
|
||||
|
||||
import 'scss/block/common.scss';
|
||||
import 'scss/block/dataview.scss';
|
||||
|
@ -256,7 +257,7 @@ class App extends React.Component<Props, State> {
|
|||
this.setWindowEvents();
|
||||
|
||||
if (pageId) {
|
||||
Storage.set('redirectTo', pageId);
|
||||
Storage.set('redirectTo', '/main/edit/' + pageId);
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ class BlockBookmark extends React.Component<Props, {}> {
|
|||
};
|
||||
|
||||
render () {
|
||||
const { rootId, block } = this.props;
|
||||
const { rootId, block, readOnly } = this.props;
|
||||
const { id, content } = block;
|
||||
const { url, title, description, imageHash, faviconHash } = content;
|
||||
|
||||
|
@ -58,7 +58,7 @@ class BlockBookmark extends React.Component<Props, {}> {
|
|||
);
|
||||
} else {
|
||||
element = (
|
||||
<InputWithFile block={block} icon="bookmark" textFile="Paste a link" withFile={false} onChangeUrl={this.onChangeUrl} />
|
||||
<InputWithFile block={block} icon="bookmark" textFile="Paste a link" withFile={false} onChangeUrl={this.onChangeUrl} readOnly={readOnly} />
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -60,7 +60,7 @@ class BlockCover extends React.Component<Props, State> {
|
|||
|
||||
render() {
|
||||
const { editing, loading } = this.state;
|
||||
const { rootId } = this.props;
|
||||
const { rootId, readOnly } = this.props;
|
||||
const details = blockStore.getDetails(rootId, rootId);
|
||||
const { coverType, coverId, } = details;
|
||||
const canEdit = coverType && [ I.CoverType.Image, I.CoverType.BgImage ].indexOf(coverType) >= 0;
|
||||
|
@ -114,9 +114,11 @@ class BlockCover extends React.Component<Props, State> {
|
|||
) : (
|
||||
<Cover id="cover" type={coverType} className={coverId} />
|
||||
)}
|
||||
<div id="elements" className="elements">
|
||||
{elements}
|
||||
</div>
|
||||
{!readOnly ? (
|
||||
<div id="elements" className="elements">
|
||||
{elements}
|
||||
</div>
|
||||
) : ''}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -26,7 +26,7 @@ class BlockFile extends React.Component<Props, {}> {
|
|||
};
|
||||
|
||||
render () {
|
||||
const { rootId, block } = this.props;
|
||||
const { rootId, block, readOnly } = this.props;
|
||||
const { id, content } = block;
|
||||
const { state, hash, size, name, mime } = content;
|
||||
|
||||
|
@ -37,7 +37,7 @@ class BlockFile extends React.Component<Props, {}> {
|
|||
default:
|
||||
case I.FileState.Empty:
|
||||
element = (
|
||||
<InputWithFile block={block} icon="file" textFile="Upload a file" onChangeUrl={this.onChangeUrl} onChangeFile={this.onChangeFile} />
|
||||
<InputWithFile block={block} icon="file" textFile="Upload a file" onChangeUrl={this.onChangeUrl} onChangeFile={this.onChangeFile} readOnly={readOnly} />
|
||||
);
|
||||
break;
|
||||
|
||||
|
@ -66,7 +66,7 @@ class BlockFile extends React.Component<Props, {}> {
|
|||
);
|
||||
break;
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<div className={cn.join(' ')} tabIndex={0} onKeyDown={this.onKeyDown} onKeyUp={this.onKeyUp} onFocus={this.onFocus}>
|
||||
{element}
|
||||
|
|
|
@ -17,13 +17,24 @@ class BlockIconPage extends React.Component<Props, {}> {
|
|||
};
|
||||
|
||||
render (): any {
|
||||
const { rootId } = this.props;
|
||||
const { rootId, readOnly } = this.props;
|
||||
const details = blockStore.getDetails(rootId, rootId);
|
||||
const { iconEmoji, iconImage } = details;
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Smile id={'block-icon-' + rootId} canEdit={true} size={32} icon={iconEmoji} hash={iconImage} offsetX={0} offsetY={16} onSelect={this.onSelect} onUpload={this.onUpload} className={'c64 ' + (commonStore.menuIsOpen('smile') ? 'active' : '')} />
|
||||
<Smile
|
||||
id={'block-icon-' + rootId}
|
||||
canEdit={!readOnly}
|
||||
size={32}
|
||||
icon={iconEmoji}
|
||||
hash={iconImage}
|
||||
offsetX={0}
|
||||
offsetY={16}
|
||||
onSelect={this.onSelect}
|
||||
onUpload={this.onUpload}
|
||||
className={'c64 ' + (commonStore.menuIsOpen('smile') ? 'active' : '')}
|
||||
/>
|
||||
</React.Fragment>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -31,7 +31,7 @@ class BlockImage extends React.Component<Props, {}> {
|
|||
};
|
||||
|
||||
render () {
|
||||
const { block } = this.props;
|
||||
const { block, readOnly } = this.props;
|
||||
const { id, fields, content } = block;
|
||||
const { width } = fields;
|
||||
const { state } = content;
|
||||
|
@ -47,7 +47,7 @@ class BlockImage extends React.Component<Props, {}> {
|
|||
default:
|
||||
case I.FileState.Empty:
|
||||
element = (
|
||||
<InputWithFile block={block} icon="image" textFile="Upload a picture" accept={Constant.extension.image} onChangeUrl={this.onChangeUrl} onChangeFile={this.onChangeFile} />
|
||||
<InputWithFile block={block} icon="image" textFile="Upload a picture" accept={Constant.extension.image} onChangeUrl={this.onChangeUrl} onChangeFile={this.onChangeFile} readOnly={readOnly} />
|
||||
);
|
||||
break;
|
||||
|
||||
|
|
|
@ -62,13 +62,13 @@ class Block extends React.Component<Props, {}> {
|
|||
};
|
||||
|
||||
render () {
|
||||
const { rootId, cnt, css, index, className, block } = this.props;
|
||||
const { rootId, cnt, css, index, className, block, readOnly } = this.props;
|
||||
const { id, type, fields, content, align, bgColor } = block;
|
||||
const { style, checked } = content || {};
|
||||
const childrenIds = blockStore.getChildrenIds(rootId, id);
|
||||
|
||||
let canSelect = true;
|
||||
let cn: string[] = [ 'block', (index ? 'index-' + index : ''), 'align' + align ];
|
||||
let cn: string[] = [ 'block', (index ? 'index-' + index : ''), 'align' + align, (readOnly ? 'isReadOnly' : '')];
|
||||
let cd: string[] = [ 'wrapContent' ];
|
||||
let blockComponent = null;
|
||||
let empty = null;
|
||||
|
@ -89,12 +89,10 @@ class Block extends React.Component<Props, {}> {
|
|||
cn.push('isChecked');
|
||||
};
|
||||
|
||||
if (block.isTextToggle()) {
|
||||
if (!childrenIds.length) {
|
||||
empty = (
|
||||
<div className="emptyToggle" onClick={this.onToggleClick}>Empty toggle. Click and drop block inside</div>
|
||||
);
|
||||
};
|
||||
if (block.isTextToggle() && !childrenIds.length && !readOnly) {
|
||||
empty = (
|
||||
<div className="emptyToggle" onClick={this.onToggleClick}>Empty toggle. Click and drop block inside</div>
|
||||
);
|
||||
};
|
||||
|
||||
blockComponent = <BlockText {...this.props} onToggle={this.onToggle} onFocus={this.onFocus} onBlur={this.onBlur} />;
|
||||
|
@ -127,7 +125,7 @@ class Block extends React.Component<Props, {}> {
|
|||
if (content.state == I.FileState.Done) {
|
||||
cn.push('withFile');
|
||||
};
|
||||
|
||||
|
||||
switch (content.type) {
|
||||
default:
|
||||
case I.FileType.File:
|
||||
|
@ -384,11 +382,12 @@ class Block extends React.Component<Props, {}> {
|
|||
onResizeStart (e: any, index: number) {
|
||||
e.stopPropagation();
|
||||
|
||||
if (!this._isMounted) {
|
||||
const { dataset, rootId, block, readOnly } = this.props;
|
||||
|
||||
if (!this._isMounted || readOnly) {
|
||||
return;
|
||||
};
|
||||
|
||||
const { dataset, rootId, block } = this.props;
|
||||
const { id } = block;
|
||||
const childrenIds = blockStore.getChildrenIds(rootId, id);
|
||||
const { selection } = dataset || {};
|
||||
|
@ -512,11 +511,11 @@ class Block extends React.Component<Props, {}> {
|
|||
return;
|
||||
};
|
||||
|
||||
const { rootId, block } = this.props;
|
||||
const { rootId, block, readOnly } = this.props;
|
||||
const { id } = block;
|
||||
const node = $(ReactDOM.findDOMNode(this));
|
||||
|
||||
if (!block.isLayoutRow() || keyboard.isDragging) {
|
||||
if (!block.isLayoutRow() || keyboard.isDragging || readOnly) {
|
||||
return;
|
||||
};
|
||||
|
||||
|
|
|
@ -23,15 +23,15 @@ class BlockLink extends React.Component<Props, {}> {
|
|||
};
|
||||
|
||||
render() {
|
||||
const { rootId, block } = this.props;
|
||||
const { rootId, block, readOnly } = this.props;
|
||||
const { id, content } = block;
|
||||
const details = blockStore.getDetails(rootId, content.targetBlockId);
|
||||
const { iconEmoji, iconImage, name, isArchived } = details;
|
||||
const cn = [ 'focusable', 'c' + id, (isArchived ? 'isArchived' : '') ];
|
||||
|
||||
|
||||
return (
|
||||
<div className={cn.join(' ')} tabIndex={0} onKeyDown={this.onKeyDown} onKeyUp={this.onKeyUp} onFocus={this.onFocus}>
|
||||
<Smile id={'block-page-' + id} offsetX={28} offsetY={-24} size={20} icon={iconEmoji} hash={iconImage} className="c24" canEdit={true} onSelect={this.onSelect} onUpload={this.onUpload} />
|
||||
<Smile id={'block-page-' + id} offsetX={28} offsetY={-24} size={20} icon={iconEmoji} hash={iconImage} className="c24" canEdit={!readOnly} onSelect={this.onSelect} onUpload={this.onUpload} />
|
||||
<div className="name" onClick={this.onClick}>
|
||||
<div className="txt">{name}</div>
|
||||
</div>
|
||||
|
|
|
@ -9,6 +9,18 @@ import { commonStore, blockStore } from 'ts/store';
|
|||
import * as Prism from 'prismjs';
|
||||
import 'prismjs/themes/prism.css';
|
||||
|
||||
interface Props extends I.BlockComponent, RouteComponentProps<any> {
|
||||
onToggle?(e: any): void;
|
||||
onFocus?(e: any): void;
|
||||
onBlur?(e: any): void;
|
||||
onMenuAdd? (id: string, text: string, range: I.TextRange): void;
|
||||
onPaste? (e: any): void;
|
||||
};
|
||||
|
||||
const { ipcRenderer } = window.require('electron');
|
||||
const Constant = require('json/constant.json');
|
||||
const $ = require('jquery');
|
||||
|
||||
// Prism languages
|
||||
const langs = [
|
||||
'clike', 'c', 'cpp', 'csharp', 'abap', 'arduino', 'bash', 'basic', 'clojure', 'coffeescript', 'dart', 'diff', 'docker', 'elixir',
|
||||
|
@ -21,22 +33,6 @@ for (let lang of langs) {
|
|||
require(`prismjs/components/prism-${lang}.js`);
|
||||
};
|
||||
|
||||
interface Props extends RouteComponentProps<any> {
|
||||
rootId: string;
|
||||
dataset?: any;
|
||||
block: I.Block;
|
||||
onToggle? (e: any): void;
|
||||
onFocus? (e: any): void;
|
||||
onBlur? (e: any): void;
|
||||
onKeyDown? (e: any, text: string, marks: I.Mark[], range: I.TextRange): void;
|
||||
onMenuAdd? (id: string, text: string, range: I.TextRange): void;
|
||||
onPaste? (e: any): void;
|
||||
};
|
||||
|
||||
const { ipcRenderer } = window.require('electron');
|
||||
const Constant = require('json/constant.json');
|
||||
const $ = require('jquery');
|
||||
|
||||
@observer
|
||||
class BlockText extends React.Component<Props, {}> {
|
||||
|
||||
|
@ -71,14 +67,14 @@ class BlockText extends React.Component<Props, {}> {
|
|||
};
|
||||
|
||||
render () {
|
||||
const { rootId, block } = this.props;
|
||||
const { rootId, block, readOnly } = this.props;
|
||||
const { id, fields, content } = block;
|
||||
const { text, marks, style, checked, color } = content;
|
||||
|
||||
let marker: any = null;
|
||||
let placeHolder = Constant.placeHolder.default;
|
||||
let ct = color ? 'textColor textColor-' + color : '';
|
||||
let cv: string[] = [ 'value', 'focusable', 'c' + id, ct ];
|
||||
let cv: string[] = [ 'value', 'focusable', 'c' + id, ct, (readOnly ? 'readOnly' : '') ];
|
||||
let additional = null;
|
||||
|
||||
for (let mark of marks) {
|
||||
|
@ -126,7 +122,7 @@ class BlockText extends React.Component<Props, {}> {
|
|||
<div
|
||||
id="value"
|
||||
className={cv.join(' ')}
|
||||
contentEditable={true}
|
||||
contentEditable={!readOnly}
|
||||
suppressContentEditableWarning={true}
|
||||
onKeyDown={this.onKeyDown}
|
||||
onKeyUp={this.onKeyUp}
|
||||
|
@ -813,9 +809,13 @@ class BlockText extends React.Component<Props, {}> {
|
|||
};
|
||||
|
||||
onCheck (e: any) {
|
||||
const { rootId, block } = this.props;
|
||||
const { rootId, block, readOnly } = this.props;
|
||||
const { id, content } = block;
|
||||
const { checked } = content;
|
||||
|
||||
if (readOnly) {
|
||||
return;
|
||||
};
|
||||
|
||||
focus.clear(true);
|
||||
DataUtil.blockSetText(rootId, block, this.getValue(), this.marks, true, () => {
|
||||
|
@ -824,9 +824,13 @@ class BlockText extends React.Component<Props, {}> {
|
|||
};
|
||||
|
||||
onLang (v: string) {
|
||||
const { rootId, block } = this.props;
|
||||
const { rootId, block, readOnly } = this.props;
|
||||
const { id, content } = block;
|
||||
const l = String(content.text || '').length;
|
||||
|
||||
if (readOnly) {
|
||||
return;
|
||||
};
|
||||
|
||||
C.BlockListSetFields(rootId, [
|
||||
{ blockId: id, fields: { lang: v } },
|
||||
|
|
|
@ -38,19 +38,19 @@ class BlockTitle extends React.Component<Props, {}> {
|
|||
};
|
||||
|
||||
render (): any {
|
||||
const { rootId, block } = this.props;
|
||||
const { rootId, block, readOnly } = this.props;
|
||||
const details = blockStore.getDetails(rootId, rootId);
|
||||
const { id } = block;
|
||||
|
||||
const name = this.checkName();
|
||||
const cv = [ 'value', 'focusable', 'c' + id ];
|
||||
const cv = [ 'value', 'focusable', 'c' + id, (readOnly ? 'readOnly' : '') ];
|
||||
|
||||
return (
|
||||
<div className="rel">
|
||||
<div
|
||||
id="value"
|
||||
className={cv.join(' ')}
|
||||
contentEditable={true}
|
||||
contentEditable={!readOnly}
|
||||
suppressContentEditableWarning={true}
|
||||
onChange={this.onChange}
|
||||
onKeyDown={this.onKeyDown}
|
||||
|
|
|
@ -32,7 +32,7 @@ class BlockVideo extends React.Component<Props, {}> {
|
|||
};
|
||||
|
||||
render () {
|
||||
const { block } = this.props;
|
||||
const { block, readOnly } = this.props;
|
||||
const { id, fields, content } = block;
|
||||
const { state, hash, type, mime } = content;
|
||||
|
||||
|
@ -49,7 +49,7 @@ class BlockVideo extends React.Component<Props, {}> {
|
|||
default:
|
||||
case I.FileState.Empty:
|
||||
element = (
|
||||
<InputWithFile block={block} icon="video" textFile="Upload a video" accept={Constant.extension.video} onChangeUrl={this.onChangeUrl} onChangeFile={this.onChangeFile} />
|
||||
<InputWithFile block={block} icon="video" textFile="Upload a video" accept={Constant.extension.video} onChangeUrl={this.onChangeUrl} onChangeFile={this.onChangeFile} readOnly={readOnly} />
|
||||
);
|
||||
break;
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@ import { commonStore, blockStore, authStore } from 'ts/store';
|
|||
import { I, C, M, Key, Util, DataUtil, SmileUtil, Mark, focus, keyboard, crumbs, Storage, Mapper, Action } from 'ts/lib';
|
||||
import { observer } from 'mobx-react';
|
||||
import { throttle } from 'lodash';
|
||||
|
||||
import Controls from './controls';
|
||||
|
||||
interface Props extends RouteComponentProps<any> {
|
||||
|
@ -451,7 +450,7 @@ class EditorPage extends React.Component<Props, State> {
|
|||
const { selection } = dataset || {};
|
||||
const { focused } = focus;
|
||||
|
||||
if (keyboard.isFocused) {
|
||||
if (keyboard.isFocused || !selection) {
|
||||
return;
|
||||
};
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ class HeaderMainEdit extends React.Component<Props, {}> {
|
|||
|
||||
const details = blockStore.getDetails(breadcrumbs, rootId);
|
||||
const { iconEmoji, iconImage, name } = details;
|
||||
const cn = [ 'header', 'headerMainEditSearch' ];
|
||||
const cn = [ 'header', 'headerMainEdit' ];
|
||||
|
||||
if (commonStore.popupIsOpen('navigation')) {
|
||||
cn.push('active');
|
||||
|
@ -55,7 +55,7 @@ class HeaderMainEdit extends React.Component<Props, {}> {
|
|||
<Icon className="forward" tooltip="Forward" onClick={this.onForward} />
|
||||
</div>
|
||||
|
||||
<div className="mid">
|
||||
<div className="side center">
|
||||
<Icon className="nav" tooltip="Navigation" onClick={(e: any) => { this.onNavigation(e, true); }} />
|
||||
|
||||
<div className="path" onMouseDown={(e: any) => { this.onNavigation(e, false); }} onMouseOver={this.onPathOver} onMouseOut={this.onPathOut}>
|
||||
|
|
60
src/ts/component/header/main/history.tsx
Normal file
60
src/ts/component/header/main/history.tsx
Normal file
|
@ -0,0 +1,60 @@
|
|||
import * as React from 'react';
|
||||
import { RouteComponentProps } from 'react-router';
|
||||
import { observer } from 'mobx-react';
|
||||
import { Icon } from 'ts/component';
|
||||
import { DataUtil, I } from 'ts/lib';
|
||||
import { C, Util } from '../../../lib';
|
||||
|
||||
interface Props extends RouteComponentProps<any> {
|
||||
rootId: string;
|
||||
version: I.Version;
|
||||
};
|
||||
|
||||
@observer
|
||||
class HeaderMainHistory extends React.Component<Props, {}> {
|
||||
|
||||
constructor (props: any) {
|
||||
super(props);
|
||||
|
||||
this.onBack = this.onBack.bind(this);
|
||||
this.onRestore = this.onRestore.bind(this);
|
||||
};
|
||||
|
||||
render () {
|
||||
const { version } = this.props;
|
||||
|
||||
return (
|
||||
<div className="header headerMainHistory">
|
||||
<div className="side left">
|
||||
<div className="item grey" onClick={this.onBack}>
|
||||
<Icon className="arrow" />Current version
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="side center">
|
||||
<div className="item">{Util.date('d F Y H:i:s', version.time)}</div>
|
||||
</div>
|
||||
|
||||
<div className="side right" onClick={this.onRestore}>
|
||||
<div className="item orange">Restore version</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
onBack(e: any) {
|
||||
const { rootId } = this.props;
|
||||
DataUtil.pageOpen(e, rootId);
|
||||
};
|
||||
|
||||
onRestore (e: any) {
|
||||
const { rootId, version } = this.props;
|
||||
|
||||
C.HistorySetVersion(rootId, version.id, (message: any) => {
|
||||
DataUtil.pageOpen(e, rootId);
|
||||
});
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
export default HeaderMainHistory;
|
|
@ -15,6 +15,7 @@ import ListChildren from './list/children';
|
|||
import HeaderAuth from './header/auth';
|
||||
import HeaderMainIndex from './header/main/index';
|
||||
import HeaderMainEdit from './header/main/edit';
|
||||
import HeaderMainHistory from './header/main/history';
|
||||
import HeaderHelpIndex from './header/help/index';
|
||||
import FooterAuth from './footer/auth';
|
||||
import FooterMainIndex from './footer/main/index';
|
||||
|
@ -68,6 +69,7 @@ export {
|
|||
HeaderAuth,
|
||||
HeaderMainIndex,
|
||||
HeaderMainEdit,
|
||||
HeaderMainHistory,
|
||||
HeaderHelpIndex,
|
||||
FooterAuth,
|
||||
FooterMainIndex,
|
||||
|
|
|
@ -127,6 +127,7 @@ class MenuBlockMore extends React.Component<Props, {}> {
|
|||
{ id: 'undo', icon: 'undo', name: 'Undo' },
|
||||
{ id: 'redo', icon: 'redo', name: 'Redo' },
|
||||
{ id: 'print', icon: 'print', name: 'Print' },
|
||||
{ id: 'history', icon: 'history', name: 'Version history' },
|
||||
{ id: 'search', icon: 'search', name: 'Search on page' },
|
||||
//{ id: 'move', icon: 'move', name: 'Move to' },
|
||||
//{ id: 'export', icon: 'export', name: 'Export to web' },
|
||||
|
@ -163,7 +164,7 @@ class MenuBlockMore extends React.Component<Props, {}> {
|
|||
onClick (e: any, item: any) {
|
||||
const { param, history } = this.props;
|
||||
const { data } = param;
|
||||
const { blockId, rootId, onSelect, onSearch } = data;
|
||||
const { blockId, rootId, onSelect } = data;
|
||||
const { breadcrumbs } = blockStore;
|
||||
const block = blockStore.getLeaf(rootId, blockId);
|
||||
|
||||
|
@ -194,9 +195,7 @@ class MenuBlockMore extends React.Component<Props, {}> {
|
|||
break;
|
||||
|
||||
case 'print':
|
||||
window.setTimeout(() => {
|
||||
window.print();
|
||||
}, 300);
|
||||
window.setTimeout(() => { window.print(); }, 300);
|
||||
break;
|
||||
|
||||
case 'export':
|
||||
|
@ -206,6 +205,10 @@ class MenuBlockMore extends React.Component<Props, {}> {
|
|||
};
|
||||
});
|
||||
break;
|
||||
|
||||
case 'history':
|
||||
history.push('/main/history/' + blockId);
|
||||
break;
|
||||
|
||||
case 'move':
|
||||
commonStore.popupOpen('navigation', {
|
||||
|
|
|
@ -17,6 +17,7 @@ import PageAuthSuccess from './auth/success';
|
|||
|
||||
import PageMainIndex from './main/index';
|
||||
import PageMainEdit from './main/edit';
|
||||
import PageMainHistory from './main/history';
|
||||
|
||||
const { ipcRenderer } = window.require('electron');
|
||||
const Constant = require('json/constant.json');
|
||||
|
@ -37,6 +38,7 @@ const Components: any = {
|
|||
|
||||
'main/index': PageMainIndex,
|
||||
'main/edit': PageMainEdit,
|
||||
'main/history': PageMainHistory,
|
||||
};
|
||||
|
||||
interface Props extends RouteComponentProps<any> {};
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import * as React from 'react';
|
||||
import * as ReactDOM from 'react-dom';
|
||||
import { RouteComponentProps } from 'react-router';
|
||||
import { Storage } from 'ts/lib';
|
||||
import { HeaderMainEdit as Header, FooterMainEdit as Footer, DragProvider, SelectionProvider, EditorPage } from 'ts/component';
|
||||
|
|
407
src/ts/component/page/main/history.tsx
Normal file
407
src/ts/component/page/main/history.tsx
Normal file
|
@ -0,0 +1,407 @@
|
|||
import * as React from 'react';
|
||||
import * as ReactDOM from 'react-dom';
|
||||
import { RouteComponentProps } from 'react-router';
|
||||
import { HeaderMainHistory as Header, Block, Loader, Icon } from 'ts/component';
|
||||
import { blockStore } from 'ts/store';
|
||||
import { I, M, C, Util, dispatcher, Storage } from 'ts/lib';
|
||||
import { observer } from 'mobx-react';
|
||||
|
||||
interface Props extends RouteComponentProps<any> { };
|
||||
|
||||
interface State {
|
||||
versions: I.Version[];
|
||||
};
|
||||
|
||||
const $ = require('jquery');
|
||||
const LIMIT = 100;
|
||||
const GROUP_OFFSET = 300;
|
||||
|
||||
@observer
|
||||
class PageMainHistory extends React.Component<Props, State> {
|
||||
|
||||
state = {
|
||||
versions: [] as I.Version[],
|
||||
};
|
||||
|
||||
version: I.Version = null;
|
||||
refHeader: any = null;
|
||||
scrollLeft: number = 0;
|
||||
scrollRight: number = 0;
|
||||
loading: boolean = false;
|
||||
lastId: string = '';
|
||||
|
||||
constructor (props: any) {
|
||||
super(props);
|
||||
};
|
||||
|
||||
render () {
|
||||
const { match } = this.props;
|
||||
const { versions } = this.state;
|
||||
const rootId = match.params.id;
|
||||
const groups = this.groupData(versions);
|
||||
|
||||
const root = blockStore.getLeaf(rootId, rootId);
|
||||
if (!this.version || !root) {
|
||||
return <Loader />;
|
||||
};
|
||||
|
||||
const childrenIds = blockStore.getChildrenIds(rootId, rootId);
|
||||
const children = blockStore.getChildren(rootId, rootId);
|
||||
const details = blockStore.getDetails(rootId, rootId);
|
||||
const length = childrenIds.length;
|
||||
|
||||
const withIcon = details.iconEmoji || details.iconImage;
|
||||
const withCover = (details.coverType != I.CoverType.None) && details.coverId;
|
||||
const cover = new M.Block({ id: rootId + '-cover', type: I.BlockType.Cover, childrenIds: [], fields: {}, content: {} });
|
||||
|
||||
let cn = [ 'editorWrapper' ];
|
||||
let icon: any = { id: rootId + '-icon', childrenIds: [], fields: {}, content: {} };
|
||||
|
||||
if (root && root.isPageProfile()) {
|
||||
cn.push('isProfile');
|
||||
icon.type = I.BlockType.IconUser;
|
||||
} else {
|
||||
icon.type = I.BlockType.IconPage;
|
||||
};
|
||||
|
||||
if (root && root.isPageSet()) {
|
||||
cn.push('isDataview');
|
||||
};
|
||||
|
||||
icon = new M.Block(icon);
|
||||
|
||||
if (withIcon && withCover) {
|
||||
cn.push('withIconAndCover');
|
||||
} else
|
||||
if (withIcon) {
|
||||
cn.push('withIcon');
|
||||
} else
|
||||
if (withCover) {
|
||||
cn.push('withCover');
|
||||
};
|
||||
|
||||
const Section = (item: any) => (
|
||||
<React.Fragment>
|
||||
<div className="section">
|
||||
<div className="date">{item.groupId}</div>
|
||||
</div>
|
||||
|
||||
<div className="items">
|
||||
{item.list.map((item: any, i: number) => {
|
||||
return <Version key={i} {...item} />
|
||||
})}
|
||||
</div>
|
||||
</React.Fragment>
|
||||
);
|
||||
|
||||
const Version = (item: any) => {
|
||||
const withChildren = item.list && item.list.length;
|
||||
return (
|
||||
<React.Fragment>
|
||||
<div id={'item-' + item.id} className={[ 'item', (withChildren ? 'withChildren' : '') ].join(' ')} onClick={(e: any) => { this.loadVersion(item.id); }}>
|
||||
{withChildren ? <Icon className="arrow" onClick={(e: any) => { this.toggleChildren(e, item.id); }} /> : ''}
|
||||
<div className="date">{Util.date('d F, H:i', item.time)}</div>
|
||||
{item.authorName ? <div className="name">{item.authorName}</div> : ''}
|
||||
</div>
|
||||
|
||||
{withChildren ? (
|
||||
<div id={'children-' + item.id} className="children">
|
||||
{item.list.map((child: any, i: number) => {
|
||||
return <Version key={i} {...child} />
|
||||
})}
|
||||
</div>
|
||||
) : ''}
|
||||
</React.Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Header ref={(ref: any) => { this.refHeader = ref; }} {...this.props} rootId={rootId} version={this.version} />
|
||||
<div id="body" className="flex">
|
||||
<div id="sideLeft" className="wrapper">
|
||||
<div className={cn.join(' ')}>
|
||||
{withCover ? <Block {...this.props} rootId={rootId} key={cover.id} block={cover} readOnly={true} /> : ''}
|
||||
<div className="editor">
|
||||
<div className="blocks">
|
||||
{withIcon ? (
|
||||
<Block
|
||||
key={icon.id}
|
||||
{...this.props}
|
||||
rootId={rootId}
|
||||
block={icon}
|
||||
className="root"
|
||||
readOnly={true}
|
||||
/>
|
||||
) : ''}
|
||||
|
||||
{children.map((block: I.Block, i: number) => {
|
||||
return (
|
||||
<Block
|
||||
key={block.id}
|
||||
{...this.props}
|
||||
rootId={rootId}
|
||||
index={i}
|
||||
block={block}
|
||||
onKeyDown={() => {}}
|
||||
onKeyUp={() => {}}
|
||||
onMenuAdd={() => {}}
|
||||
onPaste={() => {}}
|
||||
readOnly={true}
|
||||
/>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
|
||||
<div className="blockLast" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="sideRight" className="list">
|
||||
<div className="wrap">
|
||||
{groups.map((item: any, i: number) => {
|
||||
return <Section key={i} {...item} />
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
componentDidMount () {
|
||||
this.loadList('');
|
||||
this.resize();
|
||||
this.setId();
|
||||
};
|
||||
|
||||
componentDidUpdate () {
|
||||
const node = $(ReactDOM.findDOMNode(this));
|
||||
const sideLeft = node.find('#sideLeft');
|
||||
const sideRight = node.find('#sideRight');
|
||||
|
||||
this.resize();
|
||||
this.setId();
|
||||
|
||||
if (this.version) {
|
||||
this.show(this.version.id);
|
||||
};
|
||||
|
||||
sideLeft.scrollTop(this.scrollLeft);
|
||||
sideRight.scrollTop(this.scrollRight);
|
||||
|
||||
sideLeft.unbind('scroll').scroll(() => { this.onScrollLeft(); });
|
||||
sideRight.unbind('scroll').scroll(() => { this.onScrollRight(); });
|
||||
};
|
||||
|
||||
onScrollLeft () {
|
||||
const node = $(ReactDOM.findDOMNode(this));
|
||||
const sideLeft = node.find('#sideLeft');
|
||||
|
||||
this.scrollLeft = sideLeft.scrollTop();
|
||||
};
|
||||
|
||||
onScrollRight () {
|
||||
const { versions } = this.state;
|
||||
const win = $(window);
|
||||
const node = $(ReactDOM.findDOMNode(this));
|
||||
const sideRight = node.find('#sideRight');
|
||||
const wrap = sideRight.find('.wrap');
|
||||
const sections = wrap.find('.section');
|
||||
|
||||
this.scrollRight = sideRight.scrollTop();
|
||||
if (this.scrollRight >= wrap.height() - win.height()) {
|
||||
this.loadList(versions[versions.length - 1].id);
|
||||
};
|
||||
|
||||
sections.each((i: number, item: any) => {
|
||||
item = $(item);
|
||||
const top = item.offset().top;
|
||||
|
||||
let clone = sideRight.find('.section.fix.c' + i);
|
||||
if (top < 0) {
|
||||
if (!clone.length) {
|
||||
clone = item.clone();
|
||||
sideRight.prepend(clone);
|
||||
clone.addClass('fix c' + i).css({ zIndex: i + 1 });
|
||||
};
|
||||
} else {
|
||||
clone.remove();
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
setId () {
|
||||
const { match } = this.props;
|
||||
Storage.set('pageId', match.params.id);
|
||||
};
|
||||
|
||||
show (id: string) {
|
||||
if (!id) {
|
||||
return;
|
||||
};
|
||||
|
||||
const { versions } = this.state;
|
||||
const version = versions.find((it: any) => { return it.id == id; });
|
||||
if (!version) {
|
||||
return;
|
||||
};
|
||||
|
||||
const groups = this.groupData(versions);
|
||||
const month = groups.find((it: any) => { return it.groupId == this.monthId(version.time); });
|
||||
if (!month) {
|
||||
return;
|
||||
};
|
||||
|
||||
let group = month.list.find((it: any) => { return it.groupId == version.groupId; });
|
||||
if (!group) {
|
||||
return;
|
||||
};
|
||||
|
||||
const node = $(ReactDOM.findDOMNode(this));
|
||||
const sideRight = node.find('#sideRight');
|
||||
const item = sideRight.find('#item-' + version.id);
|
||||
|
||||
sideRight.find('.active').removeClass('active');
|
||||
item.addClass('active');
|
||||
|
||||
if (group) {
|
||||
const groupItem = sideRight.find('#item-' + group.id);
|
||||
const children = sideRight.find('#children-' + group.id);
|
||||
|
||||
groupItem.addClass('expanded');
|
||||
children.show();
|
||||
};
|
||||
};
|
||||
|
||||
toggleChildren (e: any, id: string) {
|
||||
e.stopPropagation();
|
||||
|
||||
const node = $(ReactDOM.findDOMNode(this));
|
||||
const sideRight = node.find('#sideRight');
|
||||
const item = sideRight.find('#item-' + id);
|
||||
const children = sideRight.find('#children-' + id);
|
||||
const isActive = item.hasClass('expanded');
|
||||
|
||||
let height = 0;
|
||||
if (isActive) {
|
||||
item.removeClass('expanded');
|
||||
children.css({ overflow: 'visible', height: 'auto' });
|
||||
height = children.height();
|
||||
children.css({ overflow: 'hidden', height: height });
|
||||
|
||||
setTimeout(() => { children.css({ height: 0 }); }, 15);
|
||||
setTimeout(() => { children.hide(); }, 215);
|
||||
} else {
|
||||
item.addClass('expanded');
|
||||
children.show();
|
||||
children.css({ overflow: 'visible', height: 'auto' });
|
||||
height = children.height();
|
||||
|
||||
children.css({ overflow: 'hidden', height: 0 });
|
||||
setTimeout(() => { children.css({ height: height }); }, 15);
|
||||
setTimeout(() => { children.css({ overflow: 'visible', height: 'auto' }); }, 215);
|
||||
};
|
||||
};
|
||||
|
||||
loadList (lastId: string) {
|
||||
const { match } = this.props;
|
||||
const { versions } = this.state;
|
||||
const rootId = match.params.id;
|
||||
|
||||
if (this.loading || (this.lastId && (lastId == this.lastId))) {
|
||||
return;
|
||||
};
|
||||
|
||||
this.loading = true;
|
||||
this.lastId = lastId;
|
||||
|
||||
C.HistoryVersions(rootId, lastId, LIMIT, (message: any) => {
|
||||
this.loading = false;
|
||||
|
||||
if (message.error.code || !message.versions.length) {
|
||||
return;
|
||||
};
|
||||
|
||||
this.setState({ versions: versions.concat(message.versions) });
|
||||
|
||||
if (!this.version) {
|
||||
this.loadVersion(message.versions[0].id);
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
loadVersion (id: string) {
|
||||
const { match } = this.props;
|
||||
const rootId = match.params.id;
|
||||
|
||||
C.HistoryShow(rootId, id, (message: any) => {
|
||||
if (message.error.code) {
|
||||
return;
|
||||
};
|
||||
|
||||
this.version = message.version;
|
||||
|
||||
let bs = message.blockShow;
|
||||
dispatcher.onBlockShow(rootId, bs.type, bs.blocks, bs.details);
|
||||
|
||||
this.forceUpdate();
|
||||
});
|
||||
};
|
||||
|
||||
groupData (versions: I.Version[]) {
|
||||
let months: any[] = [];
|
||||
let groups: any[] = [];
|
||||
let groupId = 0;
|
||||
|
||||
for (let i = 0; i < versions.length; ++i) {
|
||||
let version = versions[i];
|
||||
let prev = versions[i - 1];
|
||||
|
||||
if (prev && ((prev.time - version.time > GROUP_OFFSET) || (prev.time - version.time < 0))) {
|
||||
groupId++;
|
||||
};
|
||||
|
||||
let group = groups.find((it: any) => { return it.groupId == groupId; });
|
||||
if (!group) {
|
||||
group = { ...version, groupId: groupId, list: [] };
|
||||
groups.push(group);
|
||||
} else {
|
||||
group.list.push(version);
|
||||
};
|
||||
};
|
||||
|
||||
for (let group of groups) {
|
||||
let groupId = this.monthId(group.time);
|
||||
let month = months.find((it: any) => { return it.groupId == groupId; });
|
||||
|
||||
if (!month) {
|
||||
month = { groupId: groupId, list: [] };
|
||||
months.push(month);
|
||||
};
|
||||
|
||||
month.list.push(group);
|
||||
};
|
||||
|
||||
return months;
|
||||
};
|
||||
|
||||
monthId (time: number) {
|
||||
return Util.date('F Y', time);
|
||||
};
|
||||
|
||||
resize () {
|
||||
const win = $(window);
|
||||
const node = $(ReactDOM.findDOMNode(this));
|
||||
const sideLeft = node.find('#sideLeft');
|
||||
const sideRight = node.find('#sideRight');
|
||||
const height = win.height();
|
||||
|
||||
sideLeft.css({ height: height });
|
||||
sideRight.css({ height: height });
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
export default PageMainHistory;
|
|
@ -78,12 +78,13 @@ class PageMainIndex extends React.Component<Props, {}> {
|
|||
};
|
||||
|
||||
componentDidMount () {
|
||||
const { history } = this.props;
|
||||
const node = $(ReactDOM.findDOMNode(this));
|
||||
const hello = node.find('#hello');
|
||||
const redirectTo = Storage.get('redirectTo');
|
||||
|
||||
if (redirectTo) {
|
||||
DataUtil.pageOpen(null, redirectTo);
|
||||
history.push(redirectTo);
|
||||
Storage.delete('redirectTo');
|
||||
};
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ interface Props {
|
|||
withFile?: boolean;
|
||||
accept?: string[];
|
||||
block?: I.Block;
|
||||
readOnly?: boolean;
|
||||
onChangeUrl? (e: any, url: string): void;
|
||||
onChangeFile? (e: any, path: string): void;
|
||||
};
|
||||
|
@ -54,7 +55,7 @@ class InputWithFile extends React.Component<Props, State> {
|
|||
|
||||
render () {
|
||||
const { focused, size } = this.state;
|
||||
const { icon, textUrl, textFile, withFile } = this.props;
|
||||
const { icon, textUrl, textFile, withFile, readOnly } = this.props;
|
||||
|
||||
let cn = [ 'inputWithFile', 'resizable' ];
|
||||
let placeHolder = textUrl;
|
||||
|
@ -72,6 +73,10 @@ class InputWithFile extends React.Component<Props, State> {
|
|||
if (isSmall) {
|
||||
cn.push('isSmall');
|
||||
};
|
||||
|
||||
if (readOnly) {
|
||||
cn.push('isReadOnly');
|
||||
};
|
||||
|
||||
if (isIcon) {
|
||||
cn.push('isIcon');
|
||||
|
@ -188,6 +193,11 @@ class InputWithFile extends React.Component<Props, State> {
|
|||
|
||||
onFocus (e: any) {
|
||||
e.stopPropagation();
|
||||
|
||||
const { readOnly } = this.props;
|
||||
if (readOnly) {
|
||||
return;
|
||||
};
|
||||
this.setState({ focused: true });
|
||||
};
|
||||
|
||||
|
@ -201,7 +211,11 @@ class InputWithFile extends React.Component<Props, State> {
|
|||
};
|
||||
|
||||
onChangeUrl (e: any, force: boolean) {
|
||||
const { onChangeUrl } = this.props;
|
||||
const { onChangeUrl, readOnly } = this.props;
|
||||
|
||||
if (readOnly) {
|
||||
return;
|
||||
};
|
||||
|
||||
window.clearTimeout(this.t);
|
||||
this.t = window.setTimeout(() => {
|
||||
|
@ -221,10 +235,14 @@ class InputWithFile extends React.Component<Props, State> {
|
|||
};
|
||||
|
||||
onClickFile (e: any) {
|
||||
const { onChangeFile, accept } = this.props;
|
||||
const { onChangeFile, accept, readOnly } = this.props;
|
||||
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
if (readOnly) {
|
||||
return;
|
||||
};
|
||||
|
||||
let options: any = {
|
||||
properties: [ 'openFile' ],
|
||||
|
|
|
@ -51,6 +51,7 @@ export interface BlockComponent {
|
|||
dataset?: any;
|
||||
rootId: string;
|
||||
block: I.Block;
|
||||
readOnly?: boolean;
|
||||
onKeyDown?(e: any, text: string, marks: I.Mark[], range: I.TextRange): void;
|
||||
onKeyUp?(e: any, text: string, marks: I.Mark[], range: I.TextRange): void;
|
||||
};
|
||||
|
|
|
@ -36,4 +36,13 @@ export interface Option {
|
|||
id: string;
|
||||
name: string;
|
||||
icon?: string;
|
||||
};
|
||||
|
||||
export interface Version {
|
||||
id: string;
|
||||
previousIds: string[];
|
||||
authorId: string;
|
||||
authorName: string;
|
||||
groupId: number;
|
||||
time: number;
|
||||
};
|
|
@ -1,4 +1,4 @@
|
|||
import { Account, Platform, DragItem, CoverType, CrumbsType, NavigationType, Option } from './common';
|
||||
import { Account, Platform, DragItem, CoverType, CrumbsType, NavigationType, Option, Version } from './common';
|
||||
import { Progress, ProgressType, ProgressState } from './progress';
|
||||
import { PopupParam, Popup } from './popup';
|
||||
import { MenuType, MenuDirection, MenuParam, Menu, MenuItem } from './menu';
|
||||
|
@ -38,6 +38,7 @@ export {
|
|||
CrumbsType,
|
||||
NavigationType,
|
||||
Option,
|
||||
Version,
|
||||
|
||||
Progress,
|
||||
ProgressType,
|
||||
|
|
|
@ -596,6 +596,34 @@ const BlockDeleteDataviewRecord = (contextId: string, blockId: string, recordId:
|
|||
dispatcher.request('blockDeleteDataviewRecord', request, callBack);
|
||||
};
|
||||
|
||||
const HistoryVersions = (pageId: string, lastVersionId: string, limit: number, callBack?: (message: any) => void) => {
|
||||
const request = new Rpc.History.Versions.Request();
|
||||
|
||||
request.setPageid(pageId);
|
||||
request.setLastversionid(lastVersionId);
|
||||
request.setLimit(limit);
|
||||
|
||||
dispatcher.request('historyVersions', request, callBack);
|
||||
};
|
||||
|
||||
const HistoryShow = (pageId: string, versionId: string, callBack?: (message: any) => void) => {
|
||||
const request = new Rpc.History.Show.Request();
|
||||
|
||||
request.setPageid(pageId);
|
||||
request.setVersionid(versionId);
|
||||
|
||||
dispatcher.request('historyShow', request, callBack);
|
||||
};
|
||||
|
||||
const HistorySetVersion= (pageId: string, versionId: string, callBack?: (message: any) => void) => {
|
||||
const request = new Rpc.History.Show.Request();
|
||||
|
||||
request.setPageid(pageId);
|
||||
request.setVersionid(versionId);
|
||||
|
||||
dispatcher.request('historySetVersion', request, callBack);
|
||||
};
|
||||
|
||||
export {
|
||||
VersionGet,
|
||||
|
||||
|
@ -670,4 +698,8 @@ export {
|
|||
BlockListSetAlign,
|
||||
BlockListSetPageIsArchived,
|
||||
BlockListDeletePage,
|
||||
|
||||
HistoryVersions,
|
||||
HistoryShow,
|
||||
HistorySetVersion,
|
||||
};
|
||||
|
|
|
@ -165,36 +165,8 @@ class Dispatcher {
|
|||
break;
|
||||
|
||||
case 'blockShow':
|
||||
blocks = data.getBlocksList() || [];
|
||||
let details = data.getDetailsList() || [];
|
||||
|
||||
blocks = blocks.map((it: any) => {
|
||||
it = Mapper.From.Block(it);
|
||||
if (it.id == rootId) {
|
||||
it.type = I.BlockType.Page;
|
||||
it.pageType = data.getType();
|
||||
};
|
||||
return new M.Block(it);
|
||||
});
|
||||
|
||||
block = blocks.find((it: I.Block) => { return it.id == rootId; });
|
||||
if (!block) {
|
||||
break;
|
||||
};
|
||||
|
||||
if (block.canHaveTitle()) {
|
||||
block.childrenIds.unshift(rootId + '-title');
|
||||
blocks.unshift(new M.Block({
|
||||
id: rootId + '-title',
|
||||
type: I.BlockType.Title,
|
||||
childrenIds: [],
|
||||
fields: {},
|
||||
content: {},
|
||||
}));
|
||||
};
|
||||
|
||||
blockStore.blocksSet(rootId, blocks);
|
||||
blockStore.detailsSet(rootId, details);
|
||||
let res = Response.BlockShow(data);
|
||||
this.onBlockShow(rootId, res.type, res.blocks, res.details);
|
||||
break;
|
||||
|
||||
case 'blockAdd':
|
||||
|
@ -517,6 +489,35 @@ class Dispatcher {
|
|||
return 0;
|
||||
};
|
||||
|
||||
onBlockShow (rootId: string, type: number, blocks: any[], details: any[]) {
|
||||
blocks = blocks.map((it: any) => {
|
||||
if (it.id == rootId) {
|
||||
it.type = I.BlockType.Page;
|
||||
it.pageType = type;
|
||||
};
|
||||
return new M.Block(it);
|
||||
});
|
||||
|
||||
let root = blocks.find((it: I.Block) => { return it.id == rootId; });
|
||||
if (!root) {
|
||||
return;
|
||||
};
|
||||
|
||||
if (root.canHaveTitle()) {
|
||||
root.childrenIds.unshift(rootId + '-title');
|
||||
blocks.unshift(new M.Block({
|
||||
id: rootId + '-title',
|
||||
type: I.BlockType.Title,
|
||||
childrenIds: [],
|
||||
fields: {},
|
||||
content: {},
|
||||
}));
|
||||
};
|
||||
|
||||
blockStore.blocksSet(rootId, blocks);
|
||||
blockStore.detailsSet(rootId, details);
|
||||
};
|
||||
|
||||
public request (type: string, data: any, callBack?: (message: any) => void) {
|
||||
const { config } = commonStore;
|
||||
const upper = Util.toUpperCamelCase(type);
|
||||
|
@ -595,13 +596,6 @@ class Dispatcher {
|
|||
'Render time:', renderTime + 'ms',
|
||||
'Total time:', totalTime + 'ms'
|
||||
);
|
||||
|
||||
if (middleTime > 3000) {
|
||||
Sentry.captureMessage(`${type}: middleware time too long`);
|
||||
};
|
||||
if (renderTime > 1000) {
|
||||
Sentry.captureMessage(`${type}: render time too long`);
|
||||
};
|
||||
};
|
||||
});
|
||||
} catch (err) {
|
||||
|
|
|
@ -72,6 +72,13 @@ const Mapper = {
|
|||
if (v == ContentCase.DATAVIEW) t = I.BlockType.Dataview;
|
||||
return t;
|
||||
},
|
||||
|
||||
Details: (obj: any) => {
|
||||
return {
|
||||
id: obj.getId(),
|
||||
details: Decode.decodeStruct(obj.getDetails()),
|
||||
};
|
||||
},
|
||||
|
||||
Block: (obj: any): I.Block => {
|
||||
let type = Mapper.From.BlockType(obj.getContentCase());
|
||||
|
@ -240,6 +247,17 @@ const Mapper = {
|
|||
return observable(new M.View(view));
|
||||
},
|
||||
|
||||
HistoryVersion: (obj: any) => {
|
||||
return {
|
||||
id: obj.getId(),
|
||||
previousIds: obj.getPreviousidsList() || [],
|
||||
authorId: obj.getAuthorid(),
|
||||
authorName: obj.getAuthorname(),
|
||||
groupId: obj.getGroupid(),
|
||||
time: obj.getTime(),
|
||||
};
|
||||
},
|
||||
|
||||
},
|
||||
|
||||
//------------------------------------------------------------
|
||||
|
@ -384,26 +402,26 @@ const Mapper = {
|
|||
return item;
|
||||
},
|
||||
|
||||
View: (view: I.View) => {
|
||||
view = Util.objectCopy(new M.View(view));
|
||||
View: (obj: I.View) => {
|
||||
obj = Util.objectCopy(new M.View(obj));
|
||||
|
||||
const item = new Model.Block.Content.Dataview.View();
|
||||
|
||||
item.setId(view.id);
|
||||
item.setName(view.name);
|
||||
item.setType(view.type);
|
||||
item.setRelationsList(view.relations.map(Mapper.To.ViewRelation));
|
||||
item.setFiltersList(view.filters.map(Mapper.To.Filter));
|
||||
item.setSortsList(view.sorts.map(Mapper.To.Sort));
|
||||
item.setId(obj.id);
|
||||
item.setName(obj.name);
|
||||
item.setType(obj.type);
|
||||
item.setRelationsList(obj.relations.map(Mapper.To.ViewRelation));
|
||||
item.setFiltersList(obj.filters.map(Mapper.To.Filter));
|
||||
item.setSortsList(obj.sorts.map(Mapper.To.Sort));
|
||||
|
||||
return item;
|
||||
},
|
||||
|
||||
PasteFile: (file: any) => {
|
||||
PasteFile: (obj: any) => {
|
||||
const item = new Rpc.Block.Paste.Request.File();
|
||||
|
||||
item.setName(file.name);
|
||||
item.setLocalpath(file.path);
|
||||
item.setName(obj.name);
|
||||
item.setLocalpath(obj.path);
|
||||
|
||||
return item;
|
||||
},
|
||||
|
|
|
@ -110,6 +110,15 @@ const BlockOpen = (response: any) => {
|
|||
return {};
|
||||
};
|
||||
|
||||
const BlockShow = (response: any) => {
|
||||
return {
|
||||
rootId: response.getRootid(),
|
||||
type: response.getType(),
|
||||
blocks: (response.getBlocksList() || []).map(Mapper.From.Block),
|
||||
details: (response.getDetailsList() || []).map(Mapper.From.Details),
|
||||
};
|
||||
};
|
||||
|
||||
const BlockOpenBreadcrumbs = (response: any) => {
|
||||
return {
|
||||
blockId: response.getBlockid(),
|
||||
|
@ -311,6 +320,24 @@ const BlockDeleteDataviewRecord = (response: any) => {
|
|||
return {};
|
||||
};
|
||||
|
||||
const HistoryVersions = (response: any) => {
|
||||
return {
|
||||
versions: (response.getVersionsList() || []).map(Mapper.From.HistoryVersion),
|
||||
};
|
||||
};
|
||||
|
||||
const HistoryShow = (response: any) => {
|
||||
return {
|
||||
version: Mapper.From.HistoryVersion(response.getVersion()),
|
||||
blockShow: this.BlockShow(response.getBlockshow()),
|
||||
};
|
||||
};
|
||||
|
||||
const HistorySetVersion = (response: any) => {
|
||||
return {
|
||||
};
|
||||
};
|
||||
|
||||
export {
|
||||
VersionGet,
|
||||
|
||||
|
@ -341,6 +368,7 @@ export {
|
|||
BlockOpen,
|
||||
BlockOpenBreadcrumbs,
|
||||
BlockSetBreadcrumbs,
|
||||
BlockShow,
|
||||
|
||||
BlockUnlink,
|
||||
BlockClose,
|
||||
|
@ -391,4 +419,7 @@ export {
|
|||
BlockListSetAlign,
|
||||
BlockListDeletePage,
|
||||
|
||||
HistoryVersions,
|
||||
HistoryShow,
|
||||
HistorySetVersion,
|
||||
};
|
||||
|
|
|
@ -265,8 +265,8 @@ class Util {
|
|||
} else {
|
||||
return s;
|
||||
};
|
||||
return false;
|
||||
};
|
||||
|
||||
const f: any = {
|
||||
// Day
|
||||
d: () => {
|
||||
|
|
|
@ -60,7 +60,7 @@ class BlockStore {
|
|||
let map = observable(new Map());
|
||||
|
||||
for (let item of details) {
|
||||
map.set(item.getId(), Decode.decodeStruct(item.getDetails()));
|
||||
map.set(item.id, item.details);
|
||||
};
|
||||
|
||||
intercept(map as any, (change: any) => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue