feat(core): add track events for sidebar (#7659)
This commit is contained in:
@@ -10,6 +10,7 @@ import {
|
|||||||
filterPage,
|
filterPage,
|
||||||
useEditCollection,
|
useEditCollection,
|
||||||
} from '@affine/core/components/page-list';
|
} from '@affine/core/components/page-list';
|
||||||
|
import { mixpanel } from '@affine/core/mixpanel';
|
||||||
import { CollectionService } from '@affine/core/modules/collection';
|
import { CollectionService } from '@affine/core/modules/collection';
|
||||||
import { CompatibleFavoriteItemsAdapter } from '@affine/core/modules/properties';
|
import { CompatibleFavoriteItemsAdapter } from '@affine/core/modules/properties';
|
||||||
import { ShareDocsService } from '@affine/core/modules/share-doc';
|
import { ShareDocsService } from '@affine/core/modules/share-doc';
|
||||||
@@ -77,11 +78,16 @@ export const ExplorerCollectionNode = ({
|
|||||||
|
|
||||||
const handleRename = useCallback(
|
const handleRename = useCallback(
|
||||||
(name: string) => {
|
(name: string) => {
|
||||||
if (collection) {
|
if (collection && collection.name !== name) {
|
||||||
collectionService.updateCollection(collectionId, () => ({
|
collectionService.updateCollection(collectionId, () => ({
|
||||||
...collection,
|
...collection,
|
||||||
name,
|
name,
|
||||||
}));
|
}));
|
||||||
|
mixpanel.track('CollectionRenamed', {
|
||||||
|
page: 'sidebar',
|
||||||
|
module: 'collection',
|
||||||
|
control: 'rename collection',
|
||||||
|
});
|
||||||
toast(t['com.affine.toastMessage.rename']());
|
toast(t['com.affine.toastMessage.rename']());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -107,6 +113,11 @@ export const ExplorerCollectionNode = ({
|
|||||||
if (collection && data.treeInstruction?.type === 'make-child') {
|
if (collection && data.treeInstruction?.type === 'make-child') {
|
||||||
if (data.source.data.entity?.type === 'doc') {
|
if (data.source.data.entity?.type === 'doc') {
|
||||||
handleAddDocToCollection(data.source.data.entity.id);
|
handleAddDocToCollection(data.source.data.entity.id);
|
||||||
|
mixpanel.track('AddDocToCollection', {
|
||||||
|
page: 'sidebar',
|
||||||
|
module: 'collection',
|
||||||
|
control: 'drop doc on collection',
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
onDrop?.(data);
|
onDrop?.(data);
|
||||||
@@ -133,6 +144,11 @@ export const ExplorerCollectionNode = ({
|
|||||||
(data: DropTargetDropEvent<AffineDNDData>) => {
|
(data: DropTargetDropEvent<AffineDNDData>) => {
|
||||||
if (collection && data.source.data.entity?.type === 'doc') {
|
if (collection && data.source.data.entity?.type === 'doc') {
|
||||||
handleAddDocToCollection(data.source.data.entity.id);
|
handleAddDocToCollection(data.source.data.entity.id);
|
||||||
|
mixpanel.track('AddDocToCollection', {
|
||||||
|
page: 'sidebar',
|
||||||
|
module: 'collection',
|
||||||
|
control: 'drop doc on collection',
|
||||||
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[collection, handleAddDocToCollection]
|
[collection, handleAddDocToCollection]
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
} from '@affine/component';
|
} from '@affine/component';
|
||||||
import { useAppSettingHelper } from '@affine/core/hooks/affine/use-app-setting-helper';
|
import { useAppSettingHelper } from '@affine/core/hooks/affine/use-app-setting-helper';
|
||||||
import { useDeleteCollectionInfo } from '@affine/core/hooks/affine/use-delete-collection-info';
|
import { useDeleteCollectionInfo } from '@affine/core/hooks/affine/use-delete-collection-info';
|
||||||
|
import { mixpanel } from '@affine/core/mixpanel';
|
||||||
import { CollectionService } from '@affine/core/modules/collection';
|
import { CollectionService } from '@affine/core/modules/collection';
|
||||||
import { CompatibleFavoriteItemsAdapter } from '@affine/core/modules/properties';
|
import { CompatibleFavoriteItemsAdapter } from '@affine/core/modules/properties';
|
||||||
import { WorkbenchService } from '@affine/core/modules/workbench';
|
import { WorkbenchService } from '@affine/core/modules/workbench';
|
||||||
@@ -56,6 +57,16 @@ export const useExplorerCollectionNodeOperations = (
|
|||||||
const createAndAddDocument = useCallback(() => {
|
const createAndAddDocument = useCallback(() => {
|
||||||
const newDoc = docsService.createDoc();
|
const newDoc = docsService.createDoc();
|
||||||
collectionService.addPageToCollection(collectionId, newDoc.id);
|
collectionService.addPageToCollection(collectionId, newDoc.id);
|
||||||
|
mixpanel.track('DocCreated', {
|
||||||
|
page: 'sidebar',
|
||||||
|
module: 'collection',
|
||||||
|
control: 'add doc button',
|
||||||
|
});
|
||||||
|
mixpanel.track('AddDocToCollection', {
|
||||||
|
page: 'sidebar',
|
||||||
|
module: 'collection',
|
||||||
|
control: 'add doc button',
|
||||||
|
});
|
||||||
workbenchService.workbench.openDoc(newDoc.id);
|
workbenchService.workbench.openDoc(newDoc.id);
|
||||||
onOpenCollapsed();
|
onOpenCollapsed();
|
||||||
}, [
|
}, [
|
||||||
@@ -66,8 +77,15 @@ export const useExplorerCollectionNodeOperations = (
|
|||||||
workbenchService.workbench,
|
workbenchService.workbench,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const handleToggleFavoritePage = useCallback(() => {
|
const handleToggleFavoriteCollection = useCallback(() => {
|
||||||
compatibleFavoriteItemsAdapter.toggle(collectionId, 'collection');
|
compatibleFavoriteItemsAdapter.toggle(collectionId, 'collection');
|
||||||
|
mixpanel.track('ToggleFavorite', {
|
||||||
|
page: 'sidebar',
|
||||||
|
module: 'collection',
|
||||||
|
control: 'toggle favorite collection button',
|
||||||
|
type: 'collection',
|
||||||
|
id: collectionId,
|
||||||
|
});
|
||||||
}, [compatibleFavoriteItemsAdapter, collectionId]);
|
}, [compatibleFavoriteItemsAdapter, collectionId]);
|
||||||
|
|
||||||
const handleAddDocToCollection = useCallback(() => {
|
const handleAddDocToCollection = useCallback(() => {
|
||||||
@@ -85,10 +103,20 @@ export const useExplorerCollectionNodeOperations = (
|
|||||||
|
|
||||||
const handleOpenInSplitView = useCallback(() => {
|
const handleOpenInSplitView = useCallback(() => {
|
||||||
workbenchService.workbench.openCollection(collectionId, { at: 'beside' });
|
workbenchService.workbench.openCollection(collectionId, { at: 'beside' });
|
||||||
|
mixpanel.track('OpenInSplitView', {
|
||||||
|
page: 'sidebar',
|
||||||
|
module: 'collection',
|
||||||
|
control: 'open in split view button',
|
||||||
|
});
|
||||||
}, [collectionId, workbenchService.workbench]);
|
}, [collectionId, workbenchService.workbench]);
|
||||||
|
|
||||||
const handleDeleteCollection = useCallback(() => {
|
const handleDeleteCollection = useCallback(() => {
|
||||||
collectionService.deleteCollection(deleteInfo, collectionId);
|
collectionService.deleteCollection(deleteInfo, collectionId);
|
||||||
|
mixpanel.track('CollectionDeleted', {
|
||||||
|
page: 'sidebar',
|
||||||
|
module: 'collection',
|
||||||
|
control: 'delete collection button',
|
||||||
|
});
|
||||||
}, [collectionId, collectionService, deleteInfo]);
|
}, [collectionId, collectionService, deleteInfo]);
|
||||||
|
|
||||||
const handleShowEdit = useCallback(() => {
|
const handleShowEdit = useCallback(() => {
|
||||||
@@ -155,7 +183,7 @@ export const useExplorerCollectionNodeOperations = (
|
|||||||
)}
|
)}
|
||||||
</MenuIcon>
|
</MenuIcon>
|
||||||
}
|
}
|
||||||
onClick={handleToggleFavoritePage}
|
onClick={handleToggleFavoriteCollection}
|
||||||
>
|
>
|
||||||
{favorite
|
{favorite
|
||||||
? t['com.affine.favoritePageOperation.remove']()
|
? t['com.affine.favoritePageOperation.remove']()
|
||||||
@@ -210,7 +238,7 @@ export const useExplorerCollectionNodeOperations = (
|
|||||||
handleDeleteCollection,
|
handleDeleteCollection,
|
||||||
handleOpenInSplitView,
|
handleOpenInSplitView,
|
||||||
handleShowEdit,
|
handleShowEdit,
|
||||||
handleToggleFavoritePage,
|
handleToggleFavoriteCollection,
|
||||||
t,
|
t,
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
} from '@affine/component';
|
} from '@affine/component';
|
||||||
import { InfoModal } from '@affine/core/components/affine/page-properties';
|
import { InfoModal } from '@affine/core/components/affine/page-properties';
|
||||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||||
|
import { mixpanel } from '@affine/core/mixpanel';
|
||||||
import { DocsSearchService } from '@affine/core/modules/docs-search';
|
import { DocsSearchService } from '@affine/core/modules/docs-search';
|
||||||
import type { AffineDNDData } from '@affine/core/types/dnd';
|
import type { AffineDNDData } from '@affine/core/types/dnd';
|
||||||
import { useI18n } from '@affine/i18n';
|
import { useI18n } from '@affine/i18n';
|
||||||
@@ -115,6 +116,11 @@ export const ExplorerDocNode = ({
|
|||||||
const handleRename = useAsyncCallback(
|
const handleRename = useAsyncCallback(
|
||||||
async (newName: string) => {
|
async (newName: string) => {
|
||||||
await docsService.changeDocTitle(docId, newName);
|
await docsService.changeDocTitle(docId, newName);
|
||||||
|
mixpanel.track('DocRenamed', {
|
||||||
|
page: 'sidebar',
|
||||||
|
module: 'doc',
|
||||||
|
control: 'doc rename',
|
||||||
|
});
|
||||||
},
|
},
|
||||||
[docId, docsService]
|
[docId, docsService]
|
||||||
);
|
);
|
||||||
@@ -124,6 +130,11 @@ export const ExplorerDocNode = ({
|
|||||||
if (data.treeInstruction?.type === 'make-child') {
|
if (data.treeInstruction?.type === 'make-child') {
|
||||||
if (data.source.data.entity?.type === 'doc') {
|
if (data.source.data.entity?.type === 'doc') {
|
||||||
await docsService.addLinkedDoc(docId, data.source.data.entity.id);
|
await docsService.addLinkedDoc(docId, data.source.data.entity.id);
|
||||||
|
mixpanel.track('LinkedDocCreated', {
|
||||||
|
page: 'sidebar',
|
||||||
|
module: 'doc',
|
||||||
|
control: 'drop doc on doc',
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
toast(t['com.affine.rootAppSidebar.doc.link-doc-only']());
|
toast(t['com.affine.rootAppSidebar.doc.link-doc-only']());
|
||||||
}
|
}
|
||||||
@@ -153,6 +164,11 @@ export const ExplorerDocNode = ({
|
|||||||
if (data.source.data.entity?.type === 'doc') {
|
if (data.source.data.entity?.type === 'doc') {
|
||||||
// TODO(eyhn): timeout&error handling
|
// TODO(eyhn): timeout&error handling
|
||||||
await docsService.addLinkedDoc(docId, data.source.data.entity.id);
|
await docsService.addLinkedDoc(docId, data.source.data.entity.id);
|
||||||
|
mixpanel.track('LinkedDocCreated', {
|
||||||
|
page: 'sidebar',
|
||||||
|
module: 'doc',
|
||||||
|
control: 'drop doc on doc',
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
toast(t['com.affine.rootAppSidebar.doc.link-doc-only']());
|
toast(t['com.affine.rootAppSidebar.doc.link-doc-only']());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
} from '@affine/component';
|
} from '@affine/component';
|
||||||
import { useAppSettingHelper } from '@affine/core/hooks/affine/use-app-setting-helper';
|
import { useAppSettingHelper } from '@affine/core/hooks/affine/use-app-setting-helper';
|
||||||
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
|
||||||
|
import { mixpanel } from '@affine/core/mixpanel';
|
||||||
import { CompatibleFavoriteItemsAdapter } from '@affine/core/modules/properties';
|
import { CompatibleFavoriteItemsAdapter } from '@affine/core/modules/properties';
|
||||||
import { WorkbenchService } from '@affine/core/modules/workbench';
|
import { WorkbenchService } from '@affine/core/modules/workbench';
|
||||||
import { useI18n } from '@affine/i18n';
|
import { useI18n } from '@affine/i18n';
|
||||||
@@ -64,6 +65,11 @@ export const useExplorerDocNodeOperations = (
|
|||||||
},
|
},
|
||||||
onConfirm() {
|
onConfirm() {
|
||||||
docRecord.moveToTrash();
|
docRecord.moveToTrash();
|
||||||
|
mixpanel.track('DocMovedTrash', {
|
||||||
|
page: 'sidebar',
|
||||||
|
module: 'doc',
|
||||||
|
control: 'move to trash button',
|
||||||
|
});
|
||||||
toast(t['com.affine.toastMessage.movedTrash']());
|
toast(t['com.affine.toastMessage.movedTrash']());
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -73,18 +79,40 @@ export const useExplorerDocNodeOperations = (
|
|||||||
workbenchService.workbench.openDoc(docId, {
|
workbenchService.workbench.openDoc(docId, {
|
||||||
at: 'beside',
|
at: 'beside',
|
||||||
});
|
});
|
||||||
|
mixpanel.track('OpenInSplitView', {
|
||||||
|
page: 'sidebar',
|
||||||
|
module: 'doc',
|
||||||
|
control: 'open in split view button',
|
||||||
|
});
|
||||||
}, [docId, workbenchService]);
|
}, [docId, workbenchService]);
|
||||||
|
|
||||||
const handleAddLinkedPage = useAsyncCallback(async () => {
|
const handleAddLinkedPage = useAsyncCallback(async () => {
|
||||||
const newDoc = docsService.createDoc();
|
const newDoc = docsService.createDoc();
|
||||||
// TODO: handle timeout & error
|
// TODO: handle timeout & error
|
||||||
await docsService.addLinkedDoc(docId, newDoc.id);
|
await docsService.addLinkedDoc(docId, newDoc.id);
|
||||||
|
mixpanel.track('DocCreated', {
|
||||||
|
page: 'sidebar',
|
||||||
|
module: 'doc',
|
||||||
|
control: 'add linked doc button',
|
||||||
|
});
|
||||||
|
mixpanel.track('LinkedDocCreated', {
|
||||||
|
page: 'sidebar',
|
||||||
|
module: 'doc',
|
||||||
|
control: 'add linked doc button',
|
||||||
|
});
|
||||||
workbenchService.workbench.openDoc(newDoc.id);
|
workbenchService.workbench.openDoc(newDoc.id);
|
||||||
options.openNodeCollapsed();
|
options.openNodeCollapsed();
|
||||||
}, [docId, options, docsService, workbenchService.workbench]);
|
}, [docId, options, docsService, workbenchService.workbench]);
|
||||||
|
|
||||||
const handleToggleFavoriteDoc = useCallback(() => {
|
const handleToggleFavoriteDoc = useCallback(() => {
|
||||||
compatibleFavoriteItemsAdapter.toggle(docId, 'doc');
|
compatibleFavoriteItemsAdapter.toggle(docId, 'doc');
|
||||||
|
mixpanel.track('ToggleFavorite', {
|
||||||
|
page: 'sidebar',
|
||||||
|
module: 'doc',
|
||||||
|
control: 'toggle favorite button',
|
||||||
|
type: 'doc',
|
||||||
|
id: docId,
|
||||||
|
});
|
||||||
}, [docId, compatibleFavoriteItemsAdapter]);
|
}, [docId, compatibleFavoriteItemsAdapter]);
|
||||||
|
|
||||||
return useMemo(
|
return useMemo(
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import {
|
|||||||
useSelectDoc,
|
useSelectDoc,
|
||||||
useSelectTag,
|
useSelectTag,
|
||||||
} from '@affine/core/components/page-list/selector';
|
} from '@affine/core/components/page-list/selector';
|
||||||
|
import { mixpanel } from '@affine/core/mixpanel';
|
||||||
import {
|
import {
|
||||||
type FolderNode,
|
type FolderNode,
|
||||||
OrganizeService,
|
OrganizeService,
|
||||||
@@ -173,6 +174,11 @@ export const ExplorerFolderNodeFolder = ({
|
|||||||
|
|
||||||
const handleDelete = useCallback(() => {
|
const handleDelete = useCallback(() => {
|
||||||
node.delete();
|
node.delete();
|
||||||
|
mixpanel.track('FolderDeleted', {
|
||||||
|
page: 'sidebar',
|
||||||
|
module: 'organize',
|
||||||
|
control: `delete folder`,
|
||||||
|
});
|
||||||
}, [node]);
|
}, [node]);
|
||||||
|
|
||||||
const children = useLiveData(node.sortedChildren$);
|
const children = useLiveData(node.sortedChildren$);
|
||||||
@@ -213,10 +219,24 @@ export const ExplorerFolderNodeFolder = ({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
node.moveHere(data.source.data.entity.id, node.indexAt('before'));
|
node.moveHere(data.source.data.entity.id, node.indexAt('before'));
|
||||||
|
mixpanel.track('FolderMoved', {
|
||||||
|
page: 'sidebar',
|
||||||
|
module: 'organize',
|
||||||
|
control: 'drop folder at folder',
|
||||||
|
type: 'folder',
|
||||||
|
id: data.source.data.entity.id,
|
||||||
|
});
|
||||||
} else if (
|
} else if (
|
||||||
data.source.data.from?.at === 'explorer:organize:folder-node'
|
data.source.data.from?.at === 'explorer:organize:folder-node'
|
||||||
) {
|
) {
|
||||||
node.moveHere(data.source.data.from.nodeId, node.indexAt('before'));
|
node.moveHere(data.source.data.from.nodeId, node.indexAt('before'));
|
||||||
|
mixpanel.track('FolderLinkMoved', {
|
||||||
|
page: 'sidebar',
|
||||||
|
module: 'organize',
|
||||||
|
control: 'drop folder link at folder',
|
||||||
|
type: data.source.data.entity?.type,
|
||||||
|
id: data.source.data.entity?.id,
|
||||||
|
});
|
||||||
} else if (
|
} else if (
|
||||||
data.source.data.entity?.type === 'collection' ||
|
data.source.data.entity?.type === 'collection' ||
|
||||||
data.source.data.entity?.type === 'doc' ||
|
data.source.data.entity?.type === 'doc' ||
|
||||||
@@ -227,6 +247,13 @@ export const ExplorerFolderNodeFolder = ({
|
|||||||
data.source.data.entity.id,
|
data.source.data.entity.id,
|
||||||
node.indexAt('before')
|
node.indexAt('before')
|
||||||
);
|
);
|
||||||
|
mixpanel.track('FolderLinkCreated', {
|
||||||
|
page: 'sidebar',
|
||||||
|
module: 'organize',
|
||||||
|
control: 'drop entity at folder',
|
||||||
|
type: data.source.data.entity?.type,
|
||||||
|
id: data.source.data.entity?.id,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
onDrop?.(data);
|
onDrop?.(data);
|
||||||
@@ -275,10 +302,24 @@ export const ExplorerFolderNodeFolder = ({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
node.moveHere(data.source.data.entity.id, node.indexAt('before'));
|
node.moveHere(data.source.data.entity.id, node.indexAt('before'));
|
||||||
|
mixpanel.track('FolderMoved', {
|
||||||
|
page: 'sidebar',
|
||||||
|
module: 'organize',
|
||||||
|
control: 'drop folder at folder',
|
||||||
|
type: 'folder',
|
||||||
|
id: data.source.data.entity.id,
|
||||||
|
});
|
||||||
} else if (
|
} else if (
|
||||||
data.source.data.from?.at === 'explorer:organize:folder-node'
|
data.source.data.from?.at === 'explorer:organize:folder-node'
|
||||||
) {
|
) {
|
||||||
node.moveHere(data.source.data.from.nodeId, node.indexAt('before'));
|
node.moveHere(data.source.data.from.nodeId, node.indexAt('before'));
|
||||||
|
mixpanel.track('FolderLinkMoved', {
|
||||||
|
page: 'sidebar',
|
||||||
|
module: 'organize',
|
||||||
|
control: 'drop folder link at folder',
|
||||||
|
type: data.source.data.entity?.type,
|
||||||
|
id: data.source.data.entity?.id,
|
||||||
|
});
|
||||||
} else if (
|
} else if (
|
||||||
data.source.data.entity?.type === 'collection' ||
|
data.source.data.entity?.type === 'collection' ||
|
||||||
data.source.data.entity?.type === 'doc' ||
|
data.source.data.entity?.type === 'doc' ||
|
||||||
@@ -289,6 +330,13 @@ export const ExplorerFolderNodeFolder = ({
|
|||||||
data.source.data.entity.id,
|
data.source.data.entity.id,
|
||||||
node.indexAt('before')
|
node.indexAt('before')
|
||||||
);
|
);
|
||||||
|
mixpanel.track('FolderLinkCreated', {
|
||||||
|
page: 'sidebar',
|
||||||
|
module: 'organize',
|
||||||
|
control: 'drop entity at folder',
|
||||||
|
type: data.source.data.entity?.type,
|
||||||
|
id: data.source.data.entity?.id,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[node]
|
[node]
|
||||||
@@ -316,6 +364,13 @@ export const ExplorerFolderNodeFolder = ({
|
|||||||
data.source.data.entity.id,
|
data.source.data.entity.id,
|
||||||
node.indexAt(at, dropAtNode.id)
|
node.indexAt(at, dropAtNode.id)
|
||||||
);
|
);
|
||||||
|
mixpanel.track('FolderMoved', {
|
||||||
|
page: 'sidebar',
|
||||||
|
module: 'organize',
|
||||||
|
control: `drop folder ${at === 'before' ? 'above' : 'below'} node`,
|
||||||
|
type: 'folder',
|
||||||
|
id: data.source.data.entity?.id,
|
||||||
|
});
|
||||||
} else if (
|
} else if (
|
||||||
data.source.data.from?.at === 'explorer:organize:folder-node'
|
data.source.data.from?.at === 'explorer:organize:folder-node'
|
||||||
) {
|
) {
|
||||||
@@ -323,6 +378,13 @@ export const ExplorerFolderNodeFolder = ({
|
|||||||
data.source.data.from.nodeId,
|
data.source.data.from.nodeId,
|
||||||
node.indexAt(at, dropAtNode.id)
|
node.indexAt(at, dropAtNode.id)
|
||||||
);
|
);
|
||||||
|
mixpanel.track('FolderLinkMoved', {
|
||||||
|
page: 'sidebar',
|
||||||
|
module: 'organize',
|
||||||
|
control: `drop folder link ${at === 'before' ? 'above' : 'below'} node`,
|
||||||
|
type: data.source.data.entity?.type,
|
||||||
|
id: data.source.data.entity?.id,
|
||||||
|
});
|
||||||
} else if (
|
} else if (
|
||||||
data.source.data.entity?.type === 'collection' ||
|
data.source.data.entity?.type === 'collection' ||
|
||||||
data.source.data.entity?.type === 'doc' ||
|
data.source.data.entity?.type === 'doc' ||
|
||||||
@@ -333,6 +395,13 @@ export const ExplorerFolderNodeFolder = ({
|
|||||||
data.source.data.entity.id,
|
data.source.data.entity.id,
|
||||||
node.indexAt(at, dropAtNode.id)
|
node.indexAt(at, dropAtNode.id)
|
||||||
);
|
);
|
||||||
|
mixpanel.track('FolderLinkCreated', {
|
||||||
|
page: 'sidebar',
|
||||||
|
module: 'organize',
|
||||||
|
control: `drop entity ${at === 'before' ? 'above' : 'below'} node`,
|
||||||
|
type: data.source.data.entity?.type,
|
||||||
|
id: data.source.data.entity?.id,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} else if (data.treeInstruction?.type === 'reparent') {
|
} else if (data.treeInstruction?.type === 'reparent') {
|
||||||
const currentLevel = data.treeInstruction.currentLevel;
|
const currentLevel = data.treeInstruction.currentLevel;
|
||||||
@@ -481,6 +550,18 @@ export const ExplorerFolderNodeFolder = ({
|
|||||||
const newDoc = docsService.createDoc();
|
const newDoc = docsService.createDoc();
|
||||||
node.createLink('doc', newDoc.id, node.indexAt('before'));
|
node.createLink('doc', newDoc.id, node.indexAt('before'));
|
||||||
workbenchService.workbench.openDoc(newDoc.id);
|
workbenchService.workbench.openDoc(newDoc.id);
|
||||||
|
mixpanel.track('DocCreated', {
|
||||||
|
page: 'sidebar',
|
||||||
|
module: 'organize',
|
||||||
|
control: `folder new doc button`,
|
||||||
|
});
|
||||||
|
mixpanel.track('FolderLinkCreated', {
|
||||||
|
page: 'sidebar',
|
||||||
|
module: 'organize',
|
||||||
|
control: `folder new doc button`,
|
||||||
|
type: 'doc',
|
||||||
|
id: newDoc.id,
|
||||||
|
});
|
||||||
setCollapsed(false);
|
setCollapsed(false);
|
||||||
}, [docsService, node, workbenchService.workbench]);
|
}, [docsService, node, workbenchService.workbench]);
|
||||||
|
|
||||||
@@ -489,6 +570,11 @@ export const ExplorerFolderNodeFolder = ({
|
|||||||
t['com.affine.rootAppSidebar.organize.new-folders'](),
|
t['com.affine.rootAppSidebar.organize.new-folders'](),
|
||||||
node.indexAt('before')
|
node.indexAt('before')
|
||||||
);
|
);
|
||||||
|
mixpanel.track('FolderCreated', {
|
||||||
|
page: 'sidebar',
|
||||||
|
module: 'organize',
|
||||||
|
control: `create sub folder`,
|
||||||
|
});
|
||||||
setCollapsed(false);
|
setCollapsed(false);
|
||||||
setNewFolderId(newFolderId);
|
setNewFolderId(newFolderId);
|
||||||
}, [node, t]);
|
}, [node, t]);
|
||||||
@@ -514,9 +600,16 @@ export const ExplorerFolderNodeFolder = ({
|
|||||||
!!node.data$.value && removedItemIds.includes(node.data$.value)
|
!!node.data$.value && removedItemIds.includes(node.data$.value)
|
||||||
);
|
);
|
||||||
|
|
||||||
newItemIds.forEach(id =>
|
newItemIds.forEach(id => {
|
||||||
node.createLink(type, id, node.indexAt('after'))
|
node.createLink(type, id, node.indexAt('after'));
|
||||||
);
|
mixpanel.track('FolderLinkCreated', {
|
||||||
|
page: 'sidebar',
|
||||||
|
module: 'organize',
|
||||||
|
control: `add selector`,
|
||||||
|
type,
|
||||||
|
id,
|
||||||
|
});
|
||||||
|
});
|
||||||
removedItems.forEach(node => node.delete());
|
removedItems.forEach(node => node.delete());
|
||||||
const updated = newItemIds.length + removedItems.length;
|
const updated = newItemIds.length + removedItems.length;
|
||||||
updated && setCollapsed(false);
|
updated && setCollapsed(false);
|
||||||
@@ -649,6 +742,19 @@ export const ExplorerFolderNodeFolder = ({
|
|||||||
|
|
||||||
const handleDeleteChildren = useCallback((node: FolderNode) => {
|
const handleDeleteChildren = useCallback((node: FolderNode) => {
|
||||||
node.delete();
|
node.delete();
|
||||||
|
if (node.type$.value === 'folder') {
|
||||||
|
mixpanel.track('FolderDeleted', {
|
||||||
|
page: 'sidebar',
|
||||||
|
module: 'organize',
|
||||||
|
control: 'remove from folder button',
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
mixpanel.track('FolderLinkDeleted', {
|
||||||
|
page: 'sidebar',
|
||||||
|
module: 'organize',
|
||||||
|
control: 'remove from folder button',
|
||||||
|
});
|
||||||
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const childrenOperations = useCallback(
|
const childrenOperations = useCallback(
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import {
|
|||||||
type DropTargetOptions,
|
type DropTargetOptions,
|
||||||
toast,
|
toast,
|
||||||
} from '@affine/component';
|
} from '@affine/component';
|
||||||
|
import { mixpanel } from '@affine/core/mixpanel';
|
||||||
import type { Tag } from '@affine/core/modules/tag';
|
import type { Tag } from '@affine/core/modules/tag';
|
||||||
import { TagService } from '@affine/core/modules/tag';
|
import { TagService } from '@affine/core/modules/tag';
|
||||||
import type { AffineDNDData } from '@affine/core/types/dnd';
|
import type { AffineDNDData } from '@affine/core/types/dnd';
|
||||||
@@ -81,8 +82,13 @@ export const ExplorerTagNode = ({
|
|||||||
|
|
||||||
const handleRename = useCallback(
|
const handleRename = useCallback(
|
||||||
(newName: string) => {
|
(newName: string) => {
|
||||||
if (tagRecord) {
|
if (tagRecord && tagRecord.value$.value !== newName) {
|
||||||
tagRecord.rename(newName);
|
tagRecord.rename(newName);
|
||||||
|
mixpanel.track('TagRenamed', {
|
||||||
|
page: 'sidebar',
|
||||||
|
module: 'tag',
|
||||||
|
control: 'tag rename',
|
||||||
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[tagRecord]
|
[tagRecord]
|
||||||
@@ -93,6 +99,11 @@ export const ExplorerTagNode = ({
|
|||||||
if (data.treeInstruction?.type === 'make-child' && tagRecord) {
|
if (data.treeInstruction?.type === 'make-child' && tagRecord) {
|
||||||
if (data.source.data.entity?.type === 'doc') {
|
if (data.source.data.entity?.type === 'doc') {
|
||||||
tagRecord.tag(data.source.data.entity.id);
|
tagRecord.tag(data.source.data.entity.id);
|
||||||
|
mixpanel.track('DocTagged', {
|
||||||
|
page: 'sidebar',
|
||||||
|
module: 'tag',
|
||||||
|
control: 'drop doc on tag',
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
toast(t['com.affine.rootAppSidebar.tag.doc-only']());
|
toast(t['com.affine.rootAppSidebar.tag.doc-only']());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import {
|
|||||||
toast,
|
toast,
|
||||||
} from '@affine/component';
|
} from '@affine/component';
|
||||||
import { useAppSettingHelper } from '@affine/core/hooks/affine/use-app-setting-helper';
|
import { useAppSettingHelper } from '@affine/core/hooks/affine/use-app-setting-helper';
|
||||||
|
import { mixpanel } from '@affine/core/mixpanel';
|
||||||
import { FavoriteService } from '@affine/core/modules/favorite';
|
import { FavoriteService } from '@affine/core/modules/favorite';
|
||||||
import { TagService } from '@affine/core/modules/tag';
|
import { TagService } from '@affine/core/modules/tag';
|
||||||
import { WorkbenchService } from '@affine/core/modules/workbench';
|
import { WorkbenchService } from '@affine/core/modules/workbench';
|
||||||
@@ -49,6 +50,16 @@ export const useExplorerTagNodeOperations = (
|
|||||||
if (tagRecord) {
|
if (tagRecord) {
|
||||||
const newDoc = docsService.createDoc();
|
const newDoc = docsService.createDoc();
|
||||||
tagRecord?.tag(newDoc.id);
|
tagRecord?.tag(newDoc.id);
|
||||||
|
mixpanel.track('DocCreated', {
|
||||||
|
page: 'sidebar',
|
||||||
|
module: 'tag',
|
||||||
|
control: 'add doc button',
|
||||||
|
});
|
||||||
|
mixpanel.track('DocTagged', {
|
||||||
|
page: 'sidebar',
|
||||||
|
module: 'tag',
|
||||||
|
control: 'add doc button',
|
||||||
|
});
|
||||||
workbenchService.workbench.openDoc(newDoc.id);
|
workbenchService.workbench.openDoc(newDoc.id);
|
||||||
openNodeCollapsed();
|
openNodeCollapsed();
|
||||||
}
|
}
|
||||||
@@ -56,6 +67,11 @@ export const useExplorerTagNodeOperations = (
|
|||||||
|
|
||||||
const handleMoveToTrash = useCallback(() => {
|
const handleMoveToTrash = useCallback(() => {
|
||||||
tagService.tagList.deleteTag(tagId);
|
tagService.tagList.deleteTag(tagId);
|
||||||
|
mixpanel.track('TagDeleted', {
|
||||||
|
page: 'sidebar',
|
||||||
|
module: 'tag',
|
||||||
|
control: 'remove tag button',
|
||||||
|
});
|
||||||
toast(t['com.affine.tags.delete-tags.toast']());
|
toast(t['com.affine.tags.delete-tags.toast']());
|
||||||
}, [t, tagId, tagService.tagList]);
|
}, [t, tagId, tagService.tagList]);
|
||||||
|
|
||||||
@@ -63,10 +79,22 @@ export const useExplorerTagNodeOperations = (
|
|||||||
workbenchService.workbench.openTag(tagId, {
|
workbenchService.workbench.openTag(tagId, {
|
||||||
at: 'beside',
|
at: 'beside',
|
||||||
});
|
});
|
||||||
|
mixpanel.track('OpenInSplitView', {
|
||||||
|
page: 'sidebar',
|
||||||
|
module: 'tag',
|
||||||
|
control: 'open in split view button',
|
||||||
|
});
|
||||||
}, [tagId, workbenchService]);
|
}, [tagId, workbenchService]);
|
||||||
|
|
||||||
const handleToggleFavoriteTag = useCallback(() => {
|
const handleToggleFavoriteTag = useCallback(() => {
|
||||||
favoriteService.favoriteList.toggle('tag', tagId);
|
favoriteService.favoriteList.toggle('tag', tagId);
|
||||||
|
mixpanel.track('ToggleFavorite', {
|
||||||
|
page: 'sidebar',
|
||||||
|
module: 'tag',
|
||||||
|
control: 'toggle favorite tag button',
|
||||||
|
type: 'tag',
|
||||||
|
id: tagId,
|
||||||
|
});
|
||||||
}, [favoriteService, tagId]);
|
}, [favoriteService, tagId]);
|
||||||
|
|
||||||
return useMemo(
|
return useMemo(
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { IconButton } from '@affine/component';
|
|||||||
import { CategoryDivider } from '@affine/core/components/app-sidebar';
|
import { CategoryDivider } from '@affine/core/components/app-sidebar';
|
||||||
import { useEditCollectionName } from '@affine/core/components/page-list';
|
import { useEditCollectionName } from '@affine/core/components/page-list';
|
||||||
import { createEmptyCollection } from '@affine/core/components/page-list/use-collection-manager';
|
import { createEmptyCollection } from '@affine/core/components/page-list/use-collection-manager';
|
||||||
|
import { mixpanel } from '@affine/core/mixpanel';
|
||||||
import { CollectionService } from '@affine/core/modules/collection';
|
import { CollectionService } from '@affine/core/modules/collection';
|
||||||
import { ExplorerTreeRoot } from '@affine/core/modules/explorer/views/tree';
|
import { ExplorerTreeRoot } from '@affine/core/modules/explorer/views/tree';
|
||||||
import { WorkbenchService } from '@affine/core/modules/workbench';
|
import { WorkbenchService } from '@affine/core/modules/workbench';
|
||||||
@@ -38,6 +39,11 @@ export const ExplorerCollections = ({
|
|||||||
.then(name => {
|
.then(name => {
|
||||||
const id = nanoid();
|
const id = nanoid();
|
||||||
collectionService.addCollection(createEmptyCollection(id, { name }));
|
collectionService.addCollection(createEmptyCollection(id, { name }));
|
||||||
|
mixpanel.track('CollectionCreated', {
|
||||||
|
page: 'sidebar',
|
||||||
|
module: 'collections',
|
||||||
|
control: 'new collection button',
|
||||||
|
});
|
||||||
workbenchService.workbench.openCollection(id);
|
workbenchService.workbench.openCollection(id);
|
||||||
setCollapsed(false);
|
setCollapsed(false);
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import {
|
|||||||
useDropTarget,
|
useDropTarget,
|
||||||
} from '@affine/component';
|
} from '@affine/component';
|
||||||
import { CategoryDivider } from '@affine/core/components/app-sidebar';
|
import { CategoryDivider } from '@affine/core/components/app-sidebar';
|
||||||
|
import { mixpanel } from '@affine/core/mixpanel';
|
||||||
import {
|
import {
|
||||||
DropEffect,
|
DropEffect,
|
||||||
type ExplorerTreeNodeDropEffect,
|
type ExplorerTreeNodeDropEffect,
|
||||||
@@ -57,6 +58,13 @@ export const ExplorerFavorites = ({
|
|||||||
data.source.data.entity.id,
|
data.source.data.entity.id,
|
||||||
favoriteService.favoriteList.indexAt('before')
|
favoriteService.favoriteList.indexAt('before')
|
||||||
);
|
);
|
||||||
|
mixpanel.track('AddFavorite', {
|
||||||
|
page: 'sidebar',
|
||||||
|
module: 'favorite',
|
||||||
|
control: 'drop entity to favorite',
|
||||||
|
type: data.source.data.entity.type,
|
||||||
|
id: data.source.data.entity.id,
|
||||||
|
});
|
||||||
setCollapsed(false);
|
setCollapsed(false);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -89,6 +97,18 @@ export const ExplorerFavorites = ({
|
|||||||
newDoc.id,
|
newDoc.id,
|
||||||
favoriteService.favoriteList.indexAt('before')
|
favoriteService.favoriteList.indexAt('before')
|
||||||
);
|
);
|
||||||
|
mixpanel.track('DocCreated', {
|
||||||
|
page: 'sidebar',
|
||||||
|
module: 'favorites',
|
||||||
|
control: 'new favorite doc button',
|
||||||
|
});
|
||||||
|
mixpanel.track('AddFavorite', {
|
||||||
|
page: 'sidebar',
|
||||||
|
module: 'favorite',
|
||||||
|
control: 'new favorite doc button',
|
||||||
|
type: 'doc',
|
||||||
|
id: newDoc.id,
|
||||||
|
});
|
||||||
workbenchService.workbench.openDoc(newDoc.id);
|
workbenchService.workbench.openDoc(newDoc.id);
|
||||||
setCollapsed(false);
|
setCollapsed(false);
|
||||||
}, [docsService, favoriteService, workbenchService]);
|
}, [docsService, favoriteService, workbenchService]);
|
||||||
@@ -118,6 +138,13 @@ export const ExplorerFavorites = ({
|
|||||||
favorite
|
favorite
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
mixpanel.track('ReorderFavorite', {
|
||||||
|
page: 'sidebar',
|
||||||
|
module: 'favorite',
|
||||||
|
control: 'drop to reorder favorite',
|
||||||
|
type: data.source.data.entity.type,
|
||||||
|
id: data.source.data.entity.id,
|
||||||
|
});
|
||||||
} else if (
|
} else if (
|
||||||
data.source.data.entity?.type &&
|
data.source.data.entity?.type &&
|
||||||
isFavoriteSupportType(data.source.data.entity.type)
|
isFavoriteSupportType(data.source.data.entity.type)
|
||||||
@@ -132,6 +159,13 @@ export const ExplorerFavorites = ({
|
|||||||
favorite
|
favorite
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
mixpanel.track('AddFavorite', {
|
||||||
|
page: 'sidebar',
|
||||||
|
module: 'favorite',
|
||||||
|
control: 'drop entity to favorite',
|
||||||
|
type: data.source.data.entity.type,
|
||||||
|
id: data.source.data.entity.id,
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
return; // not supported
|
return; // not supported
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { IconButton, useConfirmModal } from '@affine/component';
|
import { IconButton, useConfirmModal } from '@affine/component';
|
||||||
import { CategoryDivider } from '@affine/core/components/app-sidebar';
|
import { CategoryDivider } from '@affine/core/components/app-sidebar';
|
||||||
|
import { mixpanel } from '@affine/core/mixpanel';
|
||||||
import { ExplorerTreeRoot } from '@affine/core/modules/explorer/views/tree';
|
import { ExplorerTreeRoot } from '@affine/core/modules/explorer/views/tree';
|
||||||
import { FavoriteItemsAdapter } from '@affine/core/modules/properties';
|
import { FavoriteItemsAdapter } from '@affine/core/modules/properties';
|
||||||
import { Trans, useI18n } from '@affine/i18n';
|
import { Trans, useI18n } from '@affine/i18n';
|
||||||
@@ -64,8 +65,18 @@ export const ExplorerMigrationFavorites = ({
|
|||||||
t['com.affine.rootAppSidebar.migration-data.clean-all.cancel'](),
|
t['com.affine.rootAppSidebar.migration-data.clean-all.cancel'](),
|
||||||
onConfirm() {
|
onConfirm() {
|
||||||
favoriteItemsAdapter.clearAll();
|
favoriteItemsAdapter.clearAll();
|
||||||
|
mixpanel.track('AllMigrationDataCleared', {
|
||||||
|
page: 'sidebar',
|
||||||
|
module: 'migration data',
|
||||||
|
control: 'clear button',
|
||||||
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
mixpanel.track('ClickClearMigrationDataButton', {
|
||||||
|
page: 'sidebar',
|
||||||
|
module: 'migration data',
|
||||||
|
control: 'clear button',
|
||||||
|
});
|
||||||
}, [favoriteItemsAdapter, openConfirmModal, t]);
|
}, [favoriteItemsAdapter, openConfirmModal, t]);
|
||||||
|
|
||||||
const handleClickHelp = useCallback(() => {
|
const handleClickHelp = useCallback(() => {
|
||||||
@@ -89,6 +100,11 @@ export const ExplorerMigrationFavorites = ({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
mixpanel.track('OpenMigrationDataHelp', {
|
||||||
|
page: 'sidebar',
|
||||||
|
module: 'migration data',
|
||||||
|
control: 'help button',
|
||||||
|
});
|
||||||
}, [handleClickClear, openConfirmModal, t]);
|
}, [handleClickClear, openConfirmModal, t]);
|
||||||
|
|
||||||
if (favorites.length === 0) {
|
if (favorites.length === 0) {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import {
|
|||||||
toast,
|
toast,
|
||||||
} from '@affine/component';
|
} from '@affine/component';
|
||||||
import { CategoryDivider } from '@affine/core/components/app-sidebar';
|
import { CategoryDivider } from '@affine/core/components/app-sidebar';
|
||||||
|
import { mixpanel } from '@affine/core/mixpanel';
|
||||||
import {
|
import {
|
||||||
type ExplorerTreeNodeDropEffect,
|
type ExplorerTreeNodeDropEffect,
|
||||||
ExplorerTreeRoot,
|
ExplorerTreeRoot,
|
||||||
@@ -44,6 +45,11 @@ export const ExplorerOrganize = ({
|
|||||||
'New Folder',
|
'New Folder',
|
||||||
rootFolder.indexAt('before')
|
rootFolder.indexAt('before')
|
||||||
);
|
);
|
||||||
|
mixpanel.track('FolderCreated', {
|
||||||
|
page: 'sidebar',
|
||||||
|
module: 'organize',
|
||||||
|
control: 'new folder',
|
||||||
|
});
|
||||||
setNewFolderId(newFolderId);
|
setNewFolderId(newFolderId);
|
||||||
setCollapsed(false);
|
setCollapsed(false);
|
||||||
}, [rootFolder]);
|
}, [rootFolder]);
|
||||||
@@ -64,6 +70,13 @@ export const ExplorerOrganize = ({
|
|||||||
data.source.data.entity.id,
|
data.source.data.entity.id,
|
||||||
rootFolder.indexAt(at, node.id)
|
rootFolder.indexAt(at, node.id)
|
||||||
);
|
);
|
||||||
|
mixpanel.track('FolderMoved', {
|
||||||
|
page: 'sidebar',
|
||||||
|
module: 'organize',
|
||||||
|
control: 'drop at root',
|
||||||
|
type: 'folder',
|
||||||
|
id: node.id,
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
toast(t['com.affine.rootAppSidebar.organize.root-folder-only']());
|
toast(t['com.affine.rootAppSidebar.organize.root-folder-only']());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { IconButton } from '@affine/component';
|
import { IconButton } from '@affine/component';
|
||||||
import { CategoryDivider } from '@affine/core/components/app-sidebar';
|
import { CategoryDivider } from '@affine/core/components/app-sidebar';
|
||||||
|
import { mixpanel } from '@affine/core/mixpanel';
|
||||||
import { ExplorerTreeRoot } from '@affine/core/modules/explorer/views/tree';
|
import { ExplorerTreeRoot } from '@affine/core/modules/explorer/views/tree';
|
||||||
import type { Tag } from '@affine/core/modules/tag';
|
import type { Tag } from '@affine/core/modules/tag';
|
||||||
import { TagService } from '@affine/core/modules/tag';
|
import { TagService } from '@affine/core/modules/tag';
|
||||||
@@ -34,6 +35,11 @@ export const ExplorerTags = ({
|
|||||||
tagService.randomTagColor()
|
tagService.randomTagColor()
|
||||||
);
|
);
|
||||||
setCreatedTag(newTags);
|
setCreatedTag(newTags);
|
||||||
|
mixpanel.track('TagCreated', {
|
||||||
|
page: 'sidebar',
|
||||||
|
module: 'tags',
|
||||||
|
control: 'new tag button',
|
||||||
|
});
|
||||||
setCollapsed(false);
|
setCollapsed(false);
|
||||||
}, [t, tagService]);
|
}, [t, tagService]);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user