[chore] Update setup.sh, with removed replacement script & added project-level ENVs (#2115)

* chore: Updated Setup Script for Splitting Env File

* chore: updated dockerfile for using inproject env varaibles

* chore: removed husky replacement script

* chore: updated shell script using sed

* chore: updated dockerfiles with removed cp statement

* chore: added example env for apiserver

* chore: refactored secret generation for backend

* chore: removed replacement script

* chore: updated docker-compose with removed env variables

* chore: resolved comments in setup.sh and docker-compose

* chore: removed secret key placeholder in apiserver example env

* chore: updated root env for project less env variables

* chore: removed project level env update from root env logic

* chore: updated API_BASE_URL in .env.example

* chore: restored docker argument as env NEXT_PUBLIC_API_BASE_URL

* chore: added pg missing env variables

* [chore] Updated web and deploy backend configuration for reverse proxy & decoupled Plane Deploy URL generation for web (#2135)

* chore: removed api url build arg from compose

* chore: set public api default argument to black string for self hosted

* chore: updated web services to accept blank string as API URL

* chore: added env variables for pg compose service

* chore: modified space app services to use accept empty string as api base

* chore: conditionally trigger web url value based on argument

* fix: made web to use identical host with spaces suffix on absense of Deploy URL for deploy

* chore: added example env for PUBLIC_DEPLOY Env

* chore: updated web dockerfile with addition as PLANE_DEPLOY Argument

* API BASE URL global update

* API BASE URL replace with api server

* api base url fixes

* typo  fixes

---------

Co-authored-by: sriram veeraghanta <veeraghanta.sriram@gmail.com>

* dev: remove API_BASE_URL from environment variable

---------

Co-authored-by: sriram veeraghanta <veeraghanta.sriram@gmail.com>
Co-authored-by: pablohashescobar <nikhilschacko@gmail.com>
This commit is contained in:
Henit Chobisa 2023-09-13 20:21:02 +05:30 committed by GitHub
parent af73bbe718
commit d0f6ca3bac
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
43 changed files with 179 additions and 286 deletions

View File

@ -1,38 +1,3 @@
# Frontend
# Extra image domains that need to be added for Next Image
NEXT_PUBLIC_EXTRA_IMAGE_DOMAINS=
# Google Client ID for Google OAuth
NEXT_PUBLIC_GOOGLE_CLIENTID=""
# Github ID for Github OAuth
NEXT_PUBLIC_GITHUB_ID=""
# Github App Name for GitHub Integration
NEXT_PUBLIC_GITHUB_APP_NAME=""
# Sentry DSN for error monitoring
NEXT_PUBLIC_SENTRY_DSN=""
# Enable/Disable OAUTH - default 0 for selfhosted instance
NEXT_PUBLIC_ENABLE_OAUTH=0
# Enable/Disable sentry
NEXT_PUBLIC_ENABLE_SENTRY=0
# Enable/Disable session recording
NEXT_PUBLIC_ENABLE_SESSION_RECORDER=0
# Enable/Disable event tracking
NEXT_PUBLIC_TRACK_EVENTS=0
# Slack for Slack Integration
NEXT_PUBLIC_SLACK_CLIENT_ID=""
# For Telemetry, set it to "app.plane.so"
NEXT_PUBLIC_PLAUSIBLE_DOMAIN=""
# public boards deploy url
NEXT_PUBLIC_DEPLOY_URL=""
# plane deploy using nginx
NEXT_PUBLIC_DEPLOY_WITH_NGINX=1
# Backend
# Debug value for api server use it as 0 for production use
DEBUG=0
# Error logs
SENTRY_DSN=""
# Database Settings
PGUSER="plane"
PGPASSWORD="plane"
@ -45,15 +10,6 @@ REDIS_HOST="plane-redis"
REDIS_PORT="6379"
REDIS_URL="redis://${REDIS_HOST}:6379/"
# Email Settings
EMAIL_HOST=""
EMAIL_HOST_USER=""
EMAIL_HOST_PASSWORD=""
EMAIL_PORT=587
EMAIL_FROM="Team Plane <team@mailer.plane.so>"
EMAIL_USE_TLS="1"
EMAIL_USE_SSL="0"
# AWS Settings
AWS_REGION=""
AWS_ACCESS_KEY_ID="access-key"
@ -69,9 +25,6 @@ OPENAI_API_BASE="https://api.openai.com/v1" # change if using a custom endpoint
OPENAI_API_KEY="sk-" # add your openai key here
GPT_ENGINE="gpt-3.5-turbo" # use "gpt-4" if you have access
# Github
GITHUB_CLIENT_SECRET="" # For fetching release notes
# Settings related to Docker
DOCKERIZED=1
# set to 1 If using the pre-configured minio setup
@ -80,10 +33,3 @@ USE_MINIO=1
# Nginx Configuration
NGINX_PORT=80
# Default Creds
DEFAULT_EMAIL="captain@plane.so"
DEFAULT_PASSWORD="password123"
# SignUps
ENABLE_SIGNUP="1"
# Auto generated and Required that will be generated from setup.sh

60
apiserver/.env.example Normal file
View File

@ -0,0 +1,60 @@
# Backend
# Debug value for api server use it as 0 for production use
DEBUG=0
# Error logs
SENTRY_DSN=""
# Database Settings
PGUSER="plane"
PGPASSWORD="plane"
PGHOST="plane-db"
PGDATABASE="plane"
DATABASE_URL=postgresql://${PGUSER}:${PGPASSWORD}@${PGHOST}/${PGDATABASE}
# Redis Settings
REDIS_HOST="plane-redis"
REDIS_PORT="6379"
REDIS_URL="redis://${REDIS_HOST}:6379/"
# Email Settings
EMAIL_HOST=""
EMAIL_HOST_USER=""
EMAIL_HOST_PASSWORD=""
EMAIL_PORT=587
EMAIL_FROM="Team Plane <team@mailer.plane.so>"
EMAIL_USE_TLS="1"
EMAIL_USE_SSL="0"
# AWS Settings
AWS_REGION=""
AWS_ACCESS_KEY_ID="access-key"
AWS_SECRET_ACCESS_KEY="secret-key"
AWS_S3_ENDPOINT_URL="http://plane-minio:9000"
# Changing this requires change in the nginx.conf for uploads if using minio setup
AWS_S3_BUCKET_NAME="uploads"
# Maximum file upload limit
FILE_SIZE_LIMIT=5242880
# GPT settings
OPENAI_API_BASE="https://api.openai.com/v1" # change if using a custom endpoint
OPENAI_API_KEY="sk-" # add your openai key here
GPT_ENGINE="gpt-3.5-turbo" # use "gpt-4" if you have access
# Github
GITHUB_CLIENT_SECRET="" # For fetching release notes
# Settings related to Docker
DOCKERIZED=1
# set to 1 If using the pre-configured minio setup
USE_MINIO=1
# Nginx Configuration
NGINX_PORT=80
# Default Creds
DEFAULT_EMAIL="captain@plane.so"
DEFAULT_PASSWORD="password123"
# SignUps
ENABLE_SIGNUP="1"

View File

@ -1,37 +1,5 @@
version: "3.8"
x-api-and-worker-env: &api-and-worker-env
DEBUG: ${DEBUG}
SENTRY_DSN: ${SENTRY_DSN}
DJANGO_SETTINGS_MODULE: plane.settings.production
DATABASE_URL: postgres://${PGUSER}:${PGPASSWORD}@${PGHOST}:5432/${PGDATABASE}
REDIS_URL: redis://plane-redis:6379/
EMAIL_HOST: ${EMAIL_HOST}
EMAIL_HOST_USER: ${EMAIL_HOST_USER}
EMAIL_HOST_PASSWORD: ${EMAIL_HOST_PASSWORD}
EMAIL_PORT: ${EMAIL_PORT}
EMAIL_FROM: ${EMAIL_FROM}
EMAIL_USE_TLS: ${EMAIL_USE_TLS}
EMAIL_USE_SSL: ${EMAIL_USE_SSL}
AWS_REGION: ${AWS_REGION}
AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID}
AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY}
AWS_S3_BUCKET_NAME: ${AWS_S3_BUCKET_NAME}
AWS_S3_ENDPOINT_URL: ${AWS_S3_ENDPOINT_URL}
FILE_SIZE_LIMIT: ${FILE_SIZE_LIMIT}
WEB_URL: ${WEB_URL}
GITHUB_CLIENT_SECRET: ${GITHUB_CLIENT_SECRET}
DISABLE_COLLECTSTATIC: 1
DOCKERIZED: 1
OPENAI_API_BASE: ${OPENAI_API_BASE}
OPENAI_API_KEY: ${OPENAI_API_KEY}
GPT_ENGINE: ${GPT_ENGINE}
SECRET_KEY: ${SECRET_KEY}
DEFAULT_EMAIL: ${DEFAULT_EMAIL}
DEFAULT_PASSWORD: ${DEFAULT_PASSWORD}
USE_MINIO: ${USE_MINIO}
ENABLE_SIGNUP: ${ENABLE_SIGNUP}
services:
plane-web:
container_name: planefrontend
@ -40,23 +8,8 @@ services:
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
command: /usr/local/bin/start.sh web/server.js web
env_file:
- .env
environment:
NEXT_PUBLIC_API_BASE_URL: ${NEXT_PUBLIC_API_BASE_URL}
NEXT_PUBLIC_DEPLOY_URL: ${NEXT_PUBLIC_DEPLOY_URL}
NEXT_PUBLIC_GOOGLE_CLIENTID: "0"
NEXT_PUBLIC_GITHUB_APP_NAME: "0"
NEXT_PUBLIC_GITHUB_ID: "0"
NEXT_PUBLIC_SENTRY_DSN: "0"
NEXT_PUBLIC_ENABLE_OAUTH: "0"
NEXT_PUBLIC_ENABLE_SENTRY: "0"
NEXT_PUBLIC_ENABLE_SESSION_RECORDER: "0"
NEXT_PUBLIC_TRACK_EVENTS: "0"
depends_on:
- plane-api
- plane-worker
@ -68,14 +21,8 @@ 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
env_file:
- .env
environment:
- NEXT_PUBLIC_API_BASE_URL=${NEXT_PUBLIC_API_BASE_URL}
depends_on:
- plane-api
- plane-worker
@ -91,9 +38,7 @@ services:
restart: always
command: ./bin/takeoff
env_file:
- .env
environment:
<<: *api-and-worker-env
- ./apiserver/.env
depends_on:
- plane-db
- plane-redis
@ -108,9 +53,7 @@ services:
restart: always
command: ./bin/worker
env_file:
- .env
environment:
<<: *api-and-worker-env
- ./apiserver/.env
depends_on:
- plane-api
- plane-db
@ -126,9 +69,7 @@ services:
restart: always
command: ./bin/beat
env_file:
- .env
environment:
<<: *api-and-worker-env
- ./apiserver/.env
depends_on:
- plane-api
- plane-db
@ -163,8 +104,6 @@ services:
command: server /export --console-address ":9090"
volumes:
- uploads:/export
env_file:
- .env
environment:
MINIO_ROOT_USER: ${AWS_ACCESS_KEY_ID}
MINIO_ROOT_PASSWORD: ${AWS_SECRET_ACCESS_KEY}
@ -187,8 +126,6 @@ services:
restart: always
ports:
- ${NGINX_PORT}:80
env_file:
- .env
environment:
FILE_SIZE_LIMIT: ${FILE_SIZE_LIMIT:-5242880}
BUCKET_NAME: ${AWS_S3_BUCKET_NAME:-uploads}

View File

@ -1,15 +0,0 @@
#!/bin/sh
FROM=$1
TO=$2
DIRECTORY=$3
if [ "${FROM}" = "${TO}" ]; then
echo "Nothing to replace, the value is already set to ${TO}."
exit 0
fi
# Only perform action if $FROM and $TO are different.
echo "Replacing all statically built instances of $FROM with this string $TO ."
grep -R -la "${FROM}" $DIRECTORY/.next | xargs -I{} sed -i "s|$FROM|$TO|g" "{}"

View File

@ -5,15 +5,12 @@ cp ./.env.example ./.env
export LC_ALL=C
export LC_CTYPE=C
# Generate the NEXT_PUBLIC_API_BASE_URL with given IP
echo -e "\nNEXT_PUBLIC_API_BASE_URL=$1" >> ./.env
cp ./web/.env.example ./web/.env
cp ./space/.env.example ./space/.env
cp ./apiserver/.env.example ./apiserver/.env
# Generate the SECRET_KEY that will be used by django
echo -e "SECRET_KEY=\"$(tr -dc 'a-z0-9' < /dev/urandom | head -c50)\"" >> ./.env
# WEB_URL for email redirection and image saving
echo -e "WEB_URL=$1" >> ./.env
echo -e "SECRET_KEY=\"$(tr -dc 'a-z0-9' < /dev/urandom | head -c50)\"" >> ./apiserver/.env
# Generate Prompt for taking tiptap auth key
echo -e "\n\e[1;38m Instructions for generating TipTap Pro Extensions Auth Token \e[0m \n"
@ -21,9 +18,7 @@ echo -e "\n\e[1;38m Instructions for generating TipTap Pro Extensions Auth Token
echo -e "\e[1;38m 1. Head over to TipTap cloud's Pro Extensions Page, https://collab.tiptap.dev/pro-extensions \e[0m"
echo -e "\e[1;38m 2. Copy the token given to you under the first paragraph, after 'Here it is' \e[0m \n"
read -p $'\e[1;32m Please Enter Your TipTap Pro Extensions Authentication Token: \e[0m \e[1;36m' authToken
read -p $'\e[1;32m Please Enter Your TipTap Pro Extensions Authentication Token: \e[0m \e[1;36m' authToken
echo "@tiptap-pro:registry=https://registry.tiptap.dev/
//registry.tiptap.dev/:_authToken=${authToken}" > .npmrc
//registry.tiptap.dev/:_authToken=${authToken}" > .npmrc

View File

@ -1,5 +1,3 @@
# Base url for the API requests
NEXT_PUBLIC_API_BASE_URL=""
# Public boards deploy URL
NEXT_PUBLIC_DEPLOY_URL=""
# Google Client ID for Google OAuth

View File

@ -1,7 +1,6 @@
FROM node:18-alpine AS builder
RUN apk add --no-cache libc6-compat
WORKDIR /app
ENV NEXT_PUBLIC_API_BASE_URL=http://NEXT_PUBLIC_API_BASE_URL_PLACEHOLDER
RUN yarn global add turbo
COPY . .
@ -20,19 +19,16 @@ RUN yarn install --network-timeout 500000
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
ARG NEXT_PUBLIC_API_BASE_URL=http://localhost:8000
ARG 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
ENV NEXT_PUBLIC_API_BASE_URL=$NEXT_PUBLIC_API_BASE_URL
ENV 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
@ -48,14 +44,14 @@ 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
ARG 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
ENV NEXT_PUBLIC_API_BASE_URL=$NEXT_PUBLIC_API_BASE_URL
ENV NEXT_PUBLIC_DEPLOY_WITH_NGINX=$NEXT_PUBLIC_DEPLOY_WITH_NGINX
USER root
COPY replace-env-vars.sh /usr/local/bin/
COPY start.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/replace-env-vars.sh
RUN chmod +x /usr/local/bin/start.sh
USER captain

View File

@ -0,0 +1,2 @@
export const API_BASE_URL =
process.env.NEXT_PUBLIC_API_BASE_URL !== undefined ? process.env.NEXT_PUBLIC_API_BASE_URL : "http://localhost:8000";

View File

@ -1,9 +1,10 @@
// services
import APIService from "services/api.service";
import { API_BASE_URL } from "helpers/common.helper";
class AuthService extends APIService {
constructor() {
super(process.env.NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
super(API_BASE_URL);
}
async emailLogin(data: any) {

View File

@ -1,7 +1,5 @@
// services
import APIService from "services/api.service";
const { NEXT_PUBLIC_API_BASE_URL } = process.env;
import { API_BASE_URL } from "helpers/common.helper";
interface UnSplashImage {
id: string;
@ -29,7 +27,7 @@ interface UnSplashImageUrls {
class FileServices extends APIService {
constructor() {
super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
super(API_BASE_URL);
}
async uploadFile(workspaceSlug: string, file: FormData): Promise<any> {

View File

@ -1,9 +1,10 @@
// services
import APIService from "services/api.service";
import { API_BASE_URL } from "helpers/common.helper";
class IssueService extends APIService {
constructor() {
super(process.env.NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
super(API_BASE_URL);
}
async getPublicIssues(workspace_slug: string, project_slug: string, params: any): Promise<any> {

View File

@ -1,9 +1,10 @@
// services
import APIService from "services/api.service";
import { API_BASE_URL } from "helpers/common.helper";
class ProjectService extends APIService {
constructor() {
super(process.env.NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
super(API_BASE_URL);
}
async getProjectSettings(workspace_slug: string, project_slug: string): Promise<any> {

View File

@ -1,9 +1,10 @@
// services
import APIService from "services/api.service";
import { API_BASE_URL } from "helpers/common.helper";
class UserService extends APIService {
constructor() {
super(process.env.NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
super(API_BASE_URL);
}
async currentUser(): Promise<any> {

View File

@ -1,9 +1,5 @@
#!/bin/sh
set -x
# Replace the statically built BUILT_NEXT_PUBLIC_API_BASE_URL with run-time NEXT_PUBLIC_API_BASE_URL
# NOTE: if these values are the same, this will be skipped.
/usr/local/bin/replace-env-vars.sh "$BUILT_NEXT_PUBLIC_API_BASE_URL" "$NEXT_PUBLIC_API_BASE_URL" $2
echo "Starting Plane Frontend.."
node $1

View File

@ -1,5 +1,3 @@
# Base url for the API requests
NEXT_PUBLIC_API_BASE_URL=""
# Extra image domains that need to be added for Next Image
NEXT_PUBLIC_EXTRA_IMAGE_DOMAINS=
# Google Client ID for Google OAuth
@ -23,4 +21,4 @@ NEXT_PUBLIC_SLACK_CLIENT_ID=""
# For Telemetry, set it to "app.plane.so"
NEXT_PUBLIC_PLAUSIBLE_DOMAIN=""
# Public boards deploy URL
NEXT_PUBLIC_DEPLOY_URL=""
NEXT_PUBLIC_DEPLOY_URL="http://localhost:3000/spaces"

View File

@ -2,7 +2,6 @@ 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
RUN yarn global add turbo
COPY . .
@ -14,8 +13,8 @@ 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
ARG NEXT_PUBLIC_API_BASE_URL=""
ARG NEXT_PUBLIC_DEPLOY_URL=""
# First install the dependencies (as they change less often)
COPY .gitignore .gitignore
@ -26,18 +25,12 @@ 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
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
ENV NEXT_PUBLIC_API_BASE_URL=$NEXT_PUBLIC_API_BASE_URL
ENV NEXT_PUBLIC_DEPLOY_URL=$NEXT_PUBLIC_DEPLOY_URL
RUN yarn turbo run build --filter=web
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
WORKDIR /app
@ -52,20 +45,15 @@ COPY --from=installer /app/web/package.json .
# Automatically leverage output traces to reduce image size
# https://nextjs.org/docs/advanced-features/output-file-tracing
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 \
NEXT_PUBLIC_DEPLOY_URL=$NEXT_PUBLIC_DEPLOY_URL
ARG NEXT_PUBLIC_API_BASE_URL=""
ARG NEXT_PUBLIC_DEPLOY_URL=""
ENV NEXT_PUBLIC_API_BASE_URL=$NEXT_PUBLIC_API_BASE_URL
ENV NEXT_PUBLIC_DEPLOY_URL=$NEXT_PUBLIC_DEPLOY_URL
USER root
COPY replace-env-vars.sh /usr/local/bin/
COPY start.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/replace-env-vars.sh
RUN chmod +x /usr/local/bin/start.sh
USER captain

View File

@ -63,7 +63,11 @@ export const PublishProjectModal: React.FC<Props> = observer(() => {
const [isUnpublishing, setIsUnpublishing] = useState(false);
const [isUpdateRequired, setIsUpdateRequired] = useState(false);
const plane_deploy_url = process.env.NEXT_PUBLIC_DEPLOY_URL ?? "http://localhost:4000";
let plane_deploy_url = process.env.NEXT_PUBLIC_DEPLOY_URL;
if (typeof window !== 'undefined' && !plane_deploy_url) {
plane_deploy_url= window.location.protocol + "//" + window.location.host + "/spaces";
}
const router = useRouter();
const { workspaceSlug } = router.query;

View File

@ -16,3 +16,8 @@ export const debounce = (func: any, wait: number, immediate: boolean = false) =>
if (callNow) func(...args);
};
};
export const API_BASE_URL =
process.env.NEXT_PUBLIC_API_BASE_URL !== undefined
? process.env.NEXT_PUBLIC_API_BASE_URL
: "http://localhost:8000";

View File

@ -17,7 +17,11 @@ type Props = {
};
const { NEXT_PUBLIC_DEPLOY_URL } = process.env;
const plane_deploy_url = NEXT_PUBLIC_DEPLOY_URL ? NEXT_PUBLIC_DEPLOY_URL : "http://localhost:3001";
let plane_deploy_url = NEXT_PUBLIC_DEPLOY_URL
if (typeof window !== 'undefined' && !plane_deploy_url) {
plane_deploy_url= window.location.protocol + "//" + window.location.host + "/spaces";
}
const Header: React.FC<Props> = ({ breadcrumbs, left, right, setToggleSidebar, noHeader }) => {
const { projectDetails } = useProjectDetails();

View File

@ -2,6 +2,8 @@
import { convertCookieStringToObject } from "./cookie";
// types
import type { IProjectMember, IUser, IWorkspace, IWorkspaceMember } from "types";
// helper
import { API_BASE_URL } from "helpers/common.helper";
export const requiredAuth = async (cookie?: string) => {
const cookies = convertCookieStringToObject(cookie);
@ -9,12 +11,10 @@ export const requiredAuth = async (cookie?: string) => {
if (!token) return null;
const baseUrl = process.env.NEXT_PUBLIC_API_BASE_URL || "https://api.plane.so";
let user: IUser | null = null;
try {
const data = await fetch(`${baseUrl}/api/users/me/`, {
const data = await fetch(`${API_BASE_URL}/api/users/me/`, {
method: "GET",
headers: {
"Content-Type": "application/json",
@ -41,13 +41,11 @@ export const requiredAdmin = async (workspaceSlug: string, projectId: string, co
const cookies = convertCookieStringToObject(cookie);
const token = cookies?.accessToken;
const baseUrl = process.env.NEXT_PUBLIC_API_BASE_URL || "https://api.plane.so";
let memberDetail: IProjectMember | null = null;
try {
const data = await fetch(
`${baseUrl}/api/workspaces/${workspaceSlug}/projects/${projectId}/project-members/me/`,
`${API_BASE_URL}/api/workspaces/${workspaceSlug}/projects/${projectId}/project-members/me/`,
{
method: "GET",
headers: {
@ -75,17 +73,18 @@ export const requiredWorkspaceAdmin = async (workspaceSlug: string, cookie?: str
const cookies = convertCookieStringToObject(cookie);
const token = cookies?.accessToken;
const baseUrl = process.env.NEXT_PUBLIC_API_BASE_URL || "https://api.plane.so";
let memberDetail: IWorkspaceMember | null = null;
try {
const data = await fetch(`${baseUrl}/api/workspaces/${workspaceSlug}/workspace-members/me/`, {
method: "GET",
headers: {
Authorization: `Bearer ${token}`,
},
})
const data = await fetch(
`${API_BASE_URL}/api/workspaces/${workspaceSlug}/workspace-members/me/`,
{
method: "GET",
headers: {
Authorization: `Bearer ${token}`,
},
}
)
.then((res) => res.json())
.then((data) => data);
@ -119,13 +118,11 @@ export const homePageRedirect = async (cookie?: string) => {
let workspaces: IWorkspace[] = [];
const baseUrl = process.env.NEXT_PUBLIC_API_BASE_URL || "https://api.plane.so";
const cookies = convertCookieStringToObject(cookie);
const token = cookies?.accessToken;
try {
const data = await fetch(`${baseUrl}/api/users/me/workspaces/`, {
const data = await fetch(`${API_BASE_URL}/api/users/me/workspaces/`, {
method: "GET",
headers: {
"Content-Type": "application/json",
@ -166,7 +163,7 @@ export const homePageRedirect = async (cookie?: string) => {
};
}
const invitations = await fetch(`${baseUrl}/api/users/me/invitations/workspaces/`, {
const invitations = await fetch(`${API_BASE_URL}/api/users/me/invitations/workspaces/`, {
method: "GET",
headers: {
"Content-Type": "application/json",

View File

@ -1,18 +1,16 @@
// services
import APIService from "services/api.service";
import trackEventServices from "services/track-event.service";
// types
import { ICurrentUserResponse, IGptResponse } from "types";
const { NEXT_PUBLIC_API_BASE_URL } = process.env;
// helpers
import { API_BASE_URL } from "helpers/common.helper";
const trackEvent =
process.env.NEXT_PUBLIC_TRACK_EVENTS === "true" || process.env.NEXT_PUBLIC_TRACK_EVENTS === "1";
class AiServices extends APIService {
constructor() {
super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
super(API_BASE_URL);
}
async createGptTask(

View File

@ -8,12 +8,11 @@ import {
IExportAnalyticsFormData,
ISaveAnalyticsFormData,
} from "types";
const { NEXT_PUBLIC_API_BASE_URL } = process.env;
import { API_BASE_URL } from "helpers/common.helper";
class AnalyticsServices extends APIService {
constructor() {
super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
super(API_BASE_URL);
}
async getAnalytics(workspaceSlug: string, params: IAnalyticsParams): Promise<IAnalyticsResponse> {

View File

@ -1,12 +1,11 @@
// services
import axios from "axios";
import APIService from "services/api.service";
const { NEXT_PUBLIC_API_BASE_URL } = process.env;
import { API_BASE_URL } from "helpers/common.helper";
class AppInstallationsService extends APIService {
constructor() {
super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
super(API_BASE_URL);
}
async addInstallationApp(workspaceSlug: string, provider: string, data: any): Promise<any> {

View File

@ -1,12 +1,11 @@
// services
import APIService from "services/api.service";
import { ICurrentUserResponse } from "types";
const { NEXT_PUBLIC_API_BASE_URL } = process.env;
import { API_BASE_URL } from "helpers/common.helper";
class AuthService extends APIService {
constructor() {
super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
super(API_BASE_URL);
}
async emailLogin(data: any) {

View File

@ -1,18 +1,16 @@
// services
import APIService from "services/api.service";
import trackEventServices from "services/track-event.service";
// types
import type { CycleDateCheckData, ICurrentUserResponse, ICycle, IIssue } from "types";
const { NEXT_PUBLIC_API_BASE_URL } = process.env;
import { API_BASE_URL } from "helpers/common.helper";
const trackEvent =
process.env.NEXT_PUBLIC_TRACK_EVENTS === "true" || process.env.NEXT_PUBLIC_TRACK_EVENTS === "1";
class ProjectCycleServices extends APIService {
constructor() {
super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
super(API_BASE_URL);
}
async createCycle(

View File

@ -3,15 +3,14 @@ import APIService from "services/api.service";
// types
import type { ICurrentUserResponse, IEstimate, IEstimateFormData } from "types";
import trackEventServices from "services/track-event.service";
const { NEXT_PUBLIC_API_BASE_URL } = process.env;
import { API_BASE_URL } from "helpers/common.helper";
const trackEvent =
process.env.NEXT_PUBLIC_TRACK_EVENTS === "true" || process.env.NEXT_PUBLIC_TRACK_EVENTS === "1";
class ProjectEstimateServices extends APIService {
constructor() {
super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
super(API_BASE_URL);
}
async createEstimate(

View File

@ -1,7 +1,6 @@
// services
import APIService from "services/api.service";
const { NEXT_PUBLIC_API_BASE_URL } = process.env;
import { API_BASE_URL } from "helpers/common.helper";
interface UnSplashImage {
id: string;
@ -29,7 +28,7 @@ interface UnSplashImageUrls {
class FileServices extends APIService {
constructor() {
super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
super(API_BASE_URL);
}
async uploadFile(workspaceSlug: string, file: FormData): Promise<any> {

View File

@ -1,7 +1,6 @@
import APIService from "services/api.service";
import trackEventServices from "services/track-event.service";
const { NEXT_PUBLIC_API_BASE_URL } = process.env;
import { API_BASE_URL } from "helpers/common.helper";
const trackEvent =
process.env.NEXT_PUBLIC_TRACK_EVENTS === "true" || process.env.NEXT_PUBLIC_TRACK_EVENTS === "1";
@ -19,7 +18,7 @@ import type {
class InboxServices extends APIService {
constructor() {
super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
super(API_BASE_URL);
}
async getInboxes(workspaceSlug: string, projectId: string): Promise<IInbox[]> {

View File

@ -1,16 +1,14 @@
import APIService from "services/api.service";
import trackEventServices from "services/track-event.service";
import { ICurrentUserResponse } from "types";
const { NEXT_PUBLIC_API_BASE_URL } = process.env;
import { API_BASE_URL } from "helpers/common.helper";
const trackEvent =
process.env.NEXT_PUBLIC_TRACK_EVENTS === "true" || process.env.NEXT_PUBLIC_TRACK_EVENTS === "1";
class CSVIntegrationService extends APIService {
constructor() {
super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
super(API_BASE_URL);
}
async exportCSVService(

View File

@ -1,5 +1,6 @@
import APIService from "services/api.service";
import trackEventServices from "services/track-event.service";
import { API_BASE_URL } from "helpers/common.helper";
import { ICurrentUserResponse, IGithubRepoInfo, IGithubServiceImportFormData } from "types";
@ -11,7 +12,7 @@ const trackEvent =
const integrationServiceType: string = "github";
class GithubIntegrationService extends APIService {
constructor() {
super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
super(API_BASE_URL);
}
async listAllRepositories(workspaceSlug: string, integrationSlug: string): Promise<any> {

View File

@ -9,15 +9,14 @@ import {
IWorkspaceIntegration,
IExportServiceResponse,
} from "types";
const { NEXT_PUBLIC_API_BASE_URL } = process.env;
import { API_BASE_URL } from "helpers/common.helper";
const trackEvent =
process.env.NEXT_PUBLIC_TRACK_EVENTS === "true" || process.env.NEXT_PUBLIC_TRACK_EVENTS === "1";
class IntegrationService extends APIService {
constructor() {
super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
super(API_BASE_URL);
}
async getAppIntegrationsList(): Promise<IAppIntegration[]> {

View File

@ -1,6 +1,6 @@
import APIService from "services/api.service";
import trackEventServices from "services/track-event.service";
import { API_BASE_URL } from "helpers/common.helper";
// types
import { IJiraMetadata, IJiraResponse, IJiraImporterForm, ICurrentUserResponse } from "types";
@ -11,7 +11,7 @@ const trackEvent =
class JiraImportedService extends APIService {
constructor() {
super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
super(API_BASE_URL);
}
async getJiraProjectInfo(workspaceSlug: string, params: IJiraMetadata): Promise<IJiraResponse> {

View File

@ -10,15 +10,14 @@ import type {
IIssueLabels,
ISubIssueResponse,
} from "types";
const { NEXT_PUBLIC_API_BASE_URL } = process.env;
import { API_BASE_URL } from "helpers/common.helper";
const trackEvent =
process.env.NEXT_PUBLIC_TRACK_EVENTS === "true" || process.env.NEXT_PUBLIC_TRACK_EVENTS === "1";
class ProjectIssuesServices extends APIService {
constructor() {
super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
super(API_BASE_URL);
}
async createIssues(

View File

@ -1,9 +1,9 @@
// services
import APIService from "services/api.service";
import trackEventServices from "./track-event.service";
// types
import type { IModule, IIssue, ICurrentUserResponse } from "types";
import type { IIssueViewOptions, IModule, IIssue, ICurrentUserResponse } from "types";
import { API_BASE_URL } from "helpers/common.helper";
const { NEXT_PUBLIC_API_BASE_URL } = process.env;
@ -12,7 +12,7 @@ const trackEvent =
class ProjectIssuesServices extends APIService {
constructor() {
super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
super(API_BASE_URL);
}
async getModules(workspaceSlug: string, projectId: string): Promise<IModule[]> {

View File

@ -1,8 +1,5 @@
// services
import APIService from "services/api.service";
const { NEXT_PUBLIC_API_BASE_URL } = process.env;
// types
import type {
IUserNotification,
@ -11,10 +8,12 @@ import type {
PaginatedUserNotification,
IMarkAllAsReadPayload,
} from "types";
// helpers
import { API_BASE_URL } from "helpers/common.helper";
class UserNotificationsServices extends APIService {
constructor() {
super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
super(API_BASE_URL);
}
async getUserNotifications(

View File

@ -1,18 +1,16 @@
import { API_BASE_URL } from "helpers/common.helper";
// services
import APIService from "services/api.service";
import trackEventServices from "services/track-event.service";
// types
import { IPage, IPageBlock, RecentPagesResponse, IIssue, ICurrentUserResponse } from "types";
const { NEXT_PUBLIC_API_BASE_URL } = process.env;
const trackEvent =
process.env.NEXT_PUBLIC_TRACK_EVENTS === "true" || process.env.NEXT_PUBLIC_TRACK_EVENTS === "1";
class PageServices extends APIService {
constructor() {
super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
super(API_BASE_URL);
}
async createPage(

View File

@ -1,3 +1,4 @@
import { API_BASE_URL } from "helpers/common.helper";
// services
import APIService from "services/api.service";
import trackEventServices from "services/track-event.service";
@ -5,14 +6,12 @@ import trackEventServices from "services/track-event.service";
import { ICurrentUserResponse } from "types";
import { IProjectPublishSettings } from "store/project-publish";
const { NEXT_PUBLIC_API_BASE_URL } = process.env;
const trackEvent =
process.env.NEXT_PUBLIC_TRACK_EVENTS === "true" || process.env.NEXT_PUBLIC_TRACK_EVENTS === "1";
class ProjectServices extends APIService {
constructor() {
super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
super(API_BASE_URL);
}
async getProjectSettingsAsync(

View File

@ -1,7 +1,7 @@
import { API_BASE_URL } from "helpers/common.helper";
// services
import APIService from "services/api.service";
import trackEventServices from "services/track-event.service";
// types
import type {
GithubRepositoriesResponse,
@ -16,14 +16,12 @@ import type {
TProjectIssuesSearchParams,
} from "types";
const { NEXT_PUBLIC_API_BASE_URL } = process.env;
const trackEvent =
process.env.NEXT_PUBLIC_TRACK_EVENTS === "true" || process.env.NEXT_PUBLIC_TRACK_EVENTS === "1";
export class ProjectServices extends APIService {
constructor() {
super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
super(API_BASE_URL);
}
async createProject(

View File

@ -1,7 +1,7 @@
import { API_BASE_URL } from "helpers/common.helper";
// services
import APIService from "services/api.service";
import trackEventServices from "services/track-event.service";
// types
import type {
ICurrentUserResponse,
@ -11,14 +11,12 @@ import type {
IssueCommentReactionForm,
} from "types";
const { NEXT_PUBLIC_API_BASE_URL } = process.env;
const trackEvent =
process.env.NEXT_PUBLIC_TRACK_EVENTS === "true" || process.env.NEXT_PUBLIC_TRACK_EVENTS === "1";
class ReactionService extends APIService {
constructor() {
super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
super(API_BASE_URL);
}
async createIssueReaction(

View File

@ -1,8 +1,8 @@
// services
import APIService from "services/api.service";
import trackEventServices from "services/track-event.service";
const { NEXT_PUBLIC_API_BASE_URL } = process.env;
// helpers
import { API_BASE_URL } from "helpers/common.helper";
const trackEvent =
process.env.NEXT_PUBLIC_TRACK_EVENTS === "true" || process.env.NEXT_PUBLIC_TRACK_EVENTS === "1";
@ -12,7 +12,7 @@ import type { ICurrentUserResponse, IState, IStateResponse } from "types";
class ProjectStateServices extends APIService {
constructor() {
super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
super(API_BASE_URL);
}
async createState(

View File

@ -12,14 +12,14 @@ import type {
IUserWorkspaceDashboard,
} from "types";
const { NEXT_PUBLIC_API_BASE_URL } = process.env;
import { API_BASE_URL } from "helpers/common.helper";
const trackEvent =
process.env.NEXT_PUBLIC_TRACK_EVENTS === "true" || process.env.NEXT_PUBLIC_TRACK_EVENTS === "1";
class UserService extends APIService {
constructor() {
super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
super(API_BASE_URL);
}
currentUserConfig() {

View File

@ -6,6 +6,8 @@ import { ICurrentUserResponse } from "types";
// types
import { IView } from "types/views";
import { API_BASE_URL } from "helpers/common.helper";
const { NEXT_PUBLIC_API_BASE_URL } = process.env;
const trackEvent =
@ -13,7 +15,7 @@ const trackEvent =
class ViewServices extends APIService {
constructor() {
super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
super(API_BASE_URL);
}
async createView(

View File

@ -1,9 +1,8 @@
// services
import APIService from "services/api.service";
import trackEventServices from "services/track-event.service";
const { NEXT_PUBLIC_API_BASE_URL } = process.env;
// helpers
import { API_BASE_URL } from "helpers/common.helper";
// types
import {
IWorkspace,
@ -22,7 +21,7 @@ const trackEvent =
class WorkspaceService extends APIService {
constructor() {
super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
super(API_BASE_URL);
}
async userWorkspaces(): Promise<IWorkspace[]> {