Compare commits

...
Author SHA1 Message Date
Palanikannan M f1db64827f fix: mention id 2025-03-19 17:48:13 +05:30
Palanikannan M 8aa5cbccf3 Merge branch 'preview' into devin/1734544044-refactor-live-server 2025-03-19 17:43:10 +05:30
Palanikannan M cd146aa608 fix: store hooks fixed 2025-03-19 17:26:00 +05:30
Prateek ShouryaandGitHub f82d4a9ead [WEB-3589] improvement: reset language to default on sign out (#6775) 2025-03-19 14:42:19 +05:30
Anmol Singh BhatiaandGitHub 3f22642732 [WEB-3580] fix: automations settings translation (#6767) 2025-03-18 16:34:58 +05:30
e339b7ad8f [WEB-3545] feat: language translations (#6762)
* feat(translations): add Korean translation (#6755)

* feat(translations): init Korean translation

Co-authored-by: NavyStack <navystack@askfront.com>
Co-authored-by: FVOCI <150913557+fvoci@users.noreply.github.com>

* feat(translations): add rough Korean translation

Co-authored-by: NavyStack <navystack@askfront.com>
Co-authored-by: FVOCI <150913557+fvoci@users.noreply.github.com>

---------

Co-authored-by: FVOCI <150913557+fvoci@users.noreply.github.com>

* feat(translations): add Slovak, Deutsch, Ukrainian and Polish translation (#6743)

* feat(translation): add Slovak translation

* feat(translation): add Slovak translation for workspace

* feat(translation): improved Slovak translation for views

* feat(translation): add Deutsch translation

* feat(translation): add Ukrainian translation

* feat(translation): add Polish translation

---------

Co-authored-by: sriram veeraghanta <veeraghanta.sriram@gmail.com>

* fix: project cycle translations

* fix: build error

* feat: Add zh-TW Traditional Chinese locale (#6764)

Co-authored-by: sriram veeraghanta <veeraghanta.sriram@gmail.com>

* chore: zh-TW core translation updated

---------

Co-authored-by: NavyStack <navystack@askfront.com>
Co-authored-by: FVOCI <150913557+fvoci@users.noreply.github.com>
Co-authored-by: Ján Regeš <jan.reges@gmail.com>
Co-authored-by: sriram veeraghanta <veeraghanta.sriram@gmail.com>
Co-authored-by: Peter Dave Hello <hsu@peterdavehello.org>
2025-03-18 13:35:46 +05:30
Vamsi KrishnaandGitHub d4991b9a48 chore: issue filters refactor (#6742)
* chore: issue filters refactor

* chore: update helper funciton implementation

* chore: removed redundant components
2025-03-17 15:45:34 +05:30
Prateek ShouryaandGitHub 1bf683e044 improvement: command palette search results (#6761) 2025-03-17 15:45:03 +05:30
Akshita GoyalandGitHub 807148671f fix: build (#6760) 2025-03-17 14:38:46 +05:30
d2b81ad2da fix: favorite mutation on quick actions (#6741)
* fix: fav mutation on quick actions

* fix: user favorite fetch

* fix: exist validation

---------

Co-authored-by: pablohashescobar <nikhilschacko@gmail.com>
2025-03-17 14:14:45 +05:30
sriram veeraghanta 3d14c9d9fe fix: build test pull request changes 2025-03-17 00:38:51 +05:30
sriram veeraghanta d7f40cf578 fix: remove files changed step from branch build workflow 2025-03-17 00:26:10 +05:30
Aaryan KhandelwalandGitHub b370ef72ee [RANTS-46] fix: modules list sidebar position (#6754) 2025-03-16 23:50:04 +05:30
sriram veeraghanta 0341205666 fix: live server dev port to 3100 2025-03-13 15:42:43 +05:30
Palanikannan M feab2b218d chore: renamed funcion name 2025-02-11 16:02:14 +05:30
Palanikannan M 4acc5989dc fix: refactored the component to use the same function 2025-02-11 15:57:12 +05:30
Palanikannan M a1b91a58a1 fix: copying text in mentions 2025-02-11 15:47:43 +05:30
Palanikannan M 5fafdddb1e fix: markdown for mentions fixed 2025-02-11 15:00:42 +05:30
58 changed files with 14365 additions and 277 deletions
-50
View File
@@ -47,12 +47,6 @@ jobs:
gh_buildx_version: ${{ steps.set_env_variables.outputs.BUILDX_VERSION }}
gh_buildx_platforms: ${{ steps.set_env_variables.outputs.BUILDX_PLATFORMS }}
gh_buildx_endpoint: ${{ steps.set_env_variables.outputs.BUILDX_ENDPOINT }}
build_proxy: ${{ steps.changed_files.outputs.proxy_any_changed }}
build_apiserver: ${{ steps.changed_files.outputs.apiserver_any_changed }}
build_admin: ${{ steps.changed_files.outputs.admin_any_changed }}
build_space: ${{ steps.changed_files.outputs.space_any_changed }}
build_web: ${{ steps.changed_files.outputs.web_any_changed }}
build_live: ${{ steps.changed_files.outputs.live_any_changed }}
dh_img_web: ${{ steps.set_env_variables.outputs.DH_IMG_WEB }}
dh_img_space: ${{ steps.set_env_variables.outputs.DH_IMG_SPACE }}
@@ -123,46 +117,7 @@ jobs:
name: Checkout Files
uses: actions/checkout@v4
- name: Get changed files
id: changed_files
uses: tj-actions/changed-files@v42
with:
files_yaml: |
apiserver:
- apiserver/**
proxy:
- nginx/**
admin:
- admin/**
- packages/**
- "package.json"
- "yarn.lock"
- "tsconfig.json"
- "turbo.json"
space:
- space/**
- packages/**
- "package.json"
- "yarn.lock"
- "tsconfig.json"
- "turbo.json"
web:
- web/**
- packages/**
- "package.json"
- "yarn.lock"
- "tsconfig.json"
- "turbo.json"
live:
- live/**
- packages/**
- 'package.json'
- 'yarn.lock'
- 'tsconfig.json'
- 'turbo.json'
branch_build_push_admin:
if: ${{ needs.branch_build_setup.outputs.build_admin == 'true' || github.event_name == 'workflow_dispatch' || needs.branch_build_setup.outputs.gh_branch_name == 'master' }}
name: Build-Push Admin Docker Image
runs-on: ubuntu-22.04
needs: [branch_build_setup]
@@ -185,7 +140,6 @@ jobs:
buildx-endpoint: ${{ needs.branch_build_setup.outputs.gh_buildx_endpoint }}
branch_build_push_web:
if: ${{ needs.branch_build_setup.outputs.build_web == 'true' || github.event_name == 'workflow_dispatch' || needs.branch_build_setup.outputs.gh_branch_name == 'master' }}
name: Build-Push Web Docker Image
runs-on: ubuntu-22.04
needs: [branch_build_setup]
@@ -208,7 +162,6 @@ jobs:
buildx-endpoint: ${{ needs.branch_build_setup.outputs.gh_buildx_endpoint }}
branch_build_push_space:
if: ${{ needs.branch_build_setup.outputs.build_space == 'true' || github.event_name == 'workflow_dispatch' || needs.branch_build_setup.outputs.gh_branch_name == 'master' }}
name: Build-Push Space Docker Image
runs-on: ubuntu-22.04
needs: [branch_build_setup]
@@ -231,7 +184,6 @@ jobs:
buildx-endpoint: ${{ needs.branch_build_setup.outputs.gh_buildx_endpoint }}
branch_build_push_live:
if: ${{ needs.branch_build_setup.outputs.build_live == 'true' || github.event_name == 'workflow_dispatch' || needs.branch_build_setup.outputs.gh_branch_name == 'master' }}
name: Build-Push Live Collaboration Docker Image
runs-on: ubuntu-22.04
needs: [branch_build_setup]
@@ -254,7 +206,6 @@ jobs:
buildx-endpoint: ${{ needs.branch_build_setup.outputs.gh_buildx_endpoint }}
branch_build_push_apiserver:
if: ${{ needs.branch_build_setup.outputs.build_apiserver == 'true' || github.event_name == 'workflow_dispatch' || needs.branch_build_setup.outputs.gh_branch_name == 'master' }}
name: Build-Push API Server Docker Image
runs-on: ubuntu-22.04
needs: [branch_build_setup]
@@ -277,7 +228,6 @@ jobs:
buildx-endpoint: ${{ needs.branch_build_setup.outputs.gh_buildx_endpoint }}
branch_build_push_proxy:
if: ${{ needs.branch_build_setup.outputs.build_proxy == 'true' || github.event_name == 'workflow_dispatch' || needs.branch_build_setup.outputs.gh_branch_name == 'master' }}
name: Build-Push Proxy Docker Image
runs-on: ubuntu-22.04
needs: [branch_build_setup]
+4 -47
View File
@@ -6,49 +6,9 @@ on:
types: ["opened", "synchronize", "ready_for_review"]
jobs:
get-changed-files:
lint-apiserver:
if: github.event.pull_request.draft == false
runs-on: ubuntu-latest
outputs:
apiserver_changed: ${{ steps.changed-files.outputs.apiserver_any_changed }}
admin_changed: ${{ steps.changed-files.outputs.admin_any_changed }}
space_changed: ${{ steps.changed-files.outputs.space_any_changed }}
web_changed: ${{ steps.changed-files.outputs.web_any_changed }}
steps:
- uses: actions/checkout@v4
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v44
with:
files_yaml: |
apiserver:
- apiserver/**
admin:
- admin/**
- packages/**
- 'package.json'
- 'yarn.lock'
- 'tsconfig.json'
- 'turbo.json'
space:
- space/**
- packages/**
- 'package.json'
- 'yarn.lock'
- 'tsconfig.json'
- 'turbo.json'
web:
- web/**
- packages/**
- 'package.json'
- 'yarn.lock'
- 'tsconfig.json'
- 'turbo.json'
lint-apiserver:
needs: get-changed-files
runs-on: ubuntu-latest
if: needs.get-changed-files.outputs.apiserver_changed == 'true'
steps:
- uses: actions/checkout@v4
- name: Set up Python
@@ -63,8 +23,7 @@ jobs:
run: ruff check --fix apiserver
lint-admin:
needs: get-changed-files
if: needs.get-changed-files.outputs.admin_changed == 'true'
if: github.event.pull_request.draft == false
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
@@ -76,8 +35,7 @@ jobs:
- run: yarn lint --filter=admin
lint-space:
needs: get-changed-files
if: needs.get-changed-files.outputs.space_changed == 'true'
if: github.event.pull_request.draft == false
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
@@ -89,8 +47,7 @@ jobs:
- run: yarn lint --filter=space
lint-web:
needs: get-changed-files
if: needs.get-changed-files.outputs.web_changed == 'true'
if: github.event.pull_request.draft == false
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
@@ -34,6 +34,22 @@ class WorkspaceFavoriteEndpoint(BaseAPIView):
def post(self, request, slug):
try:
workspace = Workspace.objects.get(slug=slug)
# If the favorite exists return
if request.data.get("entity_identifier"):
user_favorites = UserFavorite.objects.filter(
workspace=workspace,
user_id=request.user.id,
entity_type=request.data.get("entity_type"),
entity_identifier=request.data.get("entity_identifier"),
).first()
# If the favorite exists return
if user_favorites:
serializer = UserFavoriteSerializer(user_favorites)
return Response(serializer.data, status=status.HTTP_200_OK)
# else create a new favorite
serializer = UserFavoriteSerializer(data=request.data)
if serializer.is_valid():
serializer.save(
+1 -1
View File
@@ -7,7 +7,7 @@
"private": true,
"type": "module",
"scripts": {
"dev": "concurrently \"babel src --out-dir dist --extensions '.ts,.js' --watch\" \"nodemon dist/server.js\"",
"dev": "PORT=3100 concurrently \"babel src --out-dir dist --extensions '.ts,.js' --watch\" \"nodemon dist/server.js\"",
"build": "babel src --out-dir dist --extensions \".ts,.js\"",
"start": "node dist/server.js",
"lint": "eslint src --ext .ts,.tsx",
+6 -9
View File
@@ -1,8 +1,5 @@
// icons
import {
TProjectAppliedDisplayFilterKeys,
TProjectOrderByOptions,
} from "@plane/types";
import { TProjectAppliedDisplayFilterKeys, TProjectOrderByOptions } from "@plane/types";
export type TNetworkChoiceIconKey = "Lock" | "Globe2";
@@ -55,11 +52,11 @@ export const GROUP_CHOICES = {
};
export const PROJECT_AUTOMATION_MONTHS = [
{ i18n_label: "common.months_count", value: 1 },
{ i18n_label: "common.months_count", value: 3 },
{ i18n_label: "common.months_count", value: 6 },
{ i18n_label: "common.months_count", value: 9 },
{ i18n_label: "common.months_count", value: 12 },
{ i18n_label: "workspace_projects.common.months_count", value: 1 },
{ i18n_label: "workspace_projects.common.months_count", value: 3 },
{ i18n_label: "workspace_projects.common.months_count", value: 6 },
{ i18n_label: "workspace_projects.common.months_count", value: 9 },
{ i18n_label: "workspace_projects.common.months_count", value: 12 },
];
export const PROJECT_UNSPLASH_COVERS = [
+13 -1
View File
@@ -1,4 +1,4 @@
import { TStaticViewTypes } from "@plane/types";
import { TStaticViewTypes, IWorkspaceSearchResults } from "@plane/types";
import { EUserWorkspaceRoles } from "./user";
export const ORGANIZATION_SIZE = [
@@ -324,3 +324,15 @@ export const WORKSPACE_SIDEBAR_STATIC_NAVIGATION_ITEMS_LINKS: IWorkspaceSidebarN
WORKSPACE_SIDEBAR_STATIC_NAVIGATION_ITEMS["inbox"],
WORKSPACE_SIDEBAR_STATIC_NAVIGATION_ITEMS["projects"],
];
export const WORKSPACE_DEFAULT_SEARCH_RESULT: IWorkspaceSearchResults = {
results: {
workspace: [],
project: [],
issue: [],
cycle: [],
module: [],
issue_view: [],
page: [],
},
};
@@ -130,7 +130,7 @@ export const CoreEditorExtensions = (args: TArguments): Extensions => {
CustomCodeInlineExtension,
Markdown.configure({
html: true,
transformCopiedText: true,
transformCopiedText: false,
transformPastedText: true,
breaks: true,
}),
@@ -1,12 +1,15 @@
import { mergeAttributes } from "@tiptap/core";
import Mention, { MentionOptions } from "@tiptap/extension-mention";
import { MarkdownSerializerState } from "@tiptap/pm/markdown";
import { Node as NodeType } from "@tiptap/pm/model";
// types
import { TMentionHandler } from "@/types";
// local types
import { EMentionComponentAttributeNames } from "./types";
import { EMentionComponentAttributeNames, TMentionComponentAttributes } from "./types";
export type TMentionExtensionOptions = MentionOptions & {
renderComponent: TMentionHandler["renderComponent"];
getMentionedEntityDetails: TMentionHandler["getMentionedEntityDetails"];
};
export const CustomMentionExtensionConfig = Mention.extend<TMentionExtensionOptions>({
@@ -40,9 +43,26 @@ export const CustomMentionExtensionConfig = Mention.extend<TMentionExtensionOpti
class: "mention",
},
addStorage(this) {
renderText({ node }) {
return getMentionDisplayText(this.options, node);
},
addStorage() {
const options = this.options;
return {
mentionsOpen: false,
markdown: {
serialize(state: MarkdownSerializerState, node: NodeType) {
state.write(getMentionDisplayText(options, node));
},
},
};
},
});
function getMentionDisplayText(options: TMentionExtensionOptions, node: NodeType): string {
const attrs = node.attrs as TMentionComponentAttributes;
const mentionEntityId = attrs[EMentionComponentAttributeNames.ENTITY_IDENTIFIER];
const mentionEntityDetails = options.getMentionedEntityDetails?.(mentionEntityId ?? "");
return `@${mentionEntityDetails?.display_name ?? attrs[EMentionComponentAttributeNames.ID] ?? mentionEntityId}`;
}
@@ -9,12 +9,13 @@ import { MentionNodeView } from "./mention-node-view";
import { renderMentionsDropdown } from "./utils";
export const CustomMentionExtension = (props: TMentionHandler) => {
const { searchCallback, renderComponent } = props;
const { searchCallback, renderComponent, getMentionedEntityDetails } = props;
return CustomMentionExtensionConfig.extend({
addOptions(this) {
return {
...this.parent?.(),
renderComponent,
getMentionedEntityDetails,
};
},
+2 -1
View File
@@ -1,5 +1,5 @@
// plane types
import { TSearchEntities } from "@plane/types";
import { IUserLite, TSearchEntities } from "@plane/types";
export type TMentionSuggestion = {
entity_identifier: string;
@@ -20,6 +20,7 @@ export type TMentionComponentProps = Pick<TMentionSuggestion, "entity_identifier
export type TReadOnlyMentionHandler = {
renderComponent: (props: TMentionComponentProps) => React.ReactNode;
getMentionedEntityDetails?: (entity_identifier: string) => { display_name: string } | undefined;
};
export type TMentionHandler = TReadOnlyMentionHandler & {
+8 -2
View File
@@ -7,10 +7,16 @@ export const SUPPORTED_LANGUAGES: ILanguageOption[] = [
{ label: "Français", value: "fr" },
{ label: "Español", value: "es" },
{ label: "日本語", value: "ja" },
{ label: "中文", value: "zh-CN" },
{ label: "简体中文", value: "zh-CN" },
{ label: "繁體中文", value: "zh-TW" },
{ label: "Русский", value: "ru" },
{ label: "Italian", value: "it" },
{ label: "Čeština", value: "cs" },
{ label: "Slovenčina", value: "sk" },
{ label: "Deutsch", value: "de" },
{ label: "Українська", value: "ua" },
{ label: "Polski", value: "pl" },
{ label: "한국어", value: "ko" },
];
export const STORAGE_KEY = "userLanguage";
export const LANGUAGE_STORAGE_KEY = "userLanguage";
+4 -4
View File
@@ -1,8 +1,8 @@
import { useContext } from 'react';
import { useContext } from "react";
// context
import { TranslationContext } from '../context';
import { TranslationContext } from "../context";
// types
import { ILanguageOption, TLanguage } from '../types';
import { ILanguageOption, TLanguage } from "../types";
export type TTranslationStore = {
t: (key: string, params?: Record<string, any>) => string;
@@ -23,7 +23,7 @@ export type TTranslationStore = {
export function useTranslation(): TTranslationStore {
const store = useContext(TranslationContext);
if (!store) {
throw new Error('useTranslation must be used within a TranslationProvider');
throw new Error("useTranslation must be used within a TranslationProvider");
}
return {
@@ -6,7 +6,7 @@
"home": "Domov",
"your_work": "Vaše práce",
"inbox": "Doručená pošta",
"workspace": "workspace",
"workspace": "Pracovní prostor",
"views": "Pohledy",
"analytics": "Analytika",
"work_items": "Pracovní položky",
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+17 -39
View File
@@ -3,7 +3,7 @@ import get from "lodash/get";
import merge from "lodash/merge";
import { makeAutoObservable, runInAction } from "mobx";
// constants
import { FALLBACK_LANGUAGE, SUPPORTED_LANGUAGES, STORAGE_KEY } from "../constants";
import { FALLBACK_LANGUAGE, SUPPORTED_LANGUAGES, LANGUAGE_STORAGE_KEY } from "../constants";
// core translations imports
import coreEn from "../locales/en/core.json";
// types
@@ -48,14 +48,14 @@ export class TranslationStore {
private initializeLanguage() {
if (typeof window === "undefined") return;
const savedLocale = localStorage.getItem(STORAGE_KEY) as TLanguage;
const savedLocale = localStorage.getItem(LANGUAGE_STORAGE_KEY) as TLanguage;
if (this.isValidLanguage(savedLocale)) {
this.setLanguage(savedLocale);
return;
}
const browserLang = this.getBrowserLanguage();
this.setLanguage(browserLang);
// Fallback to default language
this.setLanguage(FALLBACK_LANGUAGE);
}
/** Loads the translations for the current language */
@@ -147,12 +147,24 @@ export class TranslationStore {
return import("../locales/ja/translations.json");
case "zh-CN":
return import("../locales/zh-CN/translations.json");
case "zh-TW":
return import("../locales/zh-TW/translations.json");
case "ru":
return import("../locales/ru/translations.json");
case "it":
return import("../locales/it/translations.json");
case "cs":
return import("../locales/cs/translations.json");
case "sk":
return import("../locales/sk/translations.json");
case "de":
return import("../locales/de/translations.json");
case "ua":
return import("../locales/ua/translations.json");
case "pl":
return import("../locales/pl/translations.json");
case "ko":
return import("../locales/ko/translations.json");
default:
throw new Error(`Unsupported language: ${language}`);
}
@@ -163,40 +175,6 @@ export class TranslationStore {
return lang !== null && this.availableLanguages.some((l) => l.value === lang);
}
/** Checks if a language code is similar to any supported language */
private findSimilarLanguage(lang: string): TLanguage | null {
// Convert to lowercase for case-insensitive comparison
const normalizedLang = lang.toLowerCase();
// Find a supported language that includes or is included in the browser language
const similarLang = this.availableLanguages.find(
(l) => normalizedLang.includes(l.value.toLowerCase()) || l.value.toLowerCase().includes(normalizedLang)
);
return similarLang ? similarLang.value : null;
}
/** Gets the browser language based on the navigator.language */
private getBrowserLanguage(): TLanguage {
const browserLang = navigator.language;
// Check exact match first
if (this.isValidLanguage(browserLang)) {
return browserLang;
}
// Check base language without region code
const baseLang = browserLang.split("-")[0];
if (this.isValidLanguage(baseLang)) {
return baseLang as TLanguage;
}
// Try to find a similar language
const similarLang = this.findSimilarLanguage(browserLang) || this.findSimilarLanguage(baseLang);
return similarLang || FALLBACK_LANGUAGE;
}
/**
* Gets the cache key for the given key and locale
* @param key - the key to get the cache key for
@@ -281,7 +259,7 @@ export class TranslationStore {
}
if (typeof window !== "undefined") {
localStorage.setItem(STORAGE_KEY, lng);
localStorage.setItem(LANGUAGE_STORAGE_KEY, lng);
document.documentElement.lang = lng;
}
+1 -1
View File
@@ -1,4 +1,4 @@
export type TLanguage = "en" | "fr" | "es" | "ja" | "zh-CN" | "ru" | "it" | "cs";
export type TLanguage = "en" | "fr" | "es" | "ja" | "zh-CN" | "zh-TW" | "ru" | "it" | "cs" | "sk" | "de" | "ua" | "pl" | "ko";
export interface ILanguageOption {
label: string;
@@ -7,6 +7,8 @@ import { EditorMentionsRoot } from "@/components/editor";
// helpers
import { cn } from "@/helpers/common.helper";
import { getReadOnlyEditorFileHandlers } from "@/helpers/editor.helper";
// store hooks
import { useMember } from "@/hooks/store";
type LiteTextReadOnlyEditorWrapperProps = MakeOptional<
Omit<ILiteTextReadOnlyEditor, "fileHandler" | "mentionHandler">,
@@ -17,22 +19,29 @@ type LiteTextReadOnlyEditorWrapperProps = MakeOptional<
};
export const LiteTextReadOnlyEditor = React.forwardRef<EditorReadOnlyRefApi, LiteTextReadOnlyEditorWrapperProps>(
({ anchor, workspaceId, disabledExtensions, ...props }, ref) => (
<LiteTextReadOnlyEditorWithRef
ref={ref}
disabledExtensions={disabledExtensions ?? []}
fileHandler={getReadOnlyEditorFileHandlers({
anchor,
workspaceId,
})}
mentionHandler={{
renderComponent: (props) => <EditorMentionsRoot {...props} />,
}}
{...props}
// overriding the customClassName to add relative class passed
containerClassName={cn(props.containerClassName, "relative p-2")}
/>
)
({ anchor, workspaceId, disabledExtensions, ...props }, ref) => {
const { getMemberById } = useMember();
return (
<LiteTextReadOnlyEditorWithRef
ref={ref}
disabledExtensions={disabledExtensions ?? []}
fileHandler={getReadOnlyEditorFileHandlers({
anchor,
workspaceId,
})}
mentionHandler={{
renderComponent: (props) => <EditorMentionsRoot {...props} />,
getMentionedEntityDetails: (id: string) => ({
display_name: getMemberById(id)?.member__display_name ?? "",
}),
}}
{...props}
// overriding the customClassName to add relative class passed
containerClassName={cn(props.containerClassName, "relative p-2")}
/>
);
}
);
LiteTextReadOnlyEditor.displayName = "LiteTextReadOnlyEditor";
@@ -6,6 +6,8 @@ import { MakeOptional } from "@plane/types";
import { EditorMentionsRoot } from "@/components/editor";
// helpers
import { getEditorFileHandlers } from "@/helpers/editor.helper";
// store hooks
import { useMember } from "@/hooks/store";
interface RichTextEditorWrapperProps
extends MakeOptional<Omit<IRichTextEditor, "fileHandler" | "mentionHandler">, "disabledExtensions"> {
@@ -16,11 +18,14 @@ interface RichTextEditorWrapperProps
export const RichTextEditor = forwardRef<EditorRefApi, RichTextEditorWrapperProps>((props, ref) => {
const { anchor, containerClassName, uploadFile, workspaceId, disabledExtensions, ...rest } = props;
const { getMemberById } = useMember();
return (
<RichTextEditorWithRef
mentionHandler={{
renderComponent: (props) => <EditorMentionsRoot {...props} />,
getMentionedEntityDetails: (id: string) => ({
display_name: getMemberById(id)?.member__display_name ?? "",
}),
}}
ref={ref}
disabledExtensions={disabledExtensions ?? []}
@@ -7,6 +7,8 @@ import { EditorMentionsRoot } from "@/components/editor";
// helpers
import { cn } from "@/helpers/common.helper";
import { getReadOnlyEditorFileHandlers } from "@/helpers/editor.helper";
// store hooks
import { useMember } from "@/hooks/store";
type RichTextReadOnlyEditorWrapperProps = MakeOptional<
Omit<IRichTextReadOnlyEditor, "fileHandler" | "mentionHandler">,
@@ -17,22 +19,29 @@ type RichTextReadOnlyEditorWrapperProps = MakeOptional<
};
export const RichTextReadOnlyEditor = React.forwardRef<EditorReadOnlyRefApi, RichTextReadOnlyEditorWrapperProps>(
({ anchor, workspaceId, disabledExtensions, ...props }, ref) => (
<RichTextReadOnlyEditorWithRef
ref={ref}
disabledExtensions={disabledExtensions ?? []}
fileHandler={getReadOnlyEditorFileHandlers({
anchor,
workspaceId,
})}
mentionHandler={{
renderComponent: (props) => <EditorMentionsRoot {...props} />,
}}
{...props}
// overriding the customClassName to add relative class passed
containerClassName={cn("relative p-0 border-none", props.containerClassName)}
/>
)
({ anchor, workspaceId, disabledExtensions, ...props }, ref) => {
const { getMemberById } = useMember();
return (
<RichTextReadOnlyEditorWithRef
ref={ref}
disabledExtensions={disabledExtensions ?? []}
fileHandler={getReadOnlyEditorFileHandlers({
anchor,
workspaceId,
})}
mentionHandler={{
renderComponent: (props) => <EditorMentionsRoot {...props} />,
getMentionedEntityDetails: (id: string) => ({
display_name: getMemberById(id)?.member__display_name ?? "",
}),
}}
{...props}
// overriding the customClassName to add relative class passed
containerClassName={cn("relative p-0 border-none", props.containerClassName)}
/>
);
}
);
RichTextReadOnlyEditor.displayName = "RichTextReadOnlyEditor";
@@ -38,7 +38,7 @@ const ProjectCyclesPage = observer(() => {
// derived values
const totalCycles = currentProjectCycleIds?.length ?? 0;
const project = projectId ? getProjectById(projectId?.toString()) : undefined;
const pageTitle = project?.name ? `${project?.name} - ${t("cycles.label", { count: 2 })}` : undefined;
const pageTitle = project?.name ? `${project?.name} - ${t("common.cycles", { count: 2 })}` : undefined;
const hasAdminLevelPermission = allowPermissions([EUserProjectRoles.ADMIN], EUserPermissionsLevel.PROJECT);
const hasMemberLevelPermission = allowPermissions(
[EUserProjectRoles.ADMIN, EUserProjectRoles.MEMBER],
@@ -16,14 +16,16 @@ import { generateWorkItemLink } from "@/helpers/issue.helper";
// plane web components
import { IssueIdentifier } from "@/plane-web/components/issues";
export const commandGroups: {
export type TCommandGroups = {
[key: string]: {
icon: JSX.Element | null;
itemName: (item: any) => React.ReactNode;
path: (item: any, projectId: string | undefined) => string;
title: string;
};
} = {
};
export const commandGroups: TCommandGroups = {
cycle: {
icon: <ContrastIcon className="h-3 w-3" />,
itemName: (cycle: IWorkspaceDefaultSearchResult) => (
@@ -0,0 +1,3 @@
export * from "./actions";
export * from "./modals";
export * from "./helpers";
-1
View File
@@ -1 +0,0 @@
export * from "./values";
@@ -1 +0,0 @@
export * from "./update";
@@ -1,12 +0,0 @@
import { TIssueServiceType } from "@plane/types";
export type TIssueAdditionalPropertyValuesUpdateProps = {
issueId: string;
issueTypeId: string;
projectId: string;
workspaceSlug: string;
isDisabled: boolean;
issueServiceType?: TIssueServiceType;
};
export const IssueAdditionalPropertyValuesUpdate: React.FC<TIssueAdditionalPropertyValuesUpdateProps> = () => <></>;
@@ -0,0 +1,13 @@
import React, { FC } from "react";
// plane imports
export type TWorkItemAdditionalSidebarProperties = {
workItemId: string;
workItemTypeId: string | null;
projectId: string;
workspaceSlug: string;
isEditable: boolean;
isPeekView?: boolean;
};
export const WorkItemAdditionalSidebarProperties: FC<TWorkItemAdditionalSidebarProperties> = () => <></>;
+12
View File
@@ -1,5 +1,7 @@
// types
import { IIssueDisplayProperties } from "@plane/types";
// lib
import { store } from "@/lib/store-context";
export type TShouldRenderDisplayProperty = {
workspaceSlug: string;
@@ -16,3 +18,13 @@ export const shouldRenderDisplayProperty = (props: TShouldRenderDisplayProperty)
return true;
}
};
export const shouldRenderColumn = (key: keyof IIssueDisplayProperties): boolean => {
const isEstimateEnabled: boolean = store.projectRoot.project.currentProjectDetails?.estimate !== null;
switch (key) {
case "estimate":
return isEstimateEnabled;
default:
return true;
}
};
@@ -0,0 +1,4 @@
import { TIssue } from "@plane/types";
import { getIssueIds } from "@/store/issue/helpers/base-issues-utils";
export const workItemSortWithOrderByExtended = (array: TIssue[], key?: string) => getIssueIds(array);
@@ -97,7 +97,7 @@ export const AutoArchiveAutomation: React.FC<Props> = observer((props) => {
<>
{PROJECT_AUTOMATION_MONTHS.map((month) => (
<CustomSelect.Option key={month.i18n_label} value={month.value}>
<span className="text-sm">{t(month.i18n_label, { month: month.value })}</span>
<span className="text-sm">{t(month.i18n_label, { months: month.value })}</span>
</CustomSelect.Option>
))}
@@ -106,7 +106,7 @@ export const AutoArchiveAutomation: React.FC<Props> = observer((props) => {
className="flex w-full select-none items-center rounded px-1 py-1.5 text-sm text-custom-text-200 hover:bg-custom-background-80"
onClick={() => setmonthModal(true)}
>
{t("customize_time_range")}
{t("common.customize_time_range")}
</button>
</>
</CustomSelect>
@@ -124,7 +124,7 @@ export const AutoCloseAutomation: React.FC<Props> = observer((props) => {
<>
{PROJECT_AUTOMATION_MONTHS.map((month) => (
<CustomSelect.Option key={month.i18n_label} value={month.value}>
{t(month.i18n_label, { month: month.value })}
{t(month.i18n_label, { months: month.value })}
</CustomSelect.Option>
))}
<button
@@ -132,7 +132,7 @@ export const AutoCloseAutomation: React.FC<Props> = observer((props) => {
className="flex w-full select-none items-center rounded px-1 py-1.5 text-custom-text-200 hover:bg-custom-background-80"
onClick={() => setmonthModal(true)}
>
{t("customize_time_range")}
{t("common.customize_time_range")}
</button>
</>
</CustomSelect>
@@ -2,12 +2,12 @@
import { Command } from "cmdk";
import { useParams } from "next/navigation";
// types
// plane imports
import { IWorkspaceSearchResults } from "@plane/types";
// helpers
import { commandGroups } from "@/components/command-palette";
// hooks
import { useAppRouter } from "@/hooks/use-app-router";
// plane web imports
import { commandGroups } from "@/plane-web/components/command-palette";
type Props = {
closePalette: () => void;
@@ -25,9 +25,9 @@ export const CommandPaletteSearchResults: React.FC<Props> = (props) => {
return (
<>
{Object.keys(results.results).map((key) => {
// TODO: add type for results
const section = (results.results as any)[key];
const currentSection = commandGroups[key];
if (!currentSection) return null;
if (section.length > 0) {
return (
@@ -8,7 +8,7 @@ import useSWR from "swr";
import { CommandIcon, FolderPlus, Search, Settings, X } from "lucide-react";
import { Dialog, Transition } from "@headlessui/react";
// plane imports
import { EUserPermissions, EUserPermissionsLevel } from "@plane/constants";
import { EUserPermissions, EUserPermissionsLevel, WORKSPACE_DEFAULT_SEARCH_RESULT } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
import { IWorkspaceSearchResults } from "@plane/types";
import { LayersIcon, Loader, ToggleSwitch } from "@plane/ui";
@@ -58,9 +58,7 @@ export const CommandModal: React.FC = observer(() => {
const [isLoading, setIsLoading] = useState(false);
const [isSearching, setIsSearching] = useState(false);
const [searchTerm, setSearchTerm] = useState("");
const [results, setResults] = useState<IWorkspaceSearchResults>({
results: { workspace: [], project: [], issue: [], cycle: [], module: [], issue_view: [], page: [] },
});
const [results, setResults] = useState<IWorkspaceSearchResults>(WORKSPACE_DEFAULT_SEARCH_RESULT);
const [isWorkspaceLevel, setIsWorkspaceLevel] = useState(false);
const [pages, setPages] = useState<string[]>([]);
const [searchInIssue, setSearchInIssue] = useState(false);
@@ -151,9 +149,7 @@ export const CommandModal: React.FC = observer(() => {
setIsSearching(false);
});
} else {
setResults({
results: { workspace: [], project: [], issue: [], cycle: [], module: [], issue_view: [], page: [] },
});
setResults(WORKSPACE_DEFAULT_SEARCH_RESULT);
setIsLoading(false);
setIsSearching(false);
}
@@ -2,4 +2,3 @@ export * from "./actions";
export * from "./shortcuts-modal";
export * from "./command-modal";
export * from "./command-palette";
export * from "./helpers";
@@ -13,6 +13,8 @@ import { cn } from "@/helpers/common.helper";
import { isCommentEmpty } from "@/helpers/string.helper";
// hooks
import { useEditorConfig, useEditorMention } from "@/hooks/editor";
// store hooks
import { useMember } from "@/hooks/store";
// plane web hooks
import { useEditorFlagging } from "@/plane-web/hooks/use-editor-flagging";
// plane web services
@@ -57,6 +59,8 @@ export const LiteTextEditor = React.forwardRef<EditorRefApi, LiteTextEditorWrapp
const [isFocused, setIsFocused] = useState(showToolbarInitially);
// editor flaggings
const { liteTextEditor: disabledExtensions } = useEditorFlagging(workspaceSlug?.toString());
// store hooks
const { getUserDetails } = useMember();
// use editor mention
const { fetchMentions } = useEditorMention({
searchEntity: async (payload) =>
@@ -97,6 +101,7 @@ export const LiteTextEditor = React.forwardRef<EditorRefApi, LiteTextEditorWrapp
return res;
},
renderComponent: (props) => <EditorMentionsRoot {...props} />,
getMentionedEntityDetails: (id: string) => ({ display_name: getUserDetails(id)?.display_name ?? "" }),
}}
placeholder={placeholder}
containerClassName={cn(containerClassName, "relative")}
@@ -8,6 +8,8 @@ import { EditorMentionsRoot } from "@/components/editor";
import { cn } from "@/helpers/common.helper";
// hooks
import { useEditorConfig } from "@/hooks/editor";
// store hooks
import { useMember } from "@/hooks/store";
// plane web hooks
import { useEditorFlagging } from "@/plane-web/hooks/use-editor-flagging";
@@ -22,6 +24,9 @@ type LiteTextReadOnlyEditorWrapperProps = MakeOptional<
export const LiteTextReadOnlyEditor = React.forwardRef<EditorReadOnlyRefApi, LiteTextReadOnlyEditorWrapperProps>(
({ workspaceId, workspaceSlug, projectId, disabledExtensions: additionalDisabledExtensions, ...props }, ref) => {
// store hooks
const { getUserDetails } = useMember();
// editor flaggings
const { liteTextEditor: disabledExtensions } = useEditorFlagging(workspaceSlug?.toString());
// editor config
@@ -38,6 +43,7 @@ export const LiteTextReadOnlyEditor = React.forwardRef<EditorReadOnlyRefApi, Lit
})}
mentionHandler={{
renderComponent: (props) => <EditorMentionsRoot {...props} />,
getMentionedEntityDetails: (id: string) => ({ display_name: getUserDetails(id)?.display_name ?? "" }),
}}
{...props}
// overriding the containerClassName to add relative class passed
@@ -8,6 +8,8 @@ import { EditorMentionsRoot } from "@/components/editor";
import { cn } from "@/helpers/common.helper";
// hooks
import { useEditorConfig, useEditorMention } from "@/hooks/editor";
// store hooks
import { useMember } from "@/hooks/store";
// plane web hooks
import { useEditorFlagging } from "@/plane-web/hooks/use-editor-flagging";
@@ -31,6 +33,8 @@ export const RichTextEditor = forwardRef<EditorRefApi, RichTextEditorWrapperProp
disabledExtensions: additionalDisabledExtensions,
...rest
} = props;
// store hooks
const { getUserDetails } = useMember();
// editor flaggings
const { richTextEditor: disabledExtensions } = useEditorFlagging(workspaceSlug?.toString());
// use editor mention
@@ -57,6 +61,7 @@ export const RichTextEditor = forwardRef<EditorRefApi, RichTextEditorWrapperProp
return res;
},
renderComponent: (props) => <EditorMentionsRoot {...props} />,
getMentionedEntityDetails: (id: string) => ({ display_name: getUserDetails(id)?.display_name ?? "" }),
}}
{...rest}
containerClassName={cn("relative pl-3 pb-3", containerClassName)}
@@ -8,6 +8,8 @@ import { EditorMentionsRoot } from "@/components/editor";
import { cn } from "@/helpers/common.helper";
// hooks
import { useEditorConfig } from "@/hooks/editor";
// store hooks
import { useMember } from "@/hooks/store";
// plane web hooks
import { useEditorFlagging } from "@/plane-web/hooks/use-editor-flagging";
@@ -22,6 +24,9 @@ type RichTextReadOnlyEditorWrapperProps = MakeOptional<
export const RichTextReadOnlyEditor = React.forwardRef<EditorReadOnlyRefApi, RichTextReadOnlyEditorWrapperProps>(
({ workspaceId, workspaceSlug, projectId, disabledExtensions: additionalDisabledExtensions, ...props }, ref) => {
// store hooks
const { getUserDetails } = useMember();
// editor flaggings
const { richTextEditor: disabledExtensions } = useEditorFlagging(workspaceSlug?.toString());
// editor config
@@ -38,6 +43,7 @@ export const RichTextReadOnlyEditor = React.forwardRef<EditorReadOnlyRefApi, Ric
})}
mentionHandler={{
renderComponent: (props) => <EditorMentionsRoot {...props} />,
getMentionedEntityDetails: (id: string) => ({ display_name: getUserDetails(id)?.display_name ?? "" }),
}}
{...props}
// overriding the containerClassName to add relative class passed
@@ -371,7 +371,7 @@ export const IssueDetailRoot: FC<TIssueDetailRoot> = observer((props) => {
/>
</div>
<div
className="fixed right-0 z-[5] h-full w-full min-w-[300px] overflow-hidden border-l border-custom-border-200 bg-custom-sidebar-background-100 py-5 sm:w-1/2 md:relative md:w-1/3 lg:min-w-80 xl:min-w-96"
className="fixed right-0 z-[5] h-full w-full min-w-[300px] border-l border-custom-border-200 bg-custom-sidebar-background-100 py-5 sm:w-1/2 md:relative md:w-1/3 lg:min-w-80 xl:min-w-96"
style={issueDetailSidebarCollapsed ? { right: `-${window?.innerWidth || 0}px` } : {}}
>
<IssueDetailsSidebar
@@ -24,9 +24,9 @@ import { shouldHighlightIssueDueDate } from "@/helpers/issue.helper";
// hooks
import { useProjectEstimates, useIssueDetail, useProject, useProjectState, useMember } from "@/hooks/store";
// plane web components
import { IssueAdditionalPropertyValuesUpdate } from "@/plane-web/components/issue-types/values";
import { IssueParentSelectRoot, IssueWorklogProperty } from "@/plane-web/components/issues";
// components
import { WorkItemAdditionalSidebarProperties } from "@/plane-web/components/issues/issue-details/additional-properties";
import type { TIssueOperations } from "./root";
type Props = {
@@ -293,15 +293,14 @@ export const IssueDetailsSidebar: React.FC<Props> = observer((props) => {
disabled={!isEditable}
/>
{issue.type_id && (
<IssueAdditionalPropertyValuesUpdate
issueId={issueId}
issueTypeId={issue.type_id}
projectId={projectId}
workspaceSlug={workspaceSlug}
isDisabled={!isEditable}
/>
)}
<WorkItemAdditionalSidebarProperties
workItemId={issue.id}
workItemTypeId={issue.type_id}
projectId={projectId}
workspaceSlug={workspaceSlug}
isEditable={isEditable}
isPeekView
/>
</div>
</div>
</div>
@@ -7,6 +7,7 @@ import { IIssueDisplayProperties, TIssue } from "@plane/types";
import { useEventTracker } from "@/hooks/store";
// components
import { SPREADSHEET_COLUMNS } from "@/plane-web/components/issues/issue-layouts/utils";
import { shouldRenderColumn } from "@/plane-web/helpers/issue-filter.helper";
import { WithDisplayPropertiesHOC } from "../properties/with-display-properties-HOC";
// utils
@@ -20,13 +21,13 @@ type Props = {
};
export const IssueColumn = observer((props: Props) => {
const { displayProperties, issueDetail, disableUserActions, property, updateIssue, isEstimateEnabled } = props;
const { displayProperties, issueDetail, disableUserActions, property, updateIssue } = props;
// router
const pathname = usePathname();
const tableCellRef = useRef<HTMLTableCellElement | null>(null);
const { captureIssueEvent } = useEventTracker();
const shouldRenderProperty = property === "estimate" ? isEstimateEnabled : true;
const shouldRenderProperty = shouldRenderColumn(property);
const Column = SPREADSHEET_COLUMNS[property];
@@ -3,6 +3,7 @@ import { useRef } from "react";
import { observer } from "mobx-react";
import { IIssueDisplayFilterOptions, IIssueDisplayProperties } from "@plane/types";
//components
import { shouldRenderColumn } from "@/plane-web/helpers/issue-filter.helper";
import { WithDisplayPropertiesHOC } from "../properties/with-display-properties-HOC";
import { HeaderColumn } from "./columns/header-column";
@@ -15,19 +16,12 @@ interface Props {
isEpic?: boolean;
}
export const SpreadsheetHeaderColumn = observer((props: Props) => {
const {
displayProperties,
displayFilters,
property,
isEstimateEnabled,
handleDisplayFilterUpdate,
isEpic = false,
} = props;
const { displayProperties, displayFilters, property, handleDisplayFilterUpdate, isEpic = false } = props;
//hooks
const tableHeaderCellRef = useRef<HTMLTableCellElement | null>(null);
const shouldRenderProperty = property === "estimate" ? isEstimateEnabled : true;
const shouldRenderProperty = shouldRenderColumn(property);
return (
<WithDisplayPropertiesHOC
@@ -23,8 +23,8 @@ import { getDate, renderFormattedPayloadDate } from "@/helpers/date-time.helper"
import { shouldHighlightIssueDueDate } from "@/helpers/issue.helper";
import { useIssueDetail, useMember, useProject, useProjectState } from "@/hooks/store";
// plane web components
import { IssueAdditionalPropertyValuesUpdate } from "@/plane-web/components/issue-types/values";
import { IssueParentSelectRoot, IssueWorklogProperty } from "@/plane-web/components/issues";
import { WorkItemAdditionalSidebarProperties } from "@/plane-web/components/issues/issue-details/additional-properties";
interface IPeekOverviewProperties {
workspaceSlug: string;
@@ -291,15 +291,14 @@ export const PeekOverviewProperties: FC<IPeekOverviewProperties> = observer((pro
disabled={disabled}
/>
{issue.type_id && (
<IssueAdditionalPropertyValuesUpdate
issueId={issueId}
issueTypeId={issue.type_id}
projectId={projectId}
workspaceSlug={workspaceSlug}
isDisabled={disabled}
/>
)}
<WorkItemAdditionalSidebarProperties
workItemId={issue.id}
workItemTypeId={issue.type_id}
projectId={projectId}
workspaceSlug={workspaceSlug}
isEditable={!disabled}
isPeekView
/>
</div>
</div>
);
@@ -90,20 +90,17 @@ export const ModulesListView: React.FC = observer(() => {
return (
<ContentWrapper variant={ERowVariant.HUGGING}>
{displayFilters?.layout === "list" && (
<div className="flex h-full w-full justify-between">
<div className="size-full flex justify-between">
{displayFilters?.layout === "list" && (
<ListLayout>
{filteredModuleIds.map((moduleId) => (
<ModuleListItem key={moduleId} moduleId={moduleId} />
))}
</ListLayout>
<ModulePeekOverview projectId={projectId?.toString() ?? ""} workspaceSlug={workspaceSlug?.toString() ?? ""} />
</div>
)}
{displayFilters?.layout === "board" && (
<Row className="flex h-full w-full justify-between py-page-y">
<div
className={`grid h-full w-full grid-cols-1 gap-6 overflow-y-auto ${
)}
{displayFilters?.layout === "board" && (
<Row
className={`size-full py-page-y grid grid-cols-1 gap-6 overflow-y-auto ${
peekModule
? "lg:grid-cols-1 xl:grid-cols-2 3xl:grid-cols-3"
: "lg:grid-cols-2 xl:grid-cols-3 3xl:grid-cols-4"
@@ -112,11 +109,17 @@ export const ModulesListView: React.FC = observer(() => {
{filteredModuleIds.map((moduleId) => (
<ModuleCardItem key={moduleId} moduleId={moduleId} />
))}
</Row>
)}
{displayFilters?.layout === "gantt" && (
<div className="size-full overflow-hidden">
<ModulesListGanttChartView />
</div>
)}
<div className="flex-shrink-0">
<ModulePeekOverview projectId={projectId?.toString() ?? ""} workspaceSlug={workspaceSlug?.toString() ?? ""} />
</Row>
)}
{displayFilters?.layout === "gantt" && <ModulesListGanttChartView />}
</div>
</div>
</ContentWrapper>
);
});
@@ -22,7 +22,7 @@ import { cn, LIVE_BASE_PATH, LIVE_BASE_URL } from "@/helpers/common.helper";
import { generateRandomColor } from "@/helpers/string.helper";
// hooks
import { useEditorMention } from "@/hooks/editor";
import { useUser, useWorkspace } from "@/hooks/store";
import { useUser, useWorkspace, useMember } from "@/hooks/store";
import { usePageFilters } from "@/hooks/use-page-filters";
// plane web components
import { EditorAIMenu } from "@/plane-web/components/pages";
@@ -68,6 +68,8 @@ export const PageEditorBody: React.FC<Props> = observer((props) => {
// store hooks
const { data: currentUser } = useUser();
const { getWorkspaceBySlug } = useWorkspace();
const { getUserDetails } = useMember();
// derived values
const { id: pageId, name: pageTitle, isContentEditable, updateTitle } = page;
const workspaceId = getWorkspaceBySlug(workspaceSlug)?.id ?? "";
@@ -192,6 +194,7 @@ export const PageEditorBody: React.FC<Props> = observer((props) => {
return res;
},
renderComponent: (props) => <EditorMentionsRoot {...props} />,
getMentionedEntityDetails: (id: string) => ({ display_name: getUserDetails(id)?.display_name ?? "" }),
}}
embedHandler={{
issue: issueEmbedProps,
@@ -12,6 +12,8 @@ import { EditorMentionsRoot } from "@/components/editor";
import { useEditorConfig } from "@/hooks/editor";
import { useWorkspace } from "@/hooks/store";
import { usePageFilters } from "@/hooks/use-page-filters";
// store hooks
import { useMember } from "@/hooks/store";
// plane web hooks
import { useEditorFlagging } from "@/plane-web/hooks/use-editor-flagging";
import { useIssueEmbed } from "@/plane-web/hooks/use-issue-embed";
@@ -25,6 +27,8 @@ export type TVersionEditorProps = {
export const PagesVersionEditor: React.FC<TVersionEditorProps> = observer((props) => {
const { activeVersion, currentVersionDescription, isCurrentVersionActive, versionDetails } = props;
// store hooks
const { getUserDetails } = useMember();
// params
const { workspaceSlug, projectId } = useParams();
// store hooks
@@ -108,6 +112,7 @@ export const PagesVersionEditor: React.FC<TVersionEditorProps> = observer((props
})}
mentionHandler={{
renderComponent: (props) => <EditorMentionsRoot {...props} />,
getMentionedEntityDetails: (id: string) => ({ display_name: getUserDetails(id)?.display_name ?? "" }),
}}
embedHandler={{
issue: {
+3 -1
View File
@@ -111,9 +111,10 @@ export class FavoriteStore implements IFavoriteStore {
* @returns Promise<IFavorite>
*/
addFavorite = async (workspaceSlug: string, data: Partial<IFavorite>) => {
const id = uuidv4();
data = { ...data, parent: null, is_folder: data.entity_type === "folder" };
if (data.entity_identifier && this.entityMap[data.entity_identifier]) return this.entityMap[data.entity_identifier];
const id = uuidv4();
try {
// optimistic addition
runInAction(() => {
@@ -271,6 +272,7 @@ export class FavoriteStore implements IFavoriteStore {
* @returns Promise<void>
*/
deleteFavorite = async (workspaceSlug: string, favoriteId: string) => {
if (!this.favoriteMap[favoriteId]) return;
const parent = this.favoriteMap[favoriteId].parent;
const children = this.groupedFavorites[favoriteId].children;
const entity_identifier = this.favoriteMap[favoriteId].entity_identifier;
@@ -37,6 +37,7 @@ import { convertToISODateString } from "@/helpers/date-time.helper";
// local-db
import { SPECIAL_ORDER_BY } from "@/local-db/utils/query-constructor";
import { updatePersistentLayer } from "@/local-db/utils/utils";
import { workItemSortWithOrderByExtended } from "@/plane-web/store/issue/helpers/base-issue.store";
// services
import { CycleService } from "@/services/cycle.service";
import { IssueArchiveService, IssueDraftService, IssueService } from "@/services/issue";
@@ -1991,7 +1992,7 @@ export abstract class BaseIssuesStore implements IBaseIssuesStore {
);
default:
return getIssueIds(array);
return workItemSortWithOrderByExtended(array, key);
}
};
+3 -1
View File
@@ -1,4 +1,6 @@
import { enableStaticRendering } from "mobx-react";
// plane imports
import { FALLBACK_LANGUAGE, LANGUAGE_STORAGE_KEY } from "@plane/i18n";
// plane web store
import { CommandPaletteStore, ICommandPaletteStore } from "@/plane-web/store/command-palette.store";
import { RootStore } from "@/plane-web/store/root.store";
@@ -97,7 +99,7 @@ export class CoreRootStore {
resetOnSignOut() {
// handling the system theme when user logged out from the app
localStorage.setItem("theme", "system");
localStorage.setItem(LANGUAGE_STORAGE_KEY, FALLBACK_LANGUAGE);
this.router = new RouterStore();
this.commandPalette = new CommandPaletteStore();
this.instance = new InstanceStore();
-1
View File
@@ -1 +0,0 @@
export * from "./values";
@@ -1 +0,0 @@
export * from "./update";
@@ -1 +0,0 @@
export * from "ce/components/issue-types/values/update";
@@ -0,0 +1 @@
export * from "ce/components/issues/issue-details/additional-properties";
@@ -0,0 +1 @@
export * from "ce/store/issue/helpers/base-issue.store";