Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Flexible Column Layout for Offerings and Instances Views #850

Merged
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
4 changes: 2 additions & 2 deletions docs/contributor/09-10-ui.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ Follow the steps below to run BTP Manager with UI:
```
3. Set the **IMG** environment variable to the image of BTP Manager with UI.
```shell
export IMG=europe-docker.pkg.dev/kyma-project/dev/btp-manager:PR-844
export IMG=europe-docker.pkg.dev/kyma-project/dev/btp-manager:PR-850
```
4. Run `deploy` makefile rule to deploy BTP Manager with UI.
```shell
Expand All @@ -42,7 +42,7 @@ Follow the steps below to run BTP Manager with UI:
```
If you encounter the following error during Pod creation due to Warden's admission webhook:
```
Error creating: admission webhook "validation.webhook.warden.kyma-project.io" denied the request: Pod images europe-docker.pkg.dev/kyma-project/dev/btp-manager:PR-844 validation failed
Error creating: admission webhook "validation.webhook.warden.kyma-project.io" denied the request: Pod images europe-docker.pkg.dev/kyma-project/dev/btp-manager:PR-850 validation failed
```
you must scale the BTP Manager deployment to 0 replicas, delete the webhook, and then scale the deployment back to 1 replica.
```shell
Expand Down
4 changes: 2 additions & 2 deletions ui/src/components/CreateBindingForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ function CreateBindingForm(props: any) {
const [success, setSuccess] = useState("");

const handleCreate = (e: any): boolean => {
setLoading(true)
e.preventDefault();
e.stopPropagation();

Expand All @@ -28,7 +29,6 @@ function CreateBindingForm(props: any) {

createdBinding.service_instance_id = props.instanceId ?? ""

setLoading(true)
axios
.post<ServiceInstanceBinding>(api("service-bindings"), {
name: createdBinding.name,
Expand Down Expand Up @@ -70,6 +70,7 @@ function CreateBindingForm(props: any) {
}

useEffect(() => {
setLoading(true)
if (!Ok(props.instanceId)) {
return;
}
Expand All @@ -82,7 +83,6 @@ function CreateBindingForm(props: any) {
return;
}

setLoading(true)

setLoading(false)
setError(undefined)
Expand Down
1 change: 0 additions & 1 deletion ui/src/components/ServiceBindingsList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,6 @@ const ServiceBindingsList = forwardRef((props: any, ref) => {
setError(error);
setLoading(false);
});
setLoading(false)
} else {
setServiceInstanceBindings(serviceInstancesData)
setLoading(false);
Expand Down
52 changes: 4 additions & 48 deletions ui/src/components/ServiceInstancesDetailsView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
ServiceInstance,
ServiceInstanceBinding,
} from "../shared/models";
import { forwardRef, useEffect, useImperativeHandle, useRef, useState } from "react";
import { forwardRef, useEffect, useRef, useState } from "react";
import ServiceBindingsList from "./ServiceBindingsList";
import '@ui5/webcomponents/dist/features/InputElementsFormSupport.js';
import CreateBindingForm from "./CreateBindingForm";
Expand All @@ -16,34 +16,16 @@ const ServiceInstancesDetailsView = forwardRef((props: any, ref) => {
const [error] = useState<ApiError>();

const [instance, setInstance] = useState<ServiceInstance>();
const dialogRef = useRef(null);
const listRef = useRef(null);

useImperativeHandle(ref, () => ({
MarekMichali marked this conversation as resolved.
Show resolved Hide resolved

open() {
if (dialogRef.current) {
// @ts-ignore
dialogRef.current.show();
}
}

}));

const handleClose = () => {
if (dialogRef.current) {
// @ts-ignore
dialogRef.current.close();
setInstance(undefined);
}
};

const onBindingAdded = (binding: ServiceInstanceBinding) => {
// @ts-ignore
listRef.current.add(binding)
}

useEffect(() => {
setLoading(true);
if (!Ok(props.instance)) {
return;
}
Expand Down Expand Up @@ -74,33 +56,7 @@ const ServiceInstancesDetailsView = forwardRef((props: any, ref) => {
}

return (
<ui5.Dialog
style={{ width: "50%" }}
ref={dialogRef}
onAfterClose={handleClose}
header={
<ui5.Bar
design="Header"
startContent={
<>
<ui5.Title level="H5">
Create {instance?.name} Service Instance
</ui5.Title>
</>
}
/>
}
footer={
<ui5.Bar
design="Footer"
endContent={
<>
<ui5.Button onClick={handleClose}>Close</ui5.Button>
</>
}
/>
}
>
<>
<ui5.Panel headerLevel="H2" headerText="Service Details">
<ui5.Form>
<ui5.FormItem label="Name">
Expand All @@ -116,8 +72,8 @@ const ServiceInstancesDetailsView = forwardRef((props: any, ref) => {
<ui5.Panel headerLevel="H2" headerText="Create Binding">
<CreateBindingForm secret={secret} onCreate={(binding: ServiceInstanceBinding) => onBindingAdded(binding)} instanceId={props.instance.id} instanceName={props.instance.name} />
</ui5.Panel>
</>

</ui5.Dialog>
)
}
// @ts-ignore
Expand Down
131 changes: 88 additions & 43 deletions ui/src/components/ServiceInstancesView.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
import * as ui5 from "@ui5/webcomponents-react";
import { Secret, ServiceInstance, ServiceInstances } from "../shared/models";
import axios from "axios";
import { useEffect, useRef, useState } from "react";
import { createPortal } from "react-dom";
import { useEffect, useState } from "react";
import api from "../shared/api";
import Ok from "../shared/validator";
import serviceInstancesData from '../test-data/serivce-instances.json';
import ServiceInstancesDetailsView from "./ServiceInstancesDetailsView";
import { useParams } from "react-router-dom";
import StatusMessage from "./StatusMessage";
import { splitSecret } from "../shared/common";
import { FCLLayout, FlexibleColumnLayout } from "@ui5/webcomponents-react";

function ServiceInstancesView(props: any) {
const [serviceInstances, setServiceInstances] = useState<ServiceInstances>();
const [secret, setSecret] = useState<Secret>(new Secret());
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
const [selectedInstance, setSelectedInstance] = useState<ServiceInstance>(new ServiceInstance());
const dialogRef = useRef();
MarekMichali marked this conversation as resolved.
Show resolved Hide resolved
const [success, setSuccess] = useState("");
const [layout, setLayout] = useState(FCLLayout.OneColumn);

let { id } = useParams();

Expand All @@ -28,6 +28,9 @@ function ServiceInstancesView(props: any) {
// disable selection when page refresh is done
setSelectedInstance(new ServiceInstance());

// close side panel
setLayout(FCLLayout.OneColumn)

if (!Ok(props.setTitle)) {
return;
}
Expand Down Expand Up @@ -55,7 +58,8 @@ function ServiceInstancesView(props: any) {
if (id) {
const instance = response.data.items.find((instance) => instance.id === id);
if (instance) {
openPortal(instance);
setSelectedInstance(instance)
setLayout(FCLLayout.TwoColumnsMidExpanded)
}
}
setLoading(false);
Expand All @@ -65,15 +69,14 @@ function ServiceInstancesView(props: any) {
setLoading(false);
setError(error);
});
}
}
} else {
setLoading(true)
setServiceInstances(serviceInstancesData)
setLoading(false);
}
}, [id, props, props.secret]);


if (loading) {
return <ui5.BusyIndicator
active
Expand All @@ -82,12 +85,6 @@ function ServiceInstancesView(props: any) {
/>
}

function openPortal(instance: any) {
setSelectedInstance(instance)
//@ts-ignore
dialogRef.current.open()
}

function deleteInstance(id: string): boolean {
setLoading(true);
axios
Expand All @@ -112,13 +109,13 @@ function ServiceInstancesView(props: any) {
return true;
}

const renderData = () => {
const renderTableData = () => {

// @ts-ignore
if (!Ok(serviceInstances) || !Ok(serviceInstances.items)) {
return <ui5.IllustratedMessage name="NoEntries" />
}

return serviceInstances?.items.map((instance, index) => {


Expand All @@ -127,7 +124,8 @@ function ServiceInstancesView(props: any) {
<ui5.TableRow
selected={id === instance.id}
onClick={() => {
openPortal(instance)
setSelectedInstance(instance)
setLayout(FCLLayout.TwoColumnsMidExpanded)
}}
>

Expand Down Expand Up @@ -162,39 +160,86 @@ function ServiceInstancesView(props: any) {
});
};

return (
<>

<StatusMessage
error={error ?? undefined} success={success} />
const renderData = () => {
if (loading) {
return <ui5.BusyIndicator
active
delay={1}
size="Medium"
/>
}

<ui5.Card>
if (error) {

return <>
<div className="margin-wrapper">
<StatusMessage error={error ?? undefined} success={undefined} />
<ui5.IllustratedMessage name="UnableToLoad" />
</div>
</>
}
return (
<>
<FlexibleColumnLayout id="fcl" layout={layout}>

<div selection-mode="Single" slot="startColumn" className="margin-wrapper">

<StatusMessage
error={error ?? undefined} success={success} />

<ui5.Card>
<ui5.Table
columns={
<>
<ui5.TableColumn>
<ui5.Label>Service Instance</ui5.Label>
</ui5.TableColumn>

<ui5.TableColumn>
<ui5.Label>Service Namespace</ui5.Label>
</ui5.TableColumn>

<ui5.TableColumn>
<ui5.Label>Action</ui5.Label>
</ui5.TableColumn>
</>
}
>
{renderTableData()}
</ui5.Table>
</ui5.Card>

</div>


<div slot="midColumn" >
<ui5.Bar>
<div className="icons-container" slot="endContent">
<ui5.Button design="Transparent" icon="full-screen" onClick={() => {
if (layout === FCLLayout.MidColumnFullScreen) {
setLayout(FCLLayout.TwoColumnsMidExpanded)
} else {
setLayout(FCLLayout.MidColumnFullScreen)
}
}}></ui5.Button>
<ui5.Button icon="decline" design="Transparent" onClick={() => {
setLayout(FCLLayout.OneColumn)
}}></ui5.Button>
</div>
</ui5.Bar>
<ServiceInstancesDetailsView secret={secret} instance={selectedInstance} />
</div>

</FlexibleColumnLayout>

</>
);

<ui5.Table
columns={
<>
<ui5.TableColumn>
<ui5.Label>Service Instance</ui5.Label>
</ui5.TableColumn>
};

<ui5.TableColumn>
<ui5.Label>Service Namespace</ui5.Label>
</ui5.TableColumn>
return <>{renderData()}</>;

<ui5.TableColumn>
<ui5.Label>Action</ui5.Label>
</ui5.TableColumn>
</>
}
>
{renderData()}
</ui5.Table>
</ui5.Card>
{createPortal(<ServiceInstancesDetailsView secret={secret} instance={selectedInstance} ref={dialogRef} />, document.getElementById("App")!!)}
MarekMichali marked this conversation as resolved.
Show resolved Hide resolved

</>
);
}


Expand Down
Loading
Loading