Fixed multiple issues on object browser upload (#1955)

- Fixed issue with double slashes on upload manager
- Fixed sub folders not uploading in the correct subpaths location
- Fixed an issue upload when a file is already selected
- Fixed an issue with create path button with paths finished on slash
- Simplified path handling  for object browser

Signed-off-by: Benjamin Perez <benjamin@bexsoft.net>
This commit is contained in:
Alex
2022-05-06 13:33:13 -05:00
committed by GitHub
parent 6d22aa9955
commit 3854372f4d
5 changed files with 104 additions and 61 deletions

View File

@@ -27,7 +27,7 @@ import {
} from "../../../../Common/FormComponents/common/styleLibrary";
import { connect } from "react-redux";
import history from "../../../../../../history";
import { decodeFileName, encodeFileName } from "../../../../../../common/utils";
import { encodeFileName } from "../../../../../../common/utils";
import { setModalErrorSnackMessage } from "../../../../../../actions";
import { BucketObjectItem } from "./types";
import { CreateNewPathIcon } from "../../../../../../icons";
@@ -40,8 +40,7 @@ interface ICreatePath {
folderName: string;
onClose: () => any;
existingFiles: BucketObjectItem[];
detailsOpen: boolean;
selectedInternalPaths: string | null;
simplePath: string | null;
setModalErrorSnackMessage: typeof setModalErrorSnackMessage;
}
@@ -59,53 +58,31 @@ const CreatePathModal = ({
setModalErrorSnackMessage,
classes,
existingFiles,
detailsOpen,
selectedInternalPaths,
simplePath,
}: ICreatePath) => {
const [pathUrl, setPathUrl] = useState("");
const [isFormValid, setIsFormValid] = useState<boolean>(false);
const [currentPath, setCurrentPath] = useState(bucketName);
let currentPath = `${bucketName}/${decodeFileName(folderName)}`;
useEffect(() => {
if(simplePath) {
const newPath = `${bucketName}${
!bucketName.endsWith("/") && !simplePath.startsWith("/") ? "/" : ""
}${simplePath}`;
if (selectedInternalPaths && detailsOpen) {
const decodedPathFileName = decodeFileName(selectedInternalPaths).split(
"/"
);
if (decodedPathFileName) {
decodedPathFileName.pop();
const joinFileName = decodedPathFileName.join("/");
const joinPaths = `${joinFileName}${
joinFileName.endsWith("/") ? "" : "/"
}`;
currentPath = `${bucketName}/${joinPaths}`;
setCurrentPath(newPath);
}
}
}, [simplePath, bucketName]);
const resetForm = () => {
setPathUrl("");
};
const createProcess = () => {
let folderPath = "";
let folderPath = "/";
if (selectedInternalPaths && detailsOpen) {
const decodedPathFileName = decodeFileName(selectedInternalPaths).split(
"/"
);
if (decodedPathFileName) {
decodedPathFileName.pop();
const joinFileName = decodedPathFileName.join("/");
folderPath = `${joinFileName}${joinFileName.endsWith("/") ? "" : "/"}`;
}
} else {
if (folderName !== "") {
const decodedFolderName = decodeFileName(folderName);
folderPath = decodedFolderName.endsWith("/")
? decodedFolderName
: `${decodedFolderName}/`;
}
if (simplePath) {
folderPath = simplePath.endsWith("/") ? simplePath : `${simplePath}/`;
}
const sharesName = (record: BucketObjectItem) =>
@@ -118,8 +95,14 @@ const CreatePathModal = ({
});
return;
}
const cleanPathURL = pathUrl
.split("/")
.filter((splitItem) => splitItem.trim() !== "")
.join("/");
const newPath = `/buckets/${bucketName}/browse/${encodeFileName(
`${folderPath}${pathUrl}/`
`${folderPath}${cleanPathURL}/`
)}`;
history.push(newPath);
onClose();
@@ -205,8 +188,7 @@ const CreatePathModal = ({
};
const mapStateToProps = ({ objectBrowser }: AppState) => ({
detailsOpen: objectBrowser.objectDetailsOpen,
selectedInternalPaths: objectBrowser.selectedInternalPaths,
simplePath: objectBrowser.simplePath,
});
const mapDispatchToProps = {

View File

@@ -65,6 +65,7 @@ import {
setSearchObjects,
setSelectedObjectView,
setShowDeletedObjects,
setSimplePathHandler,
setVersionsModeEnabled,
updateProgress,
} from "../../../../ObjectBrowser/actions";
@@ -221,14 +222,15 @@ interface IListObjectsProps {
searchObjects: string;
showDeleted: boolean;
loading: boolean;
setSnackBarMessage: typeof setSnackBarMessage;
setErrorSnackMessage: typeof setErrorSnackMessage;
resetRewind: typeof resetRewind;
loadingBucket: boolean;
setBucketInfo: typeof setBucketInfo;
bucketInfo: BucketInfo | null;
versionsMode: boolean;
detailsOpen: boolean;
simplePath: string | null;
setSnackBarMessage: typeof setSnackBarMessage;
setErrorSnackMessage: typeof setErrorSnackMessage;
resetRewind: typeof resetRewind;
setBucketInfo: typeof setBucketInfo;
setBucketDetailsLoad: typeof setBucketDetailsLoad;
setNewObject: typeof setNewObject;
updateProgress: typeof updateProgress;
@@ -245,6 +247,7 @@ interface IListObjectsProps {
setLoadingObjectsList: typeof setLoadingObjectsList;
failObject: typeof failObject;
cancelObjectInList: typeof cancelObjectInList;
setSimplePathHandler: typeof setSimplePathHandler;
}
function useInterval(callback: any, delay: number) {
@@ -294,6 +297,7 @@ const ListObjects = ({
searchObjects,
versionsMode,
openList,
simplePath,
setVersionsModeEnabled,
showDeleted,
detailsOpen,
@@ -306,6 +310,7 @@ const ListObjects = ({
setLoadingObjectsList,
failObject,
cancelObjectInList,
setSimplePathHandler,
}: IListObjectsProps) => {
const [records, setRecords] = useState<BucketObjectItem[]>([]);
const [deleteMultipleOpen, setDeleteMultipleOpen] = useState<boolean>(false);
@@ -482,9 +487,9 @@ const ListObjects = ({
const decodedIPaths = decodeFileName(internalPaths);
if (decodedIPaths.endsWith("/") || decodedIPaths === "") {
setLoadingObjectsList(true);
setObjectDetailsView(false);
setSearchObjects("");
setSelectedObjectView(null);
setSimplePathHandler(decodedIPaths === "" ? "/" : decodedIPaths);
} else {
setLoadingObjectInfo(true);
setObjectDetailsView(true);
@@ -492,19 +497,27 @@ const ListObjects = ({
setSelectedObjectView(
`${decodedIPaths ? `${encodeFileName(decodedIPaths)}` : ``}`
);
setSimplePathHandler(
`${decodedIPaths.split("/").slice(0, -1).join("/")}/`
);
}
}, [
internalPaths,
setSearchObjects,
rewindDate,
rewindEnabled,
setLoadingObjectInfo,
setLoadingVersions,
setObjectDetailsView,
setSelectedObjectView,
setLoadingObjectsList,
setSimplePathHandler,
]);
useEffect(() => {
setSearchObjects("");
setLoadingObjectsList(true);
setSelectedObjects([]);
}, [simplePath, setSearchObjects, setLoadingObjectsList, setSelectedObjects]);
useEffect(() => {
if (loading) {
if (displayListObjects) {
@@ -795,11 +808,8 @@ const ListObjects = ({
const uploadObject = useCallback(
(files: File[], folderPath: string): void => {
let pathPrefix = "";
if (internalPaths) {
const decodedPath = decodeFileName(internalPaths);
pathPrefix = decodedPath.endsWith("/")
? decodedPath
: decodedPath + "/";
if (simplePath) {
pathPrefix = simplePath.endsWith("/") ? simplePath : simplePath + "/";
}
const upload = (
@@ -812,13 +822,23 @@ const ListObjects = ({
return new Promise((resolve, reject) => {
let uploadUrl = `api/v1/buckets/${bucketName}/objects/upload`;
const fileName = file.name;
const blobFile = new Blob([file], { type: file.type });
let encodedPath = "";
const relativeFolderPath =
get(file, "webkitRelativePath", "") !== ""
? get(file, "webkitRelativePath", "")
: folderPath;
const filePath = get(file, "path", "");
const fileWebkitRelativePath = get(file, "webkitRelativePath", "");
let relativeFolderPath = folderPath;
// File was uploaded via drag & drop
if (filePath !== "") {
relativeFolderPath = filePath;
} else if (fileWebkitRelativePath !== "") {
// File was uploaded using upload button
relativeFolderPath = fileWebkitRelativePath;
}
if (path !== "" || relativeFolderPath !== "") {
const finalFolderPath = relativeFolderPath
@@ -826,9 +846,20 @@ const ListObjects = ({
.slice(0, -1)
.join("/");
const pathClean = path.endsWith("/") ? path.slice(0, -1) : path;
encodedPath = encodeFileName(
`${path}${finalFolderPath}${
!finalFolderPath.endsWith("/") ? "/" : ""
`${pathClean}${
!pathClean.endsWith("/") &&
finalFolderPath !== "" &&
!finalFolderPath.startsWith("/")
? "/"
: ""
}${finalFolderPath}${
!finalFolderPath.endsWith("/") ||
(finalFolderPath.trim() === "" && !path.endsWith("/"))
? "/"
: ""
}`
);
}
@@ -947,6 +978,7 @@ const ListObjects = ({
}
// We force objects list reload after all promises were handled
setLoadingObjectsList(true);
setSelectedObjects([]);
});
};
@@ -955,7 +987,6 @@ const ListObjects = ({
[
bucketName,
completeObject,
internalPaths,
openList,
setNewObject,
setErrorSnackMessage,
@@ -963,6 +994,7 @@ const ListObjects = ({
setLoadingObjectsList,
cancelObjectInList,
failObject,
simplePath,
]
);
@@ -1502,6 +1534,7 @@ const mapStateToProps = ({ objectBrowser, buckets }: AppState) => ({
detailsOpen: objectBrowser.objectDetailsOpen,
selectedInternalPaths: objectBrowser.selectedInternalPaths,
loading: objectBrowser.loadingObjects,
simplePath: objectBrowser.simplePath,
});
const mapDispatchToProps = {
@@ -1524,6 +1557,7 @@ const mapDispatchToProps = {
setLoadingObjectInfo,
setLoadingObjectsList,
cancelObjectInList,
setSimplePathHandler,
};
const connector = connect(mapStateToProps, mapDispatchToProps);

View File

@@ -37,6 +37,7 @@ import {
REWIND_RESET_REWIND,
REWIND_SET_ENABLE,
BUCKET_BROWSER_SET_SELECTED_OBJECT,
BUCKET_BROWSER_SET_SIMPLE_PATH,
IFileItem,
} from "./types";
@@ -199,3 +200,10 @@ export const setSelectedObjectView = (object: string | null) => {
object,
};
};
export const setSimplePathHandler = (path: string | null) => {
return {
type: BUCKET_BROWSER_SET_SIMPLE_PATH,
path,
};
};

View File

@@ -39,6 +39,7 @@ import {
OBJECT_MANAGER_SET_LOADING,
OBJECT_MANAGER_ERROR_IN_OBJECT,
OBJECT_MANAGER_CANCEL_OBJECT,
BUCKET_BROWSER_SET_SIMPLE_PATH,
} from "./types";
const defaultRewind = {
@@ -67,6 +68,7 @@ const initialState: ObjectBrowserState = {
selectedVersion: "",
showDeleted: false,
selectedInternalPaths: null,
simplePath: null,
};
export function objectBrowserReducer(
@@ -295,12 +297,20 @@ export function objectBrowserReducer(
return {
...state,
objectDetailsOpen: action.status,
selectedInternalPaths: action.status
? state.selectedInternalPaths
: null,
};
case BUCKET_BROWSER_SET_SELECTED_OBJECT:
return {
...state,
selectedInternalPaths: action.object,
};
case BUCKET_BROWSER_SET_SIMPLE_PATH:
return {
...state,
simplePath: action.path,
};
default:
return state;
}

View File

@@ -47,6 +47,8 @@ export const BUCKET_BROWSER_OBJECT_DETAILS_STATE =
"BUCKET_BROWSER/OBJECT_DETAILS_STATE";
export const BUCKET_BROWSER_SET_SELECTED_OBJECT =
"BUCKET_BROWSER/SET_SELECTED_OBJECT";
export const BUCKET_BROWSER_SET_SIMPLE_PATH =
"BUCKET_BROWSER/SET_SIMPLE_PATH";
export interface Route {
route: string;
@@ -74,6 +76,7 @@ export interface ObjectBrowserState {
showDeleted: boolean;
objectDetailsOpen: boolean;
selectedInternalPaths: string | null;
simplePath: string | null;
}
export interface ObjectBrowserReducer {
@@ -209,6 +212,11 @@ interface CancelObjectInManager {
instanceID: string;
}
interface SetBrowserPath {
type: typeof BUCKET_BROWSER_SET_SIMPLE_PATH;
path: string;
}
export type ObjectBrowserActionTypes =
| RewindSetEnabled
| RewindReset
@@ -231,4 +239,5 @@ export type ObjectBrowserActionTypes =
| SetObjectDetailsState
| SetSelectedObject
| SetObjectManagerLoading
| CancelObjectInManager;
| CancelObjectInManager
| SetBrowserPath;