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
24 changes: 24 additions & 0 deletions Queries/CronJob/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import apiClient from '../../utlis/apiClient';
import { ENVIRONMENT_ENDPOINT } from '../../utlis/apiEndpoints';

const url = ENVIRONMENT_ENDPOINT;

export const getCronJobs = async (id) => {
const updatedUrl = `${url}/${id}/deploymentspace/cronjob`;
try {
const data = await apiClient.get(updatedUrl);
return data;
} catch (error) {
throw new Error(error.response?.data?.error?.message || 'Failed to fetch cron jobs');
}
};

export const getCronByName = async (id, name) => {
const updatedUrl = `${url}/${id}/deploymentspace/cronjob/${name}`;
try {
const data = await apiClient.get(updatedUrl);
return data;
} catch (error) {
throw new Error(error.response?.data?.error?.message || 'Failed to fetch cron job details');
}
};
24 changes: 24 additions & 0 deletions Queries/Deployment/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import apiClient from '../../utlis/apiClient';
import { ENVIRONMENT_ENDPOINT } from '../../utlis/apiEndpoints';

const url = ENVIRONMENT_ENDPOINT;

export const getDeployment = async (id) => {
const updatedUrl = `${url}/${id}/deploymentspace/deployment`;
try {
const data = await apiClient.get(updatedUrl);
return data;
} catch (error) {
throw new Error(error.response?.data?.error?.message || 'Failed to fetch deployment');
}
};

export const getDeploymentByName = async (id, name) => {
const updatedUrl = `${url}/${id}/deploymentspace/deployment/${name}`;
try {
const data = await apiClient.get(updatedUrl);
return data;
} catch (error) {
throw new Error(error.response?.data?.error?.message || 'Failed to fetch deployment details');
}
};
24 changes: 24 additions & 0 deletions Queries/Pods/index.js

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

24 changes: 24 additions & 0 deletions Queries/Service/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import apiClient from '../../utlis/apiClient';
import { ENVIRONMENT_ENDPOINT } from '../../utlis/apiEndpoints';

const url = ENVIRONMENT_ENDPOINT;

export const getService = async (id) => {
const updatedUrl = `${url}/${id}/deploymentspace/service`;
try {
const data = await apiClient.get(updatedUrl);
return data;
} catch (error) {
throw new Error(error.response?.data?.error?.message || 'Failed to fetch services');
}
};

export const getServiceByName = async (id, name) => {
const updatedUrl = `${url}/${id}/deploymentspace/service/${name}`;
try {
const data = await apiClient.get(updatedUrl);
return data;
} catch (error) {
throw new Error(error.response?.data?.error?.message || 'Failed to fetch service details');
}
};
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,15 @@ Zop is a comprehensive tool for managing cloud infrastructure. It consists of th
Run the following command to pull and start the Docker image for the zop-api:

```bash
docker run -d -p 8000:8000 --name zop-api zopdev/zop-api:v0.0.2
docker run -d -p 8000:8000 --name zop-api zopdev/zop-api:v0.0.3
```

#### zop-ui

Run the following command to pull and start the Docker image for the zop-ui:

```bash
docker run -d -p 3000:3000 -e NEXT_PUBLIC_API_BASE_URL='http://localhost:8000' --name zop-ui zopdev/zop-ui:v0.0.2
docker run -d -p 3000:3000 -e NEXT_PUBLIC_API_BASE_URL='http://localhost:8000' --name zop-ui zopdev/zop-ui:v0.0.3
```

> **Note:** The environment variable `NEXT_PUBLIC_API_BASE_URL` is used by zop-ui to connect to the
Expand Down
19 changes: 19 additions & 0 deletions components/Button/IconButton/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React from 'react';

const IconButton = ({ disabled, onClick, children, style, ...rest }) => {
return (
<button
type="button"
className={`inline-flex items-center justify-center p-2 rounded-full ${
disabled ? 'opacity-50' : 'hover:bg-gray-200 focus:outline-none focus:bg-gray-200'
} ${style}`}
onClick={onClick}
disabled={disabled}
{...rest}
>
{children}
</button>
);
};

export default IconButton;
2 changes: 1 addition & 1 deletion components/Cards/applicationCard.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const ApplicationCard = ({ data, view }) => {
}, [data?.id, router]);

const handleRedirect = () => {
router.push(`/applications/${data?.id}/deploymentSpace`);
router.push(`/applications/${data?.id}/environment`);
};

return (
Expand Down
104 changes: 104 additions & 0 deletions components/FullScreenDrawer/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
'use client';

import React, { useState, Fragment } from 'react';
import { Dialog, DialogPanel, DialogTitle, Transition, TransitionChild } from '@headlessui/react';
import { XMarkIcon } from '@heroicons/react/24/outline';
import IconButton from '../Button/IconButton';

export function FullScreenDrawer({
title,
RenderIcon,
RenderComponent,
disabled,
isIcon,
handleMenuItemClose = () => {},
formData,
}) {
const [open, setOpen] = useState(false);

const handleClickOpen = (e) => {
e.stopPropagation();
setOpen(true);
};

const handleClose = () => {
setOpen(false);
};

const handleSuccess = () => {
setOpen(false);
};

return (
<>
{isIcon && (
// <Tooltip title={tooltipTitle}>
<IconButton onClick={(e) => handleClickOpen(e)} disabled={disabled}>
{RenderIcon}
</IconButton>
// </Tooltip>
)}

<Transition show={open} as={Fragment}>
<Dialog className="relative z-10" onClose={handleClose}>
<TransitionChild
as={Fragment}
enter="ease-in-out duration-500"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="ease-in-out duration-500"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<div className="fixed inset-0 bg-gray-800 bg-opacity-10 backdrop-blur transition-opacity" />
</TransitionChild>

<div className="fixed inset-0 overflow-hidden">
<div className="absolute inset-0 overflow-hidden">
<div className="pointer-events-none fixed inset-y-0 right-0 flex max-w-full xs:pl-0 md:pl-10">
<TransitionChild
as={Fragment}
enter="transform transition ease-in-out duration-500 sm:duration-700"
enterFrom="translate-x-full"
enterTo="translate-x-0"
leave="transform transition ease-in-out duration-500 sm:duration-700"
leaveFrom="translate-x-0"
leaveTo="translate-x-full"
>
<DialogPanel className="pointer-events-auto w-screen xs:min-w-screen md:max-w-3xl ">
<div className="flex h-full flex-col bg-gray-50 shadow-xl">
<div className="px-4 sm:px-8 bg-primary-500 py-3">
<div className="flex items-start justify-between ">
<DialogTitle className="font-semibold !text-white sm:text-2xl xs:text-xl leading-6 ">
{title}
</DialogTitle>
<div className="ml-3 flex h-7 items-center">
<IconButton
onClick={() => {
handleClose();
handleMenuItemClose();
}}
>
<XMarkIcon className="h-6 w-6 text-gray-600" aria-hidden="true" />
</IconButton>
</div>
</div>
</div>
<div className="relative mt-4 pb-4 flex-1 px-4 sm:px-2 overflow-y-scroll">
<RenderComponent
formData={formData}
handleClose={handleClose}
setOpen={handleSuccess}
/>
</div>
</div>
</DialogPanel>
</TransitionChild>
</div>
</div>
</div>
</Dialog>
</Transition>
</>
);
}
20 changes: 16 additions & 4 deletions components/Table/table.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,24 @@ import React from 'react';
import TableHeader from './tableHeader';
import TableBody from './tableBody';

const Table = ({ headers, data, onEdit, onDelete, action }) => {
const Table = ({
headers,
data,
onEdit,
onDelete,
action,
handleRowClick = () => {},
renderComponent,
enableRowClick,
}) => {
return (
<div className="-mx-4 mt-8 flow-root sm:mx-0">
<table className="min-w-full">
<div className="-mx-4 mt-4 min-w-full h-[75vh] overflow-auto flow-root sm:mx-0">
<table className="table-auto w-full border-collapse">
<colgroup>
{headers.map((header) => (
<col key={header.key} className={header.colClassName || ''} />
))}
<col className="w-auto" />
<col className=" w-[100vw]" />
</colgroup>
<TableHeader headers={headers} action={action} />
<TableBody
Expand All @@ -19,6 +28,9 @@ const Table = ({ headers, data, onEdit, onDelete, action }) => {
onEdit={onEdit}
onDelete={onDelete}
action={action}
handleRowClick={handleRowClick}
renderComponent={renderComponent}
enableRowClick={enableRowClick}
/>
</table>
</div>
Expand Down
49 changes: 41 additions & 8 deletions components/Table/tableBody.js
Original file line number Diff line number Diff line change
@@ -1,32 +1,65 @@
import React from 'react';
import { FullScreenDrawer } from '../FullScreenDrawer';
import { DocumentChartBarIcon } from '@heroicons/react/24/outline';

const TableBody = ({ data, headers, onEdit, onDelete, action = true }) => {
const TableBody = ({
data,
headers,
onEdit,
onDelete,
action = true,
handleRowClick = () => {},
renderComponent,
enableRowClick = false,
}) => {
return (
<tbody>
{data?.map((row, rowIndex) => (
<tr key={row.id || rowIndex} className="border-b border-gray-200">
<tr
key={row.id || rowIndex}
className={`border-b border-gray-200 group ${enableRowClick && 'hover:bg-gray-50 cursor-pointer'}`}
onClick={() => enableRowClick && handleRowClick(row)}
>
{headers.map((header) => (
<td
key={header.key}
className={`px-3 py-5 text-sm ${
className={`px-3 py-5 text-sm ${
header.align === 'right' ? 'text-right' : 'text-left'
} text-gray-500`}
} text-gray-500 ${header.colClassName}`}
style={{ minWidth: 175, flexGrow: 1 }}
>
{/* Allow React components or plain text */}
{typeof row[header.key] === 'function' ? row[header.key]() : row[header.key]}
</td>
))}
{action && (
<td className="px-3 py-5 text-right">
<div className="flex gap-2 justify-end">
<div className="flex gap-2 justify-center">
{onEdit && (
<button onClick={() => onEdit(row)} className="text-blue-500 hover:text-blue-700">
Edit
</button>
)}
<button onClick={() => onDelete(row)} className="text-red-500 hover:text-red-700">
Delete
</button>
{onDelete && (
<button onClick={() => onDelete(row)} className="text-red-500 hover:text-red-700">
Delete
</button>
)}
{renderComponent && (
<FullScreenDrawer
// tooltipTitle={row?.name}
isIcon
RenderIcon={
<DocumentChartBarIcon
className="-ml-0.5 h-6 w-6 text-gray-600"
aria-hidden="true"
/>
}
title={row?.name}
RenderComponent={renderComponent}
formData={row}
/>
)}
</div>
</td>
)}
Expand Down
4 changes: 2 additions & 2 deletions components/Table/tableHeader.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ const TableHeader = ({ headers, action = true }) => {
<th
key={header.key}
scope="col"
className={`px-3 py-3.5 text-sm font-semibold text-gray-900 ${
className={`px-3 py-3.5 text-sm font-semibold text-gray-900 whitespace-nowrap ${
header.align === 'right' ? 'text-right' : 'text-left'
} ${header.className || ''}`}
>
{header.label}
</th>
))}
{action && (
<th className="px-3 py-3.5 text-sm font-semibold text-gray-900 text-right">Actions</th>
<th className="px-3 py-3.5 text-sm font-semibold text-gray-900 text-center">Actions</th>
)}
</tr>
</thead>
Expand Down
Loading
Loading