this.node = node} className={cn.join(' ')}>
@@ -131,7 +143,16 @@ const HeadSimple = observer(class Controls extends React.Component
{
canEdit={canEditIcon}
/>
) : ''}
-
+
+
+ {withColorPicker ? (
+
+ ) : ''}
{descr}
@@ -285,6 +306,27 @@ const HeadSimple = observer(class Controls extends React.Component
{
return sources.includes(rootId);
};
+ onColorPicker () {
+ const { rootId, onColorChange, colorPickerTitle } = this.props;
+ const object = S.Detail.get(rootId, rootId);
+
+ S.Menu.open('dataviewOptionEdit', {
+ element: `#colorPicker`,
+ offsetY: 4,
+ title: colorPickerTitle || translate('commonColor'),
+ data: {
+ option: { color: object.color },
+ onColorPick: (color) => {
+ if (onColorChange) {
+ onColorChange(color);
+ };
+ },
+ noFilter: true,
+ noRemove: true
+ }
+ });
+ };
+
});
-export default HeadSimple;
\ No newline at end of file
+export default HeadSimple;
diff --git a/src/ts/component/page/index.tsx b/src/ts/component/page/index.tsx
index 24d16bdb3c..6e2fef6079 100644
--- a/src/ts/component/page/index.tsx
+++ b/src/ts/component/page/index.tsx
@@ -31,6 +31,9 @@ import PageMainMembership from './main/membership';
import PageMainObject from './main/object';
import PageMainOnboarding from './main/onboarding';
import PageMainChat from './main/chat';
+import PageMainTag from './main/tag';
+import PageMainDate from './main/date';
+import { createRef } from 'react';
const Components = {
'index/index': PageAuthSelect,
@@ -61,12 +64,12 @@ const Components = {
'main/onboarding': PageMainOnboarding,
'main/chat': PageMainChat,
'main/void': PageMainVoid,
-};
-
+ 'main/date': PageMainDate,
+} as const;
const Page = observer(class Page extends React.Component {
_isMounted = false;
- refChild: any = null;
+ refChild: React.RefObject = createRef();
frame = 0;
render () {
@@ -98,7 +101,7 @@ const Page = observer(class Page extends React.Component {
const wrap = (
- this.refChild = ref} {...this.props} />
+
);
@@ -353,8 +356,8 @@ const Page = observer(class Page extends React.Component {
return;
};
- if (this.refChild && this.refChild.resize) {
- this.refChild.resize();
+ if (this.refChild.current && this.refChild.current.resize) {
+ this.refChild.current.resize();
};
sidebar.resizePage(null, false);
diff --git a/src/ts/component/page/main/date/index.tsx b/src/ts/component/page/main/date/index.tsx
new file mode 100644
index 0000000000..3a8f17dcae
--- /dev/null
+++ b/src/ts/component/page/main/date/index.tsx
@@ -0,0 +1,333 @@
+import * as React from 'react';
+import { observer } from 'mobx-react';
+import { Action, C, I, J, Renderer, S, translate, U } from 'Lib';
+import { Header, Footer, ListObject, Button } from 'Component';
+import HeadSimple from 'Component/page/elements/head/simple';
+import RelationsSelector from './relations';
+import { useParams } from 'react-router-dom';
+import { useEffect, useRef, useState } from 'react';
+import { set } from 'lodash';
+import { number, unknown } from '@rspack/core/compiled/zod';
+import { then } from 'Lib/util/then';
+
+interface State {
+ isLoading: boolean;
+ isDeleted: boolean;
+ relationKeyWithCounterList: { relationKey: string, counter: number }[];
+};
+
+// const PageMainDate = observer(class PageMainDate extends React.Component {
+
+// _isMounted = false;
+// node: any = null;
+// id = '';
+// refHeader: any = null;
+// refHead: any = null;
+
+// state = {
+// isLoading: false,
+// isDeleted: false,
+// relationKeyWithCounterList: [],
+// };
+
+// render() {
+// const rootId = this.getRootId();
+// const object = S.Detail.get(rootId, rootId, ['backlinks']);
+
+// const subId = this.getSubId();
+// const total = S.Record.getMeta(subId, '').total;
+
+// const filters: I.Filter[] = [{ relationKey: 'id', condition: I.FilterCondition.In, value: object.backlinks || [] }];
+
+// const columns: any[] = [
+// { relationKey: 'type', name: translate('commonObjectType'), isObject: true },
+// { relationKey: 'creator', name: translate('commonOwner'), isObject: true },
+// ];
+
+// return (
+// this.node = node}>
+//
+//
this.refHead = ref}
+// placeholder={translate('defaultNameTag')}
+// rootId={rootId}
+// isContextMenuDisabled={true}
+// noIcon={true}
+// withColorPicker={false}
+// />
+//
+// {!object._empty_ ? (
+//
+//
{total} {U.Common.plural(total, translate('pluralObject'))}
+//
+//
+//
+//
+// ) : ''}
+//
+
+//
+//
+// );
+// };
+
+// componentDidMount() {
+// this._isMounted = true;
+// this.open();
+// };
+
+// componentDidUpdate() {
+// this.open();
+// };
+
+// componentWillUnmount() {
+// this._isMounted = false;
+// this.close();
+// };
+
+// open() {
+// const rootId = this.getRootId();
+
+// if (this.id == rootId) {
+// return;
+// };
+
+// this.close();
+// this.id = rootId;
+// this.setState({ isDeleted: false, isLoading: true });
+
+// C.ObjectOpen(rootId, '', U.Router.getRouteSpaceId(), (message: any) => {
+// if (!U.Common.checkErrorOnOpen(rootId, message.error.code, this)) {
+// return;
+// };
+
+// const object = S.Detail.get(rootId, rootId, []);
+// if (object.isDeleted) {
+// this.setState({ isDeleted: true, isLoading: false });
+// return;
+// };
+
+// this.refHeader?.forceUpdate();
+// this.refHead?.forceUpdate();
+// this.setState({ isLoading: false });
+// });
+// };
+
+// close() {
+// if (!this.id) {
+// return;
+// };
+
+// const { isPopup, match } = this.props;
+
+// let close = true;
+// if (isPopup && (match.params.id == this.id)) {
+// close = false;
+// };
+
+// if (close) {
+// Action.pageClose(this.id, true);
+// };
+// };
+
+// getSpaceId() {
+// const rootId = this.getRootId();
+// const object = S.Detail.get(rootId, rootId, ['spaceId'], true);
+
+// return object.spaceId;
+// };
+
+// getRootId() {
+// const { rootId, match } = this.props;
+// return rootId ? rootId : match.params.id;
+// };
+
+// getSubId() {
+// return S.Record.getSubId(this.getRootId(), 'backlinks');
+// };
+// });
+
+// export default PageMainDate;
+
+function getRootId({ rootId, match }) {
+ return rootId ? rootId : match.params.id;
+};
+
+const PageMainDate = observer((props: { rootId: string, isPopup: boolean }) => {
+ const { id } = useParams<{ id: string }>();
+ const { rootId = id } = props;
+
+ const [lastId, setLastId] = useState(rootId);
+ const [isDeleted, setIsDeleted] = useState(false);
+ const [isLoading, setIsLoading] = useState(false);
+
+ const object = S.Detail.get(rootId, rootId, ['backlinks']);
+
+ const subId = S.Record.getSubId(rootId, 'backlinks');
+
+ const spaceId = S.Detail.get(rootId, rootId, ['spaceId'], true).spaceId;
+
+ const total = S.Record.getMeta(subId, '').total;
+
+ const filters: I.Filter[] = [{ relationKey: 'id', condition: I.FilterCondition.In, value: object.backlinks || [] }];
+
+ const columns: any[] = [
+ { relationKey: 'type', name: translate('commonObjectType'), isObject: true },
+ { relationKey: 'creator', name: translate('commonOwner'), isObject: true },
+ ];
+
+ const mounted = useRef(false);
+
+
+ const close = () => {
+ if (!mounted.current) {
+ return;
+ }
+ if (!lastId) {
+ return;
+ };
+
+ const { isPopup } = props;
+
+ const { id } = useParams<{ id: string }>();
+
+ let close = true;
+ if (isPopup && (id == lastId)) {
+ close = false;
+ };
+
+ if (close) {
+ Action.pageClose(lastId, true);
+ };
+ };
+
+ const open = async () => {
+
+ if (!mounted.current) {
+ return;
+ }
+
+ if (lastId == rootId) {
+ return;
+ };
+
+ close();
+ setLastId(rootId);
+ setIsDeleted(false);
+ setIsLoading(true);
+
+ const message: { error?: { code?: number } } = await then(C.ObjectOpen)(rootId, '', U.Router.getRouteSpaceId());
+
+ if (!rootId) return;
+
+ const errorCode = message?.error?.code;
+
+ if (errorCode) return;
+
+ setIsLoading(false);
+
+ let hasError = false;
+
+ if (!U.Common.checkErrorCommon(errorCode)) {
+ hasError = false;
+ };
+
+ if ([J.Error.Code.NOT_FOUND, J.Error.Code.OBJECT_DELETED].includes(errorCode)) {
+ setIsDeleted(true);
+ } else {
+ const logPath = U.Common.getElectron().logPath();
+
+ S.Popup.open('confirm', {
+ data: {
+ icon: 'error',
+ bgColor: 'red',
+ title: translate('commonError'),
+ text: translate('popupConfirmObjectOpenErrorText'),
+ textConfirm: translate('popupConfirmObjectOpenErrorButton'),
+ onConfirm: () => {
+ C.DebugTree(rootId, logPath, (message: any) => {
+ if (!errorCode) {
+ Renderer.send('openPath', logPath);
+ };
+ });
+
+ U.Space.openDashboard('route', { replace: true });
+ },
+ },
+ });
+ };
+
+ hasError = false;
+
+ if (!hasError) {
+ return;
+ };
+
+ const object = S.Detail.get(rootId, rootId, []);
+ setIsLoading(false);
+
+ if (object.isDeleted) {
+ setIsDeleted(true);
+ return;
+ };
+ };
+
+ useEffect(() => {
+ if (!mounted.current) {
+ // did mount
+ mounted.current = true;
+ }
+ open();
+ return () => {
+ // will unmount
+ close();
+ mounted.current = false;
+ };
+ }, [rootId]);
+
+ return (
+
+
+
+
+ {!object._empty_ ? (
+
+
{total} {U.Common.plural(total, translate('pluralObject'))}
+
+
+
+
+ ) : ''}
+
+
+
+
+ );
+});
+
+export default PageMainDate;
\ No newline at end of file
diff --git a/src/ts/component/page/main/date/relations.tsx b/src/ts/component/page/main/date/relations.tsx
new file mode 100644
index 0000000000..7ec71b3433
--- /dev/null
+++ b/src/ts/component/page/main/date/relations.tsx
@@ -0,0 +1,127 @@
+import * as React from 'react';
+import $ from 'jquery';
+import arrayMove from 'array-move';
+import { observer } from 'mobx-react';
+import { observable } from 'mobx';
+import { SortableContainer, SortableElement } from 'react-sortable-hoc';
+import { Icon, Button, Filter } from 'Component';
+import { C, I, S, U, M, analytics, Relation, keyboard, translate, Dataview, sidebar, J } from 'Lib';
+import { RelationListWithValue } from 'Lib/api/response';
+import type { RelationWithCounter } from 'Lib/api/response';
+import { useEffect } from 'react';
+// import HeadSimple from 'Component/page/elements/head/simple';
+
+
+export interface RelationsSelectorProps {
+ rootId?: string;
+ relationId?: I.Block;
+ className?: string;
+};
+
+// type RelationsSelectorState = ReturnType;
+// const RelationsSelector: RelationsSelectorComponent = observer(class Controls extends React.Component {
+
+// _isMounted = false;
+// node: any = null;
+// refFilter = null;
+// refHead = null;
+
+// constructor(props: RelationsSelectorProps) {
+ // super(props);
+ // this.state = {
+ // relations: [],
+ // };
+ // };
+
+ // componentDidMount() {
+ // this._isMounted = true;
+ // C.RelationListWithValue(U.Router.getRouteSpaceId(), this.props.rootId, (message: any) => { });
+ // // C.RelationListWithValue(U.Router.getRouteSpaceId(), rootId, (message: any) => {
+ // // const { error } = message;
+ // // if (error) {
+ // // return;
+ // // };
+ // // const object = S.Detail.get(this.props.rootId, U.Router.getRouteSpaceId());
+ // // console.log('Object:', object);
+ // // const { countersList, relationskeysList } = message;
+ // // const relationKeyWithCounterList = relationskeysList.map((relationKey: string, ndx: number) => {
+ // // return {
+ // // relationKey,
+ // // counter: countersList[ndx],
+ // // };
+ // // });
+ // // console.log('RelationKeyWithCounterList:', relationKeyWithCounterList);
+ // // this.setState({ relationKeyWithCounterList: message.relationKeyWithCounterList });
+ // // });
+ // };
+
+ // });
+
+
+const RelationButton = SortableElement(({ relation, rootId }) => {
+ const elementId = `date-relation-item-${relation.id}`;
+ return (
+ console.log(relation)}
+ >
+ {relation.name || translate('defaultNamePage')}
+
+ );
+});
+
+const RelationsContainer = SortableContainer(({ relations, rootId }: { relations: RelationWithCounter[], rootId: string }) => (
+
+ {relations.map((relation, i: number) => (
+
+ ))}
+
+));
+
+const RelationsSelector: React.FC = (props: RelationsSelectorProps) => {
+
+ const [relations, setRelations] = React.useState([]);
+
+ const { rootId, className } = props;
+
+ const cn: string[] = ['dateRelations'];
+ if (className) {
+ cn.push(className);
+ };
+
+ useEffect(() => {
+ C.RelationListWithValue(U.Router.getRouteSpaceId(), rootId, (message: any) => {
+ const { error } = message;
+ if (error) {
+ return;
+ };
+ const object = S.Detail.get(rootId, U.Router.getRouteSpaceId());
+ console.log('Object:', object);
+ const { countersList, relationskeysList } = message;
+ const relationKeyWithCounterList = relationskeysList.map((relationKey: string, ndx: number) => {
+ return {
+ relationkey: relationKey,
+ counter: countersList[ndx],
+ };
+ });
+ console.log('RelationKeyWithCounterList:', relationKeyWithCounterList);
+ setRelations(relationKeyWithCounterList);
+ });
+ }, [rootId]);
+
+ return (
+
+ );
+};
+
+export default RelationsSelector;
diff --git a/src/ts/component/page/main/object.tsx b/src/ts/component/page/main/object.tsx
index cfefda4725..4eb93032a9 100644
--- a/src/ts/component/page/main/object.tsx
+++ b/src/ts/component/page/main/object.tsx
@@ -31,4 +31,4 @@ class PageMainObject extends React.Component {
};
-export default PageMainObject;
\ No newline at end of file
+export default PageMainObject;
diff --git a/src/ts/component/page/main/tag.tsx b/src/ts/component/page/main/tag.tsx
new file mode 100644
index 0000000000..6beb87d82b
--- /dev/null
+++ b/src/ts/component/page/main/tag.tsx
@@ -0,0 +1,182 @@
+import * as React from 'react';
+import { observer } from 'mobx-react';
+import { Action, C, I, S, translate, U } from 'Lib';
+import { Header, Footer, ListObject } from 'Component';
+import HeadSimple from 'Component/page/elements/head/simple';
+
+interface State {
+ isLoading: boolean;
+ isDeleted: boolean;
+};
+
+const PageMainTag = observer(class PageMainTag extends React.Component {
+
+ _isMounted = false;
+ node: any = null;
+ id = '';
+ refHeader: any = null;
+ refHead: any = null;
+
+ state = {
+ isLoading: false,
+ isDeleted: false,
+ };
+
+ constructor (props: I.PageComponent) {
+ super(props);
+
+ this.setColor = this.setColor.bind(this);
+ };
+
+ render () {
+ const rootId = this.getRootId();
+ const object = S.Detail.get(rootId, rootId, [ 'backlinks' ]);
+
+ const subId = this.getSubId();
+ const total = S.Record.getMeta(subId, '').total;
+
+ const filters: I.Filter[] = [ { relationKey: 'id', condition: I.FilterCondition.In, value: object.backlinks || [] } ];
+
+ const columns: any[] = [
+ { relationKey: 'type', name: translate('commonObjectType'), isObject: true },
+ {
+ relationKey: 'createdDate', name: translate('commonDateCreated'),
+ mapper: v => v ? U.Date.dateWithFormat(I.DateFormat.MonthAbbrBeforeDay, v) : '',
+ },
+ { relationKey: 'creator', name: translate('commonOwner'), isObject: true },
+ ];
+
+ return (
+ this.node = node}>
+
this.refHeader = ref}
+ rootId={rootId}
+ />
+
+
+
this.refHead = ref}
+ placeholder={translate('defaultNameTag')}
+ rootId={rootId}
+ isContextMenuDisabled={true}
+ noIcon={true}
+ withColorPicker={true}
+ onColorChange={this.setColor}
+ colorPickerTitle={translate('pageMainTagTagColor')}
+ />
+
+ {!object._empty_ ? (
+
+
{total} {U.Common.plural(total, translate('pluralObject'))}
+
+
+
+
+ ) : ''}
+
+
+
+
+ );
+ };
+
+ componentDidMount () {
+ this._isMounted = true;
+ this.open();
+ };
+
+ componentDidUpdate () {
+ this.open();
+ };
+
+ componentWillUnmount () {
+ this._isMounted = false;
+ this.close();
+ };
+
+ open () {
+ const rootId = this.getRootId();
+
+ if (this.id == rootId) {
+ return;
+ };
+
+ this.close();
+ this.id = rootId;
+ this.setState({ isLoading: true});
+
+ C.ObjectOpen(rootId, '', U.Router.getRouteSpaceId(), (message: any) => {
+ if (!U.Common.checkErrorOnOpen(rootId, message.error.code, this)) {
+ return;
+ };
+
+ const object = S.Detail.get(rootId, rootId, []);
+ if (object.isDeleted) {
+ this.setState({ isDeleted: true, isLoading: false });
+ return;
+ };
+
+ this.refHeader?.forceUpdate();
+ this.refHead?.forceUpdate();
+ this.setState({ isLoading: false });
+ });
+ };
+
+ close () {
+ if (!this.id) {
+ return;
+ };
+
+ const { isPopup, match } = this.props;
+
+ let close = true;
+ if (isPopup && (match.params.id == this.id)) {
+ close = false;
+ };
+
+ if (close) {
+ Action.pageClose(this.id, true);
+ };
+ };
+
+ setColor (color: string) {
+ const rootId = this.getRootId();
+ const object = S.Detail.get(rootId, rootId);
+
+ C.ObjectListSetDetails([ object.id ], [
+ { key: 'relationOptionColor', value: color },
+ ], (message) => {
+ S.Detail.update(rootId, { id: object.id, details: { relationOptionColor: color } }, false);
+ this.forceUpdate();
+ });
+ };
+
+ getSpaceId () {
+ const rootId = this.getRootId();
+ const object = S.Detail.get(rootId, rootId, [ 'spaceId' ], true);
+
+ return object.spaceId;
+ };
+
+ getRootId () {
+ const { rootId, match } = this.props;
+ return rootId ? rootId : match.params.id;
+ };
+
+ getSubId () {
+ return S.Record.getSubId(this.getRootId(), 'backlinks');
+ };
+});
+
+export default PageMainTag;
diff --git a/src/ts/component/page/main/type.tsx b/src/ts/component/page/main/type.tsx
index 75ff3b2dc8..7cb3c8df46 100644
--- a/src/ts/component/page/main/type.tsx
+++ b/src/ts/component/page/main/type.tsx
@@ -348,7 +348,8 @@ const PageMainType = observer(class PageMainType extends React.Component {
break;
};
+ case I.ObjectLayout.Tag: {
+ break;
+ };
+
case I.ObjectLayout.Collection:
case I.ObjectLayout.Set: {
if (iconImage) {
@@ -507,4 +511,4 @@ const IconObject = observer(class IconObject extends React.Component {
});
-export default IconObject;
\ No newline at end of file
+export default IconObject;
diff --git a/src/ts/interface/object.ts b/src/ts/interface/object.ts
index d7ca2cc073..9794885a4a 100644
--- a/src/ts/interface/object.ts
+++ b/src/ts/interface/object.ts
@@ -21,6 +21,7 @@ export enum ObjectLayout {
Participant = 19,
Pdf = 20,
Chat = 22,
+ Tag = 23,
Empty = 100,
Navigation = 101,
@@ -71,4 +72,4 @@ export enum ObjectOrigin {
Usecase = 6,
Builtin = 7,
Bookmark = 8,
-};
\ No newline at end of file
+};
diff --git a/src/ts/lib/api/response.ts b/src/ts/lib/api/response.ts
index 5de5b4cb04..6e0c7993e5 100644
--- a/src/ts/lib/api/response.ts
+++ b/src/ts/lib/api/response.ts
@@ -580,4 +580,10 @@ export const ChatAddMessage = (response: Rpc.Chat.AddMessage.Response) => {
return {
messageId: response.getMessageid(),
};
+};
+
+export const RelationListWithValue = (response: Rpc.Relation.ListWithValue.Response) => {
+ return {
+ listList: response.getListList(),
+ };
};
\ No newline at end of file
diff --git a/src/ts/lib/relation.ts b/src/ts/lib/relation.ts
index 3655dd6ea7..a62fd96463 100644
--- a/src/ts/lib/relation.ts
+++ b/src/ts/lib/relation.ts
@@ -653,4 +653,4 @@ class Relation {
};
-export default new Relation();
\ No newline at end of file
+export default new Relation();
diff --git a/src/ts/lib/util/data.ts b/src/ts/lib/util/data.ts
index ee21cc2234..f7c7160f0e 100644
--- a/src/ts/lib/util/data.ts
+++ b/src/ts/lib/util/data.ts
@@ -631,7 +631,8 @@ class UtilData {
break;
case I.ObjectLayout.Bookmark:
- case I.ObjectLayout.Task: {
+ case I.ObjectLayout.Task:
+ case I.ObjectLayout.Tag: {
break;
};
diff --git a/src/ts/lib/util/menu.ts b/src/ts/lib/util/menu.ts
index b6fa5f2b8f..c8201127a3 100644
--- a/src/ts/lib/util/menu.ts
+++ b/src/ts/lib/util/menu.ts
@@ -1018,8 +1018,8 @@ class UtilMenu {
sort = [
{ name: translate('sidebarObjectSort'), isSection: true },
- { id: I.SortId.Updated, name: translate('sidebarObjectSortUpdated'), relationKey: 'lastModifiedDate', isSort: true, defaultType: I.SortType.Desc },
- { id: I.SortId.Created, name: translate('sidebarObjectSortCreated'), relationKey: 'createdDate', isSort: true, defaultType: I.SortType.Desc },
+ { id: I.SortId.Updated, name: translate('commonDateUpdated'), relationKey: 'lastModifiedDate', isSort: true, defaultType: I.SortType.Desc },
+ { id: I.SortId.Created, name: translate('commonDateCreated'), relationKey: 'createdDate', isSort: true, defaultType: I.SortType.Desc },
{ id: I.SortId.Name, name: translate('commonName'), relationKey: 'name', isSort: true, defaultType: I.SortType.Asc },
];
};
diff --git a/src/ts/lib/util/object.ts b/src/ts/lib/util/object.ts
index 1266c008c1..e588c06a6a 100644
--- a/src/ts/lib/util/object.ts
+++ b/src/ts/lib/util/object.ts
@@ -26,6 +26,7 @@ class UtilObject {
case I.ObjectLayout.Empty: r = 'empty'; break;
case I.ObjectLayout.Space:
case I.ObjectLayout.Chat: r = 'chat'; break;
+ case I.ObjectLayout.Tag: r = 'tag'; break;
};
return r;
};
@@ -364,6 +365,10 @@ class UtilObject {
return layout == I.ObjectLayout.File;
};
+ isTagLayout (layout: I.ObjectLayout): boolean {
+ return layout == I.ObjectLayout.Tag;
+ };
+
// --------------------------------------------------------- //
getPageLayouts (): I.ObjectLayout[] {
@@ -385,7 +390,7 @@ class UtilObject {
};
getLayoutsWithoutTemplates (): I.ObjectLayout[] {
- return [].concat(this.getFileAndSystemLayouts()).concat(this.getSetLayouts()).concat([ I.ObjectLayout.Chat, I.ObjectLayout.Participant ]);
+ return [].concat(this.getFileAndSystemLayouts()).concat(this.getSetLayouts()).concat([ I.ObjectLayout.Chat, I.ObjectLayout.Participant, I.ObjectLayout.Tag ]);
};
getFileAndSystemLayouts (): I.ObjectLayout[] {
@@ -456,4 +461,4 @@ class UtilObject {
};
-export default new UtilObject();
\ No newline at end of file
+export default new UtilObject();
diff --git a/src/ts/lib/util/then.ts b/src/ts/lib/util/then.ts
new file mode 100644
index 0000000000..8af848398e
--- /dev/null
+++ b/src/ts/lib/util/then.ts
@@ -0,0 +1,10 @@
+type Fn = (...args: T) => void;
+type Callback = (data: D) => void;
+type HeadArgsTuple> = F extends Fn ? A : never;
+type CallbackDataType> = F extends Fn]> ? D : never;
+
+export function then>(fnWithCallback: F) {
+ return (...args: HeadArgsTuple) => new Promise((resolve) => fnWithCallback(...args, (data: CallbackDataType) => {
+ resolve(data);
+ }));
+}
\ No newline at end of file
diff --git a/src/ts/store/block.ts b/src/ts/store/block.ts
index f2e4e56a7b..d6ffb89872 100644
--- a/src/ts/store/block.ts
+++ b/src/ts/store/block.ts
@@ -692,4 +692,4 @@ class BlockStore {
};
- export const Block: BlockStore = new BlockStore();
\ No newline at end of file
+ export const Block: BlockStore = new BlockStore();
diff --git a/src/ts/store/detail.ts b/src/ts/store/detail.ts
index 1418816308..4f262d47fb 100644
--- a/src/ts/store/detail.ts
+++ b/src/ts/store/detail.ts
@@ -1,5 +1,5 @@
import { observable, action, set, intercept, makeObservable } from 'mobx';
-import { I, S, U, J, Relation, translate } from 'Lib';
+import { I, S, U, J, Relation, translate, C } from 'Lib';
interface Detail {
relationKey: string;
@@ -279,6 +279,14 @@ class DetailStore {
return this.mapSet(object);
};
+ private mapTag (object: any) {
+ object.color = Relation.getStringValue(object.color || object.relationOptionColor || 'default');
+
+ delete(object.relationOptionColor);
+
+ return object;
+ };
+
private mapSpaceView (object: any) {
object.spaceAccessType = Number(object.spaceAccessType) || I.SpaceType.Private;
object.spaceAccountStatus = Number(object.spaceAccountStatus) || I.SpaceStatus.Unknown;