diff --git a/.husky/pre-push b/.husky/pre-push
deleted file mode 100755
index 0e7d3240b..000000000
--- a/.husky/pre-push
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/bin/sh
-. "$(dirname -- "$0")/_/husky.sh"
-
-changed_files=$(git diff --name-only HEAD~1)
-
-web_changed=$(echo "$changed_files" | grep -E '^web/' || true)
-space_changed=$(echo "$changed_files" | grep -E '^space/' || true)
-echo $web_changed
-echo $space_changed
-
-if [ -n "$web_changed" ] && [ -n "$space_changed" ]; then
- echo "Changes detected in both web and space. Building..."
- yarn run lint
- yarn run build
-elif [ -n "$web_changed" ]; then
- echo "Changes detected in web app. Building..."
- yarn run lint --filter=web
- yarn run build --filter=web
-elif [ -n "$space_changed" ]; then
- echo "Changes detected in space app. Building..."
- yarn run lint --filter=space
- yarn run build --filter=space
-fi
diff --git a/docker-compose-hub.yml b/docker-compose-hub.yml
index fcb93c530..56dbbe670 100644
--- a/docker-compose-hub.yml
+++ b/docker-compose-hub.yml
@@ -38,7 +38,7 @@ services:
container_name: planefrontend
image: makeplane/plane-frontend:latest
restart: always
- command: /usr/local/bin/start.sh apps/app/server.js app
+ command: /usr/local/bin/start.sh web/server.js web
env_file:
- .env
environment:
@@ -56,6 +56,20 @@ services:
- plane-api
- plane-worker
+ plane-deploy:
+ container_name: planedeploy
+ image: makeplane/plane-deploy:latest
+ restart: always
+ command: /usr/local/bin/start.sh space/server.js space
+ env_file:
+ - .env
+ environment:
+ NEXT_PUBLIC_API_BASE_URL: ${NEXT_PUBLIC_API_BASE_URL}
+ depends_on:
+ - plane-api
+ - plane-worker
+ - plane-web
+
plane-api:
container_name: planebackend
image: makeplane/plane-backend:latest
diff --git a/docker-compose.yml b/docker-compose.yml
index 4fe7f4ab7..e51f88c55 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -39,6 +39,7 @@ services:
context: .
dockerfile: ./web/Dockerfile.web
args:
+ DOCKER_BUILDKIT: 1
NEXT_PUBLIC_API_BASE_URL: http://localhost:8000
NEXT_PUBLIC_DEPLOY_URL: http://localhost/spaces
restart: always
@@ -67,6 +68,7 @@ services:
dockerfile: ./space/Dockerfile.space
args:
DOCKER_BUILDKIT: 1
+ NEXT_PUBLIC_DEPLOY_WITH_NGINX: 1
NEXT_PUBLIC_API_BASE_URL: http://localhost:8000
restart: always
command: /usr/local/bin/start.sh space/server.js space
@@ -84,8 +86,12 @@ services:
build:
context: ./apiserver
dockerfile: Dockerfile.api
+ args:
+ DOCKER_BUILDKIT: 1
restart: always
command: ./bin/takeoff
+ ports:
+ - 8000:8000
env_file:
- .env
environment:
@@ -99,6 +105,8 @@ services:
build:
context: ./apiserver
dockerfile: Dockerfile.api
+ args:
+ DOCKER_BUILDKIT: 1
restart: always
command: ./bin/worker
env_file:
@@ -115,6 +123,8 @@ services:
build:
context: ./apiserver
dockerfile: Dockerfile.api
+ args:
+ DOCKER_BUILDKIT: 1
restart: always
command: ./bin/beat
env_file:
diff --git a/package.json b/package.json
index 397952b3b..eb6a23994 100644
--- a/package.json
+++ b/package.json
@@ -19,8 +19,7 @@
"devDependencies": {
"eslint-config-custom": "*",
"prettier": "latest",
- "turbo": "latest",
- "husky": "^8.0.3"
+ "turbo": "latest"
},
"packageManager": "yarn@1.22.19"
}
diff --git a/space/.env.example b/space/.env.example
index 2d3165893..238f70854 100644
--- a/space/.env.example
+++ b/space/.env.example
@@ -1,8 +1,8 @@
# Base url for the API requests
NEXT_PUBLIC_API_BASE_URL=""
# Public boards deploy URL
-NEXT_PUBLIC_DEPLOY_URL="https://plane-space-dev.vercel.app"
+NEXT_PUBLIC_DEPLOY_URL=""
# Google Client ID for Google OAuth
-NEXT_PUBLIC_GOOGLE_CLIENTID=232920797020-235n93bn7hh7628vdd69hq873129ng4o.apps.googleusercontent.com
+NEXT_PUBLIC_GOOGLE_CLIENTID=""
# Flag to toggle OAuth
NEXT_PUBLIC_ENABLE_OAUTH=1
\ No newline at end of file
diff --git a/space/Dockerfile.space b/space/Dockerfile.space
index 34fe42a13..963dad136 100644
--- a/space/Dockerfile.space
+++ b/space/Dockerfile.space
@@ -1,6 +1,5 @@
FROM node:18-alpine AS builder
RUN apk add --no-cache libc6-compat
-# Set working directory
WORKDIR /app
ENV NEXT_PUBLIC_API_BASE_URL=http://NEXT_PUBLIC_API_BASE_URL_PLACEHOLDER
@@ -9,37 +8,34 @@ COPY . .
RUN turbo prune --scope=space --docker
-# Add lockfile and package.json's of isolated subworkspace
FROM node:18-alpine AS installer
RUN apk add --no-cache libc6-compat
WORKDIR /app
-ARG NEXT_PUBLIC_API_BASE_URL=http://localhost:8000
-# First install the dependencies (as they change less often)
COPY .gitignore .gitignore
COPY --from=builder /app/out/json/ .
COPY --from=builder /app/out/yarn.lock ./yarn.lock
RUN yarn install --network-timeout 500000
-# Build the project
COPY --from=builder /app/out/full/ .
COPY turbo.json turbo.json
COPY replace-env-vars.sh /usr/local/bin/
USER root
RUN chmod +x /usr/local/bin/replace-env-vars.sh
-RUN yarn turbo run build --filter=space
+ARG NEXT_PUBLIC_API_BASE_URL=http://localhost:8000
+ARG NEXT_PUBLIC_DEPLOY_WITH_NGINX=1
-ENV NEXT_PUBLIC_API_BASE_URL=$NEXT_PUBLIC_API_BASE_URL \
- BUILT_NEXT_PUBLIC_API_BASE_URL=$NEXT_PUBLIC_API_BASE_URL
+ENV NEXT_PUBLIC_API_BASE_URL=$NEXT_PUBLIC_API_BASE_URL BUILT_NEXT_PUBLIC_API_BASE_URL=$NEXT_PUBLIC_API_BASE_URL NEXT_PUBLIC_DEPLOY_WITH_NGINX=$NEXT_PUBLIC_DEPLOY_WITH_NGINX
+
+RUN yarn turbo run build --filter=space
RUN /usr/local/bin/replace-env-vars.sh http://NEXT_PUBLIC_WEBAPP_URL_PLACEHOLDER ${NEXT_PUBLIC_API_BASE_URL} space
FROM node:18-alpine AS runner
WORKDIR /app
-# Don't run production as root
RUN addgroup --system --gid 1001 plane
RUN adduser --system --uid 1001 captain
USER captain
@@ -47,16 +43,14 @@ USER captain
COPY --from=installer /app/space/next.config.js .
COPY --from=installer /app/space/package.json .
-# Automatically leverage output traces to reduce image sizß
-# https://nextjs.org/docs/advanced-features/output-file-tracing
COPY --from=installer --chown=captain:plane /app/space/.next/standalone ./
COPY --from=installer --chown=captain:plane /app/space/.next ./space/.next
COPY --from=installer --chown=captain:plane /app/space/public ./space/public
ARG NEXT_PUBLIC_API_BASE_URL=http://localhost:8000
-ENV NEXT_PUBLIC_API_BASE_URL=$NEXT_PUBLIC_API_BASE_URL \
- BUILT_NEXT_PUBLIC_API_BASE_URL=$NEXT_PUBLIC_API_BASE_URL
+ARG NEXT_PUBLIC_DEPLOY_WITH_NGINX=1
+ENV NEXT_PUBLIC_API_BASE_URL=$NEXT_PUBLIC_API_BASE_URL BUILT_NEXT_PUBLIC_API_BASE_URL=$NEXT_PUBLIC_API_BASE_URL NEXT_PUBLIC_DEPLOY_WITH_NGINX=$NEXT_PUBLIC_DEPLOY_WITH_NGINX
USER root
COPY replace-env-vars.sh /usr/local/bin/
diff --git a/space/components/views/project-details.tsx b/space/components/views/project-details.tsx
index 9a6cd824c..1c9c6ddc9 100644
--- a/space/components/views/project-details.tsx
+++ b/space/components/views/project-details.tsx
@@ -1,5 +1,9 @@
import { useEffect } from "react";
+
+import Image from "next/image";
import { useRouter } from "next/router";
+
+// mobx
import { observer } from "mobx-react-lite";
// components
import { IssueListView } from "components/issues/board-views/list";
@@ -11,6 +15,8 @@ import { IssuePeekOverview } from "components/issues/peek-overview";
// mobx store
import { RootStore } from "store/root";
import { useMobxStore } from "lib/mobx/store-provider";
+// assets
+import SomethingWentWrongImage from "public/something-went-wrong.svg";
export const ProjectDetailsView = observer(() => {
const router = useRouter();
@@ -55,8 +61,16 @@ export const ProjectDetailsView = observer(() => {
) : (
<>
{issueStore?.error ? (
-
- Something went wrong.
+
+
+
+
Oops! Something went wrong.
+
The public board does not exist. Please check the URL.
+
) : (
projectStore?.activeBoard && (
diff --git a/space/next.config.js b/space/next.config.js
index 712c1c472..392a4cab9 100644
--- a/space/next.config.js
+++ b/space/next.config.js
@@ -13,6 +13,7 @@ const nextConfig = {
if (parseInt(process.env.NEXT_PUBLIC_DEPLOY_WITH_NGINX || "0")) {
const nextConfigWithNginx = withImages({ basePath: "/spaces", ...nextConfig });
+ module.exports = nextConfigWithNginx;
} else {
module.exports = nextConfig;
}
diff --git a/space/package.json b/space/package.json
index 1c9153567..768abb8ff 100644
--- a/space/package.json
+++ b/space/package.json
@@ -9,8 +9,15 @@
"lint": "next lint"
},
"dependencies": {
+ "@blueprintjs/core": "^4.16.3",
+ "@blueprintjs/popover2": "^1.13.3",
+ "@emotion/react": "^11.11.1",
+ "@emotion/styled": "^11.11.0",
"@headlessui/react": "^1.7.13",
- "@mui/icons-material": "^5.14.7",
+ "@heroicons/react": "^2.0.12",
+ "@mui/icons-material": "^5.14.1",
+ "@mui/material": "^5.14.1",
+ "@tailwindcss/typography": "^0.5.9",
"@tiptap-pro/extension-unique-id": "^2.1.0",
"@tiptap/extension-code-block-lowlight": "^2.0.4",
"@tiptap/extension-color": "^2.0.4",
@@ -33,17 +40,25 @@
"@tiptap/starter-kit": "^2.0.4",
"@tiptap/suggestion": "^2.0.4",
"axios": "^1.3.4",
+ "clsx": "^2.0.0",
"js-cookie": "^3.0.1",
+ "lowlight": "^2.9.0",
+ "lucide-react": "^0.263.1",
"mobx": "^6.10.0",
"mobx-react-lite": "^4.0.3",
"next": "12.3.2",
"next-images": "^1.8.5",
- "next-theme": "^0.1.5",
+ "next-themes": "^0.2.1",
"nprogress": "^0.2.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
+ "react-hook-form": "^7.38.0",
+ "react-moveable": "^0.54.1",
"swr": "^2.2.2",
+ "tailwind-merge": "^1.14.0",
+ "tiptap-markdown": "^0.8.2",
"typescript": "4.9.5",
+ "use-debounce": "^9.0.4",
"uuid": "^9.0.0"
},
"devDependencies": {
diff --git a/space/public/something-went-wrong.svg b/space/public/something-went-wrong.svg
new file mode 100644
index 000000000..bd51f7f49
--- /dev/null
+++ b/space/public/something-went-wrong.svg
@@ -0,0 +1,3 @@
+
diff --git a/web/Dockerfile.web b/web/Dockerfile.web
index 6fac46c2d..40946fa2d 100644
--- a/web/Dockerfile.web
+++ b/web/Dockerfile.web
@@ -15,6 +15,7 @@ FROM node:18-alpine AS installer
RUN apk add --no-cache libc6-compat
WORKDIR /app
ARG NEXT_PUBLIC_API_BASE_URL=http://localhost:8000
+ARG NEXT_PUBLIC_DEPLOY_URL=http://localhost/spaces
# First install the dependencies (as they change less often)
COPY .gitignore .gitignore
@@ -29,11 +30,12 @@ COPY replace-env-vars.sh /usr/local/bin/
USER root
RUN chmod +x /usr/local/bin/replace-env-vars.sh
+ENV NEXT_PUBLIC_API_BASE_URL=$NEXT_PUBLIC_API_BASE_URL \
+ BUILT_NEXT_PUBLIC_API_BASE_URL=$NEXT_PUBLIC_API_BASE_URL \
+ NEXT_PUBLIC_DEPLOY_URL=$NEXT_PUBLIC_DEPLOY_URL
+
RUN yarn turbo run build --filter=web
-ENV NEXT_PUBLIC_API_BASE_URL=$NEXT_PUBLIC_API_BASE_URL \
- BUILT_NEXT_PUBLIC_API_BASE_URL=$NEXT_PUBLIC_API_BASE_URL
-ENV NEXT_PUBLIC_DEPLOY_URL=${NEXT_PUBLIC_DEPLOY_URL}
RUN /usr/local/bin/replace-env-vars.sh http://NEXT_PUBLIC_WEBAPP_URL_PLACEHOLDER ${NEXT_PUBLIC_API_BASE_URL} web
FROM node:18-alpine AS runner
@@ -54,8 +56,11 @@ COPY --from=installer --chown=captain:plane /app/web/.next/standalone ./
COPY --from=installer --chown=captain:plane /app/web/.next ./web/.next
ARG NEXT_PUBLIC_API_BASE_URL=http://localhost:8000
+ARG NEXT_PUBLIC_DEPLOY_URL=http://localhost/spaces
+
ENV NEXT_PUBLIC_API_BASE_URL=$NEXT_PUBLIC_API_BASE_URL \
- BUILT_NEXT_PUBLIC_API_BASE_URL=$NEXT_PUBLIC_API_BASE_URL
+ BUILT_NEXT_PUBLIC_API_BASE_URL=$NEXT_PUBLIC_API_BASE_URL \
+ NEXT_PUBLIC_DEPLOY_URL=$NEXT_PUBLIC_DEPLOY_URL
USER root
COPY replace-env-vars.sh /usr/local/bin/
diff --git a/web/components/core/views/all-views.tsx b/web/components/core/views/all-views.tsx
index 79d5d6b11..eb54ccb2a 100644
--- a/web/components/core/views/all-views.tsx
+++ b/web/components/core/views/all-views.tsx
@@ -53,6 +53,7 @@ type Props = {
handleOnDragEnd: (result: DropResult) => Promise
;
openIssuesListModal: (() => void) | null;
removeIssue: ((bridgeId: string, issueId: string) => void) | null;
+ disableAddIssueOption?: boolean;
trashBox: boolean;
setTrashBox: React.Dispatch>;
viewProps: IIssueViewProps;
@@ -68,6 +69,7 @@ export const AllViews: React.FC = ({
handleOnDragEnd,
openIssuesListModal,
removeIssue,
+ disableAddIssueOption = false,
trashBox,
setTrashBox,
viewProps,
@@ -127,6 +129,7 @@ export const AllViews: React.FC = ({
openIssuesListModal={cycleId || moduleId ? openIssuesListModal : null}
removeIssue={removeIssue}
disableUserActions={disableUserActions}
+ disableAddIssueOption={disableAddIssueOption}
user={user}
userAuth={memberRole}
viewProps={viewProps}
@@ -135,6 +138,7 @@ export const AllViews: React.FC = ({
void;
disableUserActions: boolean;
+ disableAddIssueOption?: boolean;
dragDisabled: boolean;
handleIssueAction: (issue: IIssue, action: "copy" | "delete" | "edit") => void;
handleTrashBox: (isDragging: boolean) => void;
@@ -24,6 +25,7 @@ type Props = {
export const AllBoards: React.FC = ({
addIssueToGroup,
disableUserActions,
+ disableAddIssueOption = false,
dragDisabled,
handleIssueAction,
handleTrashBox,
@@ -54,6 +56,7 @@ export const AllBoards: React.FC = ({
addIssueToGroup={() => addIssueToGroup(singleGroup)}
currentState={currentState}
disableUserActions={disableUserActions}
+ disableAddIssueOption={disableAddIssueOption}
dragDisabled={dragDisabled}
groupTitle={singleGroup}
handleIssueAction={handleIssueAction}
diff --git a/web/components/core/views/board-view/single-board.tsx b/web/components/core/views/board-view/single-board.tsx
index 52e8c27c7..7ba70c97b 100644
--- a/web/components/core/views/board-view/single-board.tsx
+++ b/web/components/core/views/board-view/single-board.tsx
@@ -20,6 +20,7 @@ type Props = {
addIssueToGroup: () => void;
currentState?: IState | null;
disableUserActions: boolean;
+ disableAddIssueOption?: boolean;
dragDisabled: boolean;
groupTitle: string;
handleIssueAction: (issue: IIssue, action: "copy" | "delete" | "edit") => void;
@@ -36,6 +37,7 @@ export const SingleBoard: React.FC = ({
currentState,
groupTitle,
disableUserActions,
+ disableAddIssueOption = false,
dragDisabled,
handleIssueAction,
handleTrashBox,
@@ -53,8 +55,6 @@ export const SingleBoard: React.FC = ({
const router = useRouter();
const { cycleId, moduleId } = router.query;
- const isSubscribedIssues = router.pathname.includes("subscribed");
-
const type = cycleId ? "cycle" : moduleId ? "module" : "issue";
// Check if it has at least 4 tickets since it is enough to accommodate the Calendar height
@@ -72,7 +72,7 @@ export const SingleBoard: React.FC = ({
isCollapsed={isCollapsed}
setIsCollapsed={setIsCollapsed}
disableUserActions={disableUserActions}
- disableAddIssue={isSubscribedIssues}
+ disableAddIssue={disableAddIssueOption}
viewProps={viewProps}
/>
{isCollapsed && (
@@ -154,7 +154,7 @@ export const SingleBoard: React.FC = ({
{selectedGroup !== "created_by" && (
{type === "issue"
- ? !isSubscribedIssues && (
+ ? !disableAddIssueOption && (