1
0
Fork 0
mirror of https://github.com/anyproto/anytype-ts.git synced 2025-06-08 05:57:02 +09:00

Merge pull request #1011 from anytypeio/feature/CU-g98fkm

Feature/cu-g98fkm
This commit is contained in:
Razor 2021-04-07 11:39:21 +03:00 committed by GitHub
commit 688533c62f
60 changed files with 815 additions and 555 deletions

View file

@ -29,6 +29,7 @@ try { env = JSON.parse(fs.readFileSync(envPath)); } catch (e) {};
let isUpdating = false;
let userPath = app.getPath('userData');
let tmpPath = path.join(userPath, 'tmp');
let waitLibraryPromise;
let useGRPC = !process.env.ANYTYPE_USE_ADDON && (env.USE_GRPC || process.env.ANYTYPE_USE_GRPC || (process.platform == "win32") || is.development);
let defaultChannel = version.match('alpha') ? 'alpha' : 'latest';
@ -65,9 +66,7 @@ if (app.isPackaged && !app.requestSingleInstanceLock()) {
storage.setDataPath(userPath);
if (process.env.DATA_PATH) {
try {
fs.mkdirSync(process.env.DATA_PATH);
} catch (err) {};
try { fs.mkdirSync(process.env.DATA_PATH); } catch (e) {};
dataPath.push(process.env.DATA_PATH);
} else {
@ -78,6 +77,8 @@ if (process.env.DATA_PATH) {
dataPath.push('data');
};
try { fs.mkdirSync(tmpPath); } catch (e) {};
if (useGRPC) {
console.log('Connect via gRPC');
@ -295,6 +296,20 @@ function createWindow () {
send.apply(this, args);
});
ipcMain.on('screenshot', (event, arg) => {
win.webContents.capturePage().then((image) => {
const fp = path.join(tmpPath, 'screenshot.jpg');
fs.writeFile(fp, image.toJPEG(90), (err) => {
if (err) {
throw err;
};
send('commandEditor', 'screenshot', fp);
});
});
});
ipcMain.on('winCommand', (e, cmd) => {
switch (cmd) {
case 'menu':
@ -660,8 +675,6 @@ app.on('activate', () => {
});
function send () {
console.log('SEND', arguments);
if (win) {
win.webContents.send.apply(win.webContents, arguments);
};

View file

@ -0,0 +1,6 @@
<svg width="20" height="21" viewBox="0 0 20 21" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M15 4.25H5C4.17157 4.25 3.5 4.92157 3.5 5.75V15.75C3.5 16.5784 4.17157 17.25 5 17.25H15C15.8284 17.25 16.5 16.5784 16.5 15.75V5.75C16.5 4.92157 15.8284 4.25 15 4.25ZM5 2.75C3.34315 2.75 2 4.09315 2 5.75V15.75C2 17.4069 3.34315 18.75 5 18.75H15C16.6569 18.75 18 17.4069 18 15.75V5.75C18 4.09315 16.6569 2.75 15 2.75H5Z" fill="#ACA996"/>
<path d="M9.25 7.5C9.25 7.08579 9.58579 6.75 10 6.75C10.4142 6.75 10.75 7.08579 10.75 7.5V14C10.75 14.4142 10.4142 14.75 10 14.75C9.58579 14.75 9.25 14.4142 9.25 14V7.5Z" fill="#ACA996"/>
<path d="M6.75 11.5C6.33579 11.5 6 11.1642 6 10.75C6 10.3358 6.33579 10 6.75 10H13.25C13.6642 10 14 10.3358 14 10.75C14 11.1642 13.6642 11.5 13.25 11.5H6.75Z" fill="#ACA996"/>
</svg>

After

Width:  |  Height:  |  Size: 853 B

View file

@ -29,7 +29,8 @@
"delay": {
"menu": 60,
"popup": 60,
"header": 2000
"header": 2000,
"tooltip": 200
},
"placeHolder": {
@ -75,6 +76,10 @@
]
},
"typeId": {
"template": "_ottemplate"
},
"featuredRelations": [ "type", "creator" ],
"size": {

View file

@ -198,7 +198,7 @@
"popupSettingsColor": { "en": "Colours" },
"popupSettingsPhraseTitle": { "en": "Keychain phrase" },
"popupSettingsMobileQRSubTitle": { "en": "To use Anytype on Android & iOS" },
"popupSettingsMobileQRText": { "en": "— Launch Anytype<br/>— Press \"Login\"<br/>— \"Scan QR code\"<br/>— Point your phone to this screen" },
"popupSettingsMobileQRText": { "en": "— Launch Anytype<br/>— Press \"Login\"<br/>— \"Scan QR code\"<br/>— Click on the QR code to display it clearly<br/>— Point your phone to this screen" },
"popupSettingsPhraseText": { "en": "Your Keychain phrase protects your account. Youll need it to sign in if you dont have access to your devices. Keep it in a safe place. Click to show:" },
"popupSettingsPhraseOk": { "en": "I've written it down" },
"popupSettingsPinTitle": { "en": "Pin code" },

View file

@ -8,7 +8,7 @@
}
.cellHead {
.cellContent { cursor: grab; }
.icon { width: 20px; height: 20px; margin: 0px 4px 0px 0px; vertical-align: top; }
.icon { width: 20px; height: 20px; margin: 0px 4px 0px 0px; vertical-align: top; flex-shrink: 0; }
.name {
display: inline-block; line-height: 20px; height: 20px; vertical-align: top; width: calc(100% - 24px);
@include text-overflow-nw;
@ -31,6 +31,9 @@
tbody { border-top: 1px solid #e0ded2; }
.cellContent { width: 100%; overflow: hidden; height: 20px; line-height: 20px; }
.cellContent {
.name { line-height: 20px; @include text-overflow-nw; width: 100%; }
}
.cell.c-object, .cell.c-file { padding-right: 0px; }
.cellContent.c-object, .cellContent.c-select, .cellContent.c-file {

View file

@ -14,7 +14,8 @@
.sides { display: flex; }
.info { padding: 6px 2px; line-height: 20px; width: 215px; flex-shrink: 0; @include text-overflow-nw; }
.info { padding: 6px 2px; line-height: 20px; width: 30%; min-width: 40px; flex-shrink: 0; @include text-overflow-nw; }
.info.noValue { width: 100%; }
.info {
.input { width: calc(100% - 24px); height: 20px; line-height: 20px; }
.name {
@ -23,7 +24,7 @@
}
}
.cell { @include text-common; width: calc(100% - 216px); position: relative; padding: 5px 8px; border-radius: 4px; transition: background 0.2s ease-in-out; }
.cell { @include text-common; width: 70%; position: relative; padding: 5px 8px; border-radius: 4px; transition: background 0.2s ease-in-out; }
.cell:hover { background: rgba(172,169,150,0.15); }
.cell.c-select { padding: 4px 8px; }

View file

@ -109,8 +109,12 @@
.header.headerMainEdit {
.side.left { opacity: 1; left: 14px; }
.side.left {
.item { cursor: pointer; color: #6c6a5f; }
.icon { width: 20px; height: 20px; margin-right: 4px; border-radius: 0px; vertical-align: middle; }
.btn { cursor: pointer; color: #6c6a5f; display: inline-block; vertical-align: top; border-radius: 6px; padding: 0px 10px; height: 28px; line-height: 26px; }
.btn:hover { background-color: #f3f2ec; }
.btn {
.icon { width: 20px; height: 20px; margin-right: 4px; border-radius: 0px; vertical-align: middle; }
.txt { line-height: 20px; }
}
}
.side.center { opacity: 1; }
.path { border: 0px; cursor: default !important; }

View file

@ -12,6 +12,7 @@
.iconCommon.c20, .smileImage.c20, .iconImage.c20, .iconFile.c20, .iconCheckbox.c20 { @include pos-abs-mid; width: 20px; height: 20px; margin: -10px 0px 0px -10px; }
.iconCommon.c22, .smileImage.c22, .iconImage.c22, .iconFile.c22, .iconCheckbox.c22 { @include pos-abs-mid; width: 22px; height: 22px; margin: -11px 0px 0px -11px; }
.iconCommon.c24, .smileImage.c24, .iconImage.c24, .iconFile.c24, .iconCheckbox.c24 { @include pos-abs-mid; width: 24px; height: 24px; margin: -12px 0px 0px -12px; }
.iconCommon.c26, .smileImage.c26, .iconImage.c26, .iconFile.c26, .iconCheckbox.c26 { @include pos-abs-mid; width: 26px; height: 26px; margin: -13px 0px 0px -13px; }
.iconCommon.c28, .smileImage.c28, .iconImage.c28, .iconFile.c28, .iconCheckbox.c28 { @include pos-abs-mid; width: 28px; height: 28px; margin: -14px 0px 0px -14px; }
.iconCommon.c30, .smileImage.c30, .iconImage.c30, .iconFile.c30, .iconCheckbox.c30 { @include pos-abs-mid; width: 30px; height: 30px; margin: -15px 0px 0px -15px; }
.iconCommon.c32, .smileImage.c32, .iconImage.c32, .iconFile.c32, .iconCheckbox.c32 { @include pos-abs-mid; width: 32px; height: 32px; margin: -16px 0px 0px -16px; }

View file

@ -1,7 +1,7 @@
@import "~scss/_vars";
.linkPreview {
position: absolute; left: 0px; top: 0px; width: 320px; z-index: 100; display: none; opacity: 0;
position: absolute; left: 0px; top: 0px; width: 320px; z-index: 1000; display: none; opacity: 0;
transition: opacity 0.2s ease-in-out;
}
.linkPreview.withImage { height: 268px; }

View file

@ -2,12 +2,12 @@
.progress {
position: fixed; left: 0px; top: 0px; z-index: 110; width: 100%; height: 100%; background: rgba(0,0,0,0.4);
transition: background 0.05s ease-in-out;
transition: background 0.05s ease-in-out; pointer-events: none;
}
.progress.isUnlocked { background: none; height: auto; }
.progress.isUnlocked { background: none; }
.progress.isUnlocked {
.inner { left: auto; right: 10px; top: 40px; margin: 0px; }
.inner { top: auto; left: 10px; bottom: 10px; margin: 0px; }
}
.progress {

View file

@ -3,6 +3,5 @@
.selection { position: relative; user-select: none; }
.selection * { user-select: none; }
#selection-rect {
border: 1px dotted $colorBlack; position: absolute; left: 0px; top: 0px; width: 0px; height: 0px; display: none; z-index: 102;
opacity: 0;
border: 1px dotted $colorBlack; position: absolute; left: 0px; top: 0px; width: 0px; height: 0px; display: none; z-index: 102; opacity: 0;
}

View file

@ -18,11 +18,6 @@ html.debug {
.block.blockLayout.c2 { border-width: 2px; border-color: rgba(0,255,0,0.3); }
.block.blockRelation {
.info { background: rgba(172,169,150,0.1); }
.cell { background: rgba(172,169,150,0.1); }
}
.block.blockText.code {
.icon.codeWrap { background-color: rgba(0, 0, 255, 0.1); }
}

View file

@ -21,7 +21,6 @@
.content { max-height: 362px; padding: 12px 0px; }
}
.menu.menuBlockAdd {
.item.withColor { border-radius: 8px; }
.item.withColor.gray {
.icon, .iconObject { background-color: #f3f2ec; }
}

View file

@ -57,11 +57,12 @@
.icon.clock { background-image: url('~img/icon/menu/action/clock0.svg'); }
.icon.settings { background-image: url('~img/icon/menu/action/settings0.svg'); }
.icon.expand { background-image: url('~img/icon/menu/action/expand0.svg'); }
.icon.template { background-image: url('~img/icon/menu/action/template0.svg'); }
.icon.align.left { background-image: url('~img/icon/menu/align/left.svg'); }
.icon.align.center { background-image: url('~img/icon/menu/align/center.svg'); }
.icon.align.right { background-image: url('~img/icon/menu/align/right.svg'); }
.icon.color {
.inner {
width: 16px; height: 16px; position: absolute; left: 50%; top: 50%; margin: -8px 0px 0px -8px; border-radius: 100%;

View file

@ -92,7 +92,7 @@
.cell.c-select { padding: 4px 8px; }
.cell.c-select {
.empty { display: inline-block; vertical-align: middle; }
.empty { vertical-align: middle; }
.tagItem { margin: 3px 6px 3px 0px; }
}
@ -104,6 +104,7 @@
}
.cell.isEditing.c-select {
.empty { display: inline-block; }
.cellContent { padding: 4px 8px; }
}
.cell.isEditing.c-select.isStatus {

View file

@ -0,0 +1,105 @@
@import "~scss/_vars";
.pageMainStore {
.wrapper { height: 100%; width: 1000px; margin: 0px 0px 0px -500px; position: absolute; left: 50%; top: 0px; }
.content { height: 100%; padding-top: 40px; }
.head { width: 100%; height: 40px; padding: 8px 0px; text-align: center; position: absolute; top: 0px; left: 0px; }
.head {
.tabs {
white-space: nowrap; background: #eae9e0; display: inline-block; height: 28px; padding: 2px; border-radius: 6px;
}
.tabs {
.item {
display: inline-block; margin-right: 4px; width: 124px; border-radius: 4px; height: 24px; line-height: 24px;
font-weight: 500; cursor: pointer; transition: $transitionFast;
}
.item.active { background: #fff; }
.item:last-child { margin: 0px; }
}
}
.body { width: 100%; height: 100%; overflow-y: auto; display: flex; flex-direction: column; }
.body {
.mid { text-align: center; padding: 96px 0px 56px 0px; margin: 0px auto; padding-bottom: 4px; }
.mid {
.title { margin-bottom: 8px; }
.label { @include text-paragraph; margin-bottom: 18px; }
.button { width: 208px; border-radius: 8px; }
.button {
.txt { @include text-paragraph; font-weight: 500; }
}
}
.tabs { white-space: nowrap; margin-bottom: 26px; margin: 0px auto; display: none; }
.tabs {
.item {
display: inline-block; margin-right: 20px; font-weight: 700; cursor: pointer; font-size: 18px; line-height: 26px; letter-spacing: -0.16px;
color: $colorDarkGrey; transition: $transitionFast;
}
.item:hover, .item.active { color: $colorBlack; }
.item:last-child { margin: 0px; }
}
.loaderWrapper { position: relative !important; }
.ReactVirtualized__List { padding: 48px 20px 48px 20px; }
.items { height: 100%; }
.items {
.row { white-space: nowrap; }
.item { display: inline-block; vertical-align: top; position: relative; cursor: pointer; }
.item {
.iconObject.isObjectType, .iconObject.isRelation { position: absolute; left: 0px; top: 0px; }
.iconObject.isUser { vertical-align: middle; margin: -1px 4px 0px 0px; }
.info { height: 100%; position: relative; }
.info {
.name { font-weight: 500; @include text-overflow-nw; }
.descr { @include text-small; color: $colorDarkGrey; @include text-overflow-nw; margin: 2px 0px 3px 0px; }
.author { @include text-small; color: #6c6a5f; line-height: 18px; }
.line { width: 100%; height: 1px; background: #eae9e0; position: absolute; left: 0px; }
}
.button { height: 28px; line-height: 24px; position: absolute; right: 0px; top: 50%; margin-top: -14px; display: none; }
}
.item.marketplace {
.info { padding-right: 80px; }
.button { display: block; }
}
.item.type { margin: 0px 32px 32px 0px; width: 464px; height: 64px; padding-left: 80px; line-height: 64px; }
.item.type:nth-child(2n + 2) { margin-right: 0px; }
.item.type {
.line { bottom: -16px; }
}
.item.template { margin: 0px 24px 28px 0px; width: 304px; height: 252px; }
.item.template:nth-child(3n + 3) { margin-right: 0px; }
.item.template {
.img { width: 100%; height: 180px; border-radius: 8px; margin-bottom: 12px; background-color: $colorBlack; }
.cover { width: 100%; height: 100%; position: relative; border-radius: inherit; }
}
.item.relation { width: 300px; padding-left: 60px; height: 48px; margin: 0px 30px 16px 0px; line-height: 48px; }
.item.relation:nth-child(3n + 3) { margin-right: 0px; }
.item.relation {
.line { bottom: -8px; }
.item:nth-child(2n + 2) { margin-right: 0px; }
}
}
}
.wrapper.relation {
.mid { padding-bottom: 114px; }
.mid {
.label { margin: 0px; }
.button { display: none; }
}
}
}

View file

@ -1,48 +0,0 @@
@import "~scss/_vars";
.popups {
.popup.popupEditorPage {
.innerWrap { width: 960px; height: calc(100% - 128px); padding: 0px; }
.header { position: absolute; padding: 0px; border-radius: 12px 12px 0px 0px; top: 0px !important; }
.header {
.menu { right: 0px; top: 0px; }
}
.content { height: 100%; padding-top: 38px; }
.content > .wrap { height: 100%; }
.selection { height: 100%; overflow-x: hidden; overflow-y: scroll; }
.editor { margin-top: 38px; }
.editorWrapper.isSet { width: calc(100% - 96px); }
.editorWrapper.isSet {
.block.blockCover {
.elements { width: 100%; left: 0px; }
.elements {
.buttons { padding-left: 142px; }
}
}
}
.editorWrapper.withCover { padding-top: 318px; }
.editorWrapper.withIconAndCover { padding-top: 194px; }
.editorWrapper.withIconAndCover {
.block.blockCover {
.elements {
.buttons { padding-left: 118px; }
}
}
}
.editorWrapper.isHuman.withIconAndCover {
.block.blockCover {
.elements {
.buttons { padding-left: 150px; }
}
}
}
.block.blockCover { top: 0px; }
}
}

View file

@ -3,5 +3,57 @@
.popups {
.popup.popupPage {
.innerWrap { width: 960px; height: calc(100% - 128px); padding: 0px; }
.pageMainEdit {
.header { position: absolute; padding: 0px; border-radius: 12px 12px 0px 0px; top: 0px !important; }
.header {
.menu { right: 0px; top: 0px; }
}
.footer { display: none; }
#bodyWrapper > .loaderWrapper { position: fixed; left: 0px; top: 0px; width: 100%; height: 100%; }
.content { height: 100%; padding-top: 38px; }
.content > .wrap { height: 100%; }
.selection { height: 100%; overflow-x: hidden; overflow-y: scroll; }
.editor { margin-top: 38px; }
.editorWrapper { padding-top: 58px; }
.editorWrapper.isSet { width: calc(100% - 96px); }
.editorWrapper.isSet {
.block.blockCover {
.elements { width: 100%; left: 0px; }
.elements {
.buttons { padding-left: 142px; }
}
}
}
.editorWrapper.withIcon { padding-top: 84px; }
.editorWrapper.withCover { padding-top: 318px; }
.editorWrapper.withIconAndCover { padding-top: 194px; }
.editorWrapper.withIconAndCover {
.block.blockCover {
.elements {
.buttons { padding-left: 118px; }
}
}
}
.editorWrapper.isHuman.withIconAndCover {
.block.blockCover {
.elements {
.buttons { padding-left: 150px; }
}
}
}
.block.blockCover { top: 0px; }
}
}
}

View file

@ -98,11 +98,11 @@
b { margin-bottom: 5px; display: block; }
.label { margin: 0px; }
.side { width: 100%; }
.side.right { text-align: right; font-size: 0px; }
.side.right { text-align: right; font-size: 0px; width: 50%; padding: 6px;}
canvas { display: inline-block; }
}
.inputs { margin-bottom: 16px; }
.inputs { margin-bottom: 20px; }
.buttons { margin-top: 32px; }
}

View file

@ -1,99 +0,0 @@
@import "~scss/_vars";
.popups {
.popup.popupStore {
.innerWrap { width: 1152px; }
.content { height: 100%; padding-top: 40px; }
.wrapper { height: 100%; }
.head { width: 100%; height: 40px; padding: 8px 0px; text-align: center; position: absolute; top: 0px; left: 0px; }
.head {
.tabs {
white-space: nowrap; background: #eae9e0; display: inline-block; height: 28px; padding: 2px; border-radius: 6px;
}
.tabs {
.item {
display: inline-block; margin-right: 4px; width: 124px; border-radius: 4px; height: 24px; line-height: 24px;
font-weight: 500; cursor: pointer; transition: $transitionFast;
}
.item.active { background: #fff; }
.item:last-child { margin: 0px; }
}
}
.body { width: 100%; height: 100%; overflow-y: auto; display: flex; flex-direction: column; }
.body {
.mid { text-align: center; padding: 96px 96px 56px 96px; }
.mid {
.title { margin-bottom: 8px; }
.label { @include text-paragraph; margin-bottom: 18px; }
.button { width: 208px; border-radius: 8px; }
.button {
.txt { @include text-paragraph; font-weight: 500; }
}
}
.tabs { white-space: nowrap; margin-bottom: 26px; padding: 0px 96px; }
.tabs {
.item {
display: inline-block; margin-right: 20px; font-weight: 700; cursor: pointer; font-size: 18px; line-height: 26px; letter-spacing: -0.16px;
color: $colorDarkGrey; transition: $transitionFast;
}
.item:hover, .item.active { color: $colorBlack; }
.item:last-child { margin: 0px; }
}
.loaderWrapper { position: relative; }
.ReactVirtualized__List { padding: 0px 96px 48px 96px; }
.items { height: 100%; }
.items {
.item { display: inline-block; vertical-align: top; position: relative; cursor: pointer; }
.item {
.iconObject.isObjectType, .iconObject.isRelation { position: absolute; left: 0px; top: 0px; }
.iconObject.isUser { vertical-align: middle; margin: -1px 4px 0px 0px; }
.info { height: 100%; position: relative; }
.info {
.name { font-weight: 500; @include text-overflow-nw; }
.descr { @include text-small; color: $colorDarkGrey; @include text-overflow-nw; margin: 2px 0px 3px 0px; }
.author { @include text-small; color: #6c6a5f; line-height: 18px; }
.line { width: 100%; height: 1px; background: #eae9e0; position: absolute; left: 0px; }
}
.button { height: 28px; line-height: 24px; position: absolute; right: 0px; top: 50%; margin-top: -14px; display: none; }
}
.item.marketplace {
.info { padding-right: 80px; }
.button { display: block; }
}
.item.type { margin: 0px 32px 32px 0px; width: 464px; height: 64px; padding-left: 80px; line-height: 64px; }
.item.type:nth-child(2n + 2) { margin-right: 0px; }
.item.type {
.line { bottom: -16px; }
}
.item.relation { width: 300px; padding-left: 60px; height: 48px; margin: 0px 30px 16px 0px; line-height: 48px; }
.item.relation:nth-child(3n + 3) { margin-right: 0px; }
.item.relation {
.line { bottom: -8px; }
.item:nth-child(2n + 2) { margin-right: 0px; }
}
}
}
.wrapper.relation {
.mid { padding-bottom: 114px; }
.mid {
.label { margin: 0px; }
.button { display: none; }
}
}
}
}

View file

@ -47,6 +47,7 @@ import 'scss/page/main/history.scss';
import 'scss/page/main/set.scss';
import 'scss/page/main/type.scss';
import 'scss/page/main/relation.scss';
import 'scss/page/main/store.scss';
import 'scss/block/common.scss';
import 'scss/block/dataview.scss';
@ -80,9 +81,7 @@ import 'scss/popup/help.scss';
import 'scss/popup/shortcut.scss';
import 'scss/popup/feedback.scss';
import 'scss/popup/confirm.scss';
import 'scss/popup/store.scss';
import 'scss/popup/page.scss';
import 'scss/popup/editor/page.scss';
import 'emoji-mart/css/emoji-mart.css';
import 'scss/menu/common.scss';
@ -250,8 +249,6 @@ class App extends React.Component<Props, State> {
</div>
</div>
<div id="selection-rect" />
{Routes.map((item: RouteElement, i: number) => (
<Route path={item.path} exact={true} key={i} component={Page} />
))}
@ -494,11 +491,11 @@ class App extends React.Component<Props, State> {
win.on('mousemove.common', throttle((e: any) => {
keyboard.initPinCheck();
keyboard.disableMouse(false);
keyboard.setCoords(e.pageX, e.pageY);
keyboard.setCoords(e);
}, THROTTLE));
win.on('blur.common', () => {
Util.tooltipHide();
Util.tooltipHide(true);
Util.linkPreviewHide(true);
});
};

View file

@ -24,7 +24,7 @@ class HeadHandle extends React.Component<Props, {}> {
const { format, name, onClick } = this.props;
const Handle = SortableHandle(() => (
<div onMouseDown={this.onMouseDown} onClick={onClick}>
<div className="flex" onMouseDown={this.onMouseDown} onClick={onClick}>
<Icon className={'relation ' + DataUtil.relationClass(format)} />
<div className="name">{name}</div>
</div>

View file

@ -371,7 +371,7 @@ class Block extends React.Component<Props, {}> {
const elementId = `#button-block-menu-${block.id}`;
const element = $(elementId);
const offset = element.offset();
const rect = { x: offset.left, y: keyboard.coords.y, width: element.width(), height: 0 };
const rect = { x: offset.left, y: keyboard.mouse.page.y, width: element.width(), height: 0 };
menuStore.open('blockAction', {
offsetX: element.outerWidth(),

View file

@ -41,7 +41,7 @@ class BlockRelation extends React.Component<Props, {}> {
{!relation ?
(
<div className="sides">
<div className="info">
<div className="info noValue">
<Icon key="icon-default" className="relation default" />
<Input
id="input"

View file

@ -10,6 +10,7 @@ import { throttle } from 'lodash';
interface Props extends RouteComponentProps<any> {
dataset?: any;
rootId: string;
isPopup: boolean;
};
const $ = require('jquery');
@ -152,7 +153,7 @@ class DragProvider extends React.Component<Props, {}> {
};
onDragStart (e: any, type: string, ids: string[], component: any) {
const { rootId, dataset } = this.props;
const { rootId, dataset, isPopup } = this.props;
const { selection } = dataset || {};
const win = $(window);
const node = $(ReactDOM.findDOMNode(this));
@ -178,7 +179,7 @@ class DragProvider extends React.Component<Props, {}> {
win.on('drag.drag', throttle((e: any) => { this.onDragMove(e); }, THROTTLE));
$('.colResize.active').removeClass('active');
scrollOnMove.onMouseDown(e);
scrollOnMove.onMouseDown(e, isPopup);
if (selection) {
selection.set(this.ids);
@ -188,12 +189,17 @@ class DragProvider extends React.Component<Props, {}> {
};
onDragMove (e: any) {
const { rootId } = this.props;
const { rootId, isPopup } = this.props;
const ex = e.pageX;
const ey = e.pageY;
const dt = (e.dataTransfer || e.originalEvent.dataTransfer);
const isFileDrag = dt.types.indexOf('Files') >= 0;
const top = this.getScrollContainer().scrollTop();
let ey = e.pageY;
if (isPopup) {
ey += top;
};
this.hoverData = null;
this.position = I.BlockPosition.None;
@ -203,13 +209,17 @@ class DragProvider extends React.Component<Props, {}> {
};
this.objectData.forEach((value: any) => {
let { x, y, width, height, dropType, index } = value;
let { x, y, width, height, dropType } = value;
if (dropType == I.DragItem.Block) {
x -= OFFSET;
width += OFFSET * 2;
};
if (isPopup) {
y += top;
};
if ((ex >= x) && (ex <= x + width) && (ey >= y) && (ey <= y + height)) {
this.hoverData = value;
};
@ -310,7 +320,7 @@ class DragProvider extends React.Component<Props, {}> {
}, 10);
};
scrollOnMove.onMouseMove(e);
scrollOnMove.onMouseMove(e.clientX, e.clientY);
};
onDragEnd (e: any) {
@ -341,6 +351,8 @@ class DragProvider extends React.Component<Props, {}> {
const map = blockStore.getMap(rootId);
const element = map[targetId];
console.log(target, element);
if (!target || !element) {
return;
};
@ -394,6 +406,10 @@ class DragProvider extends React.Component<Props, {}> {
};
};
getScrollContainer () {
return this.props.isPopup ? $('#popupPage #innerWrap') : $(window);
};
getParentIds (id: string, parentIds: string[]) {
const { rootId } = this.props;
const item = this.map[id];

View file

@ -23,6 +23,7 @@ const Errors = require('json/error.json');
const $ = require('jquery');
const THROTTLE = 20;
const fs = window.require('fs');
const path = window.require('path');
@observer
class EditorPage extends React.Component<Props, {}> {
@ -31,6 +32,7 @@ class EditorPage extends React.Component<Props, {}> {
id: string = '';
timeoutHover: number = 0;
timeoutMove: number = 0;
timeoutScreen: number = 0;
hoverId: string = '';
hoverPosition: number = 0;
scrollTop: number = 0;
@ -142,7 +144,7 @@ class EditorPage extends React.Component<Props, {}> {
Storage.set('askSurvey', 1);
ipcRenderer.removeAllListeners('commandEditor');
ipcRenderer.on('commandEditor', (e: any, cmd: string) => { this.onCommand(cmd); });
ipcRenderer.on('commandEditor', (e: any, cmd: string, arg: any) => { this.onCommand(cmd, arg); });
};
componentDidUpdate () {
@ -184,12 +186,13 @@ class EditorPage extends React.Component<Props, {}> {
focus.clear(false);
Storage.delete('editorId');
window.clearInterval(this.timeoutScreen);
ipcRenderer.removeAllListeners('commandEditor');
};
getScrollContainer () {
const { isPopup } = this.props;
return isPopup ? $('#popupEditorPage .selection') : $(window);
return isPopup ? $('#popupPage .selection') : $(window);
};
getWrapper () {
@ -222,9 +225,7 @@ class EditorPage extends React.Component<Props, {}> {
C.BlockOpen(this.id, (message: any) => {
if (message.error.code) {
if (message.error.code == Errors.Code.ANYTYPE_NEEDS_UPGRADE) {
Util.onErrorUpdate(() => {
history.push('/main/index');
});
Util.onErrorUpdate(() => { history.push('/main/index'); });
} else {
history.push('/main/index');
};
@ -237,6 +238,12 @@ class EditorPage extends React.Component<Props, {}> {
this.resize();
this.getScrollContainer().scrollTop(Storage.getScroll('editor' + (isPopup ? 'Popup' : ''), rootId));
const object = blockStore.getDetails(rootId, rootId);
if (!isPopup && (object.type == Constant.typeId.template)) {
window.clearInterval(this.timeoutScreen);
this.timeoutScreen = window.setInterval(() => { ipcRenderer.send('screenshot'); }, 3000);
};
blockStore.setNumbers(rootId);
if (onOpen) {
@ -245,7 +252,7 @@ class EditorPage extends React.Component<Props, {}> {
});
};
onCommand (cmd: string) {
onCommand (cmd: string, arg: any) {
if (keyboard.isFocused) {
return;
};
@ -274,6 +281,18 @@ class EditorPage extends React.Component<Props, {}> {
case 'search':
this.onSearch();
break;
case 'screenshot':
if (!arg) {
break;
};
C.UploadFile('', arg, I.FileType.Image, true, (message: any) => {
if (message.error.code) {
return;
};
});
break;
};
};
@ -1122,7 +1141,7 @@ class EditorPage extends React.Component<Props, {}> {
const { dataset, rootId } = this.props;
const { selection } = dataset || {};
const { focused, range } = focus;
const { path } = authStore;
const filePath = authStore.path;
const currentFrom = range.from;
const currentTo = range.to;
@ -1156,26 +1175,19 @@ class EditorPage extends React.Component<Props, {}> {
commonStore.progressSet({ status: 'Processing...', current: 0, total: files.length });
for (let file of files) {
const dir = path + '/tmp';
const fn = dir + '/' + file.name;
const dir = path.join(filePath, 'tmp');
const fn = path.join(dir, file.name);
const reader = new FileReader();
reader.readAsBinaryString(file);
reader.onloadend = () => {
try {
fs.mkdirSync(dir);
} catch (e) {};
fs.writeFile(fn, reader.result, 'binary', (err: any) => {
if (err) {
console.error(err);
return;
};
data.files.push({
name: file.name,
path: fn,
});
data.files.push({ name: file.name, path: fn });
commonStore.progressSet({ status: 'Processing...', current: data.files.length, total: files.length });
@ -1559,15 +1571,13 @@ class EditorPage extends React.Component<Props, {}> {
focus (id: string, from: number, to: number, scroll: boolean) {
const { isPopup } = this.props;
const container = isPopup ? $('#popupEditorPage #innerWrap .content') : $(window);
focus.set(id, { from: from, to: to });
focus.apply();
if (scroll) {
focus.scroll(container);
focus.scroll(isPopup);
};
this.resize();
};

View file

@ -2,7 +2,7 @@ import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { RouteComponentProps } from 'react-router';
import { Icon, IconObject, Sync } from 'ts/component';
import { I, Util, DataUtil, crumbs, focus } from 'ts/lib';
import { I, Util, DataUtil, crumbs, focus, history as historyPopup } from 'ts/lib';
import { commonStore, blockStore, menuStore, popupStore } from 'ts/store';
import { observer } from 'mobx-react';
@ -18,7 +18,7 @@ const Constant = require('json/constant.json');
@observer
class HeaderMainEdit extends React.Component<Props, {}> {
isHidden: boolean = false;
timeout: number = 0;
constructor (props: any) {
super(props);
@ -59,9 +59,12 @@ class HeaderMainEdit extends React.Component<Props, {}> {
<div id="header" className={cn.join(' ')}>
{isPopup ? (
<div className="side left">
<div className="item" onClick={this.onOpen}>
<Icon className={[ 'back', 'big', (!historyPopup.checkBack() ? 'disabled' : '') ].join(' ')} tooltip="Back" onClick={this.onBack} />
<Icon className={[ 'forward', 'big', (!historyPopup.checkForward() ? 'disabled' : '') ].join(' ')} tooltip="Forward" onClick={this.onForward} />
<div className="btn" onClick={this.onOpen}>
<Icon className="expand" />
Open as page
<div className="txt">Open as page</div>
</div>
</div>
) : (
@ -107,15 +110,11 @@ class HeaderMainEdit extends React.Component<Props, {}> {
};
init () {
if (!this.isHidden) {
const node = $(ReactDOM.findDOMNode(this));
node.addClass('show');
const node = $(ReactDOM.findDOMNode(this));
node.addClass('show');
window.setTimeout(() => {
this.isHidden = true;
node.removeClass('show');
}, Constant.delay.header);
};
window.clearTimeout(this.timeout);
this.timeout = window.setTimeout(() => { node.removeClass('show'); }, Constant.delay.header);
};
onHome (e: any) {
@ -123,13 +122,29 @@ class HeaderMainEdit extends React.Component<Props, {}> {
};
onBack (e: any) {
const { isPopup, history } = this.props;
crumbs.restore(I.CrumbsType.Page);
this.props.history.goBack();
if (isPopup) {
historyPopup.goBack((match: any) => {
popupStore.updateData('page', { matchPopup: match });
});
} else {
history.goBack();
};
};
onForward (e: any) {
const { isPopup, history } = this.props;
crumbs.restore(I.CrumbsType.Page);
this.props.history.goForward();
if (isPopup) {
historyPopup.goForward((match: any) => {
popupStore.updateData('page', { matchPopup: match });
});
} else {
history.goForward();
};
};
onOpen () {
@ -191,7 +206,7 @@ class HeaderMainEdit extends React.Component<Props, {}> {
};
};
DataUtil.pageCreate(e, rootId, targetId, {}, position, (message: any) => {
DataUtil.pageCreate(rootId, targetId, {}, position, '', (message: any) => {
DataUtil.objectOpen({ id: message.targetId });
});
};
@ -295,7 +310,7 @@ class HeaderMainEdit extends React.Component<Props, {}> {
};
onPathOut () {
Util.tooltipHide();
Util.tooltipHide(false);
};
getContainer () {

View file

@ -110,7 +110,7 @@ class HeaderMainSet extends React.Component<Props, {}> {
};
onPathOut () {
Util.tooltipHide();
Util.tooltipHide(false);
};
};

View file

@ -64,7 +64,16 @@ class MenuBlockAdd extends React.Component<Props, {}> {
action.iconSize = 40;
};
return <MenuItemVertical key={action.id + '-' + i} {...action} withDescription={action.isBlock} onMouseEnter={(e: any) => { this.onMouseEnter(e, action); }} onClick={(e: any) => { this.onClick(e, action); }} />;
return (
<MenuItemVertical
key={action.id + '-' + i}
{...action}
className={action.isHidden ? 'isHidden' : ''}
withDescription={action.isBlock}
onMouseEnter={(e: any) => { this.onMouseEnter(e, action); }}
onClick={(e: any) => { this.onClick(e, action); }}
/>
);
})}
</div>
</div>
@ -400,7 +409,7 @@ class MenuBlockAdd extends React.Component<Props, {}> {
};
};
DataUtil.pageCreate(e, rootId, blockId, details, position, (message: any) => {
DataUtil.pageCreate(rootId, blockId, details, position, '', (message: any) => {
DataUtil.objectOpenPopup({ ...details, id: message.targetId });
});
};

View file

@ -190,8 +190,14 @@ class MenuBlockMore extends React.Component<Props, {}> {
//{ id: 'export', icon: 'export', name: 'Export to web' },
];
if (object.type == Constant.typeId.template) {
items.push({ id: 'createPage', icon: 'template', name: 'Create object' },);
} else {
items.push({ id: 'createTemplate', icon: 'template', name: 'Create a template' });
};
if (block.canHaveHistory()) {
items.push({ id: 'history', name: 'Version history' },);
items.push({ id: 'history', name: 'Version history' });
};
if (object.isArchived) {
@ -316,6 +322,17 @@ class MenuBlockMore extends React.Component<Props, {}> {
});
break;
case 'createTemplate':
C.MakeTemplate(rootId, (message: any) => {
});
break;
case 'createPage':
DataUtil.pageCreate('', '', {}, I.BlockPosition.Bottom, rootId, (message: any) => {
DataUtil.objectOpen({ id: message.targetId });
});
break;
case 'removePage':
C.BlockListDeletePage([ blockId ], (message: any) => {
if (block.isPage()) {
@ -408,8 +425,9 @@ class MenuBlockMore extends React.Component<Props, {}> {
case 'type':
menuId = 'searchObject';
menuParam.vertical = I.MenuDirection.Bottom;
menuParam.className = [ param.className, 'single' ].join(' ');
menuParam.fixedY = param.offsetY;
menuParam.offsetY = -36;
menuParam.data = Object.assign(menuParam.data, {
placeHolder: 'Find a type of object...',

View file

@ -366,7 +366,7 @@ class MenuDataviewObjectList extends React.Component<Props, State> {
};
};
DataUtil.pageCreate(e, '', '', details, I.BlockPosition.Bottom, (message: any) => {
DataUtil.pageCreate('', '', details, I.BlockPosition.Bottom, '', (message: any) => {
cb(message.targetId);
close();
});

View file

@ -107,7 +107,10 @@ class MenuRelationList extends React.Component<Props, {}> {
filter: '',
skipIds: relations.map((it: I.ViewRelation) => { return it.relationKey; }),
addCommand: (rootId: string, blockId: string, relation: any) => {
DataUtil.dataviewRelationAdd(rootId, blockId, relation, getView(), (message: any) => { menuStore.close('relationSuggest'); });
DataUtil.dataviewRelationAdd(rootId, blockId, relation, getView(), (message: any) => {
close();
menuStore.close('relationSuggest');
});
},
listCommand: (rootId: string, blockId: string, callBack?: (message: any) => void) => {
C.BlockDataviewRelationListAvailable(rootId, blockId, callBack);

View file

@ -89,8 +89,6 @@ class MenuText extends React.Component<Props, {}> {
node.css({ height: 'auto' });
const sh = node.get(0).scrollHeight;
console.log(sh);
node.css({ height: Math.min(wh - 78, sh) });
node.scrollTop(sh);

View file

@ -243,6 +243,8 @@ class Menu extends React.Component<Props, {}> {
if (noAnimation) {
menu.addClass('noAnimation');
} else {
window.setTimeout(() => { menu.css({ transform: 'none' }); }, Constant.delay.menu);
};
menu.addClass('show');
@ -376,7 +378,7 @@ class Menu extends React.Component<Props, {}> {
menu.css(css);
if (isSub && (type == I.MenuType.Vertical)) {
const coords = Util.objectCopy(keyboard.coords);
const coords = Util.objectCopy(keyboard.mouse.page);
const poly = $('#menu-polygon');
if (isFixed) {

View file

@ -258,11 +258,14 @@ class MenuSearchObject extends React.Component<Props, State> {
filterMapper (it: any, config: any) {
const { param } = this.props;
const { data } = param;
const { type } = data;
const { type, skipId } = data;
if (it.isArchived) {
return false;
};
if (it.id == skipId) {
return false;
};
if (!config.allowDataview && (it.layout != I.ObjectLayout.Page)) {
return false;
};

View file

@ -22,6 +22,7 @@ import PageMainHistory from './main/history';
import PageMainSet from './main/set';
import PageMainType from './main/type';
import PageMainRelation from './main/relation';
import PageMainStore from './main/store';
const { ipcRenderer } = window.require('electron');
const Constant = require('json/constant.json');
@ -46,6 +47,7 @@ const Components: any = {
'main/set': PageMainSet,
'main/type': PageMainType,
'main/relation': PageMainRelation,
'main/store': PageMainStore,
};
interface Props extends RouteComponentProps<any> {
@ -62,6 +64,7 @@ class Page extends React.Component<Props, {}> {
render () {
const { isPopup } = this.props;
const match = this.getMatch();
const path = [ match.params.page, match.params.action ].join('/');
const showNotice = !Boolean(Storage.get('firstRun'));
@ -119,6 +122,7 @@ class Page extends React.Component<Props, {}> {
const lastSurveyCanceled = Number(Storage.get('lastSurveyCanceled')) || 0;
const askSurvey = Number(Storage.get('askSurvey')) || 0;
const days = lastSurveyTime ? 30 : 14;
const win = $(window);
if (pin && !keyboard.isPinChecked && !isPinCheck && !isAuth && !isIndex) {
history.push('/auth/pin-check');
@ -170,11 +174,12 @@ class Page extends React.Component<Props, {}> {
}, Constant.delay.popup);
};
$(window).on('resize.page', () => { this.resize(); });
win.on('resize.page' + (isPopup ? 'Popup' : ''), () => { this.resize(); });
};
unbind () {
$(window).unbind('resize.page');
const { isPopup } = this.props;
$(window).unbind('resize.page' + (isPopup ? 'Popup' : ''));
};
event () {

View file

@ -3,7 +3,10 @@ import { RouteComponentProps } from 'react-router';
import { Storage } from 'ts/lib';
import { HeaderMainEdit as Header, FooterMainEdit as Footer, DragProvider, SelectionProvider, EditorPage } from 'ts/component';
interface Props extends RouteComponentProps<any> {};
interface Props extends RouteComponentProps<any> {
rootId: string;
isPopup?: boolean;
};
class PageMainEdit extends React.Component<Props, {}> {
@ -16,17 +19,17 @@ class PageMainEdit extends React.Component<Props, {}> {
};
render () {
const { history, location, match } = this.props;
const rootId = match.params.id;
const { history, location, match, isPopup } = this.props;
const rootId = this.getRootId();
return (
<div>
<SelectionProvider rootId={match.params.id}>
<DragProvider {...this.props} rootId={rootId}>
<Header ref={(ref: any) => { this.refHeader = ref; }} {...this.props} rootId={rootId} isPopup={false} />
<SelectionProvider rootId={match.params.id} isPopup={isPopup}>
<DragProvider {...this.props} rootId={rootId} isPopup={isPopup}>
<Header ref={(ref: any) => { this.refHeader = ref; }} {...this.props} rootId={rootId} isPopup={isPopup} />
<div className="wrapper">
<EditorPage key="editorPage" {...this.props} isPopup={false} rootId={rootId} onOpen={this.onOpen} />
<div id="bodyWrapper" className="wrapper">
<EditorPage key="editorPage" {...this.props} isPopup={isPopup} rootId={rootId} onOpen={this.onOpen} />
</div>
</DragProvider>
</SelectionProvider>
@ -41,6 +44,11 @@ class PageMainEdit extends React.Component<Props, {}> {
this.refHeader.forceUpdate();
};
};
getRootId () {
const { rootId, match } = this.props;
return rootId ? rootId : match.params.id;
};
};

View file

@ -165,7 +165,7 @@ class PageMainIndex extends React.Component<Props, {}> {
};
onStore (e: any) {
popupStore.open('store', {});
DataUtil.objectOpenPopup({ layout: I.ObjectLayout.Store });
};
onAdd (e: any) {
@ -226,7 +226,7 @@ class PageMainIndex extends React.Component<Props, {}> {
},
onSelect: (event: any, item: any) => {
if (item.id == 'page') {
DataUtil.pageCreate(e, root, '', {}, I.BlockPosition.Bottom, (message: any) => {
DataUtil.pageCreate(root, '', {}, I.BlockPosition.Bottom, '', (message: any) => {
DataUtil.objectOpen({ id: message.targetId });
});

View file

@ -1,13 +1,13 @@
import * as React from 'react';
import { RouteComponentProps } from 'react-router';
import { Title, Label, Button, IconObject, Loader } from 'ts/component';
import { I, C, DataUtil, SmileUtil } from 'ts/lib';
import { Title, Label, Button, IconObject, Loader, Cover } from 'ts/component';
import { I, C, DataUtil, Util, Storage } from 'ts/lib';
import { dbStore, blockStore } from 'ts/store';
import { observer } from 'mobx-react';
import { AutoSizer, CellMeasurer, InfiniteLoader, List, CellMeasurerCache } from 'react-virtualized';
interface Props extends I.Popup, RouteComponentProps<any> {
history: any;
interface Props extends RouteComponentProps<any> {
isPopup?: boolean;
};
interface State {
@ -16,6 +16,7 @@ interface State {
};
enum Tab {
None = '',
Type = 'type',
Template = 'template',
Relation = 'relation',
@ -52,10 +53,10 @@ const Tabs = [
const BLOCK_ID = 'dataview';
@observer
class PopupStore extends React.Component<Props, State> {
class PageMainStore extends React.Component<Props, State> {
state = {
tab: Tab.Type,
tab: '',
loading: false,
};
@ -68,7 +69,6 @@ class PopupStore extends React.Component<Props, State> {
this.loadMoreRows = this.loadMoreRows.bind(this);
this.getRowHeight = this.getRowHeight.bind(this);
this.resize = this.resize.bind(this);
};
render () {
@ -132,12 +132,37 @@ class PopupStore extends React.Component<Props, State> {
<Title text="Type every object" />
<Label text="Our beautifully-designed templates come with hundreds" />
<Button text="Create a new type" className="orange" onClick={(e: any) => { this.onCreateType(); }} />
<Button text="Create a new type" className="orange" onClick={(e: any) => { this.onCreateType(e); }} />
</div>
);
break;
case Tab.Template:
Item = (item: any) => {
let { name, description, coverType, coverId, coverX, coverY, coverScale } = item;
const author = blockStore.getDetails(rootId, item.creator);
return (
<div className={[ 'item', tab, meta.viewId ].join(' ')} onClick={(e: any) => { this.onClick(e, item); }}>
<div className="img">
{coverId && coverType ? <Cover type={coverType} id={coverId} image={coverId} className={coverId} x={coverX} y={coverY} scale={coverScale} withScale={true} /> : ''}
</div>
<div className="info">
<div className="name">{name}</div>
<div className="descr">{description}</div>
<Author {...author} />
</div>
</div>
);
};
mid = (
<div className="mid">
<Title text="Template space" />
<Label text="Our beautifully-designed templates come with hundreds" />
<Button text="Create tempate" className="orange" onClick={(e: any) => { this.onCreateTemplate(); }} />
</div>
);
break;
case Tab.Relation:
@ -195,7 +220,7 @@ class PopupStore extends React.Component<Props, State> {
<div className="head">
<div className="tabs">
{Tabs.map((item: any, i: number) => (
<div key={item.id} className={[ 'item', (item.id == tab ? 'active' : '') ].join(' ')} onClick={(e: any) => { this.onTab(e, item); }}>
<div key={item.id} className={[ 'item', (item.id == tab ? 'active' : '') ].join(' ')} onClick={(e: any) => { this.onTab(item.id); }}>
{item.name}
</div>
))}
@ -242,9 +267,7 @@ class PopupStore extends React.Component<Props, State> {
componentDidMount () {
this._isMounted = true;
this.rebind();
this.resize();
this.onTab(null, Tabs[0]);
this.onTab(Storage.get('storeTab') || Tabs[0].id);
};
componentDidUpdate () {
@ -255,45 +278,10 @@ class PopupStore extends React.Component<Props, State> {
defaultHeight: this.getRowHeight(),
keyMapper: (i: number) => { return (items[i] || {}).id; },
});
this.resize();
};
componentWillUnmount () {
this._isMounted = false;
this.unbind();
};
rebind () {
if (!this._isMounted) {
return;
};
this.unbind();
const win = $(window);
win.unbind('resize.store').on('resize.store', () => { this.resize(); });
};
unbind () {
$(window).unbind('resize.store');
};
resize () {
if (!this._isMounted) {
return;
};
raf(() => {
const { getId, position } = this.props;
const win = $(window);
const obj = $(`#${getId()} #innerWrap`);
const height = Math.max(648, win.height() - 128);
obj.css({ height: height });
position();
});
};
getRootId () {
@ -312,7 +300,7 @@ class PopupStore extends React.Component<Props, State> {
let h = 0;
if (tab == Tab.Type) h = 96;
if (tab == Tab.Template) h = 2;
if (tab == Tab.Template) h = 280;
if (tab == Tab.Relation) h = 64;
return h;
};
@ -322,21 +310,23 @@ class PopupStore extends React.Component<Props, State> {
let l = 0;
if (tab == Tab.Type) l = 2;
if (tab == Tab.Template) l = 2;
if (tab == Tab.Template) l = 3;
if (tab == Tab.Relation) l = 3;
return l;
};
onTab (e: any, item: any) {
const tabItem = Tabs.find((it: any) => { return it.id == item.id; });
if (!tabItem) {
onTab (id: Tab) {
if (this.state.tab == id) {
return;
};
this.state.tab = tabItem.id;
this.setState({ tab: item.id, loading: true });
Storage.set('storeTab', id);
this.state.tab = id;
this.setState({ tab: id, loading: true });
C.BlockOpen(this.getRootId(), (message: any) => {
this.getData('library', true);
this.setState({ loading: false });
});
};
@ -346,10 +336,11 @@ class PopupStore extends React.Component<Props, State> {
};
onClick (e: any, item: any) {
DataUtil.objectOpenEvent(e, item);
const { isPopup } = this.props;
isPopup ? DataUtil.objectOpenPopup(item) : DataUtil.objectOpenEvent(e, item);
};
onCreateType () {
onCreateType (e: any) {
const { objectTypes } = dbStore;
const param: any = {
name: '',
@ -364,10 +355,13 @@ class PopupStore extends React.Component<Props, State> {
objectTypes.push(message.objectType);
dbStore.objectTypesSet(objectTypes);
DataUtil.objectOpen({ ...message.objectType, layout: I.ObjectLayout.ObjectType });
this.onClick(e, { ...message.objectType, layout: I.ObjectLayout.ObjectType });
});
};
onCreateTemplate () {
};
getData (id: string, clear: boolean, callBack?: (message: any) => void) {
const rootId = this.getRootId();
const { viewId } = dbStore.getMeta(rootId, BLOCK_ID);
@ -403,7 +397,7 @@ class PopupStore extends React.Component<Props, State> {
getItems () {
const limit = this.getRowLimit();
const rootId = this.getRootId();
const data = dbStore.getData(rootId, BLOCK_ID).map((it: any) => {
const data = Util.objectCopy(dbStore.getData(rootId, BLOCK_ID)).map((it: any) => {
it.name = String(it.name || Constant.default.name || '');
return it;
});
@ -434,4 +428,4 @@ class PopupStore extends React.Component<Props, State> {
};
export default PopupStore;
export default PageMainStore;

View file

@ -1,87 +0,0 @@
import * as React from 'react';
import { I } from 'ts/lib';
import { RouteComponentProps } from 'react-router';
import { HeaderMainEdit as Header, DragProvider, SelectionProvider, EditorPage } from 'ts/component';
import { commonStore } from 'ts/store';
interface Props extends I.Popup, RouteComponentProps<any> {};
const $ = require('jquery');
const raf = require('raf');
class PopupEditorPage extends React.Component<Props, {}> {
refHeader: any = null;
_isMounted: boolean = false;
constructor (props: any) {
super(props);
this.onOpen = this.onOpen.bind(this);
};
render () {
const { param } = this.props;
const { data } = param;
const { rootId } = data;
return (
<div className="wrap">
<Header ref={(ref: any) => { this.refHeader = ref; }} {...this.props} rootId={rootId} isPopup={true} />
<SelectionProvider rootId={rootId}>
<DragProvider {...this.props} rootId={rootId}>
<EditorPage key="editorPagePopup" isPopup={true} {...this.props} rootId={rootId} onOpen={this.onOpen} />
</DragProvider>
</SelectionProvider>
</div>
);
};
componentDidMount () {
this._isMounted = true;
this.rebind();
};
componentWillUnmount () {
this._isMounted = false;
this.unbind();
};
onOpen () {
if (this.refHeader) {
this.refHeader.forceUpdate();
};
};
rebind () {
if (!this._isMounted) {
return;
};
this.unbind();
const win = $(window);
win.unbind('resize.popup.editorPage').on('resize.popup.editorPage', () => { this.resize(); });
};
unbind () {
$(window).unbind('resize.popup.editorPage');
};
resize () {
if (!this._isMounted) {
return;
};
raf(() => {
const win = $(window);
const obj = $('#popupEditorPage #innerWrap');
const width = Math.max(732, Math.min(960, win.width() - 128));
obj.css({ width: width, marginLeft: -width / 2, marginTop: 0 });
});
};
};
export default PopupEditorPage;

View file

@ -12,11 +12,9 @@ import PopupSearch from './search';
import PopupHelp from './help';
import PopupPrompt from './prompt';
import PopupPreview from './preview';
import PopupEditorPage from './editor/page';
import PopupFeedback from './feedback';
import PopupConfirm from './confirm';
import PopupShortcut from './shortcut';
import PopupStore from './store';
import PopupPage from './page';
interface Props extends I.Popup, RouteComponentProps<any> {};
@ -49,10 +47,8 @@ class Popup extends React.Component<Props, {}> {
prompt: PopupPrompt,
help: PopupHelp,
preview: PopupPreview,
editorPage: PopupEditorPage,
feedback: PopupFeedback,
shortcut: PopupShortcut,
store: PopupStore,
page: PopupPage,
};
@ -134,6 +130,9 @@ class Popup extends React.Component<Props, {}> {
};
close () {
Util.linkPreviewHide(true);
Util.tooltipHide(true);
menuStore.closeAll();
popupStore.close(this.props.id);
};

View file

@ -1,30 +1,34 @@
import * as React from 'react';
import { I } from 'ts/lib';
import { I, history as historyPopup } from 'ts/lib';
import { RouteComponentProps } from 'react-router';
import { Page } from 'ts/component';
import { commonStore } from 'ts/store';
import { observer } from 'mobx-react';
interface Props extends I.Popup, RouteComponentProps<any> {};
const $ = require('jquery');
const raf = require('raf');
@observer
class PopupPage extends React.Component<Props, {}> {
_isMounted: boolean = false;
ref: any = null;
constructor (props: any) {
super(props);
};
render () {
const { param } = this.props;
const { data } = param;
const { rootId, matchPopup } = data;
const { matchPopup } = data;
return (
<div id="wrap">
<Page {...this.props} rootId={rootId} isPopup={true} matchPopup={matchPopup} />
<Page
ref={(ref: any) => { this.ref = ref; }}
{...this.props}
rootId={matchPopup.params.id}
isPopup={true}
matchPopup={matchPopup}
/>
</div>
);
};
@ -32,11 +36,13 @@ class PopupPage extends React.Component<Props, {}> {
componentDidMount () {
this._isMounted = true;
this.rebind();
this.resize();
};
componentWillUnmount () {
this._isMounted = false;
this.unbind();
historyPopup.clear();
};
rebind () {
@ -47,11 +53,11 @@ class PopupPage extends React.Component<Props, {}> {
this.unbind();
const win = $(window);
win.unbind('resize.popup.page').on('resize.popup.page', () => { this.resize(); });
win.unbind('resize.popupPage').on('resize.popupPage', () => { this.resize(); });
};
unbind () {
$(window).unbind('resize.popup.page');
$(window).unbind('resize.popupPage');
};
resize () {
@ -59,14 +65,15 @@ class PopupPage extends React.Component<Props, {}> {
return;
};
const { getId } = this.props;
const { getId, position } = this.props;
raf(() => {
const win = $(window);
const obj = $(`#${getId()} #innerWrap`);
const width = Math.max(732, Math.min(960, win.width() - 128));
const width = Math.max(1000, Math.min(1152, win.width() - 128));
obj.css({ width: width, marginLeft: -width / 2, marginTop: 0 });
obj.css({ width: width });
position();
});
};

View file

@ -428,8 +428,14 @@ class PopupSearch extends React.Component<Props, State> {
load () {
const { config } = commonStore;
const { filter } = this.state;
let skipLayouts = [ I.ObjectLayout.File, I.ObjectLayout.Image ];
if (!config.allowDataview) {
skipLayouts = skipLayouts.concat(I.ObjectLayout.Human, I.ObjectLayout.Set, I.ObjectLayout.ObjectType, I.ObjectLayout.Relation);
};
const filters: any[] = [
{ operator: I.FilterOperator.And, relationKey: 'layout', condition: I.FilterCondition.NotIn, value: [ I.ObjectLayout.File, I.ObjectLayout.Image ] },
{ operator: I.FilterOperator.And, relationKey: 'layout', condition: I.FilterCondition.NotIn, value: skipLayouts },
];
const sorts = [
{ relationKey: 'name', type: I.SortType.Asc },

View file

@ -193,15 +193,17 @@ class PopupSettings extends React.Component<Props, State> {
readOnly={true}
/>
</div>
<div className="path">
<div className="side left">
<b>{translate('popupSettingsMobileQRSubTitle')}</b>
<Label text={translate('popupSettingsMobileQRText')} />
{!this.onConfirmPhrase ? (
<div className="path">
<div className="side left">
<b>{translate('popupSettingsMobileQRSubTitle')}</b>
<Label text={translate('popupSettingsMobileQRText')} />
</div>
<div className="side right isBlurred" onClick={this.elementUnblur}>
<QRCode value={entropy} />
</div>
</div>
<div className="side right isBlurred" onClick={this.elementUnblur}>
<QRCode value={entropy} />
</div>
</div>
) : ''}
{this.onConfirmPhrase ? (
<div className="buttons">
<Button text={translate('popupSettingsPhraseOk')} className="orange" onClick={() => { this.onConfirmPhrase(); }} />
@ -359,14 +361,17 @@ class PopupSettings extends React.Component<Props, State> {
const { param } = this.props;
const { data } = param;
const { page } = data || {};
const { phrase } = authStore;
if (page) {
this.onPage(page);
};
C.WalletConvert(authStore.phrase, '', (message: any) => {
this.setState({ entropy: message.entropy });
});
if (phrase) {
C.WalletConvert(phrase, '', (message: any) => {
this.setState({ entropy: message.entropy });
});
};
this.init();
};

View file

@ -67,7 +67,7 @@ class Icon extends React.Component<Props, {}> {
};
componentWillUnmount () {
Util.tooltipHide();
Util.tooltipHide(false);
};
onMouseEnter (e: any) {
@ -86,7 +86,7 @@ class Icon extends React.Component<Props, {}> {
onMouseLeave (e: any) {
const { onMouseLeave } = this.props;
Util.tooltipHide();
Util.tooltipHide(false);
if (onMouseLeave) {
onMouseLeave(e);
@ -96,7 +96,7 @@ class Icon extends React.Component<Props, {}> {
onMouseDown (e: any) {
const { onMouseDown } = this.props;
Util.tooltipHide();
Util.tooltipHide(true);
if (onMouseDown) {
onMouseDown(e);
@ -106,7 +106,7 @@ class Icon extends React.Component<Props, {}> {
onContextMenu (e: any) {
const { onContextMenu } = this.props;
Util.tooltipHide();
Util.tooltipHide(true);
if (onContextMenu) {
onContextMenu(e);

View file

@ -36,7 +36,7 @@ const Size = {
18: 18,
20: 18,
24: 20,
26: 20,
26: 22,
28: 22,
32: 28,
40: 24,
@ -305,7 +305,7 @@ class IconObject extends React.Component<Props, {}> {
onMouseLeave (e: any) {
const { onMouseLeave } = this.props;
Util.tooltipHide();
Util.tooltipHide(false);
if (onMouseLeave) {
onMouseLeave(e);

View file

@ -134,7 +134,7 @@ class LinkPreview extends React.Component<Props, {}> {
const { linkPreview } = commonStore;
Util.clipboardCopy({ text: linkPreview.url });
Util.linkPreviewHide(false);
Util.linkPreviewHide(true);
};
onEdit (e: any) {
@ -142,17 +142,19 @@ class LinkPreview extends React.Component<Props, {}> {
e.stopPropagation();
const { linkPreview } = commonStore;
const rect = Util.objectCopy($('#linkPreview').get(0).getBoundingClientRect());
let { marks, range, onChange } = linkPreview;
let mark = Mark.getInRange(marks, I.MarkType.Link, { from: range.from, to: range.to });
menuStore.open('blockLink', {
type: I.MenuType.Horizontal,
element: linkPreview.element,
rect: { ...rect, height: 0, y: rect.y + $(window).scrollTop() },
vertical: I.MenuDirection.Top,
horizontal: I.MenuDirection.Center,
offsetY: 44,
onOpen: () => {
Util.linkPreviewHide(false);
Util.linkPreviewHide(true);
},
data: {
value: (mark ? mark.param : ''),
@ -171,7 +173,7 @@ class LinkPreview extends React.Component<Props, {}> {
marks = Mark.toggle(marks, { type: I.MarkType.Link, param: '', range: { from: range.from, to: range.to } });
onChange(marks);
Util.linkPreviewHide(false);
Util.linkPreviewHide(true);
};
show () {

View file

@ -9,6 +9,7 @@ import { throttle } from 'lodash';
interface Props {
className?: string;
rootId: string;
isPopup: boolean;
};
const $ = require('jquery');
@ -34,6 +35,7 @@ class SelectionProvider extends React.Component<Props, {}> {
rects: Map<string, any> = new Map();
selecting: boolean = false;
top: number = 0;
containerOffset = null;
constructor (props: any) {
super(props);
@ -56,6 +58,7 @@ class SelectionProvider extends React.Component<Props, {}> {
return (
<div className={cn.join(' ')} onMouseDown={this.onMouseDown}>
<div id="selection-rect" />
{children}
</div>
);
@ -69,7 +72,7 @@ class SelectionProvider extends React.Component<Props, {}> {
win.on('keydown.selection', (e: any) => { this.onKeyDown(e); })
win.on('keyup.selection', (e: any) => { this.onKeyUp(e); });
win.on('scroll.selection', (e: any) => { this.onScroll(e); });
this.getScrollContainer().on('scroll.selection', (e: any) => { this.onScroll(e); });
};
componentWillUnmount () {
@ -139,19 +142,25 @@ class SelectionProvider extends React.Component<Props, {}> {
onKeyUp (e: any) {
};
getScrollContainer () {
return this.props.isPopup ? $('#popupPage #innerWrap') : $(window);
};
onScroll (e: any) {
if (!this.selecting || !this.moved) {
return;
};
const win = $(window);
const top = win.scrollTop();
const { isPopup } = this.props;
const top = this.getScrollContainer().scrollTop();
const d = top > this.top ? 1 : -1;
e.pageX = keyboard.coords.x;
e.pageY = keyboard.coords.y + Math.abs(top - this.top) * d;
let { x, y } = keyboard.mouse.page;
if (!isPopup) {
y += Math.abs(top - this.top) * d;
};
const rect = this.getRect(e);
const rect = this.getRect(x, y);
if ((rect.width < THRESHOLD) && (rect.height < THRESHOLD)) {
return;
};
@ -159,7 +168,7 @@ class SelectionProvider extends React.Component<Props, {}> {
this.checkNodes(e);
this.drawRect(rect);
scrollOnMove.onMouseMove(e);
scrollOnMove.onMouseMove(keyboard.mouse.client.x, keyboard.mouse.client.y);
this.moved = true;
};
@ -173,10 +182,11 @@ class SelectionProvider extends React.Component<Props, {}> {
return;
};
const { isPopup } = this.props;
const { focused } = focus;
const win = $(window);
const node = $(ReactDOM.findDOMNode(this));
const el = $('#selection-rect');
const el = node.find('#selection-rect');
el.css({ transform: 'translate3d(0px, 0px, 0px)', width: 0, height: 0 }).show();
@ -187,6 +197,13 @@ class SelectionProvider extends React.Component<Props, {}> {
this.lastIds = [];
this.focused = focused;
this.selecting = true;
this.top = this.getScrollContainer().scrollTop();
if (isPopup) {
this.containerOffset = $('#popupPage #innerWrap').offset();
this.x -= this.containerOffset.left;
this.y -= this.containerOffset.top - this.top;
};
keyboard.disablePreview(true);
@ -204,7 +221,7 @@ class SelectionProvider extends React.Component<Props, {}> {
};
};
scrollOnMove.onMouseDown(e);
scrollOnMove.onMouseDown(e, isPopup);
this.unbindMouse();
win.on('mousemove.selection', throttle((e: any) => { this.onMouseMove(e); }, THROTTLE));
@ -223,16 +240,16 @@ class SelectionProvider extends React.Component<Props, {}> {
return;
};
const rect = this.getRect(e);
const rect = this.getRect(e.pageX, e.pageY);
if ((rect.width < THRESHOLD) && (rect.height < THRESHOLD)) {
return;
};
this.top = $(window).scrollTop();
this.top = this.getScrollContainer().scrollTop();
this.checkNodes(e);
this.drawRect(rect);
scrollOnMove.onMouseMove(e);
scrollOnMove.onMouseMove(e.clientX, e.clientY);
this.moved = true;
};
@ -299,20 +316,32 @@ class SelectionProvider extends React.Component<Props, {}> {
return;
};
$('#selection-rect').css({
const node = $(ReactDOM.findDOMNode(this));
const el = node.find('#selection-rect');
el.css({
transform: `translate3d(${rect.x + 10}px, ${rect.y + 10}px, 0px)`,
width: rect.width - 10,
height: rect.height - 10,
});
};
getRect (e: any) {
return {
x: Math.min(this.x, e.pageX),
y: Math.min(this.y, e.pageY),
width: Math.abs(e.pageX - this.x) - 10,
height: Math.abs(e.pageY - this.y) - 10
getRect (x: number, y: number) {
const { isPopup } = this.props;
if (isPopup) {
const top = this.getScrollContainer().scrollTop();
x -= this.containerOffset.left;
y -= this.containerOffset.top - top;
};
const rect = {
x: Math.min(this.x, x),
y: Math.min(this.y, y),
width: Math.abs(x - this.x) - 10,
height: Math.abs(y - this.y) - 10
};
return rect;
};
cacheRect (obj: any) {
@ -326,16 +355,21 @@ class SelectionProvider extends React.Component<Props, {}> {
return cached;
};
const { isPopup } = this.props;
const offset = obj.offset();
const rect = obj.get(0).getBoundingClientRect() as DOMRect;
cached = {
x: offset.left,
y: offset.top,
width: rect.width,
height: rect.height,
let x = offset.left;
let y = offset.top;
if (isPopup) {
const top = this.getScrollContainer().scrollTop();
x -= this.containerOffset.left;
y -= this.containerOffset.top - top;
};
cached = { x: x, y: y, width: rect.width, height: rect.height };
this.rects.set(id, cached);
return cached;
};
@ -348,7 +382,6 @@ class SelectionProvider extends React.Component<Props, {}> {
};
const cached = this.cacheRect(item);
if (!cached || !Util.rectsCollide(rect, cached)) {
return;
};
@ -384,13 +417,15 @@ class SelectionProvider extends React.Component<Props, {}> {
};
const { focused, range } = focus;
const rect = this.getRect(e);
const rect = this.getRect(e.pageX, e.pageY);
if (!e.shiftKey && !e.altKey && !(e.ctrlKey || e.metaKey)) {
this.clear();
};
this.nodes.each((i: number, item: any) => { this.checkEachNode(e, rect, $(item)); });
this.nodes.each((i: number, item: any) => {
this.checkEachNode(e, rect, $(item));
});
const selected = $('.selectable.isSelected');
const length = selected.length;
@ -441,8 +476,9 @@ class SelectionProvider extends React.Component<Props, {}> {
};
const node = $(ReactDOM.findDOMNode(this));
$('#selection-rect').hide();
const el = node.find('#selection-rect');
el.hide();
this.unbindMouse();
};
@ -467,7 +503,8 @@ class SelectionProvider extends React.Component<Props, {}> {
};
unbindKeyboard () {
$(window).unbind('keydown.selection keyup.selection scroll.selection');
$(window).unbind('keydown.selection keyup.selection');
this.getScrollContainer().unbind('scroll.selection');
};
preventSelect (v: boolean) {

View file

@ -56,7 +56,7 @@ class Sync extends React.Component<Props, {}> {
};
onMouseLeave (e: any) {
Util.tooltipHide();
Util.tooltipHide(false);
};
};

View file

@ -9,8 +9,10 @@ export enum ObjectLayout {
Relation = 5,
File = 6,
Dashboard = 7,
Image = 9,
Image = 8,
Database = 20,
Store = 100,
};
export enum RelationType {

View file

@ -232,7 +232,7 @@ const BlockCreate = (block: any, contextId: string, targetId: string, position:
dispatcher.request('blockCreate', request, callBack);
};
const BlockCreatePage = (contextId: string, targetId: string, details: any, position: I.BlockPosition, callBack?: (message: any) => void) => {
const BlockCreatePage = (contextId: string, targetId: string, details: any, position: I.BlockPosition, templateId: string, callBack?: (message: any) => void) => {
details = details || {};
const request = new Rpc.Block.CreatePage.Request();
@ -241,6 +241,7 @@ const BlockCreatePage = (contextId: string, targetId: string, details: any, posi
request.setTargetid(targetId);
request.setPosition(position);
request.setDetails(Encode.encodeStruct(details));
request.setTemplateid(templateId);
dispatcher.request('blockCreatePage', request, callBack);
};
@ -946,6 +947,14 @@ const ObjectRelationListAvailable = (contextId: string, callBack?: (message: any
dispatcher.request('objectRelationListAvailable', request, callBack);
};
const MakeTemplate = (contextId: string, callBack?: (message: any) => void) => {
const request = new Rpc.MakeTemplate.Request();
request.setContextid(contextId);
dispatcher.request('makeTemplate', request, callBack);
};
export {
VersionGet,
DebugSync,
@ -1063,4 +1072,6 @@ export {
ObjectRelationDelete,
ObjectRelationListAvailable,
MakeTemplate,
};

View file

@ -1,5 +1,5 @@
import { I, C, M, keyboard, crumbs, translate, Util } from 'ts/lib';
import { commonStore, blockStore, dbStore, popupStore } from 'ts/store';
import { I, C, M, keyboard, crumbs, translate, Util, history as historyPopup } from 'ts/lib';
import { commonStore, blockStore, dbStore, popupStore, menuStore } from 'ts/store';
const Constant = require('json/constant.json');
const Errors = require('json/error.json');
@ -254,7 +254,10 @@ class DataUtil {
};
objectOpenEvent (e: any, object: any) {
if (e && (e.shiftKey || e.ctrlKey || e.metaKey)) {
e.preventDefault();
e.stopPropagation();
if (e.shiftKey || e.ctrlKey || e.metaKey || popupStore.isOpen('page')) {
this.objectOpenPopup(object);
} else {
this.objectOpen(object);
@ -280,24 +283,39 @@ class DataUtil {
};
objectOpenPopup (object: any) {
let param: any = { data: { rootId: object.id } };
let popupId = '';
const popupId = 'page';
const param: any = {
data: {
matchPopup: {
params: {
page: 'main',
id: object.id,
},
},
},
};
switch (object.layout) {
default:
popupId = 'editorPage';
param.data.matchPopup.params.action = 'edit';
break;
case I.ObjectLayout.ObjectType:
popupId = 'page';
param.data.matchPopup = { params: { page: 'main', action: 'type', id: object.id } };
param.data.matchPopup.params.action = 'type';
break;
case I.ObjectLayout.Relation:
popupId = 'page';
param.data.matchPopup = { params: { page: 'main', action: 'relation', id: object.id } };
param.data.matchPopup.params.action = 'relation';
break;
case I.ObjectLayout.Store:
param.data.matchPopup.params.action = 'store';
break;
};
historyPopup.pushMatch(param.data.matchPopup);
menuStore.closeAll();
if (popupStore.isOpen(popupId)) {
popupStore.update(popupId, param);
} else {
@ -305,16 +323,12 @@ class DataUtil {
};
};
pageCreate (e: any, rootId: string, targetId: string, details: any, position: I.BlockPosition, callBack?: (message: any) => void) {
pageCreate (rootId: string, targetId: string, details: any, position: I.BlockPosition, templateId: string, callBack?: (message: any) => void) {
details = details || {};
if (e && e.persist) {
e.persist();
};
commonStore.progressSet({ status: 'Creating page...', current: 0, total: 1 });
C.BlockCreatePage(rootId, targetId, details, position, (message: any) => {
C.BlockCreatePage(rootId, targetId, details, position, templateId, (message: any) => {
commonStore.progressSet({ status: 'Creating page...', current: 1, total: 1 });
if (message.error.code) {
@ -458,8 +472,7 @@ class DataUtil {
menuGetBlockObject () {
const { config } = commonStore;
const objectTypes = dbStore.objectTypes.filter((it: I.ObjectType) => { return !it.isHidden; });
let ret: any[] = [
{ type: I.BlockType.File, id: I.FileType.File, icon: 'file', lang: 'File' },
{ type: I.BlockType.File, id: I.FileType.Image, icon: 'image', lang: 'Image' },
@ -470,6 +483,11 @@ class DataUtil {
let i = 0;
if (config.allowDataview) {
let objectTypes = Util.objectCopy(dbStore.objectTypes);
if (!config.debug.ho) {
objectTypes = objectTypes.filter((it: I.ObjectType) => { return !it.isHidden; })
};
for (let type of objectTypes) {
ret.push({
type: I.BlockType.Page,
@ -479,6 +497,7 @@ class DataUtil {
name: type.name || Constant.default.name,
description: type.description,
isObject: true,
isHidden: type.isHidden,
});
};
} else {

View file

@ -68,7 +68,7 @@ class Focus {
return this;
};
scroll (container: any, id?: string) {
scroll (isPopup: boolean, id?: string) {
id = String(id || this.focused || '');
if (!id) {
return;
@ -79,17 +79,24 @@ class Focus {
return;
};
const wh = container.height();
const y = node.offset().top;
const offset = Constant.size.lastBlock + Constant.size.header;
const container = isPopup ? $('#popupPage #innerWrap') : $(window);
const h = container.height();
const o = Constant.size.lastBlock + Constant.size.header;
const st = container.scrollTop();
if ((y >= st) && (y <= st + wh - offset)) {
let y = 0;
if (isPopup) {
y = node.offset().top - container.offset().top + st;
} else {
y = node.offset().top;
};
if ((y >= st) && (y <= st + h - o)) {
return;
};
if (y >= wh - offset) {
container.scrollTop(y - wh + offset);
if (y >= h - o) {
container.scrollTop(y - h + o);
};
};

66
src/ts/lib/history.tsx Normal file
View file

@ -0,0 +1,66 @@
class History {
list: string[] = [];
index: number = 0;
clear () {
this.list = []
this.index = 0;
};
push (route: string) {
const last = this.list[this.list.length - 1];
if (last && (last == route)) {
return;
};
if (this.index < this.list.length - 1) {
this.list = this.list.slice(0, this.index + 1);
};
this.list.push(route);
this.index = this.list.length - 1;
};
pushMatch (match: any) {
this.push(this.build(match));
};
build (match: any): string {
return [ match.params.page, match.params.action, match.params.id ].join('/');
};
getParams (route: string) {
const [ page, action, id ] = route.split('/');
return { page, action, id };
};
checkBack () {
return this.index - 1 >= 0;
};
checkForward () {
return this.index + 1 <= this.list.length - 1;
};
go (route: string, callBack: (match: any) => void) {
callBack({ route, params: this.getParams(route) });
};
goBack (callBack: (match: any) => void) {
if (this.checkBack()) {
this.index--;
this.go(this.list[this.index], callBack);
};
};
goForward (callBack: (match: any) => void) {
if (this.checkForward()) {
this.index++;
this.go(this.list[this.index], callBack);
};
};
};
export let history: History = new History();

View file

@ -10,6 +10,7 @@ import { Encode, Decode } from './struct';
import { scrollOnMove } from './scrollOnMove';
import { analytics } from './analytics';
import { crumbs } from './crumbs';
import { history } from './history';
import * as I from 'ts/interface';
import * as M from 'ts/model';
import * as C from './command';
@ -50,6 +51,7 @@ export {
translate,
analytics,
crumbs,
history,
scrollOnMove,
Encode,
Decode,

View file

@ -1,4 +1,4 @@
import { I, Util, DataUtil, SmileUtil, Storage, focus } from 'ts/lib';
import { I, Util, DataUtil, SmileUtil, Storage, focus, history as historyPopup } from 'ts/lib';
import { authStore, blockStore, menuStore, popupStore } from 'ts/store';
const $ = require('jquery');
@ -7,7 +7,10 @@ const KeyCode = require('json/key.json');
class Keyboard {
history: any = null;
coords: any = { x: 0, y: 0 };
mouse: any = {
page: { x: 0, y: 0 },
client: { x: 0, y: 0 },
};
timeoutPin: number = 0;
pressed: string[] = [];
match: any = {};
@ -138,7 +141,7 @@ class Keyboard {
};
};
DataUtil.pageCreate(e, rootId, targetId, {}, position, (message: any) => {
DataUtil.pageCreate(rootId, targetId, {}, position, '', (message: any) => {
if (isMainIndex) {
DataUtil.objectOpen({ id: message.targetId });
} else {
@ -158,23 +161,38 @@ class Keyboard {
back () {
const { account } = authStore;
const isPopup = popupStore.isOpen('page');
if (isPopup) {
historyPopup.goBack((match: any) => {
popupStore.updateData('page', { matchPopup: match });
});
} else {
const prev = this.history.entries[this.history.index - 1];
if (prev) {
let route = Util.getRoute(prev.pathname);
if ((route.page == 'auth') && account) {
return;
};
if ((route.page == 'main') && !account) {
return;
};
};
const prev = this.history.entries[this.history.index - 1];
if (prev) {
let route = Util.getRoute(prev.pathname);
if ((route.page == 'auth') && account) {
return;
};
if ((route.page == 'main') && !account) {
return;
};
this.history.goBack();
};
this.history.goBack();
};
forward () {
this.history.goForward();
const isPopup = popupStore.isOpen('page');
if (isPopup) {
historyPopup.goForward((match: any) => {
popupStore.updateData('page', { matchPopup: match });
});
} else {
this.history.goForward();
};
};
ctrlByPlatform (e: any) {
@ -253,8 +271,11 @@ class Keyboard {
this.isPreviewDisabled = v;
};
setCoords (x: number, y: number) {
this.coords = { x: x, y: y };
setCoords (e: any) {
this.mouse = {
page: { x: e.pageX, y: e.pageY },
client: { x: e.clientX, y: e.clientY },
};
};
isArrow (k: string): boolean {

View file

@ -440,6 +440,12 @@ const ObjectRelationOptionAdd = (response: any) => {
};
};
const MakeTemplate = (response: any) => {
return {
id: response.getId(),
};
};
export {
VersionGet,
DebugSync,
@ -549,4 +555,6 @@ export {
ObjectRelationListAvailable,
ObjectRelationOptionAdd,
MakeTemplate,
};

View file

@ -1,4 +1,5 @@
const raf = require('raf');
const $ = require('jquery');
const BORDER = 100;
const THROTTLE = 30;
@ -10,37 +11,52 @@ class ScrollOnMove {
viewportHeight: number = 0;
documentWidth: number = 0;
documentHeight: number = 0;
onMouseDown (e: any) {
this.viewportWidth = document.documentElement.clientWidth;
this.viewportHeight = document.documentElement.clientHeight;
isPopup: boolean = false;
this.documentWidth = Math.max(
document.body.scrollWidth,
document.body.offsetWidth,
document.body.clientWidth,
document.documentElement.scrollWidth,
document.documentElement.offsetWidth,
document.documentElement.clientWidth
);
this.documentHeight = Math.max(
document.body.scrollHeight,
document.body.offsetHeight,
document.body.clientHeight,
document.documentElement.scrollHeight,
document.documentElement.offsetHeight,
document.documentElement.clientHeight
);
onMouseDown (e: any, isPopup: boolean) {
this.isPopup = isPopup;
if (isPopup) {
const container = $('#popupPage #innerWrap');
const content = container.find('.content');
this.viewportWidth = container.width();
this.viewportHeight = container.height();
this.documentWidth = content.width();
this.documentHeight = content.height();
} else {
this.viewportWidth = document.documentElement.clientWidth;
this.viewportHeight = document.documentElement.clientHeight;
this.documentWidth = Math.max(
document.body.scrollWidth,
document.body.offsetWidth,
document.body.clientWidth,
document.documentElement.scrollWidth,
document.documentElement.offsetWidth,
document.documentElement.clientWidth
);
this.documentHeight = Math.max(
document.body.scrollHeight,
document.body.offsetHeight,
document.body.clientHeight,
document.documentElement.scrollHeight,
document.documentElement.offsetHeight,
document.documentElement.clientHeight
);
};
};
getContainer () {
return this.isPopup ? $('#popupPage #innerWrap').get(0) : window;
};
checkForWindowScroll (param: any) {
window.clearTimeout(this.timeout);
this.clear();
if (this.adjustWindowScroll(param)) {
this.timeout = window.setTimeout(() => {
this.checkForWindowScroll(param);
}, THROTTLE);
this.timeout = window.setTimeout(() => { this.checkForWindowScroll(param); }, THROTTLE);
};
};
@ -53,8 +69,21 @@ class ScrollOnMove {
let maxScrollX = this.documentWidth - this.viewportWidth;
let maxScrollY = this.documentHeight - this.viewportHeight;
let currentScrollX = window.pageXOffset;
let currentScrollY = window.pageYOffset;
let currentScrollX = 0;
let currentScrollY = 0;
let container;
if (this.isPopup) {
container = $('#popupPage #innerWrap');
currentScrollX = container.scrollLeft();
currentScrollY = container.scrollTop();
container = container.get(0);
} else {
container = window;
currentScrollX = window.pageXOffset;
currentScrollY = window.pageYOffset;
};
let canScrollUp = (currentScrollY > 0);
let canScrollDown = (currentScrollY < maxScrollY);
let canScrollLeft = (currentScrollX > 0 );
@ -93,7 +122,7 @@ class ScrollOnMove {
(nextScrollY !== currentScrollY)
) {
raf(() => {
window.scrollTo(nextScrollX, nextScrollY);
container.scrollTo(nextScrollX, nextScrollY);
});
return true;
} else {
@ -101,28 +130,25 @@ class ScrollOnMove {
};
};
onMouseMove (e: any) {
let viewportX = e.clientX;
let viewportY = e.clientY;
onMouseMove (x: number, y: number) {
let edgeTop = BORDER;
let edgeLeft = BORDER;
let edgeBottom = this.viewportHeight - BORDER;
let edgeRight = this.viewportWidth - BORDER;
let isInLeftEdge = (viewportX < edgeLeft);
let isInRightEdge = (viewportX > edgeRight);
let isInTopEdge = (viewportY < edgeTop );
let isInBottomEdge = (viewportY > edgeBottom);
let isInLeftEdge = x < edgeLeft;
let isInRightEdge = x > edgeRight;
let isInTopEdge = y < edgeTop;
let isInBottomEdge = y > edgeBottom;
if (!(isInLeftEdge || isInRightEdge || isInTopEdge || isInBottomEdge)) {
window.clearTimeout(this.timeout);
this.clear();
return;
};
this.checkForWindowScroll({
viewportX: viewportX,
viewportY: viewportY,
viewportX: x,
viewportY: y,
isInLeftEdge: isInLeftEdge,
isInRightEdge: isInRightEdge,
isInTopEdge: isInTopEdge,
@ -135,6 +161,10 @@ class ScrollOnMove {
};
onMouseUp (e: any) {
this.clear();
};
clear () {
window.clearTimeout(this.timeout);
};

View file

@ -564,12 +564,12 @@ class Util {
}, 250);
};
tooltipHide () {
tooltipHide (force: boolean) {
let obj = $('#tooltip');
obj.css({ opacity: 0 });
window.clearTimeout(this.timeoutTooltip);
this.timeoutTooltip = window.setTimeout(() => { obj.hide(); }, 200);
this.timeoutTooltip = window.setTimeout(() => { obj.hide(); }, force ? 0 : Constant.delay.tooltip);
};
linkPreviewShow (url: string, node: any, param: any) {
@ -760,7 +760,7 @@ class Util {
return 'body';
case 'popup':
return '#popupEditorPage .selection';
return '#popupPage .selection';
case 'menuBlockRelationList':
case 'menuBlockRelationView':
@ -775,7 +775,7 @@ class Util {
return '.pageMainEdit';
case 'popup':
return '#popupEditorPage';
return '#popupPage';
case 'menuBlockRelationList':
case 'menuBlockRelationView':

View file

@ -36,6 +36,15 @@ class PopupStore {
set(item, { param: param });
};
@action
updateData (id: string, data: any) {
const item = this.get(id);
if (item) {
item.param.data = Object.assign(item.param.data, data);
this.update(id, item.param);
};
};
isOpen (id?: string): boolean {
if (!id) {