Merge pull request #3046 from makeplane/promote/dev-preview

promote: develop to preview
This commit is contained in:
sriram veeraghanta 2023-12-08 19:53:57 +05:30 committed by GitHub
commit d16a6402cd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
35 changed files with 202 additions and 134 deletions

View File

@ -27,7 +27,8 @@ WORKDIR /code
COPY requirements.txt ./requirements.txt COPY requirements.txt ./requirements.txt
ADD requirements ./requirements ADD requirements ./requirements
RUN pip install -r requirements.txt --compile --no-cache-dir # Install the local development settings
RUN pip install -r requirements/local.txt --compile --no-cache-dir
RUN addgroup -S plane && \ RUN addgroup -S plane && \
adduser -S captain -G plane adduser -S captain -G plane

View File

@ -1,4 +1,4 @@
{ {
"name": "plane-api", "name": "plane-api",
"version": "0.13.2" "version": "0.14.0"
} }

View File

@ -90,8 +90,8 @@ class ConfigurationEndpoint(BaseAPIView):
data = {} data = {}
# Authentication # Authentication
data["google_client_id"] = GOOGLE_CLIENT_ID data["google_client_id"] = GOOGLE_CLIENT_ID if GOOGLE_CLIENT_ID and GOOGLE_CLIENT_ID != "\"\"" else None
data["github_client_id"] = GITHUB_CLIENT_ID data["github_client_id"] = GITHUB_CLIENT_ID if GITHUB_CLIENT_ID and GITHUB_CLIENT_ID != "\"\"" else None
data["github_app_name"] = GITHUB_APP_NAME data["github_app_name"] = GITHUB_APP_NAME
data["magic_login"] = ( data["magic_login"] = (
bool(EMAIL_HOST_USER) and bool(EMAIL_HOST_PASSWORD) bool(EMAIL_HOST_USER) and bool(EMAIL_HOST_PASSWORD)
@ -106,7 +106,7 @@ class ConfigurationEndpoint(BaseAPIView):
data["posthog_host"] = POSTHOG_HOST data["posthog_host"] = POSTHOG_HOST
# Unsplash # Unsplash
data["has_unsplash_configured"] = UNSPLASH_ACCESS_KEY data["has_unsplash_configured"] = bool(UNSPLASH_ACCESS_KEY)
# Open AI settings # Open AI settings
data["has_openai_configured"] = bool(OPENAI_API_KEY) data["has_openai_configured"] = bool(OPENAI_API_KEY)

View File

@ -86,7 +86,14 @@ def get_access_token(request_token: str, client_id: str) -> str:
if not request_token: if not request_token:
raise ValueError("The request token has to be supplied!") raise ValueError("The request token has to be supplied!")
CLIENT_SECRET = os.environ.get("GITHUB_CLIENT_SECRET") (CLIENT_SECRET,) = get_configuration_value(
[
{
"key": "GITHUB_CLIENT_SECRET",
"default": os.environ.get("GITHUB_CLIENT_SECRET", None),
},
]
)
url = f"https://github.com/login/oauth/access_token?client_id={client_id}&client_secret={CLIENT_SECRET}&code={request_token}" url = f"https://github.com/login/oauth/access_token?client_id={client_id}&client_secret={CLIENT_SECRET}&code={request_token}"
headers = {"accept": "application/json"} headers = {"accept": "application/json"}
@ -299,7 +306,7 @@ class OauthEndpoint(BaseAPIView):
return Response(data, status=status.HTTP_200_OK) return Response(data, status=status.HTTP_200_OK)
except User.DoesNotExist: except User.DoesNotExist:
ENABLE_SIGNUP, = get_configuration_value( (ENABLE_SIGNUP,) = get_configuration_value(
[ [
{ {
"key": "ENABLE_SIGNUP", "key": "ENABLE_SIGNUP",

View File

@ -49,6 +49,10 @@ class UserEndpoint(BaseViewSet):
# Check all workspace user is active # Check all workspace user is active
user = self.get_object() user = self.get_object()
# Instance admin check
if InstanceAdmin.objects.filter(user=user).exists():
return Response({"error": "You cannot deactivate your account since you are an instance admin"}, status=status.HTTP_400_BAD_REQUEST)
projects_to_deactivate = [] projects_to_deactivate = []
workspaces_to_deactivate = [] workspaces_to_deactivate = []

View File

@ -221,37 +221,6 @@ class InstanceAdminSignInEndpoint(BaseAPIView):
is_password_autoset=False, is_password_autoset=False,
) )
# if the current user is not using captain then add the current all users to workspace and projects
if user.email != "captain@plane.so":
# Add the current user also as a workspace member and project memeber to all the workspaces and projects
captain = User.objects.filter(email="captain@plane.so")
# Workspace members
workspace_members = WorkspaceMember.objects.filter(member=captain)
WorkspaceMember.objects.bulk_create(
[
WorkspaceMember(
workspace=member.workspace_id,
member=user,
role=member.role,
)
for member in workspace_members
],
batch_size=100,
)
# project members
project_members = ProjectMember.objects.filter(member=captain)
ProjectMember.objects.bulk_create(
[
ProjectMember(
workspace=member.workspace_id,
member=user,
role=member.role,
)
for member in project_members
],
batch_size=100,
)
# settings last active for the user # settings last active for the user
user.is_active = True user.is_active = True
user.last_active = timezone.now() user.last_active = timezone.now()

View File

@ -41,7 +41,7 @@ x-app-env : &app-env
- DEFAULT_PASSWORD=${DEFAULT_PASSWORD:-password123} - DEFAULT_PASSWORD=${DEFAULT_PASSWORD:-password123}
# OPENAI SETTINGS - Deprecated can be configured through admin panel # OPENAI SETTINGS - Deprecated can be configured through admin panel
- OPENAI_API_BASE=${OPENAI_API_BASE:-https://api.openai.com/v1} - OPENAI_API_BASE=${OPENAI_API_BASE:-https://api.openai.com/v1}
- OPENAI_API_KEY=${OPENAI_API_KEY:-"sk-"} - OPENAI_API_KEY=${OPENAI_API_KEY:-""}
- GPT_ENGINE=${GPT_ENGINE:-"gpt-3.5-turbo"} - GPT_ENGINE=${GPT_ENGINE:-"gpt-3.5-turbo"}
# LOGIN/SIGNUP SETTINGS - Deprecated can be configured through admin panel # LOGIN/SIGNUP SETTINGS - Deprecated can be configured through admin panel
- ENABLE_SIGNUP=${ENABLE_SIGNUP:-1} - ENABLE_SIGNUP=${ENABLE_SIGNUP:-1}

View File

@ -1,6 +1,6 @@
{ {
"repository": "https://github.com/makeplane/plane.git", "repository": "https://github.com/makeplane/plane.git",
"version": "0.13.2", "version": "0.14.0",
"license": "AGPL-3.0", "license": "AGPL-3.0",
"private": true, "private": true,
"workspaces": [ "workspaces": [

View File

@ -1,6 +1,6 @@
{ {
"name": "@plane/editor-core", "name": "@plane/editor-core",
"version": "0.0.1", "version": "0.14.0",
"description": "Core Editor that powers Plane", "description": "Core Editor that powers Plane",
"private": true, "private": true,
"main": "./dist/index.mjs", "main": "./dist/index.mjs",
@ -80,4 +80,4 @@
"nextjs", "nextjs",
"react" "react"
] ]
} }

View File

@ -1,6 +1,6 @@
{ {
"name": "@plane/document-editor", "name": "@plane/document-editor",
"version": "0.1.0", "version": "0.14.0",
"description": "Package that powers Plane's Pages Editor", "description": "Package that powers Plane's Pages Editor",
"main": "./dist/index.mjs", "main": "./dist/index.mjs",
"module": "./dist/index.mjs", "module": "./dist/index.mjs",
@ -63,4 +63,4 @@
"nextjs", "nextjs",
"react" "react"
] ]
} }

View File

@ -1,6 +1,6 @@
{ {
"name": "@plane/editor-extensions", "name": "@plane/editor-extensions",
"version": "0.1.0", "version": "0.14.0",
"description": "Package that powers Plane's Editor with extensions", "description": "Package that powers Plane's Editor with extensions",
"private": true, "private": true,
"main": "./dist/index.mjs", "main": "./dist/index.mjs",
@ -57,4 +57,4 @@
"nextjs", "nextjs",
"react" "react"
] ]
} }

View File

@ -1,6 +1,6 @@
{ {
"name": "@plane/lite-text-editor", "name": "@plane/lite-text-editor",
"version": "0.1.0", "version": "0.14.0",
"description": "Package that powers Plane's Comment Editor", "description": "Package that powers Plane's Comment Editor",
"private": true, "private": true,
"main": "./dist/index.mjs", "main": "./dist/index.mjs",
@ -52,4 +52,4 @@
"nextjs", "nextjs",
"react" "react"
] ]
} }

View File

@ -1,6 +1,6 @@
{ {
"name": "@plane/rich-text-editor", "name": "@plane/rich-text-editor",
"version": "0.1.0", "version": "0.14.0",
"description": "Rich Text Editor that powers Plane", "description": "Rich Text Editor that powers Plane",
"private": true, "private": true,
"main": "./dist/index.mjs", "main": "./dist/index.mjs",
@ -55,4 +55,4 @@
"nextjs", "nextjs",
"react" "react"
] ]
} }

View File

@ -1,6 +1,6 @@
{ {
"name": "@plane/editor-types", "name": "@plane/editor-types",
"version": "0.1.0", "version": "0.14.0",
"description": "Package that powers Plane's Editor with extensions", "description": "Package that powers Plane's Editor with extensions",
"private": true, "private": true,
"main": "./dist/index.mjs", "main": "./dist/index.mjs",
@ -48,4 +48,4 @@
"nextjs", "nextjs",
"react" "react"
] ]
} }

View File

@ -1,7 +1,7 @@
{ {
"name": "eslint-config-custom", "name": "eslint-config-custom",
"private": true, "private": true,
"version": "0.13.2", "version": "0.14.0",
"main": "index.js", "main": "index.js",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {

View File

@ -1,6 +1,6 @@
{ {
"name": "tailwind-config-custom", "name": "tailwind-config-custom",
"version": "0.13.2", "version": "0.14.0",
"description": "common tailwind configuration across monorepo", "description": "common tailwind configuration across monorepo",
"main": "index.js", "main": "index.js",
"private": true, "private": true,

View File

@ -1,6 +1,6 @@
{ {
"name": "tsconfig", "name": "tsconfig",
"version": "0.13.2", "version": "0.14.0",
"private": true, "private": true,
"files": [ "files": [
"base.json", "base.json",

View File

@ -2,7 +2,7 @@
"name": "@plane/ui", "name": "@plane/ui",
"description": "UI components shared across multiple apps internally", "description": "UI components shared across multiple apps internally",
"private": true, "private": true,
"version": "0.1.0", "version": "0.14.0",
"main": "./dist/index.js", "main": "./dist/index.js",
"module": "./dist/index.mjs", "module": "./dist/index.mjs",
"types": "./dist/index.d.ts", "types": "./dist/index.d.ts",
@ -38,4 +38,4 @@
"react-color": "^2.19.3", "react-color": "^2.19.3",
"react-popper": "^2.3.0" "react-popper": "^2.3.0"
} }
} }

View File

@ -1,6 +1,6 @@
{ {
"name": "space", "name": "space",
"version": "0.13.2", "version": "0.14.0",
"private": true, "private": true,
"scripts": { "scripts": {
"dev": "turbo run develop", "dev": "turbo run develop",

View File

@ -61,6 +61,8 @@ export const IssueDescriptionForm: FC<IssueDetailsProps> = (props) => {
description_html: issue.description_html, description_html: issue.description_html,
}); });
// adding issue.description_html or issue.name to dependency array causes
// editor rerendering on every save
useEffect(() => { useEffect(() => {
if (issue.id) { if (issue.id) {
setLocalIssueDescription({ id: issue.id, description_html: issue.description_html }); setLocalIssueDescription({ id: issue.id, description_html: issue.description_html });
@ -100,9 +102,13 @@ export const IssueDescriptionForm: FC<IssueDetailsProps> = (props) => {
}); });
}, [issue, reset]); }, [issue, reset]);
const debouncedFormSave = debounce(async () => { // ADDING handleDescriptionFormSubmit TO DEPENDENCY ARRAY PRODUCES ADVERSE EFFECTS
handleSubmit(handleDescriptionFormSubmit)().finally(() => setIsSubmitting("submitted")); const debouncedFormSave = useCallback(
}, 1500); debounce(async () => {
handleSubmit(handleDescriptionFormSubmit)().finally(() => setIsSubmitting("submitted"));
}, 1500),
[handleSubmit]
);
return ( return (
<div className="relative"> <div className="relative">

View File

@ -16,7 +16,6 @@ import {
IViewIssuesFilterStore, IViewIssuesFilterStore,
IViewIssuesStore, IViewIssuesStore,
} from "store/issues"; } from "store/issues";
import { IIssueCalendarViewStore } from "store/issue";
import { IQuickActionProps } from "../list/list-view-types"; import { IQuickActionProps } from "../list/list-view-types";
import { EIssueActions } from "../types"; import { EIssueActions } from "../types";
import { IGroupedIssues } from "store/issues/types"; import { IGroupedIssues } from "store/issues/types";
@ -28,7 +27,6 @@ interface IBaseCalendarRoot {
| IModuleIssuesFilterStore | IModuleIssuesFilterStore
| ICycleIssuesFilterStore | ICycleIssuesFilterStore
| IViewIssuesFilterStore; | IViewIssuesFilterStore;
calendarViewStore: IIssueCalendarViewStore;
QuickActions: FC<IQuickActionProps>; QuickActions: FC<IQuickActionProps>;
issueActions: { issueActions: {
[EIssueActions.DELETE]: (issue: IIssue) => Promise<void>; [EIssueActions.DELETE]: (issue: IIssue) => Promise<void>;
@ -77,13 +75,14 @@ export const BaseCalendarRoot = observer((props: IBaseCalendarRoot) => {
<div className="h-full w-full pt-4 bg-custom-background-100 overflow-hidden"> <div className="h-full w-full pt-4 bg-custom-background-100 overflow-hidden">
<DragDropContext onDragEnd={onDragEnd}> <DragDropContext onDragEnd={onDragEnd}>
<CalendarChart <CalendarChart
issuesFilterStore={issuesFilterStore}
issues={issues} issues={issues}
groupedIssueIds={groupedIssueIds} groupedIssueIds={groupedIssueIds}
layout={displayFilters?.calendar?.layout} layout={displayFilters?.calendar?.layout}
showWeekends={displayFilters?.calendar?.show_weekends ?? false} showWeekends={displayFilters?.calendar?.show_weekends ?? false}
quickActions={(issue, customActionButton) => ( quickActions={(issue, customActionButton) => (
<QuickActions <QuickActions
customActionButton={customActionButton} customActionButton={customActionButton}
issue={issue} issue={issue}
handleDelete={async () => handleIssues(issue.target_date ?? "", issue, EIssueActions.DELETE)} handleDelete={async () => handleIssues(issue.target_date ?? "", issue, EIssueActions.DELETE)}
handleUpdate={ handleUpdate={

View File

@ -10,8 +10,19 @@ import { Spinner } from "@plane/ui";
import { ICalendarWeek } from "./types"; import { ICalendarWeek } from "./types";
import { IIssue } from "types"; import { IIssue } from "types";
import { IGroupedIssues, IIssueResponse } from "store/issues/types"; import { IGroupedIssues, IIssueResponse } from "store/issues/types";
import {
ICycleIssuesFilterStore,
IModuleIssuesFilterStore,
IProjectIssuesFilterStore,
IViewIssuesFilterStore,
} from "store/issues";
type Props = { type Props = {
issuesFilterStore:
| IProjectIssuesFilterStore
| IModuleIssuesFilterStore
| ICycleIssuesFilterStore
| IViewIssuesFilterStore;
issues: IIssueResponse | undefined; issues: IIssueResponse | undefined;
groupedIssueIds: IGroupedIssues; groupedIssueIds: IGroupedIssues;
layout: "month" | "week" | undefined; layout: "month" | "week" | undefined;
@ -27,7 +38,8 @@ type Props = {
}; };
export const CalendarChart: React.FC<Props> = observer((props) => { export const CalendarChart: React.FC<Props> = observer((props) => {
const { issues, groupedIssueIds, layout, showWeekends, quickActions, quickAddCallback, viewId } = props; const { issuesFilterStore, issues, groupedIssueIds, layout, showWeekends, quickActions, quickAddCallback, viewId } =
props;
const { calendar: calendarStore } = useMobxStore(); const { calendar: calendarStore } = useMobxStore();
@ -45,7 +57,7 @@ export const CalendarChart: React.FC<Props> = observer((props) => {
return ( return (
<> <>
<div className="h-full w-full flex flex-col overflow-hidden"> <div className="h-full w-full flex flex-col overflow-hidden">
<CalendarHeader /> <CalendarHeader issuesFilterStore={issuesFilterStore} />
<CalendarWeekHeader isLoading={!issues} showWeekends={showWeekends} /> <CalendarWeekHeader isLoading={!issues} showWeekends={showWeekends} />
<div className="h-full w-full overflow-y-auto"> <div className="h-full w-full overflow-y-auto">
{layout === "month" && ( {layout === "month" && (
@ -53,6 +65,7 @@ export const CalendarChart: React.FC<Props> = observer((props) => {
{allWeeksOfActiveMonth && {allWeeksOfActiveMonth &&
Object.values(allWeeksOfActiveMonth).map((week: ICalendarWeek, weekIndex) => ( Object.values(allWeeksOfActiveMonth).map((week: ICalendarWeek, weekIndex) => (
<CalendarWeekDays <CalendarWeekDays
issuesFilterStore={issuesFilterStore}
key={weekIndex} key={weekIndex}
week={week} week={week}
issues={issues} issues={issues}
@ -67,6 +80,7 @@ export const CalendarChart: React.FC<Props> = observer((props) => {
)} )}
{layout === "week" && ( {layout === "week" && (
<CalendarWeekDays <CalendarWeekDays
issuesFilterStore={issuesFilterStore}
week={calendarStore.allDaysOfActiveWeek} week={calendarStore.allDaysOfActiveWeek}
issues={issues} issues={issues}
groupedIssueIds={groupedIssueIds} groupedIssueIds={groupedIssueIds}

View File

@ -11,8 +11,19 @@ import { renderDateFormat } from "helpers/date-time.helper";
import { MONTHS_LIST } from "constants/calendar"; import { MONTHS_LIST } from "constants/calendar";
import { IIssue } from "types"; import { IIssue } from "types";
import { IGroupedIssues, IIssueResponse } from "store/issues/types"; import { IGroupedIssues, IIssueResponse } from "store/issues/types";
import {
ICycleIssuesFilterStore,
IModuleIssuesFilterStore,
IProjectIssuesFilterStore,
IViewIssuesFilterStore,
} from "store/issues";
type Props = { type Props = {
issuesFilterStore:
| IProjectIssuesFilterStore
| IModuleIssuesFilterStore
| ICycleIssuesFilterStore
| IViewIssuesFilterStore;
date: ICalendarDate; date: ICalendarDate;
issues: IIssueResponse | undefined; issues: IIssueResponse | undefined;
groupedIssueIds: IGroupedIssues; groupedIssueIds: IGroupedIssues;
@ -28,11 +39,18 @@ type Props = {
}; };
export const CalendarDayTile: React.FC<Props> = observer((props) => { export const CalendarDayTile: React.FC<Props> = observer((props) => {
const { date, issues, groupedIssueIds, quickActions, enableQuickIssueCreate, quickAddCallback, viewId } = props; const {
issuesFilterStore,
date,
issues,
groupedIssueIds,
quickActions,
enableQuickIssueCreate,
quickAddCallback,
viewId,
} = props;
const { issueFilter: issueFilterStore } = useMobxStore(); const calendarLayout = issuesFilterStore?.issueFilters?.displayFilters?.calendar?.layout ?? "month";
const calendarLayout = issueFilterStore.userDisplayFilters.calendar?.layout ?? "month";
const issueIdList = groupedIssueIds ? groupedIssueIds[renderDateFormat(date.date)] : null; const issueIdList = groupedIssueIds ? groupedIssueIds[renderDateFormat(date.date)] : null;

View File

@ -13,12 +13,29 @@ import { Check, ChevronUp } from "lucide-react";
import { TCalendarLayouts } from "types"; import { TCalendarLayouts } from "types";
// constants // constants
import { CALENDAR_LAYOUTS } from "constants/calendar"; import { CALENDAR_LAYOUTS } from "constants/calendar";
import { EFilterType } from "store/issues/types";
import {
ICycleIssuesFilterStore,
IModuleIssuesFilterStore,
IProjectIssuesFilterStore,
IViewIssuesFilterStore,
} from "store/issues";
interface ICalendarHeader {
issuesFilterStore:
| IProjectIssuesFilterStore
| IModuleIssuesFilterStore
| ICycleIssuesFilterStore
| IViewIssuesFilterStore;
}
export const CalendarOptionsDropdown: React.FC<ICalendarHeader> = observer((props) => {
const { issuesFilterStore } = props;
export const CalendarOptionsDropdown: React.FC = observer(() => {
const router = useRouter(); const router = useRouter();
const { workspaceSlug, projectId } = router.query; const { workspaceSlug, projectId } = router.query;
const { issueFilter: issueFilterStore, calendar: calendarStore } = useMobxStore(); const { calendar: calendarStore } = useMobxStore();
const [referenceElement, setReferenceElement] = useState<HTMLButtonElement | null>(null); const [referenceElement, setReferenceElement] = useState<HTMLButtonElement | null>(null);
const [popperElement, setPopperElement] = useState<HTMLDivElement | null>(null); const [popperElement, setPopperElement] = useState<HTMLDivElement | null>(null);
@ -35,18 +52,16 @@ export const CalendarOptionsDropdown: React.FC = observer(() => {
], ],
}); });
const calendarLayout = issueFilterStore.userDisplayFilters.calendar?.layout ?? "month"; const calendarLayout = issuesFilterStore.issueFilters?.displayFilters?.calendar?.layout ?? "month";
const showWeekends = issueFilterStore.userDisplayFilters.calendar?.show_weekends ?? false; const showWeekends = issuesFilterStore.issueFilters?.displayFilters?.calendar?.show_weekends ?? false;
const handleLayoutChange = (layout: TCalendarLayouts) => { const handleLayoutChange = (layout: TCalendarLayouts) => {
if (!workspaceSlug || !projectId) return; if (!workspaceSlug || !projectId) return;
issueFilterStore.updateUserFilters(workspaceSlug.toString(), projectId.toString(), { issuesFilterStore.updateFilters(workspaceSlug.toString(), projectId.toString(), EFilterType.DISPLAY_FILTERS, {
display_filters: { calendar: {
calendar: { ...issuesFilterStore.issueFilters?.displayFilters?.calendar,
...issueFilterStore.userDisplayFilters.calendar, layout,
layout,
},
}, },
}); });
@ -56,16 +71,14 @@ export const CalendarOptionsDropdown: React.FC = observer(() => {
}; };
const handleToggleWeekends = () => { const handleToggleWeekends = () => {
const showWeekends = issueFilterStore.userDisplayFilters.calendar?.show_weekends ?? false; const showWeekends = issuesFilterStore.issueFilters?.displayFilters?.calendar?.show_weekends ?? false;
if (!workspaceSlug || !projectId) return; if (!workspaceSlug || !projectId) return;
issueFilterStore.updateUserFilters(workspaceSlug.toString(), projectId.toString(), { issuesFilterStore.updateFilters(workspaceSlug.toString(), projectId.toString(), EFilterType.DISPLAY_FILTERS, {
display_filters: { calendar: {
calendar: { ...issuesFilterStore.issueFilters?.displayFilters?.calendar,
...issueFilterStore.userDisplayFilters.calendar, show_weekends: !showWeekends,
show_weekends: !showWeekends,
},
}, },
}); });
}; };

View File

@ -6,11 +6,27 @@ import { useMobxStore } from "lib/mobx/store-provider";
import { CalendarMonthsDropdown, CalendarOptionsDropdown } from "components/issues"; import { CalendarMonthsDropdown, CalendarOptionsDropdown } from "components/issues";
// icons // icons
import { ChevronLeft, ChevronRight } from "lucide-react"; import { ChevronLeft, ChevronRight } from "lucide-react";
import {
ICycleIssuesFilterStore,
IModuleIssuesFilterStore,
IProjectIssuesFilterStore,
IViewIssuesFilterStore,
} from "store/issues";
export const CalendarHeader: React.FC = observer(() => { interface ICalendarHeader {
const { issueFilter: issueFilterStore, calendar: calendarStore } = useMobxStore(); issuesFilterStore:
| IProjectIssuesFilterStore
| IModuleIssuesFilterStore
| ICycleIssuesFilterStore
| IViewIssuesFilterStore;
}
const calendarLayout = issueFilterStore.userDisplayFilters.calendar?.layout ?? "month"; export const CalendarHeader: React.FC<ICalendarHeader> = observer((props) => {
const { issuesFilterStore } = props;
const { calendar: calendarStore } = useMobxStore();
const calendarLayout = issuesFilterStore.issueFilters?.displayFilters?.calendar?.layout ?? "month";
const { activeMonthDate, activeWeekDate } = calendarStore.calendarFilters; const { activeMonthDate, activeWeekDate } = calendarStore.calendarFilters;
@ -91,7 +107,7 @@ export const CalendarHeader: React.FC = observer(() => {
> >
Today Today
</button> </button>
<CalendarOptionsDropdown /> <CalendarOptionsDropdown issuesFilterStore={issuesFilterStore} />
</div> </div>
</div> </div>
); );

View File

@ -13,7 +13,6 @@ export const CycleCalendarLayout: React.FC = observer(() => {
const { const {
cycleIssues: cycleIssueStore, cycleIssues: cycleIssueStore,
cycleIssuesFilter: cycleIssueFilterStore, cycleIssuesFilter: cycleIssueFilterStore,
cycleIssueCalendarView: cycleIssueCalendarViewStore,
calendarHelpers: { handleDragDrop: handleCalenderDragDrop }, calendarHelpers: { handleDragDrop: handleCalenderDragDrop },
} = useMobxStore(); } = useMobxStore();
@ -62,7 +61,6 @@ export const CycleCalendarLayout: React.FC = observer(() => {
<BaseCalendarRoot <BaseCalendarRoot
issueStore={cycleIssueStore} issueStore={cycleIssueStore}
issuesFilterStore={cycleIssueFilterStore} issuesFilterStore={cycleIssueFilterStore}
calendarViewStore={cycleIssueCalendarViewStore}
QuickActions={CycleIssueQuickActions} QuickActions={CycleIssueQuickActions}
issueActions={issueActions} issueActions={issueActions}
viewId={cycleId.toString()} viewId={cycleId.toString()}

View File

@ -13,7 +13,6 @@ export const ModuleCalendarLayout: React.FC = observer(() => {
const { const {
moduleIssues: moduleIssueStore, moduleIssues: moduleIssueStore,
moduleIssuesFilter: moduleIssueFilterStore, moduleIssuesFilter: moduleIssueFilterStore,
moduleIssueCalendarView: moduleIssueCalendarViewStore,
calendarHelpers: { handleDragDrop: handleCalenderDragDrop }, calendarHelpers: { handleDragDrop: handleCalenderDragDrop },
} = useMobxStore(); } = useMobxStore();
@ -56,7 +55,6 @@ export const ModuleCalendarLayout: React.FC = observer(() => {
<BaseCalendarRoot <BaseCalendarRoot
issueStore={moduleIssueStore} issueStore={moduleIssueStore}
issuesFilterStore={moduleIssueFilterStore} issuesFilterStore={moduleIssueFilterStore}
calendarViewStore={moduleIssueCalendarViewStore}
QuickActions={ModuleIssueQuickActions} QuickActions={ModuleIssueQuickActions}
issueActions={issueActions} issueActions={issueActions}
viewId={moduleId} viewId={moduleId}

View File

@ -14,7 +14,6 @@ export const CalendarLayout: React.FC = observer(() => {
const { const {
projectIssues: issueStore, projectIssues: issueStore,
issueCalendarView: issueCalendarViewStore,
projectIssuesFilter: projectIssueFiltersStore, projectIssuesFilter: projectIssueFiltersStore,
calendarHelpers: { handleDragDrop: handleCalenderDragDrop }, calendarHelpers: { handleDragDrop: handleCalenderDragDrop },
} = useMobxStore(); } = useMobxStore();
@ -49,7 +48,6 @@ export const CalendarLayout: React.FC = observer(() => {
<BaseCalendarRoot <BaseCalendarRoot
issueStore={issueStore} issueStore={issueStore}
issuesFilterStore={projectIssueFiltersStore} issuesFilterStore={projectIssueFiltersStore}
calendarViewStore={issueCalendarViewStore}
QuickActions={ProjectIssueQuickActions} QuickActions={ProjectIssueQuickActions}
issueActions={issueActions} issueActions={issueActions}
handleDragDrop={handleDragDrop} handleDragDrop={handleDragDrop}

View File

@ -13,7 +13,6 @@ export const ProjectViewCalendarLayout: React.FC = observer(() => {
const { const {
viewIssues: projectViewIssuesStore, viewIssues: projectViewIssuesStore,
viewIssuesFilter: projectIssueViewFiltersStore, viewIssuesFilter: projectIssueViewFiltersStore,
projectViewIssueCalendarView: projectViewIssueCalendarViewStore,
calendarHelpers: { handleDragDrop: handleCalenderDragDrop }, calendarHelpers: { handleDragDrop: handleCalenderDragDrop },
} = useMobxStore(); } = useMobxStore();
@ -50,7 +49,6 @@ export const ProjectViewCalendarLayout: React.FC = observer(() => {
<BaseCalendarRoot <BaseCalendarRoot
issueStore={projectViewIssuesStore} issueStore={projectViewIssuesStore}
issuesFilterStore={projectIssueViewFiltersStore} issuesFilterStore={projectIssueViewFiltersStore}
calendarViewStore={projectViewIssueCalendarViewStore}
QuickActions={ProjectIssueQuickActions} QuickActions={ProjectIssueQuickActions}
issueActions={issueActions} issueActions={issueActions}
handleDragDrop={handleDragDrop} handleDragDrop={handleDragDrop}

View File

@ -1,7 +1,4 @@
import { observer } from "mobx-react-lite"; import { observer } from "mobx-react-lite";
// mobx store
import { useMobxStore } from "lib/mobx/store-provider";
// components // components
import { CalendarDayTile } from "components/issues"; import { CalendarDayTile } from "components/issues";
// helpers // helpers
@ -10,8 +7,19 @@ import { renderDateFormat } from "helpers/date-time.helper";
import { ICalendarDate, ICalendarWeek } from "./types"; import { ICalendarDate, ICalendarWeek } from "./types";
import { IIssue } from "types"; import { IIssue } from "types";
import { IGroupedIssues, IIssueResponse } from "store/issues/types"; import { IGroupedIssues, IIssueResponse } from "store/issues/types";
import {
ICycleIssuesFilterStore,
IModuleIssuesFilterStore,
IProjectIssuesFilterStore,
IViewIssuesFilterStore,
} from "store/issues";
type Props = { type Props = {
issuesFilterStore:
| IProjectIssuesFilterStore
| IModuleIssuesFilterStore
| ICycleIssuesFilterStore
| IViewIssuesFilterStore;
issues: IIssueResponse | undefined; issues: IIssueResponse | undefined;
groupedIssueIds: IGroupedIssues; groupedIssueIds: IGroupedIssues;
week: ICalendarWeek | undefined; week: ICalendarWeek | undefined;
@ -27,12 +35,19 @@ type Props = {
}; };
export const CalendarWeekDays: React.FC<Props> = observer((props) => { export const CalendarWeekDays: React.FC<Props> = observer((props) => {
const { issues, groupedIssueIds, week, quickActions, enableQuickIssueCreate, quickAddCallback, viewId } = props; const {
issuesFilterStore,
issues,
groupedIssueIds,
week,
quickActions,
enableQuickIssueCreate,
quickAddCallback,
viewId,
} = props;
const { issueFilter: issueFilterStore } = useMobxStore(); const calendarLayout = issuesFilterStore?.issueFilters?.displayFilters?.calendar?.layout ?? "month";
const showWeekends = issuesFilterStore?.issueFilters?.displayFilters?.calendar?.show_weekends ?? false;
const calendarLayout = issueFilterStore.userDisplayFilters.calendar?.layout ?? "month";
const showWeekends = issueFilterStore.userDisplayFilters.calendar?.show_weekends ?? false;
if (!week) return null; if (!week) return null;
@ -47,6 +62,7 @@ export const CalendarWeekDays: React.FC<Props> = observer((props) => {
return ( return (
<CalendarDayTile <CalendarDayTile
issuesFilterStore={issuesFilterStore}
key={renderDateFormat(date.date)} key={renderDateFormat(date.date)}
date={date} date={date}
issues={issues} issues={issues}

View File

@ -147,22 +147,22 @@ const GroupByKanBan: React.FC<IGroupByKanBan> = observer((props) => {
</div> </div>
)} )}
</Droppable> </Droppable>
</div>
<div className="flex-shrink-0 w-full bg-custom-background-90 py-1 sticky bottom-0 z-[0]"> <div className="flex-shrink-0 w-full bg-custom-background-90 py-1 sticky bottom-0 z-[0]">
{enableQuickIssueCreate && ( {enableQuickIssueCreate && (
<KanBanQuickAddIssueForm <KanBanQuickAddIssueForm
formKey="name" formKey="name"
groupId={getValueFromObject(_list, listKey) as string} groupId={getValueFromObject(_list, listKey) as string}
subGroupId={sub_group_id} subGroupId={sub_group_id}
prePopulatedData={{ prePopulatedData={{
...(group_by && { [group_by]: getValueFromObject(_list, listKey) }), ...(group_by && { [group_by]: getValueFromObject(_list, listKey) }),
...(sub_group_by && sub_group_id !== "null" && { [sub_group_by]: sub_group_id }), ...(sub_group_by && sub_group_id !== "null" && { [sub_group_by]: sub_group_id }),
}} }}
quickAddCallback={quickAddCallback} quickAddCallback={quickAddCallback}
viewId={viewId} viewId={viewId}
/> />
)} )}
</div>
</div> </div>
{/* {isDragStarted && isDragDisabled && ( {/* {isDragStarted && isDragDisabled && (

View File

@ -24,6 +24,7 @@ export const IssueBlocksList: FC<Props> = (props) => {
{issueIds && issueIds.length > 0 ? ( {issueIds && issueIds.length > 0 ? (
issueIds.map( issueIds.map(
(issueId: string) => (issueId: string) =>
issueId != undefined &&
issues[issueId] && ( issues[issueId] && (
<IssueBlock <IssueBlock
key={issues[issueId].id} key={issues[issueId].id}

View File

@ -87,16 +87,22 @@ export const PeekOverviewIssueDetails: FC<IPeekOverviewIssueDetails> = (props) =
description_html: issue.description_html, description_html: issue.description_html,
}); });
// adding issue.description_html or issue.name to dependency array causes
// editor rerendering on every save
useEffect(() => { useEffect(() => {
if (issue.id) { if (issue.id) {
setLocalIssueDescription({ id: issue.id, description_html: issue.description_html }); setLocalIssueDescription({ id: issue.id, description_html: issue.description_html });
setLocalTitleValue(issue.name); setLocalTitleValue(issue.name);
} }
}, [issue.id, issue.description_html, issue.name]); }, [issue.id]);
const debouncedFormSave = debounce(async () => { // ADDING handleDescriptionFormSubmit TO DEPENDENCY ARRAY PRODUCES ADVERSE EFFECTS
handleSubmit(handleDescriptionFormSubmit)().finally(() => setIsSubmitting("submitted")); const debouncedFormSave = useCallback(
}, 1500); debounce(async () => {
handleSubmit(handleDescriptionFormSubmit)().finally(() => setIsSubmitting("submitted"));
}, 1500),
[handleSubmit]
);
useEffect(() => { useEffect(() => {
if (isSubmitting === "submitted") { if (isSubmitting === "submitted") {

View File

@ -1,6 +1,6 @@
{ {
"name": "web", "name": "web",
"version": "0.13.2", "version": "0.14.0",
"private": true, "private": true,
"scripts": { "scripts": {
"dev": "turbo run develop", "dev": "turbo run develop",

View File

@ -1,4 +1,4 @@
import React, { useEffect, useRef, useState, ReactElement } from "react"; import React, { useEffect, useRef, useState, ReactElement, useCallback } from "react";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import useSWR, { MutatorOptions } from "swr"; import useSWR, { MutatorOptions } from "swr";
import { Controller, useForm } from "react-hook-form"; import { Controller, useForm } from "react-hook-form";
@ -59,7 +59,7 @@ const PageDetailsPage: NextPageWithLayout = observer(() => {
const { user } = useUser(); const { user } = useUser();
const { handleSubmit, reset, setValue, watch, getValues, control } = useForm<IPage>({ const { handleSubmit, setValue, watch, getValues, control } = useForm<IPage>({
defaultValues: { name: "", description_html: "" }, defaultValues: { name: "", description_html: "" },
}); });
@ -152,6 +152,8 @@ const PageDetailsPage: NextPageWithLayout = observer(() => {
} }
}, [isSubmitting, setShowAlert]); }, [isSubmitting, setShowAlert]);
// adding pageDetails.description_html to dependency array causes
// editor rerendering on every save
useEffect(() => { useEffect(() => {
if (pageDetails?.description_html) { if (pageDetails?.description_html) {
setLocalIssueDescription({ id: pageId as string, description_html: pageDetails.description_html }); setLocalIssueDescription({ id: pageId as string, description_html: pageDetails.description_html });
@ -326,9 +328,13 @@ const PageDetailsPage: NextPageWithLayout = observer(() => {
description_html: "", description_html: "",
}); });
const debouncedFormSave = debounce(async () => { // ADDING updatePage TO DEPENDENCY ARRAY PRODUCES ADVERSE EFFECTS
handleSubmit(updatePage)().finally(() => setIsSubmitting("submitted")); const debouncedFormSave = useCallback(
}, 1500); debounce(async () => {
handleSubmit(updatePage)().finally(() => setIsSubmitting("submitted"));
}, 1500),
[handleSubmit]
);
if (error) if (error)
return ( return (