fix: linting issues and rule changes (#5681)

* fix: lint config package updates

* fix: tsconfig changes

* fix: lint config setup

* fix: lint errors and adding new rules

* fix: lint errors

* fix: ui and editor lints

* fix: build error

* fix: editor tsconfig

* fix: lint errors

* fix: types fixes

---------

Co-authored-by: Anmol Singh Bhatia <anmolsinghbhatia@plane.so>
Co-authored-by: Aaryan Khandelwal <aaryankhandu123@gmail.com>
This commit is contained in:
sriram veeraghanta 2024-09-23 17:10:38 +05:30 committed by GitHub
parent e143e0a051
commit 83bfca6f2d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
75 changed files with 1583 additions and 2631 deletions

View file

@ -1,59 +0,0 @@
/**
* Adds three new lint plugins over the existing configuration:
* This is used to lint staged files only.
* We should remove this file once the entire codebase follows these rules.
*/
module.exports = {
root: true,
extends: [
"custom",
],
parser: "@typescript-eslint/parser",
settings: {
"import/resolver": {
typescript: {},
node: {
moduleDirectory: ["node_modules", "."],
},
},
},
rules: {
"import/order": [
"error",
{
groups: ["builtin", "external", "internal", "parent", "sibling"],
pathGroups: [
{
pattern: "react",
group: "external",
position: "before",
},
{
pattern: "lucide-react",
group: "external",
position: "after",
},
{
pattern: "@headlessui/**",
group: "external",
position: "after",
},
{
pattern: "@plane/**",
group: "external",
position: "after",
},
{
pattern: "@/**",
group: "internal",
},
],
pathGroupsExcludedImportTypes: ["builtin", "internal", "react"],
alphabetize: {
order: "asc",
caseInsensitive: true,
},
},
],
},
};

View file

@ -1,10 +0,0 @@
module.exports = {
root: true,
// This tells ESLint to load the config from the package `eslint-config-custom`
extends: ["custom"],
settings: {
next: {
rootDir: ["web/", "space/", "admin/"],
},
},
};

View file

View file

@ -1,3 +0,0 @@
{
"*.{ts,tsx,js,jsx}": ["eslint -c ./.eslintrc-staged.js", "prettier --check"]
}

View file

@ -1,52 +1,8 @@
module.exports = { module.exports = {
root: true, root: true,
extends: ["custom"], extends: ["@plane/eslint-config/next.js"],
parser: "@typescript-eslint/parser", parser: "@typescript-eslint/parser",
settings: { parserOptions: {
"import/resolver": { project: true,
typescript: {},
node: {
moduleDirectory: ["node_modules", "."],
},
},
}, },
rules: { };
"import/order": [
"error",
{
groups: ["builtin", "external", "internal", "parent", "sibling",],
pathGroups: [
{
pattern: "react",
group: "external",
position: "before",
},
{
pattern: "lucide-react",
group: "external",
position: "after",
},
{
pattern: "@headlessui/**",
group: "external",
position: "after",
},
{
pattern: "@plane/**",
group: "external",
position: "after",
},
{
pattern: "@/**",
group: "internal",
}
],
pathGroupsExcludedImportTypes: ["builtin", "internal", "react"],
alphabetize: {
order: "asc",
caseInsensitive: true,
},
},
],
},
}

View file

@ -9,9 +9,7 @@ import { HelpSection, SidebarMenu, SidebarDropdown } from "@/components/admin-si
// hooks // hooks
import { useTheme } from "@/hooks/store"; import { useTheme } from "@/hooks/store";
export interface IInstanceSidebar {} export const InstanceSidebar: FC = observer(() => {
export const InstanceSidebar: FC<IInstanceSidebar> = observer(() => {
// store // store
const { isSidebarCollapsed, toggleSidebar } = useTheme(); const { isSidebarCollapsed, toggleSidebar } = useTheme();

View file

@ -7,11 +7,7 @@ import { Button } from "@plane/ui";
import InstanceFailureDarkImage from "@/public/instance/instance-failure-dark.svg"; import InstanceFailureDarkImage from "@/public/instance/instance-failure-dark.svg";
import InstanceFailureImage from "@/public/instance/instance-failure.svg"; import InstanceFailureImage from "@/public/instance/instance-failure.svg";
type InstanceFailureViewProps = { export const InstanceFailureView: FC = () => {
// mutate: () => void;
};
export const InstanceFailureView: FC<InstanceFailureViewProps> = () => {
const { resolvedTheme } = useTheme(); const { resolvedTheme } = useTheme();
const instanceImage = resolvedTheme === "dark" ? InstanceFailureDarkImage : InstanceFailureImage; const instanceImage = resolvedTheme === "dark" ? InstanceFailureDarkImage : InstanceFailureImage;

View file

@ -1,5 +1,5 @@
// helpers // helpers
import { API_BASE_URL } from "helpers/common.helper"; import { API_BASE_URL } from "@/helpers/common.helper";
// services // services
import { APIService } from "@/services/api.service"; import { APIService } from "@/services/api.service";

View file

@ -1,7 +1,7 @@
// helpers
import { API_BASE_URL } from "helpers/common.helper";
// types // types
import type { IUser } from "@plane/types"; import type { IUser } from "@plane/types";
// helpers
import { API_BASE_URL } from "@/helpers/common.helper";
// services // services
import { APIService } from "@/services/api.service"; import { APIService } from "@/services/api.service";

View file

@ -8,7 +8,8 @@
"build": "next build", "build": "next build",
"preview": "next build && next start", "preview": "next build && next start",
"start": "next start", "start": "next start",
"lint": "next lint" "lint": "eslint . --ext .ts,.tsx",
"lint:errors": "eslint . --ext .ts,.tsx --quiet"
}, },
"dependencies": { "dependencies": {
"@headlessui/react": "^1.7.19", "@headlessui/react": "^1.7.19",
@ -43,9 +44,9 @@
"@types/react-dom": "^18.2.18", "@types/react-dom": "^18.2.18",
"@types/uuid": "^9.0.8", "@types/uuid": "^9.0.8",
"@types/zxcvbn": "^4.4.4", "@types/zxcvbn": "^4.4.4",
"eslint-config-custom": "*", "@plane/eslint-config": "*",
"tailwind-config-custom": "*", "tailwind-config-custom": "*",
"tsconfig": "*", "@plane/typescript-config": "*",
"typescript": "5.4.5" "typescript": "5.3.3"
} }
} }

View file

@ -1,21 +1,15 @@
{ {
"extends": "tsconfig/nextjs.json", "extends": "@plane/typescript-config/nextjs.json",
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"],
"compilerOptions": { "compilerOptions": {
"plugins": [{ "name": "next" }],
"baseUrl": ".", "baseUrl": ".",
"jsx": "preserve",
"esModuleInterop": true,
"paths": { "paths": {
"@/*": ["core/*"], "@/*": ["core/*"],
"@/helpers/*": ["helpers/*"], "@/helpers/*": ["helpers/*"],
"@/public/*": ["public/*"], "@/public/*": ["public/*"],
"@/plane-admin/*": ["ce/*"] "@/plane-admin/*": ["ce/*"]
}, }
"plugins": [ },
{ "include": ["next-env.d.ts", "next.config.js", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"name": "next" "exclude": ["node_modules"]
}
]
}
} }

4
live/.eslintignore Normal file
View file

@ -0,0 +1,4 @@
.turbo/*
out/*
dist/*
public/*

8
live/.eslintrc.json Normal file
View file

@ -0,0 +1,8 @@
{
"root": true,
"extends": ["@plane/eslint-config/server.js"],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"project": true
}
}

View file

@ -7,7 +7,9 @@
"type": "module", "type": "module",
"scripts": { "scripts": {
"build": "babel src --out-dir dist --extensions \".ts,.js\"", "build": "babel src --out-dir dist --extensions \".ts,.js\"",
"start": "node dist/server.js" "start": "node dist/server.js",
"lint": "eslint . --ext .ts,.tsx",
"lint:errors": "eslint . --ext .ts,.tsx --quiet"
}, },
"keywords": [], "keywords": [],
"author": "", "author": "",
@ -55,6 +57,6 @@
"nodemon": "^3.1.0", "nodemon": "^3.1.0",
"ts-node": "^10.9.2", "ts-node": "^10.9.2",
"tsup": "^7.2.0", "tsup": "^7.2.0",
"typescript": "5.4.5" "typescript": "5.3.3"
} }
} }

View file

@ -1,2 +1 @@
// eslint-disable-next-line @typescript-eslint/ban-types export type TAdditionalDocumentTypes = {};
export type TAdditionalDocumentTypes = {}

View file

@ -45,7 +45,8 @@ export const getExtensions: () => Promise<Extension[]> = async () => {
const documentType = params.get("documentType")?.toString() as const documentType = params.get("documentType")?.toString() as
| TDocumentTypes | TDocumentTypes
| undefined; | undefined;
// TODO: Fix this lint error.
// eslint-disable-next-line no-async-promise-executor
return new Promise(async (resolve) => { return new Promise(async (resolve) => {
try { try {
let fetchedData = null; let fetchedData = null;
@ -53,7 +54,7 @@ export const getExtensions: () => Promise<Extension[]> = async () => {
fetchedData = await fetchPageDescriptionBinary( fetchedData = await fetchPageDescriptionBinary(
params, params,
pageId, pageId,
cookie, cookie
); );
} else { } else {
fetchedData = await fetchDocument({ fetchedData = await fetchDocument({
@ -83,6 +84,8 @@ export const getExtensions: () => Promise<Extension[]> = async () => {
| TDocumentTypes | TDocumentTypes
| undefined; | undefined;
// TODO: Fix this lint error.
// eslint-disable-next-line no-async-promise-executor
return new Promise(async () => { return new Promise(async () => {
try { try {
if (documentType === "project_page") { if (documentType === "project_page") {
@ -121,7 +124,7 @@ export const getExtensions: () => Promise<Extension[]> = async () => {
} }
manualLogger.warn( manualLogger.warn(
`Redis Client wasn't able to connect, continuing without Redis (you won't be able to sync data between multiple plane live servers)`, `Redis Client wasn't able to connect, continuing without Redis (you won't be able to sync data between multiple plane live servers)`,
error, error
); );
reject(error); reject(error);
}); });
@ -135,12 +138,12 @@ export const getExtensions: () => Promise<Extension[]> = async () => {
} catch (error) { } catch (error) {
manualLogger.warn( manualLogger.warn(
`Redis Client wasn't able to connect, continuing without Redis (you won't be able to sync data between multiple plane live servers)`, `Redis Client wasn't able to connect, continuing without Redis (you won't be able to sync data between multiple plane live servers)`,
error, error
); );
} }
} else { } else {
manualLogger.warn( manualLogger.warn(
"Redis URL is not set, continuing without Redis (you won't be able to sync data between multiple plane live servers)", "Redis URL is not set, continuing without Redis (you won't be able to sync data between multiple plane live servers)"
); );
} }

View file

@ -1,7 +1,7 @@
import { ErrorRequestHandler } from "express"; import { ErrorRequestHandler } from "express";
import { manualLogger } from "@/core/helpers/logger.js"; import { manualLogger } from "@/core/helpers/logger.js";
export const errorHandler: ErrorRequestHandler = (err, _req, res, _next) => { export const errorHandler: ErrorRequestHandler = (err, _req, res) => {
// Log the error // Log the error
manualLogger.error(err); manualLogger.error(err);

View file

@ -1,43 +1,26 @@
{ {
"extends": "tsconfig/base.json", "extends": "@plane/typescript-config/base.json",
"compilerOptions": { "compilerOptions": {
"module": "NodeNext", "module": "NodeNext",
"moduleResolution": "NodeNext", "moduleResolution": "NodeNext",
"lib": ["ES2015"],
"lib": [
"ES2015"
],
"outDir": "./dist", "outDir": "./dist",
"rootDir": "./src", "rootDir": ".",
"baseUrl": ".", "baseUrl": ".",
"paths": { "paths": {
"@/*": [ "@/*": ["./src/*"],
"./src/*" "@/plane-live/*": ["./src/ce/*"]
],
"@/plane-live/*": [
"./src/ce/*"
]
}, },
"removeComments": true, "removeComments": true,
"esModuleInterop": true, "esModuleInterop": true,
"skipLibCheck": true, "skipLibCheck": true,
"sourceMap": true, "sourceMap": true,
"inlineSources": true, "inlineSources": true,
// Set `sourceRoot` to "/" to strip the build path prefix // Set `sourceRoot` to "/" to strip the build path prefix
// from generated source code references. // from generated source code references.
// This improves issue grouping in Sentry. // This improves issue grouping in Sentry.
"sourceRoot": "/" "sourceRoot": "/"
}, },
"include": [ "include": ["src/**/*.ts", "tsup.config.ts"],
"src/**/*.ts" "exclude": ["./dist", "./build", "./node_modules"]
],
"exclude": [
"./dist",
"./build",
"./node_modules"
]
} }

View file

@ -8,34 +8,20 @@
"space", "space",
"admin", "admin",
"live", "live",
"packages/editor", "packages/*"
"packages/eslint-config-custom",
"packages/tailwind-config-custom",
"packages/tsconfig",
"packages/ui",
"packages/types",
"packages/constants",
"packages/helpers"
], ],
"scripts": { "scripts": {
"build": "turbo run build", "build": "turbo run build",
"dev": "turbo run dev --concurrency=13", "dev": "turbo run dev --concurrency=13",
"start": "turbo run start", "start": "turbo run start",
"lint": "turbo run lint", "lint": "turbo run lint",
"lint:errors": "turbo run lint:errors",
"clean": "turbo run clean", "clean": "turbo run clean",
"format": "prettier --write \"**/*.{ts,tsx,md}\"", "format": "prettier --write \"**/*.{ts,tsx,md}\""
"prepare": "husky"
}, },
"devDependencies": { "devDependencies": {
"autoprefixer": "^10.4.15",
"eslint-config-custom": "*",
"eslint-plugin-prettier": "^5.1.3",
"husky": "^9.0.11",
"lint-staged": "^15.2.2",
"postcss": "^8.4.29",
"prettier": "latest", "prettier": "latest",
"prettier-plugin-tailwindcss": "^0.5.4", "prettier-plugin-tailwindcss": "^0.5.4",
"tailwindcss": "^3.3.3",
"turbo": "^2.1.1" "turbo": "^2.1.1"
}, },
"resolutions": { "resolutions": {

View file

@ -1,38 +1,9 @@
module.exports = { module.exports = {
root: true, root: true,
extends: ["custom"], extends: ["@plane/eslint-config/library.js"],
rules: { parser: "@typescript-eslint/parser",
"import/order": [ parserOptions: {
"error", project: true,
{
groups: ["builtin", "external", "internal", "parent", "sibling"],
pathGroups: [
{
pattern: "react",
group: "external",
position: "before",
},
{
pattern: "lucide-react",
group: "external",
position: "after",
},
{
pattern: "@plane/**",
group: "external",
position: "after",
},
{
pattern: "@/**",
group: "internal",
},
],
pathGroupsExcludedImportTypes: ["builtin", "internal", "react"],
alphabetize: {
order: "asc",
caseInsensitive: true,
},
},
],
}, },
rules: {},
}; };

View file

@ -26,6 +26,7 @@
"build": "tsup --minify", "build": "tsup --minify",
"dev": "tsup --watch", "dev": "tsup --watch",
"check-types": "tsc --noEmit", "check-types": "tsc --noEmit",
"lint": "eslint src --ext .ts,.tsx",
"format": "prettier --write \"**/*.{ts,tsx,md}\"" "format": "prettier --write \"**/*.{ts,tsx,md}\""
}, },
"peerDependencies": { "peerDependencies": {
@ -74,12 +75,12 @@
"@types/node": "18.15.3", "@types/node": "18.15.3",
"@types/react": "^18.2.42", "@types/react": "^18.2.42",
"@types/react-dom": "^18.2.17", "@types/react-dom": "^18.2.17",
"eslint-config-custom": "*", "@plane/eslint-config": "*",
"postcss": "^8.4.38", "postcss": "^8.4.38",
"tailwind-config-custom": "*", "tailwind-config-custom": "*",
"tsconfig": "*", "@plane/typescript-config": "*",
"tsup": "^7.2.0", "tsup": "^7.2.0",
"typescript": "5.4.5" "typescript": "5.3.3"
}, },
"keywords": [ "keywords": [
"editor", "editor",

View file

@ -23,7 +23,6 @@ export const AIFeaturesMenu: React.FC<Props> = (props) => {
menuRef.current.remove(); menuRef.current.remove();
menuRef.current.style.visibility = "visible"; menuRef.current.style.visibility = "visible";
// @ts-expect-error - tippy types are incorrect
popup.current = tippy(document.body, { popup.current = tippy(document.body, {
getReferenceClientRect: null, getReferenceClientRect: null,
content: menuRef.current, content: menuRef.current,

View file

@ -34,7 +34,6 @@ export const BlockMenu = (props: BlockMenuProps) => {
menuRef.current.remove(); menuRef.current.remove();
menuRef.current.style.visibility = "visible"; menuRef.current.style.visibility = "visible";
// @ts-expect-error - tippy types are incorrect
popup.current = tippy(document.body, { popup.current = tippy(document.body, {
getReferenceClientRect: null, getReferenceClientRect: null,
content: menuRef.current, content: menuRef.current,

View file

@ -117,14 +117,18 @@ export function LowlightPlugin({
// Such transactions can happen during collab syncing via y-prosemirror, for example. // Such transactions can happen during collab syncing via y-prosemirror, for example.
transaction.steps.some( transaction.steps.some(
(step) => (step) =>
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore // @ts-ignore
step.from !== undefined && step.from !== undefined &&
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore // @ts-ignore
step.to !== undefined && step.to !== undefined &&
oldNodes.some( oldNodes.some(
(node) => (node) =>
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore // @ts-ignore
node.pos >= step.from && node.pos >= step.from &&
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore // @ts-ignore
node.pos + node.node.nodeSize <= step.to node.pos + node.node.nodeSize <= step.to
) )

View file

@ -1,6 +1,7 @@
// TODO: fix all warnings // TODO: fix all warnings
/* eslint-disable react/display-name */ /* eslint-disable react/display-name */
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-nocheck // @ts-nocheck
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { NodeViewWrapper } from "@tiptap/react"; import { NodeViewWrapper } from "@tiptap/react";

View file

@ -198,6 +198,7 @@ function createToolbox({
onSelectColor: (color: { backgroundColor: string; textColor: string }) => void; onSelectColor: (color: { backgroundColor: string; textColor: string }) => void;
colors: { [key: string]: { backgroundColor: string; textColor: string; icon?: string } }; colors: { [key: string]: { backgroundColor: string; textColor: string; icon?: string } };
}): Instance<Props> { }): Instance<Props> {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error // @ts-expect-error
const toolbox = tippy(triggerButton, { const toolbox = tippy(triggerButton, {
content: h( content: h(

View file

@ -204,11 +204,8 @@ export const Table = Node.create({
({ tr, dispatch }) => { ({ tr, dispatch }) => {
if (dispatch) { if (dispatch) {
const selection = CellSelection.create(tr.doc, position.anchorCell, position.headCell); const selection = CellSelection.create(tr.doc, position.anchorCell, position.headCell);
// @ts-ignore
tr.setSelection(selection); tr.setSelection(selection);
} }
return true; return true;
}, },
}; };
@ -247,7 +244,7 @@ export const Table = Node.create({
return ({ editor, getPos, node, decorations }) => { return ({ editor, getPos, node, decorations }) => {
const { cellMinWidth } = this.options; const { cellMinWidth } = this.options;
return new TableView(node, cellMinWidth, decorations, editor, getPos as () => number); return new TableView(node, cellMinWidth, decorations as any, editor, getPos as () => number);
}; };
}, },
@ -267,8 +264,6 @@ export const Table = Node.create({
handleWidth: this.options.handleWidth, handleWidth: this.options.handleWidth,
cellMinWidth: this.options.cellMinWidth, cellMinWidth: this.options.cellMinWidth,
// View: TableView, // View: TableView,
// @ts-ignore
lastColumnResizable: this.options.lastColumnResizable, lastColumnResizable: this.options.lastColumnResizable,
}) })
); );

View file

@ -82,7 +82,7 @@ export const useEditor = (props: CustomEditorProps) => {
}, },
mentionConfig: { mentionConfig: {
mentionSuggestions: mentionHandler.suggestions ?? (() => Promise.resolve<IMentionSuggestion[]>([])), mentionSuggestions: mentionHandler.suggestions ?? (() => Promise.resolve<IMentionSuggestion[]>([])),
mentionHighlights: mentionHandler.highlights ?? [], mentionHighlights: mentionHandler.highlights,
}, },
placeholder, placeholder,
tabIndex, tabIndex,
@ -170,9 +170,7 @@ export const useEditor = (props: CustomEditorProps) => {
editorRef.current?.off("update"); editorRef.current?.off("update");
}; };
}, },
getHeadings: () => { getHeadings: () => editorRef?.current?.storage.headingList.headings,
return editorRef?.current?.storage.headingList.headings;
},
onStateChange: (callback: () => void) => { onStateChange: (callback: () => void) => {
// Subscribe to editor state changes // Subscribe to editor state changes
editorRef.current?.on("transaction", () => { editorRef.current?.on("transaction", () => {
@ -263,13 +261,11 @@ export const useEditor = (props: CustomEditorProps) => {
editorRef.current.chain().focus().deleteRange({ from, to }).insertContent(contentHTML).run(); editorRef.current.chain().focus().deleteRange({ from, to }).insertContent(contentHTML).run();
} }
}, },
getDocumentInfo: () => { getDocumentInfo: () => ({
return { characters: editorRef?.current?.storage?.characterCount?.characters?.() ?? 0,
characters: editorRef?.current?.storage?.characterCount?.characters?.() ?? 0, paragraphs: getParagraphCount(editorRef?.current?.state),
paragraphs: getParagraphCount(editorRef?.current?.state), words: editorRef?.current?.storage?.characterCount?.words?.() ?? 0,
words: editorRef?.current?.storage?.characterCount?.words?.() ?? 0, }),
};
},
setProviderDocument: (value) => { setProviderDocument: (value) => {
const document = provider?.document; const document = provider?.document;
if (!document) return; if (!document) return;

View file

@ -95,13 +95,11 @@ export const useReadOnlyEditor = (props: CustomReadOnlyEditorProps) => {
if (!editorRef.current) return; if (!editorRef.current) return;
scrollSummary(editorRef.current, marking); scrollSummary(editorRef.current, marking);
}, },
getDocumentInfo: () => { getDocumentInfo: () => ({
return { characters: editorRef?.current?.storage?.characterCount?.characters?.() ?? 0,
characters: editorRef?.current?.storage?.characterCount?.characters?.() ?? 0, paragraphs: getParagraphCount(editorRef?.current?.state),
paragraphs: getParagraphCount(editorRef?.current?.state), words: editorRef?.current?.storage?.characterCount?.words?.() ?? 0,
words: editorRef?.current?.storage?.characterCount?.words?.() ?? 0, }),
};
},
onHeadingChange: (callback: (headings: IMarking[]) => void) => { onHeadingChange: (callback: (headings: IMarking[]) => void) => {
// Subscribe to update event emitted from headers extension // Subscribe to update event emitted from headers extension
editorRef.current?.on("update", () => { editorRef.current?.on("update", () => {
@ -114,9 +112,7 @@ export const useReadOnlyEditor = (props: CustomReadOnlyEditorProps) => {
editorRef.current?.off("update"); editorRef.current?.off("update");
}; };
}, },
getHeadings: () => { getHeadings: () => editorRef?.current?.storage.headingList.headings,
return editorRef?.current?.storage.headingList.headings;
},
})); }));
if (!editor) { if (!editor) {

View file

@ -66,7 +66,7 @@ export interface IEditorProps {
value?: string | null; value?: string | null;
} }
export interface ILiteTextEditor extends IEditorProps {} export type ILiteTextEditor = IEditorProps;
export interface IRichTextEditor extends IEditorProps { export interface IRichTextEditor extends IEditorProps {
dragDropEnabled?: boolean; dragDropEnabled?: boolean;
@ -97,9 +97,9 @@ export interface IReadOnlyEditorProps {
}; };
} }
export interface ILiteTextReadOnlyEditor extends IReadOnlyEditorProps {} export type ILiteTextReadOnlyEditor = IReadOnlyEditorProps;
export interface IRichTextReadOnlyEditor extends IReadOnlyEditorProps {} export type IRichTextReadOnlyEditor = IReadOnlyEditorProps;
export interface ICollaborativeDocumentReadOnlyEditor extends Omit<IReadOnlyEditorProps, "initialValue"> { export interface ICollaborativeDocumentReadOnlyEditor extends Omit<IReadOnlyEditorProps, "initialValue"> {
embedHandler: TEmbedConfig; embedHandler: TEmbedConfig;

View file

@ -1,13 +1,19 @@
{ {
"extends": "tsconfig/react-library.json",
"include": ["src/**/*", "index.d.ts"],
"exclude": ["dist", "build", "node_modules"],
"compilerOptions": { "compilerOptions": {
"jsx": "react-jsx",
"lib": ["ES2015", "DOM"],
"module": "ESNext",
"moduleResolution": "Node",
"target": "ES6",
"sourceMap": true,
"baseUrl": ".", "baseUrl": ".",
"paths": { "paths": {
"@/*": ["src/core/*"], "@/*": ["src/core/*"],
"@/styles/*": ["src/styles/*"], "@/styles/*": ["src/styles/*"],
"@/plane-editor/*": ["src/ce/*"] "@/plane-editor/*": ["src/ce/*"]
} },
} "allowSyntheticDefaultImports": true
},
"include": ["src/**/*", "index.d.ts"],
"exclude": ["dist", "build", "node_modules"]
} }

View file

@ -1,18 +0,0 @@
{
"name": "eslint-config-custom",
"private": true,
"version": "0.22.0",
"main": "index.js",
"license": "MIT",
"dependencies": {
"@typescript-eslint/eslint-plugin": "^7.1.1",
"@typescript-eslint/parser": "^7.1.1",
"eslint": "^8.57.0",
"eslint-config-next": "^14.1.0",
"eslint-config-prettier": "^9.1.0",
"eslint-config-turbo": "^1.12.4",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-react": "^7.33.2",
"typescript": "5.4.5"
}
}

View file

@ -1,19 +1,25 @@
const { resolve } = require("node:path");
const project = resolve(process.cwd(), "tsconfig.json");
/** @type {import("eslint").Linter.Config} */
module.exports = { module.exports = {
extends: ["next", "prettier", "plugin:@typescript-eslint/recommended"], extends: ["prettier", "plugin:@typescript-eslint/recommended"],
parser: "@typescript-eslint/parser",
parserOptions: {
ecmaVersion: 2021, // Or the ECMAScript version you are using
sourceType: "module", // Or 'script' if you're using CommonJS or other modules
},
plugins: ["react", "@typescript-eslint", "import"], plugins: ["react", "@typescript-eslint", "import"],
settings: {
next: {
rootDir: ["."],
},
},
globals: { globals: {
React: "readonly", React: true,
JSX: "readonly", JSX: true,
},
env: {
node: true,
browser: true,
},
settings: {
"import/resolver": {
typescript: {
project,
},
},
}, },
rules: { rules: {
"no-useless-escape": "off", "no-useless-escape": "off",
@ -32,18 +38,12 @@ module.exports = {
"react/self-closing-comp": ["error", { component: true, html: true }], "react/self-closing-comp": ["error", { component: true, html: true }],
"react/jsx-boolean-value": "error", "react/jsx-boolean-value": "error",
"react/jsx-no-duplicate-props": "error", "react/jsx-no-duplicate-props": "error",
"react-hooks/exhaustive-deps": "warn", // "react-hooks/exhaustive-deps": "warn",
"@typescript-eslint/no-unused-vars": ["error"], "@typescript-eslint/no-unused-expressions": "warn",
"@typescript-eslint/no-unused-vars": ["warn"],
"@typescript-eslint/no-explicit-any": "warn", "@typescript-eslint/no-explicit-any": "warn",
"@typescript-eslint/no-useless-empty-export": "error", "@typescript-eslint/no-useless-empty-export": "error",
"@typescript-eslint/prefer-ts-expect-error": "error", "@typescript-eslint/prefer-ts-expect-error": "warn",
"@typescript-eslint/naming-convention": [
"error",
{
selector: ["function", "variable"],
format: ["camelCase", "snake_case", "UPPER_CASE", "PascalCase"],
leadingUnderscore: "allow",
},
],
}, },
ignorePatterns: [".*.js", "node_modules/", "dist/"],
}; };

View file

@ -0,0 +1,92 @@
const { resolve } = require("node:path");
const project = resolve(process.cwd(), "tsconfig.json");
module.exports = {
extends: ["next", "prettier", "plugin:@typescript-eslint/recommended"],
globals: {
React: "readonly",
JSX: "readonly",
},
env: {
node: true,
browser: true,
},
plugins: ["react", "@typescript-eslint", "import"],
settings: {
"import/resolver": {
typescript: {
project,
},
},
},
ignorePatterns: [".*.js", "node_modules/"],
rules: {
"no-useless-escape": "off",
"prefer-const": "error",
"no-irregular-whitespace": "error",
"no-trailing-spaces": "error",
"no-duplicate-imports": "error",
"no-useless-catch": "warn",
"no-case-declarations": "error",
"no-undef": "error",
"no-unreachable": "error",
"arrow-body-style": ["error", "as-needed"],
"@next/next/no-html-link-for-pages": "off",
"@next/next/no-img-element": "off",
"react/jsx-key": "error",
"react/self-closing-comp": ["error", { component: true, html: true }],
"react/jsx-boolean-value": "error",
"react/jsx-no-duplicate-props": "error",
"react-hooks/exhaustive-deps": "warn",
"@typescript-eslint/no-unused-expressions": "warn",
"@typescript-eslint/no-unused-vars": ["warn"],
"@typescript-eslint/no-explicit-any": "warn",
"@typescript-eslint/no-useless-empty-export": "error",
"@typescript-eslint/prefer-ts-expect-error": "warn",
"@typescript-eslint/naming-convention": [
"warn",
{
selector: "variable",
format: ["camelCase", "snake_case", "UPPER_CASE", "PascalCase"],
leadingUnderscore: "allow",
},
],
"import/order": [
"error",
{
groups: ["builtin", "external", "internal", "parent", "sibling"],
pathGroups: [
{
pattern: "react",
group: "external",
position: "before",
},
{
pattern: "lucide-react",
group: "external",
position: "after",
},
{
pattern: "@headlessui/**",
group: "external",
position: "after",
},
{
pattern: "@plane/**",
group: "external",
position: "after",
},
{
pattern: "@/**",
group: "internal",
},
],
pathGroupsExcludedImportTypes: ["builtin", "internal", "react"],
alphabetize: {
order: "asc",
caseInsensitive: true,
},
},
],
},
};

View file

@ -0,0 +1,21 @@
{
"name": "@plane/eslint-config",
"private": true,
"version": "0.22.0",
"files": [
"library.js",
"next.js",
"server.js"
],
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^8.6.0",
"@typescript-eslint/parser": "^8.6.0",
"eslint": "8",
"eslint-config-next": "^14.1.0",
"eslint-config-prettier": "^9.1.0",
"eslint-config-turbo": "^1.12.4",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-react": "^7.33.2",
"typescript": "5.3.3"
}
}

View file

@ -0,0 +1,11 @@
module.exports = {
extends: ["eslint:recommended"],
env: {
node: true,
es6: true,
},
parserOptions: {
ecmaVersion: "latest",
sourceType: "module",
},
};

View file

@ -1,15 +1,15 @@
import React, { useEffect } from "react"; import React, { useEffect } from "react";
export const useOutsideClickDetector = ( export const useOutsideClickDetector = (
ref: React.RefObject<HTMLElement>, ref: React.RefObject<HTMLElement> | any,
callback: () => void, callback: () => void,
useCapture = false useCapture = false
) => { ) => {
const handleClick = (event: MouseEvent) => { const handleClick = (event: MouseEvent) => {
if (ref.current && !ref.current.contains(event.target as Node)) { if (ref.current && !ref.current.contains(event.target as any)) {
// check for the closest element with attribute name data-prevent-outside-click // check for the closest element with attribute name data-prevent-outside-click
const preventOutsideClickElement = ( const preventOutsideClickElement = (
event.target as HTMLElement | undefined event.target as unknown as HTMLElement | undefined
)?.closest("[data-prevent-outside-click]"); )?.closest("[data-prevent-outside-click]");
// if the closest element with attribute name data-prevent-outside-click is found, return // if the closest element with attribute name data-prevent-outside-click is found, return
if (preventOutsideClickElement) { if (preventOutsideClickElement) {

View file

@ -1,7 +1,8 @@
{ {
"extends": "tsconfig/react-library.json", "extends": "@plane/typescript-config/react-library.json",
"compilerOptions": { "compilerOptions": {
"jsx": "react" "jsx": "react",
"lib": ["esnext", "dom"]
}, },
"include": ["."], "include": ["."],
"exclude": ["dist", "build", "node_modules"] "exclude": ["dist", "build", "node_modules"]

View file

@ -9,7 +9,8 @@
"forceConsistentCasingInFileNames": true, "forceConsistentCasingInFileNames": true,
"inlineSources": false, "inlineSources": false,
"isolatedModules": true, "isolatedModules": true,
"moduleResolution": "node", "module": "NodeNext",
"moduleResolution": "NodeNext",
"noUnusedLocals": false, "noUnusedLocals": false,
"noUnusedParameters": false, "noUnusedParameters": false,
"preserveWatchOutput": true, "preserveWatchOutput": true,

View file

@ -3,6 +3,7 @@
"display": "Next.js", "display": "Next.js",
"extends": "./base.json", "extends": "./base.json",
"compilerOptions": { "compilerOptions": {
"plugins": [{ "name": "next" }],
"target": "es5", "target": "es5",
"lib": ["dom", "dom.iterable", "esnext"], "lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true, "allowJs": true,
@ -12,7 +13,8 @@
"noEmit": true, "noEmit": true,
"incremental": true, "incremental": true,
"esModuleInterop": true, "esModuleInterop": true,
"module": "esnext", "module": "ESNext",
"moduleResolution": "Bundler",
"resolveJsonModule": true, "resolveJsonModule": true,
"isolatedModules": true, "isolatedModules": true,
"jsx": "preserve" "jsx": "preserve"

View file

@ -1,5 +1,5 @@
{ {
"name": "tsconfig", "name": "@plane/typescript-config",
"version": "0.22.0", "version": "0.22.0",
"private": true, "private": true,
"files": [ "files": [

View file

@ -3,10 +3,9 @@
"display": "React Library", "display": "React Library",
"extends": "./base.json", "extends": "./base.json",
"compilerOptions": { "compilerOptions": {
"jsx": "react-jsx", "lib": ["ES2015"],
"lib": ["ES2015", "DOM"], "target": "ES6",
"module": "ESNext", "jsx": "react-jsx"
"target": "es6", },
"sourceMap": true "exclude": ["node_modules"]
}
} }

10
packages/ui/.eslintrc.js Normal file
View file

@ -0,0 +1,10 @@
/** @type {import("eslint").Linter.Config} */
module.exports = {
root: true,
extends: ["@plane/eslint-config/library.js"],
parser: "@typescript-eslint/parser",
parserOptions: {
project: "./tsconfig.json",
tsconfigRootDir: __dirname,
},
};

View file

@ -17,7 +17,8 @@
"clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist", "clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist",
"storybook": "storybook dev -p 6006", "storybook": "storybook dev -p 6006",
"build-storybook": "storybook build", "build-storybook": "storybook build",
"postcss": "postcss styles/globals.css -o styles/output.css --watch" "postcss": "postcss styles/globals.css -o styles/output.css --watch",
"lint": "eslint src --ext .ts,.tsx"
}, },
"dependencies": { "dependencies": {
"@atlaskit/pragmatic-drag-and-drop": "^1.1.10", "@atlaskit/pragmatic-drag-and-drop": "^1.1.10",
@ -57,15 +58,15 @@
"@types/react-dom": "^18.2.17", "@types/react-dom": "^18.2.17",
"autoprefixer": "^10.4.19", "autoprefixer": "^10.4.19",
"classnames": "^2.3.2", "classnames": "^2.3.2",
"eslint-config-custom": "*", "@plane/eslint-config": "*",
"postcss-cli": "^11.0.0", "postcss-cli": "^11.0.0",
"postcss-nested": "^6.0.1", "postcss-nested": "^6.0.1",
"react": "^18.2.0", "react": "^18.2.0",
"storybook": "^8.1.1", "storybook": "^8.1.1",
"tailwind-config-custom": "*", "tailwind-config-custom": "*",
"tailwindcss": "^3.4.3", "tailwindcss": "^3.4.3",
"tsconfig": "*", "@plane/typescript-config": "*",
"tsup": "^7.2.0", "tsup": "^7.2.0",
"typescript": "5.4.5" "typescript": "5.3.3"
} }
} }

View file

@ -25,6 +25,7 @@ export interface IBadgeStyling {
}; };
} }
// TODO: convert them to objects instead of enums
enum badgeSizeStyling { enum badgeSizeStyling {
sm = `px-2.5 py-1 font-medium text-xs rounded flex items-center gap-1.5 whitespace-nowrap transition-all justify-center inline`, sm = `px-2.5 py-1 font-medium text-xs rounded flex items-center gap-1.5 whitespace-nowrap transition-all justify-center inline`,
md = `px-4 py-1.5 font-medium text-sm rounded flex items-center gap-1.5 whitespace-nowrap transition-all justify-center inline`, md = `px-4 py-1.5 font-medium text-sm rounded flex items-center gap-1.5 whitespace-nowrap transition-all justify-center inline`,
@ -32,10 +33,12 @@ enum badgeSizeStyling {
xl = `px-5 py-3 font-medium text-sm rounded flex items-center gap-1.5 whitespace-nowrap transition-all justify-center inline`, xl = `px-5 py-3 font-medium text-sm rounded flex items-center gap-1.5 whitespace-nowrap transition-all justify-center inline`,
} }
// TODO: convert them to objects instead of enums
enum badgeIconStyling { enum badgeIconStyling {
sm = "h-3 w-3 flex justify-center items-center overflow-hidden flex-shrink-0", sm = "h-3 w-3 flex justify-center items-center overflow-hidden flex-shrink-0",
md = "h-3.5 w-3.5 flex justify-center items-center overflow-hidden flex-shrink-0", md = "h-3.5 w-3.5 flex justify-center items-center overflow-hidden flex-shrink-0",
lg = "h-4 w-4 flex justify-center items-center overflow-hidden flex-shrink-0", lg = "h-4 w-4 flex justify-center items-center overflow-hidden flex-shrink-0",
// eslint-disable-next-line @typescript-eslint/no-duplicate-enum-values
xl = "h-4 w-4 flex justify-center items-center overflow-hidden flex-shrink-0", xl = "h-4 w-4 flex justify-center items-center overflow-hidden flex-shrink-0",
} }

View file

@ -33,7 +33,7 @@ enum buttonIconStyling {
sm = "h-3 w-3 flex justify-center items-center overflow-hidden my-0.5 flex-shrink-0", sm = "h-3 w-3 flex justify-center items-center overflow-hidden my-0.5 flex-shrink-0",
md = "h-3.5 w-3.5 flex justify-center items-center overflow-hidden my-0.5 flex-shrink-0", md = "h-3.5 w-3.5 flex justify-center items-center overflow-hidden my-0.5 flex-shrink-0",
lg = "h-4 w-4 flex justify-center items-center overflow-hidden my-0.5 flex-shrink-0", lg = "h-4 w-4 flex justify-center items-center overflow-hidden my-0.5 flex-shrink-0",
xl = "h-4 w-4 flex justify-center items-center overflow-hidden my-0.5 flex-shrink-0", xl = "h-4 w-4 flex justify-center items-center overflow-hidden my-0.5 flex-shrink-0 ",
} }
export const buttonStyling: IButtonStyling = { export const buttonStyling: IButtonStyling = {

View file

@ -105,7 +105,6 @@ export const MultiSelectDropdown: FC<IMultiSelectDropdown> = (props) => {
(option) => !(value ?? []).includes(option.data[option.value]), (option) => !(value ?? []).includes(option.data[option.value]),
() => sortByKey && sortByKey.toLowerCase(), () => sortByKey && sortByKey.toLowerCase(),
]); ]);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [query, options]); }, [query, options]);
// hooks // hooks

View file

@ -105,7 +105,6 @@ export const Dropdown: FC<ISingleSelectDropdown> = (props) => {
(option) => !(value ?? []).includes(option.data[option.value]), (option) => !(value ?? []).includes(option.data[option.value]),
() => sortByKey && sortByKey.toLowerCase(), () => sortByKey && sortByKey.toLowerCase(),
]); ]);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [query, options]); }, [query, options]);
// hooks // hooks

View file

@ -38,7 +38,7 @@ const ComboDropDown = forwardRef((props: Props, ref) => {
}; };
useEffect(() => { useEffect(() => {
const element = dropDownButtonRef.current; const element = dropDownButtonRef.current as any;
if (!element) return; if (!element) return;
@ -58,7 +58,8 @@ const ComboDropDown = forwardRef((props: Props, ref) => {
} }
return ( return (
// @ts-ignore // eslint-disable-next-line @typescript-eslint/prefer-ts-expect-error, @typescript-eslint/ban-ts-comment
// @ts-expect-error
<Combobox {...rest} ref={ref}> <Combobox {...rest} ref={ref}>
<Combobox.Button as={Fragment}>{button}</Combobox.Button> <Combobox.Button as={Fragment}>{button}</Combobox.Button>
{children} {children}

View file

@ -102,7 +102,7 @@ export const CustomEmojiIconPicker: React.FC<TCustomEmojiPicker> = (props) => {
type: EmojiIconPickerTypes.EMOJI, type: EmojiIconPickerTypes.EMOJI,
value: val, value: val,
}); });
if (closeOnSelect) close(); if (closeOnSelect) handleToggle(false);
}} }}
height="20rem" height="20rem"
width="100%" width="100%"
@ -121,7 +121,7 @@ export const CustomEmojiIconPicker: React.FC<TCustomEmojiPicker> = (props) => {
type: EmojiIconPickerTypes.ICON, type: EmojiIconPickerTypes.ICON,
value: val, value: val,
}); });
if (closeOnSelect) close(); if (closeOnSelect) handleToggle(false);
}} }}
/> />
</Tab.Panel> </Tab.Panel>

View file

@ -27,7 +27,7 @@ export const LinearProgressIndicator: React.FC<Props> = ({
backgroundColor: item.color, backgroundColor: item.color,
}; };
progress += item.value; progress += item.value;
if (noTooltip) return <div style={style} />; if (noTooltip) return <div style={style} key={item.id} />;
else else
return ( return (
<Tooltip key={item.id} tooltipContent={`${item.name} ${Math.round(item.value)}${inPercentage ? "%" : ""}`}> <Tooltip key={item.id} tooltipContent={`${item.name} ${Math.round(item.value)}${inPercentage ? "%" : ""}`}>

View file

@ -54,7 +54,7 @@ export const Tooltip: React.FC<ITooltipProps> = ({
}; };
useEffect(() => { useEffect(() => {
const element = toolTipRef.current; const element = toolTipRef.current as any;
if (!element) return; if (!element) return;

View file

@ -1,7 +1,8 @@
{ {
"extends": "tsconfig/react-library.json", "extends": "@plane/typescript-config/react-library.json",
"compilerOptions": { "compilerOptions": {
"jsx": "react" "jsx": "react",
"lib": ["esnext", "dom"]
}, },
"include": ["."], "include": ["."],
"exclude": ["dist", "build", "node_modules"] "exclude": ["dist", "build", "node_modules"]

View file

@ -1,52 +1,10 @@
/** @type {import("eslint").Linter.Config} */
module.exports = { module.exports = {
root: true, root: true,
extends: ["custom"], extends: ["@plane/eslint-config/next.js"],
parser: "@typescript-eslint/parser", parser: "@typescript-eslint/parser",
settings: { parserOptions: {
"import/resolver": { project: true,
typescript: {},
node: {
moduleDirectory: ["node_modules", "."],
},
},
},
rules: {
"import/order": [
"error",
{
groups: ["builtin", "external", "internal", "parent", "sibling",],
pathGroups: [
{
pattern: "react",
group: "external",
position: "before",
},
{
pattern: "lucide-react",
group: "external",
position: "after",
},
{
pattern: "@headlessui/**",
group: "external",
position: "after",
},
{
pattern: "@plane/**",
group: "external",
position: "after",
},
{
pattern: "@/**",
group: "internal",
}
],
pathGroupsExcludedImportTypes: ["builtin", "internal", "react"],
alphabetize: {
order: "asc",
caseInsensitive: true,
},
},
],
}, },
rules: {},
}; };

View file

@ -6,7 +6,7 @@ import { cn } from "@/helpers/common.helper";
// hooks // hooks
import { useMention } from "@/hooks/use-mention"; import { useMention } from "@/hooks/use-mention";
interface LiteTextReadOnlyEditorWrapperProps extends Omit<ILiteTextReadOnlyEditor, "mentionHandler"> {} type LiteTextReadOnlyEditorWrapperProps = Omit<ILiteTextReadOnlyEditor, "mentionHandler">;
export const LiteTextReadOnlyEditor = React.forwardRef<EditorReadOnlyRefApi, LiteTextReadOnlyEditorWrapperProps>( export const LiteTextReadOnlyEditor = React.forwardRef<EditorReadOnlyRefApi, LiteTextReadOnlyEditorWrapperProps>(
({ ...props }, ref) => { ({ ...props }, ref) => {

View file

@ -6,7 +6,7 @@ import { cn } from "@/helpers/common.helper";
// hooks // hooks
import { useMention } from "@/hooks/use-mention"; import { useMention } from "@/hooks/use-mention";
interface RichTextReadOnlyEditorWrapperProps extends Omit<IRichTextReadOnlyEditor, "mentionHandler"> {} type RichTextReadOnlyEditorWrapperProps = Omit<IRichTextReadOnlyEditor, "mentionHandler">;
export const RichTextReadOnlyEditor = React.forwardRef<EditorReadOnlyRefApi, RichTextReadOnlyEditorWrapperProps>( export const RichTextReadOnlyEditor = React.forwardRef<EditorReadOnlyRefApi, RichTextReadOnlyEditorWrapperProps>(
({ ...props }, ref) => { ({ ...props }, ref) => {

View file

@ -7,7 +7,8 @@
"develop": "next dev -p 3002", "develop": "next dev -p 3002",
"build": "next build", "build": "next build",
"start": "next start", "start": "next start",
"lint": "next lint", "lint": "eslint . --ext .ts,.tsx",
"lint:errors": "eslint . --ext .ts,.tsx --quiet",
"export": "next export" "export": "next export"
}, },
"dependencies": { "dependencies": {
@ -58,9 +59,9 @@
"@types/uuid": "^9.0.1", "@types/uuid": "^9.0.1",
"@types/zxcvbn": "^4.4.4", "@types/zxcvbn": "^4.4.4",
"@typescript-eslint/eslint-plugin": "^5.48.2", "@typescript-eslint/eslint-plugin": "^5.48.2",
"eslint-config-custom": "*", "@plane/eslint-config": "*",
"tailwind-config-custom": "*", "tailwind-config-custom": "*",
"tsconfig": "*", "@plane/typescript-config": "*",
"typescript": "5.4.5" "typescript": "5.3.3"
} }
} }

View file

@ -1,5 +1,5 @@
{ {
"extends": "tsconfig/nextjs.json", "extends": "@plane/typescript-config/nextjs.json",
"plugins": [ "plugins": [
{ {
"name": "next" "name": "next"

View file

@ -1,55 +1,9 @@
/** @type {import("eslint").Linter.Config} */
module.exports = { module.exports = {
root: true, root: true,
extends: ["custom"], extends: ["@plane/eslint-config/next.js"],
parser: "@typescript-eslint/parser", parser: "@typescript-eslint/parser",
settings: { parserOptions: {
"import/resolver": { project: true,
typescript: {},
node: {
moduleDirectory: ["node_modules", "."],
},
},
next: {
rootDir: ["."],
},
},
rules: {
"import/order": [
"error",
{
groups: ["builtin", "external", "internal", "parent", "sibling"],
pathGroups: [
{
pattern: "react",
group: "external",
position: "before",
},
{
pattern: "lucide-react",
group: "external",
position: "after",
},
{
pattern: "@headlessui/**",
group: "external",
position: "after",
},
{
pattern: "@plane/**",
group: "external",
position: "after",
},
{
pattern: "@/**",
group: "internal",
},
],
pathGroupsExcludedImportTypes: ["builtin", "internal", "react"],
alphabetize: {
order: "asc",
caseInsensitive: true,
},
},
],
}, },
}; };

View file

@ -21,9 +21,7 @@ import useSize from "@/hooks/use-window-size";
import { SidebarAppSwitcher } from "@/plane-web/components/sidebar"; import { SidebarAppSwitcher } from "@/plane-web/components/sidebar";
import { EUserPermissions, EUserPermissionsLevel } from "@/plane-web/constants/user-permissions"; import { EUserPermissions, EUserPermissionsLevel } from "@/plane-web/constants/user-permissions";
export interface IAppSidebar {} export const AppSidebar: FC = observer(() => {
export const AppSidebar: FC<IAppSidebar> = observer(() => {
// store hooks // store hooks
const { allowPermissions } = useUserPermissions(); const { allowPermissions } = useUserPermissions();
const { toggleSidebar, sidebarCollapsed } = useAppTheme(); const { toggleSidebar, sidebarCollapsed } = useAppTheme();

View file

@ -1,13 +1,14 @@
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import { Control, Controller, UseFormSetValue } from "react-hook-form"; import { Control, Controller, UseFormSetValue } from "react-hook-form";
// types
import { IAnalyticsParams } from "@plane/types"; import { IAnalyticsParams } from "@plane/types";
// hooks // ui
import { SelectProject, SelectSegment, SelectXAxis, SelectYAxis } from "@/components/analytics";
import { ANALYTICS_X_AXIS_VALUES } from "@/constants/analytics";
import { useProject } from "@/hooks/store";
import { Row } from "@plane/ui"; import { Row } from "@plane/ui";
// components // components
// types import { SelectProject, SelectSegment, SelectXAxis, SelectYAxis } from "@/components/analytics";
import { ANALYTICS_X_AXIS_VALUES } from "@/constants/analytics";
// hooks
import { useProject } from "@/hooks/store";
type Props = { type Props = {
control: Control<IAnalyticsParams, any>; control: Control<IAnalyticsParams, any>;

View file

@ -6,7 +6,7 @@ import { cn } from "@/helpers/common.helper";
// hooks // hooks
import { useMention, useUser } from "@/hooks/store"; import { useMention, useUser } from "@/hooks/store";
interface LiteTextReadOnlyEditorWrapperProps extends Omit<ILiteTextReadOnlyEditor, "mentionHandler"> {} type LiteTextReadOnlyEditorWrapperProps = Omit<ILiteTextReadOnlyEditor, "mentionHandler">;
export const LiteTextReadOnlyEditor = React.forwardRef<EditorReadOnlyRefApi, LiteTextReadOnlyEditorWrapperProps>( export const LiteTextReadOnlyEditor = React.forwardRef<EditorReadOnlyRefApi, LiteTextReadOnlyEditorWrapperProps>(
({ ...props }, ref) => { ({ ...props }, ref) => {

View file

@ -6,7 +6,7 @@ import { cn } from "@/helpers/common.helper";
// hooks // hooks
import { useMention } from "@/hooks/store"; import { useMention } from "@/hooks/store";
interface RichTextReadOnlyEditorWrapperProps extends Omit<IRichTextReadOnlyEditor, "mentionHandler"> {} type RichTextReadOnlyEditorWrapperProps = Omit<IRichTextReadOnlyEditor, "mentionHandler">;
export const RichTextReadOnlyEditor = React.forwardRef<EditorReadOnlyRefApi, RichTextReadOnlyEditorWrapperProps>( export const RichTextReadOnlyEditor = React.forwardRef<EditorReadOnlyRefApi, RichTextReadOnlyEditorWrapperProps>(
({ ...props }, ref) => { ({ ...props }, ref) => {

View file

@ -10,6 +10,8 @@ import { useIssueDetail, useLabel, useProjectInbox, useUserPermissions } from "@
// ui // ui
// types // types
import { LabelList, LabelCreate, IssueLabelSelectRoot } from "./"; import { LabelList, LabelCreate, IssueLabelSelectRoot } from "./";
// TODO: Fix this import statement, as core should not import from ee
// eslint-disable-next-line import/order
import { EUserPermissions, EUserPermissionsLevel } from "ee/constants/user-permissions"; import { EUserPermissions, EUserPermissionsLevel } from "ee/constants/user-permissions";
export type TIssueLabel = { export type TIssueLabel = {

View file

@ -11,8 +11,6 @@ import { EUserPermissions, EUserPermissionsLevel } from "@/plane-web/constants/u
// components // components
import { BaseKanBanRoot } from "../base-kanban-root"; import { BaseKanBanRoot } from "../base-kanban-root";
export interface ICycleKanBanLayout {}
export const CycleKanBanLayout: React.FC = observer(() => { export const CycleKanBanLayout: React.FC = observer(() => {
const { workspaceSlug, projectId, cycleId } = useParams(); const { workspaceSlug, projectId, cycleId } = useParams();

View file

@ -3,6 +3,4 @@ import { observer } from "mobx-react";
import { DraftIssueQuickActions } from "@/components/issues"; import { DraftIssueQuickActions } from "@/components/issues";
import { BaseKanBanRoot } from "../base-kanban-root"; import { BaseKanBanRoot } from "../base-kanban-root";
export interface IKanBanLayout {}
export const DraftKanBanLayout: React.FC = observer(() => <BaseKanBanRoot QuickActions={DraftIssueQuickActions} />); export const DraftKanBanLayout: React.FC = observer(() => <BaseKanBanRoot QuickActions={DraftIssueQuickActions} />);

View file

@ -10,8 +10,6 @@ import { useIssues } from "@/hooks/store";
// constants // constants
import { BaseKanBanRoot } from "../base-kanban-root"; import { BaseKanBanRoot } from "../base-kanban-root";
export interface IModuleKanBanLayout {}
export const ModuleKanBanLayout: React.FC = observer(() => { export const ModuleKanBanLayout: React.FC = observer(() => {
const { workspaceSlug, projectId, moduleId } = useParams(); const { workspaceSlug, projectId, moduleId } = useParams();

View file

@ -131,9 +131,7 @@ export const IssueBlockRoot: FC<Props> = observer((props) => {
classNames={`relative ${isLastChild && !isExpanded ? "" : "border-b border-b-custom-border-200"}`} classNames={`relative ${isLastChild && !isExpanded ? "" : "border-b border-b-custom-border-200"}`}
verticalOffset={100} verticalOffset={100}
defaultValue={shouldRenderByDefault || isIssueNew(issuesMap[issueId])} defaultValue={shouldRenderByDefault || isIssueNew(issuesMap[issueId])}
placeholderChildren={ placeholderChildren={<ListLoaderItemRow shouldAnimate={false} renderForPlaceHolder defaultPropertyCount={4} />}
<ListLoaderItemRow shouldAnimate={false} renderForPlaceHolder={true} defaultPropertyCount={4} />
}
shouldRecordHeights={isMobile} shouldRecordHeights={isMobile}
> >
<IssueBlock <IssueBlock

View file

@ -11,8 +11,6 @@ import { EUserPermissions, EUserPermissionsLevel } from "@/plane-web/constants/u
// types // types
import { BaseListRoot } from "../base-list-root"; import { BaseListRoot } from "../base-list-root";
export interface ICycleListLayout {}
export const CycleListLayout: React.FC = observer(() => { export const CycleListLayout: React.FC = observer(() => {
const { workspaceSlug, projectId, cycleId } = useParams(); const { workspaceSlug, projectId, cycleId } = useParams();
// store // store

View file

@ -10,8 +10,6 @@ import { useIssues } from "@/hooks/store";
// constants // constants
import { BaseListRoot } from "../base-list-root"; import { BaseListRoot } from "../base-list-root";
export interface IModuleListLayout {}
export const ModuleListLayout: React.FC = observer(() => { export const ModuleListLayout: React.FC = observer(() => {
const { workspaceSlug, projectId, moduleId } = useParams(); const { workspaceSlug, projectId, moduleId } = useParams();

View file

@ -4,9 +4,7 @@ import { FC } from "react";
// components // components
import { Loader } from "@plane/ui"; import { Loader } from "@plane/ui";
export interface IProjectDetailsFormLoader {} export const ProjectDetailsFormLoader: FC = () => (
export const ProjectDetailsFormLoader: FC<IProjectDetailsFormLoader> = () => (
<> <>
<div className="relative mt-6 h-44 w-full"> <div className="relative mt-6 h-44 w-full">
<Loader> <Loader>

View file

@ -7,7 +7,8 @@
"develop": "next dev --port 3000", "develop": "next dev --port 3000",
"build": "next build", "build": "next build",
"start": "next start", "start": "next start",
"lint": "next lint", "lint": "eslint . --ext .ts,.tsx",
"lint:errors": "eslint . --ext .ts,.tsx --quiet",
"export": "next export", "export": "next export",
"clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist" "clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist"
}, },
@ -76,10 +77,10 @@
"@types/react-dom": "^18.2.18", "@types/react-dom": "^18.2.18",
"@types/uuid": "^8.3.4", "@types/uuid": "^8.3.4",
"@types/zxcvbn": "^4.4.4", "@types/zxcvbn": "^4.4.4",
"eslint-config-custom": "*", "@plane/eslint-config": "*",
"prettier": "^3.2.5", "prettier": "^3.2.5",
"tailwind-config-custom": "*", "tailwind-config-custom": "*",
"tsconfig": "*", "@plane/typescript-config": "*",
"typescript": "5.4.5" "typescript": "5.3.3"
} }
} }

View file

@ -1,11 +1,7 @@
{ {
"extends": "tsconfig/nextjs.json", "extends": "@plane/typescript-config/nextjs.json",
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"],
"compilerOptions": { "compilerOptions": {
"baseUrl": ".", "baseUrl": ".",
"jsx": "preserve",
"esModuleInterop": true,
"paths": { "paths": {
"@/*": ["core/*"], "@/*": ["core/*"],
"@/helpers/*": ["helpers/*"], "@/helpers/*": ["helpers/*"],
@ -13,11 +9,9 @@
"@/styles/*": ["styles/*"], "@/styles/*": ["styles/*"],
"@/plane-web/*": ["ce/*"] "@/plane-web/*": ["ce/*"]
}, },
"plugins": [ "plugins": [{ "name": "next" }],
{
"name": "next"
}
],
"strictNullChecks": true "strictNullChecks": true
} },
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"]
} }

1
web/use-font-face-observer.d.ts vendored Normal file
View file

@ -0,0 +1 @@
declare module "use-font-face-observer";

3392
yarn.lock

File diff suppressed because it is too large Load diff