Skip to content

Commit

Permalink
create vesselGroups from vessel section
Browse files Browse the repository at this point in the history
  • Loading branch information
j8seangel committed Aug 28, 2024
1 parent ea1f3a3 commit a17a820
Show file tree
Hide file tree
Showing 6 changed files with 122 additions and 34 deletions.
26 changes: 14 additions & 12 deletions apps/fishing-map/features/dataviews/dataviews.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -216,20 +216,22 @@ export const getContextDataviewInstance = (datasetId: string): DataviewInstance<

export const getVesselGroupDataviewInstance = (
vesselGroupId: string
): DataviewInstance<DataviewType> => {
const contextDataviewInstance = {
id: `${VESSEL_GROUP_DATAVIEW_PREFIX}${Date.now()}`,
category: DataviewCategory.VesselGroups,
config: {
colorCyclingType: 'fill' as ColorCyclingType,
visible: true,
filters: {
'vessel-groups': [vesselGroupId],
): DataviewInstance<DataviewType> | undefined => {
if (vesselGroupId) {
const contextDataviewInstance = {
id: `${VESSEL_GROUP_DATAVIEW_PREFIX}${Date.now()}`,
category: DataviewCategory.VesselGroups,
config: {
colorCyclingType: 'fill' as ColorCyclingType,
visible: true,
filters: {
'vessel-groups': [vesselGroupId],
},
},
},
dataviewId: PRESENCE_DATAVIEW_SLUG,
dataviewId: PRESENCE_DATAVIEW_SLUG,
}
return contextDataviewInstance
}
return contextDataviewInstance
}

export const getDataviewInstanceFromDataview = (dataview: Dataview) => {
Expand Down
52 changes: 40 additions & 12 deletions apps/fishing-map/features/vessel-groups/VesselGroupAddButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,22 @@ import cx from 'classnames'
import { useTranslation } from 'react-i18next'
import React from 'react'
import { Button, ButtonType, ButtonSize } from '@globalfishingwatch/ui-components'
import { VesselGroupUpsert } from '@globalfishingwatch/api-types'
import { VesselLastIdentity } from 'features/search/search.slice'
import {
setVesselGroupEditId,
setNewVesselGroupSearchVessels,
setVesselGroupsModalOpen,
MAX_VESSEL_GROUP_VESSELS,
updateVesselGroupVesselsThunk,
createVesselGroupThunk,
} from 'features/vessel-groups/vessel-groups.slice'
import { useAppDispatch } from 'features/app/app.hooks'
import { IdentityVesselData } from 'features/vessel/vessel.slice'
import { ReportVesselWithDatasets } from 'features/area-report/reports.selectors'
import { getCurrentIdentityVessel } from 'features/vessel/vessel.utils'
import styles from './VesselGroupListTooltip.module.css'
import VesselGroupListTooltip from './VesselGroupListTooltip'
import VesselGroupListTooltip, { NEW_VESSEL_GROUP_ID } from './VesselGroupListTooltip'

type VesselGroupAddButtonProps = {
mode?: 'auto' | 'manual'
Expand Down Expand Up @@ -79,12 +83,36 @@ function VesselGroupAddButton(props: VesselGroupAddButtonProps) {
const handleAddToVesselGroupClick = useCallback(
async (vesselGroupId?: string) => {
if (mode === 'auto') {
console.log('TODO')
// const vesselGroup = {
// id: vesselGroupId,
// vessels,
// }
// dispatchedAction = await dispatch(updateVesselGroupThunk(vesselGroup))
const vesselGroup: VesselGroupUpsert = {
vessels: vessels.flatMap((vessel) => {
const { id, dataset } = getCurrentIdentityVessel(vessel as IdentityVesselData)
if (!id || !dataset) {
return []
}
return {
vesselId: id,
dataset: dataset as any,
}
}),
}
const thunkFn: any =
vesselGroupId === NEW_VESSEL_GROUP_ID
? createVesselGroupThunk
: updateVesselGroupVesselsThunk
if (vesselGroupId === NEW_VESSEL_GROUP_ID) {
const name = prompt(t('vesselGroup.enterName', 'Enter vessel group name'))
if (name) {
vesselGroup.name = name
}
} else {
vesselGroup.id = vesselGroupId
}
const dispatchedAction = await dispatch(thunkFn(vesselGroup))
if (thunkFn.fulfilled.match(dispatchedAction)) {
if (onAddToVesselGroup) {
onAddToVesselGroup(dispatchedAction.payload.id)
}
}
} else {
const vesselsWithDataset = vessels.map((vessel) => ({
...vessel,
Expand All @@ -94,20 +122,20 @@ function VesselGroupAddButton(props: VesselGroupAddButtonProps) {
(vessel as ReportVesselWithDatasets)?.infoDataset?.id,
}))
if (vesselsWithDataset?.length) {
if (vesselGroupId) {
if (vesselGroupId && vesselGroupId !== NEW_VESSEL_GROUP_ID) {
dispatch(setVesselGroupEditId(vesselGroupId))
}
dispatch(setNewVesselGroupSearchVessels(vesselsWithDataset))
dispatch(setVesselGroupsModalOpen(true))
} else {
console.warn('No related activity datasets founds for', vesselsWithDataset)
}
}
if (onAddToVesselGroup) {
onAddToVesselGroup(vesselGroupId)
if (onAddToVesselGroup) {
onAddToVesselGroup(vesselGroupId)
}
}
},
[dispatch, mode, onAddToVesselGroup, vessels]
[dispatch, mode, onAddToVesselGroup, t, vessels]
)
return (
<VesselGroupListTooltip onAddToVesselGroup={handleAddToVesselGroupClick} children={children} />
Expand Down
28 changes: 24 additions & 4 deletions apps/fishing-map/features/vessel-groups/vessel-groups.slice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ export const createVesselGroupThunk = createAsyncThunk(
async (vesselGroupCreate: VesselGroupUpsert, { dispatch, getState }) => {
const vesselGroupUpsert: VesselGroupUpsert = {
...vesselGroupCreate,
vessels: removeDuplicatedVesselGroupvessels(vesselGroupCreate.vessels),
vessels: removeDuplicatedVesselGroupvessels(vesselGroupCreate.vessels || []),
}
const saveVesselGroup: any = async (vesselGroup: VesselGroupUpsert, tries = 0) => {
let vesselGroupUpdated: VesselGroup
Expand Down Expand Up @@ -366,19 +366,39 @@ export const updateVesselGroupThunk = createAsyncThunk(
'vessel-groups/update',
async (vesselGroupUpsert: VesselGroupUpsert & { id: string }) => {
const { id, ...rest } = vesselGroupUpsert
const url = `/vessel-groups/${id}`
const vesselGroup: VesselGroupUpsert = {
...rest,
vessels: removeDuplicatedVesselGroupvessels(rest.vessels),
vessels: removeDuplicatedVesselGroupvessels(rest.vessels || []),
}
const vesselGroupUpdated = await GFWAPI.fetch<VesselGroup>(url, {
const vesselGroupUpdated = await GFWAPI.fetch<VesselGroup>(`/vessel-groups/${id}`, {
method: 'PATCH',
body: vesselGroup,
} as FetchOptions<any>)
return vesselGroupUpdated
}
)

export const updateVesselGroupVesselsThunk = createAsyncThunk(
'vessel-groups/update-vessels',
async (
{ id, vessels = [] }: Pick<VesselGroupUpsert, 'vessels'> & { id: string },
{ getState, dispatch }
) => {
let vesselGroup = selectVesselGroupById(id)(getState() as any)
if (!vesselGroup) {
vesselGroup = await GFWAPI.fetch<VesselGroup>(`/vessel-groups/${id}`)
}
if (vesselGroup) {
return dispatch(
updateVesselGroupThunk({
id: vesselGroup.id,
vessels: [...vesselGroup.vessels, ...vessels],
})
)
}
}
)

export const deleteVesselGroupThunk = createAsyncThunk<
VesselGroup,
string,
Expand Down
47 changes: 42 additions & 5 deletions apps/fishing-map/features/workspace/vessels/VesselsSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { SortableContext } from '@dnd-kit/sortable'
import cx from 'classnames'
import { useTranslation, Trans } from 'react-i18next'
import { IconButton, Switch } from '@globalfishingwatch/ui-components'
import { DatasetTypes, ResourceStatus } from '@globalfishingwatch/api-types'
import { resolveDataviewDatasetResource } from '@globalfishingwatch/dataviews-client'
import { useLocationConnect } from 'routes/routes.hook'
import styles from 'features/workspace/shared/Sections.module.css'
import { isBasicSearchAllowed } from 'features/search/search.selectors'
Expand All @@ -21,9 +23,13 @@ import {
} from 'features/timebar/timebar-vessel.hooks'
import { getVesselLabel } from 'utils/info'
import { selectResources, ResourcesState } from 'features/resources/resources.slice'
import { VESSEL_DATAVIEW_INSTANCE_PREFIX } from 'features/dataviews/dataviews.utils'
import {
getVesselGroupDataviewInstance,
VESSEL_DATAVIEW_INSTANCE_PREFIX,
} from 'features/dataviews/dataviews.utils'
import { selectReadOnly } from 'features/app/selectors/app.selectors'
import VesselGroupAddButton from 'features/vessel-groups/VesselGroupAddButton'
import { NEW_VESSEL_GROUP_ID } from 'features/vessel-groups/VesselGroupListTooltip'
import VesselEventsLegend from './VesselEventsLegend'
import VesselLayerPanel from './VesselLayerPanel'
import VesselsFromPositions from './VesselsFromPositions'
Expand Down Expand Up @@ -68,9 +74,20 @@ function VesselsSection(): React.ReactElement {
deleteDataviewInstance(dataviews.map((d) => d.id))
}, [dataviews, deleteDataviewInstance])

const onAddToVesselGroupClick = useCallback(() => {
console.log('todo')
}, [])
const onAddToVesselGroupClick = useCallback(
(vesselGroupId?: string) => {
if (vesselGroupId && vesselGroupId !== NEW_VESSEL_GROUP_ID) {
const dataviewInstance = getVesselGroupDataviewInstance(vesselGroupId)
if (dataviewInstance) {
const dataviewsToDelete = dataviews.flatMap((d) =>
d.config?.visible ? { id: d.id, deleted: true } : []
)
upsertDataviewInstance([...dataviewsToDelete, dataviewInstance])
}
}
},
[dataviews, upsertDataviewInstance]
)

const onSetSortOrderClick = useCallback(() => {
sortOrder.current = sortOrder.current === 'ASC' ? 'DESC' : 'ASC'
Expand Down Expand Up @@ -104,6 +121,20 @@ function VesselsSection(): React.ReactElement {
})
}, [dispatchLocation, workspace])

const vesselResources = dataviews.flatMap((dataview) => {
if (!dataview.config?.visible) {
return []
}
const { url: infoUrl } = resolveDataviewDatasetResource(dataview, DatasetTypes.Vessels)
return resources[infoUrl] || []
})
const areVesselsLoading = vesselResources.some(
(resource) => resource.status === ResourceStatus.Loading
)
const vesselsToVesselGroup = areVesselsLoading
? []
: vesselResources.map((resource) => resource.data)

return (
<div className={cx(styles.container, { 'print-hidden': !hasVisibleDataviews })}>
<div className={cx('print-hidden', styles.header)}>
Expand All @@ -123,9 +154,15 @@ function VesselsSection(): React.ReactElement {
<div className={cx(styles.sectionButtons, styles.sectionButtonsSecondary)}>
{dataviews.length > 1 && (
<Fragment>
<VesselGroupAddButton vessels={[]} onAddToVesselGroup={onAddToVesselGroupClick}>
<VesselGroupAddButton
mode="auto"
vessels={vesselsToVesselGroup}
onAddToVesselGroup={onAddToVesselGroupClick}
>
<IconButton
icon={'add-to-vessel-group'}
loading={areVesselsLoading}
disabled={areVesselsLoading}
size="medium"
tooltip={t('vesselGroup.addVessels', 'Add vessels to vessel group')}
tooltipPlacement="top"
Expand Down
1 change: 1 addition & 0 deletions apps/fishing-map/public/locales/source/translations.json
Original file line number Diff line number Diff line change
Expand Up @@ -999,6 +999,7 @@
"createNewGroup": "Create new group",
"csvError": "Uploaded CSV file has multiple columns and there is no obvious ID column",
"edit": "Edit list of vessels",
"enterName": "Enter vessel group name",
"emptyState": "Your vessel groups will appear here",
"groupName": "Group name",
"idField": "ID field",
Expand Down
2 changes: 1 addition & 1 deletion libs/api-types/src/vesselGroups.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@ export interface VesselGroup {
createdAt?: string
}

export type VesselGroupUpsert = Omit<VesselGroup, 'id' | 'public' | 'ownerId' | 'ownerType'>
export type VesselGroupUpsert = Partial<Pick<VesselGroup, 'id' | 'name' | 'vessels'>>

0 comments on commit a17a820

Please sign in to comment.