Skip to content

Commit

Permalink
Merge branch 'main' of https://github.com/redhat-cop/babylon
Browse files Browse the repository at this point in the history
  • Loading branch information
aleixhub committed Jan 24, 2025
2 parents a308f1c + 5df7757 commit 7f4ca59
Show file tree
Hide file tree
Showing 10 changed files with 103 additions and 33 deletions.
9 changes: 5 additions & 4 deletions catalog/ui/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion catalog/ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
"@babel/preset-typescript": "^7.26.0",
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/react": "^16.2.0",
"@testing-library/user-event": "^14.6.0",
"@testing-library/user-event": "^14.6.1",
"@types/dompurify": "^3.2.0",
"@types/jest": "^29.5.14",
"@types/js-yaml": "^4.0.9",
Expand Down
16 changes: 8 additions & 8 deletions catalog/ui/src/app/Admin/Workshops.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ const Workshops: React.FC<{}> = () => {
.split(/ +/)
.filter((w) => w != '')
: null,
[searchParams.get('search')],
[searchParams.get('search')]
);
const [modalState, setModalState] = useState<{ action?: string; workshop?: Workshop }>({});
const [selectedUids, setSelectedUids] = useState([]);
Expand All @@ -69,7 +69,7 @@ const Workshops: React.FC<{}> = () => {
setModalState({ action, workshop });
openModalAction();
},
[openModalAction],
[openModalAction]
);

const {
Expand Down Expand Up @@ -100,7 +100,7 @@ const Workshops: React.FC<{}> = () => {
}
return true;
},
},
}
);
const isReachingEnd = workshopsPages && !workshopsPages[workshopsPages.length - 1].metadata.continue;
const isLoadingInitialData = !workshopsPages;
Expand All @@ -126,7 +126,7 @@ const Workshops: React.FC<{}> = () => {
}
}
},
[mutate, workshopsPages],
[mutate, workshopsPages]
);
const filterWorkshop = useCallback(
(workshop: Workshop): boolean => {
Expand All @@ -143,12 +143,12 @@ const Workshops: React.FC<{}> = () => {
}
return true;
},
[keywordFilter],
[keywordFilter]
);

const workshops: Workshop[] = useMemo(
() => [].concat(...workshopsPages.map((page) => page.items)).filter(filterWorkshop) || [],
[filterWorkshop, workshopsPages],
[filterWorkshop, workshopsPages]
);

// Trigger continue fetching more resource claims on scroll.
Expand All @@ -173,7 +173,7 @@ const Workshops: React.FC<{}> = () => {
apiPaths.WORKSHOP({
namespace: workshop.metadata.namespace,
workshopName: workshop.metadata.name,
}),
})
);
deletedWorkshops.push(workshop);
}
Expand Down Expand Up @@ -319,7 +319,7 @@ const Workshops: React.FC<{}> = () => {
icon={TrashIcon}
/>
</div>
</React.Fragment>,
</React.Fragment>
);
return {
cells: cells,
Expand Down
16 changes: 12 additions & 4 deletions catalog/ui/src/app/Services/renderWorkshopRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
checkWorkshopCanStop,
getWorkshopAutoStopTime,
getWorkshopLifespan,
isWorkshopLocked,
} from '@app/Workshops/workshops-utils';
import CheckCircleIcon from '@patternfly/react-icons/dist/js/icons/check-circle-icon';
import Label from '@app/components/Label';
Expand All @@ -37,6 +38,7 @@ const renderWorkshopRow = ({
}) => void;
isAdmin: boolean;
}) => {
const isLocked = isWorkshopLocked(workshop, isAdmin);
const actionHandlers = {
delete: () => showModal({ modal: 'action', action: 'delete', workshop }),
lifespan: () => showModal({ action: 'retirement', modal: 'scheduleAction', workshop }),
Expand Down Expand Up @@ -109,7 +111,7 @@ const renderWorkshopRow = ({
<AutoStopDestroy
type="auto-stop"
onClick={actionHandlers.runtime}
isDisabled={!showModal || !checkWorkshopCanStop(workshop.resourceClaims)}
isDisabled={isLocked || !showModal || !checkWorkshopCanStop(workshop.resourceClaims)}
time={autoStopTime}
destroyTimestamp={autoDestroyTime}
key="workshop-auto-stop"
Expand All @@ -122,7 +124,7 @@ const renderWorkshopRow = ({
type="auto-destroy"
onClick={actionHandlers.lifespan}
time={autoDestroyTime}
isDisabled={!showModal}
isDisabled={isLocked || !showModal}
notDefinedMessage="- Not defined -"
key="workshop-auto-destroy"
/>
Expand All @@ -145,13 +147,19 @@ const renderWorkshopRow = ({
key="actions__start"
/>
<ButtonCircleIcon
isDisabled={!checkWorkshopCanStop(workshop.resourceClaims)}
isDisabled={isLocked || !checkWorkshopCanStop(workshop.resourceClaims)}
onClick={actionHandlers.stop}
description="Stop"
icon={StopIcon}
key="actions__stop"
/>
<ButtonCircleIcon key="actions__delete" onClick={actionHandlers.delete} description="Delete" icon={TrashIcon} />
<ButtonCircleIcon
key="actions__delete"
isDisabled={isLocked}
onClick={actionHandlers.delete}
description="Delete"
icon={TrashIcon}
/>
</div>
</React.Fragment>
);
Expand Down
16 changes: 10 additions & 6 deletions catalog/ui/src/app/Workshops/WorkshopActions.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from 'react';
import { DropdownPosition } from '@patternfly/react-core/deprecated';
import { ActionDropdown, ActionDropdownItem } from '@app/components/ActionDropdown';
import { LockedIcon } from '@patternfly/react-icons';

const WorkshopActions: React.FC<{
actionHandlers: {
Expand All @@ -13,13 +14,15 @@ const WorkshopActions: React.FC<{
isDisabled?: boolean;
position?: DropdownPosition | 'right' | 'left';
workshopName?: string;
}> = ({ actionHandlers, className, isDisabled, position, workshopName }) => {
isLocked?: boolean;
}> = ({ actionHandlers, className, isDisabled, position, workshopName, isLocked = false }) => {
const actionDropdownItems = [
<ActionDropdownItem
key="delete"
isDisabled={!actionHandlers.delete}
isDisabled={isLocked || !actionHandlers.delete}
label={workshopName ? `Delete ${workshopName}` : 'Delete'}
onSelect={actionHandlers.delete}
icon={isLocked ? <LockedIcon /> : null}
/>,
];
actionHandlers.deleteService &&
Expand All @@ -29,7 +32,7 @@ const WorkshopActions: React.FC<{
isDisabled={!actionHandlers.deleteService}
label="Delete Selected Services"
onSelect={actionHandlers.deleteService}
/>,
/>
);
actionHandlers.start &&
actionDropdownItems.push(
Expand All @@ -38,16 +41,17 @@ const WorkshopActions: React.FC<{
isDisabled={!actionHandlers.start}
label="Start Workshop instances"
onSelect={actionHandlers.start}
/>,
/>
);
actionHandlers.stop &&
actionDropdownItems.push(
<ActionDropdownItem
key="stopServices"
isDisabled={!actionHandlers.stop}
isDisabled={isLocked || !actionHandlers.stop}
label="Stop Workshop instances"
onSelect={actionHandlers.stop}
/>,
icon={isLocked ? <LockedIcon /> : null}
/>
);

return (
Expand Down
3 changes: 2 additions & 1 deletion catalog/ui/src/app/Workshops/WorkshopsItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ import WorkshopsItemProvisioning from './WorkshopsItemProvisioning';
import WorkshopsItemServices from './WorkshopsItemServices';
import WorkshopsItemUserAssignments from './WorkshopsItemUserAssignments';
import WorkshopScheduleAction from './WorkshopScheduleAction';
import { checkWorkshopCanStart, checkWorkshopCanStop, isWorkshopStarted } from './workshops-utils';
import { checkWorkshopCanStart, checkWorkshopCanStop, isWorkshopLocked, isWorkshopStarted } from './workshops-utils';
import Label from '@app/components/Label';
import ProjectSelector from '@app/components/ProjectSelector';
import ErrorBoundaryPage from '@app/components/ErrorBoundaryPage';
Expand Down Expand Up @@ -415,6 +415,7 @@ const WorkshopsItemComponent: React.FC<{
? () => showModal({ action: 'stopServices', resourceClaims })
: null,
}}
isLocked={isWorkshopLocked(workshop, isAdmin)}
/>
</Bullseye>
</SplitItem>
Expand Down
49 changes: 44 additions & 5 deletions catalog/ui/src/app/Workshops/WorkshopsItemDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,12 @@ import LoadingIcon from '@app/components/LoadingIcon';
import OpenshiftConsoleLink from '@app/components/OpenshiftConsoleLink';
import Editor from '@app/components/Editor/Editor';
import AutoStopDestroy from '@app/components/AutoStopDestroy';
import { checkWorkshopCanStop, getWorkshopAutoStopTime, getWorkshopLifespan } from './workshops-utils';
import {
checkWorkshopCanStop,
getWorkshopAutoStopTime,
getWorkshopLifespan,
isWorkshopLocked,
} from './workshops-utils';
import { ModalState } from './WorkshopsItem';
import WorkshopStatus from './WorkshopStatus';
import { useSWRConfig } from 'swr';
Expand Down Expand Up @@ -77,6 +82,7 @@ const WorkshopsItemDetails: React.FC<{
const debouncedApiFetch = useDebounce(apiFetch, 1000);
const { cache } = useSWRConfig();
const whiteGloved = getWhiteGloved(workshop);
const isLocked = isWorkshopLocked(workshop, isAdmin);
const debouncedPatchWorkshop = useDebounce(patchWorkshop, 1000) as (...args: unknown[]) => Promise<Workshop>;
const userRegistrationValue = workshop.spec.openRegistration === false ? 'pre' : 'open';
const workshopId = workshop.metadata.labels?.[`${BABYLON_DOMAIN}/workshop-id`];
Expand Down Expand Up @@ -200,6 +206,23 @@ const WorkshopsItemDetails: React.FC<{
}
}

async function handleLockedChange(_: any, isChecked: boolean) {
const patchObj = {
metadata: {
labels: {
[`${DEMO_DOMAIN}/lock-enabled`]: String(isChecked),
},
},
};
onWorkshopUpdate(
await patchWorkshop({
name: workshop.metadata.name,
namespace: workshop.metadata.namespace,
patch: patchObj,
})
);
}

return (
<DescriptionList isHorizontal className="workshops-item-details">
<DescriptionListGroup>
Expand Down Expand Up @@ -367,8 +390,8 @@ const WorkshopsItemDetails: React.FC<{
<DescriptionListDescription>
<AutoStopDestroy
type="auto-stop"
onClick={() => (showModal ? showModal({ action: 'scheduleStop', resourceClaims }) : null)}
isDisabled={!showModal}
onClick={() => (showModal && !isLocked ? showModal({ action: 'scheduleStop', resourceClaims }) : null)}
isDisabled={isLocked || !showModal}
time={autoStopTime}
variant="extended"
className="workshops-item__schedule-btn"
Expand All @@ -385,12 +408,12 @@ const WorkshopsItemDetails: React.FC<{
<AutoStopDestroy
type="auto-destroy"
onClick={() => {
if (showModal) {
if (showModal && !isLocked) {
showModal({ resourceClaims, action: 'scheduleDelete' });
}
}}
time={autoDestroyTime}
isDisabled={!showModal}
isDisabled={isLocked || !showModal}
variant="extended"
className="workshops-item__schedule-btn"
notDefinedMessage="- Not defined -"
Expand Down Expand Up @@ -524,6 +547,22 @@ const WorkshopsItemDetails: React.FC<{
</DescriptionListDescription>
</DescriptionListGroup>
) : null}

{isAdmin ? (
<DescriptionListGroup>
<DescriptionListTerm> </DescriptionListTerm>
<DescriptionListDescription>
<Switch
id="lock-switch"
aria-label="Locked"
label="Locked"
isChecked={isWorkshopLocked(workshop, false)}
hasCheckIcon
onChange={handleLockedChange}
/>
</DescriptionListDescription>
</DescriptionListGroup>
) : null}
</DescriptionList>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
EmptyStateHeader,
} from '@patternfly/react-core';
import { Table /* data-codemods */, Thead, Tr, Th, Tbody, Td } from '@patternfly/react-table';
import { apiPaths, assignWorkshopUser, bulkAssignWorkshopUsers } from '@app/api';
import { assignWorkshopUser, bulkAssignWorkshopUsers } from '@app/api';
import { WorkshopUserAssignment } from '@app/types';
import { renderContent } from '@app/util';
import BulkUserAssignmentModal from '@app/components/BulkUserAssignmentModal';
Expand Down
12 changes: 11 additions & 1 deletion catalog/ui/src/app/Workshops/workshops-utils.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ResourceClaim, Workshop, WorkshopProvision } from '@app/types';
import { canExecuteAction, checkResourceClaimCanStart, checkResourceClaimCanStop } from '@app/util';
import { canExecuteAction, checkResourceClaimCanStart, checkResourceClaimCanStop, DEMO_DOMAIN } from '@app/util';
import { getAutoStopTime, getMinDefaultRuntime, getStartTime } from '@app/Services/service-utils';
import parseDuration from 'parse-duration';

Expand Down Expand Up @@ -75,3 +75,13 @@ export function checkWorkshopCanStart(resourceClaims: ResourceClaim[] = []) {

return resourceClaimsCanStart && resourceClaimsCanStart.length > 0;
}

export function isWorkshopLocked(workshop: Workshop, isAdmin: boolean) {
if (isAdmin) {
return false;
}
if (workshop.metadata?.labels?.[`${DEMO_DOMAIN}/lock-enabled`]) {
return workshop.metadata?.labels?.[`${DEMO_DOMAIN}/lock-enabled`] === 'true';
}
return false;
}
11 changes: 9 additions & 2 deletions catalog/ui/src/app/components/ActionDropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,16 @@ const ActionDropdownItem: React.FC<{
label: string;
onSelect: () => void;
className?: string;
}> = ({ label, className, isDisabled = false, onSelect }) => {
icon?: React.ReactNode;
}> = ({ label, className, isDisabled = false, onSelect, icon }) => {
return (
<DropdownItem className={className} key={label} isDisabled={isDisabled} onClick={() => onSelect()}>
<DropdownItem
className={className}
key={label}
isDisabled={isDisabled}
onClick={() => (isDisabled === true ? null : onSelect())}
icon={icon}
>
{label}
</DropdownItem>
);
Expand Down

0 comments on commit 7f4ca59

Please sign in to comment.