mirror of
https://github.com/minio/minio.git
synced 2025-11-23 02:57:42 -05:00
revert browser newux changes (#5714)
This commit is contained in:
@@ -21,29 +21,40 @@ import logo from "../../img/logo.svg"
|
||||
export const AboutModal = ({ serverInfo, hideAbout }) => {
|
||||
const { version, memory, platform, runtime } = serverInfo
|
||||
return (
|
||||
<Modal className="about" animation={false} show={true} onHide={hideAbout}>
|
||||
<i className="close" onClick={hideAbout} />
|
||||
<div className="about__content">
|
||||
<div className="about__logo hidden-xs">
|
||||
<img src={logo} alt="" />
|
||||
<Modal
|
||||
className="modal-about modal-dark"
|
||||
animation={false}
|
||||
show={true}
|
||||
onHide={hideAbout}
|
||||
>
|
||||
<button className="close" onClick={hideAbout}>
|
||||
<span>×</span>
|
||||
</button>
|
||||
<div className="ma-inner">
|
||||
<div className="mai-item hidden-xs">
|
||||
<a href="https://minio.io" target="_blank">
|
||||
<img className="maii-logo" src={logo} alt="" />
|
||||
</a>
|
||||
</div>
|
||||
<div className="about__info">
|
||||
<div className="about__item">
|
||||
<strong>Version</strong>
|
||||
<small>{version}</small>
|
||||
</div>
|
||||
<div className="about__item">
|
||||
<strong>Memory</strong>
|
||||
<small>{memory}</small>
|
||||
</div>
|
||||
<div className="about__item">
|
||||
<strong>Platform</strong>
|
||||
<small>{platform}</small>
|
||||
</div>
|
||||
<div className="about__item">
|
||||
<strong>Runtime</strong>
|
||||
<small>{runtime}</small>
|
||||
</div>
|
||||
<div className="mai-item">
|
||||
<ul className="maii-list">
|
||||
<li>
|
||||
<div>Version</div>
|
||||
<small>{version}</small>
|
||||
</li>
|
||||
<li>
|
||||
<div>Memory</div>
|
||||
<small>{memory}</small>
|
||||
</li>
|
||||
<li>
|
||||
<div>Platform</div>
|
||||
<small>{platform}</small>
|
||||
</li>
|
||||
<li>
|
||||
<div>Runtime</div>
|
||||
<small>{runtime}</small>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
|
||||
@@ -15,21 +15,24 @@
|
||||
*/
|
||||
|
||||
import React from "react"
|
||||
import classNames from "classnames"
|
||||
import { connect } from "react-redux"
|
||||
import SideBar from "./SideBar"
|
||||
import MainContent from "./MainContent"
|
||||
import AlertContainer from "../alert/AlertContainer"
|
||||
|
||||
const Aux = props => props.children
|
||||
|
||||
class Browser extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<Aux>
|
||||
<div
|
||||
className={classNames({
|
||||
"file-explorer": true
|
||||
})}
|
||||
>
|
||||
<SideBar />
|
||||
<MainContent />
|
||||
<AlertContainer />
|
||||
</Aux>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,61 +81,62 @@ export class BrowserDropdown extends React.Component {
|
||||
render() {
|
||||
const { serverInfo } = this.props
|
||||
return (
|
||||
<Dropdown pullRight id="toolbar-menu">
|
||||
<Dropdown.Toggle
|
||||
noCaret
|
||||
className="toolbar__item zmdi zmdi-more-vert"
|
||||
/>
|
||||
<Dropdown.Menu>
|
||||
<li>
|
||||
<a target="_blank" href="https://github.com/minio/minio">
|
||||
Github <i className="zmdi zmdi-github" />
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="" onClick={this.fullScreen}>
|
||||
Fullscreen <i className="zmdi zmdi-fullscreen" />
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a target="_blank" href="https://docs.minio.io/">
|
||||
Documentation <i className="zmdi zmdi-assignment" />
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a target="_blank" href="https://slack.minio.io">
|
||||
Ask for help <i className="zmdi zmdi-help" />
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="" id="show-about" onClick={this.showAbout.bind(this)}>
|
||||
About <i className="zmdi zmdi-info" />
|
||||
</a>
|
||||
{this.state.showAboutModal && (
|
||||
<AboutModal
|
||||
serverInfo={serverInfo}
|
||||
hideAbout={this.hideAbout.bind(this)}
|
||||
/>
|
||||
)}
|
||||
</li>
|
||||
<li>
|
||||
<a href="" onClick={this.showChangePassword.bind(this)}>
|
||||
Change Password <i className="zmdi zmdi-settings" />
|
||||
</a>
|
||||
{this.state.showChangePasswordModal && (
|
||||
<ChangePasswordModal
|
||||
serverInfo={serverInfo}
|
||||
hideChangePassword={this.hideChangePassword.bind(this)}
|
||||
/>
|
||||
)}
|
||||
</li>
|
||||
<li>
|
||||
<a href="" id="logout" onClick={this.logout}>
|
||||
Sign Out <i className="zmdi zmdi-sign-in" />
|
||||
</a>
|
||||
</li>
|
||||
</Dropdown.Menu>
|
||||
</Dropdown>
|
||||
<li>
|
||||
<Dropdown pullRight id="top-right-menu">
|
||||
<Dropdown.Toggle noCaret>
|
||||
<i className="fa fa-reorder" />
|
||||
</Dropdown.Toggle>
|
||||
<Dropdown.Menu className="dropdown-menu-right">
|
||||
<li>
|
||||
<a target="_blank" href="https://github.com/minio/minio">
|
||||
Github <i className="fa fa-github" />
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="" onClick={this.fullScreen}>
|
||||
Fullscreen <i className="fa fa-expand" />
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a target="_blank" href="https://docs.minio.io/">
|
||||
Documentation <i className="fa fa-book" />
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a target="_blank" href="https://slack.minio.io">
|
||||
Ask for help <i className="fa fa-question-circle" />
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="" id="show-about" onClick={this.showAbout.bind(this)}>
|
||||
About <i className="fa fa-info-circle" />
|
||||
</a>
|
||||
{this.state.showAboutModal && (
|
||||
<AboutModal
|
||||
serverInfo={serverInfo}
|
||||
hideAbout={this.hideAbout.bind(this)}
|
||||
/>
|
||||
)}
|
||||
</li>
|
||||
<li>
|
||||
<a href="" onClick={this.showChangePassword.bind(this)}>
|
||||
Change Password <i className="fa fa-cog" />
|
||||
</a>
|
||||
{this.state.showChangePasswordModal && (
|
||||
<ChangePasswordModal
|
||||
serverInfo={serverInfo}
|
||||
hideChangePassword={this.hideChangePassword.bind(this)}
|
||||
/>
|
||||
)}
|
||||
</li>
|
||||
<li>
|
||||
<a href="" id="logout" onClick={this.logout}>
|
||||
Sign Out <i className="fa fa-sign-out" />
|
||||
</a>
|
||||
</li>
|
||||
</Dropdown.Menu>
|
||||
</Dropdown>
|
||||
</li>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import {
|
||||
ModalHeader,
|
||||
OverlayTrigger
|
||||
} from "react-bootstrap"
|
||||
import InputGroup from "./InputGroup"
|
||||
|
||||
export class ChangePasswordModal extends React.Component {
|
||||
constructor(props) {
|
||||
@@ -113,55 +114,51 @@ export class ChangePasswordModal extends React.Component {
|
||||
render() {
|
||||
const { hideChangePassword } = this.props
|
||||
return (
|
||||
<Modal bsSize="sm" animation={false} show={true} className="settings">
|
||||
<Modal.Header>Change Password</Modal.Header>
|
||||
<Modal.Body className="m-t-20">
|
||||
<div className="form-group">
|
||||
<label className="form-group__label">Access key</label>
|
||||
<input
|
||||
type="text"
|
||||
value={this.state.accessKey}
|
||||
onChange={this.accessKeyChange.bind(this)}
|
||||
id="accessKey"
|
||||
className="form-group__field"
|
||||
name="accesskey"
|
||||
required="required"
|
||||
autoComplete="false"
|
||||
readonly={this.state.keysReadOnly}
|
||||
/>
|
||||
<i className="form-group__helper" />
|
||||
</div>
|
||||
<div className="form-group">
|
||||
<label className="form-group__label">Secret key</label>
|
||||
<input
|
||||
type={this.state.secretKeyVisible ? "text" : "password"}
|
||||
value={this.state.secretKey}
|
||||
onChange={this.secretKeyChange.bind(this)}
|
||||
id="secretKey"
|
||||
className="form-group__field"
|
||||
name="secretKey"
|
||||
required="required"
|
||||
autoComplete="false"
|
||||
readonly={this.state.keysReadOnly}
|
||||
/>
|
||||
<i className="form-group__helper" />
|
||||
<i
|
||||
onClick={this.secretKeyVisible.bind(
|
||||
this,
|
||||
!this.state.secretKeyVisible
|
||||
)}
|
||||
className={
|
||||
"form-group__addon zmdi " +
|
||||
(this.state.secretKeyVisible ? "zmdi-eye-off" : "zmdi-eye")
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</Modal.Body>
|
||||
<Modal bsSize="sm" animation={false} show={true}>
|
||||
<ModalHeader>Change Password</ModalHeader>
|
||||
<ModalBody className="m-t-20">
|
||||
<InputGroup
|
||||
value={this.state.accessKey}
|
||||
onChange={this.accessKeyChange.bind(this)}
|
||||
id="accessKey"
|
||||
label="Access Key"
|
||||
name="accesskey"
|
||||
type="text"
|
||||
spellCheck="false"
|
||||
required="required"
|
||||
autoComplete="false"
|
||||
align="ig-left"
|
||||
readonly={this.state.keysReadOnly}
|
||||
/>
|
||||
<i
|
||||
onClick={this.secretKeyVisible.bind(
|
||||
this,
|
||||
!this.state.secretKeyVisible
|
||||
)}
|
||||
className={
|
||||
"toggle-password fa fa-eye " +
|
||||
(this.state.secretKeyVisible ? "toggled" : "")
|
||||
}
|
||||
/>
|
||||
<InputGroup
|
||||
value={this.state.secretKey}
|
||||
onChange={this.secretKeyChange.bind(this)}
|
||||
id="secretKey"
|
||||
label="Secret Key"
|
||||
name="accesskey"
|
||||
type={this.state.secretKeyVisible ? "text" : "password"}
|
||||
spellCheck="false"
|
||||
required="required"
|
||||
autoComplete="false"
|
||||
align="ig-left"
|
||||
readonly={this.state.keysReadOnly}
|
||||
/>
|
||||
</ModalBody>
|
||||
<div className="modal-footer">
|
||||
<button
|
||||
id="generate-keys"
|
||||
className={
|
||||
"btn btn--link " + (this.state.keysReadOnly ? "hidden" : "")
|
||||
"btn btn-primary " + (this.state.keysReadOnly ? "hidden" : "")
|
||||
}
|
||||
onClick={this.generateAuth.bind(this)}
|
||||
>
|
||||
@@ -170,7 +167,7 @@ export class ChangePasswordModal extends React.Component {
|
||||
<button
|
||||
id="update-keys"
|
||||
className={
|
||||
"btn btn--link " + (this.state.keysReadOnly ? "hidden" : "")
|
||||
"btn btn-success " + (this.state.keysReadOnly ? "hidden" : "")
|
||||
}
|
||||
onClick={this.setAuth.bind(this)}
|
||||
>
|
||||
@@ -178,7 +175,7 @@ export class ChangePasswordModal extends React.Component {
|
||||
</button>
|
||||
<button
|
||||
id="cancel-change-password"
|
||||
className="btn btn--link"
|
||||
className="btn btn-link"
|
||||
onClick={hideChangePassword}
|
||||
>
|
||||
Cancel
|
||||
|
||||
@@ -33,23 +33,23 @@ let ConfirmModal = ({
|
||||
bsSize="small"
|
||||
animation={false}
|
||||
show={show}
|
||||
className={"dialog " + (baseClass || "")}
|
||||
className={"modal-confirm " + (baseClass || "")}
|
||||
>
|
||||
<Modal.Body>
|
||||
<div className="dialog__icon">
|
||||
<ModalBody>
|
||||
<div className="mc-icon">
|
||||
<i className={icon} />
|
||||
</div>
|
||||
<div className="dialog__text">{text}</div>
|
||||
<div className="dialog__sub">{sub}</div>
|
||||
<div className="dialog__actions">
|
||||
<button className="btn btn--link" onClick={okHandler}>
|
||||
{okText}
|
||||
</button>
|
||||
<button className="btn btn--link" onClick={cancelHandler}>
|
||||
{cancelText}
|
||||
</button>
|
||||
</div>
|
||||
</Modal.Body>
|
||||
<div className="mc-text">{text}</div>
|
||||
<div className="mc-sub">{sub}</div>
|
||||
</ModalBody>
|
||||
<div className="modal-footer">
|
||||
<button className="btn btn-danger" onClick={okHandler}>
|
||||
{okText}
|
||||
</button>
|
||||
<button className="btn btn-link" onClick={cancelHandler}>
|
||||
{cancelText}
|
||||
</button>
|
||||
</div>
|
||||
</Modal>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -16,13 +16,26 @@
|
||||
|
||||
import React from "react"
|
||||
import Path from "../objects/Path"
|
||||
import Toolbar from "../objects/Toolbar"
|
||||
import StorageInfo from "./StorageInfo"
|
||||
import BrowserDropdown from "./BrowserDropdown"
|
||||
import web from "../web"
|
||||
import { minioBrowserPrefix } from "../constants"
|
||||
|
||||
export const Header = () => {
|
||||
const loggedIn = web.LoggedIn()
|
||||
return (
|
||||
<header className="header">
|
||||
<Toolbar />
|
||||
<header className="fe-header">
|
||||
<Path />
|
||||
{loggedIn && <StorageInfo />}
|
||||
<ul className="feh-actions">
|
||||
{loggedIn ? (
|
||||
<BrowserDropdown />
|
||||
) : (
|
||||
<a className="btn btn-danger" href={minioBrowserPrefix + "/login"}>
|
||||
Login
|
||||
</a>
|
||||
)}
|
||||
</ul>
|
||||
</header>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -16,6 +16,11 @@
|
||||
|
||||
import React from "react"
|
||||
|
||||
export const Host = () => <small>{window.location.host}</small>
|
||||
export const Host = () => (
|
||||
<div className="fes-host">
|
||||
<i className="fa fa-globe" />
|
||||
<a href="/">{window.location.host}</a>
|
||||
</div>
|
||||
)
|
||||
|
||||
export default Host
|
||||
|
||||
70
browser/app/js/browser/InputGroup.js
Normal file
70
browser/app/js/browser/InputGroup.js
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Minio Cloud Storage (C) 2016, 2018 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React from "react"
|
||||
|
||||
let InputGroup = ({
|
||||
label,
|
||||
id,
|
||||
name,
|
||||
value,
|
||||
onChange,
|
||||
type,
|
||||
spellCheck,
|
||||
required,
|
||||
readonly,
|
||||
autoComplete,
|
||||
align,
|
||||
className
|
||||
}) => {
|
||||
var input = (
|
||||
<input
|
||||
id={id}
|
||||
name={name}
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
className="ig-text"
|
||||
type={type}
|
||||
spellCheck={spellCheck}
|
||||
required={required}
|
||||
autoComplete={autoComplete}
|
||||
/>
|
||||
)
|
||||
if (readonly)
|
||||
input = (
|
||||
<input
|
||||
id={id}
|
||||
name={name}
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
className="ig-text"
|
||||
type={type}
|
||||
spellCheck={spellCheck}
|
||||
required={required}
|
||||
autoComplete={autoComplete}
|
||||
disabled
|
||||
/>
|
||||
)
|
||||
return (
|
||||
<div className={"input-group " + align + " " + className}>
|
||||
{input}
|
||||
<i className="ig-helpers" />
|
||||
<label className="ig-label">{label}</label>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default InputGroup
|
||||
@@ -16,9 +16,11 @@
|
||||
|
||||
import React from "react"
|
||||
import { connect } from "react-redux"
|
||||
import classNames from "classnames"
|
||||
import logo from "../../img/logo.svg"
|
||||
import Alert from "../alert/Alert"
|
||||
import * as actionsAlert from "../alert/actions"
|
||||
import InputGroup from "./InputGroup"
|
||||
import web from "../web"
|
||||
import { Redirect } from "react-router-dom"
|
||||
|
||||
@@ -72,37 +74,39 @@ export class Login extends React.Component {
|
||||
return (
|
||||
<div className="login">
|
||||
{alertBox}
|
||||
<div className="login__inner">
|
||||
<div className="login__header">
|
||||
<img className="login__logo" src={logo} alt="" />
|
||||
<div className="login__host">{window.location.host}</div>
|
||||
</div>
|
||||
<form className="login__form" onSubmit={this.handleSubmit.bind(this)}>
|
||||
<div className="form-group">
|
||||
<input
|
||||
placeholder="Access Key"
|
||||
type="text"
|
||||
id="accessKey"
|
||||
className="form-group__field"
|
||||
spellCheck="false"
|
||||
required="required"
|
||||
/>
|
||||
<i className="form-group__helper" />
|
||||
</div>
|
||||
<div className="form-group">
|
||||
<input
|
||||
placeholder="Secret Key"
|
||||
type="password"
|
||||
id="secretKey"
|
||||
className="form-group__field"
|
||||
spellCheck="false"
|
||||
required="required"
|
||||
/>
|
||||
<i className="form-group__helper" />
|
||||
</div>
|
||||
<button className="login__btn" type="submit" />
|
||||
<div className="l-wrap">
|
||||
<form onSubmit={this.handleSubmit.bind(this)}>
|
||||
<InputGroup
|
||||
className="ig-dark"
|
||||
label="Access Key"
|
||||
id="accessKey"
|
||||
name="username"
|
||||
type="text"
|
||||
spellCheck="false"
|
||||
required="required"
|
||||
autoComplete="username"
|
||||
/>
|
||||
<InputGroup
|
||||
className="ig-dark"
|
||||
label="Secret Key"
|
||||
id="secretKey"
|
||||
name="password"
|
||||
type="password"
|
||||
spellCheck="false"
|
||||
required="required"
|
||||
autoComplete="new-password"
|
||||
/>
|
||||
<button className="lw-btn" type="submit">
|
||||
<i className="fa fa-sign-in" />
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
<div className="l-footer">
|
||||
<a className="lf-logo" href="">
|
||||
<img src={logo} alt="" />
|
||||
</a>
|
||||
<div className="lf-server">{window.location.host}</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -111,12 +115,7 @@ export class Login extends React.Component {
|
||||
const mapDispatchToProps = dispatch => {
|
||||
return {
|
||||
showAlert: (type, message) =>
|
||||
dispatch(
|
||||
actionsAlert.set({
|
||||
type: type,
|
||||
message: message
|
||||
})
|
||||
),
|
||||
dispatch(actionsAlert.set({ type: type, message: message })),
|
||||
clearAlert: () => dispatch(actionsAlert.clear())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,9 +27,9 @@ export const MainActions = ({
|
||||
uploadFile,
|
||||
showMakeBucketModal
|
||||
}) => {
|
||||
const uploadTooltip = <Tooltip id="tooltip-upload-file">Upload file</Tooltip>
|
||||
const uploadTooltip = <Tooltip id="tt-upload-file">Upload file</Tooltip>
|
||||
const makeBucketTooltip = (
|
||||
<Tooltip id="tooltip-create-bucket">Create bucket</Tooltip>
|
||||
<Tooltip id="tt-create-bucket">Create bucket</Tooltip>
|
||||
)
|
||||
const onFileUpload = e => {
|
||||
e.preventDefault()
|
||||
@@ -41,20 +41,15 @@ export const MainActions = ({
|
||||
|
||||
if (loggedIn || prefixWritable) {
|
||||
return (
|
||||
<Dropdown
|
||||
dropup
|
||||
pullRight
|
||||
className="create"
|
||||
id="main-actions"
|
||||
componentClass="div"
|
||||
>
|
||||
<Dropdown.Toggle noCaret className="create__toggle" useAnchor={true}>
|
||||
<i className="zmdi zmdi-plus" />
|
||||
<i className="zmdi zmdi-close" />
|
||||
<Dropdown dropup className="feb-actions" id="fe-action-toggle">
|
||||
<Dropdown.Toggle noCaret className="feba-toggle">
|
||||
<span>
|
||||
<i className="fa fa-plus" />
|
||||
</span>
|
||||
</Dropdown.Toggle>
|
||||
<Dropdown.Menu>
|
||||
<OverlayTrigger placement="left" overlay={uploadTooltip}>
|
||||
<a href="#" className="create__btn create__btn--upload">
|
||||
<a href="#" className="feba-btn feba-upload">
|
||||
<input
|
||||
type="file"
|
||||
onChange={onFileUpload}
|
||||
@@ -62,7 +57,8 @@ export const MainActions = ({
|
||||
id="file-input"
|
||||
/>
|
||||
<label htmlFor="file-input">
|
||||
<i className="zmdi zmdi-upload" />
|
||||
{" "}
|
||||
<i className="fa fa-cloud-upload" />{" "}
|
||||
</label>
|
||||
</a>
|
||||
</OverlayTrigger>
|
||||
@@ -71,12 +67,14 @@ export const MainActions = ({
|
||||
<a
|
||||
href="#"
|
||||
id="show-make-bucket"
|
||||
className="create__btn create__btn--bucket"
|
||||
className="feba-btn feba-bucket"
|
||||
onClick={e => {
|
||||
e.preventDefault()
|
||||
showMakeBucketModal()
|
||||
}}
|
||||
/>
|
||||
>
|
||||
<i className="fa fa-hdd-o" />
|
||||
</a>
|
||||
</OverlayTrigger>
|
||||
)}
|
||||
</Dropdown.Menu>
|
||||
|
||||
@@ -15,27 +15,29 @@
|
||||
*/
|
||||
|
||||
import React from "react"
|
||||
import MobileHeader from "./MobileHeader"
|
||||
import Header from "./Header"
|
||||
import SidebarBackdrop from "./SidebarBackdrop"
|
||||
import ObjectsSection from "../objects/ObjectsSection"
|
||||
import MainActions from "./MainActions"
|
||||
import BucketPolicyModal from "../buckets/BucketPolicyModal"
|
||||
import MakeBucketModal from "../buckets/MakeBucketModal"
|
||||
import UploadModal from "../uploads/UploadModal"
|
||||
import ObjectsBulkActions from "../objects/ObjectsBulkActions"
|
||||
import Dropzone from "../uploads/Dropzone"
|
||||
|
||||
export const MainContent = ({ sidebarOpen }) => (
|
||||
<section className="content">
|
||||
<Header />
|
||||
export const MainContent = () => (
|
||||
<div className="fe-body">
|
||||
<ObjectsBulkActions />
|
||||
<MobileHeader />
|
||||
<Dropzone>
|
||||
<Header />
|
||||
<ObjectsSection />
|
||||
</Dropzone>
|
||||
<MainActions />
|
||||
<BucketPolicyModal />
|
||||
<MakeBucketModal />
|
||||
<UploadModal />
|
||||
<SidebarBackdrop />
|
||||
</section>
|
||||
</div>
|
||||
)
|
||||
|
||||
export default MainContent
|
||||
|
||||
@@ -15,17 +15,34 @@
|
||||
*/
|
||||
|
||||
import React from "react"
|
||||
import classNames from "classnames"
|
||||
import { connect } from "react-redux"
|
||||
import logo from "../../img/logo.svg"
|
||||
import * as actionsCommon from "./actions"
|
||||
|
||||
export const SidebarBackdrop = ({ sidebarOpen, toggleSidebar }) => (
|
||||
<div
|
||||
className="sidebar-backdrop"
|
||||
onClick={e => {
|
||||
e.stopPropagation()
|
||||
toggleSidebar()
|
||||
}}
|
||||
/>
|
||||
export const MobileHeader = ({ sidebarOpen, toggleSidebar }) => (
|
||||
<header className="fe-header-mobile hidden-lg hidden-md">
|
||||
<div
|
||||
id="sidebar-toggle"
|
||||
className={
|
||||
"feh-trigger " +
|
||||
classNames({
|
||||
"feht-toggled": sidebarOpen
|
||||
})
|
||||
}
|
||||
onClick={e => {
|
||||
e.stopPropagation()
|
||||
toggleSidebar()
|
||||
}}
|
||||
>
|
||||
<div className="feht-lines">
|
||||
<div className="top" />
|
||||
<div className="center" />
|
||||
<div className="bottom" />
|
||||
</div>
|
||||
</div>
|
||||
<img className="mh-logo" src={logo} alt="" />
|
||||
</header>
|
||||
)
|
||||
|
||||
const mapStateToProps = state => {
|
||||
@@ -40,4 +57,4 @@ const mapDispatchToProps = dispatch => {
|
||||
}
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(SidebarBackdrop)
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(MobileHeader)
|
||||
@@ -16,38 +16,37 @@
|
||||
|
||||
import React from "react"
|
||||
import classNames from "classnames"
|
||||
import ClickOutHandler from "react-onclickout"
|
||||
import { connect } from "react-redux"
|
||||
|
||||
import logo from "../../img/logo.svg"
|
||||
import Dropdown from "react-bootstrap/lib/Dropdown"
|
||||
import BucketSearch from "../buckets/BucketSearch"
|
||||
import BucketList from "../buckets/BucketList"
|
||||
import StorageInfo from "./StorageInfo"
|
||||
import Host from "./Host"
|
||||
import * as actionsCommon from "./actions"
|
||||
import web from "../web"
|
||||
|
||||
export const SideBar = ({ sidebarOpen }) => {
|
||||
export const SideBar = ({ sidebarOpen, clickOutside }) => {
|
||||
return (
|
||||
<aside
|
||||
className={classNames({
|
||||
sidebar: true,
|
||||
"sidebar--toggled": sidebarOpen
|
||||
})}
|
||||
>
|
||||
<div className="sidebar__inner">
|
||||
<div className="logo">
|
||||
<img className="logo__img" src={logo} alt="" />
|
||||
<div className="logo__title">
|
||||
<h2>Minio Browser</h2>
|
||||
<Host />
|
||||
</div>
|
||||
<ClickOutHandler onClickOut={clickOutside}>
|
||||
<div
|
||||
className={classNames({
|
||||
"fe-sidebar": true,
|
||||
toggled: sidebarOpen
|
||||
})}
|
||||
>
|
||||
<div className="fes-header clearfix hidden-sm hidden-xs">
|
||||
<img src={logo} alt="" />
|
||||
<h2>Minio Browser</h2>
|
||||
</div>
|
||||
<div className="buckets">
|
||||
<div className="fes-list">
|
||||
{web.LoggedIn() && <BucketSearch />}
|
||||
<BucketList />
|
||||
</div>
|
||||
<StorageInfo />
|
||||
<Host />
|
||||
</div>
|
||||
</aside>
|
||||
</ClickOutHandler>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -59,7 +58,7 @@ const mapStateToProps = state => {
|
||||
|
||||
const mapDispatchToProps = dispatch => {
|
||||
return {
|
||||
toggleSidebar: () => dispatch(actionsCommon.toggleSidebar())
|
||||
clickOutside: () => dispatch(actionsCommon.closeSidebar())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
* Minio Cloud Storage (C) 2018 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React from "react"
|
||||
import { connect } from "react-redux"
|
||||
import * as actionsCommon from "./actions"
|
||||
|
||||
export const SidebarToggle = ({ sidebarOpen, toggleSidebar }) => (
|
||||
<button
|
||||
className="toolbar__item zmdi zmdi-menu"
|
||||
onClick={e => {
|
||||
e.stopPropagation()
|
||||
toggleSidebar()
|
||||
}}
|
||||
/>
|
||||
)
|
||||
|
||||
const mapStateToProps = state => {
|
||||
return {
|
||||
sidebarOpen: state.browser.sidebarOpen
|
||||
}
|
||||
}
|
||||
|
||||
const mapDispatchToProps = dispatch => {
|
||||
return {
|
||||
toggleSidebar: () => dispatch(actionsCommon.toggleSidebar())
|
||||
}
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(SidebarToggle)
|
||||
@@ -28,15 +28,22 @@ export class StorageInfo extends React.Component {
|
||||
const { total, free } = this.props.storageInfo
|
||||
const used = total - free
|
||||
const usedPercent = used / total * 100 + "%"
|
||||
|
||||
const freePercent = free * 100 / total
|
||||
return (
|
||||
<div className="storage hidden-sm hidden-xs">
|
||||
<small>
|
||||
{humanize.filesize(total - free)} of {humanize.filesize(total)} Used
|
||||
</small>
|
||||
<div className="storage__progress">
|
||||
<span style={{ width: usedPercent }} />
|
||||
<div className="feh-usage">
|
||||
<div className="fehu-chart">
|
||||
<div style={{ width: usedPercent }} />
|
||||
</div>
|
||||
<ul>
|
||||
<li>
|
||||
<span>Used: </span>
|
||||
{humanize.filesize(total - free)}
|
||||
</li>
|
||||
<li className="pull-right">
|
||||
<span>Free: </span>
|
||||
{humanize.filesize(total - used)}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ describe("AboutModal", () => {
|
||||
const wrapper = shallow(
|
||||
<AboutModal serverInfo={serverInfo} hideAbout={hideAbout} />
|
||||
)
|
||||
wrapper.find("i").simulate("click")
|
||||
wrapper.find("button").simulate("click")
|
||||
expect(hideAbout).toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
|
||||
@@ -24,6 +24,6 @@ const mockStore = configureStore()
|
||||
describe("Browser", () => {
|
||||
it("should render without crashing", () => {
|
||||
const store = mockStore()
|
||||
shallow(<Browser store={store} />)
|
||||
shallow(<Browser store={store}/>)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -47,9 +47,7 @@ describe("BrowserDropdown", () => {
|
||||
const wrapper = shallow(
|
||||
<BrowserDropdown serverInfo={serverInfo} fetchServerInfo={jest.fn()} />
|
||||
)
|
||||
wrapper.find("#show-about").simulate("click", {
|
||||
preventDefault: jest.fn()
|
||||
})
|
||||
wrapper.find("#show-about").simulate("click", { preventDefault: jest.fn() })
|
||||
wrapper.update()
|
||||
expect(wrapper.state("showAboutModal")).toBeTruthy()
|
||||
expect(wrapper.find("AboutModal").length).toBe(1)
|
||||
@@ -59,9 +57,7 @@ describe("BrowserDropdown", () => {
|
||||
const wrapper = shallow(
|
||||
<BrowserDropdown serverInfo={serverInfo} fetchServerInfo={jest.fn()} />
|
||||
)
|
||||
wrapper.find("#logout").simulate("click", {
|
||||
preventDefault: jest.fn()
|
||||
})
|
||||
wrapper.find("#logout").simulate("click", { preventDefault: jest.fn() })
|
||||
expect(window.location.pathname.endsWith("/login")).toBeTruthy()
|
||||
})
|
||||
})
|
||||
|
||||
@@ -20,24 +20,16 @@ import { ChangePasswordModal } from "../ChangePasswordModal"
|
||||
|
||||
jest.mock("../../web", () => ({
|
||||
GetAuth: jest.fn(() => {
|
||||
return Promise.resolve({
|
||||
accessKey: "test1",
|
||||
secretKey: "test2"
|
||||
})
|
||||
return Promise.resolve({ accessKey: "test1", secretKey: "test2" })
|
||||
}),
|
||||
GenerateAuth: jest.fn(() => {
|
||||
return Promise.resolve({
|
||||
accessKey: "gen1",
|
||||
secretKey: "gen2"
|
||||
})
|
||||
return Promise.resolve({ accessKey: "gen1", secretKey: "gen2" })
|
||||
}),
|
||||
SetAuth: jest.fn(({ accessKey, secretKey }) => {
|
||||
if (accessKey == "test3" && secretKey == "test4") {
|
||||
return Promise.resolve({})
|
||||
} else {
|
||||
return Promise.reject({
|
||||
message: "Error"
|
||||
})
|
||||
return Promise.reject({ message: "Error" })
|
||||
}
|
||||
})
|
||||
}))
|
||||
@@ -48,9 +40,7 @@ describe("ChangePasswordModal", () => {
|
||||
memory: "test",
|
||||
platform: "test",
|
||||
runtime: "test",
|
||||
info: {
|
||||
isEnvCreds: false
|
||||
}
|
||||
info: { isEnvCreds: false }
|
||||
}
|
||||
|
||||
it("should render without crashing", () => {
|
||||
@@ -66,12 +56,7 @@ describe("ChangePasswordModal", () => {
|
||||
})
|
||||
|
||||
it("should show readonly keys when isEnvCreds is true", () => {
|
||||
const newServerInfo = {
|
||||
...serverInfo,
|
||||
info: {
|
||||
isEnvCreds: true
|
||||
}
|
||||
}
|
||||
const newServerInfo = { ...serverInfo, info: { isEnvCreds: true } }
|
||||
const wrapper = shallow(<ChangePasswordModal serverInfo={newServerInfo} />)
|
||||
expect(wrapper.state("accessKey")).toBe("xxxxxxxxx")
|
||||
expect(wrapper.state("secretKey")).toBe("xxxxxxxxx")
|
||||
@@ -95,16 +80,12 @@ describe("ChangePasswordModal", () => {
|
||||
const wrapper = shallow(
|
||||
<ChangePasswordModal serverInfo={serverInfo} showAlert={showAlert} />
|
||||
)
|
||||
wrapper.find("#accessKey").simulate("change", {
|
||||
target: {
|
||||
value: "test3"
|
||||
}
|
||||
})
|
||||
wrapper.find("#secretKey").simulate("change", {
|
||||
target: {
|
||||
value: "test4"
|
||||
}
|
||||
})
|
||||
wrapper
|
||||
.find("#accessKey")
|
||||
.simulate("change", { target: { value: "test3" } })
|
||||
wrapper
|
||||
.find("#secretKey")
|
||||
.simulate("change", { target: { value: "test4" } })
|
||||
wrapper.find("#update-keys").simulate("click")
|
||||
setImmediate(() => {
|
||||
expect(showAlert).toHaveBeenCalledWith({
|
||||
|
||||
@@ -18,8 +18,25 @@ import React from "react"
|
||||
import { shallow } from "enzyme"
|
||||
import Header from "../Header"
|
||||
|
||||
jest.mock("../../web", () => ({
|
||||
LoggedIn: jest
|
||||
.fn(() => true)
|
||||
.mockReturnValueOnce(true)
|
||||
.mockReturnValueOnce(false)
|
||||
}))
|
||||
describe("Header", () => {
|
||||
it("should render without crashing", () => {
|
||||
shallow(<Header />)
|
||||
})
|
||||
|
||||
it("should render Login button when the user has not LoggedIn", () => {
|
||||
const wrapper = shallow(<Header />)
|
||||
expect(wrapper.find("a").text()).toBe("Login")
|
||||
})
|
||||
|
||||
it("should render StorageInfo and BrowserDropdown when the user has LoggedIn", () => {
|
||||
const wrapper = shallow(<Header />)
|
||||
expect(wrapper.find("Connect(BrowserDropdown)").length).toBe(1)
|
||||
expect(wrapper.find("Connect(StorageInfo)").length).toBe(1)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -19,12 +19,9 @@ import { shallow, mount } from "enzyme"
|
||||
import { Login } from "../Login"
|
||||
import web from "../../web"
|
||||
|
||||
jest.mock("../../web", () => ({
|
||||
jest.mock('../../web', () => ({
|
||||
Login: jest.fn(() => {
|
||||
return Promise.resolve({
|
||||
token: "test",
|
||||
uiVersion: "2018-02-01T01:17:47Z"
|
||||
})
|
||||
return Promise.resolve({ token: "test", uiVersion: "2018-02-01T01:17:47Z" })
|
||||
}),
|
||||
LoggedIn: jest.fn()
|
||||
}))
|
||||
@@ -33,87 +30,70 @@ describe("Login", () => {
|
||||
const dispatchMock = jest.fn()
|
||||
const showAlertMock = jest.fn()
|
||||
const clearAlertMock = jest.fn()
|
||||
|
||||
|
||||
it("should render without crashing", () => {
|
||||
shallow(
|
||||
<Login
|
||||
dispatch={dispatchMock}
|
||||
alert={{ show: false, type: "danger" }}
|
||||
showAlert={showAlertMock}
|
||||
clearAlert={clearAlertMock}
|
||||
/>
|
||||
)
|
||||
shallow(<Login
|
||||
dispatch={dispatchMock}
|
||||
alert={{ show: false, type: "danger"}}
|
||||
showAlert={showAlertMock}
|
||||
clearAlert={clearAlertMock}
|
||||
/>)
|
||||
})
|
||||
|
||||
it("should initially have the is-guest class", () => {
|
||||
const wrapper = shallow(
|
||||
<Login
|
||||
dispatch={dispatchMock}
|
||||
alert={{ show: false, type: "danger" }}
|
||||
<Login
|
||||
dispatch={dispatchMock}
|
||||
alert={{ show: false, type: "danger"}}
|
||||
showAlert={showAlertMock}
|
||||
clearAlert={clearAlertMock}
|
||||
/>,
|
||||
{
|
||||
attachTo: document.body
|
||||
}
|
||||
{ attachTo: document.body }
|
||||
)
|
||||
expect(document.body.classList.contains("is-guest")).toBeTruthy()
|
||||
})
|
||||
|
||||
it("should throw an alert if the keys are empty in login form", () => {
|
||||
const wrapper = mount(
|
||||
<Login
|
||||
dispatch={dispatchMock}
|
||||
alert={{ show: false, type: "danger" }}
|
||||
<Login
|
||||
dispatch={dispatchMock}
|
||||
alert={{ show: false, type: "danger"}}
|
||||
showAlert={showAlertMock}
|
||||
clearAlert={clearAlertMock}
|
||||
/>,
|
||||
{
|
||||
attachTo: document.body
|
||||
}
|
||||
{ attachTo: document.body }
|
||||
)
|
||||
// case where both keys are empty - displays the second warning
|
||||
wrapper.find("form").simulate("submit")
|
||||
expect(showAlertMock).toHaveBeenCalledWith(
|
||||
"danger",
|
||||
"Secret Key cannot be empty"
|
||||
)
|
||||
expect(showAlertMock).toHaveBeenCalledWith("danger", "Secret Key cannot be empty")
|
||||
|
||||
// case where access key is empty
|
||||
document.getElementById("secretKey").value = "secretKey"
|
||||
wrapper.find("form").simulate("submit")
|
||||
expect(showAlertMock).toHaveBeenCalledWith(
|
||||
"danger",
|
||||
"Access Key cannot be empty"
|
||||
)
|
||||
expect(showAlertMock).toHaveBeenCalledWith("danger", "Access Key cannot be empty")
|
||||
|
||||
// case where secret key is empty
|
||||
document.getElementById("accessKey").value = "accessKey"
|
||||
wrapper.find("form").simulate("submit")
|
||||
expect(showAlertMock).toHaveBeenCalledWith(
|
||||
"danger",
|
||||
"Secret Key cannot be empty"
|
||||
)
|
||||
expect(showAlertMock).toHaveBeenCalledWith("danger", "Secret Key cannot be empty")
|
||||
})
|
||||
|
||||
it("should call web.Login with correct arguments if both keys are entered", () => {
|
||||
const wrapper = mount(
|
||||
<Login
|
||||
dispatch={dispatchMock}
|
||||
alert={{ show: false, type: "danger" }}
|
||||
<Login
|
||||
dispatch={dispatchMock}
|
||||
alert={{ show: false, type: "danger"}}
|
||||
showAlert={showAlertMock}
|
||||
clearAlert={clearAlertMock}
|
||||
/>,
|
||||
{
|
||||
attachTo: document.body
|
||||
}
|
||||
{ attachTo: document.body }
|
||||
)
|
||||
document.getElementById("accessKey").value = "accessKey"
|
||||
document.getElementById("secretKey").value = "secretKey"
|
||||
wrapper.find("form").simulate("submit")
|
||||
expect(web.Login).toHaveBeenCalledWith({
|
||||
username: "accessKey",
|
||||
password: "secretKey"
|
||||
"username": "accessKey",
|
||||
"password": "secretKey"
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -54,23 +54,19 @@ describe("MainActions", () => {
|
||||
const wrapper = shallow(
|
||||
<MainActions showMakeBucketModal={showMakeBucketModal} />
|
||||
)
|
||||
wrapper.find("#show-make-bucket").simulate("click", {
|
||||
preventDefault: jest.fn()
|
||||
})
|
||||
wrapper
|
||||
.find("#show-make-bucket")
|
||||
.simulate("click", { preventDefault: jest.fn() })
|
||||
expect(showMakeBucketModal).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it("should call uploadFile when a file is selected for upload", () => {
|
||||
const uploadFile = jest.fn()
|
||||
const wrapper = shallow(<MainActions uploadFile={uploadFile} />)
|
||||
const file = new Blob(["file content"], {
|
||||
type: "text/plain"
|
||||
})
|
||||
const file = new Blob(["file content"], { type: "text/plain" })
|
||||
wrapper.find("#file-input").simulate("change", {
|
||||
preventDefault: jest.fn(),
|
||||
target: {
|
||||
files: [file]
|
||||
}
|
||||
target: { files: [file] }
|
||||
})
|
||||
expect(uploadFile).toHaveBeenCalledWith(file)
|
||||
})
|
||||
|
||||
@@ -16,21 +16,21 @@
|
||||
|
||||
import React from "react"
|
||||
import { shallow } from "enzyme"
|
||||
import { SidebarToggle } from "../SidebarToggle"
|
||||
import { MobileHeader } from "../MobileHeader"
|
||||
|
||||
describe("SidebarToggle", () => {
|
||||
describe("Bucket", () => {
|
||||
it("should render without crashing", () => {
|
||||
shallow(<SidebarToggle sidebarOpen={false} />)
|
||||
shallow(<MobileHeader sidebarOpen={false} />)
|
||||
})
|
||||
|
||||
it("should toggleSidebar when trigger is clicked", () => {
|
||||
const toggleSidebar = jest.fn()
|
||||
const wrapper = shallow(
|
||||
<SidebarToggle sidebarOpen={false} toggleSidebar={toggleSidebar} />
|
||||
<MobileHeader sidebarOpen={false} toggleSidebar={toggleSidebar} />
|
||||
)
|
||||
wrapper.find("button").simulate("click", {
|
||||
stopPropagation: jest.fn()
|
||||
})
|
||||
wrapper
|
||||
.find("#sidebar-toggle")
|
||||
.simulate("click", { stopPropagation: jest.fn() })
|
||||
expect(toggleSidebar).toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
@@ -31,4 +31,11 @@ describe("SideBar", () => {
|
||||
const wrapper = shallow(<SideBar />)
|
||||
expect(wrapper.find("Connect(BucketSearch)").length).toBe(0)
|
||||
})
|
||||
|
||||
it("should call clickOutside when the user clicks outside the sidebar", () => {
|
||||
const clickOutside = jest.fn()
|
||||
const wrapper = shallow(<SideBar clickOutside={clickOutside} />)
|
||||
wrapper.simulate("clickOut", { preventDefault: jest.fn() })
|
||||
expect(clickOutside).toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
|
||||
@@ -20,12 +20,7 @@ import * as actionsCommon from "../actions"
|
||||
|
||||
jest.mock("../../web", () => ({
|
||||
StorageInfo: jest.fn(() => {
|
||||
return Promise.resolve({
|
||||
storageInfo: {
|
||||
Total: 100,
|
||||
Free: 60
|
||||
}
|
||||
})
|
||||
return Promise.resolve({ storageInfo: { Total: 100, Free: 60 } })
|
||||
}),
|
||||
ServerInfo: jest.fn(() => {
|
||||
return Promise.resolve({
|
||||
@@ -45,13 +40,7 @@ describe("Common actions", () => {
|
||||
it("creates common/SET_STORAGE_INFO after fetching the storage details ", () => {
|
||||
const store = mockStore()
|
||||
const expectedActions = [
|
||||
{
|
||||
type: "common/SET_STORAGE_INFO",
|
||||
storageInfo: {
|
||||
total: 100,
|
||||
free: 60
|
||||
}
|
||||
}
|
||||
{ type: "common/SET_STORAGE_INFO", storageInfo: { total: 100, free: 60 } }
|
||||
]
|
||||
return store.dispatch(actionsCommon.fetchStorageInfo()).then(() => {
|
||||
const actions = store.getActions()
|
||||
|
||||
@@ -32,9 +32,7 @@ describe("common reducer", () => {
|
||||
it("should handle TOGGLE_SIDEBAR", () => {
|
||||
expect(
|
||||
reducer(
|
||||
{
|
||||
sidebarOpen: false
|
||||
},
|
||||
{ sidebarOpen: false },
|
||||
{
|
||||
type: actionsCommon.TOGGLE_SIDEBAR
|
||||
}
|
||||
@@ -47,9 +45,7 @@ describe("common reducer", () => {
|
||||
it("should handle CLOSE_SIDEBAR", () => {
|
||||
expect(
|
||||
reducer(
|
||||
{
|
||||
sidebarOpen: true
|
||||
},
|
||||
{ sidebarOpen: true },
|
||||
{
|
||||
type: actionsCommon.CLOSE_SIDEBAR
|
||||
}
|
||||
@@ -65,17 +61,11 @@ describe("common reducer", () => {
|
||||
{},
|
||||
{
|
||||
type: actionsCommon.SET_STORAGE_INFO,
|
||||
storageInfo: {
|
||||
total: 100,
|
||||
free: 40
|
||||
}
|
||||
storageInfo: { total: 100, free: 40 }
|
||||
}
|
||||
)
|
||||
).toEqual({
|
||||
storageInfo: {
|
||||
total: 100,
|
||||
free: 40
|
||||
}
|
||||
storageInfo: { total: 100, free: 40 }
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -19,10 +19,7 @@ import * as actionsCommon from "./actions"
|
||||
export default (
|
||||
state = {
|
||||
sidebarOpen: false,
|
||||
storageInfo: {
|
||||
total: 0,
|
||||
free: 0
|
||||
},
|
||||
storageInfo: { total: 0, free: 0 },
|
||||
serverInfo: {}
|
||||
},
|
||||
action
|
||||
@@ -41,10 +38,7 @@ export default (
|
||||
storageInfo: action.storageInfo
|
||||
})
|
||||
case actionsCommon.SET_SERVER_INFO:
|
||||
return {
|
||||
...state,
|
||||
serverInfo: action.serverInfo
|
||||
}
|
||||
return { ...state, serverInfo: action.serverInfo }
|
||||
default:
|
||||
return state
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user