diff --git a/.github/workflows/create-sync-pr.yml b/.github/workflows/create-sync-pr.yml index d93aec13e..c8e27f322 100644 --- a/.github/workflows/create-sync-pr.yml +++ b/.github/workflows/create-sync-pr.yml @@ -2,7 +2,7 @@ name: Create PR in Plane EE Repository to sync the changes on: pull_request: - branches: + branches: - master types: - closed diff --git a/README.md b/README.md index 79d1ef431..c00aee995 100644 --- a/README.md +++ b/README.md @@ -39,29 +39,33 @@ Meet [Plane](https://plane.so). An open-source software development tool to mana The easiest way to get started with Plane is by creating a [Plane Cloud](https://app.plane.so) account. Plane Cloud offers a hosted solution for Plane. If you prefer to self-host Plane, please refer to our [deployment documentation](https://docs.plane.so/self-hosting). -## ⚡️ Contributors Quick Start +## ⚡️ Contributors Quick Start ### Prerequisite + Development system must have docker engine installed and running. +### Steps -### Steps Setting up local environment is extremely easy and straight forward. Follow the below step and you will be ready to contribute 1. Clone the code locally using `git clone https://github.com/makeplane/plane.git` 1. Switch to the code folder `cd plane` 1. Create your feature or fix branch you plan to work on using `git checkout -b ` 1. Open terminal and run `./setup.sh` -1. Open the code on VSCode or similar equivalent IDE +1. Open the code on VSCode or similar equivalent IDE 1. Review the `.env` files available in various folders. Visit [Environment Setup](./ENV_SETUP.md) to know about various environment variables used in system 1. Run the docker command to initiate various services `docker compose -f docker-compose-local.yml up -d` -You are ready to make changes to the code. Do not forget to refresh the browser (in case id does not auto-reload) +```bash +./setup.sh +``` -Thats it! +You are ready to make changes to the code. Do not forget to refresh the browser (in case id does not auto-reload) +Thats it! -## 🍙 Self Hosting +## 🍙 Self Hosting For self hosting environment setup, visit the [Self Hosting](https://docs.plane.so/self-hosting) documentation page diff --git a/apiserver/plane/utils/issue_filters.py b/apiserver/plane/utils/issue_filters.py index f3f180645..0b8f39e14 100644 --- a/apiserver/plane/utils/issue_filters.py +++ b/apiserver/plane/utils/issue_filters.py @@ -187,7 +187,6 @@ def filter_target_date(params, filter, method): if method == "GET": target_dates = params.get("target_date").split(",") if len(target_dates) and "" not in target_dates: - date_filter(filter=filter, date_term="target_date", queries=target_dates) else: if params.get("target_date", None) and len(params.get("target_date")): diff --git a/package.json b/package.json index ba0fd9a61..2ed56291f 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "prettier": "latest", "prettier-plugin-tailwindcss": "^0.5.4", "tailwindcss": "^3.3.3", - "turbo": "latest" + "turbo": "^1.10.14" }, "resolutions": { "@types/react": "18.2.0" diff --git a/packages/editor/core/tsconfig.json b/packages/editor/core/tsconfig.json index 61a60f324..57d0e9a74 100644 --- a/packages/editor/core/tsconfig.json +++ b/packages/editor/core/tsconfig.json @@ -1,12 +1,5 @@ { - "extends": "tsconfig/react.json", - "include": [ - "src/**/*", - "index.d.ts" - ], - "exclude": [ - "dist", - "build", - "node_modules" - ] + "extends": "tsconfig/react-library.json", + "include": ["src/**/*", "index.d.ts"], + "exclude": ["dist", "build", "node_modules"] } diff --git a/packages/editor/lite-text-editor/tsconfig.json b/packages/editor/lite-text-editor/tsconfig.json index 61a60f324..57d0e9a74 100644 --- a/packages/editor/lite-text-editor/tsconfig.json +++ b/packages/editor/lite-text-editor/tsconfig.json @@ -1,12 +1,5 @@ { - "extends": "tsconfig/react.json", - "include": [ - "src/**/*", - "index.d.ts" - ], - "exclude": [ - "dist", - "build", - "node_modules" - ] + "extends": "tsconfig/react-library.json", + "include": ["src/**/*", "index.d.ts"], + "exclude": ["dist", "build", "node_modules"] } diff --git a/packages/editor/rich-text-editor/tsconfig.json b/packages/editor/rich-text-editor/tsconfig.json index 61a60f324..57d0e9a74 100644 --- a/packages/editor/rich-text-editor/tsconfig.json +++ b/packages/editor/rich-text-editor/tsconfig.json @@ -1,12 +1,5 @@ { - "extends": "tsconfig/react.json", - "include": [ - "src/**/*", - "index.d.ts" - ], - "exclude": [ - "dist", - "build", - "node_modules" - ] + "extends": "tsconfig/react-library.json", + "include": ["src/**/*", "index.d.ts"], + "exclude": ["dist", "build", "node_modules"] } diff --git a/packages/tailwind-config-custom/tailwind.config.js b/packages/tailwind-config-custom/tailwind.config.js index dd2f9291b..810f5d70d 100644 --- a/packages/tailwind-config-custom/tailwind.config.js +++ b/packages/tailwind-config-custom/tailwind.config.js @@ -11,8 +11,9 @@ module.exports = { "./layouts/**/*.tsx", "./pages/**/*.tsx", "./ui/**/*.tsx", - "../packages/editor/**/*.{js,ts,jsx,tsx}" - ] + "../packages/ui/**/*.{js,ts,jsx,tsx}", + "../packages/editor/**/*.{js,ts,jsx,tsx}", + ], }, theme: { extend: { diff --git a/packages/tsconfig/react.json b/packages/tsconfig/react-library.json similarity index 83% rename from packages/tsconfig/react.json rename to packages/tsconfig/react-library.json index 36b62be38..211c87d8d 100644 --- a/packages/tsconfig/react.json +++ b/packages/tsconfig/react-library.json @@ -6,6 +6,7 @@ "jsx": "react-jsx", "lib": ["ES2015", "DOM"], "module": "ESNext", - "target": "es6" + "target": "es6", + "sourceMap": true } } diff --git a/packages/ui/button/index.tsx b/packages/ui/button/index.tsx deleted file mode 100644 index 0a1550ec0..000000000 --- a/packages/ui/button/index.tsx +++ /dev/null @@ -1,3 +0,0 @@ -export const Button = () => { - return ; -}; diff --git a/packages/ui/index.tsx b/packages/ui/index.tsx deleted file mode 100644 index 677dc8f4d..000000000 --- a/packages/ui/index.tsx +++ /dev/null @@ -1,17 +0,0 @@ -// import * as React from "react"; -// components -// export * from "./breadcrumbs"; -// export * from "./button"; -// export * from "./custom-listbox"; -// export * from "./custom-menu"; -// export * from "./custom-select"; -// export * from "./empty-space"; -// export * from "./header-button"; -// export * from "./input"; -// export * from "./loader"; -// export * from "./outline-button"; -// export * from "./select"; -// export * from "./spinner"; -// export * from "./text-area"; -// export * from "./tooltip"; -export * from "./button"; diff --git a/packages/ui/package.json b/packages/ui/package.json index d107e711c..603d0e250 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -1,23 +1,40 @@ { - "name": "ui", - "version": "0.13.2", - "main": "./index.tsx", - "types": "./index.tsx", + "name": "@plane/ui", + "version": "0.0.1", + "main": "./dist/index.js", + "module": "./dist/index.mjs", + "types": "./dist/index.d.ts", + "sideEffects": false, "license": "MIT", + "files": [ + "dist/**" + ], "scripts": { - "lint": "eslint *.ts*" + "build": "tsup src/index.tsx --format esm,cjs --dts --external react", + "dev": "tsup src/index.tsx --format esm,cjs --watch --dts --external react", + "lint": "eslint src/", + "clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist" }, "devDependencies": { - "@types/react": "^18.0.17", - "@types/react-dom": "^18.0.6", - "@typescript-eslint/eslint-plugin": "^5.51.0", + "@types/node": "^20.5.2", + "@types/react": "18.2.0", + "@types/react-dom": "18.2.0", "classnames": "^2.3.2", - "eslint": "^7.32.0", "eslint-config-custom": "*", - "next": "12.3.2", "react": "^18.2.0", "tsconfig": "*", "tailwind-config-custom": "*", + "tsup": "^5.10.1", "typescript": "4.7.4" + }, + "publishConfig": { + "access": "public" + }, + "dependencies": { + "@blueprintjs/core": "^4.16.3", + "@blueprintjs/popover2": "^1.13.3", + "@headlessui/react": "^1.7.17", + "clsx": "^2.0.0", + "next-themes": "^0.2.1" } } diff --git a/packages/ui/src/button/button.tsx b/packages/ui/src/button/button.tsx new file mode 100644 index 000000000..706b0ae6c --- /dev/null +++ b/packages/ui/src/button/button.tsx @@ -0,0 +1,66 @@ +import * as React from "react"; + +import { + getIconStyling, + getButtonStyling, + TButtonVariant, + TButtonSizes, +} from "./helper"; + +export interface ButtonProps + extends React.ButtonHTMLAttributes { + variant?: TButtonVariant; + size?: TButtonSizes; + className?: string; + loading?: boolean; + disabled?: boolean; + appendIcon?: any; + prependIcon?: any; + children: React.ReactNode; +} + +const Button = React.forwardRef( + (props, ref) => { + const { + variant = "primary", + size = "md", + className = "", + type = "button", + loading = false, + disabled = false, + prependIcon = null, + appendIcon = null, + children, + ...rest + } = props; + + const buttonStyle = getButtonStyling(variant, size, disabled || loading); + const buttonIconStyle = getIconStyling(size); + + return ( + + ); + } +); + +Button.displayName = "plane-ui-button"; + +export { Button }; diff --git a/packages/ui/src/button/helper.tsx b/packages/ui/src/button/helper.tsx new file mode 100644 index 000000000..82489c3e8 --- /dev/null +++ b/packages/ui/src/button/helper.tsx @@ -0,0 +1,123 @@ +export type TButtonVariant = + | "primary" + | "accent-primary" + | "outline-primary" + | "neutral-primary" + | "link-primary" + | "danger" + | "accent-danger" + | "outline-danger" + | "link-danger" + | "tertiary-danger"; + +export type TButtonSizes = "sm" | "md" | "lg" | "xl"; + +export interface IButtonStyling { + [key: string]: { + default: string; + hover: string; + pressed: string; + disabled: string; + }; +} + +enum buttonSizeStyling { + sm = `px-3 py-1.5 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`, + lg = `px-5 py-2 font-medium text-sm rounded flex items-center gap-1.5 whitespace-nowrap transition-all justify-center inline`, + xl = `px-5 py-3.5 font-medium text-sm rounded flex items-center gap-1.5 whitespace-nowrap transition-all justify-center inline`, +} + +enum buttonIconStyling { + 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", + 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", +} + +export const buttonStyling: IButtonStyling = { + primary: { + default: `text-white bg-custom-primary-100`, + hover: `hover:bg-custom-primary-200`, + pressed: `focus:text-custom-brand-40 focus:bg-custom-primary-200`, + disabled: `cursor-not-allowed !bg-custom-primary-60 hover:bg-custom-primary-60`, + }, + "accent-primary": { + default: `bg-custom-primary-10 text-custom-primary-100`, + hover: `hover:bg-custom-primary-20 hover:text-custom-primary-200`, + pressed: `focus:bg-custom-primary-20`, + disabled: `cursor-not-allowed !text-custom-primary-60`, + }, + "outline-primary": { + default: `text-custom-primary-100 bg-custom-background-100 border border-custom-primary-100`, + hover: `hover:border-custom-primary-80 hover:bg-custom-primary-10`, + pressed: `focus:text-custom-primary-80 focus:bg-custom-primary-10 focus:border-custom-primary-80`, + disabled: `cursor-not-allowed !text-custom-primary-60 !border-custom-primary-60 `, + }, + "neutral-primary": { + default: `text-custom-text-200 bg-custom-background-100 border border-custom-border-200`, + hover: `hover:bg-custom-background-90`, + pressed: `focus:text-custom-text-300 focus:bg-custom-background-90`, + disabled: `cursor-not-allowed !text-custom-text-400`, + }, + "link-primary": { + default: `text-custom-primary-100 bg-custom-background-100`, + hover: `hover:text-custom-primary-200`, + pressed: `focus:text-custom-primary-80 `, + disabled: `cursor-not-allowed !text-custom-primary-60`, + }, + + danger: { + default: `text-white bg-red-500`, + hover: ` hover:bg-red-600`, + pressed: `focus:text-red-200 focus:bg-red-600`, + disabled: `cursor-not-allowed !bg-red-300`, + }, + "accent-danger": { + default: `text-red-500 bg-red-50`, + hover: `hover:text-red-600 hover:bg-red-100`, + pressed: `focus:text-red-500 focus:bg-red-100`, + disabled: `cursor-not-allowed !text-red-300`, + }, + "outline-danger": { + default: `text-red-500 bg-custom-background-100 border border-red-500`, + hover: `hover:text-red-400 hover:border-red-400`, + pressed: `focus:text-red-400 focus:border-red-400`, + disabled: `cursor-not-allowed !text-red-300 !border-red-300`, + }, + "link-danger": { + default: `text-red-500 bg-custom-background-100`, + hover: `hover:text-red-400`, + pressed: `focus:text-red-400`, + disabled: `cursor-not-allowed !text-red-300`, + }, + "tertiary-danger": { + default: `text-red-500 bg-custom-background-100 border border-red-200`, + hover: `hover:bg-red-50 hover:border-red-300`, + pressed: `focus:text-red-400`, + disabled: `cursor-not-allowed !text-red-300`, + }, +}; + +export const getButtonStyling = ( + variant: TButtonVariant, + size: TButtonSizes, + disabled: boolean = false +): string => { + let _variant: string = ``; + const currentVariant = buttonStyling[variant]; + + _variant = `${currentVariant.default} ${ + disabled ? currentVariant.disabled : currentVariant.hover + } ${currentVariant.pressed}`; + + let _size: string = ``; + if (size) _size = buttonSizeStyling[size]; + return `${_variant} ${_size}`; +}; + +export const getIconStyling = (size: TButtonSizes): string => { + let icon: string = ``; + if (size) icon = buttonIconStyling[size]; + return icon; +}; diff --git a/packages/ui/src/button/index.tsx b/packages/ui/src/button/index.tsx new file mode 100644 index 000000000..f1a2d03d4 --- /dev/null +++ b/packages/ui/src/button/index.tsx @@ -0,0 +1,2 @@ +export * from "./button"; +export * from "./toggle-switch"; diff --git a/packages/ui/src/button/toggle-switch.tsx b/packages/ui/src/button/toggle-switch.tsx new file mode 100644 index 000000000..9888dd205 --- /dev/null +++ b/packages/ui/src/button/toggle-switch.tsx @@ -0,0 +1,49 @@ +import * as React from "react"; + +import { Switch } from "@headlessui/react"; + +interface IToggleSwitchProps { + value: boolean; + onChange: (value: boolean) => void; + label?: string; + size?: "sm" | "md" | "lg"; + disabled?: boolean; + className?: string; +} + +const ToggleSwitch: React.FC = (props) => { + const { value, onChange, label, size = "sm", disabled, className } = props; + + return ( + + {label} + + ); +}; + +ToggleSwitch.displayName = "plane-ui-toggle-switch"; + +export { ToggleSwitch }; diff --git a/packages/ui/src/form-fields/index.tsx b/packages/ui/src/form-fields/index.tsx new file mode 100644 index 000000000..01cd4edea --- /dev/null +++ b/packages/ui/src/form-fields/index.tsx @@ -0,0 +1,2 @@ +export * from "./input"; +export * from "./textarea"; diff --git a/packages/ui/src/form-fields/input.tsx b/packages/ui/src/form-fields/input.tsx new file mode 100644 index 000000000..648b78aa7 --- /dev/null +++ b/packages/ui/src/form-fields/input.tsx @@ -0,0 +1,49 @@ +import * as React from "react"; + +export interface InputProps + extends React.InputHTMLAttributes { + mode?: "primary" | "transparent" | "true-transparent"; + inputSize?: "sm" | "md"; + hasError?: boolean; + className?: string; +} + +const Input = React.forwardRef((props, ref) => { + const { + id, + type, + name, + mode = "primary", + inputSize = "sm", + hasError = false, + className = "", + ...rest + } = props; + + return ( + + ); +}); + +Input.displayName = "form-input-field"; + +export { Input }; diff --git a/packages/ui/src/form-fields/textarea.tsx b/packages/ui/src/form-fields/textarea.tsx new file mode 100644 index 000000000..93a850059 --- /dev/null +++ b/packages/ui/src/form-fields/textarea.tsx @@ -0,0 +1,69 @@ +import * as React from "react"; + +export interface TextAreaProps + extends React.TextareaHTMLAttributes { + mode?: "primary" | "transparent"; + hasError?: boolean; + className?: string; +} + +// Updates the height of a