-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
240 additions
and
147 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
# Add directories or file patterns to ignore during indexing (e.g. foo/ or *.csv) | ||
__fixtures__ | ||
__mocks__ | ||
__test__ | ||
./**/*.fixture.tsx | ||
./**/fixture/*.* | ||
.github/workflows/run_e2e_tests.yml | ||
.helpers | ||
*.fixture.{ts,tsx} | ||
**/*.test.tsx | ||
appconfig.js | ||
configs/* | ||
cosmos** | ||
e2e/** | ||
jest.config.js | ||
jest.setup.js | ||
playwright** | ||
postcss.config.ts | ||
public | ||
scripts | ||
server | ||
template.config.js | ||
vite.config.ts | ||
vite.proxy.ts | ||
i18next-scanner.config.cjs |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import { configRepo } from '~core/config'; | ||
import { apiClient } from '~core/apiClientInstance'; | ||
import type { Event } from '~core/types'; | ||
|
||
export interface EventListParams { | ||
feed?: string; | ||
bbox?: string; | ||
} | ||
|
||
export function getEventsList(params: EventListParams, abortController: AbortController) { | ||
return apiClient | ||
.get<Event[]>( | ||
'/events', | ||
{ | ||
appId: configRepo.get().id, | ||
...params, | ||
}, | ||
true, | ||
{ | ||
signal: abortController.signal, | ||
errorsConfig: { hideErrors: true }, | ||
}, | ||
) | ||
.then((response) => response ?? []); // Ensure we always return an array | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,38 +1,63 @@ | ||
import { createAtom, createBooleanAtom } from '~utils/atoms'; | ||
import { atom, action } from '@reatom/core'; | ||
import { v3toV2 } from '~utils/atoms/v3tov2'; | ||
import { focusedGeometryAtom } from '../focused_geometry/model'; | ||
|
||
// * CurrentEventAtomState * | ||
// null represents the initial state of event - we need that state for cases of autoselecting event | ||
// { id: null } represents event reset was caused by user actions | ||
export type CurrentEventAtomState = { | ||
id: string | null; | ||
} | null; | ||
|
||
export const currentEventAtom = createAtom( | ||
{ | ||
setCurrentEventId: (eventId: string | null) => eventId, | ||
focusedGeometryAtom, | ||
}, | ||
({ onAction, onChange }, state: CurrentEventAtomState = null) => { | ||
onChange('focusedGeometryAtom', (focusedGeometry) => { | ||
const currentGeometrySource = focusedGeometry?.source; | ||
if ( | ||
currentGeometrySource && | ||
currentGeometrySource.type !== 'event' && | ||
currentGeometrySource.type !== 'episode' | ||
) { | ||
// if focused geometry is no longer represents event, user stopped work with events | ||
// following state specifies that | ||
state = { id: null }; | ||
// reatom v2 imports mapped to reatom v3 | ||
const __v3_imports = { | ||
focusedGeometryAtom: focusedGeometryAtom.v3atom, | ||
}; | ||
|
||
function __create_v3() { | ||
const { focusedGeometryAtom } = __v3_imports; | ||
// v3 definitions section | ||
|
||
// * CurrentEventAtomState * | ||
// null represents the initial state of event - we need that state for cases of autoselecting event | ||
// { id: null } represents event reset was caused by user actions | ||
type CurrentEventAtomState = { id: string | null } | null; | ||
|
||
const currentEventAtom = atom<CurrentEventAtomState>(null, 'currentEventAtom'); | ||
const scheduledAutoSelect = atom(false, 'scheduledAutoSelect'); | ||
const scheduledAutoFocus = atom(false, 'scheduledAutoFocus'); | ||
|
||
const setCurrentEventId = action((ctx, eventId: string | null) => { | ||
currentEventAtom(ctx, { id: eventId }); | ||
}, 'setCurrentEventId'); | ||
|
||
// Stateless computed atom that updates currentEventAtom based on focusedGeometryAtom | ||
const computedCurrentEventAtom = atom((ctx) => { | ||
const currentEvent = ctx.spy(currentEventAtom); | ||
const focusedGeometry = ctx.spy(focusedGeometryAtom); | ||
const currentGeometrySource = focusedGeometry?.source; | ||
|
||
if ( | ||
currentGeometrySource && | ||
currentGeometrySource.type !== 'event' && | ||
currentGeometrySource.type !== 'episode' | ||
) { | ||
if (currentEvent?.id !== null) { | ||
currentEventAtom(ctx, { id: null }); | ||
} | ||
}); | ||
} | ||
}, 'computedCurrentEventAtom'); | ||
|
||
onAction('setCurrentEventId', (eventId) => (state = { id: eventId })); | ||
// v3 exports object | ||
return { | ||
currentEventAtom, | ||
scheduledAutoSelect, | ||
scheduledAutoFocus, | ||
setCurrentEventId, | ||
computedCurrentEventAtom, | ||
}; | ||
} | ||
|
||
return state; | ||
}, | ||
'[Shared state] currentEventAtom', | ||
); | ||
const v3 = __create_v3(); | ||
// v3 exports as default | ||
export default v3; | ||
|
||
export const scheduledAutoSelect = createBooleanAtom(false, 'scheduledAutoSelect'); | ||
export const scheduledAutoFocus = createBooleanAtom(false, 'scheduledAutoFocus'); | ||
// v2 compatible exports keeping the same names | ||
export const currentEventAtom = v3toV2(v3.currentEventAtom, { | ||
setCurrentEventId: v3.setCurrentEventId, | ||
}); | ||
export const scheduledAutoSelect = v3toV2(v3.scheduledAutoSelect); | ||
export const scheduledAutoFocus = v3toV2(v3.scheduledAutoFocus); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,55 +1,85 @@ | ||
import { createAtom } from '~utils/atoms'; | ||
import { atom, action, type Ctx } from '@reatom/core'; | ||
import { v3toV2 } from '~utils/atoms/v3tov2'; | ||
import { configRepo } from '~core/config'; | ||
import { currentEventAtom, scheduledAutoSelect } from './currentEvent'; | ||
import type { EventFeedConfig } from '~core/config/types'; | ||
|
||
type CurrentEventFeedAtomState = { | ||
id: string; | ||
} | null; | ||
|
||
export const currentEventFeedAtom = createAtom( | ||
{ | ||
setCurrentFeed: (feedId: string) => feedId, | ||
setFeedForExistingEvent: (feedId: string) => feedId, | ||
resetCurrentFeed: () => null, | ||
syncFeed: (eventFeeds) => eventFeeds, | ||
}, | ||
( | ||
{ onAction, onChange, schedule, getUnlistedState }, | ||
state: CurrentEventFeedAtomState = { id: configRepo.get().defaultFeed }, | ||
) => { | ||
onAction('setCurrentFeed', (feedId) => { | ||
if (state?.id !== feedId) { | ||
state = { id: feedId }; | ||
} | ||
schedule((dispatch) => dispatch(currentEventAtom.setCurrentEventId(null))); | ||
}); | ||
// reatom v2 imports mapped to reatom v3 | ||
const __v3_imports = { | ||
currentEventAtom: currentEventAtom.v3atom, | ||
scheduledAutoSelect: scheduledAutoSelect.v3atom, | ||
}; | ||
|
||
onAction('resetCurrentFeed', () => { | ||
if (state) { | ||
state = null; | ||
} | ||
}); | ||
|
||
onAction('syncFeed', (eventFeeds) => { | ||
if (eventFeeds && eventFeeds.data.length && !eventFeeds.loading) { | ||
const newFeed = checkFeed(eventFeeds.data, state?.id); | ||
if (newFeed !== undefined && newFeed !== state?.id) { | ||
state = { id: newFeed }; | ||
const currentEvent = getUnlistedState(currentEventAtom); | ||
if (currentEvent !== null) | ||
schedule((dispatch) => dispatch(scheduledAutoSelect.setTrue())); | ||
} | ||
function __create_v3() { | ||
const { currentEventAtom, scheduledAutoSelect } = __v3_imports; | ||
// v3 definitions section | ||
|
||
type CurrentEventFeedAtomState = { | ||
id: string; | ||
} | null; | ||
|
||
const currentEventFeedAtom = atom<CurrentEventFeedAtomState>( | ||
{ id: configRepo.get().defaultFeed }, | ||
'currentEventFeedAtom', | ||
); | ||
|
||
const setCurrentFeed = action((ctx, feedId: string) => { | ||
updateFeed(ctx, feedId); | ||
}, 'setCurrentFeed'); | ||
|
||
const setFeedForExistingEvent = action((ctx, feedId: string) => { | ||
updateFeed(ctx, feedId); | ||
}, 'setFeedForExistingEvent'); | ||
|
||
const resetCurrentFeed = action((ctx) => { | ||
updateFeed(ctx, null); | ||
}, 'resetCurrentFeed'); | ||
|
||
const syncFeed = action( | ||
(ctx, eventFeeds: { data: EventFeedConfig[]; loading: boolean }) => { | ||
if (eventFeeds?.data?.length && !eventFeeds.loading) { | ||
const currentFeed = ctx.get(currentEventFeedAtom); | ||
const newFeed = checkFeed(eventFeeds.data, currentFeed?.id); | ||
updateFeed(ctx, newFeed); | ||
} | ||
}); | ||
}, | ||
'syncFeed', | ||
); | ||
|
||
function updateFeed(ctx: Ctx, newFeedId: string | null) { | ||
const currentFeed = ctx.get(currentEventFeedAtom); | ||
if (currentFeed?.id !== newFeedId) { | ||
currentEventFeedAtom(ctx, newFeedId ? { id: newFeedId } : null); | ||
// deselect current event | ||
currentEventAtom(ctx, { id: null }); | ||
scheduledAutoSelect(ctx, false); | ||
} | ||
} | ||
|
||
return state; | ||
}, | ||
'[Shared state] currentEventFeedAtom', | ||
); | ||
function checkFeed(eventFeeds: EventFeedConfig[], feedId?: string) { | ||
if (!feedId) return configRepo.get().defaultFeed; | ||
const feed = eventFeeds?.find((fd) => fd.feed === feedId); | ||
return feed ? feed.feed : configRepo.get().defaultFeed; | ||
} | ||
|
||
function checkFeed(eventFeeds: EventFeedConfig[], feedId?: string) { | ||
if (!feedId) return configRepo.get().defaultFeed; | ||
const feed = eventFeeds?.find((fd) => fd.feed === feedId); | ||
return feed ? feed.feed : configRepo.get().defaultFeed; | ||
// v3 exports object | ||
return { | ||
currentEventFeedAtom, | ||
setCurrentFeed, | ||
setFeedForExistingEvent, | ||
resetCurrentFeed, | ||
syncFeed, | ||
}; | ||
} | ||
|
||
const v3 = __create_v3(); | ||
// v3 exports as default | ||
export default v3; | ||
|
||
// v2 compatible exports keeping the same names | ||
export const currentEventFeedAtom = v3toV2(v3.currentEventFeedAtom, { | ||
setCurrentFeed: v3.setCurrentFeed, | ||
setFeedForExistingEvent: v3.setFeedForExistingEvent, | ||
resetCurrentFeed: v3.resetCurrentFeed, | ||
syncFeed: v3.syncFeed, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,60 +1,58 @@ | ||
import { createAtom } from '~utils/atoms'; | ||
import { atom } from '@reatom/core'; | ||
import { currentNotificationAtom } from '~core/shared_state'; | ||
import { | ||
currentEventAtom, | ||
scheduledAutoFocus, | ||
scheduledAutoSelect, | ||
} from '~core/shared_state/currentEvent'; | ||
import { currentEventAtom, scheduledAutoSelect } from '~core/shared_state/currentEvent'; | ||
import { i18n } from '~core/localization'; | ||
import { v3toV2 } from '~utils/atoms/v3tov2'; | ||
import { eventListResourceAtom } from './eventListResource'; | ||
|
||
export const autoSelectEvent = createAtom( | ||
{ | ||
eventListResourceAtom, | ||
}, | ||
({ getUnlistedState, schedule, onChange }, state = {}) => { | ||
onChange('eventListResourceAtom', (eventListResource) => { | ||
const autoSelectWasScheduled = getUnlistedState(scheduledAutoSelect); | ||
if ( | ||
autoSelectWasScheduled && | ||
eventListResource && | ||
!eventListResource.loading && | ||
!eventListResource.error && | ||
eventListResource.data && | ||
eventListResource.data.length | ||
) { | ||
const currentEvent = getUnlistedState(currentEventAtom); | ||
const currentEventNotInTheList = !eventListResource.data.some( | ||
(e) => e.eventId === currentEvent?.id, | ||
); | ||
// reatom v2 imports mapped to reatom v3 | ||
const __v3_imports = { | ||
eventListResourceAtom: eventListResourceAtom.v3atom, | ||
scheduledAutoSelect: scheduledAutoSelect.v3atom, | ||
currentEventAtom: currentEventAtom.v3atom, | ||
}; | ||
function __create_v3() { | ||
const { eventListResourceAtom, scheduledAutoSelect, currentEventAtom } = __v3_imports; | ||
// v3 definitions section | ||
const autoSelectEvent = atom((ctx) => { | ||
const eventListResource = ctx.spy(eventListResourceAtom); | ||
const autoSelectWasScheduled = ctx.spy(scheduledAutoSelect); | ||
const currentEvent = ctx.spy(currentEventAtom); | ||
|
||
if (!currentEventNotInTheList) return state; | ||
if ( | ||
!autoSelectWasScheduled || | ||
!eventListResource?.data?.length || | ||
eventListResource.loading || | ||
eventListResource.error | ||
) { | ||
return; | ||
} | ||
|
||
if (currentEvent?.id) { | ||
// This case happens when call for event by provided eventId didn't return event | ||
schedule((dispatch) => | ||
dispatch( | ||
currentNotificationAtom.showNotification( | ||
'warning', | ||
{ title: i18n.t('event_list.no_event_in_feed') }, | ||
5, | ||
), | ||
), | ||
); | ||
} else { | ||
const firstEventInList = eventListResource.data[0]; | ||
schedule((dispatch) => { | ||
dispatch([ | ||
scheduledAutoSelect.setFalse(), | ||
scheduledAutoFocus.setTrue(), | ||
currentEventAtom.setCurrentEventId(firstEventInList.eventId), | ||
]); | ||
}); | ||
} | ||
} | ||
}); | ||
const currentEventNotInTheList = !eventListResource.data.some( | ||
(e) => e.eventId === currentEvent?.id, | ||
); | ||
|
||
return state; | ||
}, | ||
'autoSelectEvent', | ||
); | ||
if (currentEventNotInTheList && currentEvent?.id) { | ||
currentNotificationAtom.showNotification.v3action( | ||
ctx, | ||
'warning', | ||
{ title: i18n.t('event_list.no_event_in_feed') }, | ||
5, | ||
); | ||
currentEventAtom(ctx, { id: null }); | ||
} | ||
|
||
scheduledAutoSelect(ctx, false); | ||
}, 'autoSelectEvent'); | ||
|
||
// v3 exports object | ||
return { | ||
autoSelectEvent, | ||
}; | ||
} | ||
const v3 = __create_v3(); | ||
// v3 exports as default | ||
export default v3; | ||
|
||
// v2 compatible exports keeping the same names | ||
export const autoSelectEvent = v3toV2(v3.autoSelectEvent); |
Oops, something went wrong.