diff --git a/frontend/src/metabase/components/CollectionLanding.jsx b/frontend/src/metabase/components/CollectionLanding.jsx index ab6d525f5bf860fb893c928be0b0fa6b9e5fba09..7ed3da917445890e0915d6e2a0994de79b6a3333 100644 --- a/frontend/src/metabase/components/CollectionLanding.jsx +++ b/frontend/src/metabase/components/CollectionLanding.jsx @@ -2,18 +2,16 @@ import React from "react"; import { Box, Flex, Subhead, Truncate } from "rebass"; import { t } from "c-3po"; import { connect } from "react-redux"; -import { withRouter } from "react-router"; import _ from "underscore"; import listSelect from "metabase/hoc/ListSelect"; - -import Question from "metabase/entities/questions"; -import Dashboard from "metabase/entities/dashboards"; +import BulkActionBar from "metabase/components/BulkActionBar" import * as Urls from "metabase/lib/urls"; import { normal } from "metabase/lib/colors"; +import Button from "metabase/components/Button"; import Card from "metabase/components/Card"; -import CheckBox from "metabase/components/CheckBox"; +import StackedCheckBox from "metabase/components/StackedCheckBox"; import EntityItem from "metabase/components/EntityItem"; import { Grid, GridItem } from "metabase/components/Grid"; import Icon from "metabase/components/Icon"; @@ -35,11 +33,6 @@ const mapStateToProps = (state, props) => ({ }) || {}, }); -const mapDispatchToProps = { - updateQuestion: Question.actions.update, - updateDashboard: Dashboard.actions.update, -}; - const CollectionItem = ({ collection }) => ( <Link to={`collection/${collection.id}`} @@ -103,7 +96,7 @@ class DefaultLanding extends React.Component { }; render() { - const { collectionId, list, onToggleSelected, selection } = this.props; + const { collectionId, list, onToggleSelected, selection, selected } = this.props; // Show the const showCollectionList = collectionId === "root"; @@ -189,6 +182,7 @@ class DefaultLanding extends React.Component { <Box key={item.type + item.id}> <Link to={item.getUrl()}> <EntityItem + showSelect={selected.length > 0} selectable item={item} type={item.type} @@ -219,6 +213,11 @@ class DefaultLanding extends React.Component { ); }} </CollectionLoader> + <BulkActionBar showing={selected.length > 0}> + <SelectionControls {...this.props} /> + <BulkActionControls {...this.props} /> + <Box ml="auto">{t`${selected.length} items selected`}</Box> + </BulkActionBar> </Box> </Box> </Flex> @@ -226,6 +225,45 @@ class DefaultLanding extends React.Component { } } +const BulkActionControls = ({ selected, reload }) => ( + <Box> + <Button + ml={1} + medium + onClick={async () => { + try { + await Promise.all(selected.map(item => item.setArchived(true))); + } finally { + reload(); + } + }} + >{t`Archive`}</Button> + <Button + ml={1} + medium + onClick={async () => { + try { + await Promise.all(selected.map(item => item.setArchived(true))); + } finally { + reload(); + } + }} + >{t`Move`}</Button> + </Box> +); + +const SelectionControls = ({ + selected, + deselected, + onSelectAll, + onSelectNone, +}) => + deselected.length === 0 ? ( + <StackedCheckBox checked={true} onChange={onSelectNone} /> + ) : ( + <StackedCheckBox checked={false} onChange={onSelectAll} /> + ); + @connect(mapStateToProps) class CollectionLanding extends React.Component { render() { diff --git a/frontend/src/metabase/components/EntityItem.jsx b/frontend/src/metabase/components/EntityItem.jsx index 185d5074005c9b17b479e0c0b7b63c238ad18f65..ede6ba6f67374cbfc70d8b90cbe56d1925596e1e 100644 --- a/frontend/src/metabase/components/EntityItem.jsx +++ b/frontend/src/metabase/components/EntityItem.jsx @@ -37,7 +37,8 @@ const EntityItem = ({ onFavorite, selected, onToggleSelected, - selectable + selectable, + showSelect }) => { return ( <EntityItemWrapper py={2} px={2} className="hover-parent hover--visibility"> @@ -49,6 +50,7 @@ const EntityItem = ({ > { selectable ? ( <Swapper + startSwapped={showSelect} defaultElement={<Icon name={iconName} color={iconColor} />} swappedElement={ <CheckBox @@ -122,7 +124,7 @@ class Swapper extends React.Component { } render () { - const { defaultElement, swappedElement } = this.props + const { defaultElement, swappedElement, startSwapped } = this.props const { hovered } = this.state return ( @@ -136,7 +138,7 @@ class Swapper extends React.Component { scale: 1 }} style={{ - scale: hovered ? spring(0): spring(1) + scale: hovered || startSwapped ? spring(0): spring(1) }} > {({ scale }) => { @@ -152,7 +154,7 @@ class Swapper extends React.Component { scale: 0 }} style={{ - scale: hovered ? spring(1): spring(0) + scale: hovered || startSwapped ? spring(1): spring(0) }} > {({ scale }) => {