Skip to content

Commit

Permalink
Merge pull request #4580 from kobotoolbox/quick-actions-mobile
Browse files Browse the repository at this point in the history
Show quick actions on narrow screens
  • Loading branch information
magicznyleszek committed Sep 4, 2023
2 parents cb3df6a + abd2536 commit 6ddce34
Show file tree
Hide file tree
Showing 8 changed files with 218 additions and 215 deletions.
20 changes: 18 additions & 2 deletions jsapp/js/projects/customViewRoute.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ import styles from './projectViews.module.scss';
import {toJS} from 'mobx';
import {ROOT_URL} from 'js/constants';
import {fetchPostUrl} from 'js/api';
import ProjectQuickActionsEmpty from './projectsTable/projectQuickActionsEmpty';
import ProjectQuickActions from './projectsTable/projectQuickActions';
import ProjectBulkActions from './projectsTable/projectBulkActions';

function CustomViewRoute() {
const {viewUid} = useParams();
Expand Down Expand Up @@ -100,18 +102,32 @@ function CustomViewRoute() {
onClick={exportAllData}
/>

{selectedAssets.length === 0 && (
<div className={styles.actions}>
<ProjectQuickActionsEmpty />
</div>
)}

{selectedAssets.length === 1 && (
<div className={styles.quickActions}>
<div className={styles.actions}>
<ProjectQuickActions asset={selectedAssets[0]} />
</div>
)}

{selectedAssets.length > 1 && (
<div className={styles.actions}>
<ProjectBulkActions assets={selectedAssets} />
</div>
)}
</header>

<ProjectsTable
assets={customView.assets}
isLoading={!customView.isFirstLoadComplete}
highlightedFields={getFilteredFieldsNames()}
visibleFields={toJS(customView.fields) || customView.defaultVisibleFields}
visibleFields={
toJS(customView.fields) || customView.defaultVisibleFields
}
orderableFields={DEFAULT_ORDERABLE_FIELDS}
order={customView.order}
onChangeOrderRequested={customView.setOrder.bind(customView)}
Expand Down
7 changes: 7 additions & 0 deletions jsapp/js/projects/myProjectsRoute.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import styles from './projectViews.module.scss';
import routeStyles from './myProjectsRoute.module.scss';
import {toJS} from 'mobx';
import {COMMON_QUERIES, ROOT_URL} from 'js/constants';
import ProjectQuickActionsEmpty from './projectsTable/projectQuickActionsEmpty';
import ProjectQuickActions from './projectsTable/projectQuickActions';
import ProjectBulkActions from './projectsTable/projectBulkActions';
import Dropzone from 'react-dropzone';
Expand Down Expand Up @@ -125,6 +126,12 @@ function MyProjectsRoute() {
excludedFields={HOME_EXCLUDED_FIELDS}
/>

{selectedAssets.length === 0 && (
<div className={styles.actions}>
<ProjectQuickActionsEmpty />
</div>
)}

{selectedAssets.length === 1 && (
<div className={styles.actions}>
<ProjectQuickActions asset={selectedAssets[0]} />
Expand Down
3 changes: 2 additions & 1 deletion jsapp/js/projects/projectViews.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@

.header {
@include mixins.centerRowFlex;
gap: sizes.$x30;
padding: sizes.$x30 sizes.$x30 sizes.$x40;
gap: sizes.$x10 sizes.$x30;
flex-wrap: wrap;
}

.actions {
Expand Down
12 changes: 0 additions & 12 deletions jsapp/js/projects/projectsTable/projectActions.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,3 @@
@include mixins.centerRowFlex;
gap: sizes.$x10;
}

.menu {
@include mixins.floatingRoundedBox;
padding: sizes.$x6;
min-width: sizes.$x180;

// There is a `isFullWidth` property on Button component, but it also has text
// centering styles on it, so we can't use it.
:global .k-button {
width: 100%;
}
}
63 changes: 51 additions & 12 deletions jsapp/js/projects/projectsTable/projectBulkActions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,68 @@ import type {AssetResponse, ProjectViewAsset} from 'js/dataInterface';
import Button from 'js/components/common/button';
import actionsStyles from './projectActions.module.scss';
import BulkDeletePrompt from './bulkActions/bulkDeletePrompt';
import {userCan} from 'js/components/permissions/utils';

interface ProjectBulkActionsProps {
/** A list of selected assets for bulk operations. */
assets: Array<AssetResponse | ProjectViewAsset>;
}

function userCanDeleteAssets(assets: Array<AssetResponse | ProjectViewAsset>) {
return assets.every((asset) => userCan('manage_asset', asset));
}

/**
* "Bulk" Quick Actions buttons. Use these when two or more projects are
* selected in the Project Table.
*/
export default function ProjectBulkActions(props: ProjectBulkActionsProps) {
const [isDeletePromptOpen, setIsDeletePromptOpen] = useState(false);
const canBulkDelete = userCanDeleteAssets(props.assets);

let tooltipForDelete = t('Delete projects');
if (canBulkDelete) {
tooltipForDelete = t('Delete ##count## projects').replace(
'##count##',
String(props.assets.length)
);
}

return (
<div className={actionsStyles.root}>
<Button
type='bare'
color='storm'
size='s'
startIcon='trash'
tooltip={t('Delete ##count## projects').replace(
'##count##',
String(props.assets.length)
)}
onClick={() => setIsDeletePromptOpen(true)}
classNames={['right-tooltip']}
/>
{/* Archive / Unarchive - Bulk action not supported yet */}
<span data-tip={t('Archive/Unarchive')} className='right-tooltip'>
<Button
isDisabled
type='bare'
color='storm'
size='s'
startIcon='archived'
/>
</span>

{/* Share - Bulk action not supported yet */}
<span data-tip={t('Share projects')} className='right-tooltip'>
<Button
isDisabled
type='bare'
color='storm'
size='s'
startIcon='user-share'
/>
</span>

{/* Delete */}
<span data-tip={tooltipForDelete} className='right-tooltip'>
<Button
isDisabled={!canBulkDelete}
type='bare'
color='storm'
size='s'
startIcon='trash'
onClick={() => setIsDeletePromptOpen(true)}
/>
</span>

{isDeletePromptOpen && (
<BulkDeletePrompt
Expand Down

0 comments on commit 6ddce34

Please sign in to comment.