Compare commits
22 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8df67c339b | |||
| 1ea52d47a0 | |||
| 9f206331bc | |||
| b56d188a83 | |||
| 8d3853b129 | |||
| 30d6235108 | |||
| 6e461dd8c3 | |||
| 86379c51b7 | |||
| f7cc2eca36 | |||
| 63d1ad286b | |||
| 1412c1c94a | |||
| 26de35bd8d | |||
| 1986c0dfd4 | |||
| 25f3a5b2e4 | |||
| f30b16e9d8 | |||
| 93d03f82b4 | |||
| 98974fdc50 | |||
| 040563d148 | |||
| 4de64f112f | |||
| 0afb900678 | |||
| baf17a109b | |||
| 37bf465fcd |
@@ -1,33 +1,41 @@
|
||||
|
||||
name: Docker Branch Build
|
||||
name: Branch Build
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
logLevel:
|
||||
description: 'Log level'
|
||||
required: true
|
||||
default: 'warning'
|
||||
tags:
|
||||
description: 'Dev/QA Builds'
|
||||
pull_request:
|
||||
types:
|
||||
- closed
|
||||
branches:
|
||||
- master
|
||||
- release
|
||||
- qa
|
||||
- develop
|
||||
|
||||
env:
|
||||
gh_branch: ${{ github.ref_name }}
|
||||
img_tag: latest
|
||||
TARGET_BRANCH: ${{ github.event.pull_request.base.ref }}
|
||||
|
||||
jobs:
|
||||
branch_build_and_push:
|
||||
if: ${{ (github.event_name == 'pull_request' && github.event.action =='closed' && github.event.pull_request.merged == true) }}
|
||||
name: Build-Push Web/Space/API/Proxy Docker Image
|
||||
runs-on: ubuntu-20.04
|
||||
|
||||
steps:
|
||||
- name: Check out the repo
|
||||
uses: actions/checkout@v3.3.0
|
||||
|
||||
# - name: Set Target Branch Name on PR close
|
||||
# if: ${{ github.event_name == 'pull_request' && github.event.action =='closed' }}
|
||||
# run: echo "TARGET_BRANCH=${{ github.event.pull_request.base.ref }}" >> $GITHUB_ENV
|
||||
|
||||
# - name: Set Target Branch Name on other than PR close
|
||||
# if: ${{ github.event_name == 'push' }}
|
||||
# run: echo "TARGET_BRANCH=${{ github.ref_name }}" >> $GITHUB_ENV
|
||||
|
||||
- uses: ASzc/change-string-case-action@v2
|
||||
id: gh_branch_upper_lower
|
||||
with:
|
||||
string: ${{ env.gh_branch }}
|
||||
string: ${{env.TARGET_BRANCH}}
|
||||
|
||||
- uses: mad9000/actions-find-and-replace-string@2
|
||||
id: gh_branch_replace_slash
|
||||
@@ -111,7 +119,7 @@ jobs:
|
||||
env:
|
||||
DOCKER_BUILDKIT: 1
|
||||
DOCKER_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
DOCKET_PASSWORD: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
DOCKER_PASSWORD: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
branch_build_push_space:
|
||||
runs-on: ubuntu-20.04
|
||||
@@ -141,7 +149,7 @@ jobs:
|
||||
env:
|
||||
DOCKER_BUILDKIT: 1
|
||||
DOCKER_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
DOCKET_PASSWORD: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
DOCKER_PASSWORD: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
branch_build_push_backend:
|
||||
runs-on: ubuntu-20.04
|
||||
@@ -171,7 +179,7 @@ jobs:
|
||||
env:
|
||||
DOCKER_BUILDKIT: 1
|
||||
DOCKER_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
DOCKET_PASSWORD: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
DOCKER_PASSWORD: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
branch_build_push_proxy:
|
||||
runs-on: ubuntu-20.04
|
||||
@@ -202,4 +210,4 @@ jobs:
|
||||
env:
|
||||
DOCKER_BUILDKIT: 1
|
||||
DOCKER_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
DOCKET_PASSWORD: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
DOCKER_PASSWORD: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
@@ -70,3 +70,6 @@ ENABLE_MAGIC_LINK_LOGIN="0"
|
||||
# Email redirections and minio domain settings
|
||||
WEB_URL="http://localhost"
|
||||
|
||||
|
||||
# Gunicorn Workers
|
||||
GUNICORN_WORKERS=2
|
||||
|
||||
@@ -6,4 +6,4 @@ python manage.py migrate
|
||||
# Create a Default User
|
||||
python bin/user_script.py
|
||||
|
||||
exec gunicorn -w 8 -k uvicorn.workers.UvicornWorker plane.asgi:application --bind 0.0.0.0:8000 --max-requests 1200 --max-requests-jitter 1000 --access-logfile -
|
||||
exec gunicorn -w $GUNICORN_WORKERS -k uvicorn.workers.UvicornWorker plane.asgi:application --bind 0.0.0.0:8000 --max-requests 1200 --max-requests-jitter 1000 --access-logfile -
|
||||
|
||||
@@ -21,8 +21,8 @@ class ConfigurationEndpoint(BaseAPIView):
|
||||
|
||||
def get(self, request):
|
||||
data = {}
|
||||
data["google"] = os.environ.get("GOOGLE_CLIENT_ID", None)
|
||||
data["github"] = os.environ.get("GITHUB_CLIENT_ID", None)
|
||||
data["google_client_id"] = os.environ.get("GOOGLE_CLIENT_ID", None)
|
||||
data["github_client_id"] = os.environ.get("GITHUB_CLIENT_ID", None)
|
||||
data["github_app_name"] = os.environ.get("GITHUB_APP_NAME", None)
|
||||
data["magic_login"] = (
|
||||
bool(settings.EMAIL_HOST_USER) and bool(settings.EMAIL_HOST_PASSWORD)
|
||||
@@ -30,5 +30,5 @@ class ConfigurationEndpoint(BaseAPIView):
|
||||
data["email_password_login"] = (
|
||||
os.environ.get("ENABLE_EMAIL_PASSWORD", "0") == "1"
|
||||
)
|
||||
data["slack"] = os.environ.get("SLACK_CLIENT_ID", None)
|
||||
data["slack_client_id"] = os.environ.get("SLACK_CLIENT_ID", None)
|
||||
return Response(data, status=status.HTTP_200_OK)
|
||||
|
||||
@@ -479,13 +479,13 @@ class CycleViewSet(BaseViewSet):
|
||||
)
|
||||
)
|
||||
cycle = Cycle.objects.get(workspace__slug=slug, project_id=project_id, pk=pk)
|
||||
# Delete the cycle
|
||||
cycle.delete()
|
||||
|
||||
issue_activity.delay(
|
||||
type="cycle.activity.deleted",
|
||||
requested_data=json.dumps(
|
||||
{
|
||||
"cycle_id": str(pk),
|
||||
"cycle_name": str(cycle.name),
|
||||
"issues": [str(issue_id) for issue_id in cycle_issues],
|
||||
}
|
||||
),
|
||||
@@ -495,6 +495,8 @@ class CycleViewSet(BaseViewSet):
|
||||
current_instance=None,
|
||||
epoch=int(timezone.now().timestamp()),
|
||||
)
|
||||
# Delete the cycle
|
||||
cycle.delete()
|
||||
return Response(status=status.HTTP_204_NO_CONTENT)
|
||||
|
||||
|
||||
@@ -511,12 +513,6 @@ class CycleIssueViewSet(BaseViewSet):
|
||||
"issue__assignees__id",
|
||||
]
|
||||
|
||||
def perform_create(self, serializer):
|
||||
serializer.save(
|
||||
project_id=self.kwargs.get("project_id"),
|
||||
cycle_id=self.kwargs.get("cycle_id"),
|
||||
)
|
||||
|
||||
def get_queryset(self):
|
||||
return self.filter_queryset(
|
||||
super()
|
||||
@@ -669,7 +665,7 @@ class CycleIssueViewSet(BaseViewSet):
|
||||
type="cycle.activity.created",
|
||||
requested_data=json.dumps({"cycles_list": issues}),
|
||||
actor_id=str(self.request.user.id),
|
||||
issue_id=str(self.kwargs.get("pk", None)),
|
||||
issue_id=None,
|
||||
project_id=str(self.kwargs.get("project_id", None)),
|
||||
current_instance=json.dumps(
|
||||
{
|
||||
|
||||
@@ -7,7 +7,7 @@ from django.contrib.auth.hashers import make_password
|
||||
# Third party imports
|
||||
from rest_framework.response import Response
|
||||
from rest_framework import status
|
||||
from sentry_sdk import capture_exception, capture_message
|
||||
from sentry_sdk import capture_exception
|
||||
|
||||
# Module imports
|
||||
from plane.api.views import BaseViewSet
|
||||
@@ -109,7 +109,6 @@ class WorkspaceIntegrationViewSet(BaseViewSet):
|
||||
access_token = metadata.get("access_token", False)
|
||||
team_id = metadata.get("team", {}).get("id", False)
|
||||
if not metadata or not access_token or not team_id:
|
||||
capture_message(slack_response)
|
||||
return Response(
|
||||
{"error": "Slack could not be installed. Please try again later"},
|
||||
status=status.HTTP_400_BAD_REQUEST,
|
||||
@@ -134,7 +133,6 @@ class WorkspaceIntegrationViewSet(BaseViewSet):
|
||||
user=bot_user,
|
||||
user_type=1, # bot user
|
||||
workspace=workspace,
|
||||
description="",
|
||||
)
|
||||
|
||||
workspace_integration = WorkspaceIntegration.objects.create(
|
||||
|
||||
@@ -59,6 +59,7 @@ class SlackProjectSyncViewSet(BaseViewSet):
|
||||
team_id=slack_response.get("team", {}).get("id"),
|
||||
team_name=slack_response.get("team", {}).get("name"),
|
||||
workspace_integration=workspace_integration,
|
||||
project_id=project_id,
|
||||
)
|
||||
_ = ProjectMember.objects.get_or_create(
|
||||
member=workspace_integration.actor, role=20, project_id=project_id
|
||||
|
||||
@@ -2230,7 +2230,7 @@ class IssueDraftViewSet(BaseViewSet):
|
||||
def destroy(self, request, slug, project_id, pk=None):
|
||||
issue = Issue.objects.get(workspace__slug=slug, project_id=project_id, pk=pk)
|
||||
current_instance = json.dumps(
|
||||
IssueSerializer(current_instance).data, cls=DjangoJSONEncoder
|
||||
IssueSerializer(issue).data, cls=DjangoJSONEncoder
|
||||
)
|
||||
issue.delete()
|
||||
issue_activity.delay(
|
||||
|
||||
@@ -266,12 +266,12 @@ class ModuleViewSet(BaseViewSet):
|
||||
module_issues = list(
|
||||
ModuleIssue.objects.filter(module_id=pk).values_list("issue", flat=True)
|
||||
)
|
||||
module.delete()
|
||||
issue_activity.delay(
|
||||
type="module.activity.deleted",
|
||||
requested_data=json.dumps(
|
||||
{
|
||||
"module_id": str(pk),
|
||||
"module_name": str(module.name),
|
||||
"issues": [str(issue_id) for issue_id in module_issues],
|
||||
}
|
||||
),
|
||||
@@ -281,6 +281,7 @@ class ModuleViewSet(BaseViewSet):
|
||||
current_instance=None,
|
||||
epoch=int(timezone.now().timestamp()),
|
||||
)
|
||||
module.delete()
|
||||
return Response(status=status.HTTP_204_NO_CONTENT)
|
||||
|
||||
|
||||
@@ -297,12 +298,6 @@ class ModuleIssueViewSet(BaseViewSet):
|
||||
ProjectEntityPermission,
|
||||
]
|
||||
|
||||
def perform_create(self, serializer):
|
||||
serializer.save(
|
||||
project_id=self.kwargs.get("project_id"),
|
||||
module_id=self.kwargs.get("module_id"),
|
||||
)
|
||||
|
||||
def get_queryset(self):
|
||||
return self.filter_queryset(
|
||||
super()
|
||||
@@ -446,7 +441,7 @@ class ModuleIssueViewSet(BaseViewSet):
|
||||
type="module.activity.created",
|
||||
requested_data=json.dumps({"modules_list": issues}),
|
||||
actor_id=str(self.request.user.id),
|
||||
issue_id=str(self.kwargs.get("pk", None)),
|
||||
issue_id=None,
|
||||
project_id=str(self.kwargs.get("project_id", None)),
|
||||
current_instance=json.dumps(
|
||||
{
|
||||
|
||||
@@ -691,6 +691,10 @@ def create_cycle_issue_activity(
|
||||
new_cycle = Cycle.objects.filter(
|
||||
pk=updated_record.get("new_cycle_id", None)
|
||||
).first()
|
||||
issue = Issue.objects.filter(pk=updated_record.get("issue_id")).first()
|
||||
if issue:
|
||||
issue.updated_at = timezone.now()
|
||||
issue.save(update_fields=["updated_at"])
|
||||
|
||||
issue_activities.append(
|
||||
IssueActivity(
|
||||
@@ -713,6 +717,10 @@ def create_cycle_issue_activity(
|
||||
cycle = Cycle.objects.filter(
|
||||
pk=created_record.get("fields").get("cycle")
|
||||
).first()
|
||||
issue = Issue.objects.filter(pk=created_record.get("fields").get("issue")).first()
|
||||
if issue:
|
||||
issue.updated_at = timezone.now()
|
||||
issue.save(update_fields=["updated_at"])
|
||||
|
||||
issue_activities.append(
|
||||
IssueActivity(
|
||||
@@ -747,22 +755,27 @@ def delete_cycle_issue_activity(
|
||||
)
|
||||
|
||||
cycle_id = requested_data.get("cycle_id", "")
|
||||
cycle_name = requested_data.get("cycle_name", "")
|
||||
cycle = Cycle.objects.filter(pk=cycle_id).first()
|
||||
issues = requested_data.get("issues")
|
||||
|
||||
for issue in issues:
|
||||
current_issue = Issue.objects.filter(pk=issue).first()
|
||||
if issue:
|
||||
current_issue.updated_at = timezone.now()
|
||||
current_issue.save(update_fields=["updated_at"])
|
||||
issue_activities.append(
|
||||
IssueActivity(
|
||||
issue_id=issue,
|
||||
actor_id=actor_id,
|
||||
verb="deleted",
|
||||
old_value=cycle.name if cycle is not None else "",
|
||||
old_value=cycle.name if cycle is not None else cycle_name,
|
||||
new_value="",
|
||||
field="cycles",
|
||||
project_id=project_id,
|
||||
workspace_id=workspace_id,
|
||||
comment=f"removed this issue from {cycle.name if cycle is not None else None}",
|
||||
old_identifier=cycle.id if cycle is not None else None,
|
||||
comment=f"removed this issue from {cycle.name if cycle is not None else cycle_name}",
|
||||
old_identifier=cycle_id if cycle_id is not None else None,
|
||||
epoch=epoch,
|
||||
)
|
||||
)
|
||||
@@ -794,6 +807,10 @@ def create_module_issue_activity(
|
||||
new_module = Module.objects.filter(
|
||||
pk=updated_record.get("new_module_id", None)
|
||||
).first()
|
||||
issue = Issue.objects.filter(pk=updated_record.get("issue_id")).first()
|
||||
if issue:
|
||||
issue.updated_at = timezone.now()
|
||||
issue.save(update_fields=["updated_at"])
|
||||
|
||||
issue_activities.append(
|
||||
IssueActivity(
|
||||
@@ -816,6 +833,10 @@ def create_module_issue_activity(
|
||||
module = Module.objects.filter(
|
||||
pk=created_record.get("fields").get("module")
|
||||
).first()
|
||||
issue = Issue.objects.filter(pk=created_record.get("fields").get("issue")).first()
|
||||
if issue:
|
||||
issue.updated_at = timezone.now()
|
||||
issue.save(update_fields=["updated_at"])
|
||||
issue_activities.append(
|
||||
IssueActivity(
|
||||
issue_id=created_record.get("fields").get("issue"),
|
||||
@@ -849,22 +870,27 @@ def delete_module_issue_activity(
|
||||
)
|
||||
|
||||
module_id = requested_data.get("module_id", "")
|
||||
module_name = requested_data.get("module_name", "")
|
||||
module = Module.objects.filter(pk=module_id).first()
|
||||
issues = requested_data.get("issues")
|
||||
|
||||
for issue in issues:
|
||||
current_issue = Issue.objects.filter(pk=issue).first()
|
||||
if issue:
|
||||
current_issue.updated_at = timezone.now()
|
||||
current_issue.save(update_fields=["updated_at"])
|
||||
issue_activities.append(
|
||||
IssueActivity(
|
||||
issue_id=issue,
|
||||
actor_id=actor_id,
|
||||
verb="deleted",
|
||||
old_value=module.name if module is not None else "",
|
||||
old_value=module.name if module is not None else module_name,
|
||||
new_value="",
|
||||
field="modules",
|
||||
project_id=project_id,
|
||||
workspace_id=workspace_id,
|
||||
comment=f"removed this issue from ",
|
||||
old_identifier=module.id if module is not None else None,
|
||||
comment=f"removed this issue from {module.name if module is not None else module_name}",
|
||||
old_identifier=module_id if module_id is not None else None,
|
||||
epoch=epoch,
|
||||
)
|
||||
)
|
||||
@@ -1452,15 +1478,16 @@ def issue_activity(
|
||||
issue_activities = []
|
||||
|
||||
project = Project.objects.get(pk=project_id)
|
||||
issue = Issue.objects.filter(pk=issue_id).first()
|
||||
workspace_id = project.workspace_id
|
||||
|
||||
if issue is not None:
|
||||
try:
|
||||
issue.updated_at = timezone.now()
|
||||
issue.save(update_fields=["updated_at"])
|
||||
except Exception as e:
|
||||
pass
|
||||
if issue_id is not None:
|
||||
issue = Issue.objects.filter(pk=issue_id).first()
|
||||
if issue:
|
||||
try:
|
||||
issue.updated_at = timezone.now()
|
||||
issue.save(update_fields=["updated_at"])
|
||||
except Exception as e:
|
||||
pass
|
||||
|
||||
ACTIVITY_MAPPER = {
|
||||
"issue.activity.created": create_issue_activity,
|
||||
|
||||
@@ -10,6 +10,8 @@ x-app-env : &app-env
|
||||
- SENTRY_DSN=${SENTRY_DSN:-""}
|
||||
- GITHUB_CLIENT_SECRET=${GITHUB_CLIENT_SECRET:-""}
|
||||
- DOCKERIZED=${DOCKERIZED:-1}
|
||||
# Gunicorn Workers
|
||||
- GUNICORN_WORKERS=${GUNICORN_WORKERS:-2}
|
||||
#DB SETTINGS
|
||||
- PGHOST=${PGHOST:-plane-db}
|
||||
- PGDATABASE=${PGDATABASE:-plane}
|
||||
|
||||
@@ -61,3 +61,5 @@ MINIO_ROOT_PASSWORD="secret-key"
|
||||
BUCKET_NAME=uploads
|
||||
FILE_SIZE_LIMIT=5242880
|
||||
|
||||
# Gunicorn Workers
|
||||
GUNICORN_WORKERS=2
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// @ts-nocheck
|
||||
import { NodeViewWrapper } from "@tiptap/react";
|
||||
import { cn } from "../../lib/utils";
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { IMentionHighlight } from "../../types/mention-suggestion";
|
||||
|
||||
// eslint-disable-next-line import/no-anonymous-default-export
|
||||
|
||||
@@ -15,7 +15,10 @@
|
||||
"module": "esnext",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"jsx": "preserve"
|
||||
"jsx": "react",
|
||||
"paths": {
|
||||
"react": [ "./node_modules/@types/react" ]
|
||||
}
|
||||
},
|
||||
"include": ["src", "next-env.d.ts"],
|
||||
"exclude": ["node_modules"]
|
||||
|
||||
@@ -4,9 +4,13 @@
|
||||
"extends": "./base.json",
|
||||
"compilerOptions": {
|
||||
"jsx": "react-jsx",
|
||||
"strict": true,
|
||||
"lib": ["ES2015", "DOM"],
|
||||
"module": "ESNext",
|
||||
"target": "es6",
|
||||
"sourceMap": true
|
||||
"sourceMap": true,
|
||||
"paths": {
|
||||
"react": [ "./node_modules/@types/react" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,9 +30,6 @@
|
||||
"tsup": "^5.10.1",
|
||||
"typescript": "4.7.4"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"dependencies": {
|
||||
"@blueprintjs/core": "^4.16.3",
|
||||
"@blueprintjs/popover2": "^1.13.3",
|
||||
|
||||
@@ -42,6 +42,10 @@ type Props = {
|
||||
* The source of the avatar image
|
||||
*/
|
||||
src?: string;
|
||||
/**
|
||||
* The custom CSS class name to apply to the component
|
||||
*/
|
||||
className?: string;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -94,7 +98,7 @@ export const getBorderRadius = (shape: "circle" | "square") => {
|
||||
case "circle":
|
||||
return "rounded-full";
|
||||
case "square":
|
||||
return "rounded-md";
|
||||
return "rounded";
|
||||
default:
|
||||
return "rounded-full";
|
||||
}
|
||||
@@ -119,6 +123,7 @@ export const Avatar: React.FC<Props> = (props) => {
|
||||
size = "md",
|
||||
shape = "circle",
|
||||
src,
|
||||
className = ""
|
||||
} = props;
|
||||
|
||||
// get size details based on the size prop
|
||||
@@ -145,14 +150,14 @@ export const Avatar: React.FC<Props> = (props) => {
|
||||
{src ? (
|
||||
<img
|
||||
src={src}
|
||||
className={`h-full w-full ${getBorderRadius(shape)}`}
|
||||
className={`h-full w-full ${getBorderRadius(shape)} ${className}`}
|
||||
alt={name}
|
||||
/>
|
||||
) : (
|
||||
<div
|
||||
className={`${
|
||||
sizeInfo.fontSize
|
||||
} grid place-items-center h-full w-full ${getBorderRadius(shape)}`}
|
||||
} grid place-items-center h-full w-full ${getBorderRadius(shape)} ${className}`}
|
||||
style={{
|
||||
backgroundColor:
|
||||
fallbackBackgroundColor ?? "rgba(var(--color-primary-500))",
|
||||
|
||||
@@ -1,10 +1,23 @@
|
||||
import * as React from "react";
|
||||
|
||||
export const Spinner: React.FC = () => (
|
||||
export interface ISpinner extends React.SVGAttributes<SVGElement> {
|
||||
height?: string;
|
||||
width?: string;
|
||||
className?: string | undefined;
|
||||
}
|
||||
|
||||
export const Spinner: React.FC<ISpinner> = ({
|
||||
height = "32px",
|
||||
width = "32px",
|
||||
className = "",
|
||||
...rest
|
||||
}) => (
|
||||
<div role="status">
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
className="mr-2 h-8 w-8 animate-spin fill-blue-600 text-custom-text-200"
|
||||
height={height}
|
||||
width={width}
|
||||
className={`mr-2 animate-spin fill-blue-600 text-custom-text-200 ${className}`}
|
||||
viewBox="0 0 100 101"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { useState } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
import Link from "next/link";
|
||||
import { useForm } from "react-hook-form";
|
||||
// components
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useEffect, useState, FC } from "react";
|
||||
import Link from "next/link";
|
||||
import Image from "next/image";
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
// next-themes
|
||||
import { useTheme } from "next-themes";
|
||||
// images
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useEffect, Fragment } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
import { Listbox, Transition } from "@headlessui/react";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from "react";
|
||||
import useSWR from "swr";
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
// mobx
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
@@ -116,7 +116,9 @@ export const SignInView = observer(() => {
|
||||
)}
|
||||
|
||||
<div className="flex flex-col items-center justify-center gap-4 pt-7 sm:w-[360px] mx-auto overflow-hidden">
|
||||
{data?.google && <GoogleLoginButton clientId={data.google} handleSignIn={handleGoogleSignIn} />}
|
||||
{data?.google_client_id && (
|
||||
<GoogleLoginButton clientId={data.google_client_id} handleSignIn={handleGoogleSignIn} />
|
||||
)}
|
||||
</div>
|
||||
|
||||
<p className="pt-16 text-custom-text-200 text-sm text-center">
|
||||
|
||||
@@ -11,7 +11,7 @@ import { IssueBlockDueDate } from "components/issues/board-views/block-due-date"
|
||||
// interfaces
|
||||
import { IIssue } from "types/issue";
|
||||
import { RootStore } from "store/root";
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
export const IssueListBlock = observer(({ issue }: { issue: IIssue }) => {
|
||||
const { project: projectStore, issueDetails: issueDetailStore }: RootStore = useMobxStore();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { FC } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { observer } from "mobx-react-lite";
|
||||
// components
|
||||
import { IssueBlockPriority } from "components/issues/board-views/block-priority";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
// mobx react lite
|
||||
import { observer } from "mobx-react-lite";
|
||||
// components
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
// mobx react lite
|
||||
import { observer } from "mobx-react-lite";
|
||||
// mobx hook
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
// mobx react lite
|
||||
import { observer } from "mobx-react-lite";
|
||||
// components
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
// mobx react lite
|
||||
import { observer } from "mobx-react-lite";
|
||||
// mobx hook
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
// mobx react lite
|
||||
import { observer } from "mobx-react-lite";
|
||||
// mobx hook
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
// mobx react lite
|
||||
import { observer } from "mobx-react-lite";
|
||||
// mobx hook
|
||||
@@ -29,7 +29,7 @@ export const RenderIssueState = observer(({ state }: { state: IIssueState }) =>
|
||||
return (
|
||||
<div className={`inline-flex items-center gap-x-1 rounded-full px-2 py-0.5 ${stateGroup.className || ``}`}>
|
||||
<div className="flex-shrink-0 w-3 h-3 flex justify-center items-center overflow-hidden rounded-full">
|
||||
<stateGroup.icon />
|
||||
{/* <stateGroup.icon /> */}
|
||||
</div>
|
||||
<div className="text-xs font-medium whitespace-nowrap">{state?.name}</div>
|
||||
<div
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
// mobx react lite
|
||||
import { observer } from "mobx-react-lite";
|
||||
// components
|
||||
|
||||
@@ -2,7 +2,7 @@ import { useEffect } from "react";
|
||||
|
||||
import Link from "next/link";
|
||||
import Image from "next/image";
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
// mobx
|
||||
import { observer } from "mobx-react-lite";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { observer } from "mobx-react-lite";
|
||||
// constants
|
||||
import { issueViews } from "constants/data";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { ChevronDown } from "lucide-react";
|
||||
// mobx store
|
||||
@@ -77,7 +77,7 @@ export const NavbarIssueFilter = observer(() => {
|
||||
return {
|
||||
display: (
|
||||
<span className="capitalize flex items-center gap-x-2">
|
||||
{stateGroup && <stateGroup.icon />}
|
||||
{/* {stateGroup && <stateGroup.icon />} */}
|
||||
{state.name}
|
||||
</span>
|
||||
),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { useRef } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { useForm, Controller } from "react-hook-form";
|
||||
// lib
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from "react";
|
||||
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
// mobx
|
||||
import { observer } from "mobx-react-lite";
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from "react";
|
||||
|
||||
import Link from "next/link";
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
// mobx
|
||||
import { observer } from "mobx-react-lite";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useEffect } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { observer } from "mobx-react-lite";
|
||||
// lib
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
// hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
// ui
|
||||
import { StateGroupIcon } from "@plane/ui";
|
||||
// icons
|
||||
import { Icon } from "components/ui";
|
||||
// helpers
|
||||
@@ -63,7 +65,7 @@ export const PeekOverviewIssueProperties: React.FC<Props> = ({ issueDetails, mod
|
||||
{stateGroup && (
|
||||
<div className="inline-flex bg-custom-background-80 text-sm rounded px-2.5 py-0.5">
|
||||
<div className="flex items-center gap-1.5 text-left text-custom-text-100">
|
||||
<stateGroup.icon />
|
||||
<StateGroupIcon stateGroup={state.group} color={state.color} />
|
||||
{addSpaceIfCamelCase(state?.name ?? "")}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useState, useEffect } from "react";
|
||||
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
// mobx
|
||||
import { observer } from "mobx-react-lite";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
// mobx
|
||||
import { observer } from "mobx-react-lite";
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useEffect } from "react";
|
||||
|
||||
import Image from "next/image";
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
// mobx
|
||||
import { observer } from "mobx-react-lite";
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
// interfaces
|
||||
import {
|
||||
IIssueBoardViews,
|
||||
// priority
|
||||
TIssuePriorityKey,
|
||||
// state groups
|
||||
@@ -8,14 +7,6 @@ import {
|
||||
IIssuePriorityFilters,
|
||||
IIssueGroup,
|
||||
} from "types/issue";
|
||||
// icons
|
||||
import {
|
||||
BacklogStateIcon,
|
||||
UnstartedStateIcon,
|
||||
StartedStateIcon,
|
||||
CompletedStateIcon,
|
||||
CancelledStateIcon,
|
||||
} from "components/icons";
|
||||
|
||||
// all issue views
|
||||
export const issueViews: any = {
|
||||
@@ -92,35 +83,30 @@ export const issueGroups: IIssueGroup[] = [
|
||||
title: "Backlog",
|
||||
color: "#d9d9d9",
|
||||
className: `text-[#d9d9d9] bg-[#d9d9d9]/10`,
|
||||
icon: BacklogStateIcon,
|
||||
},
|
||||
{
|
||||
key: "unstarted",
|
||||
title: "Unstarted",
|
||||
color: "#3f76ff",
|
||||
className: `text-[#3f76ff] bg-[#3f76ff]/10`,
|
||||
icon: UnstartedStateIcon,
|
||||
},
|
||||
{
|
||||
key: "started",
|
||||
title: "Started",
|
||||
color: "#f59e0b",
|
||||
className: `text-[#f59e0b] bg-[#f59e0b]/10`,
|
||||
icon: StartedStateIcon,
|
||||
},
|
||||
{
|
||||
key: "completed",
|
||||
title: "Completed",
|
||||
color: "#16a34a",
|
||||
className: `text-[#16a34a] bg-[#16a34a]/10`,
|
||||
icon: CompletedStateIcon,
|
||||
},
|
||||
{
|
||||
key: "cancelled",
|
||||
title: "Cancelled",
|
||||
color: "#dc2626",
|
||||
className: `text-[#dc2626] bg-[#dc2626]/10`,
|
||||
icon: CancelledStateIcon,
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import { useEffect } from "react";
|
||||
// next imports
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
// js cookie
|
||||
import Cookie from "js-cookie";
|
||||
// mobx store
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import Head from "next/head";
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
import useSWR from "swr";
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import { useEffect } from "react";
|
||||
|
||||
// next
|
||||
import { NextPage } from "next";
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
const Index: NextPage = () => {
|
||||
const router = useRouter();
|
||||
|
||||
@@ -3,12 +3,13 @@ import APIService from "services/api.service";
|
||||
// helper
|
||||
import { API_BASE_URL } from "helpers/common.helper";
|
||||
|
||||
export interface IEnvConfig {
|
||||
github: string;
|
||||
google: string;
|
||||
github_app_name: string | null;
|
||||
export interface IAppConfig {
|
||||
email_password_login: boolean;
|
||||
google_client_id: string | null;
|
||||
github_app_name: string | null;
|
||||
github_client_id: string | null;
|
||||
magic_login: boolean;
|
||||
slack_client_id: string | null;
|
||||
}
|
||||
|
||||
export class AppConfigService extends APIService {
|
||||
@@ -16,7 +17,7 @@ export class AppConfigService extends APIService {
|
||||
super(API_BASE_URL);
|
||||
}
|
||||
|
||||
async envConfig(): Promise<IEnvConfig> {
|
||||
async envConfig(): Promise<IAppConfig> {
|
||||
return this.get("/api/configs/", {
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
|
||||
@@ -24,7 +24,6 @@ export interface IIssueGroup {
|
||||
title: TIssueGroupTitle;
|
||||
color: string;
|
||||
className: string;
|
||||
icon: React.FC;
|
||||
}
|
||||
|
||||
export interface IIssue {
|
||||
@@ -40,7 +39,12 @@ export interface IIssue {
|
||||
sequence_id: number;
|
||||
start_date: any;
|
||||
state: string;
|
||||
state_detail: any;
|
||||
state_detail: {
|
||||
id: string;
|
||||
name: string;
|
||||
group: TIssueGroupKey;
|
||||
color: string;
|
||||
};
|
||||
target_date: any;
|
||||
votes: IVote[];
|
||||
}
|
||||
|
||||
+1
-3
@@ -5,7 +5,6 @@
|
||||
"NEXT_PUBLIC_DEPLOY_URL",
|
||||
"NEXT_PUBLIC_SENTRY_DSN",
|
||||
"NEXT_PUBLIC_SENTRY_ENVIRONMENT",
|
||||
"NEXT_PUBLIC_GITHUB_APP_NAME",
|
||||
"NEXT_PUBLIC_ENABLE_SENTRY",
|
||||
"NEXT_PUBLIC_ENABLE_OAUTH",
|
||||
"NEXT_PUBLIC_TRACK_EVENTS",
|
||||
@@ -22,8 +21,7 @@
|
||||
"SLACK_CLIENT_SECRET",
|
||||
"JITSU_TRACKER_ACCESS_KEY",
|
||||
"JITSU_TRACKER_HOST",
|
||||
"UNSPLASH_ACCESS_KEY",
|
||||
"NEXT_PUBLIC_SLACK_CLIENT_ID"
|
||||
"UNSPLASH_ACCESS_KEY"
|
||||
],
|
||||
"pipeline": {
|
||||
"build": {
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
"use client"
|
||||
import { ReactElement } from "react";
|
||||
import Head from "next/head";
|
||||
import dynamic from "next/dynamic";
|
||||
import Router from "next/navigation";
|
||||
import { AppProps } from "next/app";
|
||||
import { ThemeProvider } from "next-themes";
|
||||
import NProgress from "nprogress";
|
||||
// styles
|
||||
import "styles/globals.css";
|
||||
import "styles/editor.css";
|
||||
import "styles/table.css";
|
||||
import "styles/command-pallette.css";
|
||||
import "styles/nprogress.css";
|
||||
import "styles/react-datepicker.css";
|
||||
// contexts
|
||||
import { ToastContextProvider } from "contexts/toast.context";
|
||||
// constants
|
||||
import { THEMES } from "constants/themes";
|
||||
import { SITE_TITLE } from "constants/seo-variables";
|
||||
// mobx store provider
|
||||
import { MobxStoreProvider } from "lib/mobx/store-provider";
|
||||
import MobxStoreInit from "lib/mobx/store-init";
|
||||
// types
|
||||
import { NextPageWithLayout } from "types/app";
|
||||
|
||||
const CrispWithNoSSR = dynamic(() => import("constants/crisp"), { ssr: false });
|
||||
|
||||
// // nprogress
|
||||
// NProgress.configure({ showSpinner: false });
|
||||
// Router.events.on("routeChangeStart", NProgress.start);
|
||||
// Router.events.on("routeChangeError", NProgress.done);
|
||||
// Router.events.on("routeChangeComplete", NProgress.done);
|
||||
|
||||
export default function AppLayout({ children }:any) {
|
||||
// Use the layout defined at the page level, if available
|
||||
// const getLayout = Component.getLayout ?? ((page: ReactElement) => page);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>{SITE_TITLE}</title>
|
||||
</Head>
|
||||
<MobxStoreProvider>
|
||||
<ThemeProvider themes={THEMES} defaultTheme="system">
|
||||
<ToastContextProvider>
|
||||
<CrispWithNoSSR />
|
||||
<MobxStoreInit />
|
||||
{children}
|
||||
</ToastContextProvider>
|
||||
</ThemeProvider>
|
||||
</MobxStoreProvider>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
"use client"
|
||||
import { ReactElement } from "react";
|
||||
// layouts
|
||||
import DefaultLayout from "layouts/default-layout";
|
||||
// components
|
||||
import { SignInView } from "components/page-views";
|
||||
// type
|
||||
import { NextPageWithLayout } from "types/app";
|
||||
|
||||
const HomePage: NextPageWithLayout = () => <SignInView />;
|
||||
|
||||
// HomePage.getLayout = function getLayout(page: ReactElement) {
|
||||
// return <DefaultLayout>{page}</DefaultLayout>;
|
||||
// };
|
||||
|
||||
export default HomePage;
|
||||
@@ -1,5 +1,5 @@
|
||||
import { FC } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useForm, Controller } from "react-hook-form";
|
||||
// ui
|
||||
import { Input, Button } from "@plane/ui";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from "react";
|
||||
import { useForm, Controller } from "react-hook-form";
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
// ui
|
||||
import { Input, Button } from "@plane/ui";
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useEffect, useState, FC } from "react";
|
||||
import Link from "next/link";
|
||||
import Image from "next/image";
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useTheme } from "next-themes";
|
||||
// images
|
||||
import githubBlackImage from "/public/logos/github-black.png";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
import useSWR from "swr";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { observer } from "mobx-react-lite";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { mutate } from "swr";
|
||||
|
||||
// components
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { Control, Controller, UseFormSetValue } from "react-hook-form";
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
// ui
|
||||
import { CustomSelect } from "@plane/ui";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
// ui
|
||||
import { CustomSelect } from "@plane/ui";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { observer } from "mobx-react-lite";
|
||||
|
||||
// mobx store
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useEffect } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { mutate } from "swr";
|
||||
// services
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from "react";
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { Tab } from "@headlessui/react";
|
||||
// mobx store
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
import useSWR from "swr";
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import React from "react";
|
||||
// next
|
||||
import Link from "next/link";
|
||||
import Image from "next/image";
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
// layouts
|
||||
import DefaultLayout from "layouts/default-layout";
|
||||
// hooks
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useState } from "react";
|
||||
import Image from "next/image";
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
// mobx store
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
// ui
|
||||
|
||||
@@ -29,7 +29,7 @@ export const AutoArchiveAutomation: React.FC<Props> = ({ projectDetails, handleC
|
||||
handleClose={() => setmonthModal(false)}
|
||||
handleChange={handleChange}
|
||||
/>
|
||||
<div className="flex flex-col gap-4 border-b border-custom-border-200 px-4 py-6">
|
||||
<div className="flex flex-col gap-4 border-b border-custom-border-100 px-4 py-6">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-start gap-3">
|
||||
<div className="flex items-center justify-center p-3 rounded bg-custom-background-90">
|
||||
@@ -54,7 +54,7 @@ export const AutoArchiveAutomation: React.FC<Props> = ({ projectDetails, handleC
|
||||
|
||||
{projectDetails?.archive_in !== 0 && (
|
||||
<div className="ml-12">
|
||||
<div className="flex items-center justify-between rounded px-5 py-4 bg-custom-background-90 border border-custom-border-200 gap-2 w-full">
|
||||
<div className="flex items-center justify-between rounded px-5 py-4 bg-custom-background-90 border-[0.5px] border-custom-border-200 gap-2 w-full">
|
||||
<div className="w-1/2 text-sm font-medium">Auto-archive issues that are closed for</div>
|
||||
<div className="w-1/2">
|
||||
<CustomSelect
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { useState } from "react";
|
||||
import useSWR from "swr";
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
// component
|
||||
import { SelectMonthModal } from "components/automation";
|
||||
import { CustomSelect, CustomSearchSelect, ToggleSwitch, StateGroupIcon, DoubleCircleIcon } from "@plane/ui";
|
||||
@@ -73,7 +73,7 @@ export const AutoCloseAutomation: React.FC<Props> = ({ projectDetails, handleCha
|
||||
handleChange={handleChange}
|
||||
/>
|
||||
|
||||
<div className="flex flex-col gap-4 border-b border-custom-border-200 px-4 py-6">
|
||||
<div className="flex flex-col gap-4 border-b border-custom-border-100 px-4 py-6">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-start gap-3">
|
||||
<div className="flex items-center justify-center p-3 rounded bg-custom-background-90">
|
||||
@@ -100,7 +100,7 @@ export const AutoCloseAutomation: React.FC<Props> = ({ projectDetails, handleCha
|
||||
|
||||
{projectDetails?.close_in !== 0 && (
|
||||
<div className="ml-12">
|
||||
<div className="flex flex-col rounded bg-custom-background-90 border border-custom-border-200 p-2">
|
||||
<div className="flex flex-col rounded bg-custom-background-90 border-[0.5px] border-custom-border-200 p-2">
|
||||
<div className="flex items-center justify-between px-5 py-4 gap-2 w-full">
|
||||
<div className="w-1/2 text-sm font-medium">Auto-close issues that are inactive for</div>
|
||||
<div className="w-1/2">
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from "react";
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
// react-hook-form
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
// headless ui
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import * as React from "react";
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
import Link from "next/link";
|
||||
// icons
|
||||
import { MoveLeft } from "lucide-react";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { useCallback, useEffect, useState } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
import useSWR, { mutate } from "swr";
|
||||
import { Command } from "cmdk";
|
||||
import { Dialog, Transition } from "@headlessui/react";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { useCallback, useEffect, FC } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
import useSWR from "swr";
|
||||
import { observer } from "mobx-react-lite";
|
||||
// hooks
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Dispatch, SetStateAction, useCallback, FC } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { mutate } from "swr";
|
||||
import { Command } from "cmdk";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { Dispatch, SetStateAction, useCallback } from "react";
|
||||
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
import { mutate } from "swr";
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { Dispatch, SetStateAction, useCallback } from "react";
|
||||
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
import useSWR, { mutate } from "swr";
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
import useSWR from "swr";
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { useEffect, useState, useRef, useCallback } from "react";
|
||||
import Image from "next/image";
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import useSWR from "swr";
|
||||
import { useDropzone } from "react-dropzone";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { useState } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
import useSWR from "swr";
|
||||
// react hook form
|
||||
import { SubmitHandler, useForm } from "react-hook-form";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { Combobox, Dialog, Transition } from "@headlessui/react";
|
||||
import { Rocket, Search, X } from "lucide-react";
|
||||
// services
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { useEffect, useState, useRef } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
// react-hook-form
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
// services
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { useCallback, useState } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { useDropzone } from "react-dropzone";
|
||||
import { Transition, Dialog } from "@headlessui/react";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { MouseEvent } from "react";
|
||||
import Link from "next/link";
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
import useSWR from "swr";
|
||||
// hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { useEffect } from "react";
|
||||
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
// mobx
|
||||
import { observer } from "mobx-react-lite";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { FC, MouseEvent, useState } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
import Link from "next/link";
|
||||
// hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
@@ -44,6 +44,7 @@ export const CyclesBoardCard: FC<ICyclesBoardCard> = (props) => {
|
||||
const isCompleted = cycleStatus === "completed";
|
||||
const endDate = new Date(cycle.end_date ?? "");
|
||||
const startDate = new Date(cycle.start_date ?? "");
|
||||
const isDateValid = cycle.start_date || cycle.end_date;
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
@@ -64,9 +65,7 @@ export const CyclesBoardCard: FC<ICyclesBoardCard> = (props) => {
|
||||
? cycleTotalIssues === 0
|
||||
? "0 Issue"
|
||||
: cycleTotalIssues === cycle.completed_issues
|
||||
? cycleTotalIssues > 1
|
||||
? `${cycleTotalIssues} Issues`
|
||||
: `${cycleTotalIssues} Issue`
|
||||
? `${cycleTotalIssues} Issue${cycleTotalIssues > 1 ? "s" : ""}`
|
||||
: `${cycle.completed_issues}/${cycleTotalIssues} Issues`
|
||||
: "0 Issue";
|
||||
|
||||
@@ -225,10 +224,14 @@ export const CyclesBoardCard: FC<ICyclesBoardCard> = (props) => {
|
||||
</Tooltip>
|
||||
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-xs text-custom-text-300">
|
||||
{areYearsEqual ? renderShortDate(startDate, "_ _") : renderShortMonthDate(startDate, "_ _")} -{" "}
|
||||
{areYearsEqual ? renderShortDate(endDate, "_ _") : renderShortMonthDate(endDate, "_ _")}
|
||||
</span>
|
||||
{isDateValid ? (
|
||||
<span className="text-xs text-custom-text-300">
|
||||
{areYearsEqual ? renderShortDate(startDate, "_ _") : renderShortMonthDate(startDate, "_ _")} -{" "}
|
||||
{areYearsEqual ? renderShortDate(endDate, "_ _") : renderShortMonthDate(endDate, "_ _")}
|
||||
</span>
|
||||
) : (
|
||||
<span className="text-xs text-custom-text-400">No due date</span>
|
||||
)}
|
||||
<div className="flex items-center gap-1.5 z-10">
|
||||
{cycle.is_favorite ? (
|
||||
<button type="button" onClick={handleRemoveFromFavorites}>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { FC, MouseEvent, useState } from "react";
|
||||
import Link from "next/link";
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
// stores
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
@@ -155,9 +155,11 @@ export const CyclesListItem: FC<TCyclesListItem> = (props) => {
|
||||
<span className="flex-shrink-0">
|
||||
<CircularProgressIndicator size={38} percentage={progress}>
|
||||
{isCompleted ? (
|
||||
<span className="text-sm text-custom-primary-100">{`!`}</span>
|
||||
) : progress === 100 ? (
|
||||
<Check className="h-3 w-3 text-custom-primary-100 stroke-[2]" />
|
||||
progress === 100 ? (
|
||||
<Check className="h-3 w-3 text-custom-primary-100 stroke-[2]" />
|
||||
) : (
|
||||
<span className="text-sm text-custom-primary-100">{`!`}</span>
|
||||
)
|
||||
) : (
|
||||
<span className="text-xs text-custom-text-300">{`${progress}%`}</span>
|
||||
)}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
// ui
|
||||
import { Tooltip, ContrastIcon } from "@plane/ui";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { FC } from "react";
|
||||
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
import { KeyedMutator } from "swr";
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { useState } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
import useSWR from "swr";
|
||||
import { Listbox, Transition } from "@headlessui/react";
|
||||
// icons
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { mutate } from "swr";
|
||||
import { useForm } from "react-hook-form";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { useState } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
import useSWR from "swr";
|
||||
import { Dialog, Transition } from "@headlessui/react";
|
||||
// services
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from "react";
|
||||
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
import useSWR from "swr";
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { useEffect } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
import { Dialog, Transition } from "@headlessui/react";
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { Dialog, Transition } from "@headlessui/react";
|
||||
// store
|
||||
import { observer } from "mobx-react-lite";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from "react";
|
||||
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
// store
|
||||
import { observer } from "mobx-react-lite";
|
||||
@@ -54,7 +54,7 @@ export const EstimateListItem: React.FC<Props> = observer((props) => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="gap-2 p-4 border-b border-custom-border-200">
|
||||
<div className="gap-2 p-4 border-b border-custom-border-100">
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<h6 className="flex w-[40vw] items-center gap-2 truncate text-sm font-medium">
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { useState } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
// store
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
@@ -71,7 +71,7 @@ export const EstimatesList: React.FC = observer(() => {
|
||||
data={projectStore.getProjectEstimateById(estimateToDelete!)}
|
||||
/>
|
||||
|
||||
<section className="flex items-center justify-between py-3.5 border-b border-custom-border-200">
|
||||
<section className="flex items-center justify-between py-3.5 border-b border-custom-border-100">
|
||||
<h3 className="text-xl font-medium">Estimates</h3>
|
||||
<div className="col-span-12 space-y-5 sm:col-span-7">
|
||||
<div className="flex items-center gap-2">
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { useState } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { Dialog, Transition } from "@headlessui/react";
|
||||
// mobx store
|
||||
|
||||
@@ -2,7 +2,7 @@ import { useState } from "react";
|
||||
|
||||
import Link from "next/link";
|
||||
import Image from "next/image";
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
import useSWR, { mutate } from "swr";
|
||||
|
||||
@@ -53,7 +53,7 @@ const IntegrationGuide = () => {
|
||||
{EXPORTERS_LIST.map((service) => (
|
||||
<div
|
||||
key={service.provider}
|
||||
className="flex items-center justify-between gap-2 border-b border-custom-border-200 bg-custom-background-100 px-4 py-6"
|
||||
className="flex items-center justify-between gap-2 border-b border-custom-border-100 bg-custom-background-100 px-4 py-6"
|
||||
>
|
||||
<div className="flex items-start justify-between gap-4 w-full">
|
||||
<div className="flex item-center gap-2.5">
|
||||
@@ -79,7 +79,7 @@ const IntegrationGuide = () => {
|
||||
))}
|
||||
</div>
|
||||
<div>
|
||||
<div className="flex items-center justify-between pt-7 pb-3.5 border-b border-custom-border-200">
|
||||
<div className="flex items-center justify-between pt-7 pb-3.5 border-b border-custom-border-100">
|
||||
<div className="flex gap-2 items-center">
|
||||
<h3 className="flex gap-2 text-xl font-medium">Previous Exports</h3>
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { DragDropContext, Draggable, DropResult } from "@hello-pangea/dnd";
|
||||
import StrictModeDroppable from "components/dnd/StrictModeDroppable";
|
||||
import { MoreVertical } from "lucide-react";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { DragDropContext, Draggable, DropResult } from "@hello-pangea/dnd";
|
||||
import StrictModeDroppable from "components/dnd/StrictModeDroppable";
|
||||
import { MoreVertical } from "lucide-react";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { DragDropContext, Draggable, DropResult } from "@hello-pangea/dnd";
|
||||
import StrictModeDroppable from "components/dnd/StrictModeDroppable";
|
||||
import { MoreVertical } from "lucide-react";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useCallback, useState } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { observer } from "mobx-react-lite";
|
||||
// mobx store
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user