mirror of
https://github.com/minio/minio.git
synced 2025-01-11 15:03:22 -05:00
Fix regression issue where users couldn't click into folders (#6029)
This commit fixes the issue introduced in #6023 The clicks on folder names direct the users inside the folders; while the clicks on file names don't download the files, and will open file previews on a separate modal in the future. Additionally, when a file has been selected using the checkbox, it can now be downloaded without being inside a zip file. Fixes #6026
This commit is contained in:
parent
7e12c3e8b9
commit
39919708d6
@ -15,7 +15,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import React from "react"
|
import React from "react"
|
||||||
import classNames from "classnames"
|
|
||||||
import { connect } from "react-redux"
|
import { connect } from "react-redux"
|
||||||
import humanize from "humanize"
|
import humanize from "humanize"
|
||||||
import Moment from "moment"
|
import Moment from "moment"
|
||||||
@ -35,22 +34,19 @@ export const ObjectItem = ({
|
|||||||
onClick
|
onClick
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<div
|
<div className={"fesl-row"} data-type={getDataType(name, contentType)}>
|
||||||
className={
|
|
||||||
"fesl-row " +
|
|
||||||
classNames({
|
|
||||||
"fesl-row-selected": checked
|
|
||||||
})
|
|
||||||
}
|
|
||||||
data-type={getDataType(name, contentType)}
|
|
||||||
>
|
|
||||||
<div className="fesl-item fesl-item-icon">
|
<div className="fesl-item fesl-item-icon">
|
||||||
<div className="fi-select">
|
<div className="fi-select">
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
name={name}
|
name={name}
|
||||||
|
checked={checked}
|
||||||
|
onChange={() => {
|
||||||
|
checked ? uncheckObject(name) : checkObject(name)
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
<i className="fis-icon" />
|
<i className="fis-icon" />
|
||||||
|
<i className="fis-helper" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="fesl-item fesl-item-name">
|
<div className="fesl-item fesl-item-name">
|
||||||
@ -58,7 +54,9 @@ export const ObjectItem = ({
|
|||||||
href="#"
|
href="#"
|
||||||
onClick={e => {
|
onClick={e => {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
checked ? uncheckObject(name) : checkObject(name)
|
if (onClick) {
|
||||||
|
onClick()
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{name}
|
{name}
|
||||||
|
@ -29,10 +29,10 @@ export class ObjectsBulkActions extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
handleDownload() {
|
handleDownload() {
|
||||||
const { checkedObjects, resetCheckedList, downloadChecked, downloadObject } = this.props
|
const { checkedObjects, clearChecked, downloadChecked, downloadObject } = this.props
|
||||||
if (checkedObjects.length === 1) {
|
if (checkedObjects.length === 1 && !checkedObjects[0].endsWith('/')) {
|
||||||
downloadObject(checkedObjects[0])
|
downloadObject(checkedObjects[0])
|
||||||
resetCheckedList()
|
clearChecked()
|
||||||
} else {
|
} else {
|
||||||
downloadChecked()
|
downloadChecked()
|
||||||
}
|
}
|
||||||
@ -64,12 +64,11 @@ export class ObjectsBulkActions extends React.Component {
|
|||||||
selected
|
selected
|
||||||
</span>
|
</span>
|
||||||
<span className="la-actions pull-right">
|
<span className="la-actions pull-right">
|
||||||
<button
|
<button id="download-checked" onClick={this.handleDownload.bind(this)}>
|
||||||
id="download-checked"
|
|
||||||
onClick={this.handleDownload.bind(this)}
|
|
||||||
>
|
|
||||||
{" "}
|
{" "}
|
||||||
Download {checkedObjects.length === 1 ? "object" : "all as zip"}{" "}
|
Download
|
||||||
|
{(checkedObjects.length === 1 && !checkedObjects[0].endsWith('/')) ?
|
||||||
|
" object" : " all as zip" }{" "}
|
||||||
</button>
|
</button>
|
||||||
</span>
|
</span>
|
||||||
<span className="la-actions pull-right">
|
<span className="la-actions pull-right">
|
||||||
@ -105,6 +104,7 @@ const mapStateToProps = state => {
|
|||||||
|
|
||||||
const mapDispatchToProps = dispatch => {
|
const mapDispatchToProps = dispatch => {
|
||||||
return {
|
return {
|
||||||
|
downloadObject: object => dispatch(actions.downloadObject(object)),
|
||||||
downloadChecked: () => dispatch(actions.downloadCheckedObjects()),
|
downloadChecked: () => dispatch(actions.downloadCheckedObjects()),
|
||||||
downloadObject: object => dispatch(actions.downloadObject(object)),
|
downloadObject: object => dispatch(actions.downloadObject(object)),
|
||||||
resetCheckedList: () => dispatch(actions.resetCheckedList()),
|
resetCheckedList: () => dispatch(actions.resetCheckedList()),
|
||||||
|
@ -28,22 +28,40 @@ describe("ObjectItem", () => {
|
|||||||
expect(wrapper.prop("data-type")).toBe("image")
|
expect(wrapper.prop("data-type")).toBe("image")
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should call checkObject when the object is selected", () => {
|
it("shouldn't call onClick when the object isclicked", () => {
|
||||||
const checkObject = jest.fn()
|
const onClick = jest.fn()
|
||||||
const wrapper = shallow(<ObjectItem name={"test"} checked={false} checkObject={checkObject} />)
|
const wrapper = shallow(<ObjectItem name={"test"} />)
|
||||||
wrapper.find("a").simulate("click", { preventDefault: jest.fn() })
|
wrapper.find("a").simulate("click", { preventDefault: jest.fn() })
|
||||||
|
expect(onClick).not.toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should call onClick when the folder isclicked", () => {
|
||||||
|
const onClick = jest.fn()
|
||||||
|
const wrapper = shallow(<ObjectItem name={"test/"} onClick={onClick} />)
|
||||||
|
wrapper.find("a").simulate("click", { preventDefault: jest.fn() })
|
||||||
|
expect(onClick).toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should call checkObject when the object/prefix is checked", () => {
|
||||||
|
const checkObject = jest.fn()
|
||||||
|
const wrapper = shallow(
|
||||||
|
<ObjectItem name={"test"} checked={false} checkObject={checkObject} />
|
||||||
|
)
|
||||||
|
wrapper.find("input[type='checkbox']").simulate("change")
|
||||||
expect(checkObject).toHaveBeenCalledWith("test")
|
expect(checkObject).toHaveBeenCalledWith("test")
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should render highlighted row when object is selected", () => {
|
it("should render checked checkbox", () => {
|
||||||
const wrapper = shallow(<ObjectItem name={"test"} checked={true} />)
|
const wrapper = shallow(<ObjectItem name={"test"} checked={true} />)
|
||||||
expect(wrapper.find(".fesl-row").hasClass("fesl-row-selected")).toBeTruthy()
|
expect(wrapper.find("input[type='checkbox']").prop("checked")).toBeTruthy()
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should call uncheckObject when the object is deselected", () => {
|
it("should call uncheckObject when the object/prefix is unchecked", () => {
|
||||||
const uncheckObject = jest.fn()
|
const uncheckObject = jest.fn()
|
||||||
const wrapper = shallow(<ObjectItem name={"test"} checked={true} uncheckObject={uncheckObject} />)
|
const wrapper = shallow(
|
||||||
wrapper.find("a").simulate("click", { preventDefault: jest.fn() })
|
<ObjectItem name={"test"} checked={true} uncheckObject={uncheckObject} />
|
||||||
|
)
|
||||||
|
wrapper.find("input[type='checkbox']").simulate("change")
|
||||||
expect(uncheckObject).toHaveBeenCalledWith("test")
|
expect(uncheckObject).toHaveBeenCalledWith("test")
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -20,7 +20,7 @@ import { ObjectsBulkActions } from "../ObjectsBulkActions"
|
|||||||
|
|
||||||
describe("ObjectsBulkActions", () => {
|
describe("ObjectsBulkActions", () => {
|
||||||
it("should render without crashing", () => {
|
it("should render without crashing", () => {
|
||||||
shallow(<ObjectsBulkActions checkedObjects={0} />)
|
shallow(<ObjectsBulkActions checkedObjects={[]} />)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should show actions when checkObjectsCount is more than 0", () => {
|
it("should show actions when checkObjectsCount is more than 0", () => {
|
||||||
@ -28,21 +28,33 @@ describe("ObjectsBulkActions", () => {
|
|||||||
expect(wrapper.hasClass("list-actions-toggled")).toBeTruthy()
|
expect(wrapper.hasClass("list-actions-toggled")).toBeTruthy()
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should call downloadObject for single object when download button is clicked", () => {
|
it("should call downloadObject when single object is selected and download button is clicked", () => {
|
||||||
const downloadObject = jest.fn()
|
const downloadObject = jest.fn()
|
||||||
const resetCheckedList = jest.fn()
|
const clearChecked = jest.fn()
|
||||||
const wrapper = shallow(
|
const wrapper = shallow(
|
||||||
<ObjectsBulkActions
|
<ObjectsBulkActions
|
||||||
checkedObjects={["test1"]}
|
checkedObjects={["test"]}
|
||||||
downloadObject={downloadObject}
|
downloadObject={downloadObject}
|
||||||
resetCheckedList={resetCheckedList}
|
clearChecked={clearChecked}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
wrapper.find("#download-checked").simulate("click")
|
wrapper.find("#download-checked").simulate("click")
|
||||||
expect(downloadObject).toHaveBeenCalled()
|
expect(downloadObject).toHaveBeenCalled()
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should call downloadChecked for multiple objects when download button is clicked", () => {
|
it("should call downloadChecked when a folder is selected and download button is clicked", () => {
|
||||||
|
const downloadChecked = jest.fn()
|
||||||
|
const wrapper = shallow(
|
||||||
|
<ObjectsBulkActions
|
||||||
|
checkedObjects={["test/"]}
|
||||||
|
downloadChecked={downloadChecked}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
wrapper.find("#download-checked").simulate("click")
|
||||||
|
expect(downloadChecked).toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should call downloadChecked when multiple objects are selected and download button is clicked", () => {
|
||||||
const downloadChecked = jest.fn()
|
const downloadChecked = jest.fn()
|
||||||
const wrapper = shallow(
|
const wrapper = shallow(
|
||||||
<ObjectsBulkActions
|
<ObjectsBulkActions
|
||||||
|
@ -74,7 +74,7 @@ div.fesl-row {
|
|||||||
border-bottom: 1px solid transparent;
|
border-bottom: 1px solid transparent;
|
||||||
cursor: default;
|
cursor: default;
|
||||||
.transition(background-color);
|
.transition(background-color);
|
||||||
.transition-duration(300ms);
|
.transition-duration(500ms);
|
||||||
|
|
||||||
@media (max-width: (@screen-xs-max - 100px)) {
|
@media (max-width: (@screen-xs-max - 100px)) {
|
||||||
padding: 5px 20px;
|
padding: 5px 20px;
|
||||||
@ -87,8 +87,16 @@ div.fesl-row {
|
|||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
&:not(.fesl-row-selected) {
|
.fis-icon {
|
||||||
background: lighten(@text-muted-color, 22%);
|
&:before {
|
||||||
|
.opacity(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.fis-helper {
|
||||||
|
&:before {
|
||||||
|
.opacity(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,14 +137,6 @@ div.fesl-row {
|
|||||||
.fesl-row-selected {
|
.fesl-row-selected {
|
||||||
background-color: @list-row-selected-bg;
|
background-color: @list-row-selected-bg;
|
||||||
|
|
||||||
&:nth-child(even) {
|
|
||||||
background-color: @list-row-selected-even-bg;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background: @list-row-selected-hover;
|
|
||||||
}
|
|
||||||
|
|
||||||
&, .fesl-item a {
|
&, .fesl-item a {
|
||||||
color: darken(@text-color, 10%);
|
color: darken(@text-color, 10%);
|
||||||
}
|
}
|
||||||
@ -161,6 +161,27 @@ div.fesl-row {
|
|||||||
height: 35px;
|
height: 35px;
|
||||||
z-index: 8;
|
z-index: 8;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:checked {
|
||||||
|
& ~ .fis-icon {
|
||||||
|
background-color: #32393F;
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
& ~ .fis-helper {
|
||||||
|
&:before {
|
||||||
|
.scale(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:after {
|
||||||
|
.scale(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -189,6 +210,38 @@ div.fesl-row {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.fis-helper {
|
||||||
|
&:before,
|
||||||
|
&:after {
|
||||||
|
position: absolute;
|
||||||
|
.transition(all);
|
||||||
|
.transition-duration(250ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
content: '';
|
||||||
|
width: 15px;
|
||||||
|
height: 15px;
|
||||||
|
border: 2px solid @white;
|
||||||
|
z-index: 7;
|
||||||
|
border-radius: 2px;
|
||||||
|
top: 10px;
|
||||||
|
left: 10px;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:after {
|
||||||
|
font-family: @font-family-icon;
|
||||||
|
content: '\f00c';
|
||||||
|
top: 8px;
|
||||||
|
left: 9px;
|
||||||
|
color: @white;
|
||||||
|
font-size: 14px;
|
||||||
|
.scale(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*--------------------------
|
/*--------------------------
|
||||||
Files and Folders
|
Files and Folders
|
||||||
----------------------------*/
|
----------------------------*/
|
||||||
|
@ -97,7 +97,5 @@
|
|||||||
/*-------------------------
|
/*-------------------------
|
||||||
List
|
List
|
||||||
--------------------------*/
|
--------------------------*/
|
||||||
@list-row-selected-bg: #fffad6;
|
@list-row-selected-bg: #fbf2bf;
|
||||||
@list-row-selected-even-bg: #faf5d1;
|
|
||||||
@list-row-selected-hover: #f5f0cc;
|
|
||||||
@list-row-even-bg: #fafafa;
|
@list-row-even-bg: #fafafa;
|
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user