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

Merge branch 'main' of github.com:anyproto/anytype-ts into feature/embed

This commit is contained in:
Andrew Simachev 2023-12-05 16:47:16 +01:00
commit 0c44b3602e
No known key found for this signature in database
GPG key ID: 49A163D0D14E6FD8
68 changed files with 595 additions and 423 deletions

3
dist/polyfill.js vendored
View file

@ -1,6 +1,7 @@
const RendererEvents = {};
window.Config = {
window.Anytype = window.Anytype || {};
window.Anytype.Config = {
debug: {
mw: true,
},

View file

@ -131,7 +131,7 @@ class MenuManager {
{ label: Util.translate('electronMenuZoomOut'), accelerator: 'CmdOrCtrl+-', click: () => Api.setZoom(this.win, this.win.webContents.getZoomLevel() - 1) },
{ label: Util.translate('electronMenuZoomDefault'), accelerator: 'CmdOrCtrl+0', click: () => Api.setZoom(this.win, 0) },
{
label: Util.translate('electronMenuFullscreen'), accelerator: 'CmdOrCtrl+Alt+F', type: 'checkbox', checked: this.win.isFullScreen(),
label: Util.translate('electronMenuFullscreen'), accelerator: (is.macos ? 'Cmd+Ctrl+F' : 'Ctrl+Alt+F'), type: 'checkbox', checked: this.win.isFullScreen(),
click: () => this.win.setFullScreen(!this.win.isFullScreen())
},
{ label: Util.translate('electronMenuReload'), accelerator: 'CmdOrCtrl+R', click: () => this.win.reload() }

View file

@ -1 +1 @@
0.29.16
0.30.0-rc1

4
package-lock.json generated
View file

@ -1,12 +1,12 @@
{
"name": "anytype",
"version": "0.36.2-alpha",
"version": "0.36.5-alpha",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "anytype",
"version": "0.36.2-alpha",
"version": "0.36.5-alpha",
"hasInstallScript": true,
"license": "SEE LICENSE IN LICENSE.md",
"dependencies": {

View file

@ -1,6 +1,6 @@
{
"name": "anytype",
"version": "0.36.2-alpha",
"version": "0.36.5-alpha",
"description": "Anytype",
"main": "electron.js",
"scripts": {
@ -19,7 +19,7 @@
"dist:mac": "npm run build:deps && webpack --progress --mode=production --node-env=production && DATE=`date '+%Y-%m-%d_%H_%M'` GIT_COMMIT=`git rev-parse --short HEAD` electron-builder --macos --arm64 --x64",
"dist:macarm": "npm run build:deps && webpack --mode=production --node-env=production && DATE=`date '+%Y-%m-%d_%H_%M'` GIT_COMMIT=`git rev-parse --short HEAD` electron-builder --macos --arm64",
"dist:macamd": "npm run build:deps && webpack --mode=production --node-env=production && DATE=`date '+%Y-%m-%d_%H_%M'` GIT_COMMIT=`git rev-parse --short HEAD` electron-builder --macos --x64",
"dist:win": "npm run build:deps && webpack --mode=production --node-env=production && electron-builder --windows",
"dist:win": "webpack --mode=production --node-env=production && electron-builder --windows",
"dist:linux": "npm run build:deps && webpack --mode=production --node-env=production && DATE=`date '+%Y-%m-%d_%H_%M'` GIT_COMMIT=`git rev-parse --short HEAD` electron-builder --linux --arm64 --x64",
"dist:linuxamd": "npm run build:deps && webpack --mode=production --node-env=production && DATE=`date '+%Y-%m-%d_%H_%M'` GIT_COMMIT=`git rev-parse --short HEAD` electron-builder --linux --x64",
"dist:linuxarm": "npm run build:deps && webpack --mode=production --node-env=production && DATE=`date '+%Y-%m-%d_%H_%M'` GIT_COMMIT=`git rev-parse --short HEAD` electron-builder --linux --arm64",

View file

@ -19,7 +19,8 @@
"limit": {
"menuRecords": 100,
"widgets": 20,
"space": 10
"space": 10,
"notification": 20
},
"default": {

View file

@ -1459,15 +1459,6 @@
"selectTemplateBanner": "This type has templates",
"selectTemplateBannerWithNumber": "This type has %s %s",
"dispatcherExportSuccessTitle": "The export process is complete!",
"dispatcherExportSuccessText": "You can find the exported objects in the folder you selected.",
"dispatcherImportErrorTitle": "The import wasn't completed",
"dispatcherImportErrorText": "Sorry, but something went wrong during the import process. Please try again or let us know if it doesn't work.",
"dispatcherExportErrorTitle": "The export wasn't completed",
"dispatcherExportErrorText": "Sorry, but something went wrong during the export process. Please try again or let us know if it doesn't work.",
"dispatcherImportConfirm": "Ok! I got it!",
"dispatcherImportTryAgain": "Try again",
"onboardingMainGraph": "Onboarding",
"onboardingMainGraph11": "<b>Space is essentially a graph</b>, and Anytype aims to provide a natural way of thinking where everything is represented as objects with specific relationships, just like in the real world.",
@ -1624,6 +1615,16 @@
"notification0ErrorTitle": "Something went wrong",
"notification0ErrorText": "Oops! &quot;%s&quot; wasn't installed. Please check your internet connection and try again or post a report on forum.",
"notification1Text": "<span id='object' class='element'></span> requested to join <span id='subject' class='element'></span> with read-only access rights."
"notification1Text": "<span id='object' class='element'></span> requested to join <span id='subject' class='element'></span> with read-only access rights.",
"notificationImportSuccessTitle": "Import complete!",
"notificationImportSuccessText": "You can find the imported objects in the selected space.",
"notificationImportErrorTitle": "Import failed",
"notificationImportErrorText": "Sorry, but something went wrong during the import. Please try again, and let us know if it doesn't work.",
"notificationExportSuccessTitle": "Export complete!",
"notificationExportSuccessText": "You can find the exported objects in the folder you selected.",
"notificationExportErrorTitle": "Export failed",
"notificationExportErrorText": "Sorry, but something went wrong during the export. Please try again, and let us know if it doesn't work."
}

View file

@ -22,13 +22,16 @@
}
.button.red { color: $colorRed; border: solid 1px $colorShapePrimary; }
.button.red:not(.disabled):hover, .button.red:not(.disabled).hover { background: #fee7e0; border-color: #fcd1c3; }
.button.red:not(.disabled):hover,
.button.red:not(.disabled).hover { background: #fee7e0; border-color: #fcd1c3; }
.button.dark { background: rgba(0,0,0,0.3); color: $colorBgPrimary; }
.button.dark:not(.disabled):hover, .button.dark:not(.disabled).hover { background: rgba(0,0,0,0.4); }
.button.dark:not(.disabled):hover,
.button.dark:not(.disabled).hover { background: rgba(0,0,0,0.4); }
.button.blank { background: none; border: solid 1px $colorShapePrimary; font-weight: 400; }
.button.blank:not(.disabled):hover, .button.blank:not(.disabled).hover { background: $colorShapeHighlightMedium; }
.button.blank:not(.disabled):hover,
.button.blank:not(.disabled).hover { background: $colorShapeHighlightMedium; }
.button.c36 { @include text-common; height: 36px; border-radius: 6px; padding: 0px 12px; }
.button.c28 { @include text-common; height: 28px; border-radius: 6px; padding: 0px 10px; }
@ -45,4 +48,5 @@ input.button { line-height: 1; }
height: auto; padding: 0px; color: $colorControlActive; font-weight: bold; line-height: 1.43;
letter-spacing: 0.1px;
}
.button.simple:hover, .button.simple.hover { color: $colorTextPrimary; }
.button.simple:hover,
.button.simple.hover { color: $colorTextPrimary; }

View file

@ -25,9 +25,9 @@
.section { padding: 11px 14px !important; border: 0px; }
.section > .name { padding: 0px; margin: 0px; }
.row { padding: 0px 12px; }
.row { padding: 0px 12px; display: flex; flex-direction: row; align-items: center; flex-wrap: nowrap; }
.item { width: 40px; height: 40px; position: relative; border-radius: 6px; display: inline-block; vertical-align: top; padding: 0px; }
.item { width: 40px; height: 40px; position: relative; border-radius: 6px; padding: 0px; }
.item::before { display: none; }
.item.active { background: $colorShapeHighlightMedium; }

View file

@ -3,27 +3,27 @@
.popups {
.popup.popupObjectManager {
.innerWrap { width: 548px; height: 472px; padding: 32px 32px 40px 32px; }
.content { height: 100%; display: flex; flex-direction: column; gap: 24px 0; }
.content { height: 100%; display: flex; flex-direction: column; }
.title { @include text-header3; flex-shrink: 0; }
.title { @include text-header3; flex-shrink: 0; margin: 0px 0px 24px 0px; }
.ReactVirtualized__List { padding: 8px 0px; }
.objectManagerWrapper {
.controls { margin-bottom: 8px; }
.items {
.row { grid-template-columns: repeat(2, minmax(0, 1fr)); grid-gap: 32px; }
.objectManagerWrapper { flex-grow: 1; }
.item { gap: 0px 12px; }
.item {
.iconObject { flex-shrink: 0; flex-basis: 48px; border-radius: 10px; background-color: $colorShapeTertiary; }
.objectClickArea { width: calc(100% - 30px); }
.items {
.row { grid-template-columns: repeat(2, minmax(0, 1fr)); grid-gap: 32px; }
.name { @include text-overflow-nw; width: 100%; }
.descr { @include text-overflow-nw; @include text-small; width: 100%; color: $colorTextSecondary; }
}
}
.emptySearch { height: 238px; }
}
.item { gap: 0px 12px; }
.item {
.iconObject { flex-shrink: 0; flex-basis: 48px; border-radius: 10px; background-color: $colorShapeTertiary; }
.objectClickArea { width: calc(100% - 30px); }
.button { flex-shrink: 0; width: 100%; height: 36px; }
.name { @include text-overflow-nw; width: 100%; }
.descr { @include text-overflow-nw; @include text-small; width: 100%; color: $colorTextSecondary; }
}
}
.emptySearch { height: 238px; }
.button { flex-shrink: 0; width: 100%; }
}
}

View file

@ -106,18 +106,22 @@ html.themeDark {
/* Button */
.button.black { background: $colorControlAccent; color: $colorTextInversion; }
.button.black:hover { background: $colorControlActive }
.button.black:hover,
.button.black.hover { background: $colorControlActive }
.button.black {
.arrow { background-image: url('~img/arrow/button/black.svg'); }
}
.button.blank { color: $colorTextPrimary; border-color: $colorShapePrimary; }
.button.blank:not(.disabled):hover { border-color: $colorShapePrimary; background: $colorShapeHighlightMedium; }
.button.blank:not(.disabled):hover,
.button.blank:not(.disabled).hover { border-color: $colorShapePrimary; background: $colorShapeHighlightMedium; }
.button.red,
.button.red.blank { border-color: $colorShapePrimary; background: none; color: $colorRed; }
.button.red:hover,
.button.red.blank:hover { border-color: #581f0c; background: #311107; }
.button.red.hover,
.button.red.blank:hover,
.button.red.blank.hover { border-color: #581f0c; background: #311107; }
.filter {
.line { background: $colorShapeSecondary; }

View file

@ -54,15 +54,12 @@ interface State {
declare global {
interface Window {
Electron: any;
Store: any;
$: any;
Lib: any;
Graph: any;
Electron: any;
Anytype: any;
isWebVersion: boolean;
Config: any;
Renderer: any;
}
};
@ -85,31 +82,34 @@ const rootStore = {
notificationStore,
};
window.$ = $;
if (!window.Electron.isPackaged) {
window.Store = rootStore;
window.$ = $;
window.Lib = {
I,
C,
UtilCommon,
UtilData,
UtilFile,
UtilObject,
UtilMenu,
UtilRouter,
UtilSmile,
analytics,
dispatcher,
keyboard,
Renderer,
Preview,
Storage,
Animation,
Onboarding,
Survey,
Docs,
Encode,
Decode,
window.Anytype = {
Store: rootStore,
Lib: {
I,
C,
UtilCommon,
UtilData,
UtilFile,
UtilObject,
UtilMenu,
UtilRouter,
UtilSmile,
analytics,
dispatcher,
keyboard,
Renderer,
Preview,
Storage,
Animation,
Onboarding,
Survey,
Docs,
Encode,
Decode,
},
};
};

View file

@ -679,7 +679,7 @@ const BlockDataview = observer(class BlockDataview extends React.Component<Props
});
};
Storage.setLastUsedTypes(typeId);
Storage.addLastUsedType(typeId);
});
};

View file

@ -161,9 +161,15 @@ const ViewCalendar = observer(class ViewCalendar extends React.Component<I.ViewC
return;
};
const { m, y } = this.getDateParam(this.value);
const start = UtilDate.timestamp(y, m, 1, 0, 0, 0);
const end = UtilDate.timestamp(y, m, Constant.monthDays[m] + (y % 4 === 0 ? 1 : 0), 23, 59, 59);
const data = this.getData();
if (!data.length) {
return;
};
const first = data[0];
const last = data[data.length - 1];
const start = UtilDate.timestamp(first.y, first.m, first.d, 0, 0, 0);
const end = UtilDate.timestamp(last.y, last.m, last.d, 23, 59, 59);
const filters: I.Filter[] = [
{ operator: I.FilterOperator.And, relationKey: 'layout', condition: I.FilterCondition.NotIn, value: UtilObject.excludeFromSet() },
].concat(view.filters);

View file

@ -129,7 +129,6 @@ const Item = observer(class Item extends React.Component<Props> {
noFlipX: true,
data: {
...this.props,
items: this.getItems(),
}
});
});

View file

@ -53,8 +53,6 @@ const ViewGraph = observer(class ViewGraph extends React.Component<I.ViewCompone
this.rebind();
this.resize();
this.load();
window.Graph = this;
};
componentDidUpdate () {

View file

@ -137,7 +137,6 @@ const BlockRelation = observer(class BlockRelation extends React.Component<I.Blo
filter: '',
menuIdEdit: 'blockRelationEdit',
ref: 'block',
skipKeys: Relation.systemKeysWithoutUser(),
addCommand: (rootId: string, blockId: string, relation: any, onChange: (message: any) => void) => {
C.ObjectRelationAdd(rootId, [ relation.relationKey ], (message: any) => {
if (message.error.code) {

View file

@ -45,6 +45,7 @@ const BlockTable = observer(class BlockTable extends React.Component<I.BlockComp
this.onCellEnter = this.onCellEnter.bind(this);
this.onCellLeave = this.onCellLeave.bind(this);
this.onCellKeyDown = this.onCellKeyDown.bind(this);
this.onCellKeyUp = this.onCellKeyUp.bind(this);
this.onOptions = this.onOptions.bind(this);
this.onResizeStart = this.onResizeStart.bind(this);
this.onDragStartRow = this.onDragStartRow.bind(this);
@ -103,6 +104,7 @@ const BlockTable = observer(class BlockTable extends React.Component<I.BlockComp
onCellEnter={this.onCellEnter}
onCellLeave={this.onCellLeave}
onCellKeyDown={this.onCellKeyDown}
onCellKeyUp={this.onCellKeyUp}
onResizeStart={this.onResizeStart}
onDragStartRow={this.onDragStartRow}
onDragStartColumn={this.onDragStartColumn}
@ -779,9 +781,14 @@ const BlockTable = observer(class BlockTable extends React.Component<I.BlockComp
if (!ret) {
onKeyDown(e, text, marks, range, props);
this.framesUpdate();
};
};
onCellKeyUp (e: any, rowId: string, columnId: string, id: string, text: string, marks: I.Mark[], range: I.TextRange, props: any) {
this.framesUpdate();
};
setEditing (id: string) {
if (!this._isMounted) {
return;
@ -1226,10 +1233,8 @@ const BlockTable = observer(class BlockTable extends React.Component<I.BlockComp
{
id: 'rowHeader', icon: 'table-header-row', name: translate('blockTableOptionsRowHeaderRow'), withSwitch: true, switchValue: isHeader,
onSwitch: (e: any, v: boolean, callBack?: () => void) => {
C.BlockTableRowSetHeader(rootId, id, v, (message: any) => {
this.frames.forEach((it: any) => {
this.frameAdd(it.type, it.rowId, it.columnId, it.cellId, it.position);
});
C.BlockTableRowSetHeader(rootId, id, v, () => {
this.framesUpdate();
if (callBack) {
callBack();
@ -1513,7 +1518,15 @@ const BlockTable = observer(class BlockTable extends React.Component<I.BlockComp
obj = frame;
};
obj.css({ left: item.x, top: item.y, width: item.w, height: item.h });
raf(() => {
obj.css({ left: item.x, top: item.y, width: item.w, height: item.h });
});
};
framesUpdate () {
this.frames.forEach(it => {
this.frameAdd(it.type, it.rowId, it.columnId, it.cellId, it.position);
});
};
getClassByPosition (position: I.BlockPosition) {

View file

@ -22,7 +22,7 @@ const BlockTableCell = observer(class BlockTableCell extends React.Component<Pro
render () {
const {
readonly, block, rowIdx, columnIdx, row, column, onHandleRow, onHandleColumn, onOptions, onCellFocus, onCellBlur, onCellClick, onCellEnter,
onCellLeave, onCellKeyDown, onResizeStart, onDragStartColumn, onDragStartRow, onEnterHandle, onLeaveHandle, onCellUpdate
onCellLeave, onCellKeyDown, onCellKeyUp, onResizeStart, onDragStartColumn, onDragStartRow, onEnterHandle, onLeaveHandle, onCellUpdate
} = this.props;
if (!row || !column) {
@ -39,9 +39,10 @@ const BlockTableCell = observer(class BlockTableCell extends React.Component<Pro
};
const Handle = (item: any) => {
const cn = [ 'handle' ];
let onDragStart = null;
let onClick = null;
const cn = [ 'handle' ];
let canDrag = true;
switch (item.type) {
@ -119,9 +120,9 @@ const BlockTableCell = observer(class BlockTableCell extends React.Component<Pro
<div
id={`cell-${cellId}`}
className={cn.join(' ')}
onClick={(e: any) => { onCellClick(e, row.id, column.id, cellId); }}
onMouseEnter={(e: any) => { onCellEnter(e, row.id, column.id, cellId); }}
onMouseLeave={(e: any) => { onCellLeave(e, row.id, column.id, cellId); }}
onClick={e => onCellClick(e, row.id, column.id, cellId)}
onMouseEnter={e => onCellEnter(e, row.id, column.id, cellId)}
onMouseLeave={e => onCellLeave(e, row.id, column.id, cellId)}
onMouseDown={this.onMouseDown}
{...UtilCommon.dataProps({ 'column-id': column.id })}
>
@ -138,6 +139,9 @@ const BlockTableCell = observer(class BlockTableCell extends React.Component<Pro
onKeyDown={(e: any, text: string, marks: I.Mark[], range: I.TextRange, props: any) => {
onCellKeyDown(e, row.id, column.id, cellId, text, marks, range, props);
}}
onKeyUp={(e: any, text: string, marks: I.Mark[], range: I.TextRange, props: any) => {
onCellKeyUp(e, row.id, column.id, cellId, text, marks, range, props);
}}
onUpdate={() => { onCellUpdate(cellId); }}
onFocus={(e: any) => { onCellFocus(e, row.id, column.id, cellId); }}
onBlur={(e: any) => { onCellBlur(e, row.id, column.id, cellId); }}

View file

@ -786,6 +786,20 @@ const BlockText = observer(class BlockText extends React.Component<Props> {
return;
};
if (range.to) {
let parsed = this.checkMarkOnBackspace(value);
if (parsed.save) {
e.preventDefault();
value = parsed.value;
this.marks = Mark.checkRanges(value, this.marks);
UtilData.blockSetText(rootId, block.id, value, this.marks, true, () => {
onKeyDown(e, value, this.marks, range, this.props);
});
ret = true;
};
} else
if (!menuOpenAdd && !menuOpenMention && !range.to) {
const parsed = this.getMarksFromHtml();
@ -1469,6 +1483,35 @@ const BlockText = observer(class BlockText extends React.Component<Props> {
UtilObject.setDone(objectId, done);
});
};
checkMarkOnBackspace (value: string) {
const range = this.getRange();
if (!range || !range.to) {
return;
};
let save = false;
for (const type of [ I.MarkType.Mention, I.MarkType.Emoji ]) {
const mark = Mark.getInRange(this.marks, type, range);
if (!mark) {
continue;
};
value = UtilCommon.stringCut(value, mark.range.from, mark.range.to);
this.marks = this.marks.filter(it => {
if ((it.type == mark.type) && (it.range.from == mark.range.from) && (it.range.to == mark.range.to)) {
return false;
};
return true;
});
save = true;
};
return { value, save };
};
});

View file

@ -220,7 +220,7 @@ const BlockType = observer(class BlockType extends React.Component<I.BlockCompon
this.onChange(item.id);
};
Storage.setLastUsedTypes(item.id);
Storage.addLastUsedType(item.id);
};
onObjectTo (layout: I.ObjectLayout) {

View file

@ -15,6 +15,7 @@ interface Props {
tooltipCaption?: string;
tooltipX?: I.MenuDirection.Left | I.MenuDirection.Center | I.MenuDirection.Right;
tooltipY?: I.MenuDirection.Top | I.MenuDirection.Bottom;
focusOnMount?: boolean;
onClick?(e: any): void;
onFocus?(e: any): void;
onBlur?(e: any): void;
@ -58,7 +59,7 @@ class Filter extends React.Component<Props, State> {
render () {
const { isActive } = this.state;
const { id, value, icon, tooltip, tooltipCaption, tooltipX, tooltipY, placeholder, className, inputClassName, onKeyDown, onKeyUp, onClick, onIconClick } = this.props;
const { id, value, icon, tooltip, tooltipCaption, tooltipX, tooltipY, placeholder, className, inputClassName, focusOnMount, onKeyDown, onKeyUp, onClick, onIconClick } = this.props;
const cn = [ 'filter' ];
if (className) {
@ -99,6 +100,7 @@ class Filter extends React.Component<Props, State> {
id="input"
className={inputClassName}
value={value}
focusOnMount={focusOnMount}
onFocus={this.onFocus}
onBlur={this.onBlur}
onChange={this.onChange}

View file

@ -4,7 +4,7 @@ import raf from 'raf';
import { Notification, Icon } from 'Component';
import { notificationStore } from 'Store';
import { observer } from 'mobx-react';
import { I, UtilSmile, UtilCommon } from 'Lib';
import { I, C } from 'Lib';
const LIMIT = 5;
@ -55,32 +55,6 @@ const ListNotification = observer(class ListNotification extends React.Component
};
componentDidMount (): void {
/*
for (let i = 0; i < 10; ++i) {
const icon1 = UtilSmile.randomParam();
const icon2 = UtilSmile.randomParam();
const object = {
name: 'Strategic writing',
iconEmoji: `:${icon1.id}:`,
layout: I.ObjectLayout.Page,
};
const subject = {
name: 'Investors space',
iconEmoji: `:${icon2.id}:`,
layout: I.ObjectLayout.Page,
};
notificationStore.add({
type: UtilCommon.rand(0, 1),
status: Boolean(UtilCommon.rand(0, 1)),
object,
subject,
});
};
*/
this.resize();
};
@ -115,6 +89,7 @@ const ListNotification = observer(class ListNotification extends React.Component
};
onClear () {
C.NotificationReply(notificationStore.list.map(it => it.id), I.NotificationAction.Close);
notificationStore.clear();
};

View file

@ -1,4 +1,5 @@
import * as React from 'react';
import $ from 'jquery';
import { observer } from 'mobx-react';
import { Popup } from 'Component';
import { popupStore } from 'Store';

View file

@ -1,7 +1,7 @@
import * as React from 'react';
import $ from 'jquery';
import { Filter, MenuItemVertical } from 'Component';
import { detailStore, blockStore, menuStore, commonStore, dbStore } from 'Store';
import { detailStore, blockStore, menuStore, commonStore } from 'Store';
import { I, C, keyboard, UtilData, UtilObject, UtilMenu, focus, Action, translate, analytics, Dataview, UtilCommon } from 'Lib';
import Constant from 'json/constant.json';
@ -80,6 +80,7 @@ class MenuBlockAction extends React.Component<I.Menu, State> {
value={filter}
onFocus={this.onFilterFocus}
onChange={this.onFilterChange}
focusOnMount={true}
/>
{!sections.length ? <div className="item empty">{translate('commonFilterEmpty')}</div> : ''}
@ -96,7 +97,6 @@ class MenuBlockAction extends React.Component<I.Menu, State> {
this._isMounted = true;
this.rebind();
this.focus();
menu.off('mouseleave').on('mouseleave', () => { menuStore.clearTimeout(); });
};
@ -114,14 +114,6 @@ class MenuBlockAction extends React.Component<I.Menu, State> {
menuStore.clearTimeout();
};
focus () {
window.setTimeout(() => {
if (this.refFilter) {
this.refFilter.focus();
};
}, 15);
};
onFilterFocus (e: any) {
menuStore.closeAll(Constant.menuIds.action);
this.props.setActive();

View file

@ -247,7 +247,7 @@ const MenuBlockRelationView = observer(class MenuBlockRelationView extends React
filter: '',
ref: 'menu',
menuIdEdit: 'blockRelationEdit',
skipKeys: dbStore.getObjectRelationKeys(rootId, rootId).concat(Relation.systemKeysWithoutUser()),
skipKeys: dbStore.getObjectRelationKeys(rootId, rootId),
addCommand: (rootId: string, blockId: string, relation: any, onChange: (message: any) => void) => {
C.ObjectRelationAdd(rootId, [ relation.relationKey ], onChange);
},

View file

@ -1,6 +1,6 @@
import * as React from 'react';
import { IconObject, ObjectName } from 'Component';
import { I, UtilObject, keyboard } from 'Lib';
import { I, UtilObject, keyboard, UtilDate } from 'Lib';
import { blockStore, dbStore, detailStore } from 'Store';
import { observer } from 'mobx-react';
@ -90,23 +90,6 @@ const MenuCalendarDay = observer(class MenuCalendarDay extends React.Component<I
$(window).off('keydown.menu');
};
getItems () {
const { param } = this.props;
const { data } = param;
const { getSubId, getView, getDateParam, d, m, y } = data;
const subId = getSubId();
const view = getView();
if (!view) {
return [];
};
return dbStore.getRecords(subId, '').map(id => detailStore.get(subId, id, [ view.groupRelationKey ])).filter(it => {
const value = getDateParam(it[view.groupRelationKey]);
return [ value.d, value.m, value.y ].join('-') == [ d, m, y ].join('-');
});
};
onMouseEnter (e: any, item: any) {
if (!keyboard.isMouseDisabled) {
this.props.setActive(item, false);
@ -129,6 +112,18 @@ const MenuCalendarDay = observer(class MenuCalendarDay extends React.Component<I
UtilObject.setDone(item.id, !item.done);
};
getItems () {
const { param } = this.props;
const { data } = param;
const { rootId, block, getView, d, m, y } = data;
const view = getView();
const subId = dbStore.getSubId(rootId, block.id);
const items = dbStore.getRecords(subId, '').map(id => detailStore.get(subId, id, [ view.groupRelationKey ]));
const current = [ d, m, y ].join('-');
return items.filter(it => UtilDate.date('j-n-Y', it[view.groupRelationKey]) == current);
};
});
export default MenuCalendarDay;

View file

@ -97,6 +97,7 @@ const MenuDataviewFileList = observer(class MenuDataviewFileList extends React.C
placeholderFocus={translate('commonFilterObjects')}
value={filter}
onChange={this.onFilterChange}
focusOnMount={true}
/>
{loading ? <Loader /> : (
@ -137,7 +138,6 @@ const MenuDataviewFileList = observer(class MenuDataviewFileList extends React.C
this._isMounted = true;
this.rebind();
this.resize();
this.focus();
this.load(true);
};
@ -164,9 +164,8 @@ const MenuDataviewFileList = observer(class MenuDataviewFileList extends React.C
if (this.refList && this.top) {
this.refList.scrollToPosition(this.top);
};
this.resize();
this.focus();
this.resize();
this.props.setActive();
};
@ -174,14 +173,6 @@ const MenuDataviewFileList = observer(class MenuDataviewFileList extends React.C
this._isMounted = false;
};
focus () {
window.setTimeout(() => {
if (this.refFilter) {
this.refFilter.focus();
};
}, 15);
};
rebind () {
this.unbind();
$(window).on('keydown.menu', (e: any) => { this.props.onKeyDown(e); });

View file

@ -379,10 +379,14 @@ const MenuDataviewObjectList = observer(class MenuDataviewObjectList extends Rea
resize () {
const { getId, position, param } = this.props;
const { data } = param;
const { noFilter } = data;
const { noFilter, canAdd } = data;
const items = this.getItems();
const obj = $(`#${getId()} .content`);
const height = Math.max(300, items.reduce((res: number, current: any) => { return res + this.getRowHeight(current); }, HEIGHT_ITEM + 16 + (noFilter ? 0 : 44)));
let height = items.reduce((res: number, current: any) => { return res + this.getRowHeight(current); }, 16 + (noFilter ? 0 : 44));
if (!canAdd) {
height = Math.max(180, height);
};
obj.css({ height });
position();

View file

@ -100,6 +100,7 @@ const MenuOptionList = observer(class MenuOptionList extends React.Component<I.M
placeholderFocus={placeholder}
value={filter}
onChange={this.onFilterChange}
focusOnMount={true}
/>
) : ''}
@ -142,7 +143,6 @@ const MenuOptionList = observer(class MenuOptionList extends React.Component<I.M
const items = this.getItems();
this._isMounted = true;
this.focus();
this.rebind();
this.resize();
@ -174,14 +174,6 @@ const MenuOptionList = observer(class MenuOptionList extends React.Component<I.M
this.unbind();
};
focus () {
window.setTimeout(() => {
if (this.refFilter) {
this.refFilter.focus();
};
}, 15);
};
rebind () {
this.unbind();
$(window).on('keydown.menu', e => this.onKeyDown(e));

View file

@ -356,7 +356,7 @@ const MenuRelationEdit = observer(class MenuRelationEdit extends React.Component
menuIdEdit: 'blockRelationEdit',
filter: '',
ref: 'dataview',
skipKeys: relations.map(it => it.relationKey).concat(Relation.systemKeysWithoutUser()),
skipKeys: relations.map(it => it.relationKey),
addCommand: (rootId: string, blockId: string, relation: any, onChange: (message: any) => void) => {
Dataview.relationAdd(rootId, blockId, relation.relationKey, Math.max(0, idx + item.dir), view, (message: any) => {
menuStore.closeAll([ this.props.id, 'relationSuggest' ]);

View file

@ -229,16 +229,10 @@ const MenuRelationList = observer(class MenuRelationList extends React.Component
onAdd (e: any) {
const { param, getId, getSize } = this.props;
const { data } = param;
const { rootId, blockId, getView } = data;
const { rootId, blockId, getView, onAdd } = data;
const view = getView();
const relations = Dataview.viewGetRelations(rootId, blockId, view);
const onAdd = () => {
if (data.onAdd) {
data.onAdd();
};
};
menuStore.open('relationSuggest', {
element: `#${getId()} #item-add`,
offsetX: getSize().width,
@ -251,11 +245,12 @@ const MenuRelationList = observer(class MenuRelationList extends React.Component
menuIdEdit: 'dataviewRelationEdit',
filter: '',
ref: 'dataview',
skipKeys: relations.map(it => it.relationKey).concat(Relation.systemKeysWithoutUser()),
onAdd,
skipKeys: relations.map(it => it.relationKey),
addCommand: (rootId: string, blockId: string, relation: any, onChange: (message: any) => void) => {
Dataview.relationAdd(rootId, blockId, relation.relationKey, relations.length, getView(), (message: any) => {
onAdd();
if (onAdd) {
onAdd();
};
if (onChange) {
onChange(message);

View file

@ -148,6 +148,7 @@ const MenuViewLayout = observer(class MenuViewLayout extends React.Component<I.M
return;
};
const view = data.view.get();
const isBoard = this.param.type == I.ViewType.Board;
const isCalendar = this.param.type == I.ViewType.Calendar;
const current = data.view.get();
@ -170,11 +171,9 @@ const MenuViewLayout = observer(class MenuViewLayout extends React.Component<I.M
if (withName) {
this.param.name = this.getViewName();
view.name = this.param.name;
};
let view = data.view.get();
view = Object.assign(view, this.param);
C.BlockDataviewViewUpdate(rootId, blockId, current.id, this.param, () => {
if (clearGroups) {
Dataview.groupUpdate(rootId, blockId, current.id, []);
@ -370,10 +369,12 @@ const MenuViewLayout = observer(class MenuViewLayout extends React.Component<I.M
if (item.sectionId == 'type') {
let withName = false;
if (this.param.name == Dataview.defaultViewName(this.param.type)) {
this.param.name = Dataview.defaultViewName(item.id);
withName = true;
};
this.param.type = item.id;
this.n = -1;

View file

@ -737,9 +737,9 @@ const Menu = observer(class Menu extends React.Component<I.Menu, State> {
};
this.ref.n = this.ref.getItems().length - 1;
refInput.blur();
this.setActive(null, true);
refInput.blur();
ret = true;
});
} else {
@ -881,7 +881,6 @@ const Menu = observer(class Menu extends React.Component<I.Menu, State> {
this.ref.n = n + dir;
this.checkIndex();
this.ref.onSortEnd({ oldIndex: n, newIndex: this.ref.n });
};

View file

@ -66,6 +66,7 @@ class MenuQuickCapture extends React.Component<I.Menu> {
placeholder={translate('menuQuickCaptureSearchObjectTypes')}
value={this.filter}
onChange={this.onFilterChange}
focusOnMount={true}
/>
) : ''}
<div className="items scrollWrap">
@ -95,7 +96,6 @@ class MenuQuickCapture extends React.Component<I.Menu> {
};
this.props.position();
this.resize();
this.rebind();
};
@ -285,7 +285,7 @@ class MenuQuickCapture extends React.Component<I.Menu> {
return;
};
Storage.setLastUsedTypes(type.id);
Storage.addLastUsedType(type.id);
UtilObject.openAuto(message.details);
analytics.event('CreateObject', { route: 'Navigation', objectType: type.id });
});
@ -316,12 +316,6 @@ class MenuQuickCapture extends React.Component<I.Menu> {
this.isExpanded = true;
this.forceUpdate();
window.setTimeout(() => {
if (this.refFilter) {
this.refFilter.focus();
};
}, 15);
};
onOver (e: any, item: any) {
@ -330,7 +324,7 @@ class MenuQuickCapture extends React.Component<I.Menu> {
};
};
resize () {
beforePosition () {
const node = $(this.node);
node.find('.item').each((i: number, item: any) => {

View file

@ -110,7 +110,8 @@ const MenuRelationSuggest = observer(class MenuRelationSuggest extends React.Com
ref={ref => this.refFilter = ref}
placeholderFocus={translate('menuRelationSuggestFilterOrCreateRelation')}
value={filter}
onChange={this.onFilterChange}
onChange={this.onFilterChange}
focusOnMount={true}
/>
) : ''}
@ -152,9 +153,7 @@ const MenuRelationSuggest = observer(class MenuRelationSuggest extends React.Com
this.rebind();
this.resize();
this.focus();
this.load(true);
this.forceUpdate();
};
@ -179,7 +178,6 @@ const MenuRelationSuggest = observer(class MenuRelationSuggest extends React.Com
});
this.resize();
this.focus();
this.rebind();
};
@ -190,14 +188,6 @@ const MenuRelationSuggest = observer(class MenuRelationSuggest extends React.Com
window.clearTimeout(this.timeoutFilter);
};
focus () {
window.setTimeout(() => {
if (this.refFilter) {
this.refFilter.focus();
};
}, 15);
};
rebind () {
this.unbind();
$(window).on('keydown.menu', e => this.props.onKeyDown(e));

View file

@ -145,6 +145,7 @@ const MenuSearchObject = observer(class MenuSearchObject extends React.Component
placeholderFocus={placeholderFocus}
value={filter}
onChange={this.onFilterChange}
focusOnMount={true}
/>
) : ''}
@ -191,7 +192,6 @@ const MenuSearchObject = observer(class MenuSearchObject extends React.Component
this._isMounted = true;
this.rebind();
this.resize();
this.focus();
this.load(true);
};
@ -214,7 +214,6 @@ const MenuSearchObject = observer(class MenuSearchObject extends React.Component
});
this.resize();
this.focus();
this.props.setActive();
};
@ -233,14 +232,6 @@ const MenuSearchObject = observer(class MenuSearchObject extends React.Component
$(window).off('keydown.menu');
};
focus () {
window.setTimeout(() => {
if (this.refFilter) {
this.refFilter.focus();
};
}, 15);
};
getItems () {
const { param } = this.props;
const { data } = param;

View file

@ -148,6 +148,7 @@ const MenuSelect = observer(class MenuSelect extends React.Component<I.Menu> {
placeholder={placeholder}
onChange={this.onFilterChange}
onKeyUp={this.onFilterKeyUp}
focusOnMount={true}
/>
) : ''}
@ -193,7 +194,6 @@ const MenuSelect = observer(class MenuSelect extends React.Component<I.Menu> {
window.setTimeout(() => { setActive(active, true); }, 15);
};
this.focus();
this.resize();
};

View file

@ -6,17 +6,18 @@ import { I, C, UtilCommon, UtilSmile, UtilMenu, keyboard, translate, analytics,
import { menuStore, commonStore } from 'Store';
import Constant from 'json/constant.json';
interface State {
filter: string;
page: number;
isLoading: boolean;
};
enum Tab {
Gallery = 0,
Upload = 1,
};
interface State {
filter: string;
page: number;
tab: Tab;
isLoading: boolean;
};
const LIMIT_RECENT = 18;
const LIMIT_ROW = 9;
const LIMIT_SEARCH = 12;
@ -32,6 +33,7 @@ class MenuSmile extends React.Component<I.Menu, State> {
filter: '',
page: 0,
isLoading: false,
tab: Tab.Gallery,
};
refFilter: any = null;
@ -43,11 +45,9 @@ class MenuSmile extends React.Component<I.Menu, State> {
timeoutFilter = 0;
cache: any = null;
groupCache: any[] = [];
aliases = {};
row: number = -1;
n: number = 0;
coll: number = 0;
active: any = null;
tab: Tab = Tab.Gallery;
constructor (props: I.Menu) {
super(props);
@ -66,14 +66,14 @@ class MenuSmile extends React.Component<I.Menu, State> {
};
render () {
const { filter, isLoading } = this.state;
const { filter, isLoading, tab } = this.state;
const { param } = this.props;
const { data } = param;
const { noHead, noGallery, noUpload, noRemove } = data;
let content = null;
switch (this.tab) {
switch (tab) {
case Tab.Gallery: {
if (!this.cache) {
break;
@ -139,7 +139,8 @@ class MenuSmile extends React.Component<I.Menu, State> {
ref={ref => this.refFilter = ref}
value={filter}
className={!noHead ? 'withHead' : ''}
onChange={(e: any) => { this.onKeyUp(e, false); }}
onChange={e => this.onKeyUp(e, false)}
focusOnMount={true}
/>
<div className="items">
@ -227,7 +228,7 @@ class MenuSmile extends React.Component<I.Menu, State> {
</div>
) : ''}
<div className={[ 'body', Tab[this.tab].toLowerCase() ].join(' ')}>
<div className={[ 'body', Tab[tab].toLowerCase() ].join(' ')}>
{content}
</div>
</div>
@ -240,35 +241,22 @@ class MenuSmile extends React.Component<I.Menu, State> {
const { storageGet, param } = this.props;
const { data } = param;
const { noGallery } = data;
const items = this.getItems();
this.rebind();
this.skin = Number(storageGet().skin) || 1;
this.cache = new CellMeasurerCache({
fixedWidth: true,
defaultHeight: HEIGHT_SECTION,
keyMapper: i => (items[i] || {}).id,
});
if (noGallery) {
this.onTab(Tab.Upload);
};
this.skin = Number(storageGet().skin) || 1;
this.aliases = {};
for (const k in UtilSmile.data.aliases) {
this.aliases[UtilSmile.data.aliases[k]] = k;
};
if (!this.cache) {
const items = this.getItems();
this.cache = new CellMeasurerCache({
fixedWidth: true,
defaultHeight: HEIGHT_SECTION,
keyMapper: i => (items[i] || {}).id,
});
} else {
this.forceUpdate();
};
window.setTimeout(() => {
if (this.refFilter) {
this.refFilter.focus();
};
}, 15);
this.rebind();
};
componentDidUpdate () {
@ -285,10 +273,6 @@ class MenuSmile extends React.Component<I.Menu, State> {
componentWillUnmount () {
this._isMounted = false;
const { param } = this.props;
const { data } = param;
const { rebind } = data;
window.clearTimeout(this.timeoutMenu);
window.clearTimeout(this.timeoutFilter);
@ -296,10 +280,6 @@ class MenuSmile extends React.Component<I.Menu, State> {
menuStore.close('smileSkin');
this.unbind();
if (rebind) {
rebind();
};
};
rebind () {
@ -512,8 +492,7 @@ class MenuSmile extends React.Component<I.Menu, State> {
const element = node.find(`#item-${$.escapeSelector(this.active.id)}`);
element.addClass('active');
Preview.tooltipShow({ text: (this.aliases[this.active.itemId] || this.active.itemId), element });
Preview.tooltipShow({ text: (UtilSmile.aliases[this.active.itemId] || this.active.itemId), element });
};
};
@ -539,11 +518,11 @@ class MenuSmile extends React.Component<I.Menu, State> {
return;
};
if (this.n > current.children.length) {
this.n = 0;
if (this.coll > current.children.length) {
this.coll = 0;
};
this.setActive(current.children[this.n], this.row);
this.setActive(current.children[this.coll], this.row);
};
onArrowHorizontal (dir: number) {
@ -551,26 +530,26 @@ class MenuSmile extends React.Component<I.Menu, State> {
return;
};
this.n += dir;
this.coll += dir;
const rows = this.getItems();
const current = rows[this.row];
// Arrow left
if (this.n < 0) {
this.n = LIMIT_ROW - 1;
if (this.coll < 0) {
this.coll = LIMIT_ROW - 1;
this.onArrowVertical(dir);
return;
};
// Arrow right
if (this.n > current.children.length - 1) {
this.n = 0;
if (this.coll > current.children.length - 1) {
this.coll = 0;
this.onArrowVertical(dir);
return;
};
this.setActive(current.children[this.n], this.row);
this.setActive(current.children[this.coll], this.row);
};
onRandom () {
@ -618,7 +597,7 @@ class MenuSmile extends React.Component<I.Menu, State> {
onMouseEnter (e: any, item: any) {
if (!keyboard.isMouseDisabled) {
this.row = item.position.row;
this.n = item.position.n;
this.coll = item.position.n;
this.setActive(item);
};
};
@ -626,7 +605,7 @@ class MenuSmile extends React.Component<I.Menu, State> {
onMouseLeave () {
if (!keyboard.isMouseDisabled) {
this.setActive(null);
this.n = 0;
this.coll = 0;
};
};
@ -731,7 +710,7 @@ class MenuSmile extends React.Component<I.Menu, State> {
this.refList.scrollToRow(Math.max(0, idx));
this.row = Math.max(0, idx);
this.n = -1;
this.coll = 0;
};
getGroupCache () {
@ -740,6 +719,7 @@ class MenuSmile extends React.Component<I.Menu, State> {
};
const items = this.getItems();
let t = 0;
let last = null;
@ -788,10 +768,7 @@ class MenuSmile extends React.Component<I.Menu, State> {
return;
};
const node = $(this.node);
const zone = node.find('.dropzone');
zone.addClass('isDraggingOver');
$(this.node).find('.dropzone').addClass('isDraggingOver');
};
onDragLeave (e: any) {
@ -799,10 +776,7 @@ class MenuSmile extends React.Component<I.Menu, State> {
return;
};
const node = $(this.node);
const zone = node.find('.dropzone');
zone.removeClass('isDraggingOver');
$(this.node).find('.dropzone').removeClass('isDraggingOver');
};
onDrop (e: any) {
@ -825,6 +799,7 @@ class MenuSmile extends React.Component<I.Menu, State> {
C.FileUpload(commonStore.space, '', file, I.FileType.Image, (message: any) => {
this.setState({ isLoading: false });
preventCommonDrop(false);
if (!message.error.code) {
@ -836,10 +811,9 @@ class MenuSmile extends React.Component<I.Menu, State> {
};
onTab (tab: Tab) {
this.tab = tab;
this.forceUpdate();
this.setState({ tab });
};
};
export default MenuSmile;

View file

@ -1,8 +1,8 @@
import * as React from 'react';
import { observer } from 'mobx-react';
import { IconObject, Icon, ObjectName } from 'Component';
import { I, UtilCommon, UtilData, UtilObject, UtilRouter, keyboard, translate, Action } from 'Lib';
import { authStore, dbStore, detailStore, popupStore, menuStore, blockStore } from 'Store';
import { I, UtilCommon, UtilObject, UtilRouter, keyboard, translate, Action, analytics } from 'Lib';
import { authStore, dbStore, popupStore, menuStore, blockStore } from 'Store';
import Constant from 'json/constant.json';
const MenuSpace = observer(class MenuSpace extends React.Component<I.Menu> {
@ -213,6 +213,7 @@ const MenuSpace = observer(class MenuSpace extends React.Component<I.Menu> {
this.onAdd();
} else {
UtilRouter.switchSpace(item.targetSpaceId);
analytics.event('SwitchSpace');
this.props.close();
};
};
@ -223,10 +224,13 @@ const MenuSpace = observer(class MenuSpace extends React.Component<I.Menu> {
data: {
page: 'spaceCreate',
isSpace: true,
onCreate: (id) => UtilRouter.switchSpace(id, ''),
onCreate: (id) => {
UtilRouter.switchSpace(id, '');
analytics.event('SwitchSpace');
},
},
});
this.props.close();
};

View file

@ -111,6 +111,7 @@ const MenuTypeSuggest = observer(class MenuTypeSuggest extends React.Component<I
placeholderFocus={translate('menuTypeSuggestFilterTypes')}
value={filter}
onChange={this.onFilterChange}
focusOnMount={true}
/>
) : ''}
@ -152,9 +153,7 @@ const MenuTypeSuggest = observer(class MenuTypeSuggest extends React.Component<I
this.rebind();
this.resize();
this.focus();
this.load(true);
this.forceUpdate();
};
@ -179,7 +178,6 @@ const MenuTypeSuggest = observer(class MenuTypeSuggest extends React.Component<I
});
this.resize();
this.focus();
this.props.setActive();
};
@ -192,14 +190,6 @@ const MenuTypeSuggest = observer(class MenuTypeSuggest extends React.Component<I
window.clearTimeout(this.timeoutFilter);
};
focus () {
window.setTimeout(() => {
if (this.refFilter) {
this.refFilter.focus();
};
}, 15);
};
rebind () {
this.unbind();
$(window).on('keydown.menu', (e: any) => { this.props.onKeyDown(e); });
@ -445,7 +435,7 @@ const MenuTypeSuggest = observer(class MenuTypeSuggest extends React.Component<I
item = detailStore.mapper(item);
Storage.setLastUsedTypes(item.id);
Storage.addLastUsedType(item.id);
if (onClick) {
onClick(item);

View file

@ -0,0 +1,26 @@
import * as React from 'react';
import { observer } from 'mobx-react';
import { Title, Label } from 'Component';
import { I, UtilCommon, translate } from 'Lib';
const NotificationImport = observer(class NotificationImport extends React.Component<I.NotificationComponent, {}> {
render () {
const { item } = this.props;
const { payload, type } = item;
const { errorCode } = payload;
const lang = errorCode ? 'error' : 'success';
const title = translate(UtilCommon.toCamelCase(`notification-${type}-${lang}-title`));
const text = translate(UtilCommon.toCamelCase(`notification-${type}-${lang}-text`));
return (
<React.Fragment>
<Title text={title} />
<Label text={text} />
</React.Fragment>
);
};
});
export default NotificationImport;

View file

@ -0,0 +1,47 @@
import * as React from 'react';
import { observer } from 'mobx-react';
import { Title, Label, Button } from 'Component';
import { I, UtilCommon, UtilObject, translate } from 'Lib';
import { commonStore } from 'Store';
const NotificationImport = observer(class NotificationImport extends React.Component<I.NotificationComponent, {}> {
render () {
const { item, onButton } = this.props;
const { payload, type } = item;
const { errorCode, spaceId } = payload;
const object = UtilObject.getSpaceviewBySpaceId(spaceId) || {};
const lang = errorCode ? 'error' : 'success';
const title = translate(UtilCommon.toCamelCase(`notification-${type}-${lang}-title`));
const text = translate(UtilCommon.toCamelCase(`notification-${type}-${lang}-text`));
let buttons = [];
if (errorCode) {
buttons = buttons.concat([
{ id: 'importRetry', text: 'Retry' },
{ id: 'importReport', text: 'Report' },
]);
} else
if (spaceId != commonStore.space) {
buttons = buttons.concat([
{ id: 'space', text: 'Go to space' }
]);
};
return (
<React.Fragment>
<Title text={UtilCommon.sprintf(title, object.name)} />
<Label text={UtilCommon.sprintf(text, object.name)} />
<div className="buttons">
{buttons.map((item: any, i: number) => (
<Button key={i} color="blank" className="c28" {...item} onClick={e => onButton(e, item.id)} />
))}
</div>
</React.Fragment>
);
};
});
export default NotificationImport;

View file

@ -1,13 +1,14 @@
import * as React from 'react';
import $ from 'jquery';
import raf from 'raf';
import { observer } from 'mobx-react';
import { Icon } from 'Component';
import { I } from 'Lib';
import { I, C, UtilRouter } from 'Lib';
import { notificationStore } from 'Store';
import Constant from 'json/constant.json';
import NotificationUsecase from './usecase';
import NotificationImport from './import';
import NotificationExport from './export';
import NotificationInvite from './invite';
const Notification = observer(class Notification extends React.Component<I.NotificationComponent, {}> {
@ -39,6 +40,16 @@ const Notification = observer(class Notification extends React.Component<I.Notif
break;
};
case I.NotificationType.Import: {
content = <NotificationImport {...this.props} onButton={this.onButton} />;
break;
};
case I.NotificationType.Export: {
content = <NotificationExport {...this.props} onButton={this.onButton} />;
break;
};
case I.NotificationType.Invite: {
content = <NotificationInvite {...this.props} onButton={this.onButton} />;
break;
@ -77,14 +88,19 @@ const Notification = observer(class Notification extends React.Component<I.Notif
e.stopPropagation();
const { item } = this.props;
const { payload } = item;
switch (action) {
case 'space': {
UtilRouter.switchSpace(payload.spaceId);
break;
};
};
this.onDelete(e);
};
onDelete (e: any) {
onDelete (e: any): void {
e.stopPropagation();
const { item, resize } = this.props;
@ -92,6 +108,8 @@ const Notification = observer(class Notification extends React.Component<I.Notif
node.addClass('to');
this.timeout = window.setTimeout(() => {
C.NotificationReply([ item.id ], I.NotificationAction.Close);
notificationStore.delete(item.id);
resize();
}, Constant.delay.notification);

View file

@ -29,6 +29,7 @@ const NotificationInvite = observer(class NotificationInvite extends React.Compo
);
};
/*
componentDidMount(): void {
const { item } = this.props;
const { object, subject } = item;
@ -46,6 +47,7 @@ const NotificationInvite = observer(class NotificationInvite extends React.Compo
ReactDOM.render(<Element {...object} />, objectEl.get(0));
ReactDOM.render(<Element {...subject} />, subjectEl.get(0));
};
*/
});

View file

@ -6,6 +6,7 @@ import { I, UtilCommon, translate } from 'Lib';
const NotificationUsecase = observer(class NotificationUsecase extends React.Component<I.NotificationComponent, {}> {
render () {
/*
const { item, onButton } = this.props;
const { type, status, object } = item;
@ -42,6 +43,8 @@ const NotificationUsecase = observer(class NotificationUsecase extends React.Com
</div>
</React.Fragment>
);
*/
return <div />;
};
});

View file

@ -66,8 +66,6 @@ const PageMainGraph = observer(class PageMainGraph extends React.Component<I.Pag
this.resize();
this.load();
this.initRootId(this.getRootId());
window.Graph = this;
};
componentDidUpdate () {

View file

@ -386,7 +386,7 @@ const PageMainType = observer(class PageMainType extends React.Component<I.PageC
};
UtilObject.openPopup(message.details);
Storage.setLastUsedTypes(type.id);
Storage.addLastUsedType(type.id);
analytics.event('CreateObject', {
route: 'ObjectType',

View file

@ -13,6 +13,7 @@ const PopupConfirm = observer(class PopupConfirm extends React.Component<I.Popup
this.onConfirm = this.onConfirm.bind(this);
this.onCancel = this.onCancel.bind(this);
this.onMouseEnter = this.onMouseEnter.bind(this);
this.setHighlight = this.setHighlight.bind(this);
};
@ -35,8 +36,8 @@ const PopupConfirm = observer(class PopupConfirm extends React.Component<I.Popup
<Label text={text} />
<div ref={ref => this.refButtons = ref} className="buttons">
{canConfirm ? <Button text={textConfirm} color={colorConfirm} className="c36" onClick={this.onConfirm} /> : ''}
{canCancel ? <Button text={textCancel} color={colorCancel} className="c36" onClick={this.onCancel} /> : ''}
{canConfirm ? <Button text={textConfirm} color={colorConfirm} className="c36" onClick={this.onConfirm} onMouseEnter={this.onMouseEnter} /> : ''}
{canCancel ? <Button text={textCancel} color={colorCancel} className="c36" onClick={this.onCancel} onMouseEnter={this.onMouseEnter} /> : ''}
</div>
</React.Fragment>
);
@ -124,6 +125,13 @@ const PopupConfirm = observer(class PopupConfirm extends React.Component<I.Popup
};
};
onMouseEnter (e: any) {
const buttons = $(this.refButtons).find('.button');
this.n = $(buttons).index(e.currentTarget);
this.setHighlight();
};
setHighlight () {
const buttons = $(this.refButtons).find('.button');

View file

@ -45,7 +45,7 @@ const PopupObjectManager = observer(class PopupObjectManager extends React.Compo
onAfterLoad={this.onAfterLoad}
/>
<Button text={translate('commonDone')} onClick={this.onClick} />
<Button text={translate('commonDone')} className="c36" onClick={this.onClick} />
</React.Fragment>
);
};

View file

@ -133,7 +133,7 @@ class PopupShortcut extends React.Component<I.Popup, State> {
{ com: `${cmd} + Shift + N`, name: translate('popupShortcutMainBasics2') },
{ com: `${cmd} + ${alt} + N`, name: translate('popupShortcutMainBasics3') },
{ com: `${cmd} + Enter`, name: translate('popupShortcutMainBasics4') },
{ com: `${cmd} + ${alt} + F`, name: translate('popupShortcutMainBasics5') },
{ mac: `${cmd} + Ctrl + F`, com: `${cmd} + ${alt} + F`, name: translate('popupShortcutMainBasics5') },
{ com: `${cmd} + Z`, name: translate('popupShortcutMainBasics6') },
{ com: `${cmd} + Shift + Z`, name: translate('popupShortcutMainBasics7') },
{ com: `${cmd} + P`, name: translate('popupShortcutMainBasics8') },

View file

@ -33,7 +33,7 @@ class Navigation extends React.Component {
const buttons: any[] = [
{ id: 'back', tooltip: translate('commonBack'), caption: cb, onClick: this.onBack, disabled: !keyboard.checkBack() },
{ id: 'forward', tooltip: translate('commonForward'), caption: cf, onClick: this.onForward, disabled: !keyboard.checkForward() },
{ id: 'plus', tooltip: translate('navigationCreateNew'), caption: `${cmd} + N`, onClick: this.onAdd },
{ id: 'plus', tooltip: translate('navigationCreateNew'), caption: `${cmd} + N`, onClick: this.onAdd, onContextMenu: () => keyboard.onQuickCapture() },
{ id: 'graph', tooltip: translate('commonGraph'), caption: `${cmd} + ${alt} + O`, onClick: this.onGraph },
{ id: 'search', tooltip: translate('commonSearch'), caption: `${cmd} + S`, onClick: this.onSearch },
];
@ -56,7 +56,8 @@ class Navigation extends React.Component {
<div
key={item.id}
id={`button-navigation-${item.id}`}
onClick={item.onClick}
onClick={item.onClick}
onContextMenu={item.onContextMenu}
className={cn.join(' ')}
onMouseEnter={e => item.disabled ? null : this.onTooltipShow(e, item.tooltip, item.caption)}
onMouseLeave={e => Preview.tooltipHide(false)}
@ -117,8 +118,8 @@ class Navigation extends React.Component {
keyboard.onForward();
};
onAdd () {
keyboard.onQuickCapture();
onAdd (e: any) {
e.altKey ? keyboard.onQuickCapture() : keyboard.pageCreate({}, 'Navigation');
};
onGraph () {

View file

@ -14,6 +14,7 @@ export interface BlockComponentTable extends I.BlockComponent {
onCellLeave: (e: any, rowId: string, columnId: string, cellId: string) => void;
onCellUpdate: (cellId: string) => void;
onCellKeyDown: (e: any, rowId: string, columnId: string, cellId: string, text: string, marks: I.Mark[], range: I.TextRange, props: any) => void;
onCellKeyUp: (e: any, rowId: string, columnId: string, cellId: string, text: string, marks: I.Mark[], range: I.TextRange, props: any) => void;
onResizeStart: (e: any, id: string) => void;
onDragStartRow: (e: any, id: string) => void;
onDragStartColumn: (e: any, id: string) => void;

View file

@ -39,7 +39,7 @@ import { Preview, PreviewLink, PreviewType, PreviewSize } from './preview';
import { MenuTab, MenuType, MenuDirection, MenuParam, Menu, MenuItem } from './menu';
import { ObjectLayout, ObjectFlag, RelationType, RelationScope, ObjectOrigin } from './object';
import { RestrictionObject, RestrictionDataview } from './restriction';
import { NotificationType, Notification, NotificationComponent } from './notification';
import { NotificationType, NotificationStatus, NotificationAction, NotificationPayloadImport, Notification, NotificationComponent } from './notification';
import { PageInfo, BlockType, BlockPosition, BlockSplitMode, BlockHAlign, BlockVAlign, BlockComponent, Block, BlockStructure } from './block';
import {
@ -157,8 +157,11 @@ export {
RestrictionDataview,
NotificationType,
NotificationStatus,
Notification,
NotificationPayloadImport,
NotificationComponent,
NotificationAction,
PageInfo,

View file

@ -1,14 +1,43 @@
import { I } from 'Lib';
export enum NotificationType {
Usecase = 0,
Invite = 1,
None = '',
Import = 'import',
Export = 'export',
Invite = 'invite',
Usecase = 'usecase',
};
export enum NotificationStatus {
Created = 0,
Shown = 1,
Read = 2,
Replied = 3,
};
export enum NotificationAction {
Retry = 0,
Report = 1,
OpenObject = 2,
OpenSpace = 3,
Close = 4,
};
export interface Notification {
id?: string;
id: string;
type: NotificationType;
status: boolean;
object?: any;
subject?: any;
status: NotificationStatus;
createTime: number;
isLocal: boolean;
payload: any;
};
export interface NotificationPayloadImport {
processId: string;
errorCode: number;
importType: I.ImportType;
spaceId: string;
name: string;
};
export interface NotificationComponent {

View file

@ -1807,6 +1807,26 @@ const DebugStackGoroutines = (path: string, callBack?: (message: any) => void) =
dispatcher.request(DebugStackGoroutines.name, request, callBack);
};
// ---------------------- NOTIFICATION ---------------------- //
const NotificationList = (includeRead: boolean, limit: number, callBack?: (message: any) => void) => {
const request = new Rpc.Notification.List.Request();
request.setIncluderead(includeRead);
request.setLimit(limit);
dispatcher.request(NotificationList.name, request, callBack);
};
const NotificationReply = (ids: string[], action: I.NotificationAction, callBack?: (message: any) => void) => {
const request = new Rpc.Notification.Reply.Request();
request.setIdsList(ids);
request.setActiontype(action as number);
dispatcher.request(NotificationReply.name, request, callBack);
};
export {
MetricsSetParameters,
LinkPreview,
@ -2016,4 +2036,7 @@ export {
UnsplashSearch,
UnsplashDownload,
NotificationList,
NotificationReply,
};

View file

@ -4,7 +4,7 @@ import { observable, set } from 'mobx';
import Commands from 'protobuf/pb/protos/commands_pb';
import Events from 'protobuf/pb/protos/events_pb';
import Service from 'protobuf/pb/protos/service/service_grpc_web_pb';
import { authStore, commonStore, blockStore, detailStore, dbStore, popupStore } from 'Store';
import { authStore, commonStore, blockStore, detailStore, dbStore, popupStore, notificationStore } from 'Store';
import { UtilCommon, UtilObject, I, M, translate, analytics, Renderer, Action, Dataview, Preview, Mapper, Decode, UtilRouter } from 'Lib';
import * as Response from './response';
import { ClientReadableStream } from 'grpc-web';
@ -145,6 +145,9 @@ class Dispatcher {
if (v == V.FILELOCALUSAGE) t = 'fileLocalUsage';
if (v == V.FILELIMITREACHED) t = 'fileLimitReached';
if (v == V.NOTIFICATIONSEND) t = 'notificationSend';
if (v == V.NOTIFICATIONUPDATE) t = 'notificationUpdate';
return t;
};
@ -945,6 +948,16 @@ class Dispatcher {
break;
};
case 'notificationSend': {
notificationStore.add(Mapper.From.Notification(data.getNotification()));
break;
};
case 'notificationUpdate': {
notificationStore.update(Mapper.From.Notification(data.getNotification()));
break;
};
case 'processNew':
case 'processUpdate':
case 'processDone': {
@ -978,63 +991,6 @@ class Dispatcher {
case I.ProgressState.Done:
case I.ProgressState.Canceled: {
commonStore.progressClear();
let title = '';
let text = '';
let textConfirm = '';
let showPopup = [ I.ProgressType.Import, I.ProgressType.Export ].includes(type) && [ I.ProgressState.Error, I.ProgressState.Done ].includes(state);
switch (state) {
case I.ProgressState.Error: {
textConfirm = translate('dispatcherImportTryAgain');
switch (type) {
case I.ProgressType.Import: {
title = translate('dispatcherImportErrorTitle');
text = translate('dispatcherImportErrorText');
break;
};
case I.ProgressType.Export: {
title = translate('dispatcherExportErrorTitle');
text = translate('dispatcherExportErrorText');
break;
};
};
break;
};
case I.ProgressState.Done: {
textConfirm = translate('dispatcherImportConfirm');
switch (type) {
case I.ProgressType.Import: {
showPopup = false;
break;
};
case I.ProgressType.Export: {
title = translate('dispatcherExportSuccessTitle');
text = translate('dispatcherExportSuccessText');
break;
};
};
break;
};
};
if (showPopup) {
window.setTimeout(() => {
popupStore.open('confirm', {
data: {
title,
text,
textConfirm,
canCancel: false,
}
});
}, Constant.delay.popup);
};
break;
};
};

View file

@ -38,9 +38,18 @@ export const Mapper = {
return t;
},
NotificationPayload (v: number) {
const V = Model.Notification.PayloadCase;
let t = '';
if (v == V.IMPORT) t = 'import';
if (v == V.EXPORT) t = 'export';
return t;
},
From: {
Account: (obj: any): I.Account => {
Account: (obj: Model.Account): I.Account => {
return {
id: obj.getId(),
info: obj.hasInfo() ? Mapper.From.AccountInfo(obj.getInfo()) : null,
@ -66,8 +75,7 @@ export const Mapper = {
},
AccountConfig: (obj: any): I.AccountConfig => {
return {
};
return {};
},
AccountStatus: (obj: any): I.AccountStatus => {
@ -479,6 +487,45 @@ export const Mapper = {
};
},
Notification: (obj: any): I.Notification => {
const type = Mapper.NotificationPayload(obj.getPayloadCase());
const field = obj['get' + UtilCommon.ucFirst(type)]();
let payload: any = {};
switch (type) {
case 'import': {
payload = Object.assign(payload, {
processId: field.getProcessid(),
errorCode: field.getErrorcode(),
importType: field.getImporttype(),
spaceId: field.getSpaceid(),
name: field.getName(),
});
break;
};
case 'export': {
payload = Object.assign(payload, {
errorCode: field.getErrorcode(),
exportType: field.getExporttype(),
});
break;
};
};
return {
id: obj.getId(),
createTime: obj.getCreatetime(),
status: obj.getStatus(),
isLocal: obj.getIslocal(),
type: type as I.NotificationType,
payload,
};
},
},
//------------------------------------------------------------

View file

@ -420,4 +420,10 @@ export const DownloadManifest = (response: Rpc.DownloadManifest.Response) => {
categories: info.getCategoriesList() || [],
},
};
};
export const NotificationList = (response: Rpc.Notification.List.Response) => {
return {
list: (response.getNotificationsList() || []).map(Mapper.From.Notification),
};
};

View file

@ -246,7 +246,7 @@ class Keyboard {
// Create new page
this.shortcut(`${cmd}+n`, e, () => {
e.preventDefault();
this.onQuickCapture();
this.pageCreate({}, 'Shortcut');
});
// Settings

View file

@ -1,5 +1,6 @@
import { I, UtilCommon } from 'Lib';
import { commonStore } from 'Store';
import { commonStore, dbStore } from 'Store';
import Constant from 'json/constant.json';
const SPACE_KEYS = [
'toggle',
@ -199,12 +200,31 @@ class Storage {
this.set('survey', obj, true);
};
setLastUsedTypes (id: string) {
let list = this.getLastUsedTypes();
initLastUsedTypes () {
const list = this.getLastUsedTypes();
if (('object' != typeof(list)) || !UtilCommon.hasProperty(list, 'length')) {
list = [];
if (!list.length) {
const keys = [
Constant.typeKey.note,
Constant.typeKey.page,
Constant.typeKey.task,
];
for (let key of keys) {
const type = dbStore.getTypeByKey(key);
if (type) {
list.push(type.id);
};
};
if (list.length) {
this.set('lastUsedTypes', list, true);
};
};
};
addLastUsedType (id: string) {
let list = this.getLastUsedTypes();
if (!id) {
return list;
@ -219,13 +239,14 @@ class Storage {
};
getLastUsedTypes () {
const list = this.get('lastUsedTypes') || [];
return this.checkArray(this.get('lastUsedTypes') || []);
};
if (('object' != typeof(list)) || !UtilCommon.hasProperty(list, 'length')) {
checkArray (a) {
if (('object' != typeof(a)) || !UtilCommon.hasProperty(a, 'length')) {
return [];
};
return list;
return a;
};
logout () {

View file

@ -1,5 +1,5 @@
import { I, C, keyboard, translate, UtilCommon, UtilRouter, Storage, analytics, dispatcher, Mark, UtilObject, focus } from 'Lib';
import { commonStore, blockStore, detailStore, dbStore, authStore } from 'Store';
import { commonStore, blockStore, detailStore, dbStore, authStore, notificationStore } from 'Store';
import Constant from 'json/constant.json';
import * as Sentry from '@sentry/browser';
@ -228,12 +228,6 @@ class UtilData {
keyboard.initPinCheck();
analytics.event('OpenAccount');
C.FileNodeUsage((message: any) => {
if (!message.error.code) {
commonStore.spaceStorageSet(message);
};
});
C.ObjectOpen(blockStore.rootId, '', space, (message: any) => {
if (!UtilCommon.checkError(message.error.code)) {
return;
@ -241,6 +235,18 @@ class UtilData {
C.ObjectOpen(widgets, '', space, () => {
this.createsSubscriptions(() => {
C.NotificationList(false, Constant.limit.notification, (message: any) => {
if (!message.error.code) {
notificationStore.set(message.list);
};
});
C.FileNodeUsage((message: any) => {
if (!message.error.code) {
commonStore.spaceStorageSet(message);
};
});
if (pin && !keyboard.isPinChecked) {
UtilRouter.go('/auth/pin-check', routeParam);
} else {
@ -253,6 +259,8 @@ class UtilData {
commonStore.redirectSet('');
};
Storage.initLastUsedTypes();
if (!color) {
Storage.set('color', 'orange');
};

View file

@ -229,7 +229,7 @@ class UtilObject {
templateId = type.defaultTemplateId || Constant.templateId.blank;
};
Storage.setLastUsedTypes(type.id);
Storage.addLastUsedType(type.id);
};
};

View file

@ -1,3 +1,4 @@
import $ from 'jquery';
import { C, UtilData, Preview, analytics, Storage, keyboard } from 'Lib';
import { commonStore, authStore, blockStore, menuStore, popupStore } from 'Store';
import Constant from 'json/constant.json';
@ -150,8 +151,6 @@ class UtilRouter {
UtilData.onInfo(message.info);
UtilData.onAuth({ routeParam: { replace: true } }, callBack);
analytics.event('SwitchSpace');
}
});
});

View file

@ -10,6 +10,7 @@ class UtilSmile {
icons: any[] = [];
cache: any = {};
data: any = {};
aliases: any = {};
constructor () {
init({ data });
@ -24,6 +25,10 @@ class UtilSmile {
this.cache[skin.native] = skin.shortcodes;
};
};
for (const k in this.data.aliases) {
this.aliases[this.data.aliases[k]] = k;
};
};
nativeById (id: string, skin: number): string {

View file

@ -4,24 +4,22 @@ import { observable, intercept, makeObservable } from 'mobx';
class Notification implements I.Notification {
id = '';
type: I.NotificationType = 0;
status = false;
object = null;
subject = null;
type: I.NotificationType = I.NotificationType.None;
status: I.NotificationStatus = I.NotificationStatus.Created;
createTime = 0;
isLocal = false;
payload = {};
constructor (props: I.Notification) {
this.id = String(props.id || '');
this.type = Number(props.type) || 0;
this.status = Boolean(props.status);
this.object = props.object;
this.subject = props.subject;
this.type = props.type || I.NotificationType.None;
this.status = Number(props.status) || I.NotificationStatus.Created;
this.createTime = Number(props.createTime) || 0;
this.isLocal = Boolean(props.isLocal);
this.payload = props.payload || {};
makeObservable(this, {
id: observable,
type: observable,
status: observable,
object: observable,
subject: observable,
});
intercept(this as any, change => UtilCommon.intercept(this, change));

View file

@ -122,7 +122,7 @@ class CommonStore {
};
get config(): any {
return window.Config || { ...this.configObj, debug: this.configObj.debug || {} };
return window.Anytype?.Config || { ...this.configObj, debug: this.configObj.debug || {} };
};
get progress(): I.Progress {

View file

@ -1,4 +1,4 @@
import { observable, action, computed, makeObservable } from 'mobx';
import { observable, action, computed, makeObservable, set } from 'mobx';
import { I, M } from 'Lib';
class NotificationStore {
@ -18,12 +18,22 @@ class NotificationStore {
return this.itemList;
};
add (item: I.Notification): void {
item.id = item.id || String(Math.random()).replace(/\./, '-');
set (list: I.Notification[]): void {
this.itemList = list.map(it => new M.Notification(it));
};
add (item: I.Notification): void {
this.itemList.unshift(new M.Notification(item));
};
update (item: I.Notification): void {
const current = this.itemList.find(it => it.id == item.id);
if (current) {
set(current, item);
};
};
delete (id: string) {
this.itemList = this.itemList.filter(it => it.id != id);
};