Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
90 commits
Select commit Hold shift + click to select a range
0fbf951
Add radio group component
gjmooney Nov 27, 2025
e792701
Add Command and Dialog
gjmooney Nov 27, 2025
7309b3c
playing
gjmooney Nov 26, 2025
f329a3d
css
gjmooney Nov 28, 2025
b5025b8
Move to hook
gjmooney Nov 28, 2025
53790b7
Compose hooks
gjmooney Dec 1, 2025
e576a1e
Better names
gjmooney Dec 1, 2025
206d274
Build filter object
gjmooney Dec 1, 2025
ad50f8e
Context refactor
gjmooney Dec 1, 2025
0fc2573
Added limit; pagination wip
gjmooney Dec 1, 2025
15b4301
Move where links are saved
gjmooney Dec 2, 2025
b6f78ef
Remove placeholder section
gjmooney Dec 2, 2025
4b1a165
Links in context
gjmooney Dec 2, 2025
1f80392
Might regret
gjmooney Dec 2, 2025
f555c4d
pre moving context update to hook
gjmooney Dec 2, 2025
8ce19f9
Remove redundant state
gjmooney Dec 4, 2025
35ceaac
woooooooooo
gjmooney Dec 4, 2025
33dbb3d
Remove debug logs
gjmooney Dec 4, 2025
aab2bdf
Restore add to map
gjmooney Dec 4, 2025
7938e51
working mostly
gjmooney Dec 5, 2025
0266382
Move common stuff to generic hook
gjmooney Dec 5, 2025
2ef8109
Big ole refactor
gjmooney Dec 5, 2025
a126517
Rename function
gjmooney Dec 8, 2025
62318a6
Use ref to build query
gjmooney Dec 8, 2025
fc06991
Handle prev and use currentpage in UI
gjmooney Dec 8, 2025
e162081
CSS fix
gjmooney Dec 8, 2025
c6f72ff
Thank god
gjmooney Dec 8, 2025
d446336
Get total pages again
gjmooney Dec 8, 2025
a5ca19d
comments
gjmooney Dec 9, 2025
49b9c10
disable page numebr links
gjmooney Dec 9, 2025
0cf8d16
pagination works??
gjmooney Dec 9, 2025
d0db299
Accept prev and previous
gjmooney Dec 9, 2025
7e08159
Move addToMap to context
gjmooney Dec 9, 2025
174b3d1
handler comment for later
gjmooney Dec 9, 2025
81c06f2
refactor execute query
gjmooney Dec 9, 2025
fe7741b
paginatio update
gjmooney Dec 9, 2025
40bbba1
Remove redundant fetch finally
gjmooney Dec 9, 2025
5fb2740
Lint
gjmooney Dec 10, 2025
fb92b83
Pagination stuff
gjmooney Dec 10, 2025
a3477b4
Clean up
gjmooney Dec 10, 2025
a1099a1
Some css
gjmooney Dec 10, 2025
1e46d7f
Saving filter state but restore this
gjmooney Dec 10, 2025
4dd33ac
Move inline styles to css
gjmooney Dec 11, 2025
4d76981
Use border color for borders
gjmooney Dec 11, 2025
7d1136a
Still good
gjmooney Dec 11, 2025
992187a
Renaming is fun
gjmooney Dec 11, 2025
f9b7135
Clean round 1 fin
gjmooney Dec 11, 2025
b238765
Better naming
gjmooney Dec 11, 2025
a49fccd
Use @ imports and remove unused things
gjmooney Dec 12, 2025
81607ef
Better typing for queries
gjmooney Dec 12, 2025
ea32c39
Derive all state from hook
gjmooney Dec 12, 2025
109e5d2
I hate time
gjmooney Dec 12, 2025
ed57a18
Ill never stop renaming
gjmooney Dec 12, 2025
890b6b4
Move types where they go
gjmooney Dec 12, 2025
9d6d32d
Format datetime for display
gjmooney Dec 12, 2025
63fc558
Dont set collection if there is one
gjmooney Dec 15, 2025
6b14649
Hide panel until provider selected
gjmooney Dec 15, 2025
6755450
Move spatial/temporal extent to useStacSearch
gjmooney Dec 15, 2025
a701cd5
Query on filter change
gjmooney Dec 15, 2025
4ea30dd
Better types
gjmooney Dec 15, 2025
b6ff6ac
Move inline styles to css classes
gjmooney Dec 15, 2025
768917a
oh boy
gjmooney Dec 16, 2025
54703bf
Much css tweaking
gjmooney Dec 16, 2025
4dda7de
Combobox select thing
gjmooney Dec 16, 2025
467cd20
Well yea it all just looks like shadcn now woops
gjmooney Dec 16, 2025
ffbf47d
Grid queryable rows
gjmooney Dec 17, 2025
501efe6
CSS 4eva
gjmooney Dec 17, 2025
9f89779
Move components around
gjmooney Dec 17, 2025
07573e9
Lint
gjmooney Dec 17, 2025
0205e3a
Pagination fix
gjmooney Dec 17, 2025
9395a59
Lint
gjmooney Dec 18, 2025
8f98081
Adjust geodes css
gjmooney Dec 18, 2025
d7c140f
Update Playwright Snapshots
github-actions[bot] Dec 19, 2025
aca12fa
Update Playwright Snapshots
github-actions[bot] Dec 19, 2025
2378342
CSS
gjmooney Dec 19, 2025
cd28bd8
More CSS
gjmooney Dec 19, 2025
8b1863e
You guessed it, more CSS
gjmooney Dec 19, 2025
026779c
Yep
gjmooney Dec 19, 2025
7588755
Add Search prop to Select
gjmooney Dec 19, 2025
630e84c
Make collections searchable
gjmooney Dec 19, 2025
175477e
lint
gjmooney Dec 19, 2025
a7dbdb8
Update stac test
gjmooney Jan 5, 2026
c0c877e
Update snapshot
gjmooney Jan 5, 2026
13eb8bd
Update Playwright Snapshots
github-actions[bot] Jan 5, 2026
186c9eb
Persist selected provider
gjmooney Jan 5, 2026
a43dac0
Zoom to layer when adding STAC result
gjmooney Jan 5, 2026
d23d53c
Lint
gjmooney Jan 5, 2026
63adf4d
Increase specificity of result selector
gjmooney Jan 5, 2026
2ffed6b
Show a + after results if there are more results
gjmooney Jan 8, 2026
2a6b30f
Dont hardcode proxy strategy
gjmooney Jan 9, 2026
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
65 changes: 48 additions & 17 deletions packages/base/src/mainview/mainView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2045,25 +2045,56 @@ export class MainView extends React.Component<IProps, IStates> {
let extent;
const layer = this.getLayer(id);
const source = layer?.getSource();

// TODO: Story segment layers don't have an associated OL layer
// This could be better
const jgisLayer = this._model.getLayer(id);

/**
* Layer may be undefined in two cases:
* 1. StorySegmentLayer: These layers don't have an associated OpenLayers layer
* 2. StacLayer: When centerOnPosition is called immediately after adding the layer,
* the OpenLayers layer hasn't been created yet, so we use the bbox from the
* layer model's STAC data directly.
*/
if (!layer) {
const jgisLayer = this._model.getLayer(id);
const layerParams = jgisLayer?.parameters as IStorySegmentLayer;
const coords = getCenter(layerParams.extent);

// TODO: Should pass args through signal??
// const { story } = this._model.getSelectedStory();

this._flyToPosition(
{ x: coords[0], y: coords[1] },
layerParams.zoom,
(layerParams.transition.time ?? 1) * 1000, // seconds -> ms
layerParams.transition.type,
);
// Handle StacLayer that hasn't been added to the map yet
if (jgisLayer?.type === 'StacLayer') {
const layerParams = jgisLayer.parameters as IStacLayer;
const stacBbox = layerParams.data?.bbox;

if (stacBbox && stacBbox.length === 4) {
// STAC bbox format: [west, south, east, north] in EPSG:4326
const [west, south, east, north] = stacBbox;
const bboxExtent = [west, south, east, north];

// Convert from EPSG:4326 to view projection
const viewProjection = this._Map.getView().getProjection();
const transformedExtent =
viewProjection.getCode() !== 'EPSG:4326'
? transformExtent(bboxExtent, 'EPSG:4326', viewProjection)
: bboxExtent;

this._Map.getView().fit(transformedExtent, {
size: this._Map.getSize(),
duration: 500,
padding: [250, 250, 250, 250],
});
return;
}
}

return;
// Handle StorySegmentLayer
if (jgisLayer?.type === 'StorySegmentLayer') {
const layerParams = jgisLayer.parameters as IStorySegmentLayer;
const coords = getCenter(layerParams.extent);

this._flyToPosition(
{ x: coords[0], y: coords[1] },
layerParams.zoom,
(layerParams.transition.time ?? 1) * 1000, // seconds -> ms
layerParams.transition.type,
);

return;
}
}

if (source instanceof VectorSource) {
Expand Down
7 changes: 5 additions & 2 deletions packages/base/src/panelview/leftpanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ import {
TabsList,
TabsTrigger,
} from '../shared/components/Tabs';
import StacPanel from '../stacBrowser/components/StacPanel';
import FilterComponent from './components/filter-panel/Filter';
import StacPanel from '../stacBrowser/components/StacPanel';

export interface ILeftPanelClickHandlerParams {
type: SelectionType;
Expand Down Expand Up @@ -210,7 +210,10 @@ export const LeftPanel: React.FC<ILeftPanelProps> = (
)}

{!settings.stacBrowserDisabled && (
<TabsContent value="stac" className="jgis-panel-tab-content">
<TabsContent
value="stac"
className="jgis-panel-tab-content jgis-panel-tab-content-stac-panel"
>
<StacPanel model={props.model} />
</TabsContent>
)}
Expand Down
104 changes: 104 additions & 0 deletions packages/base/src/shared/components/Combobox.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import { CheckIcon, ChevronsUpDownIcon } from 'lucide-react';
import React, { useState } from 'react';

import { Button } from '@/src/shared/components/Button';
import {
Command,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
CommandList,
} from '@/src/shared/components/Command';
import {
Popover,
PopoverContent,
PopoverTrigger,
} from '@/src/shared/components/Popover';
import { cn } from './utils';

export interface IComboboxItem {
value: string;
label: string;
onSelect?: () => void;
selected?: boolean;
showCheckIcon?: boolean;
}

interface IComboboxProps {
items: IComboboxItem[];
buttonText: string;
searchPlaceholder?: string;
emptyText?: string;
className?: string;
buttonClassName?: string;
open?: boolean;
onOpenChange?: (open: boolean) => void;
showSearch?: boolean;
}

export function Combobox({
items,
buttonText,
searchPlaceholder = 'Search...',
emptyText = 'No option found.',
className,
buttonClassName,
open: controlledOpen,
onOpenChange: controlledOnOpenChange,
showSearch = true,
}: IComboboxProps) {
const [internalOpen, setInternalOpen] = useState(false);
const open = controlledOpen !== undefined ? controlledOpen : internalOpen;
const setOpen = controlledOnOpenChange || setInternalOpen;

const handleSelect = (item: IComboboxItem) => {
// Don't close automatically - allow multi-select
if (item.onSelect) {
item.onSelect();
}
};

return (
<Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger asChild>
<Button
variant="outline"
role="combobox"
aria-expanded={open}
className={cn('jgis-combobox-button', buttonClassName)}
>
<span className="jgis-combobox-button-text">{buttonText}</span>
<ChevronsUpDownIcon className="jgis-combobox-icon" />
</Button>
</PopoverTrigger>
<PopoverContent className={cn('jgis-combobox-popover', className)}>
<Command>
{showSearch && <CommandInput placeholder={searchPlaceholder} />}
<CommandList>
<CommandEmpty>{emptyText}</CommandEmpty>
<CommandGroup>
{items.map(item => (
<CommandItem
key={item.value}
value={item.label}
onSelect={() => handleSelect(item)}
>
{item.showCheckIcon && (
<CheckIcon
className="jgis-combobox-check-icon"
style={{
opacity: item.selected ? 1 : 0,
}}
/>
)}
{item.label}
</CommandItem>
))}
</CommandGroup>
</CommandList>
</Command>
</PopoverContent>
</Popover>
);
}
40 changes: 10 additions & 30 deletions packages/base/src/shared/components/Command.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,7 @@ function Command({
return (
<CommandPrimitive
data-slot="command"
className={cn(
'bg-popover text-popover-foreground flex h-full w-full flex-col overflow-hidden rounded-md',
className,
)}
className={cn('jgis-command', className)}
{...props}
/>
);
Expand All @@ -47,12 +44,10 @@ function CommandDialog({
<DialogDescription>{description}</DialogDescription>
</DialogHeader>
<DialogContent
className={cn('overflow-hidden p-0', className)}
className={cn(className)}
showCloseButton={showCloseButton}
>
<Command className="[&_[cmdk-group-heading]]:text-muted-foreground **:data-[slot=command-input-wrapper]:h-12 [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group]]:px-2 [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5">
{children}
</Command>
<Command>{children}</Command>
</DialogContent>
</Dialog>
);
Expand All @@ -65,15 +60,12 @@ function CommandInput({
return (
<div
data-slot="command-input-wrapper"
className="flex h-9 items-center gap-2 border-b px-3"
className="jgis-command-input-wrapper"
>
<SearchIcon className="size-4 shrink-0 opacity-50" />
<SearchIcon className="size-4" />
<CommandPrimitive.Input
data-slot="command-input"
className={cn(
'placeholder:text-muted-foreground flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-hidden disabled:cursor-not-allowed disabled:opacity-50',
className,
)}
className={cn('jgis-command-input', className)}
{...props}
/>
</div>
Expand All @@ -87,10 +79,7 @@ function CommandList({
return (
<CommandPrimitive.List
data-slot="command-list"
className={cn(
'max-h-[300px] scroll-py-1 overflow-x-hidden overflow-y-auto',
className,
)}
className={cn('jgis-command-list', className)}
{...props}
/>
);
Expand All @@ -115,10 +104,7 @@ function CommandGroup({
return (
<CommandPrimitive.Group
data-slot="command-group"
className={cn(
'text-foreground [&_[cmdk-group-heading]]:text-muted-foreground overflow-hidden p-1 [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium',
className,
)}
className={cn('jgis-command-group', className)}
{...props}
/>
);
Expand All @@ -144,10 +130,7 @@ function CommandItem({
return (
<CommandPrimitive.Item
data-slot="command-item"
className={cn(
"data-[selected=true]:bg-accent data-[selected=true]:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
className,
)}
className={cn('jgis-command-item', className)}
{...props}
/>
);
Expand All @@ -160,10 +143,7 @@ function CommandShortcut({
return (
<span
data-slot="command-shortcut"
className={cn(
'text-muted-foreground ml-auto text-xs tracking-widest',
className,
)}
className={cn('jgis-command-shortcut', className)}
{...props}
/>
);
Expand Down
11 changes: 11 additions & 0 deletions packages/base/src/shared/components/Input.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import * as React from 'react';

import { cn } from './utils';

function Input({ className, type, ...props }: React.ComponentProps<'input'>) {
return (
<input type={type} data-slot="input" className={cn(className)} {...props} />
);
}

export { Input };
9 changes: 7 additions & 2 deletions packages/base/src/shared/components/Pagination.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { ChevronLeft, ChevronRight, MoreHorizontal } from 'lucide-react';
import * as React from 'react';

import { Button, ButtonProps } from './Button';
import { cn } from './utils';

const Pagination: React.FC<React.ComponentProps<'nav'>> = ({ ...props }) => (
<nav
Expand All @@ -16,8 +17,12 @@ Pagination.displayName = 'Pagination';
const PaginationContent = React.forwardRef<
HTMLUListElement,
React.ComponentProps<'ul'>
>(({ ...props }, ref) => (
<ul ref={ref} className={'jgis-pagination-content'} {...props} />
>(({ className, ...props }, ref) => (
<ul
ref={ref}
className={cn('jgis-pagination-content', className)}
{...props}
/>
));
PaginationContent.displayName = 'PaginationContent';

Expand Down
Loading
Loading