Merge pull request #288 from makeplane/sync/ce-ee

sync: merge conflicts need to be resolved
This commit is contained in:
sriram veeraghanta
2024-05-22 12:32:02 +05:30
committed by GitHub
20 changed files with 71 additions and 286 deletions

View File

View File

@@ -0,0 +1,6 @@
#!/bin/bash
set -e
python manage.py wait_for_db $1
python manage.py migrate $1

View File

@@ -1,8 +0,0 @@
## Coolify Setup
Access the `coolify-docker-compose` file [here](https://raw.githubusercontent.com/makeplane/plane/master/deploy/coolify/coolify-docker-compose.yml) or download using using below command
```
curl -fsSL https://raw.githubusercontent.com/makeplane/plane/master/deploy/coolify/coolify-docker-compose.yml
```

View File

@@ -1,230 +0,0 @@
services:
web:
container_name: web
platform: linux/amd64
image: makeplane/plane-frontend:latest
restart: always
command: /usr/local/bin/start.sh web/server.js web
environment:
- NEXT_PUBLIC_DEPLOY_URL=$SERVICE_FQDN_SPACE_8082
depends_on:
- api
- worker
space:
container_name: space
platform: linux/amd64
image: makeplane/plane-space:latest
restart: always
command: /usr/local/bin/start.sh space/server.js space
environment:
- SERVICE_FQDN_SPACE_8082=/api
depends_on:
- api
- worker
- web
api:
container_name: api
platform: linux/amd64
image: makeplane/plane-backend:latest
restart: always
command: ./bin/takeoff
environment:
- DEBUG=${DEBUG:-0}
- SENTRY_DSN=${SENTRY_DSN:-""}
- PGUSER=${PGUSER:-plane}
- PGPASSWORD=${PGPASSWORD:-plane}
- PGHOST=${PGHOST:-plane-db}
- PGDATABASE=${PGDATABASE:-plane}
- DATABASE_URL=postgresql://${PGUSER}:${PGPASSWORD}@${PGHOST}/${PGDATABASE}
- REDIS_HOST=${REDIS_HOST:-plane-redis}
- REDIS_PORT=${REDIS_PORT:-6379}
- REDIS_URL=redis://${REDIS_HOST}:6379/
- EMAIL_HOST=${EMAIL_HOST:-""}
- EMAIL_HOST_USER=${EMAIL_HOST_USER:-""}
- EMAIL_HOST_PASSWORD=${EMAIL_HOST_PASSWORD:-""}
- EMAIL_PORT=${EMAIL_PORT:-587}
- EMAIL_FROM=${EMAIL_FROM:-Team Plane <team@mailer.plane.so>}
- EMAIL_USE_TLS=${EMAIL_USE_TLS:-1}
- EMAIL_USE_SSL=${EMAIL_USE_SSL:-0}
- AWS_REGION=${AWS_REGION:-""}
- AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID:-access-key}
- AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY:-secret-key}
- AWS_S3_ENDPOINT_URL=${AWS_S3_ENDPOINT_URL:-http://plane-minio:9000}
- AWS_S3_BUCKET_NAME=${AWS_S3_BUCKET_NAME:-uploads}
- FILE_SIZE_LIMIT=${FILE_SIZE_LIMIT:-5242880}
- OPENAI_API_BASE=${OPENAI_API_BASE:-https://api.openai.com/v1}
- OPENAI_API_KEY=${OPENAI_API_KEY:-sk-}
- GPT_ENGINE=${GPT_ENGINE:-gpt-3.5-turbo}
- GITHUB_CLIENT_SECRET=${GITHUB_CLIENT_SECRET:-""}
- DOCKERIZED=${DOCKERIZED:-1}
- USE_MINIO=${USE_MINIO:-1}
- NGINX_PORT=${NGINX_PORT:-8082}
- DEFAULT_EMAIL=${DEFAULT_EMAIL:-captain@plane.so}
- DEFAULT_PASSWORD=${DEFAULT_PASSWORD:-password123}
- ENABLE_SIGNUP=${ENABLE_SIGNUP:-1}
- ENABLE_EMAIL_PASSWORD=${ENABLE_EMAIL_PASSWORD:-1}
- ENABLE_MAGIC_LINK_LOGIN=${ENABLE_MAGIC_LINK_LOGIN:-0}
- SECRET_KEY=${SECRET_KEY:-60gp0byfz2dvffa45cxl20p1scy9xbpf6d8c5y0geejgkyp1b5}
- WEB_URL=$SERVICE_FQDN_PLANE_8082
depends_on:
- plane-db
- plane-redis
worker:
container_name: bgworker
platform: linux/amd64
image: makeplane/plane-backend:latest
restart: always
command: ./bin/worker
environment:
- DEBUG=${DEBUG:-0}
- SENTRY_DSN=${SENTRY_DSN:-""}
- PGUSER=${PGUSER:-plane}
- PGPASSWORD=${PGPASSWORD:-plane}
- PGHOST=${PGHOST:-plane-db}
- PGDATABASE=${PGDATABASE:-plane}
- DATABASE_URL=postgresql://${PGUSER}:${PGPASSWORD}@${PGHOST}/${PGDATABASE}
- REDIS_HOST=${REDIS_HOST:-plane-redis}
- REDIS_PORT=${REDIS_PORT:-6379}
- REDIS_URL=redis://${REDIS_HOST}:6379/
- EMAIL_HOST=${EMAIL_HOST:-""}
- EMAIL_HOST_USER=${EMAIL_HOST_USER:-""}
- EMAIL_HOST_PASSWORD=${EMAIL_HOST_PASSWORD:-""}
- EMAIL_PORT=${EMAIL_PORT:-587}
- EMAIL_FROM=${EMAIL_FROM:-Team Plane <team@mailer.plane.so>}
- EMAIL_USE_TLS=${EMAIL_USE_TLS:-1}
- EMAIL_USE_SSL=${EMAIL_USE_SSL:-0}
- AWS_REGION=${AWS_REGION:-""}
- AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID:-access-key}
- AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY:-secret-key}
- AWS_S3_ENDPOINT_URL=${AWS_S3_ENDPOINT_URL:-http://plane-minio:9000}
- AWS_S3_BUCKET_NAME=${AWS_S3_BUCKET_NAME:-uploads}
- FILE_SIZE_LIMIT=${FILE_SIZE_LIMIT:-5242880}
- OPENAI_API_BASE=${OPENAI_API_BASE:-https://api.openai.com/v1}
- OPENAI_API_KEY=${OPENAI_API_KEY:-sk-}
- GPT_ENGINE=${GPT_ENGINE:-gpt-3.5-turbo}
- GITHUB_CLIENT_SECRET=${GITHUB_CLIENT_SECRET:-""}
- DOCKERIZED=${DOCKERIZED:-1}
- USE_MINIO=${USE_MINIO:-1}
- NGINX_PORT=${NGINX_PORT:-8082}
- DEFAULT_EMAIL=${DEFAULT_EMAIL:-captain@plane.so}
- DEFAULT_PASSWORD=${DEFAULT_PASSWORD:-password123}
- ENABLE_SIGNUP=${ENABLE_SIGNUP:-1}
- SECRET_KEY=${SECRET_KEY:-60gp0byfz2dvffa45cxl20p1scy9xbpf6d8c5y0geejgkyp1b5}
depends_on:
- api
- plane-db
- plane-redis
beat-worker:
container_name: beatworker
platform: linux/amd64
image: makeplane/plane-backend:latest
restart: always
command: ./bin/beat
environment:
- DEBUG=${DEBUG:-0}
- SENTRY_DSN=${SENTRY_DSN:-""}
- PGUSER=${PGUSER:-plane}
- PGPASSWORD=${PGPASSWORD:-plane}
- PGHOST=${PGHOST:-plane-db}
- PGDATABASE=${PGDATABASE:-plane}
- DATABASE_URL=postgresql://${PGUSER}:${PGPASSWORD}@${PGHOST}/${PGDATABASE}
- REDIS_HOST=${REDIS_HOST:-plane-redis}
- REDIS_PORT=${REDIS_PORT:-6379}
- REDIS_URL=redis://${REDIS_HOST}:6379/
- EMAIL_HOST=${EMAIL_HOST:-""}
- EMAIL_HOST_USER=${EMAIL_HOST_USER:-""}
- EMAIL_HOST_PASSWORD=${EMAIL_HOST_PASSWORD:-""}
- EMAIL_PORT=${EMAIL_PORT:-587}
- EMAIL_FROM=${EMAIL_FROM:-Team Plane <team@mailer.plane.so>}
- EMAIL_USE_TLS=${EMAIL_USE_TLS:-1}
- EMAIL_USE_SSL=${EMAIL_USE_SSL:-0}
- AWS_REGION=${AWS_REGION:-""}
- AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID:-access-key}
- AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY:-secret-key}
- AWS_S3_ENDPOINT_URL=${AWS_S3_ENDPOINT_URL:-http://plane-minio:9000}
- AWS_S3_BUCKET_NAME=${AWS_S3_BUCKET_NAME:-uploads}
- FILE_SIZE_LIMIT=${FILE_SIZE_LIMIT:-5242880}
- OPENAI_API_BASE=${OPENAI_API_BASE:-https://api.openai.com/v1}
- OPENAI_API_KEY=${OPENAI_API_KEY:-sk-}
- GPT_ENGINE=${GPT_ENGINE:-gpt-3.5-turbo}
- GITHUB_CLIENT_SECRET=${GITHUB_CLIENT_SECRET:-""}
- DOCKERIZED=${DOCKERIZED:-1}
- USE_MINIO=${USE_MINIO:-1}
- NGINX_PORT=${NGINX_PORT:-8082}
- DEFAULT_EMAIL=${DEFAULT_EMAIL:-captain@plane.so}
- DEFAULT_PASSWORD=${DEFAULT_PASSWORD:-password123}
- ENABLE_SIGNUP=${ENABLE_SIGNUP:-1}
- SECRET_KEY=${SECRET_KEY:-60gp0byfz2dvffa45cxl20p1scy9xbpf6d8c5y0geejgkyp1b5}
depends_on:
- api
- plane-db
- plane-redis
plane-db:
container_name: plane-db
image: postgres:15.2-alpine
restart: always
command: postgres -c 'max_connections=1000'
volumes:
- pgdata:/var/lib/postgresql/data
environment:
- POSTGRES_USER=${POSTGRES_USER:-plane}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-plane}
- POSTGRES_DB=${POSTGRES_DB:-plane}
- PGDATA=${PGDATA:-/var/lib/postgresql/data}
plane-redis:
container_name: plane-redis
image: redis:7.2.4-alpine
restart: always
volumes:
- redisdata:/data
plane-minio:
container_name: plane-minio
image: minio/minio
restart: always
command: server /export --console-address ":9090"
volumes:
- uploads:/export
environment:
- MINIO_ROOT_USER=${MINIO_ROOT_USER:-access-key}
- MINIO_ROOT_PASSWORD=${MINIO_ROOT_PASSWORD:-secret-key}
createbuckets:
image: minio/mc
entrypoint: >
/bin/sh -c " /usr/bin/mc config host add plane-minio http://plane-minio:9000 \$AWS_ACCESS_KEY_ID \$AWS_SECRET_ACCESS_KEY; /usr/bin/mc mb plane-minio/\$AWS_S3_BUCKET_NAME; /usr/bin/mc anonymous set download plane-minio/\$AWS_S3_BUCKET_NAME; exit 0; "
environment:
- AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID:-access-key}
- AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY:-secret-key}
- AWS_S3_BUCKET_NAME=${AWS_S3_BUCKET_NAME:-uploads}
depends_on:
- plane-minio
# Comment this if you already have a reverse proxy running
proxy:
container_name: proxy
platform: linux/amd64
image: makeplane/plane-proxy:latest
ports:
- 8082:80
environment:
- SERVICE_FQDN_PLANE_8082
- NGINX_PORT=${NGINX_PORT:-8082}
- FILE_SIZE_LIMIT=${FILE_SIZE_LIMIT:-5242880}
- BUCKET_NAME=${AWS_S3_BUCKET_NAME:-uploads}
depends_on:
- web
- api
- space
volumes:
pgdata:
redisdata:
uploads:

View File

@@ -86,7 +86,7 @@ services:
platform: ${DOCKER_PLATFORM:-}
pull_policy: ${PULL_POLICY:-always}
restart: unless-stopped
command: ./bin/takeoff
command: ./bin/docker-entry-api.sh
deploy:
replicas: ${API_REPLICAS:-1}
volumes:
@@ -101,7 +101,7 @@ services:
platform: ${DOCKER_PLATFORM:-}
pull_policy: ${PULL_POLICY:-always}
restart: unless-stopped
command: ./bin/worker
command: ./bin/docker-entry-worker.sh
volumes:
- logs_worker:/code/plane/logs
depends_on:
@@ -115,7 +115,7 @@ services:
platform: ${DOCKER_PLATFORM:-}
pull_policy: ${PULL_POLICY:-always}
restart: unless-stopped
command: ./bin/beat
command: ./bin/docker-entry-beat.sh
volumes:
- logs_beat-worker:/code/plane/logs
depends_on:
@@ -129,9 +129,7 @@ services:
platform: ${DOCKER_PLATFORM:-}
pull_policy: ${PULL_POLICY:-always}
restart: no
command: >
sh -c "python manage.py wait_for_db &&
python manage.py migrate"
command: ./bin/docker-entry-migrator.sh
volumes:
- logs_migrator:/code/plane/logs
depends_on:

View File

@@ -108,7 +108,7 @@ services:
- dev_env
volumes:
- ./apiserver:/code
command: ./bin/takeoff.local
command: ./bin/docker-entry-api.sh
env_file:
- ./apiserver/.env
depends_on:
@@ -126,7 +126,7 @@ services:
- dev_env
volumes:
- ./apiserver:/code
command: ./bin/worker
command: ./bin/docker-entry-worker.sh
env_file:
- ./apiserver/.env
depends_on:
@@ -145,7 +145,7 @@ services:
- dev_env
volumes:
- ./apiserver:/code
command: ./bin/beat
command: ./bin/docker-entry-beat.sh
env_file:
- ./apiserver/.env
depends_on:
@@ -164,9 +164,7 @@ services:
- dev_env
volumes:
- ./apiserver:/code
command: >
sh -c "python manage.py wait_for_db --settings=plane.settings.local &&
python manage.py migrate --settings=plane.settings.local"
command: ./bin/docker-entry-migrator.sh --settings=plane.settings.local
env_file:
- ./apiserver/.env
depends_on:

View File

@@ -45,7 +45,7 @@ services:
args:
DOCKER_BUILDKIT: 1
restart: always
command: ./bin/takeoff
command: ./bin/docker-entry-api.sh
env_file:
- ./apiserver/.env
depends_on:
@@ -69,7 +69,7 @@ services:
args:
DOCKER_BUILDKIT: 1
restart: always
command: ./bin/worker
command: ./bin/docker-entry-worker.sh
env_file:
- ./apiserver/.env
depends_on:
@@ -85,7 +85,7 @@ services:
args:
DOCKER_BUILDKIT: 1
restart: always
command: ./bin/beat
command: ./bin/docker-entry-beat.sh
env_file:
- ./apiserver/.env
depends_on:
@@ -101,9 +101,7 @@ services:
args:
DOCKER_BUILDKIT: 1
restart: no
command: >
sh -c "python manage.py wait_for_db &&
python manage.py migrate"
command: ./bin/docker-entry-migrator.sh
env_file:
- ./apiserver/.env
depends_on:

View File

@@ -17,7 +17,7 @@ export const DragHandle = forwardRef<HTMLButtonElement | null, IDragHandle>((pro
return (
<button
type="button"
className={`mr-1 p-[2px] flex flex-shrink-0 rounded bg-custom-background-90 text-custom-sidebar-text-200 group-hover:opacity-100 cursor-grab ${
className={` p-[2px] flex flex-shrink-0 rounded bg-custom-background-90 text-custom-sidebar-text-200 group-hover:opacity-100 cursor-grab ${
isDragging ? "opacity-100" : "opacity-0"
}`}
onContextMenu={(e) => {

View File

@@ -118,7 +118,7 @@ export const IssueBlockRoot: FC<Props> = observer((props) => {
key={`${issueId}`}
defaultHeight="3rem"
root={containerRef}
classNames={`relative ${isLastChild ? "" : "border-b border-b-custom-border-200"}`}
classNames={`relative ${isLastChild && !isExpanded ? "" : "border-b border-b-custom-border-200"}`}
>
<IssueBlock
issueId={issueId}

View File

@@ -67,8 +67,9 @@ export const IssueBlock = observer((props: IssueBlockProps) => {
!getIsIssuePeeked(issue.id) &&
setPeekIssue({ workspaceSlug, projectId: issue.project_id, issueId: issue.id, nestingLevel: nestingLevel });
const issue = issuesMap[issueId];
const subIssues = subIssuesStore.subIssuesByIssueId(issueId);
const issue = issuesMap[issueId];
const subIssuesCount = issue.sub_issues_count;
const { isMobile } = usePlatformOS();
useEffect(() => {
@@ -97,8 +98,6 @@ export const IssueBlock = observer((props: IssueBlockProps) => {
const canEditIssueProperties = canEditProperties(issue.project_id);
const projectIdentifier = getProjectIdentifierById(issue.project_id);
// if sub issues have been fetched for the issue, use that for count or use issue's sub_issues_count
const subIssuesCount = subIssues ? subIssues.length : issue.sub_issues_count;
const paddingLeft = `${spacingLeft}px`;
@@ -120,7 +119,7 @@ export const IssueBlock = observer((props: IssueBlockProps) => {
<div
ref={issueRef}
className={cn(
"group min-h-11 relative flex flex-col md:flex-row md:items-center gap-3 bg-custom-background-100 p-3 text-sm",
"group min-h-11 relative flex flex-col md:flex-row md:items-center gap-3 bg-custom-background-100 pl-1.5 pr-1 text-sm",
{
"border border-custom-primary-70 hover:border-custom-primary-70":
getIsIssuePeeked(issue.id) && peekIssue?.nestingLevel === nestingLevel,
@@ -146,7 +145,7 @@ export const IssueBlock = observer((props: IssueBlockProps) => {
</div>
</div>
{displayProperties && displayProperties?.key && (
<div className="flex-shrink-0 text-xs font-medium text-custom-text-300">
<div className="pl-1 flex-shrink-0 text-xs font-medium text-custom-text-300">
{projectIdentifier}-{issue.sequence_id}
</div>
)}

View File

@@ -65,7 +65,7 @@ export const HeaderGroupByCard = observer(
return (
<>
<div className="relative flex w-full flex-shrink-0 flex-row items-center gap-2 py-1.5">
<div className="relative flex w-full flex-shrink-0 flex-row items-center gap-1.5 py-1.5">
<div className="flex h-5 w-5 flex-shrink-0 items-center justify-center overflow-hidden rounded-sm">
{icon ? icon : <CircleDashed className="h-3.5 w-3.5" strokeWidth={2} />}
</div>

View File

@@ -152,7 +152,7 @@ export const ListQuickAddIssueForm: FC<IListQuickAddIssueForm> = observer((props
</div>
) : (
<div
className="flex w-full cursor-pointer items-center gap-2 p-3 py-3 text-custom-primary-100"
className="flex w-full cursor-pointer items-center gap-3 p-6 py-3 text-custom-primary-100"
onClick={() => setIsOpen(true)}
>
<PlusIcon className="h-3.5 w-3.5 stroke-2" />

View File

@@ -2,10 +2,13 @@ import { SyntheticEvent, useCallback, useMemo } from "react";
import xor from "lodash/xor";
import { observer } from "mobx-react";
import { useRouter } from "next/router";
// icons
import { CalendarCheck2, CalendarClock, Layers, Link, Paperclip } from "lucide-react";
// types
import { TIssue, IIssueDisplayProperties, TIssuePriorities } from "@plane/types";
// hooks
// ui
import { Tooltip } from "@plane/ui";
// components
import {
DateDropdown,
EstimateDropdown,
@@ -15,23 +18,19 @@ import {
CycleDropdown,
StateDropdown,
} from "@/components/dropdowns";
// helpers
// types
// constants
import { ISSUE_UPDATED } from "@/constants/event-tracker";
import { EIssuesStoreType } from "@/constants/issue";
// helpers
import { cn } from "@/helpers/common.helper";
import { getDate, renderFormattedPayloadDate } from "@/helpers/date-time.helper";
import { shouldHighlightIssueDueDate } from "@/helpers/issue.helper";
// hooks
import { useEventTracker, useEstimate, useLabel, useIssues, useProjectState, useProject } from "@/hooks/store";
import { usePlatformOS } from "@/hooks/use-platform-os";
// components
// local components
import { IssuePropertyLabels } from "../properties/labels";
import { WithDisplayPropertiesHOC } from "../properties/with-display-properties-HOC";
// helpers
// types
// constants
export interface IIssueProperties {
issue: TIssue;
@@ -64,6 +63,7 @@ export const IssueProperties: React.FC<IIssueProperties> = observer((props) => {
const currentLayout = `${activeLayout} layout`;
// derived values
const stateDetails = getStateById(issue.state_id);
const subIssueCount = issue.sub_issues_count;
const issueOperations = useMemo(
() => ({
@@ -414,24 +414,25 @@ export const IssueProperties: React.FC<IIssueProperties> = observer((props) => {
<WithDisplayPropertiesHOC
displayProperties={displayProperties}
displayPropertyKey="sub_issue_count"
shouldRenderProperty={(properties) => !!properties.sub_issue_count && !!issue.sub_issues_count}
shouldRenderProperty={(properties) => !!properties.sub_issue_count && !!subIssueCount}
>
<Tooltip tooltipHeading="Sub-issues" tooltipContent={`${issue.sub_issues_count}`} isMobile={isMobile}>
<Tooltip tooltipHeading="Sub-issues" tooltipContent={`${subIssueCount}`} isMobile={isMobile}>
<div
onFocus={handleEventPropagation}
onClick={(e) => {
handleEventPropagation(e);
if (issue.sub_issues_count) redirectToIssueDetail();
e.stopPropagation();
e.preventDefault();
if (subIssueCount) redirectToIssueDetail();
}}
className={cn(
"flex h-5 flex-shrink-0 items-center justify-center gap-2 overflow-hidden rounded border-[0.5px] border-custom-border-300 px-2.5 py-1",
{
"hover:bg-custom-background-80 cursor-pointer": issue.sub_issues_count,
"hover:bg-custom-background-80 cursor-pointer": subIssueCount,
}
)}
>
<Layers className="h-3 w-3 flex-shrink-0" strokeWidth={2} />
<div className="text-xs">{issue.sub_issues_count}</div>
<div className="text-xs">{subIssueCount}</div>
</div>
</Tooltip>
</WithDisplayPropertiesHOC>

View File

@@ -18,6 +18,8 @@ export const SpreadsheetSubIssueColumn: React.FC<Props> = observer((props: Props
const router = useRouter();
// hooks
const { workspaceSlug } = useAppRouter();
// derived values
const subIssueCount = issue.sub_issues_count;
const redirectToIssueDetail = () => {
router.push({
@@ -30,15 +32,15 @@ export const SpreadsheetSubIssueColumn: React.FC<Props> = observer((props: Props
return (
<div
onClick={issue?.sub_issues_count ? redirectToIssueDetail : () => {}}
onClick={subIssueCount ? redirectToIssueDetail : () => {}}
className={cn(
"flex h-11 w-full items-center border-b-[0.5px] border-custom-border-200 px-2.5 py-1 text-xs hover:bg-custom-background-80",
{
"cursor-pointer": issue?.sub_issues_count,
"cursor-pointer": subIssueCount,
}
)}
>
{issue?.sub_issues_count} {issue?.sub_issues_count === 1 ? "sub-issue" : "sub-issues"}
{subIssueCount} {subIssueCount === 1 ? "sub-issue" : "sub-issues"}
</div>
);
});

View File

@@ -203,6 +203,7 @@ const IssueRowDetails = observer((props: IssueRowDetailsProps) => {
};
const disableUserActions = !canEditProperties(issueDetail.project_id);
const subIssuesCount = issueDetail.sub_issues_count;
return (
<>
@@ -230,7 +231,7 @@ const IssueRowDetails = observer((props: IssueRowDetailsProps) => {
{/* bulk ops */}
<span className="size-3.5" />
<div className="flex size-4 items-center justify-center">
{issueDetail.sub_issues_count > 0 && (
{subIssuesCount > 0 && (
<button
className="flex items-center justify-center size-4 cursor-pointer rounded-sm text-custom-text-400 hover:text-custom-text-300"
onClick={handleToggleExpand}

View File

@@ -59,6 +59,7 @@ export const IssueListItem: React.FC<ISubIssues> = observer((props) => {
undefined;
const subIssueHelpers = subIssueHelpersByIssueId(parentIssueId);
const subIssueCount = issue?.sub_issues_count || 0;
const handleIssuePeekOverview = (issue: TIssue) =>
workspaceSlug &&
@@ -77,7 +78,7 @@ export const IssueListItem: React.FC<ISubIssues> = observer((props) => {
style={{ paddingLeft: `${spacingLeft}px` }}
>
<div className="h-[22px] w-[22px] flex-shrink-0">
{issue?.sub_issues_count > 0 && (
{subIssueCount > 0 && (
<>
{subIssueHelpers.preview_loader.includes(issue.id) ? (
<div className="flex h-full w-full cursor-not-allowed items-center justify-center rounded-sm bg-custom-background-80 transition-all">
@@ -205,7 +206,7 @@ export const IssueListItem: React.FC<ISubIssues> = observer((props) => {
</div>
)}
{subIssueHelpers.issue_visibility.includes(issueId) && issue.sub_issues_count && issue.sub_issues_count > 0 && (
{subIssueHelpers.issue_visibility.includes(issueId) && subIssueCount > 0 && (
<IssueList
workspaceSlug={workspaceSlug}
projectId={issue.project_id}

View File

@@ -174,6 +174,13 @@ export class IssueSubIssuesStore implements IIssueSubIssuesStore {
this.rootIssueDetailStore.rootIssueStore.issues.addIssue(subIssues);
// update sub-issues_count of the parent issue
set(
this.rootIssueDetailStore.rootIssueStore.issues.issuesMap,
[parentIssueId, "sub_issues_count"],
this.subIssues[parentIssueId].length
);
return;
} catch (error) {
throw error;
@@ -270,6 +277,12 @@ export class IssueSubIssuesStore implements IIssueSubIssuesStore {
runInAction(() => {
pull(this.subIssues[parentIssueId], issueId);
// update sub-issues_count of the parent issue
set(
this.rootIssueDetailStore.rootIssueStore.issues.issuesMap,
[parentIssueId, "sub_issues_count"],
this.subIssues[parentIssueId].length
);
});
return;
@@ -301,6 +314,12 @@ export class IssueSubIssuesStore implements IIssueSubIssuesStore {
runInAction(() => {
pull(this.subIssues[parentIssueId], issueId);
// update sub-issues_count of the parent issue
set(
this.rootIssueDetailStore.rootIssueStore.issues.issuesMap,
[parentIssueId, "sub_issues_count"],
this.subIssues[parentIssueId].length
);
});
return;