Skip to content

Commit 9937d47

Browse files
authored
Merge pull request #135 from sapcc/marketplace
Add commitment marketplace
2 parents 5028ad7 + 5901521 commit 9937d47

32 files changed

+1008
-137
lines changed

.changeset/evil-ideas-mix.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@sapcc/limes-ui": minor
3+
---
4+
5+
Add commitment marketplace.

src/components/commitment/CommitmentTable.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ const CommitmentTable = (props) => {
3131
const { commitmentIsFetching } = createCommitmentStore();
3232
const commitmentTransferID = React.useRef(null);
3333
const { isCommitting } = createCommitmentStore();
34-
const { serviceType, currentCategory, currentResource, currentAZ, commitmentData, mergeOps } = {
34+
const { serviceType, currentCategory, currentResource, currentTab, commitmentData, mergeOps } = {
3535
...props,
3636
};
3737
const durations = getResourceDurations(currentResource);
@@ -90,9 +90,9 @@ const CommitmentTable = (props) => {
9090

9191
//Add or remove edit commitment row.
9292
const filteredCommitments = React.useMemo(() => {
93-
const filteredData = filterCommitments(resourceName, currentAZ);
93+
const filteredData = filterCommitments(resourceName, currentTab);
9494
return filteredData;
95-
}, [commitmentData, currentAZ, resourceName]);
95+
}, [commitmentData, currentTab, resourceName]);
9696

9797
const { items, TableSortHeader } = useSortTableData(filteredCommitments, initialSortConfig);
9898

@@ -134,7 +134,7 @@ const CommitmentTable = (props) => {
134134
serviceType={serviceType}
135135
currentCategory={currentCategory}
136136
currentResource={currentResource}
137-
currentAZ={currentAZ}
137+
currentTab={currentTab}
138138
commitmentTransferID={commitmentTransferID}
139139
mergeOps={mergeOps}
140140
/>

src/components/commitment/CommitmentTableDetails.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ const transferLabel = Object.freeze({
3232
});
3333

3434
const CommitmentTableDetails = (props) => {
35-
const { commitment, commitmentTransferID, mergeOps } = props;
35+
const { currentTab, commitment, commitmentTransferID, mergeOps } = props;
3636
const {
3737
id,
3838
amount,
@@ -49,7 +49,6 @@ const CommitmentTableDetails = (props) => {
4949
const serviceType = props.serviceType;
5050
const currentResource = props.currentResource;
5151
const resourceName = currentResource?.name;
52-
const currentAZ = props.currentAZ;
5352
const isAddingCommitment = id === COMMITMENTID ? true : false;
5453
const { commitment: newCommitment } = createCommitmentStore();
5554
const { commitmentIsLoading } = createCommitmentStore();
@@ -110,7 +109,7 @@ const CommitmentTableDetails = (props) => {
110109
...newCommitment,
111110
service_type: serviceType,
112111
resource_name: resourceName,
113-
availability_zone: currentAZ,
112+
availability_zone: currentTab,
114113
amount: parsedInput,
115114
durationLabel: durationLabel.current,
116115
});
@@ -235,7 +234,9 @@ const CommitmentTableDetails = (props) => {
235234
}}
236235
disabled={newCommitment?.id == id}
237236
>
238-
{commitment.id == commitmentTransferID.current ? transferLabel.Selected : transferLabel.Move}
237+
{isTransferring && commitment.id == commitmentTransferID.current
238+
? transferLabel.Selected
239+
: transferLabel.Move}
239240
</Button>
240241
<Button
241242
size="small"
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
/**
2+
* Copyright 2025 SAP SE
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import React from "react";
18+
import { DataGrid, DataGridRow, IntroBox, LoadingIndicator, Message } from "@cloudoperators/juno-ui-components/index";
19+
import useSortTableData from "../../hooks/useSortTable";
20+
import MarketplaceDetails from "./MarketplaceDetails";
21+
22+
const Marketplace = (props) => {
23+
const { project, resource, publicCommitmentQuery, transferCommitment } = props;
24+
const { data, isLoading, isError, error } = publicCommitmentQuery;
25+
const publicCommitments = data?.commitments || [];
26+
27+
const initialSortConfig = {
28+
expires_at: {
29+
direction: "ascending",
30+
sortStrategy: "numeric",
31+
},
32+
};
33+
const { items, TableSortHeader } = useSortTableData(publicCommitments, initialSortConfig);
34+
35+
const headCells = [
36+
{
37+
key: "amount",
38+
label: "Amount",
39+
sortStrategy: "numeric",
40+
},
41+
{
42+
key: "availability_zone",
43+
label: "Zone",
44+
sortStrategy: "text",
45+
},
46+
{
47+
key: "duration",
48+
label: "Duration",
49+
sortStrategy: "text",
50+
},
51+
{
52+
key: "expires_at",
53+
label: "Expires",
54+
sortStrategy: "numeric",
55+
},
56+
{
57+
key: "edit",
58+
label: "Actions",
59+
},
60+
];
61+
62+
return (
63+
(isLoading && <LoadingIndicator className="m-auto" />) ||
64+
(isError && <Message variant="danger" text={error.toString()} />) ||
65+
(publicCommitments.length == 0 && <IntroBox text="No commitments available." />) || (
66+
<DataGrid columns={headCells.length}>
67+
<DataGridRow>
68+
{headCells.map((headCell) => (
69+
<TableSortHeader
70+
key={headCell.key}
71+
identifier={headCell.key}
72+
value={headCell.label}
73+
sortStrategy={headCell.sortStrategy}
74+
/>
75+
))}
76+
</DataGridRow>
77+
{items.map((commitment) => (
78+
<MarketplaceDetails
79+
key={commitment.id}
80+
project={project}
81+
resource={resource}
82+
commitment={commitment}
83+
transferCommitment={transferCommitment}
84+
/>
85+
))}
86+
</DataGrid>
87+
)
88+
);
89+
};
90+
91+
export default Marketplace;
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/**
2+
* Copyright 2025 SAP SE
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import React from "react";
18+
import { DataGridRow, DataGridCell, Stack, Button } from "@cloudoperators/juno-ui-components/index";
19+
import { valueWithUnit, Unit } from "../../lib/unit";
20+
import { formatTimeISO8160, formatTime } from "../../lib/utils";
21+
import useCommitmentFilter from "../../hooks/useCommitmentFilter";
22+
import ToolTipWrapper from "../shared/ToolTipWrapper";
23+
import MarketplaceModal from "./Modals/MarketplaceModal";
24+
25+
const MarketplaceDetails = (props) => {
26+
const { project, resource, commitment, transferCommitment } = props;
27+
const unit = new Unit(resource.unit);
28+
const { getCommitmentLabel } = useCommitmentFilter();
29+
const [showModal, setShowModal] = React.useState(false);
30+
31+
return (
32+
<DataGridRow>
33+
<DataGridCell>{valueWithUnit(commitment.amount, unit)}</DataGridCell>
34+
<DataGridCell>{commitment.availability_zone}</DataGridCell>
35+
<DataGridCell>{commitment.duration}</DataGridCell>
36+
<DataGridCell className="items-start">
37+
<ToolTipWrapper
38+
trigger={formatTimeISO8160(commitment.expires_at)}
39+
content={formatTime(commitment.expires_at, "YYYY-MM-DD HH:mm A")}
40+
/>
41+
</DataGridCell>
42+
<DataGridCell>
43+
<Stack gap="1" distribution="between">
44+
{getCommitmentLabel(commitment)}{" "}
45+
<Button variant="primary" icon="download" size="small" onClick={() => setShowModal(true)} />
46+
</Stack>
47+
</DataGridCell>
48+
{showModal && (
49+
<MarketplaceModal
50+
action={transferCommitment}
51+
title="Marketplace: Receive commitment"
52+
subText="receive"
53+
onModalClose={() => {
54+
setShowModal(false);
55+
}}
56+
project={project}
57+
commitment={commitment}
58+
/>
59+
)}
60+
</DataGridRow>
61+
);
62+
};
63+
64+
export default MarketplaceDetails;

src/components/commitment/Modals/CommitmentModal.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ import { formatTimeISO8160 } from "../../../lib/utils";
3434
const label = "font-semibold";
3535

3636
const CommitmentModal = (props) => {
37-
const { action, az, canConfirm, commitment, minConfirmDate, onModalClose, subText, title } = { ...props };
37+
const { action, currentTab, canConfirm, commitment, minConfirmDate, onModalClose, subText, title } = { ...props };
3838
const unit = new Unit(commitment.unit);
3939
const { ConfirmInput, inputProps, checkInput } = useConfirmInput({ confirmationText: subText });
4040
const hasMinConfirmDate = minConfirmDate ? true : false;
@@ -99,7 +99,7 @@ const CommitmentModal = (props) => {
9999
<DataGrid columns={2} className={!showCalendar ? "mb-6" : "mb-0"} columnMaxSize="1fr">
100100
<DataGridRow>
101101
<DataGridCell className={label}>Availability Zone:</DataGridCell>
102-
<DataGridCell>{az}</DataGridCell>
102+
<DataGridCell>{currentTab}</DataGridCell>
103103
</DataGridRow>
104104
<DataGridRow>
105105
<DataGridCell className={label}>Amount:</DataGridCell>

src/components/commitment/Modals/CommitmentModal.test.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ describe("test commitment creation modal", () => {
3737
<CommitmentModal
3838
title="Confirm commitment creation"
3939
subText="Commit"
40-
az={"az1"}
40+
currentTab={"az1"}
4141
canConfirm={false}
4242
minConfirmDate={null}
4343
commitment={newCommitment}
@@ -70,7 +70,7 @@ describe("test commitment creation modal", () => {
7070
<CommitmentModal
7171
title="Confirm commitment creation"
7272
subText="Commit"
73-
az={"az1"}
73+
currentTab={"az1"}
7474
canConfirm={true}
7575
minConfirmDate={moment(new Date("2024-01-01T00:00:00.000Z")).utc().unix()}
7676
commitment={newCommitment}
@@ -102,7 +102,7 @@ describe("test commitment creation modal", () => {
102102
<CommitmentModal
103103
title="Confirm commitment creation"
104104
subText="Commit"
105-
az={"az1"}
105+
currentTab={"az1"}
106106
canConfirm={true}
107107
minConfirmDate={moment(new Date("2024-01-02T00:00:00.000Z")).utc().unix()}
108108
commitment={newCommitment}
@@ -143,7 +143,7 @@ describe("test commitment creation modal", () => {
143143
<CommitmentModal
144144
title="Confirm commitment creation"
145145
subText="Commit"
146-
az={"az1"}
146+
currentTab={"az1"}
147147
canConfirm={true}
148148
commitment={newCommitment}
149149
action={onConfirm}

src/components/commitment/Modals/DeleteModal.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import { Unit } from "../../../lib/unit";
2424
const label = "font-semibold";
2525

2626
const DeleteModal = (props) => {
27-
const { action, az, title, subText, onModalClose, commitment } = props;
27+
const { action, currentTab, title, subText, onModalClose, commitment } = props;
2828
const unit = new Unit(commitment.unit);
2929
const { ConfirmInput, inputProps, checkInput } = useConfirmInput({
3030
confirmationText: subText,
@@ -54,7 +54,7 @@ const DeleteModal = (props) => {
5454
<DataGrid columns={2} columnMaxSize="1fr">
5555
<DataGridRow>
5656
<DataGridCell className={label}>Availability Zone:</DataGridCell>
57-
<DataGridCell>{az}</DataGridCell>
57+
<DataGridCell>{currentTab}</DataGridCell>
5858
</DataGridRow>
5959
<DataGridRow>
6060
<DataGridCell className={label}>Amount:</DataGridCell>

0 commit comments

Comments
 (0)