Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,11 @@ export default function ManageProductModal({
const [cores, setCores] = useState("");
const [tps, setTps] = useState("");
const [description, setDescription] = useState("");
const [addUpdateState, setAddUpdateState] = useState<{
canAdd: boolean;
isSaving: boolean;
handleAdd: () => void;
} | null>(null);

const patchProduct = usePatchDeploymentProduct();
const isSubmitting = patchProduct.isPending;
Expand Down Expand Up @@ -308,7 +313,7 @@ export default function ManageProductModal({
}
isLoading={false}
onSaveUpdates={handleSaveUpdates}
onClose={handleClose}
onFormStateChange={setAddUpdateState}
/>
)}
</DialogContent>
Expand All @@ -319,7 +324,7 @@ export default function ManageProductModal({
<Button
variant="outlined"
onClick={handleClose}
disabled={isSubmitting}
disabled={isSubmitting || addUpdateState?.isSaving}
Comment thread
dileepapeiris marked this conversation as resolved.
>
Close
</Button>
Expand All @@ -343,6 +348,28 @@ export default function ManageProductModal({
Save Changes
</Button>
))}
{tabValue === 1 && addUpdateState && (
addUpdateState.isSaving ? (
<Button
variant="contained"
color="primary"
startIcon={<CircularProgress color="inherit" size={16} />}
disabled
>
Adding...
</Button>
) : (
<Button
type="button"
variant="contained"
color="primary"
onClick={addUpdateState.handleAdd}
disabled={!addUpdateState.canAdd}
>
Add Update
</Button>
)
)}
</DialogActions>
</Dialog>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {
import { SquarePen, Trash2 } from "@wso2/oxygen-ui-icons-react";
import {
useCallback,
useEffect,
useMemo,
useState,
type ChangeEvent,
Expand All @@ -42,7 +43,11 @@ export interface UpdateHistoryTabProps {
productVersion: string;
isLoading?: boolean;
onSaveUpdates: (updates: ProductUpdate[]) => Promise<void>;
onClose: () => void;
onFormStateChange?: (state: {
canAdd: boolean;
isSaving: boolean;
handleAdd: () => void;
}) => void;
Comment thread
dileepapeiris marked this conversation as resolved.
}

interface UpdateFormData {
Expand All @@ -69,7 +74,7 @@ export default function UpdateHistoryTab({
productVersion,
isLoading,
onSaveUpdates,
onClose,
onFormStateChange,
}: UpdateHistoryTabProps): JSX.Element {
const [form, setForm] = useState<UpdateFormData>(INITIAL_FORM);
const [editingIndex, setEditingIndex] = useState<number | null>(null);
Expand Down Expand Up @@ -184,6 +189,19 @@ export default function UpdateHistoryTab({
}
}, [form, updates, onSaveUpdates]);

const isFormValid = !!form.updateLevel && !!form.date;

// Notify parent of form state changes
useEffect(() => {
if (onFormStateChange) {
onFormStateChange({
canAdd: isFormValid && !isSaving,
isSaving,
handleAdd: handleAddUpdate,
});
}
}, [isFormValid, isSaving, handleAddUpdate, onFormStateChange]);

const handleEditClick = useCallback(
(update: ProductUpdate) => {
const index = updates.findIndex(
Expand Down Expand Up @@ -425,32 +443,19 @@ export default function UpdateHistoryTab({
</Typography>
</Box>
)}
<Box
sx={{
display: "flex",
justifyContent: "flex-end",
gap: 1,
pt: 1,
}}
>
<Button
variant="outlined"
onClick={onClose}
disabled={isSaving}
sx={{ minWidth: 100 }}
>
Close
</Button>
<Button
variant="contained"
color="primary"
onClick={handleAddUpdate}
disabled={!form.updateLevel || !form.date || isSaving}
sx={{ minWidth: 120 }}
>
{isSaving ? "Adding..." : "Add Update"}
</Button>
</Box>
{!onFormStateChange && (
<Box sx={{ display: "flex", justifyContent: "flex-end" }}>
<Button
variant="contained"
color="primary"
onClick={handleAddUpdate}
disabled={!isFormValid || isSaving}
sx={{ minWidth: 120 }}
>
{isSaving ? "Adding..." : "Add Update"}
</Button>
</Box>
)}
</Box>
</Box>
);
Expand Down Expand Up @@ -489,6 +494,10 @@ function TimelineItem({
}: TimelineItemProps): JSX.Element {
const [editForm, setEditForm] = useState<ProductUpdate>(update);

useEffect(() => {
setEditForm(update);
}, [update, isEditing]);

const handleEditChange =
(field: keyof ProductUpdate) => (e: ChangeEvent<HTMLInputElement>) => {
const value = e.target.value;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ describe("UpdateHistoryTab", () => {
productVersion: "2.1.0",
isLoading: false,
onSaveUpdates: vi.fn(),
onClose: vi.fn(),
};

it("renders update history timeline", () => {
Expand Down
16 changes: 12 additions & 4 deletions apps/customer-portal/webapp/src/pages/ProjectDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import ProjectDeployments from "@components/project-details/deployments/ProjectD
import ProjectTimeTracking from "@components/project-details/time-tracking/ProjectTimeTracking";
import useGetProjectDetails from "@api/useGetProjectDetails";
import { useGetProjectStat } from "@api/useGetProjectStat";
import useInfiniteProjects, { flattenProjectPages } from "@api/useGetProjects";
import { useLogger } from "@hooks/useLogger";
import { useLoader } from "@context/linear-loader/LoaderContext";

Expand All @@ -52,6 +53,14 @@ export default function ProjectDetails(): JSX.Element {
sidebarCollapsed: boolean;
}>() || { sidebarCollapsed: false };

const { data: projectsData } = useInfiniteProjects({ enabled: true });
const allProjects = flattenProjectPages(projectsData);
const currentProject = useMemo(
() => allProjects.find((p) => p.id === projectId),
[allProjects, projectId],
);
const projectTypeLabel = currentProject?.type?.label;

Comment thread
dileepapeiris marked this conversation as resolved.
const {
data: project,
isFetching: isProjectFetching,
Expand Down Expand Up @@ -89,7 +98,6 @@ export default function ProjectDetails(): JSX.Element {
}
}, [projectError, statsError, logger]);

const projectTypeLabel = project?.type?.label;
const hideDeploymentsAndTimeTracking =
projectTypeLabel === PROJECT_TYPE_LABELS.CLOUD_SUPPORT ||
projectTypeLabel === PROJECT_TYPE_LABELS.CLOUD_EVALUATION_SUPPORT;
Expand Down Expand Up @@ -185,7 +193,7 @@ export default function ProjectDetails(): JSX.Element {
};

return (
<>
<Box>
{/* project page tabs */}
<TabBar
tabs={visibleTabs}
Expand All @@ -194,7 +202,7 @@ export default function ProjectDetails(): JSX.Element {
/>

{/* project page content */}
<Box sx={{ flex: 1 }}>{renderContent()}</Box>
</>
<Box>{renderContent()}</Box>
</Box>
);
}