Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WEB-1116] feat: pages realtime sync #5057

Merged
merged 27 commits into from
Jul 22, 2024
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
f5afa92
init: live server for editor realtime sync
aaryan610 Jul 5, 2024
09e0331
chore: authentication added
aaryan610 Jul 5, 2024
cfa6f4e
fix: merge conflicts resolved from preview
aaryan610 Jul 5, 2024
03ca244
chore: updated logic to convert html to binary for old pages
aaryan610 Jul 8, 2024
d94c5b0
chore: added description json on page update
NarayanBavisetti Jul 8, 2024
0936708
chore: made all functions generic
aaryan610 Jul 8, 2024
1745aa9
Merge branch 'feat-realtime-sync' of https://github.com/makeplane/pla…
aaryan610 Jul 8, 2024
607ec56
chore: save description in json and html formats
aaryan610 Jul 10, 2024
746109c
refactor: document editor components
aaryan610 Jul 10, 2024
c174501
chore: uncomment ui package components
aaryan610 Jul 10, 2024
3d82ae7
fix: without props extensions refactor
aaryan610 Jul 12, 2024
ac986b3
fix: merge conflicts resolved from preview
aaryan610 Jul 15, 2024
093b9b3
fix: merge conflicts resolved from preview
aaryan610 Jul 15, 2024
ba244aa
chore: init docker compose
aaryan610 Jul 16, 2024
8a84518
fix: merge conflicts resolved from preview
aaryan610 Jul 16, 2024
23a05d5
Merge branch 'develop' of github.com:makeplane/plane into feat-realti…
sriramveeraghanta Jul 16, 2024
8044d42
Merge branch 'preview' of github.com:makeplane/plane into feat-realti…
NarayanBavisetti Jul 16, 2024
73f3b69
chore: pages custom error codes
NarayanBavisetti Jun 26, 2024
d80ab7e
Merge branch 'preview' of https://github.com/makeplane/plane into fea…
aaryan610 Jul 17, 2024
0d9b346
fix: merge conflicts resolved from preview
aaryan610 Jul 19, 2024
616e885
chore: add health check endpoint to the live server
aaryan610 Jul 19, 2024
e7a1265
chore: update without props extensions type
aaryan610 Jul 19, 2024
b354547
fix: merge conflicts resolved from preview
aaryan610 Jul 19, 2024
f38fd54
chore: better error handling
aaryan610 Jul 19, 2024
67fd504
Merge branch 'develop' of https://github.com/makeplane/plane into fea…
aaryan610 Jul 22, 2024
fda0344
chore: update react-hook-form versions
aaryan610 Jul 22, 2024
4e043a1
fix: build errors
aaryan610 Jul 22, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions apiserver/plane/app/views/issue/archive.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
from plane.app.serializers import (
IssueFlatSerializer,
IssueSerializer,
IssueDetailSerializer
IssueDetailSerializer,
)
from plane.bgtasks.issue_activites_task import issue_activity
from plane.db.models import (
Expand All @@ -46,6 +46,7 @@
GroupedOffsetPaginator,
SubGroupedOffsetPaginator,
)
from plane.utils.error_codes import ERROR_CODES

# Module imports
from .. import BaseViewSet, BaseAPIView
Expand Down Expand Up @@ -341,8 +342,10 @@ def post(self, request, slug, project_id):
if issue.state.group not in ["completed", "cancelled"]:
return Response(
{
"error_code": 4091,
"error_message": "INVALID_ARCHIVE_STATE_GROUP"
"error_code": ERROR_CODES[
"INVALID_ARCHIVE_STATE_GROUP"
],
"error_message": "INVALID_ARCHIVE_STATE_GROUP",
},
status=status.HTTP_400_BAD_REQUEST,
)
Expand Down
23 changes: 17 additions & 6 deletions apiserver/plane/app/views/issue/bulk_operations.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
IssueAssignee,
)
from plane.bgtasks.issue_activites_task import issue_activity
from plane.utils.error_codes import ERROR_CODES


class BulkIssueOperationsEndpoint(BaseAPIView):
Expand Down Expand Up @@ -59,14 +60,20 @@ def post(self, request, slug, project_id):

properties = request.data.get("properties", {})

if properties.get("start_date", False) and properties.get("target_date", False):
if properties.get("start_date", False) and properties.get(
"target_date", False
):
if (
datetime.strptime(properties.get("start_date"), "%Y-%m-%d").date()
> datetime.strptime(properties.get("target_date"), "%Y-%m-%d").date()
datetime.strptime(
properties.get("start_date"), "%Y-%m-%d"
).date()
> datetime.strptime(
properties.get("target_date"), "%Y-%m-%d"
).date()
):
return Response(
{
"error_code": 4100,
"error_code": ERROR_CODES["INVALID_ISSUE_DATES"],
"error_message": "INVALID_ISSUE_DATES",
},
status=status.HTTP_400_BAD_REQUEST,
Expand Down Expand Up @@ -124,7 +131,9 @@ def post(self, request, slug, project_id):
):
return Response(
{
"error_code": 4101,
"error_code": ERROR_CODES[
"INVALID_ISSUE_START_DATE"
],
"error_message": "INVALID_ISSUE_START_DATE",
},
status=status.HTTP_400_BAD_REQUEST,
Expand Down Expand Up @@ -158,7 +167,9 @@ def post(self, request, slug, project_id):
):
return Response(
{
"error_code": 4102,
"error_code": ERROR_CODES[
"INVALID_ISSUE_TARGET_DATE"
],
"error_message": "INVALID_ISSUE_TARGET_DATE",
},
status=status.HTTP_400_BAD_REQUEST,
Expand Down
17 changes: 12 additions & 5 deletions apiserver/plane/app/views/page/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
ProjectMember,
ProjectPage,
)

from plane.utils.error_codes import ERROR_CODES
# Module imports
from ..base import BaseAPIView, BaseViewSet

Expand Down Expand Up @@ -472,14 +472,20 @@ def partial_update(self, request, slug, project_id, pk):

if page.is_locked:
return Response(
{"error": "Page is locked"},
status=471,
{
"error_code": ERROR_CODES["PAGE_LOCKED"],
"error_message": "PAGE_LOCKED",
},
status=status.HTTP_400_BAD_REQUEST,
)

if page.archived_at:
return Response(
{"error": "Page is archived"},
status=472,
{
"error_code": ERROR_CODES["PAGE_ARCHIVED"],
"error_message": "PAGE_ARCHIVED",
},
status=status.HTTP_400_BAD_REQUEST,
)

# Serialize the existing instance
Expand Down Expand Up @@ -507,6 +513,7 @@ def partial_update(self, request, slug, project_id, pk):
# Store the updated binary data
page.description_binary = new_binary_data
page.description_html = request.data.get("description_html")
page.description = request.data.get("description")
page.save()
# Return a success response
page_version.delay(
Expand Down
10 changes: 10 additions & 0 deletions apiserver/plane/utils/error_codes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
ERROR_CODES = {
# issues
"INVALID_ARCHIVE_STATE_GROUP": 4091,
"INVALID_ISSUE_DATES": 4100,
"INVALID_ISSUE_START_DATE": 4101,
"INVALID_ISSUE_TARGET_DATE": 4102,
# pages
"PAGE_LOCKED": 4701,
"PAGE_ARCHIVED": 4702,
}
14 changes: 14 additions & 0 deletions docker-compose-local.yml
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,20 @@ services:
- worker
- web

live:
build:
context: .
dockerfile: ./live/Dockerfile.dev
restart: unless-stopped
networks:
- dev_env
volumes:
- ./live:/app/live
depends_on:
- api
- worker
- web

api:
build:
context: ./apiserver
Expand Down
1 change: 1 addition & 0 deletions live/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
API_BASE_URL="http://api:8000"
28 changes: 28 additions & 0 deletions live/Dockerfile.channel
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Use a Node.js base image
FROM node:latest
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Specify a Node.js version instead of using latest.

Using node:latest can introduce instability due to potential breaking changes in future releases. It's better to use a specific version.

- FROM node:latest
+ FROM node:14
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
FROM node:latest
FROM node:14


# Set working directory
WORKDIR /app

# Copy package.json and package-lock.json
COPY ./channel/package*.json ./

# Install dependencies
RUN yarn install

# COPY ./plane/editor-core ./node_modules/@plane/editor-core

# Install TypeScript
RUN yarn add typescript

# Copy the rest of the application
COPY ./channel .

# Compile TypeScript to JavaScript
RUN npx tsc

# Expose port 3003
EXPOSE 3003

# Start the Node.js server
CMD ["node", "dist/index.js"]
13 changes: 13 additions & 0 deletions live/Dockerfile.dev
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
FROM node:18-alpine
RUN apk add --no-cache libc6-compat
# Set working directory
WORKDIR /app


COPY . .
RUN yarn global add turbo
RUN yarn install
EXPOSE 3003

VOLUME [ "/app/node_modules", "/app/channel/node_modules"]
CMD ["yarn","dev", "--filter=live"]
42 changes: 42 additions & 0 deletions live/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"name": "live",
"version": "0.22.0",
"description": "",
"main": "./src/index.ts",
"scripts": {
"build": "tsup",
"start": "node dist/index.js",
"dev": "tsup --watch"
},
"keywords": [],
"type": "module",
"author": "",
"license": "ISC",
"dependencies": {
"@hocuspocus/extension-database": "^2.11.3",
"@hocuspocus/extension-logger": "^2.11.3",
"@hocuspocus/server": "^2.11.3",
"@plane/editor": "*",
"@plane/types": "*",
"@tiptap/core": "^2.4.0",
"@tiptap/html": "^2.3.0",
"axios": "^1.7.2",
"dotenv": "^16.4.5",
"express": "^4.19.2",
"express-ws": "^5.0.2",
"lodash": "^4.17.21",
"y-prosemirror": "^1.2.9",
"y-protocols": "^1.0.6",
"yjs": "^13.6.14"
},
"devDependencies": {
"@types/dotenv": "^8.2.0",
"@types/express": "^4.17.21",
"@types/express-ws": "^3.0.4",
"@types/node": "^20.14.9",
"tsup": "^7.2.0",
"nodemon": "^3.1.0",
"ts-node": "^10.9.2",
"typescript": "^5.4.5"
}
}
55 changes: 55 additions & 0 deletions live/src/authentication.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { ConnectionConfiguration } from "@hocuspocus/server";
// services
import { UserService } from "./services/user.service.js";
aaryan610 marked this conversation as resolved.
Show resolved Hide resolved
// types
import { TDocumentTypes } from "./types/common.js";
const userService = new UserService();

type Props = {
connection: ConnectionConfiguration;
cookie: string;
params: URLSearchParams;
token: string;
};

export const handleAuthentication = async (props: Props) => {
const { connection, cookie, params, token } = props;
// params
const workspaceSlug = params.get("workspaceSlug")?.toString();
const projectId = params.get("projectId")?.toString();
const documentType = params.get("documentType")?.toString() as
| TDocumentTypes
| undefined;
// fetch current user info
const response = await userService.currentUser(cookie);
if (response.id !== token) {
throw Error("Token doesn't match");
aaryan610 marked this conversation as resolved.
Show resolved Hide resolved
}

if (documentType === "project_page") {
if (!workspaceSlug || !projectId) {
throw Error(
"Incomplete query params, workspaceSlug or projectId missing",
);
}
// fetch current user's roles
const workspaceRoles = await userService.getUserAllProjectsRole(
workspaceSlug,
cookie,
);
const currentProjectRole = workspaceRoles[projectId];
// make the connection read only for roles lower than a member
if (currentProjectRole < 15) {
connection.readOnly = true;
}
} else {
throw Error("Invalid document type provided");
}
aaryan610 marked this conversation as resolved.
Show resolved Hide resolved

return {
user: {
id: response.id,
name: response.display_name,
},
};
};
Loading
Loading