mirror of
https://github.com/anyproto/anytype-ts.git
synced 2025-06-08 05:57:02 +09:00
Merge branch 'main' into nightly-ci-test-beta
This commit is contained in:
commit
9f7a07730a
35 changed files with 4441 additions and 3173 deletions
|
@ -5,7 +5,7 @@ npx lint-staged --concurrent false
|
|||
# npm run typecheck
|
||||
|
||||
# Checking for secrets
|
||||
# gitleaks protect --verbose --redact --staged
|
||||
gitleaks protect --verbose --redact --staged
|
||||
|
||||
# Checking dependencies' licenses
|
||||
npx license-checker --production --json --out licenses.json
|
||||
|
|
|
@ -76,7 +76,7 @@ class Server {
|
|||
};
|
||||
|
||||
this.lastErrors.push(chunk);
|
||||
Util.log('warn', chunk);
|
||||
console.log(chunk);
|
||||
});
|
||||
|
||||
this.cp.on('exit', () => {
|
||||
|
|
|
@ -112,13 +112,7 @@ class UpdateManager {
|
|||
};
|
||||
|
||||
checkUpdate (auto) {
|
||||
if (!this.isAllowed()) {
|
||||
return;
|
||||
};
|
||||
|
||||
Util.log('info', 'isUpdating: ' + this.isUpdating);
|
||||
|
||||
if (this.isUpdating) {
|
||||
if (!this.isAllowed() || this.isUpdating) {
|
||||
return;
|
||||
};
|
||||
|
||||
|
|
6644
package-lock.json
generated
6644
package-lock.json
generated
File diff suppressed because it is too large
Load diff
4
src/img/icon/widget/button/link.svg
Normal file
4
src/img/icon/widget/button/link.svg
Normal file
|
@ -0,0 +1,4 @@
|
|||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M13.8841 10.0056L15.3039 8.58581C16.3779 7.51187 16.3779 5.77067 15.3039 4.69672C14.23 3.62278 12.4888 3.62278 11.4148 4.69672L9.29351 6.81804C8.21957 7.89199 8.21957 9.63319 9.29351 10.7071C9.64823 11.0618 10.0757 11.2994 10.528 11.4198C10.492 11.8129 10.3236 12.1961 10.0227 12.497L9.76827 12.7514C9.2081 12.5454 8.68261 12.2176 8.23285 11.7678C6.57312 10.1081 6.57312 7.41711 8.23285 5.75738L10.3542 3.63606C12.0139 1.97633 14.7049 1.97633 16.3646 3.63606C18.0243 5.29579 18.0243 7.98674 16.3646 9.64647L14.2433 11.7678C14.1587 11.8523 14.0715 11.9326 13.9819 12.0085C14.0774 11.3424 14.0448 10.6615 13.8841 10.0056Z" fill="#252525"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.11783 9.99439L4.69803 11.4142C3.62409 12.4881 3.62409 14.2293 4.69803 15.3033C5.77198 16.3772 7.51318 16.3772 8.58712 15.3033L10.7084 13.182C11.7824 12.108 11.7824 10.3668 10.7084 9.29287C10.3537 8.93815 9.92621 8.70059 9.47399 8.5802C9.50992 8.18714 9.67833 7.80391 9.97924 7.50301L10.2337 7.24856C10.7939 7.45457 11.3193 7.78245 11.7691 8.23221C13.4288 9.89194 13.4288 12.5829 11.7691 14.2426L9.64778 16.3639C7.98805 18.0237 5.2971 18.0237 3.63737 16.3639C1.97765 14.7042 1.97765 12.0133 3.63737 10.3535L5.7587 8.23221C5.84323 8.14767 5.93044 8.06744 6.02005 7.99152C5.92459 8.65758 5.95718 9.33846 6.11783 9.99439Z" fill="#252525"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.4 KiB |
4
src/img/theme/dark/icon/widget/button/link.svg
Normal file
4
src/img/theme/dark/icon/widget/button/link.svg
Normal file
|
@ -0,0 +1,4 @@
|
|||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M13.8841 10.0056L15.3039 8.58581C16.3779 7.51187 16.3779 5.77067 15.3039 4.69672C14.23 3.62278 12.4888 3.62278 11.4148 4.69672L9.29351 6.81804C8.21957 7.89199 8.21957 9.63319 9.29351 10.7071C9.64823 11.0618 10.0757 11.2994 10.528 11.4198C10.492 11.8129 10.3236 12.1961 10.0227 12.497L9.76827 12.7514C9.2081 12.5454 8.68261 12.2176 8.23285 11.7678C6.57312 10.1081 6.57312 7.41711 8.23285 5.75738L10.3542 3.63606C12.0139 1.97633 14.7049 1.97633 16.3646 3.63606C18.0243 5.29579 18.0243 7.98674 16.3646 9.64647L14.2433 11.7678C14.1587 11.8523 14.0715 11.9326 13.9819 12.0085C14.0774 11.3424 14.0448 10.6615 13.8841 10.0056Z" fill="#f8f8f8"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.11783 9.99439L4.69803 11.4142C3.62409 12.4881 3.62409 14.2293 4.69803 15.3033C5.77198 16.3772 7.51318 16.3772 8.58712 15.3033L10.7084 13.182C11.7824 12.108 11.7824 10.3668 10.7084 9.29287C10.3537 8.93815 9.92621 8.70059 9.47399 8.5802C9.50992 8.18714 9.67833 7.80391 9.97924 7.50301L10.2337 7.24856C10.7939 7.45457 11.3193 7.78245 11.7691 8.23221C13.4288 9.89194 13.4288 12.5829 11.7691 14.2426L9.64778 16.3639C7.98805 18.0237 5.2971 18.0237 3.63737 16.3639C1.97765 14.7042 1.97765 12.0133 3.63737 10.3535L5.7587 8.23221C5.84323 8.14767 5.93044 8.06744 6.02005 7.99152C5.92459 8.65758 5.95718 9.33846 6.11783 9.99439Z" fill="#f8f8f8"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.4 KiB |
|
@ -132,6 +132,7 @@
|
|||
"commonNewSpace": "New Space",
|
||||
"commonSelectObject": "Select Object",
|
||||
"commonCopyLink": "Copy Link",
|
||||
"commonCopyDeeplink": "Copy Deeplink",
|
||||
"commonSidebar": "Sidebar",
|
||||
"commonLanguage": "Language",
|
||||
"commonSpelling": "Spelling",
|
||||
|
|
|
@ -68,7 +68,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
.block.blockMedia.isAudio > .wrapContent { border: 1px solid var(--color-shape-secondary); }
|
||||
.block.blockMedia.isAudio.withContent > .wrapContent { border: 1px solid var(--color-shape-secondary); }
|
||||
.block.blockMedia.isAudio > .wrapContent > .selectionTarget > .dropTarget > .focusable > .wrap { width: 100%; padding: 12px 12px 7px 14px; }
|
||||
|
||||
.block.blockMedia.isReadonly {
|
||||
|
@ -98,5 +98,5 @@
|
|||
.block.blockMedia.isPdf.withContent > .wrapContent > .selectionTarget.isSelectionSelected::after { border-radius: 0px; }
|
||||
.block.blockMedia.isImage.withContent > .wrapContent > .selectionTarget.isSelectionSelected::after { border-radius: 0px; }
|
||||
.block.blockMedia.isVideo.withContent > .wrapContent > .selectionTarget.isSelectionSelected::after { border-radius: 0px; }
|
||||
.block.blockMedia.isAudio.withContent > .wrapContent > .selectionTarget.isSelectionSelected::after { border-radius: 8px; }
|
||||
.block.blockMedia.isAudio.withContent > .wrapContent > .selectionTarget.isSelectionSelected::after { border-radius: 0px; }
|
||||
}
|
|
@ -26,36 +26,29 @@
|
|||
|
||||
.tabs, .sides.sidesFilter { padding: 0px 16px; }
|
||||
|
||||
.tabs { position: relative; }
|
||||
.tabs { position: relative; font-weight: 500; color: var(--color-control-active); height: 22px; }
|
||||
.tabs {
|
||||
.scrollWrap { overflow-y: hidden; overflow-x: auto; padding: 0px 0px 3px 0px; }
|
||||
.scrollWrap::-webkit-scrollbar { display: none; }
|
||||
|
||||
.scroll { display: flex; align-items: center; gap: 0px 12px; font-weight: 500; color: var(--color-control-active); }
|
||||
|
||||
.tab { white-space: nowrap; flex-shrink: 0; transition: $transitionAllCommon; }
|
||||
.tab.active, .tab:hover { color: var(--color-text-primary); }
|
||||
|
||||
.controls { position: absolute; top: -4px; left: 0px; width: 100%; display: flex; justify-content: space-between; }
|
||||
.controls {
|
||||
.side { width: 60px; position: relative; }
|
||||
.side.hide {
|
||||
.icon.arrow, .gradient { display: none; }
|
||||
.swiper { overflow: visible; position: absolute; left: 0px; top: 0px; width: 100%; padding: 0px 16px; }
|
||||
.swiper-slide { width: auto; }
|
||||
.swiper-button-prev, .swiper-button-next { width: 60px; height: 28px; position: absolute; top: -3px; z-index: 1; }
|
||||
.swiper-button-prev, .swiper-button-next {
|
||||
&::before {
|
||||
content: ''; width: 24px; height: 24px; display: block; position: absolute; left: 12px; top: 2px; z-index: 1;
|
||||
background-image: url('~img/arrow/sidebarObjectTab.svg'); background-size: 20px; background-repeat: no-repeat;
|
||||
border-radius: 6px; background-position: center;
|
||||
}
|
||||
|
||||
.icon.arrow { background-image: url('~img/arrow/sidebarObjectTab.svg'); position: absolute; z-index: 2; top: 1px; }
|
||||
.gradient { position: absolute; width: 100%; height: 28px; z-index: 1; top: 0px; pointer-events: none; }
|
||||
|
||||
.side.left {
|
||||
.icon.arrow { left: 16px; transform: rotateZ(180deg); }
|
||||
.gradient { left: 0px; background-image: linear-gradient(270deg, rgba(255,255,255,0) 0px, var(--color-bg-primary) 16px, var(--color-bg-primary) 100%); }
|
||||
}
|
||||
|
||||
.side.right {
|
||||
.icon.arrow { right: 16px; }
|
||||
.gradient { right: 0px; background-image: linear-gradient(90deg, rgba(255,255,255,0) 0px, var(--color-bg-primary) 16px, var(--color-bg-primary) 100%); }
|
||||
&::after {
|
||||
content: ''; width: 100%; height: 100%; display: block; position: absolute; left: 0px; top: 0px;
|
||||
background-image: linear-gradient(90deg, rgba(255,255,255,0) 0px, var(--color-bg-primary) 16px, var(--color-bg-primary) 100%);
|
||||
}
|
||||
&:hover::before { background-color: var(--color-shape-highlight-medium); }
|
||||
}
|
||||
.swiper-button-prev { left: -16px; transform: rotateZ(180deg); }
|
||||
.swiper-button-next { right: -16px; }
|
||||
.swiper-button-disabled { display: none; }
|
||||
}
|
||||
|
||||
.filter { padding: 0px 4px; border-radius: 6px; border: 1px solid var(--color-shape-secondary); }
|
||||
|
|
|
@ -37,6 +37,10 @@
|
|||
border-radius: 50%; opacity: 0; transition: opacity 0.2s $easeInQuint; opacity: 0;
|
||||
}
|
||||
|
||||
.item.isButton {
|
||||
.iconWrap { background-color: var(--color-shape-highlight-dark); }
|
||||
}
|
||||
|
||||
.item:hover, .item.hover { padding: 0px; }
|
||||
|
||||
.item.isActive::after { opacity: 1; }
|
||||
|
|
|
@ -98,6 +98,17 @@ html.printMedia {
|
|||
.block.blockText.textCode > .wrapContent > .selectionTarget > .dropTarget #value { white-space: pre-wrap; overflow-x: visible; }
|
||||
|
||||
.block.blockMedia.isAudio > .wrapContent { box-shadow: 0px 0px; }
|
||||
.block.blockMedia.isAudio {
|
||||
.mediaAudio {
|
||||
.controlsWrapper {
|
||||
.controls {
|
||||
.input-drag-horizontal {
|
||||
.back { width: 100% !important; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.block.blockDataview.isInline {
|
||||
.content {
|
||||
|
|
|
@ -61,6 +61,7 @@
|
|||
.item:hover::before { background: var(--color-shape-highlight-medium); }
|
||||
|
||||
.icon { flex-shrink: 0; }
|
||||
.icon.link { background-image: url('~img/icon/widget/button/link.svg'); }
|
||||
.icon.space { background-image: url('~img/icon/widget/button/member.svg'); }
|
||||
.icon.export { background-image: url('~img/icon/widget/button/export.svg'); }
|
||||
.icon.arrow { background-size: 6px 10px; background-image: url('~img/icon/popup/settings/forward.svg'); right: 12px; }
|
||||
|
|
|
@ -308,6 +308,7 @@
|
|||
.input.isReadonly { background: rgba(255, 255, 255, 0.03); }
|
||||
|
||||
.outer {
|
||||
.icon.link { background-image: url('#{$themePath}/icon/widget/button/link.svg'); }
|
||||
.icon.space { background-image: url('#{$themePath}/icon/widget/button/member.svg'); }
|
||||
.icon.export { background-image: url('#{$themePath}/icon/widget/button/export.svg'); }
|
||||
}
|
||||
|
|
|
@ -88,7 +88,8 @@ const BlockBookmark = observer(class BlockBookmark extends React.Component<I.Blo
|
|||
};
|
||||
|
||||
element = (
|
||||
<div
|
||||
<a
|
||||
href={url}
|
||||
className={cni.join(' ')}
|
||||
onClick={this.onClick}
|
||||
onMouseDown={this.onMouseDown}
|
||||
|
@ -107,7 +108,7 @@ const BlockBookmark = observer(class BlockBookmark extends React.Component<I.Blo
|
|||
<div className="side right">
|
||||
{picture ? <img src={S.Common.imageUrl(picture, 500)} className="img" /> : ''}
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
);
|
||||
break;
|
||||
};
|
||||
|
@ -196,6 +197,8 @@ const BlockBookmark = observer(class BlockBookmark extends React.Component<I.Blo
|
|||
return;
|
||||
};
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
const selection = S.Common.getRef('selectionProvider');
|
||||
const ids = selection?.get(I.SelectType.Block) || [];
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ const BlockTable = observer(class BlockTable extends React.Component<I.BlockComp
|
|||
rowId = '';
|
||||
cellId = '';
|
||||
data: any = {};
|
||||
frameResize = 0;
|
||||
|
||||
constructor (props: I.BlockComponent) {
|
||||
super(props);
|
||||
|
@ -165,6 +166,7 @@ const BlockTable = observer(class BlockTable extends React.Component<I.BlockComp
|
|||
unbind () {
|
||||
const { block } = this.props;
|
||||
$(window).off(`resize.${block.id}`);
|
||||
$(this.node).off('resizeInit resizeMove');
|
||||
};
|
||||
|
||||
rebind () {
|
||||
|
@ -173,6 +175,7 @@ const BlockTable = observer(class BlockTable extends React.Component<I.BlockComp
|
|||
|
||||
this.unbind();
|
||||
win.on(`resize.${block.id}`, () => raf(() => this.resize()));
|
||||
$(this.node).on('resizeInit resizeMove', e => this.resize());
|
||||
};
|
||||
|
||||
getData () {
|
||||
|
@ -1530,35 +1533,41 @@ const BlockTable = observer(class BlockTable extends React.Component<I.BlockComp
|
|||
const row = node.find(`#row-${rows[0].id}`);
|
||||
const obj = $(`#block-${block.id}`);
|
||||
|
||||
let width = J.Size.blockMenu + 10;
|
||||
let maxWidth = 0;
|
||||
let wrapperWidth = 0;
|
||||
|
||||
String(row.css('grid-template-columns') || '').split(' ').forEach(it => width += parseInt(it));
|
||||
|
||||
obj.css({ width: 'auto' });
|
||||
|
||||
if (parent.isPage() || parent.isLayoutDiv()) {
|
||||
const container = U.Common.getPageContainer(isPopup);
|
||||
|
||||
maxWidth = container.width() - PADDING;
|
||||
wrapperWidth = getWrapperWidth() + J.Size.blockMenu;
|
||||
|
||||
wrap.toggleClass('withScroll', width > maxWidth);
|
||||
width = Math.max(wrapperWidth, Math.min(maxWidth, width));
|
||||
|
||||
obj.css({
|
||||
width: (width >= wrapperWidth) ? width : 'auto',
|
||||
marginLeft: (width >= wrapperWidth) ? Math.min(0, (wrapperWidth - width) / 2) : '',
|
||||
});
|
||||
} else {
|
||||
const parentObj = $(`#block-${parent.id}`);
|
||||
if (parentObj.length) {
|
||||
maxWidth = parentObj.width() - J.Size.blockMenu;
|
||||
};
|
||||
|
||||
wrap.toggleClass('withScroll', width > maxWidth);
|
||||
if (this.frameResize) {
|
||||
raf.cancel(this.frameResize);
|
||||
};
|
||||
|
||||
this.frameResize = raf(() => {
|
||||
let width = J.Size.blockMenu + 10;
|
||||
let maxWidth = 0;
|
||||
let wrapperWidth = 0;
|
||||
|
||||
String(row.css('grid-template-columns') || '').split(' ').forEach(it => width += parseInt(it));
|
||||
|
||||
obj.css({ width: 'auto', marginLeft: 0 });
|
||||
|
||||
if (parent.isPage() || parent.isLayoutDiv()) {
|
||||
const container = U.Common.getPageContainer(isPopup);
|
||||
|
||||
maxWidth = container.width() - PADDING;
|
||||
wrapperWidth = getWrapperWidth() + J.Size.blockMenu;
|
||||
|
||||
wrap.toggleClass('withScroll', width > maxWidth);
|
||||
width = Math.max(wrapperWidth, Math.min(maxWidth, width));
|
||||
|
||||
obj.css({
|
||||
width: (width >= wrapperWidth) ? width : 'auto',
|
||||
marginLeft: (width >= wrapperWidth) ? Math.min(0, (wrapperWidth - width) / 2) : '',
|
||||
});
|
||||
} else {
|
||||
const parentObj = $(`#block-${parent.id}`);
|
||||
if (parentObj.length) {
|
||||
maxWidth = parentObj.width() - J.Size.blockMenu;
|
||||
};
|
||||
|
||||
wrap.toggleClass('withScroll', width > maxWidth);
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
});
|
||||
|
|
|
@ -2319,7 +2319,6 @@ const EditorPage = observer(class EditorPage extends React.Component<Props, Stat
|
|||
const cover = node.find('.block.blockCover');
|
||||
const pageContainer = U.Common.getPageContainer(isPopup);
|
||||
const header = pageContainer.find('#header');
|
||||
const root = S.Block.getLeaf(rootId, rootId);
|
||||
const scrollContainer = U.Common.getScrollContainer(isPopup);
|
||||
const hh = isPopup ? header.height() : J.Size.header;
|
||||
|
||||
|
@ -2393,6 +2392,8 @@ const EditorPage = observer(class EditorPage extends React.Component<Props, Stat
|
|||
this.refHeader.refDrag.setValue(v);
|
||||
this.refHeader.setPercent(v);
|
||||
};
|
||||
|
||||
$('.resizable').trigger('resizeInit');
|
||||
};
|
||||
|
||||
getWidth (w: number) {
|
||||
|
|
|
@ -358,6 +358,7 @@ const MenuBlockLink = observer(class MenuBlockLink extends React.Component<I.Men
|
|||
|
||||
if (item.itemId == 'link') {
|
||||
let url = filter;
|
||||
|
||||
if (item.isLocal && url && !url.match(/^file:/)) {
|
||||
url = `file://${url}`;
|
||||
};
|
||||
|
|
|
@ -34,7 +34,6 @@ const MenuBlockRelationEdit = observer(class MenuBlockRelationEdit extends React
|
|||
|
||||
const relation = this.getRelation();
|
||||
const root = S.Block.getLeaf(rootId, rootId);
|
||||
const isDate = this.format == I.RelationType.Date;
|
||||
const isObject = this.format == I.RelationType.Object;
|
||||
const isReadonly = this.isReadonly();
|
||||
|
||||
|
@ -59,8 +58,11 @@ const MenuBlockRelationEdit = observer(class MenuBlockRelationEdit extends React
|
|||
canDuplicate = canDelete = false;
|
||||
};
|
||||
};
|
||||
if (relation && Relation.isSystemWithoutUser(relation.relationKey)) {
|
||||
canDelete = false;
|
||||
|
||||
if (relation) {
|
||||
const allowedDelete = relation ? S.Block.isAllowed(relation.restrictions, [ I.RestrictionObject.Delete ]) : false;
|
||||
|
||||
canDelete = allowedDelete && Relation.isSystemWithoutUser(relation.relationKey);
|
||||
};
|
||||
|
||||
switch (ref) {
|
||||
|
@ -155,7 +157,7 @@ const MenuBlockRelationEdit = observer(class MenuBlockRelationEdit extends React
|
|||
<div className="section">
|
||||
<MenuItemVertical icon="expand" name={translate('commonOpenObject')} onClick={this.onOpen} onMouseEnter={this.menuClose} />
|
||||
{canDuplicate ? <MenuItemVertical icon="copy" name={translate('commonDuplicate')} onClick={this.onCopy} onMouseEnter={this.menuClose} /> : ''}
|
||||
{canDelete && unlinkText && !noUnlink ? <MenuItemVertical icon="unlink" name={unlinkText} onClick={this.onUnlink} onMouseEnter={this.menuClose} /> : ''}
|
||||
{unlinkText && !noUnlink ? <MenuItemVertical icon="unlink" name={unlinkText} onClick={this.onUnlink} onMouseEnter={this.menuClose} /> : ''}
|
||||
{canDelete ? <MenuItemVertical icon="remove" name={translate('commonDelete')} onClick={this.onRemove} onMouseEnter={this.menuClose} /> : ''}
|
||||
</div>
|
||||
) : ''}
|
||||
|
|
|
@ -1,206 +1,60 @@
|
|||
import * as React from 'react';
|
||||
import React, { forwardRef, useRef, useEffect, useImperativeHandle } from 'react';
|
||||
import $ from 'jquery';
|
||||
import { observer } from 'mobx-react';
|
||||
import arrayMove from 'array-move';
|
||||
import { AutoSizer, CellMeasurer, InfiniteLoader, List as VList, CellMeasurerCache } from 'react-virtualized';
|
||||
import { SortableContainer, SortableElement, SortableHandle } from 'react-sortable-hoc';
|
||||
import { DndContext, closestCenter, useSensors, useSensor, PointerSensor, KeyboardSensor } from '@dnd-kit/core';
|
||||
import { SortableContext, verticalListSortingStrategy, sortableKeyboardCoordinates, arrayMove, useSortable } from '@dnd-kit/sortable';
|
||||
import { restrictToVerticalAxis, restrictToFirstScrollableAncestor } from '@dnd-kit/modifiers';
|
||||
import { CSS } from '@dnd-kit/utilities';
|
||||
import { Icon, Switch, Cell } from 'Component';
|
||||
import { I, C, S, J, Dataview, keyboard, translate } from 'Lib';
|
||||
|
||||
const HEIGHT = 28;
|
||||
const LIMIT = 20;
|
||||
|
||||
const MenuGroupList = observer(class MenuGroupList extends React.Component<I.Menu> {
|
||||
|
||||
node: any = null;
|
||||
n = -1;
|
||||
top = 0;
|
||||
cache: any = {};
|
||||
refList: any = null;
|
||||
const MenuGroupList = observer(forwardRef<I.MenuRef, I.Menu>((props, ref) => {
|
||||
|
||||
constructor (props: I.Menu) {
|
||||
super(props);
|
||||
|
||||
this.onSortStart = this.onSortStart.bind(this);
|
||||
this.onSortEnd = this.onSortEnd.bind(this);
|
||||
this.onSwitch = this.onSwitch.bind(this);
|
||||
this.onScroll = this.onScroll.bind(this);
|
||||
const { param, getId, setActive, onKeyDown, position } = props;
|
||||
const { data } = param;
|
||||
const { readonly, rootId, blockId, getView } = data;
|
||||
const view = getView();
|
||||
const items = Dataview.getGroups(rootId, blockId, view.id, true);
|
||||
const block = S.Block.getLeaf(rootId, blockId);
|
||||
const allowedView = S.Block.checkFlags(rootId, blockId, [ I.RestrictionDataview.View ]);
|
||||
const cache = useRef({});
|
||||
const listRef = useRef(null);
|
||||
const top = useRef(0);
|
||||
const n = useRef(-1);
|
||||
const sensors = useSensors(
|
||||
useSensor(PointerSensor, { activationConstraint: { distance: 10 } }),
|
||||
useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates })
|
||||
);
|
||||
|
||||
cache.current = new CellMeasurerCache({
|
||||
fixedWidth: true,
|
||||
defaultHeight: HEIGHT,
|
||||
keyMapper: i => (items[i] || {}).id,
|
||||
});
|
||||
|
||||
const rebind = () => {
|
||||
unbind();
|
||||
$(window).on('keydown.menu', e => onKeyDownHandler(e));
|
||||
window.setTimeout(() => setActive(), 15);
|
||||
};
|
||||
|
||||
render () {
|
||||
const { param, getId } = this.props;
|
||||
const { data } = param;
|
||||
const { readonly, rootId, blockId, getView } = data;
|
||||
const items = this.getItems();
|
||||
const view = getView();
|
||||
const block = S.Block.getLeaf(rootId, blockId);
|
||||
const allowedView = S.Block.checkFlags(rootId, blockId, [ I.RestrictionDataview.View ]);
|
||||
|
||||
const Handle = SortableHandle(() => (
|
||||
<Icon className="dnd" />
|
||||
));
|
||||
|
||||
const Item = SortableElement((item: any) => {
|
||||
const canHide = allowedView;
|
||||
const canEdit = !readonly && allowedView;
|
||||
const subId = S.Record.getSubId(rootId, [ blockId, item.id ].join(':'));
|
||||
const cn = [ 'item' ];
|
||||
const head = {};
|
||||
|
||||
head[view.groupRelationKey] = item.value;
|
||||
|
||||
if (!canEdit) {
|
||||
cn.push('isReadonly');
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={node => this.node = node}
|
||||
id={'item-' + item.id}
|
||||
className={cn.join(' ')}
|
||||
onMouseEnter={e => this.onMouseEnter(e, item)}
|
||||
style={item.style}
|
||||
>
|
||||
{allowedView ? <Handle /> : ''}
|
||||
<span className="clickable">
|
||||
<Cell
|
||||
id={'menu-group-' + item.id}
|
||||
rootId={rootId}
|
||||
subId={subId}
|
||||
block={block}
|
||||
relationKey={view.groupRelationKey}
|
||||
viewType={I.ViewType.Board}
|
||||
getRecord={() => head}
|
||||
readonly={true}
|
||||
arrayLimit={4}
|
||||
withName={true}
|
||||
placeholder={translate('commonUncategorized')}
|
||||
/>
|
||||
</span>
|
||||
{canHide ? (
|
||||
<Switch
|
||||
value={!item.isHidden}
|
||||
onChange={(e: any, v: boolean) => { this.onSwitch(e, item, v); }}
|
||||
/>
|
||||
) : ''}
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
const rowRenderer = (param: any) => {
|
||||
const item: any = items[param.index];
|
||||
|
||||
return (
|
||||
<CellMeasurer
|
||||
key={param.key}
|
||||
parent={param.parent}
|
||||
cache={this.cache}
|
||||
columnIndex={0}
|
||||
rowIndex={param.index}
|
||||
>
|
||||
<Item key={item.id} {...item} index={param.index} style={param.style} />
|
||||
</CellMeasurer>
|
||||
);
|
||||
};
|
||||
|
||||
const List = SortableContainer(() => (
|
||||
<div className="items">
|
||||
<InfiniteLoader
|
||||
rowCount={items.length}
|
||||
loadMoreRows={() => {}}
|
||||
isRowLoaded={() => true}
|
||||
threshold={LIMIT}
|
||||
>
|
||||
{({ onRowsRendered }) => (
|
||||
<AutoSizer className="scrollArea">
|
||||
{({ width, height }) => (
|
||||
<VList
|
||||
ref={ref => this.refList = ref}
|
||||
width={width}
|
||||
height={height}
|
||||
deferredMeasurmentCache={this.cache}
|
||||
rowCount={items.length}
|
||||
rowHeight={HEIGHT}
|
||||
rowRenderer={rowRenderer}
|
||||
onRowsRendered={onRowsRendered}
|
||||
overscanRowCount={LIMIT}
|
||||
onScroll={this.onScroll}
|
||||
scrollToAlignment="center"
|
||||
/>
|
||||
)}
|
||||
</AutoSizer>
|
||||
)}
|
||||
</InfiniteLoader>
|
||||
</div>
|
||||
));
|
||||
|
||||
return (
|
||||
<div className="wrap">
|
||||
<List
|
||||
axis="y"
|
||||
lockAxis="y"
|
||||
lockToContainerEdges={true}
|
||||
transitionDuration={150}
|
||||
distance={10}
|
||||
onSortStart={this.onSortStart}
|
||||
onSortEnd={this.onSortEnd}
|
||||
useDragHandle={true}
|
||||
helperClass="isDragging"
|
||||
helperContainer={() => $(`#${getId()} .items`).get(0)}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
const items = this.getItems();
|
||||
|
||||
this.rebind();
|
||||
this.resize();
|
||||
|
||||
this.cache = new CellMeasurerCache({
|
||||
fixedWidth: true,
|
||||
defaultHeight: HEIGHT,
|
||||
keyMapper: i => (items[i] || {}).id,
|
||||
});
|
||||
};
|
||||
|
||||
componentDidUpdate () {
|
||||
this.resize();
|
||||
this.rebind();
|
||||
|
||||
this.props.setActive(null, true);
|
||||
this.props.position();
|
||||
|
||||
if (this.refList && this.top) {
|
||||
this.refList.scrollToPosition(this.top);
|
||||
};
|
||||
};
|
||||
|
||||
componentWillUnmount () {
|
||||
this.unbind();
|
||||
S.Menu.closeAll(J.Menu.cell);
|
||||
};
|
||||
|
||||
rebind () {
|
||||
this.unbind();
|
||||
$(window).on('keydown.menu', e => this.onKeyDown(e));
|
||||
window.setTimeout(() => this.props.setActive(), 15);
|
||||
};
|
||||
|
||||
unbind () {
|
||||
const unbind = () => {
|
||||
$(window).off('keydown.menu');
|
||||
};
|
||||
|
||||
onKeyDown (e: any) {
|
||||
const onKeyDownHandler = (e: any) => {
|
||||
const item = items[n.current];
|
||||
|
||||
let ret = false;
|
||||
const items = this.getItems();
|
||||
const item = items[this.n];
|
||||
|
||||
keyboard.shortcut('space', e, (pressed: string) => {
|
||||
e.preventDefault();
|
||||
|
||||
this.onSwitch(e, item, !item.isVisible);
|
||||
onSwitch(e, item, !item.isVisible);
|
||||
ret = true;
|
||||
});
|
||||
|
||||
|
@ -208,80 +62,215 @@ const MenuGroupList = observer(class MenuGroupList extends React.Component<I.Men
|
|||
return;
|
||||
};
|
||||
|
||||
this.props.onKeyDown(e);
|
||||
onKeyDown(e);
|
||||
};
|
||||
|
||||
onMouseEnter (e: any, item: any) {
|
||||
const onMouseEnter = (e: any, item: any) => {
|
||||
if (!keyboard.isMouseDisabled) {
|
||||
this.props.setActive(item, false);
|
||||
setActive(item, false);
|
||||
};
|
||||
};
|
||||
|
||||
onSortStart () {
|
||||
const onSortStart = () => {
|
||||
keyboard.disableSelection(true);
|
||||
};
|
||||
|
||||
onSortEnd (result: any) {
|
||||
const { oldIndex, newIndex } = result;
|
||||
const { param } = this.props;
|
||||
const { data } = param;
|
||||
const { rootId, blockId } = data;
|
||||
const onSortEnd = (result: any) => {
|
||||
const { active, over } = result;
|
||||
const ids = items.map(it => it.id);
|
||||
const oldIndex = ids.indexOf(active.id);
|
||||
const newIndex = ids.indexOf(over.id);
|
||||
|
||||
S.Record.groupsSet(rootId, blockId, arrayMove(this.getItems(), oldIndex, newIndex));
|
||||
this.save();
|
||||
S.Record.groupsSet(rootId, blockId, arrayMove(items, oldIndex, newIndex));
|
||||
save();
|
||||
|
||||
keyboard.disableSelection(false);
|
||||
};
|
||||
|
||||
onSwitch (e: any, item: any, v: boolean) {
|
||||
const groups = this.getItems();
|
||||
const group = groups.find(it => it.id == item.id);
|
||||
const onSwitch = (e: any, item: any, v: boolean) => {
|
||||
const current = items.find(it => it.id == item.id);
|
||||
|
||||
group.isHidden = !v;
|
||||
this.save();
|
||||
current.isHidden = !v;
|
||||
save();
|
||||
};
|
||||
|
||||
save () {
|
||||
const { param } = this.props;
|
||||
const { data } = param;
|
||||
const { rootId, blockId, getView } = data;
|
||||
const save = () => {
|
||||
const view = getView();
|
||||
const groups = this.getItems();
|
||||
const items = S.Record.getGroups(rootId, blockId);
|
||||
const update: any[] = [];
|
||||
|
||||
groups.forEach((it: any, i: number) => {
|
||||
items.forEach((it: any, i: number) => {
|
||||
update.push({ ...it, groupId: it.id, index: i });
|
||||
});
|
||||
|
||||
S.Record.groupsSet(rootId, blockId, groups);
|
||||
S.Record.groupsSet(rootId, blockId, items);
|
||||
Dataview.groupUpdate(rootId, blockId, view.id, update);
|
||||
C.BlockDataviewGroupOrderUpdate(rootId, blockId, { viewId: view.id, groups: update });
|
||||
};
|
||||
|
||||
onScroll ({ scrollTop }) {
|
||||
const onScroll = ({ scrollTop }) => {
|
||||
if (scrollTop) {
|
||||
this.top = scrollTop;
|
||||
top.current = scrollTop;
|
||||
};
|
||||
};
|
||||
|
||||
getItems () {
|
||||
const { param } = this.props;
|
||||
const { data } = param;
|
||||
const { rootId, blockId } = data;
|
||||
|
||||
return S.Record.getGroups(rootId, blockId);
|
||||
};
|
||||
|
||||
resize () {
|
||||
const { getId, position } = this.props;
|
||||
const items = this.getItems();
|
||||
const resize = () => {
|
||||
const obj = $(`#${getId()} .content`);
|
||||
const height = Math.max(HEIGHT * 2, Math.min(360, items.length * HEIGHT + 16));
|
||||
|
||||
obj.css({ height });
|
||||
position();
|
||||
};
|
||||
|
||||
const Handle = () => (
|
||||
<Icon className="dnd" />
|
||||
);
|
||||
|
||||
const Item = (item: any) => {
|
||||
const { attributes, listeners, setNodeRef, transform, transition } = useSortable({ id: item.id, disabled: !allowedView });
|
||||
const canHide = allowedView;
|
||||
const canEdit = !readonly && allowedView;
|
||||
const subId = S.Record.getSubId(rootId, [ blockId, item.id ].join(':'));
|
||||
const cn = [ 'item' ];
|
||||
const head = {};
|
||||
const style = {
|
||||
transform: CSS.Transform.toString(transform),
|
||||
transition,
|
||||
};
|
||||
|
||||
head[view.groupRelationKey] = item.value;
|
||||
|
||||
if (!canEdit) {
|
||||
cn.push('isReadonly');
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
id={'item-' + item.id}
|
||||
className={cn.join(' ')}
|
||||
onMouseEnter={e => onMouseEnter(e, item)}
|
||||
ref={setNodeRef}
|
||||
{...attributes}
|
||||
{...listeners}
|
||||
style={style}
|
||||
>
|
||||
{allowedView ? <Icon className="dnd" /> : ''}
|
||||
<span className="clickable">
|
||||
<Cell
|
||||
id={'menu-group-' + item.id}
|
||||
rootId={rootId}
|
||||
subId={subId}
|
||||
block={block}
|
||||
relationKey={view.groupRelationKey}
|
||||
viewType={I.ViewType.Board}
|
||||
getRecord={() => head}
|
||||
readonly={true}
|
||||
arrayLimit={4}
|
||||
withName={true}
|
||||
placeholder={translate('commonUncategorized')}
|
||||
/>
|
||||
</span>
|
||||
{canHide ? (
|
||||
<Switch
|
||||
value={!item.isHidden}
|
||||
onChange={(e: any, v: boolean) => onSwitch(e, item, v)}
|
||||
/>
|
||||
) : ''}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
});
|
||||
const rowRenderer = (param: any) => {
|
||||
const item: any = items[param.index];
|
||||
|
||||
return (
|
||||
<CellMeasurer
|
||||
key={param.key}
|
||||
parent={param.parent}
|
||||
cache={cache.current}
|
||||
columnIndex={0}
|
||||
rowIndex={param.index}
|
||||
>
|
||||
<Item key={item.id} {...item} index={param.index} style={param.style} />
|
||||
</CellMeasurer>
|
||||
);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
rebind();
|
||||
resize();
|
||||
|
||||
return () => {
|
||||
unbind();
|
||||
S.Menu.closeAll(J.Menu.cell);
|
||||
};
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
resize();
|
||||
rebind();
|
||||
setActive(null, true);
|
||||
position();
|
||||
|
||||
if (top.current) {
|
||||
listRef.current?.scrollToPosition(top.current);
|
||||
};
|
||||
});
|
||||
|
||||
useImperativeHandle(ref, () => ({
|
||||
rebind,
|
||||
unbind,
|
||||
getItems: () => items,
|
||||
getIndex: () => n.current,
|
||||
setIndex: (i: number) => n.current = i,
|
||||
}), []);
|
||||
|
||||
return (
|
||||
<div className="wrap">
|
||||
<DndContext
|
||||
sensors={sensors}
|
||||
collisionDetection={closestCenter}
|
||||
onDragStart={onSortStart}
|
||||
onDragEnd={onSortEnd}
|
||||
modifiers={[ restrictToVerticalAxis, restrictToFirstScrollableAncestor ]}
|
||||
>
|
||||
<SortableContext
|
||||
items={items.map((item) => item.id)}
|
||||
strategy={verticalListSortingStrategy}
|
||||
>
|
||||
<div className="items">
|
||||
<InfiniteLoader
|
||||
rowCount={items.length}
|
||||
loadMoreRows={() => {}}
|
||||
isRowLoaded={() => true}
|
||||
threshold={LIMIT}
|
||||
>
|
||||
{({ onRowsRendered }) => (
|
||||
<AutoSizer className="scrollArea">
|
||||
{({ width, height }) => (
|
||||
<VList
|
||||
ref={listRef}
|
||||
width={width}
|
||||
height={height}
|
||||
deferredMeasurmentCache={cache.current}
|
||||
rowCount={items.length}
|
||||
rowHeight={HEIGHT}
|
||||
rowRenderer={rowRenderer}
|
||||
onRowsRendered={onRowsRendered}
|
||||
overscanRowCount={LIMIT}
|
||||
onScroll={onScroll}
|
||||
scrollToAlignment="center"
|
||||
/>
|
||||
)}
|
||||
</AutoSizer>
|
||||
)}
|
||||
</InfiniteLoader>
|
||||
</div>
|
||||
</SortableContext>
|
||||
</DndContext>
|
||||
</div>
|
||||
);
|
||||
|
||||
}));
|
||||
|
||||
export default MenuGroupList;
|
|
@ -119,7 +119,7 @@ class MenuObject extends React.Component<I.Menu> {
|
|||
let history = { id: 'history', name: translate('commonVersionHistory'), caption: keyboard.getCaption('history') };
|
||||
let createWidget = { id: 'createWidget', icon: 'createWidget', name: translate('menuObjectCreateWidget') };
|
||||
let pageCopy = { id: 'pageCopy', icon: 'copy', name: translate('commonDuplicate') };
|
||||
let pageLink = { id: 'pageLink', icon: 'link', name: translate('commonCopyLink') };
|
||||
let pageLink = { id: 'pageLink', icon: 'link', name: translate('commonCopyDeeplink') };
|
||||
let pageReload = { id: 'pageReload', icon: 'reload', name: translate('menuObjectReloadFromSource') };
|
||||
let pageExport = { id: 'pageExport', icon: 'export', name: translate('menuObjectExport') };
|
||||
let downloadFile = { id: 'downloadFile', icon: 'download', name: translate('commonDownload') };
|
||||
|
@ -486,24 +486,7 @@ class MenuObject extends React.Component<I.Menu> {
|
|||
};
|
||||
|
||||
case 'pageLink': {
|
||||
const link = `${J.Constant.protocol}://${U.Object.universalRoute(object)}`;
|
||||
const cb = (link: string) => {
|
||||
U.Common.copyToast(translate('commonLink'), link);
|
||||
analytics.event('CopyLink', { route });
|
||||
};
|
||||
|
||||
if (space.isShared) {
|
||||
U.Space.getInvite(S.Common.space, (cid: string, key: string) => {
|
||||
if (cid && key) {
|
||||
cb(link + `&cid=${cid}&key=${key}`);
|
||||
} else {
|
||||
cb(link);
|
||||
};
|
||||
});
|
||||
} else {
|
||||
cb(link);
|
||||
};
|
||||
|
||||
U.Object.copyLink(object, space, 'deeplink', '');
|
||||
break;
|
||||
};
|
||||
|
||||
|
|
|
@ -25,6 +25,11 @@ const MenuPublish = observer(forwardRef<I.MenuRef, I.Menu>((props, ref) => {
|
|||
const domain = U.Space.getPublishDomain();
|
||||
const url = U.Space.getPublishUrl(slug);
|
||||
const items = [
|
||||
{
|
||||
id: 'link',
|
||||
name: translate('commonCopyLink'),
|
||||
onClick: () => U.Object.copyLink(object, space, 'web', ''),
|
||||
},
|
||||
(!space.isPersonal ?
|
||||
{
|
||||
id: 'space',
|
||||
|
|
|
@ -155,12 +155,16 @@ const Page = observer(class Page extends React.Component<I.PageComponent> {
|
|||
ret.params.spaceId = data.spaceId;
|
||||
ret.params.cid = data.cid;
|
||||
ret.params.key = data.key;
|
||||
ret.params.route = data.route;
|
||||
};
|
||||
|
||||
// Invite route
|
||||
if (pathname.match(/^\/invite/)) {
|
||||
ret.params.page = 'main';
|
||||
ret.params.action = 'invite';
|
||||
ret.params.cid = data.cid;
|
||||
ret.params.key = data.key;
|
||||
ret.params.route = data.route;
|
||||
};
|
||||
|
||||
// Membership route
|
||||
|
|
|
@ -8,27 +8,27 @@ interface PageMainInviteRefProps {
|
|||
|
||||
const PageMainInvite = forwardRef<PageMainInviteRefProps, I.PageComponent>((props, ref) => {
|
||||
|
||||
const { isPopup } = props;
|
||||
const { isPopup, match } = props;
|
||||
const nodeRef = useRef(null);
|
||||
const frameRef = useRef(null);
|
||||
const cid = useRef('');
|
||||
const key = useRef('');
|
||||
const cidRef = useRef('');
|
||||
const keyRef = useRef('');
|
||||
const [ error, setError ] = useState('');
|
||||
|
||||
const init = () => {
|
||||
const data = U.Common.searchParam(U.Router.history.location.search);
|
||||
const { cid, key, route } = match.params || {};
|
||||
|
||||
if ((cid.current == data.cid) && (key.current == data.key)) {
|
||||
if ((cidRef.current == cid) && (keyRef.current == key)) {
|
||||
return;
|
||||
};
|
||||
|
||||
cid.current = data.cid;
|
||||
key.current = data.key;
|
||||
cidRef.current = cid;
|
||||
keyRef.current = key;
|
||||
|
||||
if (!data.cid || !data.key) {
|
||||
if (!cid || !key) {
|
||||
setError(translate('pageMainInviteErrorData'));
|
||||
} else {
|
||||
C.SpaceInviteView(data.cid, data.key, (message: any) => {
|
||||
C.SpaceInviteView(cid, key, (message: any) => {
|
||||
U.Space.openDashboard({ replace: true });
|
||||
|
||||
S.Popup.closeAll(null, () => {
|
||||
|
@ -75,10 +75,24 @@ const PageMainInvite = forwardRef<PageMainInviteRefProps, I.PageComponent>((prop
|
|||
},
|
||||
});
|
||||
} else {
|
||||
S.Popup.open('inviteRequest', { data: { invite: message, ...data } });
|
||||
S.Popup.open('inviteRequest', {
|
||||
data: {
|
||||
invite: message,
|
||||
cid,
|
||||
key,
|
||||
route,
|
||||
},
|
||||
});
|
||||
};
|
||||
} else {
|
||||
S.Popup.open('inviteRequest', { data: { invite: message, ...data } });
|
||||
S.Popup.open('inviteRequest', {
|
||||
data: {
|
||||
invite: message,
|
||||
cid,
|
||||
key,
|
||||
route,
|
||||
},
|
||||
});
|
||||
};
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,17 +1,18 @@
|
|||
import React, { forwardRef, useEffect } from 'react';
|
||||
import { I, C, U } from 'Lib';
|
||||
import { I, C, U, analytics } from 'Lib';
|
||||
|
||||
const PageMainObject = forwardRef<{}, I.PageComponent>((props, ref) => {
|
||||
|
||||
const { match } = props;
|
||||
|
||||
useEffect(() => {
|
||||
const { id, spaceId, cid, key } = match.params || {};
|
||||
const { id, spaceId, cid, key, route } = match.params || {};
|
||||
const space = U.Space.getSpaceviewBySpaceId(spaceId);
|
||||
|
||||
// Redirect to invite page when invite parameters are present
|
||||
if ((!space || !space.isAccountActive) && cid && key) {
|
||||
U.Router.go(`/main/invite/?cid=${cid}&key=${key}`, { replace: true });
|
||||
analytics.event('OpenObjectByLink', { route, type: 'Invite' });
|
||||
return;
|
||||
};
|
||||
|
||||
|
@ -29,7 +30,10 @@ const PageMainObject = forwardRef<{}, I.PageComponent>((props, ref) => {
|
|||
return;
|
||||
};
|
||||
|
||||
U.Object.openRoute(item.details);
|
||||
const object = item.details;
|
||||
|
||||
U.Object.openRoute(object);
|
||||
analytics.event('OpenObjectByLink', { route, objectType: object.type, type: 'Object' });
|
||||
});
|
||||
|
||||
}, []);
|
||||
|
|
|
@ -50,6 +50,14 @@ const PopupInviteRequest = observer(class PopupInviteRequest extends React.Compo
|
|||
);
|
||||
};
|
||||
|
||||
componentDidMount(): void {
|
||||
const { param } = this.props;
|
||||
const { data } = param;
|
||||
const { route } = data;
|
||||
|
||||
analytics.event('ScreenInviteRequest', { route });
|
||||
};
|
||||
|
||||
onRequest () {
|
||||
const { param, close } = this.props;
|
||||
const { account } = S.Auth;
|
||||
|
|
|
@ -31,6 +31,8 @@ const PreviewDefault = observer(forwardRef<{}, Props>((props, ref) => {
|
|||
};
|
||||
|
||||
const load = () => {
|
||||
console.log(rootId, idRef.current);
|
||||
|
||||
if (isLoading || (idRef.current == rootId)) {
|
||||
return;
|
||||
};
|
||||
|
@ -49,6 +51,8 @@ const PreviewDefault = observer(forwardRef<{}, Props>((props, ref) => {
|
|||
};
|
||||
|
||||
useEffect(() => {
|
||||
console.log(initialObject);
|
||||
|
||||
if (initialObject) {
|
||||
setObject(initialObject);
|
||||
};
|
||||
|
|
|
@ -13,7 +13,7 @@ const PreviewIndex = observer(forwardRef(() => {
|
|||
const polygonRef = useRef(null);
|
||||
const { preview } = S.Common;
|
||||
const { type, target, object: initialObject, marks, range, noUnlink, noEdit, x, y, width, height, onChange } = preview;
|
||||
const [ object, setObject ] = useState(initialObject || {});
|
||||
const [ object, setObject ] = useState(initialObject);
|
||||
const cn = [ 'previewWrapper' ];
|
||||
const win = $(window);
|
||||
|
||||
|
|
|
@ -2,7 +2,9 @@ import * as React from 'react';
|
|||
import { observer } from 'mobx-react';
|
||||
import { AutoSizer, CellMeasurer, InfiniteLoader, List, CellMeasurerCache } from 'react-virtualized';
|
||||
import { Title, Filter, Icon, Button, Label, EmptySearch } from 'Component';
|
||||
import { I, U, J, S, translate, Storage, sidebar, keyboard, analytics, Action, Relation } from 'Lib';
|
||||
import { I, U, J, S, translate, Storage, sidebar, keyboard, analytics, Action } from 'Lib';
|
||||
import { Swiper, SwiperSlide } from 'swiper/react';
|
||||
import { Mousewheel, Navigation } from 'swiper/modules';
|
||||
|
||||
import Item from './allObject/item';
|
||||
|
||||
|
@ -23,6 +25,7 @@ const SidebarPageObject = observer(class SidebarPageObject extends React.Compone
|
|||
node = null;
|
||||
refFilter = null;
|
||||
refList = null;
|
||||
refSwiper = null;
|
||||
cache: any = {};
|
||||
offset = 0;
|
||||
sortId: I.SortId = I.SortId.Updated;
|
||||
|
@ -40,6 +43,7 @@ const SidebarPageObject = observer(class SidebarPageObject extends React.Compone
|
|||
tabIndex = 0;
|
||||
tabArray = [];
|
||||
x = 0;
|
||||
top = 0;
|
||||
|
||||
constructor (props: any) {
|
||||
super(props);
|
||||
|
@ -50,13 +54,10 @@ const SidebarPageObject = observer(class SidebarPageObject extends React.Compone
|
|||
this.onFilterClear = this.onFilterClear.bind(this);
|
||||
this.onAdd = this.onAdd.bind(this);
|
||||
this.onScroll = this.onScroll.bind(this);
|
||||
this.onTabOver = this.onTabOver.bind(this);
|
||||
this.onTabLeave = this.onTabLeave.bind(this);
|
||||
this.onTabScroll = this.onTabScroll.bind(this);
|
||||
this.loadMoreRows = this.loadMoreRows.bind(this);
|
||||
};
|
||||
|
||||
render() {
|
||||
render () {
|
||||
const { isLoading } = this.state;
|
||||
const items = this.getItems();
|
||||
const isAllowedObject = this.isAllowedObject();
|
||||
|
@ -125,25 +126,26 @@ const SidebarPageObject = observer(class SidebarPageObject extends React.Compone
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
id="tabs"
|
||||
className="tabs"
|
||||
onMouseEnter={this.onTabOver}
|
||||
onMouseLeave={this.onTabLeave}
|
||||
>
|
||||
<div
|
||||
className="scrollWrap"
|
||||
onScroll={this.onTabScroll}
|
||||
<div id="tabs" className="tabs">
|
||||
<Swiper
|
||||
onSwiper={swiper => this.refSwiper = swiper}
|
||||
direction={'horizontal'}
|
||||
slidesPerView={'auto'}
|
||||
slidesPerGroupAuto={true}
|
||||
spaceBetween={12}
|
||||
mousewheel={true}
|
||||
navigation={true}
|
||||
modules={[ Mousewheel, Navigation ]}
|
||||
>
|
||||
<div className="scroll">
|
||||
{typeOptions.map((it: any, i: number) => {
|
||||
const cn = [ 'tab' ];
|
||||
{typeOptions.map((it: any, i: number) => {
|
||||
const cn = [ 'tab' ];
|
||||
|
||||
if (this.type == it.id) {
|
||||
cn.push('active');
|
||||
};
|
||||
if (this.type == it.id) {
|
||||
cn.push('active');
|
||||
};
|
||||
|
||||
return (
|
||||
return (
|
||||
<SwiperSlide key={it.id}>
|
||||
<div
|
||||
key={it.id}
|
||||
className={cn.join(' ')}
|
||||
|
@ -151,22 +153,10 @@ const SidebarPageObject = observer(class SidebarPageObject extends React.Compone
|
|||
>
|
||||
{it.name}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="controls">
|
||||
<div className="side left">
|
||||
<Icon className="arrow withBackground" onClick={() => this.onTabArrow(-1)} />
|
||||
<div className="gradient" />
|
||||
</div>
|
||||
|
||||
<div className="side right">
|
||||
<Icon className="arrow withBackground" onClick={() => this.onTabArrow(1)} />
|
||||
<div className="gradient" />
|
||||
</div>
|
||||
</div>
|
||||
</SwiperSlide>
|
||||
);
|
||||
})}
|
||||
</Swiper>
|
||||
</div>
|
||||
|
||||
<div className="sides sidesFilter">
|
||||
|
@ -201,7 +191,14 @@ const SidebarPageObject = observer(class SidebarPageObject extends React.Compone
|
|||
threshold={LIMIT}
|
||||
>
|
||||
{({ onRowsRendered }) => (
|
||||
<AutoSizer className="scrollArea">
|
||||
<AutoSizer
|
||||
className="scrollArea"
|
||||
onResize={() => {
|
||||
if (this.top) {
|
||||
this.refList?.scrollToPosition(this.top);
|
||||
};
|
||||
}}
|
||||
>
|
||||
{({ width, height }) => (
|
||||
<List
|
||||
ref={ref => this.refList = ref}
|
||||
|
@ -235,7 +232,7 @@ const SidebarPageObject = observer(class SidebarPageObject extends React.Compone
|
|||
this.load(true);
|
||||
|
||||
const idx = Math.max(0, this.getTypeOptions().findIndex(it => it.id == this.type));
|
||||
this.scrollToTab(idx, false);
|
||||
this.refSwiper?.slideTo(idx);
|
||||
|
||||
analytics.event('ScreenLibrary');
|
||||
};
|
||||
|
@ -250,7 +247,6 @@ const SidebarPageObject = observer(class SidebarPageObject extends React.Compone
|
|||
});
|
||||
|
||||
this.setActive(items[this.n]);
|
||||
this.checkTabButtons();
|
||||
};
|
||||
|
||||
componentWillUnmount(): void {
|
||||
|
@ -790,7 +786,10 @@ const SidebarPageObject = observer(class SidebarPageObject extends React.Compone
|
|||
};
|
||||
};
|
||||
|
||||
onScroll () {
|
||||
onScroll ({ scrollTop }) {
|
||||
if (scrollTop) {
|
||||
this.top = scrollTop;
|
||||
};
|
||||
this.renderSelection();
|
||||
};
|
||||
|
||||
|
@ -985,123 +984,6 @@ const SidebarPageObject = observer(class SidebarPageObject extends React.Compone
|
|||
return [ I.SortId.Created, I.SortId.Updated ].includes(this.sortId);
|
||||
};
|
||||
|
||||
onTabOver () {
|
||||
const node = $(this.node);
|
||||
const tabs = node.find('#tabs');
|
||||
const controls = tabs.find('.controls');
|
||||
const sideLeft = controls.find('.side.left');
|
||||
const sideRight = controls.find('.side.right');
|
||||
const width = tabs.outerWidth();
|
||||
const cx = tabs.offset().left;
|
||||
const half = width / 2;
|
||||
|
||||
this.onTabLeave();
|
||||
|
||||
const check = () => {
|
||||
const x = keyboard.mouse.page.x - cx;
|
||||
|
||||
if ((x >= 0) && (x <= half)) {
|
||||
sideLeft.addClass('hover');
|
||||
};
|
||||
if ((x > half) && (x <= width)) {
|
||||
sideRight.addClass('hover');
|
||||
};
|
||||
};
|
||||
|
||||
check();
|
||||
$(window).off('mousemove.sidebarObject').on('mousemove.sidebarObject', e => check());
|
||||
};
|
||||
|
||||
onTabLeave () {
|
||||
const node = $(this.node);
|
||||
const tabs = node.find('#tabs');
|
||||
const controls = tabs.find('.controls');
|
||||
const sideLeft = controls.find('.side.left');
|
||||
const sideRight = controls.find('.side.right');
|
||||
|
||||
sideLeft.removeClass('hover');
|
||||
sideRight.removeClass('hover');
|
||||
|
||||
$(window).off('mousemove.sidebarObject');
|
||||
};
|
||||
|
||||
onTabArrow (dir: number) {
|
||||
this.tabIndex += dir;
|
||||
this.checkTabIndex();
|
||||
this.scrollToTab(this.tabIndex, true);
|
||||
};
|
||||
|
||||
onTabScroll () {
|
||||
const node = $(this.node);
|
||||
const tabs = node.find('#tabs');
|
||||
const scroll = tabs.find('.scrollWrap');
|
||||
|
||||
this.x = scroll.scrollLeft();
|
||||
|
||||
for (const item of this.tabArray) {
|
||||
if ((this.x >= item.x) && (this.x <= item.x + item.w)) {
|
||||
this.tabIndex = item.i;
|
||||
break;
|
||||
};
|
||||
};
|
||||
|
||||
this.checkTabX();
|
||||
this.checkTabIndex();
|
||||
this.checkTabButtons();
|
||||
};
|
||||
|
||||
scrollToTab (idx: number, animate: boolean) {
|
||||
const node = $(this.node);
|
||||
const tabs = node.find('#tabs');
|
||||
const scroll = tabs.find('.scrollWrap');
|
||||
|
||||
this.fillTabArray();
|
||||
|
||||
this.tabIndex = idx;
|
||||
this.checkTabIndex();
|
||||
|
||||
this.x = this.tabArray[this.tabIndex].x;
|
||||
this.checkTabX();
|
||||
|
||||
if (animate) {
|
||||
scroll.animate({ scrollLeft: this.x }, 200);
|
||||
} else {
|
||||
scroll.scrollLeft(this.x);
|
||||
};
|
||||
this.checkTabButtons();
|
||||
};
|
||||
|
||||
checkTabX () {
|
||||
const node = $(this.node);
|
||||
const tabs = node.find('#tabs');
|
||||
const scroll = tabs.find('.scroll');
|
||||
const max = this.getMaxWidth();
|
||||
const sw = scroll.width();
|
||||
|
||||
this.x = Math.floor(this.x);
|
||||
this.x = Math.max(0, this.x);
|
||||
this.x = Math.min(max - sw, this.x);
|
||||
};
|
||||
|
||||
checkTabIndex () {
|
||||
this.tabIndex = Math.max(0, this.tabIndex);
|
||||
this.tabIndex = Math.min(this.tabArray.length - 1, this.tabIndex);
|
||||
};
|
||||
|
||||
checkTabButtons () {
|
||||
const node = $(this.node);
|
||||
const tabs = node.find('#tabs');
|
||||
const scroll = tabs.find('.scroll');
|
||||
const controls = node.find('.controls');
|
||||
const sideLeft = controls.find('.side.left');
|
||||
const sideRight = controls.find('.side.right');
|
||||
const max = this.getMaxWidth();
|
||||
const sw = scroll.width();
|
||||
|
||||
sideLeft.toggleClass('hide', this.x <= 0);
|
||||
sideRight.toggleClass('hide', this.x >= max - sw - 1);
|
||||
};
|
||||
|
||||
getMaxWidth () {
|
||||
const node = $(this.node);
|
||||
const tabs = node.find('#tabs');
|
||||
|
@ -1130,10 +1012,6 @@ const SidebarPageObject = observer(class SidebarPageObject extends React.Compone
|
|||
};
|
||||
};
|
||||
|
||||
resize () {
|
||||
this.scrollToTab(0, false);
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
export default SidebarPageObject;
|
||||
|
|
|
@ -68,7 +68,7 @@ const SidebarSectionTypeRelation = observer(forwardRef<I.SidebarSectionRef, I.Si
|
|||
|
||||
const onAdd = (e: any, id: string) => {
|
||||
const list = lists.find(it => it.id == id);
|
||||
const keys = lists.reduce((acc, it) => acc.concat(it.data.map(it => it.relationKey)), []);
|
||||
const keys = lists.reduce((acc, it) => acc.concat(it.data.map(it => it.relationKey)), []).concat('description');
|
||||
const ids = list.data.map(it => it.id);
|
||||
|
||||
S.Menu.open('relationSuggest', {
|
||||
|
|
|
@ -27,9 +27,9 @@ const Vault = observer(forwardRef<VaultRefProps>((props, ref) => {
|
|||
const items = U.Menu.getVaultItems();
|
||||
const cn = [ 'vault' ];
|
||||
const sensors = useSensors(
|
||||
useSensor(PointerSensor, { activationConstraint: { distance: 10 } }),
|
||||
useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates })
|
||||
);
|
||||
useSensor(PointerSensor, { activationConstraint: { distance: 10 } }),
|
||||
useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates })
|
||||
);
|
||||
|
||||
if (!showVault) {
|
||||
cn.push('isHidden');
|
||||
|
@ -322,16 +322,16 @@ const Vault = observer(forwardRef<VaultRefProps>((props, ref) => {
|
|||
<div className="head" />
|
||||
<div className="body">
|
||||
<DndContext
|
||||
sensors={sensors}
|
||||
collisionDetection={closestCenter}
|
||||
sensors={sensors}
|
||||
collisionDetection={closestCenter}
|
||||
onDragStart={onSortStart}
|
||||
onDragEnd={onSortEnd}
|
||||
onDragEnd={onSortEnd}
|
||||
modifiers={[ restrictToVerticalAxis, restrictToFirstScrollableAncestor ]}
|
||||
>
|
||||
<SortableContext
|
||||
items={items.map((item) => item.id)}
|
||||
strategy={verticalListSortingStrategy}
|
||||
>
|
||||
>
|
||||
<SortableContext
|
||||
items={items.map((item) => item.id)}
|
||||
strategy={verticalListSortingStrategy}
|
||||
>
|
||||
<div id="scroll" className="side top" onScroll={onScroll}>
|
||||
{items.map((item, i) => (
|
||||
<VaultItem
|
||||
|
|
|
@ -596,7 +596,6 @@ class Analytics {
|
|||
popupMapper (params: any): string {
|
||||
const { id } = params;
|
||||
const map = {
|
||||
inviteRequest: 'ScreenInviteRequest',
|
||||
spaceCreate: 'ScreenSettingsSpaceCreate',
|
||||
};
|
||||
|
||||
|
|
|
@ -635,7 +635,7 @@ class Mark {
|
|||
|
||||
switch (type) {
|
||||
case I.MarkType.Link: {
|
||||
attr = `href="${param}"`;
|
||||
attr = `href="${U.Common.urlFix(param)}"`;
|
||||
break;
|
||||
};
|
||||
|
||||
|
@ -717,6 +717,10 @@ class Mark {
|
|||
};
|
||||
|
||||
getTag (t: I.MarkType): string {
|
||||
if (t == I.MarkType.Link) {
|
||||
return 'a';
|
||||
};
|
||||
|
||||
return I.MarkType[t] ? `markup${I.MarkType[t].toLowerCase()}` : '';
|
||||
};
|
||||
|
||||
|
|
|
@ -134,10 +134,10 @@ class ScrollOnMove {
|
|||
const edgeLeft = BORDER;
|
||||
const edgeBottom = this.viewportHeight - BORDER;
|
||||
const edgeRight = this.viewportWidth - BORDER;
|
||||
|
||||
const isInLeftEdge = x < edgeLeft;
|
||||
|
||||
const isInLeftEdge = (x > 0) && (x < edgeLeft);
|
||||
const isInRightEdge = x > edgeRight;
|
||||
const isInTopEdge = y < edgeTop;
|
||||
const isInTopEdge = (y > 0) && (y < edgeTop);
|
||||
const isInBottomEdge = y > edgeBottom;
|
||||
|
||||
if (!(isInLeftEdge || isInRightEdge || isInTopEdge || isInBottomEdge)) {
|
||||
|
|
|
@ -1084,7 +1084,7 @@ class UtilCommon {
|
|||
return text;
|
||||
};
|
||||
|
||||
match.forEach((m: any) => {
|
||||
Array.from(match).forEach((m: any) => {
|
||||
const m0 = String(m[0] || '');
|
||||
const m1 = String(m[1] || '');
|
||||
const m2 = String(m[2] || '');
|
||||
|
|
|
@ -586,6 +586,49 @@ class UtilObject {
|
|||
C.BlockListSetFields(id, [ { blockId: id, fields } ]);
|
||||
};
|
||||
|
||||
copyLink (object: any, space: any, type: string, route: string) {
|
||||
const cb = (link: string) => {
|
||||
U.Common.copyToast(translate('commonLink'), link);
|
||||
analytics.event('CopyLink', { route });
|
||||
};
|
||||
|
||||
let link = '';
|
||||
|
||||
switch (type) {
|
||||
case 'deeplink': {
|
||||
link = `${J.Constant.protocol}://${U.Object.universalRoute(object)}`;
|
||||
break;
|
||||
};
|
||||
|
||||
case 'web': {
|
||||
link = `https://object.any.coop/${object.id}?spaceId=${space.targetSpaceId}`;
|
||||
break;
|
||||
};
|
||||
};
|
||||
|
||||
if (space.isShared) {
|
||||
U.Space.getInvite(space.targetSpaceId, (cid: string, key: string) => {
|
||||
if (cid && key) {
|
||||
switch (type) {
|
||||
case 'deeplink': {
|
||||
cb(link + `&cid=${cid}&key=${key}`);
|
||||
break;
|
||||
};
|
||||
|
||||
case 'web': {
|
||||
cb(link + `&inviteID=${cid}#${key}`);
|
||||
break;
|
||||
};
|
||||
};
|
||||
} else {
|
||||
cb(link);
|
||||
};
|
||||
});
|
||||
} else {
|
||||
cb(link);
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
export default new UtilObject();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue