forked from github/plane
Merge pull request #2090 from makeplane/develop
Promote: Develop to Stage Release
This commit is contained in:
commit
3db0ec819a
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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/
|
||||
|
@ -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": {
|
||||
|
@ -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/
|
||||
|
@ -53,6 +53,7 @@ type Props = {
|
||||
handleOnDragEnd: (result: DropResult) => Promise<void>;
|
||||
openIssuesListModal: (() => void) | null;
|
||||
removeIssue: ((bridgeId: string, issueId: string) => void) | null;
|
||||
disableAddIssueOption?: boolean;
|
||||
trashBox: boolean;
|
||||
setTrashBox: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
viewProps: IIssueViewProps;
|
||||
@ -68,6 +69,7 @@ export const AllViews: React.FC<Props> = ({
|
||||
handleOnDragEnd,
|
||||
openIssuesListModal,
|
||||
removeIssue,
|
||||
disableAddIssueOption = false,
|
||||
trashBox,
|
||||
setTrashBox,
|
||||
viewProps,
|
||||
@ -127,6 +129,7 @@ export const AllViews: React.FC<Props> = ({
|
||||
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<Props> = ({
|
||||
<AllBoards
|
||||
addIssueToGroup={addIssueToGroup}
|
||||
disableUserActions={disableUserActions}
|
||||
disableAddIssueOption={disableAddIssueOption}
|
||||
dragDisabled={dragDisabled}
|
||||
handleIssueAction={handleIssueAction}
|
||||
handleTrashBox={handleTrashBox}
|
||||
|
@ -10,6 +10,7 @@ import { ICurrentUserResponse, IIssue, IIssueViewProps, IState, UserAuth } from
|
||||
type Props = {
|
||||
addIssueToGroup: (groupTitle: string) => 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<Props> = ({
|
||||
addIssueToGroup,
|
||||
disableUserActions,
|
||||
disableAddIssueOption = false,
|
||||
dragDisabled,
|
||||
handleIssueAction,
|
||||
handleTrashBox,
|
||||
@ -52,6 +54,7 @@ export const AllBoards: React.FC<Props> = ({
|
||||
addIssueToGroup={() => addIssueToGroup(singleGroup)}
|
||||
currentState={currentState}
|
||||
disableUserActions={disableUserActions}
|
||||
disableAddIssueOption={disableAddIssueOption}
|
||||
dragDisabled={dragDisabled}
|
||||
groupTitle={singleGroup}
|
||||
handleIssueAction={handleIssueAction}
|
||||
|
@ -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<Props> = ({
|
||||
currentState,
|
||||
groupTitle,
|
||||
disableUserActions,
|
||||
disableAddIssueOption = false,
|
||||
dragDisabled,
|
||||
handleIssueAction,
|
||||
handleTrashBox,
|
||||
@ -53,8 +55,6 @@ export const SingleBoard: React.FC<Props> = ({
|
||||
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<Props> = ({
|
||||
isCollapsed={isCollapsed}
|
||||
setIsCollapsed={setIsCollapsed}
|
||||
disableUserActions={disableUserActions}
|
||||
disableAddIssue={isSubscribedIssues}
|
||||
disableAddIssue={disableAddIssueOption}
|
||||
viewProps={viewProps}
|
||||
/>
|
||||
{isCollapsed && (
|
||||
@ -154,7 +154,7 @@ export const SingleBoard: React.FC<Props> = ({
|
||||
{selectedGroup !== "created_by" && (
|
||||
<div>
|
||||
{type === "issue"
|
||||
? !isSubscribedIssues && (
|
||||
? !disableAddIssueOption && (
|
||||
<button
|
||||
type="button"
|
||||
className="flex items-center gap-2 font-medium text-custom-primary outline-none p-1"
|
||||
|
@ -11,6 +11,7 @@ type Props = {
|
||||
openIssuesListModal?: (() => void) | null;
|
||||
removeIssue: ((bridgeId: string, issueId: string) => void) | null;
|
||||
disableUserActions: boolean;
|
||||
disableAddIssueOption?: boolean;
|
||||
user: ICurrentUserResponse | undefined;
|
||||
userAuth: UserAuth;
|
||||
viewProps: IIssueViewProps;
|
||||
@ -20,6 +21,7 @@ export const AllLists: React.FC<Props> = ({
|
||||
addIssueToGroup,
|
||||
handleIssueAction,
|
||||
disableUserActions,
|
||||
disableAddIssueOption = false,
|
||||
openIssuesListModal,
|
||||
removeIssue,
|
||||
states,
|
||||
@ -49,6 +51,7 @@ export const AllLists: React.FC<Props> = ({
|
||||
openIssuesListModal={openIssuesListModal}
|
||||
removeIssue={removeIssue}
|
||||
disableUserActions={disableUserActions}
|
||||
disableAddIssueOption={disableAddIssueOption}
|
||||
user={user}
|
||||
userAuth={userAuth}
|
||||
viewProps={viewProps}
|
||||
|
@ -39,6 +39,7 @@ type Props = {
|
||||
openIssuesListModal?: (() => void) | null;
|
||||
removeIssue: ((bridgeId: string, issueId: string) => void) | null;
|
||||
disableUserActions: boolean;
|
||||
disableAddIssueOption?: boolean;
|
||||
user: ICurrentUserResponse | undefined;
|
||||
userAuth: UserAuth;
|
||||
viewProps: IIssueViewProps;
|
||||
@ -52,6 +53,7 @@ export const SingleList: React.FC<Props> = ({
|
||||
openIssuesListModal,
|
||||
removeIssue,
|
||||
disableUserActions,
|
||||
disableAddIssueOption = false,
|
||||
user,
|
||||
userAuth,
|
||||
viewProps,
|
||||
@ -60,7 +62,6 @@ export const SingleList: React.FC<Props> = ({
|
||||
const { workspaceSlug, projectId, cycleId, moduleId } = router.query;
|
||||
|
||||
const isArchivedIssues = router.pathname.includes("archived-issues");
|
||||
const isSubscribedIssues = router.pathname.includes("subscribed");
|
||||
|
||||
const type = cycleId ? "cycle" : moduleId ? "module" : "issue";
|
||||
|
||||
@ -181,7 +182,7 @@ export const SingleList: React.FC<Props> = ({
|
||||
{isArchivedIssues ? (
|
||||
""
|
||||
) : type === "issue" ? (
|
||||
!isSubscribedIssues && (
|
||||
!disableAddIssueOption && (
|
||||
<button
|
||||
type="button"
|
||||
className="p-1 text-custom-text-200 hover:bg-custom-background-80"
|
||||
|
@ -209,6 +209,15 @@ export const MyIssuesView: React.FC<Props> = ({
|
||||
Object.keys(filtersToDisplay).length > 0 &&
|
||||
nullFilters.length !== Object.keys(filtersToDisplay).length;
|
||||
|
||||
const isSubscribedIssuesRoute = router.pathname.includes("subscribed");
|
||||
const isMySubscribedIssues =
|
||||
(filters.subscriber &&
|
||||
filters.subscriber.length > 0 &&
|
||||
router.pathname.includes("my-issues")) ??
|
||||
false;
|
||||
|
||||
const disableAddIssueOption = isSubscribedIssuesRoute || isMySubscribedIssues;
|
||||
|
||||
return (
|
||||
<>
|
||||
<CreateUpdateIssueModal
|
||||
@ -291,6 +300,7 @@ export const MyIssuesView: React.FC<Props> = ({
|
||||
handleIssueAction={handleIssueAction}
|
||||
openIssuesListModal={openIssuesListModal ? openIssuesListModal : null}
|
||||
removeIssue={null}
|
||||
disableAddIssueOption={disableAddIssueOption}
|
||||
trashBox={trashBox}
|
||||
setTrashBox={setTrashBox}
|
||||
viewProps={{
|
||||
|
@ -223,6 +223,15 @@ export const ProfileIssuesView = () => {
|
||||
Object.keys(filtersToDisplay).length > 0 &&
|
||||
nullFilters.length !== Object.keys(filtersToDisplay).length;
|
||||
|
||||
const isSubscribedIssuesRoute = router.pathname.includes("subscribed");
|
||||
const isMySubscribedIssues =
|
||||
(filters.subscriber &&
|
||||
filters.subscriber.length > 0 &&
|
||||
router.pathname.includes("my-issues")) ??
|
||||
false;
|
||||
|
||||
const disableAddIssueOption = isSubscribedIssuesRoute || isMySubscribedIssues;
|
||||
|
||||
return (
|
||||
<>
|
||||
<CreateUpdateIssueModal
|
||||
@ -292,6 +301,7 @@ export const ProfileIssuesView = () => {
|
||||
handleIssueAction={handleIssueAction}
|
||||
openIssuesListModal={null}
|
||||
removeIssue={null}
|
||||
disableAddIssueOption={disableAddIssueOption}
|
||||
trashBox={trashBox}
|
||||
setTrashBox={setTrashBox}
|
||||
viewProps={{
|
||||
|
@ -14,7 +14,7 @@ import { Icon, Loader, Tooltip } from "components/ui";
|
||||
// icons
|
||||
import { EditOutlined } from "@mui/icons-material";
|
||||
// helpers
|
||||
import { render12HourFormatTime, renderLongDetailDateFormat } from "helpers/date-time.helper";
|
||||
import { renderLongDetailDateFormat } from "helpers/date-time.helper";
|
||||
import { renderEmoji } from "helpers/emoji.helper";
|
||||
// fetch-keys
|
||||
import { USER_PROFILE_PROJECT_SEGREGATION } from "constants/fetch-keys";
|
||||
@ -35,6 +35,16 @@ export const ProfileSidebar = () => {
|
||||
: null
|
||||
);
|
||||
|
||||
// Create a date object for the current time in the specified timezone
|
||||
const currentTime = new Date();
|
||||
const formatter = new Intl.DateTimeFormat("en-US", {
|
||||
timeZone: userProjectsData?.user_data.user_timezone,
|
||||
hour12: false, // Use 24-hour format
|
||||
hour: "2-digit",
|
||||
minute: "2-digit",
|
||||
});
|
||||
const timeString = formatter.format(currentTime);
|
||||
|
||||
const userDetails = [
|
||||
{
|
||||
label: "Joined on",
|
||||
@ -44,7 +54,7 @@ export const ProfileSidebar = () => {
|
||||
label: "Timezone",
|
||||
value: (
|
||||
<span>
|
||||
{render12HourFormatTime(new Date())}{" "}
|
||||
{timeString}{" "}
|
||||
<span className="text-custom-text-200">{userProjectsData?.user_data.user_timezone}</span>
|
||||
</span>
|
||||
),
|
||||
|
Loading…
Reference in New Issue
Block a user