github.com/minio/console@v1.4.1/web-app/src/screens/Console/Buckets/ListBuckets/AddBucket/addBucketsSlice.ts (about) 1 // This file is part of MinIO Console Server 2 // Copyright (c) 2022 MinIO, Inc. 3 // 4 // This program is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Affero General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // This program is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Affero General Public License for more details. 13 // 14 // You should have received a copy of the GNU Affero General Public License 15 // along with this program. If not, see <http://www.gnu.org/licenses/>. 16 17 import { createSlice, PayloadAction } from "@reduxjs/toolkit"; 18 import { addBucketAsync } from "./addBucketThunks"; 19 import { ObjectRetentionMode } from "api/consoleApi"; 20 21 export interface AddBucketState { 22 loading: boolean; 23 isDirty: boolean; 24 invalidFields: string[]; 25 name: string; 26 versioningEnabled: boolean; 27 lockingEnabled: boolean; 28 lockingFieldDisabled: boolean; 29 quotaEnabled: boolean; 30 quotaSize: string; 31 quotaUnit: string; 32 retentionEnabled: boolean; 33 retentionMode: ObjectRetentionMode; 34 retentionUnit: string; 35 retentionValidity: number; 36 navigateTo: string; 37 excludeFolders: boolean; 38 excludedPrefixes: string; 39 } 40 41 const initialState: AddBucketState = { 42 loading: false, 43 isDirty: false, 44 invalidFields: [], 45 name: "", 46 versioningEnabled: false, 47 lockingEnabled: false, 48 lockingFieldDisabled: false, 49 quotaEnabled: false, 50 quotaSize: "1", 51 quotaUnit: "Ti", 52 retentionEnabled: false, 53 retentionMode: ObjectRetentionMode.Compliance, 54 retentionUnit: "days", 55 retentionValidity: 180, 56 navigateTo: "", 57 excludeFolders: false, 58 excludedPrefixes: "", 59 }; 60 61 export const addBucketsSlice = createSlice({ 62 name: "addBuckets", 63 initialState, 64 reducers: { 65 setIsDirty: (state, action: PayloadAction<boolean>) => { 66 state.isDirty = action.payload; 67 }, 68 setName: (state, action: PayloadAction<string>) => { 69 state.name = action.payload; 70 71 if (state.name.trim() === "") { 72 state.invalidFields = [...state.invalidFields, "name"]; 73 } else { 74 state.invalidFields = state.invalidFields.filter( 75 (field) => field !== "name", 76 ); 77 } 78 }, 79 setVersioning: (state, action: PayloadAction<boolean>) => { 80 state.versioningEnabled = action.payload; 81 if (!state.versioningEnabled || !state.retentionEnabled) { 82 state.retentionEnabled = false; 83 state.retentionMode = ObjectRetentionMode.Compliance; 84 state.retentionUnit = "days"; 85 state.retentionValidity = 180; 86 } 87 }, 88 setExcludeFolders: (state, action: PayloadAction<boolean>) => { 89 state.excludeFolders = action.payload; 90 }, 91 setExcludedPrefixes: (state, action: PayloadAction<string>) => { 92 state.excludedPrefixes = action.payload; 93 }, 94 setEnableObjectLocking: (state, action: PayloadAction<boolean>) => { 95 state.lockingEnabled = action.payload; 96 }, 97 setQuota: (state, action: PayloadAction<boolean>) => { 98 state.quotaEnabled = action.payload; 99 100 if (!action.payload) { 101 state.quotaSize = "1"; 102 state.quotaUnit = "Ti"; 103 104 state.invalidFields = state.invalidFields.filter( 105 (field) => field !== "quotaSize", 106 ); 107 } 108 }, 109 setQuotaSize: (state, action: PayloadAction<string>) => { 110 state.quotaSize = action.payload; 111 112 if (state.quotaEnabled) { 113 if ( 114 state.quotaSize.trim() === "" || 115 parseInt(state.quotaSize) === 0 || 116 !/^\d*(?:\.\d{1,2})?$/.test(state.quotaSize) 117 ) { 118 state.invalidFields = [...state.invalidFields, "quotaSize"]; 119 } else { 120 state.invalidFields = state.invalidFields.filter( 121 (field) => field !== "quotaSize", 122 ); 123 } 124 } 125 }, 126 setQuotaUnit: (state, action: PayloadAction<string>) => { 127 state.quotaUnit = action.payload; 128 }, 129 setRetention: (state, action: PayloadAction<boolean>) => { 130 state.retentionEnabled = action.payload; 131 if (!state.versioningEnabled || !state.retentionEnabled) { 132 state.retentionEnabled = false; 133 state.retentionMode = ObjectRetentionMode.Compliance; 134 state.retentionUnit = "days"; 135 state.retentionValidity = 180; 136 } 137 138 if (state.retentionEnabled) { 139 // if retention is enabled, then object locking should be enabled as well 140 state.lockingEnabled = true; 141 state.lockingFieldDisabled = true; 142 } else { 143 state.lockingFieldDisabled = false; 144 } 145 146 if ( 147 state.retentionEnabled && 148 (Number.isNaN(state.retentionValidity) || state.retentionValidity < 1) 149 ) { 150 state.invalidFields = [...state.invalidFields, "retentionValidity"]; 151 } else { 152 state.invalidFields = state.invalidFields.filter( 153 (field) => field !== "retentionValidity", 154 ); 155 } 156 }, 157 setRetentionMode: (state, action: PayloadAction<ObjectRetentionMode>) => { 158 state.retentionMode = action.payload; 159 }, 160 setRetentionUnit: (state, action: PayloadAction<string>) => { 161 state.retentionUnit = action.payload; 162 }, 163 setRetentionValidity: (state, action: PayloadAction<number>) => { 164 state.retentionValidity = action.payload; 165 if ( 166 state.retentionEnabled && 167 (Number.isNaN(state.retentionValidity) || state.retentionValidity < 1) 168 ) { 169 state.invalidFields = [...state.invalidFields, "retentionValidity"]; 170 } else { 171 state.invalidFields = state.invalidFields.filter( 172 (field) => field !== "retentionValidity", 173 ); 174 } 175 }, 176 177 resetForm: (state) => initialState, 178 }, 179 extraReducers: (builder) => { 180 builder 181 .addCase(addBucketAsync.pending, (state) => { 182 state.loading = true; 183 }) 184 .addCase(addBucketAsync.rejected, (state) => { 185 state.loading = false; 186 }) 187 .addCase(addBucketAsync.fulfilled, (state, action) => { 188 state.loading = false; 189 state.navigateTo = action.payload.data.bucketName 190 ? "/buckets" 191 : `/buckets/${action.payload.data.bucketName}/admin`; 192 }); 193 }, 194 }); 195 196 export const { 197 setName, 198 setIsDirty, 199 setVersioning, 200 setEnableObjectLocking, 201 setQuota, 202 setQuotaSize, 203 setQuotaUnit, 204 resetForm, 205 setRetention, 206 setRetentionMode, 207 setRetentionUnit, 208 setRetentionValidity, 209 setExcludedPrefixes, 210 setExcludeFolders, 211 } = addBucketsSlice.actions; 212 213 export default addBucketsSlice.reducer;