Skip to content

Commit

Permalink
Implement install modal skeleton (#274)
Browse files Browse the repository at this point in the history
* Increment chart versions [skip ci]

* Minor UI fixes (#234)

* Add username and password support to Repo add feature (#228)

* Add username and password support to Repo add in UI

* Add support for Username and Passowrd in Add Repo API

* Display resource health aggregate icons on list of releases (#235)

* Display aggregate resource health status

* Reuse old API request, show icons

* Take progress indication from deployment conditions

* Improve status

* Cleanup

* Fixups

* Squares approach

* Improve console message in case no k8s connection possible

* Count API docs in user analytics

* Removing redundant table header (#268)

* update README (#270)

* Skeleton for Install Modal

* Revert "Merge branch 'komodorio:main' into Implement-install-modal-skeleton"

This reverts commit f731e6f, reversing
changes made to 6d90d43.

* some little fixes

* Fix modal pushed down bug

---------

Co-authored-by: komodor-bot <[email protected]>
Co-authored-by: Harshit Mehta <[email protected]>
Co-authored-by: Andrey Pokhilko <[email protected]>
  • Loading branch information
4 people authored Mar 19, 2023
1 parent cff68e1 commit fc6b67b
Show file tree
Hide file tree
Showing 3 changed files with 229 additions and 53 deletions.
30 changes: 30 additions & 0 deletions dashboard/src/components/modal/InstallModal.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Modal.stories.ts|tsx

import { ComponentStory, ComponentMeta } from "@storybook/react";
import InstallModal from "./InstallModal";

//👇 This default export determines where your story goes in the story list
export default {
/* 👇 The title prop is optional.
* See https://storybook.js.org/docs/react/configure/overview#configure-story-loading
* to learn how to generate automatic titles
*/
title: "InstallModal",
component: InstallModal,
} as ComponentMeta<typeof InstallModal>;

//👇 We create a “template” of how args map to rendering
const Template: ComponentStory<typeof InstallModal> = (args) => (
<InstallModal
{...args}
isOpen={true}
onConfirm={() => console.log("confirm clicked")}
></InstallModal>
);

export const Default = Template.bind({});

Default.args = {
installTarget: "airflow",
isOpen: true,
};
147 changes: 147 additions & 0 deletions dashboard/src/components/modal/InstallModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
import { useEffect, useState } from "react";
import Modal from "./Modal";
import { ModalAction, ModalButtonStyle } from "./Modal";

interface InstallModalProps {
isOpen: boolean;
installTarget: string;
onConfirm: () => void;
}

interface VersionToInstall {
id: string;
name: string;
}

const versionsToInstall: VersionToInstall[] = [
{ id: "1", name: "bitnami @ 14.0.14" },
{ id: "2", name: "bitnami @ 15.0.15" },
{ id: "3", name: "bitnami @ 16.0.16" },
];

const cluster = "kind-kind";

export default function InstallModal({
isOpen,
onConfirm,
installTarget,
}: InstallModalProps) {
const uninstallTitle = (
<div className="font-medium text-2xl">
Install <span className="text-green-700 font-bold">{installTarget}</span>
</div>
);

const [confirmModalActions, setConfirmModalActions] =
useState<ModalAction[]>();

useEffect(() => {
setConfirmModalActions([
{
id: "1",
text: "Confirm",
callback: onConfirm,
variant: ModalButtonStyle.info,
},
]);
}, [onConfirm]);

return (
<Modal
title={uninstallTitle}
isOpen={isOpen}
onClose={onConfirm}
actions={confirmModalActions}
>
<div>
<div>
<label className="text-xl font-medium">Version to install:</label>
<div className="inline-block relative mb-6">
<select className="block appearance-none w-full font-semibold bg-white border border-gray-400 hover:border-gray-500 ml-2 px-4 py-2 pr-8 rounded shadow leading-tight focus:outline-none focus:shadow-outline text-green-700">
{versionsToInstall.map((version) => (
<option key={version.id} value={version.id}>
{version.name}
</option>
))}
</select>
<div className="pointer-events-none absolute inset-y-0 right-0 flex items-center px-2 text-gray-700">
<svg
className="fill-current h-4 w-4"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
>
<path d="M9.293 12.95l.707.707L15.657 8l-1.414-1.414L10 10.828 5.757 6.586 4.343 8z" />
</svg>
</div>
</div>
</div>
<div className="flex flex-wrap mb-2 gap-2">
<div className="w-full md:w-1/4 mb-6 md:mb-0">
<label
className="block tracking-wide text-gray-700 text-xl font-medium mb-2"
htmlFor="grid-release-name"
>
Release Name:
</label>
<input
className="appearance-none block w-full text-gray-700 border border-gray-200 rounded py-3 px-4 leading-tight focus:outline-none focus:bg-white focus:border-gray-500"
id="grid-release-name"
type="text"
placeholder="Airflow"
/>
</div>

<div className="w-full md:w-1/4 mb-6 md:mb-0">
<label
className="block tracking-wide text-gray-700 text-xl font-medium mb-2"
htmlFor="grid-namespace"
>
Namespace (optional):
</label>
<input
className="appearance-none block w-full text-gray-700 border border-gray-200 rounded py-3 px-4 leading-tight focus:outline-none focus:bg-white focus:border-gray-500"
id="grid-namespace"
type="text"
/>
</div>
<div className="md:w-1/3 mb-6 md:mb-0">
<label
className="block tracking-wide text-gray-700 text-xl font-medium mb-2"
htmlFor="grid-zip"
>
Cluster: {cluster}
</label>
</div>
<div className="flex w-full gap-6 mt-4">
<div className="w-1/2">
<label
className="block tracking-wide text-gray-700 text-xl font-medium mb-2"
htmlFor="grid-user-defined-values"
>
User-Defined Values:
</label>
<textarea
id="message"
rows={16}
className="block p-2.5 w-full text-sm text-gray-900 rounded-lg border border-gray-300 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500 resize-none"
></textarea>
</div>
<div className="w-1/2">
<label
className="block tracking-wide text-gray-700 text-xl font-medium mb-2"
htmlFor="grid-user-defined-values"
>
Chart Values Reference:
</label>
<div className="border border-gray-200 bg-slate-200 h-8"></div>
</div>
</div>
</div>
<label className="block tracking-wide text-gray-700 text-xl font-medium mt-4 mb-2">
Manifest changes:
</label>
<div className="bg-gray-200 w-full h-7"></div>
</div>
</Modal>
);
}
105 changes: 52 additions & 53 deletions dashboard/src/components/modal/Modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,18 @@ export enum ModalButtonStyle {
}

export interface ModalAction {
id: string,
callback: () => void,
text: string,
variant?: ModalButtonStyle,
className?: string
id: string;
callback: () => void;
text: string;
variant?: ModalButtonStyle;
className?: string;
}

export interface ModalProps extends PropsWithChildren {
title?: string | ReactNode,
isOpen: boolean,
onClose: () => void,
actions?: ModalAction[],
title?: string | ReactNode;
isOpen: boolean;
onClose: () => void;
actions?: ModalAction[];
}

const Modal = ({ title, isOpen, onClose, children, actions }: ModalProps) => {
Expand Down Expand Up @@ -70,56 +70,55 @@ const Modal = ({ title, isOpen, onClose, children, actions }: ModalProps) => {
return ReactDom.createPortal(
<>
{isVisible && (
<>
<div className="fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity"></div>
<div className="relative bg-white rounded-lg shadow dark:bg-gray-700 m-7">
{title && (
<div className="flex items-start justify-between p-4 border-b rounded-t dark:border-gray-600">
{getTitle(title)}
<button
type="button"
className="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm p-1.5 ml-auto inline-flex items-center dark:hover:bg-gray-600 dark:hover:text-white"
data-modal-hide="staticModal"
onClick={onClose}
>
<svg
className="w-5 h-5"
fill="currentColor"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"
<div className="fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity">
<div className="relative bg-white rounded-lg shadow dark:bg-gray-700 m-7">
{title && (
<div className="flex items-start justify-between p-4 border-b rounded-t dark:border-gray-600">
{getTitle(title)}
<button
type="button"
className="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm p-1.5 ml-auto inline-flex items-center dark:hover:bg-gray-600 dark:hover:text-white"
data-modal-hide="staticModal"
onClick={onClose}
>
<path
fillRule="evenodd"
d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z"
clipRule="evenodd"
></path>
</svg>
</button>
<svg
className="w-5 h-5"
fill="currentColor"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"
>
<path
fillRule="evenodd"
d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z"
clipRule="evenodd"
></path>
</svg>
</button>
</div>
)}
<div
className="p-4 space-y-6 overflow-y-auto"
style={{ maxHeight: "500px" }}
>
{children}
</div>
<div className="flex justify-end p-6 space-x-2 border-t border-gray-200 rounded-b dark:border-gray-600">
{actions?.map((action) => (
<button
key={action.id}
type="button"
className={getClassName(action)}
onClick={action.callback}
>
{action.text}
</button>
))}
</div>
)}
<div
className="p-4 space-y-6 overflow-y-auto"
style={{ maxHeight: "500px" }}
>
{children}
</div>
<div className="flex justify-end p-6 space-x-2 border-t border-gray-200 rounded-b dark:border-gray-600">
{actions?.map((action) => (
<button
key={action.id}
type="button"
className={getClassName(action)}
onClick={action.callback}
>
{action.text}
</button>
))}
</div>
</div>
</>
)}
</>,
document.getElementById("portal")
document.getElementById("portal")!
);
};

Expand Down

0 comments on commit fc6b67b

Please sign in to comment.