feat: estimates revamp and space app refactor (#4742)

* Move code from EE to CE repo

* chore: folder structure updates

* Move sortabla and radio input to packages/ui

* chore: updated empty and loading screens

* chore: delete an estimate point

* chore: estimate point response change

* chore: updated create estimate and handled the build error

* chore: migration fixes

* chore: updated create estimate

* chore: create estimate workflow update

* chore: editing and deleting the existing estimate updates

* chore: updating the new estinates in update modal

* chore: ui changed

* chore: response changes of get and post

* chore: new field added in estimates

* chore: individual endpoint for estimate points

* chore: typo changes

* chore: create estimate point

* chore: integrated new endpoints

* chore: update key value pair

* chore: update sorting in the estimates

* Add custom option in the estimate templates

* chore: handled current project active estimate

* chore: handle estimate update worklfow

* chore: handled estimates switch

* chore: handled estimate edit

* chore: handled close button in estimate edit

* chore: updated ceate estimare workflow

* chore: updated switch estimate

* chore: UI and typos

* chore: resolved build error

* chore: updated delete dropdown and handled the repeated values while creating and updating the estimate point

* chore: handled inline errors in the estimate switch

* chore: handled active and availability vadilation

* chore: handled create and update components in projecr estimates

* chore: added migration

* Add category specific values for custom template

* chore: estimate dropdown handled in issues

* chore: estimate alerts

* chore: updated alerts

* Extract the list row actions

* fix: updated and handled the estimate points

* fix: upgrader ee banner

* Fix issues with sortable

* Fix sortable spacing issue in create estimate modal

* fix: updated the issue create sorting

* chore: removed radio button from ui and updated in the estimates

* chore: resolved import error in packaged ui

* chore: handled props in create modal

* chore: removed ee files

* chore: changed default analytics

* chore: removed the migration file

* chore: estimate point value in graph

* chore: estimate point key change

* chore: squashed migration (#4634)

* chore: squashed migration

* chore: removed instance migraion

* chore: key changes

* chore: issue activity back migration

* dev: replaced estimate key with estimate id and replaced estimate type from number to string in issue

* chore: estimate point value field

* chore: estimate point activity

* chore: removed the unused function

* chore: resolved merge conflicts

* chore: deploy board keys changed

* chore: yarn lock file change

* chore: resolved frontend build

---------

Co-authored-by: guru_sainath <gurusainath007@gmail.com>

* [WEB-1516] refactor: space app routing and layouts (#4705)

* dev: change layout

* chore: replace workspace slug and project id with anchor

* chore: migration fixes

* chore: update filtering logic

* chore: endpoint changes

* chore: update endpoint

* chore: changed url pratterns

* chore: use client side for layout and page

* chore: issue vote changes

* chore: project deploy board response change

* refactor: publish project store and components

* fix: update layout options after fetching settings

* chore: remove unnecessary types

* style: peek overview

* refactor: components folder structure

* fix: redirect from old path

* chore: make the whole issue block clickable

* chore: removed the migration file

* chore: add server side redirection for old routes

* chore: is enabled key change

* chore: update types

* chore: removed the migration file

---------

Co-authored-by: NarayanBavisetti <narayan3119@gmail.com>

* Merge develop into revamp-estimates-ce

* chore: removed migration file and updated the estimate system order and removed ee banner

* chore: initial radio select in create estimate

* chore: space key changes

* Fix sortable component as the sort order was broken.

* [WEB-1516] refactor: publish project modal and types (#4716)

* refacotr: project publish

* chore: rename service names

* chore: is_deployed changed to anchor

* chore: update is_deployed key

---------

Co-authored-by: NarayanBavisetti <narayan3119@gmail.com>

* [WEB-412] chore: estimates analytics  (#4730)

* chore: estimate points in modules and cycle

* chore: burn down chart analytics

* chore: module serializer change

* dev: handled y-axis estimates in analytics, implemented estimate points on modules

* chore: burn down analytics

* chore: state estimate point analytics

* chore: updated the burn down values

* Remove check mark from estimate point edit field in
create estimate flow

---------

Co-authored-by: guru_sainath <gurusainath007@gmail.com>
Co-authored-by: Satish Gandham <satish.iitg@gmail.com>

---------

Co-authored-by: Satish Gandham <satish.iitg@gmail.com>
Co-authored-by: guru_sainath <gurusainath007@gmail.com>
Co-authored-by: NarayanBavisetti <narayan3119@gmail.com>
Co-authored-by: Bavisetti Narayan <72156168+NarayanBavisetti@users.noreply.github.com>
Co-authored-by: Aaryan Khandelwal <65252264+aaryan610@users.noreply.github.com>
Co-authored-by: pushya22 <130810100+pushya22@users.noreply.github.com>
This commit is contained in:
sriram veeraghanta 2024-06-10 12:16:23 +05:30 committed by GitHub
parent fb2b4ae303
commit 59fdd611e4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
223 changed files with 6874 additions and 4658 deletions

View file

@ -2,7 +2,7 @@ import { FC } from "react";
import { observer } from "mobx-react";
import { Triangle } from "lucide-react";
// hooks
import { useEstimate, useIssueDetail } from "@/hooks/store";
import { useIssueDetail } from "@/hooks/store";
// components
import { IssueActivityBlockComponent, IssueLink } from "./";
@ -14,15 +14,11 @@ export const IssueEstimateActivity: FC<TIssueEstimateActivity> = observer((props
const {
activity: { getActivityById },
} = useIssueDetail();
const { areEstimatesEnabledForCurrentProject, getEstimatePointValue } = useEstimate();
const activity = getActivityById(activityId);
if (!activity) return <></>;
const estimateValue = getEstimatePointValue(Number(activity.new_value), null);
const currentPoint = Number(activity.new_value) + 1;
return (
<IssueActivityBlockComponent
icon={<Triangle size={14} color="#6b7280" aria-hidden="true" />}
@ -31,15 +27,7 @@ export const IssueEstimateActivity: FC<TIssueEstimateActivity> = observer((props
>
<>
{activity.new_value ? `set the estimate point to ` : `removed the estimate point `}
{activity.new_value && (
<>
<span className="font-medium text-custom-text-100">
{areEstimatesEnabledForCurrentProject
? estimateValue
: `${currentPoint} ${currentPoint > 1 ? "points" : "point"}`}
</span>
</>
)}
{activity.new_value ? activity.new_value : activity?.old_value || ""}
{showIssue && (activity.new_value ? ` to ` : ` from `)}
{showIssue && <IssueLink activityId={activityId} />}.
</>

View file

@ -141,7 +141,7 @@ export const IssueActivity: FC<TIssueActivity> = observer((props) => {
workspaceSlug={workspaceSlug}
issueId={issueId}
activityOperations={activityOperations}
showAccessSpecifier={project.is_deployed}
showAccessSpecifier={!!project.anchor}
disabled={disabled}
/>
{!disabled && (
@ -150,7 +150,7 @@ export const IssueActivity: FC<TIssueActivity> = observer((props) => {
projectId={projectId}
workspaceSlug={workspaceSlug}
activityOperations={activityOperations}
showAccessSpecifier={project.is_deployed}
showAccessSpecifier={!!project.anchor}
/>
)}
</div>
@ -161,7 +161,7 @@ export const IssueActivity: FC<TIssueActivity> = observer((props) => {
workspaceSlug={workspaceSlug}
issueId={issueId}
activityOperations={activityOperations}
showAccessSpecifier={project.is_deployed}
showAccessSpecifier={!!project.anchor}
disabled={disabled}
/>
{!disabled && (
@ -170,7 +170,7 @@ export const IssueActivity: FC<TIssueActivity> = observer((props) => {
projectId={projectId}
workspaceSlug={workspaceSlug}
activityOperations={activityOperations}
showAccessSpecifier={project.is_deployed}
showAccessSpecifier={!!project.anchor}
/>
)}
</div>

View file

@ -54,7 +54,7 @@ import { getDate, renderFormattedPayloadDate } from "@/helpers/date-time.helper"
import { shouldHighlightIssueDueDate } from "@/helpers/issue.helper";
import { copyTextToClipboard } from "@/helpers/string.helper";
// types
import { useEstimate, useIssueDetail, useProject, useProjectState, useUser } from "@/hooks/store";
import { useProjectEstimates, useIssueDetail, useProject, useProjectState, useUser } from "@/hooks/store";
import { usePlatformOS } from "@/hooks/use-platform-os";
// components
import type { TIssueOperations } from "./root";
@ -82,7 +82,7 @@ export const IssueDetailsSidebar: React.FC<Props> = observer((props) => {
// store hooks
const { getProjectById } = useProject();
const { data: currentUser } = useUser();
const { areEstimatesEnabledForCurrentProject } = useEstimate();
const { areEstimateEnabledByProjectId } = useProjectEstimates();
const {
issue: { getIssueById },
} = useIssueDetail();
@ -311,15 +311,17 @@ export const IssueDetailsSidebar: React.FC<Props> = observer((props) => {
/>
</div>
{areEstimatesEnabledForCurrentProject && (
{projectId && areEstimateEnabledByProjectId(projectId) && (
<div className="flex h-8 items-center gap-2">
<div className="flex w-2/5 flex-shrink-0 items-center gap-1 text-sm text-custom-text-300">
<Triangle className="h-4 w-4 flex-shrink-0" />
<span>Estimate</span>
</div>
<EstimateDropdown
value={issue?.estimate_point !== null ? issue.estimate_point : null}
onChange={(val) => issueOperations.update(workspaceSlug, projectId, issueId, { estimate_point: val })}
value={issue?.estimate_point ?? undefined}
onChange={(val: string | undefined) =>
issueOperations.update(workspaceSlug, projectId, issueId, { estimate_point: val })
}
projectId={projectId}
disabled={!isEditable}
buttonVariant="transparent-with-text"

View file

@ -26,7 +26,7 @@ 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 { useEventTracker, useLabel, useIssues, useProjectState, useProject, useProjectEstimates } from "@/hooks/store";
import { usePlatformOS } from "@/hooks/use-platform-os";
// local components
import { IssuePropertyLabels } from "../properties/labels";
@ -42,6 +42,9 @@ export interface IIssueProperties {
}
export const IssueProperties: React.FC<IIssueProperties> = observer((props) => {
// router
const router = useRouter();
const { workspaceSlug, projectId } = router.query;
const { issue, updateIssue, displayProperties, activeLayout, isReadOnly, className } = props;
// store hooks
const { getProjectById } = useProject();
@ -53,13 +56,10 @@ export const IssueProperties: React.FC<IIssueProperties> = observer((props) => {
const {
issues: { addCycleToIssue, removeCycleFromIssue },
} = useIssues(EIssuesStoreType.CYCLE);
const { areEstimatesEnabledForCurrentProject } = useEstimate();
const { areEstimateEnabledByProjectId } = useProjectEstimates();
const { getStateById } = useProjectState();
const { isMobile } = usePlatformOS();
const projectDetails = getProjectById(issue.project_id);
// router
const router = useRouter();
const { workspaceSlug } = router.query;
const currentLayout = `${activeLayout} layout`;
// derived values
const stateDetails = getStateById(issue.state_id);
@ -220,7 +220,7 @@ export const IssueProperties: React.FC<IIssueProperties> = observer((props) => {
);
};
const handleEstimate = (value: number | null) => {
const handleEstimate = (value: string | undefined) => {
updateIssue &&
updateIssue(issue.project_id, issue.id, { estimate_point: value }).then(() => {
captureIssueEvent({
@ -394,11 +394,11 @@ export const IssueProperties: React.FC<IIssueProperties> = observer((props) => {
)}
{/* estimates */}
{areEstimatesEnabledForCurrentProject && (
{projectId && areEstimateEnabledByProjectId(projectId?.toString()) && (
<WithDisplayPropertiesHOC displayProperties={displayProperties} displayPropertyKey="estimate">
<div className="h-5" onClick={handleEventPropagation}>
<EstimateDropdown
value={issue.estimate_point}
value={issue.estimate_point ?? undefined}
onChange={handleEstimate}
projectId={issue.project_id}
disabled={isReadOnly}

View file

@ -17,7 +17,7 @@ export const SpreadsheetEstimateColumn: React.FC<Props> = observer((props: Props
return (
<div className="h-11 border-b-[0.5px] border-custom-border-200">
<EstimateDropdown
value={issue.estimate_point}
value={issue.estimate_point || undefined}
onChange={(data) =>
onChange(issue, { estimate_point: data }, { changed_property: "estimate_point", change_details: data })
}

View file

@ -499,7 +499,7 @@ export const handleGroupDragDrop = async (
// update updatedIssue values based on the source and destination groupIds
if (source.groupId && destination.groupId && source.groupId !== destination.groupId) {
const groupKey = ISSUE_FILTER_DEFAULT_DATA[groupBy];
let groupValue = clone(sourceIssue[groupKey]);
let groupValue: any = clone(sourceIssue[groupKey]);
// If groupValues is an array, remove source groupId and add destination groupId
if (Array.isArray(groupValue)) {
@ -519,7 +519,7 @@ export const handleGroupDragDrop = async (
// update updatedIssue values based on the source and destination subGroupIds
if (subGroupBy && source.subGroupId && destination.subGroupId && source.subGroupId !== destination.subGroupId) {
const subGroupKey = ISSUE_FILTER_DEFAULT_DATA[subGroupBy];
let subGroupValue = clone(sourceIssue[subGroupKey]);
let subGroupValue: any = clone(sourceIssue[subGroupKey]);
// If subGroupValue is an array, remove source subGroupId and add destination subGroupId
if (Array.isArray(subGroupValue)) {

View file

@ -28,7 +28,14 @@ import { renderFormattedPayloadDate, getDate } from "@/helpers/date-time.helper"
import { getChangedIssuefields, getDescriptionPlaceholder } from "@/helpers/issue.helper";
import { shouldRenderProject } from "@/helpers/project.helper";
// hooks
import { useAppRouter, useEstimate, useInstance, useIssueDetail, useProject, useWorkspace } from "@/hooks/store";
import {
useAppRouter,
useProjectEstimates,
useInstance,
useIssueDetail,
useProject,
useWorkspace,
} from "@/hooks/store";
import useKeypress from "@/hooks/use-keypress";
import { useProjectIssueProperties } from "@/hooks/use-project-issue-properties";
// services
@ -120,7 +127,7 @@ export const IssueFormRoot: FC<IssueFormProps> = observer((props) => {
const { projectId: routeProjectId } = useAppRouter();
const { config } = useInstance();
const { getProjectById } = useProject();
const { areEstimatesEnabledForProject } = useEstimate();
const { areEstimateEnabledByProjectId } = useProjectEstimates();
const handleKeyDown = (event: KeyboardEvent) => {
if (editorRef.current?.isEditorReadyToDiscard()) {
@ -659,14 +666,14 @@ export const IssueFormRoot: FC<IssueFormProps> = observer((props) => {
)}
/>
)}
{areEstimatesEnabledForProject(projectId) && (
{projectId && areEstimateEnabledByProjectId(projectId) && (
<Controller
control={control}
name="estimate_point"
render={({ field: { value, onChange } }) => (
<div className="h-7">
<EstimateDropdown
value={value}
value={value || undefined}
onChange={(estimatePoint) => {
onChange(estimatePoint);
handleFormChange();

View file

@ -197,14 +197,14 @@ export const PeekOverviewProperties: FC<IPeekOverviewProperties> = observer((pro
<span>Estimate</span>
</div>
<EstimateDropdown
value={issue?.estimate_point !== null ? issue.estimate_point : null}
value={issue.estimate_point ?? undefined}
onChange={(val) => issueOperations.update(workspaceSlug, projectId, issueId, { estimate_point: val })}
projectId={projectId}
disabled={disabled}
buttonVariant="transparent-with-text"
className="w-3/4 flex-grow group"
buttonContainerClassName="w-full text-left"
buttonClassName={`text-sm ${issue?.estimate_point !== null ? "" : "text-custom-text-400"}`}
buttonClassName={`text-sm ${issue?.estimate_point !== undefined ? "" : "text-custom-text-400"}`}
placeholder="None"
hideIcon
dropdownArrow