forked from github/plane
Merge pull request #3046 from makeplane/promote/dev-preview
promote: develop to preview
This commit is contained in:
commit
d16a6402cd
@ -27,7 +27,8 @@ WORKDIR /code
|
||||
COPY requirements.txt ./requirements.txt
|
||||
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 && \
|
||||
adduser -S captain -G plane
|
||||
|
@ -1,4 +1,4 @@
|
||||
{
|
||||
"name": "plane-api",
|
||||
"version": "0.13.2"
|
||||
"name": "plane-api",
|
||||
"version": "0.14.0"
|
||||
}
|
@ -90,8 +90,8 @@ class ConfigurationEndpoint(BaseAPIView):
|
||||
|
||||
data = {}
|
||||
# Authentication
|
||||
data["google_client_id"] = GOOGLE_CLIENT_ID
|
||||
data["github_client_id"] = GITHUB_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 if GITHUB_CLIENT_ID and GITHUB_CLIENT_ID != "\"\"" else None
|
||||
data["github_app_name"] = GITHUB_APP_NAME
|
||||
data["magic_login"] = (
|
||||
bool(EMAIL_HOST_USER) and bool(EMAIL_HOST_PASSWORD)
|
||||
@ -106,7 +106,7 @@ class ConfigurationEndpoint(BaseAPIView):
|
||||
data["posthog_host"] = POSTHOG_HOST
|
||||
|
||||
# Unsplash
|
||||
data["has_unsplash_configured"] = UNSPLASH_ACCESS_KEY
|
||||
data["has_unsplash_configured"] = bool(UNSPLASH_ACCESS_KEY)
|
||||
|
||||
# Open AI settings
|
||||
data["has_openai_configured"] = bool(OPENAI_API_KEY)
|
||||
|
@ -86,7 +86,14 @@ def get_access_token(request_token: str, client_id: str) -> str:
|
||||
if not request_token:
|
||||
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}"
|
||||
headers = {"accept": "application/json"}
|
||||
@ -299,7 +306,7 @@ class OauthEndpoint(BaseAPIView):
|
||||
return Response(data, status=status.HTTP_200_OK)
|
||||
|
||||
except User.DoesNotExist:
|
||||
ENABLE_SIGNUP, = get_configuration_value(
|
||||
(ENABLE_SIGNUP,) = get_configuration_value(
|
||||
[
|
||||
{
|
||||
"key": "ENABLE_SIGNUP",
|
||||
|
@ -49,6 +49,10 @@ class UserEndpoint(BaseViewSet):
|
||||
# Check all workspace user is active
|
||||
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 = []
|
||||
workspaces_to_deactivate = []
|
||||
|
||||
|
@ -221,37 +221,6 @@ class InstanceAdminSignInEndpoint(BaseAPIView):
|
||||
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
|
||||
user.is_active = True
|
||||
user.last_active = timezone.now()
|
||||
|
@ -41,7 +41,7 @@ x-app-env : &app-env
|
||||
- DEFAULT_PASSWORD=${DEFAULT_PASSWORD:-password123}
|
||||
# OPENAI SETTINGS - Deprecated can be configured through admin panel
|
||||
- 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"}
|
||||
# LOGIN/SIGNUP SETTINGS - Deprecated can be configured through admin panel
|
||||
- ENABLE_SIGNUP=${ENABLE_SIGNUP:-1}
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"repository": "https://github.com/makeplane/plane.git",
|
||||
"version": "0.13.2",
|
||||
"version": "0.14.0",
|
||||
"license": "AGPL-3.0",
|
||||
"private": true,
|
||||
"workspaces": [
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@plane/editor-core",
|
||||
"version": "0.0.1",
|
||||
"version": "0.14.0",
|
||||
"description": "Core Editor that powers Plane",
|
||||
"private": true,
|
||||
"main": "./dist/index.mjs",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@plane/document-editor",
|
||||
"version": "0.1.0",
|
||||
"version": "0.14.0",
|
||||
"description": "Package that powers Plane's Pages Editor",
|
||||
"main": "./dist/index.mjs",
|
||||
"module": "./dist/index.mjs",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@plane/editor-extensions",
|
||||
"version": "0.1.0",
|
||||
"version": "0.14.0",
|
||||
"description": "Package that powers Plane's Editor with extensions",
|
||||
"private": true,
|
||||
"main": "./dist/index.mjs",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@plane/lite-text-editor",
|
||||
"version": "0.1.0",
|
||||
"version": "0.14.0",
|
||||
"description": "Package that powers Plane's Comment Editor",
|
||||
"private": true,
|
||||
"main": "./dist/index.mjs",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@plane/rich-text-editor",
|
||||
"version": "0.1.0",
|
||||
"version": "0.14.0",
|
||||
"description": "Rich Text Editor that powers Plane",
|
||||
"private": true,
|
||||
"main": "./dist/index.mjs",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@plane/editor-types",
|
||||
"version": "0.1.0",
|
||||
"version": "0.14.0",
|
||||
"description": "Package that powers Plane's Editor with extensions",
|
||||
"private": true,
|
||||
"main": "./dist/index.mjs",
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "eslint-config-custom",
|
||||
"private": true,
|
||||
"version": "0.13.2",
|
||||
"version": "0.14.0",
|
||||
"main": "index.js",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "tailwind-config-custom",
|
||||
"version": "0.13.2",
|
||||
"version": "0.14.0",
|
||||
"description": "common tailwind configuration across monorepo",
|
||||
"main": "index.js",
|
||||
"private": true,
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "tsconfig",
|
||||
"version": "0.13.2",
|
||||
"version": "0.14.0",
|
||||
"private": true,
|
||||
"files": [
|
||||
"base.json",
|
||||
|
@ -2,7 +2,7 @@
|
||||
"name": "@plane/ui",
|
||||
"description": "UI components shared across multiple apps internally",
|
||||
"private": true,
|
||||
"version": "0.1.0",
|
||||
"version": "0.14.0",
|
||||
"main": "./dist/index.js",
|
||||
"module": "./dist/index.mjs",
|
||||
"types": "./dist/index.d.ts",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "space",
|
||||
"version": "0.13.2",
|
||||
"version": "0.14.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "turbo run develop",
|
||||
|
@ -61,6 +61,8 @@ export const IssueDescriptionForm: FC<IssueDetailsProps> = (props) => {
|
||||
description_html: issue.description_html,
|
||||
});
|
||||
|
||||
// adding issue.description_html or issue.name to dependency array causes
|
||||
// editor rerendering on every save
|
||||
useEffect(() => {
|
||||
if (issue.id) {
|
||||
setLocalIssueDescription({ id: issue.id, description_html: issue.description_html });
|
||||
@ -100,9 +102,13 @@ export const IssueDescriptionForm: FC<IssueDetailsProps> = (props) => {
|
||||
});
|
||||
}, [issue, reset]);
|
||||
|
||||
const debouncedFormSave = debounce(async () => {
|
||||
handleSubmit(handleDescriptionFormSubmit)().finally(() => setIsSubmitting("submitted"));
|
||||
}, 1500);
|
||||
// ADDING handleDescriptionFormSubmit TO DEPENDENCY ARRAY PRODUCES ADVERSE EFFECTS
|
||||
const debouncedFormSave = useCallback(
|
||||
debounce(async () => {
|
||||
handleSubmit(handleDescriptionFormSubmit)().finally(() => setIsSubmitting("submitted"));
|
||||
}, 1500),
|
||||
[handleSubmit]
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="relative">
|
||||
|
@ -16,7 +16,6 @@ import {
|
||||
IViewIssuesFilterStore,
|
||||
IViewIssuesStore,
|
||||
} from "store/issues";
|
||||
import { IIssueCalendarViewStore } from "store/issue";
|
||||
import { IQuickActionProps } from "../list/list-view-types";
|
||||
import { EIssueActions } from "../types";
|
||||
import { IGroupedIssues } from "store/issues/types";
|
||||
@ -28,7 +27,6 @@ interface IBaseCalendarRoot {
|
||||
| IModuleIssuesFilterStore
|
||||
| ICycleIssuesFilterStore
|
||||
| IViewIssuesFilterStore;
|
||||
calendarViewStore: IIssueCalendarViewStore;
|
||||
QuickActions: FC<IQuickActionProps>;
|
||||
issueActions: {
|
||||
[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">
|
||||
<DragDropContext onDragEnd={onDragEnd}>
|
||||
<CalendarChart
|
||||
issuesFilterStore={issuesFilterStore}
|
||||
issues={issues}
|
||||
groupedIssueIds={groupedIssueIds}
|
||||
layout={displayFilters?.calendar?.layout}
|
||||
showWeekends={displayFilters?.calendar?.show_weekends ?? false}
|
||||
quickActions={(issue, customActionButton) => (
|
||||
<QuickActions
|
||||
customActionButton={customActionButton}
|
||||
customActionButton={customActionButton}
|
||||
issue={issue}
|
||||
handleDelete={async () => handleIssues(issue.target_date ?? "", issue, EIssueActions.DELETE)}
|
||||
handleUpdate={
|
||||
|
@ -10,8 +10,19 @@ import { Spinner } from "@plane/ui";
|
||||
import { ICalendarWeek } from "./types";
|
||||
import { IIssue } from "types";
|
||||
import { IGroupedIssues, IIssueResponse } from "store/issues/types";
|
||||
import {
|
||||
ICycleIssuesFilterStore,
|
||||
IModuleIssuesFilterStore,
|
||||
IProjectIssuesFilterStore,
|
||||
IViewIssuesFilterStore,
|
||||
} from "store/issues";
|
||||
|
||||
type Props = {
|
||||
issuesFilterStore:
|
||||
| IProjectIssuesFilterStore
|
||||
| IModuleIssuesFilterStore
|
||||
| ICycleIssuesFilterStore
|
||||
| IViewIssuesFilterStore;
|
||||
issues: IIssueResponse | undefined;
|
||||
groupedIssueIds: IGroupedIssues;
|
||||
layout: "month" | "week" | undefined;
|
||||
@ -27,7 +38,8 @@ type 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();
|
||||
|
||||
@ -45,7 +57,7 @@ export const CalendarChart: React.FC<Props> = observer((props) => {
|
||||
return (
|
||||
<>
|
||||
<div className="h-full w-full flex flex-col overflow-hidden">
|
||||
<CalendarHeader />
|
||||
<CalendarHeader issuesFilterStore={issuesFilterStore} />
|
||||
<CalendarWeekHeader isLoading={!issues} showWeekends={showWeekends} />
|
||||
<div className="h-full w-full overflow-y-auto">
|
||||
{layout === "month" && (
|
||||
@ -53,6 +65,7 @@ export const CalendarChart: React.FC<Props> = observer((props) => {
|
||||
{allWeeksOfActiveMonth &&
|
||||
Object.values(allWeeksOfActiveMonth).map((week: ICalendarWeek, weekIndex) => (
|
||||
<CalendarWeekDays
|
||||
issuesFilterStore={issuesFilterStore}
|
||||
key={weekIndex}
|
||||
week={week}
|
||||
issues={issues}
|
||||
@ -67,6 +80,7 @@ export const CalendarChart: React.FC<Props> = observer((props) => {
|
||||
)}
|
||||
{layout === "week" && (
|
||||
<CalendarWeekDays
|
||||
issuesFilterStore={issuesFilterStore}
|
||||
week={calendarStore.allDaysOfActiveWeek}
|
||||
issues={issues}
|
||||
groupedIssueIds={groupedIssueIds}
|
||||
|
@ -11,8 +11,19 @@ import { renderDateFormat } from "helpers/date-time.helper";
|
||||
import { MONTHS_LIST } from "constants/calendar";
|
||||
import { IIssue } from "types";
|
||||
import { IGroupedIssues, IIssueResponse } from "store/issues/types";
|
||||
import {
|
||||
ICycleIssuesFilterStore,
|
||||
IModuleIssuesFilterStore,
|
||||
IProjectIssuesFilterStore,
|
||||
IViewIssuesFilterStore,
|
||||
} from "store/issues";
|
||||
|
||||
type Props = {
|
||||
issuesFilterStore:
|
||||
| IProjectIssuesFilterStore
|
||||
| IModuleIssuesFilterStore
|
||||
| ICycleIssuesFilterStore
|
||||
| IViewIssuesFilterStore;
|
||||
date: ICalendarDate;
|
||||
issues: IIssueResponse | undefined;
|
||||
groupedIssueIds: IGroupedIssues;
|
||||
@ -28,11 +39,18 @@ type 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 = issueFilterStore.userDisplayFilters.calendar?.layout ?? "month";
|
||||
const calendarLayout = issuesFilterStore?.issueFilters?.displayFilters?.calendar?.layout ?? "month";
|
||||
|
||||
const issueIdList = groupedIssueIds ? groupedIssueIds[renderDateFormat(date.date)] : null;
|
||||
|
||||
|
@ -13,12 +13,29 @@ import { Check, ChevronUp } from "lucide-react";
|
||||
import { TCalendarLayouts } from "types";
|
||||
// constants
|
||||
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 { workspaceSlug, projectId } = router.query;
|
||||
|
||||
const { issueFilter: issueFilterStore, calendar: calendarStore } = useMobxStore();
|
||||
const { calendar: calendarStore } = useMobxStore();
|
||||
|
||||
const [referenceElement, setReferenceElement] = useState<HTMLButtonElement | 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 showWeekends = issueFilterStore.userDisplayFilters.calendar?.show_weekends ?? false;
|
||||
const calendarLayout = issuesFilterStore.issueFilters?.displayFilters?.calendar?.layout ?? "month";
|
||||
const showWeekends = issuesFilterStore.issueFilters?.displayFilters?.calendar?.show_weekends ?? false;
|
||||
|
||||
const handleLayoutChange = (layout: TCalendarLayouts) => {
|
||||
if (!workspaceSlug || !projectId) return;
|
||||
|
||||
issueFilterStore.updateUserFilters(workspaceSlug.toString(), projectId.toString(), {
|
||||
display_filters: {
|
||||
calendar: {
|
||||
...issueFilterStore.userDisplayFilters.calendar,
|
||||
layout,
|
||||
},
|
||||
issuesFilterStore.updateFilters(workspaceSlug.toString(), projectId.toString(), EFilterType.DISPLAY_FILTERS, {
|
||||
calendar: {
|
||||
...issuesFilterStore.issueFilters?.displayFilters?.calendar,
|
||||
layout,
|
||||
},
|
||||
});
|
||||
|
||||
@ -56,16 +71,14 @@ export const CalendarOptionsDropdown: React.FC = observer(() => {
|
||||
};
|
||||
|
||||
const handleToggleWeekends = () => {
|
||||
const showWeekends = issueFilterStore.userDisplayFilters.calendar?.show_weekends ?? false;
|
||||
const showWeekends = issuesFilterStore.issueFilters?.displayFilters?.calendar?.show_weekends ?? false;
|
||||
|
||||
if (!workspaceSlug || !projectId) return;
|
||||
|
||||
issueFilterStore.updateUserFilters(workspaceSlug.toString(), projectId.toString(), {
|
||||
display_filters: {
|
||||
calendar: {
|
||||
...issueFilterStore.userDisplayFilters.calendar,
|
||||
show_weekends: !showWeekends,
|
||||
},
|
||||
issuesFilterStore.updateFilters(workspaceSlug.toString(), projectId.toString(), EFilterType.DISPLAY_FILTERS, {
|
||||
calendar: {
|
||||
...issuesFilterStore.issueFilters?.displayFilters?.calendar,
|
||||
show_weekends: !showWeekends,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
@ -6,11 +6,27 @@ import { useMobxStore } from "lib/mobx/store-provider";
|
||||
import { CalendarMonthsDropdown, CalendarOptionsDropdown } from "components/issues";
|
||||
// icons
|
||||
import { ChevronLeft, ChevronRight } from "lucide-react";
|
||||
import {
|
||||
ICycleIssuesFilterStore,
|
||||
IModuleIssuesFilterStore,
|
||||
IProjectIssuesFilterStore,
|
||||
IViewIssuesFilterStore,
|
||||
} from "store/issues";
|
||||
|
||||
export const CalendarHeader: React.FC = observer(() => {
|
||||
const { issueFilter: issueFilterStore, calendar: calendarStore } = useMobxStore();
|
||||
interface ICalendarHeader {
|
||||
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;
|
||||
|
||||
@ -91,7 +107,7 @@ export const CalendarHeader: React.FC = observer(() => {
|
||||
>
|
||||
Today
|
||||
</button>
|
||||
<CalendarOptionsDropdown />
|
||||
<CalendarOptionsDropdown issuesFilterStore={issuesFilterStore} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -13,7 +13,6 @@ export const CycleCalendarLayout: React.FC = observer(() => {
|
||||
const {
|
||||
cycleIssues: cycleIssueStore,
|
||||
cycleIssuesFilter: cycleIssueFilterStore,
|
||||
cycleIssueCalendarView: cycleIssueCalendarViewStore,
|
||||
calendarHelpers: { handleDragDrop: handleCalenderDragDrop },
|
||||
} = useMobxStore();
|
||||
|
||||
@ -62,7 +61,6 @@ export const CycleCalendarLayout: React.FC = observer(() => {
|
||||
<BaseCalendarRoot
|
||||
issueStore={cycleIssueStore}
|
||||
issuesFilterStore={cycleIssueFilterStore}
|
||||
calendarViewStore={cycleIssueCalendarViewStore}
|
||||
QuickActions={CycleIssueQuickActions}
|
||||
issueActions={issueActions}
|
||||
viewId={cycleId.toString()}
|
||||
|
@ -13,7 +13,6 @@ export const ModuleCalendarLayout: React.FC = observer(() => {
|
||||
const {
|
||||
moduleIssues: moduleIssueStore,
|
||||
moduleIssuesFilter: moduleIssueFilterStore,
|
||||
moduleIssueCalendarView: moduleIssueCalendarViewStore,
|
||||
calendarHelpers: { handleDragDrop: handleCalenderDragDrop },
|
||||
} = useMobxStore();
|
||||
|
||||
@ -56,7 +55,6 @@ export const ModuleCalendarLayout: React.FC = observer(() => {
|
||||
<BaseCalendarRoot
|
||||
issueStore={moduleIssueStore}
|
||||
issuesFilterStore={moduleIssueFilterStore}
|
||||
calendarViewStore={moduleIssueCalendarViewStore}
|
||||
QuickActions={ModuleIssueQuickActions}
|
||||
issueActions={issueActions}
|
||||
viewId={moduleId}
|
||||
|
@ -14,7 +14,6 @@ export const CalendarLayout: React.FC = observer(() => {
|
||||
|
||||
const {
|
||||
projectIssues: issueStore,
|
||||
issueCalendarView: issueCalendarViewStore,
|
||||
projectIssuesFilter: projectIssueFiltersStore,
|
||||
calendarHelpers: { handleDragDrop: handleCalenderDragDrop },
|
||||
} = useMobxStore();
|
||||
@ -49,7 +48,6 @@ export const CalendarLayout: React.FC = observer(() => {
|
||||
<BaseCalendarRoot
|
||||
issueStore={issueStore}
|
||||
issuesFilterStore={projectIssueFiltersStore}
|
||||
calendarViewStore={issueCalendarViewStore}
|
||||
QuickActions={ProjectIssueQuickActions}
|
||||
issueActions={issueActions}
|
||||
handleDragDrop={handleDragDrop}
|
||||
|
@ -13,7 +13,6 @@ export const ProjectViewCalendarLayout: React.FC = observer(() => {
|
||||
const {
|
||||
viewIssues: projectViewIssuesStore,
|
||||
viewIssuesFilter: projectIssueViewFiltersStore,
|
||||
projectViewIssueCalendarView: projectViewIssueCalendarViewStore,
|
||||
calendarHelpers: { handleDragDrop: handleCalenderDragDrop },
|
||||
} = useMobxStore();
|
||||
|
||||
@ -50,7 +49,6 @@ export const ProjectViewCalendarLayout: React.FC = observer(() => {
|
||||
<BaseCalendarRoot
|
||||
issueStore={projectViewIssuesStore}
|
||||
issuesFilterStore={projectIssueViewFiltersStore}
|
||||
calendarViewStore={projectViewIssueCalendarViewStore}
|
||||
QuickActions={ProjectIssueQuickActions}
|
||||
issueActions={issueActions}
|
||||
handleDragDrop={handleDragDrop}
|
||||
|
@ -1,7 +1,4 @@
|
||||
import { observer } from "mobx-react-lite";
|
||||
|
||||
// mobx store
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
// components
|
||||
import { CalendarDayTile } from "components/issues";
|
||||
// helpers
|
||||
@ -10,8 +7,19 @@ import { renderDateFormat } from "helpers/date-time.helper";
|
||||
import { ICalendarDate, ICalendarWeek } from "./types";
|
||||
import { IIssue } from "types";
|
||||
import { IGroupedIssues, IIssueResponse } from "store/issues/types";
|
||||
import {
|
||||
ICycleIssuesFilterStore,
|
||||
IModuleIssuesFilterStore,
|
||||
IProjectIssuesFilterStore,
|
||||
IViewIssuesFilterStore,
|
||||
} from "store/issues";
|
||||
|
||||
type Props = {
|
||||
issuesFilterStore:
|
||||
| IProjectIssuesFilterStore
|
||||
| IModuleIssuesFilterStore
|
||||
| ICycleIssuesFilterStore
|
||||
| IViewIssuesFilterStore;
|
||||
issues: IIssueResponse | undefined;
|
||||
groupedIssueIds: IGroupedIssues;
|
||||
week: ICalendarWeek | undefined;
|
||||
@ -27,12 +35,19 @@ type 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 = issueFilterStore.userDisplayFilters.calendar?.layout ?? "month";
|
||||
const showWeekends = issueFilterStore.userDisplayFilters.calendar?.show_weekends ?? false;
|
||||
const calendarLayout = issuesFilterStore?.issueFilters?.displayFilters?.calendar?.layout ?? "month";
|
||||
const showWeekends = issuesFilterStore?.issueFilters?.displayFilters?.calendar?.show_weekends ?? false;
|
||||
|
||||
if (!week) return null;
|
||||
|
||||
@ -47,6 +62,7 @@ export const CalendarWeekDays: React.FC<Props> = observer((props) => {
|
||||
|
||||
return (
|
||||
<CalendarDayTile
|
||||
issuesFilterStore={issuesFilterStore}
|
||||
key={renderDateFormat(date.date)}
|
||||
date={date}
|
||||
issues={issues}
|
||||
|
@ -147,22 +147,22 @@ const GroupByKanBan: React.FC<IGroupByKanBan> = observer((props) => {
|
||||
</div>
|
||||
)}
|
||||
</Droppable>
|
||||
</div>
|
||||
|
||||
<div className="flex-shrink-0 w-full bg-custom-background-90 py-1 sticky bottom-0 z-[0]">
|
||||
{enableQuickIssueCreate && (
|
||||
<KanBanQuickAddIssueForm
|
||||
formKey="name"
|
||||
groupId={getValueFromObject(_list, listKey) as string}
|
||||
subGroupId={sub_group_id}
|
||||
prePopulatedData={{
|
||||
...(group_by && { [group_by]: getValueFromObject(_list, listKey) }),
|
||||
...(sub_group_by && sub_group_id !== "null" && { [sub_group_by]: sub_group_id }),
|
||||
}}
|
||||
quickAddCallback={quickAddCallback}
|
||||
viewId={viewId}
|
||||
/>
|
||||
)}
|
||||
<div className="flex-shrink-0 w-full bg-custom-background-90 py-1 sticky bottom-0 z-[0]">
|
||||
{enableQuickIssueCreate && (
|
||||
<KanBanQuickAddIssueForm
|
||||
formKey="name"
|
||||
groupId={getValueFromObject(_list, listKey) as string}
|
||||
subGroupId={sub_group_id}
|
||||
prePopulatedData={{
|
||||
...(group_by && { [group_by]: getValueFromObject(_list, listKey) }),
|
||||
...(sub_group_by && sub_group_id !== "null" && { [sub_group_by]: sub_group_id }),
|
||||
}}
|
||||
quickAddCallback={quickAddCallback}
|
||||
viewId={viewId}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* {isDragStarted && isDragDisabled && (
|
||||
|
@ -24,6 +24,7 @@ export const IssueBlocksList: FC<Props> = (props) => {
|
||||
{issueIds && issueIds.length > 0 ? (
|
||||
issueIds.map(
|
||||
(issueId: string) =>
|
||||
issueId != undefined &&
|
||||
issues[issueId] && (
|
||||
<IssueBlock
|
||||
key={issues[issueId].id}
|
||||
|
@ -87,16 +87,22 @@ export const PeekOverviewIssueDetails: FC<IPeekOverviewIssueDetails> = (props) =
|
||||
description_html: issue.description_html,
|
||||
});
|
||||
|
||||
// adding issue.description_html or issue.name to dependency array causes
|
||||
// editor rerendering on every save
|
||||
useEffect(() => {
|
||||
if (issue.id) {
|
||||
setLocalIssueDescription({ id: issue.id, description_html: issue.description_html });
|
||||
setLocalTitleValue(issue.name);
|
||||
}
|
||||
}, [issue.id, issue.description_html, issue.name]);
|
||||
}, [issue.id]);
|
||||
|
||||
const debouncedFormSave = debounce(async () => {
|
||||
handleSubmit(handleDescriptionFormSubmit)().finally(() => setIsSubmitting("submitted"));
|
||||
}, 1500);
|
||||
// ADDING handleDescriptionFormSubmit TO DEPENDENCY ARRAY PRODUCES ADVERSE EFFECTS
|
||||
const debouncedFormSave = useCallback(
|
||||
debounce(async () => {
|
||||
handleSubmit(handleDescriptionFormSubmit)().finally(() => setIsSubmitting("submitted"));
|
||||
}, 1500),
|
||||
[handleSubmit]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (isSubmitting === "submitted") {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "web",
|
||||
"version": "0.13.2",
|
||||
"version": "0.14.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "turbo run develop",
|
||||
|
@ -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 useSWR, { MutatorOptions } from "swr";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
@ -59,7 +59,7 @@ const PageDetailsPage: NextPageWithLayout = observer(() => {
|
||||
|
||||
const { user } = useUser();
|
||||
|
||||
const { handleSubmit, reset, setValue, watch, getValues, control } = useForm<IPage>({
|
||||
const { handleSubmit, setValue, watch, getValues, control } = useForm<IPage>({
|
||||
defaultValues: { name: "", description_html: "" },
|
||||
});
|
||||
|
||||
@ -152,6 +152,8 @@ const PageDetailsPage: NextPageWithLayout = observer(() => {
|
||||
}
|
||||
}, [isSubmitting, setShowAlert]);
|
||||
|
||||
// adding pageDetails.description_html to dependency array causes
|
||||
// editor rerendering on every save
|
||||
useEffect(() => {
|
||||
if (pageDetails?.description_html) {
|
||||
setLocalIssueDescription({ id: pageId as string, description_html: pageDetails.description_html });
|
||||
@ -326,9 +328,13 @@ const PageDetailsPage: NextPageWithLayout = observer(() => {
|
||||
description_html: "",
|
||||
});
|
||||
|
||||
const debouncedFormSave = debounce(async () => {
|
||||
handleSubmit(updatePage)().finally(() => setIsSubmitting("submitted"));
|
||||
}, 1500);
|
||||
// ADDING updatePage TO DEPENDENCY ARRAY PRODUCES ADVERSE EFFECTS
|
||||
const debouncedFormSave = useCallback(
|
||||
debounce(async () => {
|
||||
handleSubmit(updatePage)().finally(() => setIsSubmitting("submitted"));
|
||||
}, 1500),
|
||||
[handleSubmit]
|
||||
);
|
||||
|
||||
if (error)
|
||||
return (
|
||||
|
Loading…
Reference in New Issue
Block a user