feat: init
Some checks failed
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled

This commit is contained in:
chuan
2025-11-11 01:56:44 +08:00
commit bba4bb40c8
4638 changed files with 447437 additions and 0 deletions

View File

@@ -0,0 +1,2 @@
export * from "./use-editor-config";
export * from "./use-editor-mention";

View File

@@ -0,0 +1,100 @@
import { useCallback } from "react";
// plane imports
import type { TFileHandler } from "@plane/editor";
import { getEditorAssetDownloadSrc, getEditorAssetSrc } from "@plane/utils";
// hooks
import { useEditorAsset } from "@/hooks/store/use-editor-asset";
// plane web hooks
import { useExtendedEditorConfig } from "@/plane-web/hooks/editor/use-extended-editor-config";
import { useFileSize } from "@/plane-web/hooks/use-file-size";
// services
import { FileService } from "@/services/file.service";
const fileService = new FileService();
type TArgs = {
projectId?: string;
uploadFile: TFileHandler["upload"];
workspaceId: string;
workspaceSlug: string;
};
export const useEditorConfig = () => {
// store hooks
const { assetsUploadPercentage } = useEditorAsset();
// file size
const { maxFileSize } = useFileSize();
const { getExtendedEditorFileHandlers } = useExtendedEditorConfig();
const getEditorFileHandlers = useCallback(
(args: TArgs): TFileHandler => {
const { projectId, uploadFile, workspaceId, workspaceSlug } = args;
return {
assetsUploadStatus: assetsUploadPercentage,
cancel: fileService.cancelUpload,
checkIfAssetExists: async (assetId: string) => {
const res = await fileService.checkIfAssetExists(workspaceSlug, assetId);
return res?.exists ?? false;
},
delete: async (src: string) => {
if (src?.startsWith("http")) {
await fileService.deleteOldWorkspaceAsset(workspaceId, src);
} else {
await fileService.deleteNewAsset(
getEditorAssetSrc({
assetId: src,
projectId,
workspaceSlug,
}) ?? ""
);
}
},
getAssetDownloadSrc: async (path) => {
if (!path) return "";
if (path?.startsWith("http")) {
return path;
} else {
return (
getEditorAssetDownloadSrc({
assetId: path,
projectId,
workspaceSlug,
}) ?? ""
);
}
},
getAssetSrc: async (path) => {
if (!path) return "";
if (path?.startsWith("http")) {
return path;
} else {
return (
getEditorAssetSrc({
assetId: path,
projectId,
workspaceSlug,
}) ?? ""
);
}
},
restore: async (src: string) => {
if (src?.startsWith("http")) {
await fileService.restoreOldEditorAsset(workspaceId, src);
} else {
await fileService.restoreNewAsset(workspaceSlug, src);
}
},
upload: uploadFile,
validation: {
maxFileSize,
},
...getExtendedEditorFileHandlers({ projectId, workspaceSlug }),
};
},
[assetsUploadPercentage, getExtendedEditorFileHandlers, maxFileSize]
);
return {
getEditorFileHandlers,
};
};

View File

@@ -0,0 +1,76 @@
import { useCallback } from "react";
// plane editor
import type { TMentionSection, TMentionSuggestion } from "@plane/editor";
// plane types
import type { TSearchEntities, TSearchEntityRequestPayload, TSearchResponse, TUserSearchResponse } from "@plane/types";
// plane ui
import { Avatar } from "@plane/ui";
// helpers
import { getFileURL } from "@plane/utils";
// plane web constants
import { EDITOR_MENTION_TYPES } from "@/plane-web/constants/editor";
// plane web hooks
import { useAdditionalEditorMention } from "@/plane-web/hooks/use-additional-editor-mention";
type TArgs = {
searchEntity: (payload: TSearchEntityRequestPayload) => Promise<TSearchResponse>;
};
export const useEditorMention = (args: TArgs) => {
const { searchEntity } = args;
// additional mentions
const { updateAdditionalSections } = useAdditionalEditorMention();
// fetch mentions handler
const fetchMentions = useCallback(
async (query: string): Promise<TMentionSection[]> => {
try {
const res = await searchEntity({
count: 5,
query_type: EDITOR_MENTION_TYPES,
query,
});
const suggestionSections: TMentionSection[] = [];
if (!res) {
throw new Error("No response found");
}
Object.keys(res).map((key) => {
const responseKey = key as TSearchEntities;
const response = res[responseKey];
if (responseKey === "user_mention" && response && response.length > 0) {
const items: TMentionSuggestion[] = (response as TUserSearchResponse[]).map((user) => ({
icon: (
<Avatar
className="flex-shrink-0"
src={getFileURL(user.member__avatar_url)}
name={user.member__display_name}
/>
),
id: user.member__id,
entity_identifier: user.member__id,
entity_name: "user_mention",
title: user.member__display_name,
}));
suggestionSections.push({
key: "users",
title: "Users",
items,
});
}
});
updateAdditionalSections({
response: res,
sections: suggestionSections,
});
return suggestionSections;
} catch (error) {
console.error("Error in fetching mentions for project pages:", error);
throw error;
}
},
[searchEntity, updateAdditionalSections]
);
return {
fetchMentions,
};
};