Skip to content

Commit 7ecc102

Browse files
authored
Added decimal support to bucket quota selectors (#2126)
- Fixed an issue with calculateBytes function - Fixed add bucket validation form Signed-off-by: Benjamin Perez <benjamin@bexsoft.net>
1 parent a5c1479 commit 7ecc102

File tree

14 files changed

+234
-220
lines changed

14 files changed

+234
-220
lines changed

portal-ui/src/common/utils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -596,7 +596,7 @@ export const calculateBytes = (
596596
// Get unit for measure
597597
const i = Math.floor(Math.log(bytes) / Math.log(k));
598598

599-
const fractionDigits = showDecimals ? 0 : 1;
599+
const fractionDigits = showDecimals ? 1 : 0;
600600

601601
const bytesUnit = bytes / Math.pow(k, i);
602602

portal-ui/src/history.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
11
// check if we are using base path, if not this always is `/`
22
const baseLocation = new URL(document.baseURI);
33
export const baseUrl = baseLocation.pathname;
4-
5-

portal-ui/src/screens/Console/Buckets/BucketDetails/EnableQuota.tsx

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -70,21 +70,34 @@ const EnableQuota = ({
7070
const [quotaEnabled, setQuotaEnabled] = useState<boolean>(false);
7171
const [quotaSize, setQuotaSize] = useState<string>("1");
7272
const [quotaUnit, setQuotaUnit] = useState<string>("Ti");
73+
const [validInput, setValidInput] = useState<boolean>(false);
7374

7475
useEffect(() => {
7576
if (enabled) {
7677
setQuotaEnabled(true);
7778
if (cfg) {
78-
const unitCalc = calculateBytes(cfg.quota, false, false, true);
79+
const unitCalc = calculateBytes(cfg.quota, true, false, true);
7980

8081
setQuotaSize(unitCalc.total.toString());
8182
setQuotaUnit(unitCalc.unit);
83+
setValidInput(true);
8284
}
8385
}
8486
}, [enabled, cfg]);
8587

88+
useEffect(() => {
89+
const valRegExp = /^\d*(?:\.\d{1,2})?$/;
90+
91+
if (!quotaEnabled) {
92+
setValidInput(true);
93+
return;
94+
}
95+
96+
setValidInput(valRegExp.test(quotaSize));
97+
}, [quotaEnabled, quotaSize]);
98+
8699
const enableBucketEncryption = () => {
87-
if (loading) {
100+
if (loading || !validInput) {
88101
return;
89102
}
90103
let req = {
@@ -145,11 +158,13 @@ const EnableQuota = ({
145158
id="quota_size"
146159
name="quota_size"
147160
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
148-
if (e.target.validity.valid) {
149-
setQuotaSize(e.target.value);
161+
setQuotaSize(e.target.value);
162+
if (!e.target.validity.valid) {
163+
setValidInput(false);
164+
} else {
165+
setValidInput(true);
150166
}
151167
}}
152-
pattern={"[0-9]*"}
153168
label="Quota"
154169
value={quotaSize}
155170
required
@@ -165,6 +180,7 @@ const EnableQuota = ({
165180
disabled={false}
166181
/>
167182
}
183+
error={!validInput ? "Please enter a valid quota" : ""}
168184
/>
169185
</Grid>
170186
</Grid>
@@ -189,7 +205,7 @@ const EnableQuota = ({
189205
type="submit"
190206
variant="contained"
191207
color="primary"
192-
disabled={loading}
208+
disabled={loading || !validInput}
193209
>
194210
Save
195211
</Button>

portal-ui/src/screens/Console/Buckets/ListBuckets/AddBucket/AddBucket.tsx

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ const AddBucket = ({ classes }: IsetProps) => {
130130
(state: AppState) => state.addBucket.retentionValidity
131131
);
132132
const addLoading = useSelector((state: AppState) => state.addBucket.loading);
133-
const valid = useSelector((state: AppState) => state.addBucket.valid);
133+
const invalidFields = useSelector((state: AppState) => state.addBucket.invalidFields);
134134
const lockingFieldDisabled = useSelector(
135135
(state: AppState) => state.addBucket.lockingFieldDisabled
136136
);
@@ -285,19 +285,16 @@ const AddBucket = ({ classes }: IsetProps) => {
285285
<React.Fragment>
286286
<Grid item xs={12}>
287287
<InputBoxWrapper
288-
type="number"
288+
type="string"
289289
id="quota_size"
290290
name="quota_size"
291291
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
292-
if (e.target.validity.valid) {
293292
dispatch(setQuotaSize(e.target.value));
294-
}
295293
}}
296294
label="Capacity"
297295
value={quotaSize}
298296
required
299297
min="1"
300-
pattern={"[0-9]*"}
301298
overlayObject={
302299
<InputUnitMenu
303300
id={"quota_unit"}
@@ -309,6 +306,7 @@ const AddBucket = ({ classes }: IsetProps) => {
309306
disabled={false}
310307
/>
311308
}
309+
error={invalidFields.includes("quotaSize") ? "Please enter a valid quota" : ""}
312310
/>
313311
</Grid>
314312
</React.Fragment>
@@ -387,7 +385,7 @@ const AddBucket = ({ classes }: IsetProps) => {
387385
type="submit"
388386
variant="contained"
389387
color="primary"
390-
disabled={addLoading || valid}
388+
disabled={addLoading || invalidFields.length > 0}
391389
>
392390
Create Bucket
393391
</Button>

portal-ui/src/screens/Console/Buckets/ListBuckets/AddBucket/addBucketsSlice.ts

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import { addBucketAsync } from "./addBucketThunks";
1919

2020
export interface AddBucketState {
2121
loading: boolean;
22-
valid: boolean;
22+
invalidFields: string[];
2323
name: string;
2424
versioningEnabled: boolean;
2525
lockingEnabled: boolean;
@@ -36,7 +36,7 @@ export interface AddBucketState {
3636

3737
const initialState: AddBucketState = {
3838
loading: false,
39-
valid: false,
39+
invalidFields: ["name"],
4040
name: "",
4141
versioningEnabled: false,
4242
lockingEnabled: false,
@@ -57,8 +57,11 @@ export const addBucketsSlice = createSlice({
5757
reducers: {
5858
setName: (state, action: PayloadAction<string>) => {
5959
state.name = action.payload;
60+
6061
if (state.name.trim() === "") {
61-
state.valid = false;
62+
state.invalidFields = [...state.invalidFields, "name"];
63+
} else {
64+
state.invalidFields = state.invalidFields.filter((field) => field !== "name");
6265
}
6366
},
6467
setVersioning: (state, action: PayloadAction<boolean>) => {
@@ -75,13 +78,22 @@ export const addBucketsSlice = createSlice({
7578
},
7679
setQuota: (state, action: PayloadAction<boolean>) => {
7780
state.quotaEnabled = action.payload;
81+
82+
if(!action.payload) {
83+
state.quotaSize = "1";
84+
state.quotaUnit = "Ti";
85+
86+
state.invalidFields = state.invalidFields.filter((field) => field !== "quotaSize");
87+
}
7888
},
7989
setQuotaSize: (state, action: PayloadAction<string>) => {
8090
state.quotaSize = action.payload;
8191

82-
if (state.quotaEnabled && state.valid) {
83-
if (state.quotaSize.trim() === "" || parseInt(state.quotaSize) === 0) {
84-
state.valid = false;
92+
if (state.quotaEnabled) {
93+
if (state.quotaSize.trim() === "" || parseInt(state.quotaSize) === 0 || !(/^\d*(?:\.\d{1,2})?$/.test(state.quotaSize))) {
94+
state.invalidFields = [...state.invalidFields, "quotaSize"];
95+
} else {
96+
state.invalidFields = state.invalidFields.filter((field) => field !== "quotaSize");
8597
}
8698
}
8799
},
@@ -109,7 +121,9 @@ export const addBucketsSlice = createSlice({
109121
state.retentionEnabled &&
110122
(Number.isNaN(state.retentionValidity) || state.retentionValidity < 1)
111123
) {
112-
state.valid = false;
124+
state.invalidFields = [...state.invalidFields, "retentionValidity"];
125+
} else {
126+
state.invalidFields = state.invalidFields.filter((field) => field !== "retentionValidity");
113127
}
114128
},
115129
setRetentionMode: (state, action: PayloadAction<string>) => {
@@ -121,10 +135,12 @@ export const addBucketsSlice = createSlice({
121135
setRetentionValidity: (state, action: PayloadAction<number>) => {
122136
state.retentionValidity = action.payload;
123137
if (
124-
state.retentionEnabled &&
125-
(Number.isNaN(state.retentionValidity) || state.retentionValidity < 1)
138+
state.retentionEnabled &&
139+
(Number.isNaN(state.retentionValidity) || state.retentionValidity < 1)
126140
) {
127-
state.valid = false;
141+
state.invalidFields = [...state.invalidFields, "retentionValidity"];
142+
} else {
143+
state.invalidFields = state.invalidFields.filter((field) => field !== "retentionValidity");
128144
}
129145
},
130146

portal-ui/src/screens/Console/Buckets/ListBuckets/BucketListItem.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ const BucketListItem = ({
177177
const usageUnit = usage.split(" ")[1];
178178

179179
const quota = get(bucket, "details.quota.quota", "0");
180-
const quotaForString = calculateBytes(quota);
180+
const quotaForString = calculateBytes(quota, true, false);
181181

182182
const accessToStr = (bucket: Bucket): string => {
183183
if (bucket.rw_access?.read && !bucket.rw_access?.write) {

portal-ui/src/screens/Console/Configurations/TiersConfiguration/AddTierConfiguration.tsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,7 @@ interface IAddNotificationEndpointProps {
7878
classes: any;
7979
}
8080

81-
const AddTierConfiguration = ({
82-
classes,
83-
}: IAddNotificationEndpointProps) => {
81+
const AddTierConfiguration = ({ classes }: IAddNotificationEndpointProps) => {
8482
const dispatch = useAppDispatch();
8583
const navigate = useNavigate();
8684
const params = useParams();

portal-ui/src/screens/Console/Policies/PolicySelectors.tsx

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -85,11 +85,13 @@ const PolicySelectors = ({
8585
const [loading, isLoading] = useState<boolean>(false);
8686
const [filter, setFilter] = useState<string>("");
8787

88-
const currentPolicies = useSelector((state: AppState) => state.createUser.selectedPolicies);
88+
const currentPolicies = useSelector(
89+
(state: AppState) => state.createUser.selectedPolicies
90+
);
8991

9092
const fetchPolicies = useCallback(() => {
9193
isLoading(true);
92-
94+
9395
api
9496
.invoke("GET", `/api/v1/policies?limit=1000`)
9597
.then((res: PolicyList) => {
@@ -115,11 +117,10 @@ const PolicySelectors = ({
115117
}, [loading, fetchPolicies]);
116118

117119
const selectionChanged = (e: React.ChangeEvent<HTMLInputElement>) => {
118-
119120
const targetD = e.target;
120121
const value = targetD.value;
121122
const checked = targetD.checked;
122-
123+
123124
let elements: string[] = [...currentPolicies]; // We clone the checkedUsers array
124125

125126
if (checked) {
@@ -131,7 +132,7 @@ const PolicySelectors = ({
131132
}
132133
// remove empty values
133134
elements = elements.filter((element) => element !== "");
134-
135+
135136
dispatch(setSelectedPolicies(elements));
136137
};
137138

portal-ui/src/screens/Console/Policies/SetPolicy.tsx

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,6 @@ interface ISetPolicyProps {
4848
open: boolean;
4949
}
5050

51-
52-
5351
const styles = (theme: Theme) =>
5452
createStyles({
5553
...modalBasic,
@@ -76,7 +74,9 @@ const SetPolicy = ({
7674
const [loading, setLoading] = useState<boolean>(false);
7775
const [actualPolicy, setActualPolicy] = useState<string[]>([]);
7876
const [selectedPolicy, setSelectedPolicy] = useState<string[]>([]);
79-
const currentPolicies = useSelector((state: AppState) => state.createUser.selectedPolicies);
77+
const currentPolicies = useSelector(
78+
(state: AppState) => state.createUser.selectedPolicies
79+
);
8080
const setPolicyAction = () => {
8181
let users = null;
8282
let groups = null;
@@ -175,9 +175,7 @@ const SetPolicy = ({
175175
)}
176176
<Grid item xs={12}>
177177
<div className={classes.tableBlock}>
178-
<PolicySelectors
179-
selectedPolicy={selectedPolicy}
180-
/>
178+
<PolicySelectors selectedPolicy={selectedPolicy} />
181179
</div>
182180
</Grid>
183181
</Grid>

0 commit comments

Comments
 (0)