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:
commit
0c44b3602e
68 changed files with 595 additions and 423 deletions
3
dist/polyfill.js
vendored
3
dist/polyfill.js
vendored
|
@ -1,6 +1,7 @@
|
|||
const RendererEvents = {};
|
||||
|
||||
window.Config = {
|
||||
window.Anytype = window.Anytype || {};
|
||||
window.Anytype.Config = {
|
||||
debug: {
|
||||
mw: true,
|
||||
},
|
||||
|
|
|
@ -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() }
|
||||
|
|
|
@ -1 +1 @@
|
|||
0.29.16
|
||||
0.30.0-rc1
|
4
package-lock.json
generated
4
package-lock.json
generated
|
@ -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": {
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -19,7 +19,8 @@
|
|||
"limit": {
|
||||
"menuRecords": 100,
|
||||
"widgets": 20,
|
||||
"space": 10
|
||||
"space": 10,
|
||||
"notification": 20
|
||||
},
|
||||
|
||||
"default": {
|
||||
|
|
|
@ -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! "%s" 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."
|
||||
|
||||
}
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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; }
|
||||
|
||||
|
|
|
@ -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%; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -679,7 +679,7 @@ const BlockDataview = observer(class BlockDataview extends React.Component<Props
|
|||
});
|
||||
};
|
||||
|
||||
Storage.setLastUsedTypes(typeId);
|
||||
Storage.addLastUsedType(typeId);
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -129,7 +129,6 @@ const Item = observer(class Item extends React.Component<Props> {
|
|||
noFlipX: true,
|
||||
data: {
|
||||
...this.props,
|
||||
items: this.getItems(),
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
|
@ -53,8 +53,6 @@ const ViewGraph = observer(class ViewGraph extends React.Component<I.ViewCompone
|
|||
this.rebind();
|
||||
this.resize();
|
||||
this.load();
|
||||
|
||||
window.Graph = this;
|
||||
};
|
||||
|
||||
componentDidUpdate () {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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); }}
|
||||
|
|
|
@ -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 };
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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();
|
||||
};
|
||||
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
},
|
||||
|
|
|
@ -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;
|
|
@ -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); });
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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' ]);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 });
|
||||
};
|
||||
|
||||
|
|
|
@ -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) => {
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
|
@ -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();
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
26
src/ts/component/notification/export.tsx
Normal file
26
src/ts/component/notification/export.tsx
Normal 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;
|
47
src/ts/component/notification/import.tsx
Normal file
47
src/ts/component/notification/import.tsx
Normal 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;
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
};
|
||||
*/
|
||||
|
||||
});
|
||||
|
||||
|
|
|
@ -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 />;
|
||||
};
|
||||
|
||||
});
|
||||
|
|
|
@ -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 () {
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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');
|
||||
|
||||
|
|
|
@ -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>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -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') },
|
||||
|
|
|
@ -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 () {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
},
|
||||
|
||||
},
|
||||
|
||||
//------------------------------------------------------------
|
||||
|
|
|
@ -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),
|
||||
};
|
||||
};
|
|
@ -246,7 +246,7 @@ class Keyboard {
|
|||
// Create new page
|
||||
this.shortcut(`${cmd}+n`, e, () => {
|
||||
e.preventDefault();
|
||||
this.onQuickCapture();
|
||||
this.pageCreate({}, 'Shortcut');
|
||||
});
|
||||
|
||||
// Settings
|
||||
|
|
|
@ -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 () {
|
||||
|
|
|
@ -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');
|
||||
};
|
||||
|
|
|
@ -229,7 +229,7 @@ class UtilObject {
|
|||
templateId = type.defaultTemplateId || Constant.templateId.blank;
|
||||
};
|
||||
|
||||
Storage.setLastUsedTypes(type.id);
|
||||
Storage.addLastUsedType(type.id);
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -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');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue