Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Classifier: Move MetaTools into same grid area as subject viewer #4021

Merged
merged 19 commits into from
Jan 16, 2023
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import styled from 'styled-components'
import { pxToRem } from '@zooniverse/react-components'
import { Box } from 'grommet'

import { withStores } from '@helpers'
import Banners from '@components/Classifier/components/Banners'
import FeedbackModal from '@components/Classifier/components/Feedback'
import ImageToolbar from '@components/Classifier/components/ImageToolbar'
Expand Down Expand Up @@ -45,7 +43,7 @@ export const ViewerGrid = styled.section`
display: grid;
grid-area: viewer;
grid-template-columns: auto 4.5rem;
grid-template-areas: "subject toolbar" "metatools ...";
grid-template-areas: "subject toolbar";
`

export const StyledImageToolbarContainer = styled.div`
Expand All @@ -57,26 +55,18 @@ export const StyledImageToolbar = styled(ImageToolbar)`
top: 10px;
`

const StyledMetaTools = styled(MetaTools)`
grid-area: metatools;
margin-top: 10px;
`

export default function DefaultLayout({
className = '',
project
}) {
export default function DefaultLayout({ className = '' }) {
return (
<ContainerGrid className={className}>
<ViewerGrid>
<Box gridArea='subject'>
<Banners />
<SubjectViewer />
<MetaTools />
</Box>
<StyledImageToolbarContainer>
<StyledImageToolbar />
</StyledImageToolbarContainer>
<StyledMetaTools />
</ViewerGrid>
<StyledTaskAreaContainer>
<StyledTaskArea />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,16 @@
import { Component } from 'react';
import PropTypes from 'prop-types'
import { Box } from 'grommet'
import { FavouritesButton, withResponsiveContext } from '@zooniverse/react-components'

import { useStores } from '@hooks'
import Metadata from './components/Metadata'
import CollectionsButton from './components/CollectionsButton'
import HidePreviousMarksButton from './components/HidePreviousMarksButton'
import SHOWN_MARKS from '@helpers/shownMarks'
import { withStores } from '@helpers'

function storeMapper(store) {
const {
subjects: {
active: subject,
isThereMetadata
},
userProjectPreferences: {
active: upp
},
workflowSteps: {
interactionTask
}
subjects: { active: subject, isThereMetadata },
userProjectPreferences: { active: upp },
workflowSteps: { interactionTask }
} = store

return {
Expand All @@ -31,69 +21,54 @@ function storeMapper(store) {
}
}

class MetaTools extends Component {
constructor () {
super()

this.addToCollection = this.addToCollection.bind(this)
}
const MetaTools = () => {
const {
className = '',
interactionTask = {},
isThereMetadata = false,
screenSize,
subject = null,
upp = null
} = useStores(storeMapper)
const { shownMarks, marks, togglePreviousMarks, type } = interactionTask
const gap = (screenSize === 'small') ? 'xsmall' : 'small'
const margin = (screenSize === 'small') ? { top: 'small' } : 'none'

addToCollection () {
const { subject } = this.props
const addToCollection = () => {
subject.addToCollection()
}

// TODO: Add fallbacks for when Panoptes is not serializing the subject favorite info
render () {
const {
className,
interactionTask,
isThereMetadata,
screenSize,
subject,
upp
} = this.props
const { shownMarks, marks, togglePreviousMarks, type } = interactionTask
const gap = (screenSize === 'small') ? 'xsmall' : 'small'
const margin = (screenSize === 'small') ? { top: 'small' } : 'none'

return (
<Box
key={subject && subject.id}
className={className}
direction='row-responsive'
gap={gap}
margin={margin}
>
<Metadata isThereMetadata={isThereMetadata} metadata={subject && subject.metadata} />
<FavouritesButton
checked={subject?.favorite}
disabled={!subject || !upp}
onClick={subject?.toggleFavorite}
return (
<Box
key={subject && subject.id}
className={className}
direction='row-responsive'
gap={gap}
margin={margin}
>
<Metadata
isThereMetadata={isThereMetadata}
metadata={subject && subject.metadata}
/>
<FavouritesButton
checked={subject?.favorite}
disabled={!subject || !upp}
onClick={subject?.toggleFavorite}
/>
<CollectionsButton
disabled={!subject || !upp}
onClick={addToCollection}
/>
Comment on lines +49 to +61
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When I run locally, signed in, and load https://local.zooniverse.org:3000/projects/brooke/i-fancy-cats/classify/workflow/693 or https://local.zooniverse.org:3000/projects/pmlogan/poets-and-lovers/classify/workflow/21362/subject-set/104809?env=production the Metadata, FavouritesButton, and CollectionsButton are unexpectedly disabled. Console logging the subject from MetaTools returns null and the component doesn't appear to rerender once the subject (and related isThereMetadata) is defined.

Copy link
Contributor

@mcbouslog mcbouslog Jan 10, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh I think the mobx observer should wrap the MetaTools export.
export default withResponsiveContext(observer(MetaTools)) with related mobx observer import.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right! I think adding observer restored some of the expected functionality, but I also noticed that you can visit i-fancy-cats on frontend.preview, sign-in to enable FavouritesButton and CollectionsButton, but then upon sign-out the upp from the store still contains user data, and the buttons are all still enabled. I think this is a bug of the UserProjectPreferences store so I'll do a quick search for an already existing Github Issue or open a new one.

{Object.keys(interactionTask).length > 0 && (
<HidePreviousMarksButton
disabled={marks?.length === 0}
shownMarks={shownMarks}
type={type}
onClick={state => togglePreviousMarks(state)}
/>
<CollectionsButton
disabled={!subject || !upp}
onClick={this.addToCollection}
/>
{Object.keys(interactionTask).length > 0 && (
<HidePreviousMarksButton
disabled={marks?.length === 0}
shownMarks={shownMarks}
type={type}
onClick={(state) => togglePreviousMarks(state)}
/>
)}
</Box>
)
}
}

MetaTools.defaultProps = {
className: '',
interactionTask: {},
isThereMetadata: false,
subject: null,
upp: null
)}
</Box>
)
}

MetaTools.propTypes = {
Expand All @@ -109,5 +84,4 @@ MetaTools.propTypes = {
upp: PropTypes.object
}

export default withStores(withResponsiveContext(MetaTools), storeMapper)
export { MetaTools }
export default withResponsiveContext(MetaTools)
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { render, screen } from '@testing-library/react'
import asyncStates from '@zooniverse/async-states'
import zooTheme from '@zooniverse/grommet-theme'
import { Grommet } from 'grommet'
import { Provider } from 'mobx-react'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import zooTheme from '@zooniverse/grommet-theme'
import { Box, Grommet } from 'grommet'
import { Provider } from 'mobx-react'
import {
DrawingTaskFactory,
SubjectFactory,
UPPFactory,
WorkflowFactory
} from '@test/factories'
import mockStore from '@test/mockStore'

import MetaTools from './MetaTools'

export default {
title: 'Meta Tools / MetaToolsContainer',
component: MetaTools,
args: {
dark: false
}
}

const background = {
dark: 'dark-1',
light: 'light-1'
}

const mockSubject = SubjectFactory.build({
locations: [
{
'image/jpeg':
'https://panoptes-uploads.zooniverse.org/subject_location/1e54b552-4608-4701-9db9-b8342b81278a.jpeg'
}
],
metadata: {
time: 'Morning',
location: 'United States'
}
})

const mockWorkflow = WorkflowFactory.build({
tasks: {
T0: DrawingTaskFactory.build()
}
})

const upp = UPPFactory.build()

const store = mockStore({
subject: mockSubject,
workflow: mockWorkflow
})

store.userProjectPreferences.setUPP(upp)

export const Default = ({ dark }) => {
const themeMode = dark ? 'dark' : 'light'
return (
<Grommet background={background} theme={zooTheme} themeMode={themeMode}>
<Provider classifierStore={store}>
<MetaTools />
</Provider>
</Grommet>
)
}

export const SmallSubjectViewer = ({ dark }) => {
const themeMode = dark ? 'dark' : 'light'
return (
<Grommet background={background} theme={zooTheme} themeMode={themeMode}>
<Provider classifierStore={store}>
<Box width='300px' style={{ border: 'solid 1px red' }}>
mcbouslog marked this conversation as resolved.
Show resolved Hide resolved
<MetaTools />
</Box>
</Provider>
</Grommet>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { MetaToolsButton, SpacedText } from '@zooniverse/react-components'
import PropTypes from 'prop-types'
import { Box, DropButton } from 'grommet'
import { FormDown, FormView, FormViewHide, Hide } from 'grommet-icons'
import { useState } from 'react';
import { useState } from 'react'
import styled, { css, withTheme } from 'styled-components'
import { useTranslation } from '@translations/i18n'

Expand Down
Original file line number Diff line number Diff line change
@@ -1,45 +1,34 @@
import { Component } from 'react';
import { useState } from 'react'
import PropTypes from 'prop-types'
import MetadataButton from './components/MetadataButton'
import { MetadataModal } from './components/MetadataModal'

export default class Metadata extends Component {
constructor () {
super()
const Metadata = ({
isThereMetadata = false,
metadata = {}
}) => {
const [showMetadataModal, setShowMetadataModal] = useState(false)

this.state = {
showMetadataModal: false
}

this.toggleMetadataModal = this.toggleMetadataModal.bind(this)
}

toggleMetadataModal () {
this.setState((prevState) => { return { showMetadataModal: !prevState.showMetadataModal } })
const toggleMetadataModal = () => {
setShowMetadataModal(!showMetadataModal)
}

render () {
const { isThereMetadata, metadata } = this.props
return (
<>
<MetadataButton disabled={!isThereMetadata} onClick={this.toggleMetadataModal} />
{isThereMetadata &&
<MetadataModal
active={this.state.showMetadataModal}
closeFn={this.toggleMetadataModal}
metadata={metadata}
/>}
</>
)
}
}

Metadata.defaultProps = {
isThereMetadata: false,
metadata: {}
return (
<>
<MetadataButton disabled={!isThereMetadata} onClick={toggleMetadataModal} />
{isThereMetadata &&
<MetadataModal
active={showMetadataModal}
closeFn={toggleMetadataModal}
metadata={metadata}
/>}
</>
)
}

Metadata.propTypes = {
isThereMetadata: PropTypes.bool,
metadata: PropTypes.object
}

export default Metadata
Loading