Skip to content

Commit

Permalink
Flexible Column Layout for Offerings and Instances Views (#850)
Browse files Browse the repository at this point in the history
* Flexible Column Layout for Offerings and Instances

* Updated PR Number

* Unnecessary DialogRef and OpenPortal

* Corrected Border Radius and Error Message Margin

Main object page was displaied with rounder bottom corners, which is not compliant with how Busola displays it. Additionally, error message was rendered just at the top of its component withouth any margins.

* Removed Unused Imports

* UnableToLoad Page Corrections

Copied the same mechanics from offerings view for displaying error message when secret data is not able to load hiding main view. Previously, the view for service instances was rendered without any data. Not it is hidden behind error banner.

Added additional error message to UnableToLoad banner to show more detailed message of what has gone wrong.

* Unused Import

* Unused Import

* Closing Panel on Selected Secret Change
  • Loading branch information
ralikio authored Aug 29, 2024
1 parent c45c9a2 commit fa5711a
Show file tree
Hide file tree
Showing 9 changed files with 170 additions and 166 deletions.
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, () => ({

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();
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")!!)}

</>
);
}


Expand Down
Loading

0 comments on commit fa5711a

Please sign in to comment.