Skip to content

Commit 6de5862

Browse files
Draw / Super Draw edit modes + UX batch (elections revert, panel renames, portal routes, CMS place-page ordering) (#617)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
1 parent 53db1c0 commit 6de5862

89 files changed

Lines changed: 2161 additions & 1485 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

app/bun.lock

Lines changed: 0 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/e2e/tests/sidebar/data-panels.spec.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,17 @@ test.describe('Sidebar Responsiveness', () => {
273273
// Sidebar should be hidden on mobile
274274
const sidebar = page.locator(testSelectors.sidebar);
275275
await expect(sidebar).not.toBeVisible();
276+
277+
// ...but the drawing tools move to the mobile dock instead of vanishing.
278+
const toolbar = page.locator('[data-testid="toolbar"]');
279+
await expect(toolbar).toBeVisible();
280+
281+
// Selecting the paint tool reveals the brush controls (district picker).
282+
const brushTool = page.locator(testSelectors.brushTool);
283+
if (await brushTool.isVisible()) {
284+
await brushTool.click();
285+
await expect(page.getByText('Brush Size')).toBeVisible();
286+
}
276287
});
277288

278289
test('should show sidebar on landscape mobile/tablet', async ({page}) => {

app/e2e/tests/tools/shatter-tool.spec.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,14 @@ test.describe('Shatter Tool', () => {
2323
test.skip(true, 'No document ID available');
2424
return;
2525
}
26+
// The shatter tool is only rendered in Super Draw; seed the persisted
27+
// toolbar store so a fresh browser context doesn't silently skip the suite.
28+
await page.addInitScript(() => {
29+
window.localStorage.setItem(
30+
'toolbarStore',
31+
JSON.stringify({state: {superDraw: true}, version: 3})
32+
);
33+
});
2634
await navigateToMap(page, sharedDocumentId);
2735
});
2836

app/next.config.mjs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,13 @@ import createMDX from '@next/mdx';
55
const nextConfig = {
66
// Configure pageExtensions to include MDX files
77
pageExtensions: ['js', 'jsx', 'md', 'mdx', 'ts', 'tsx'],
8+
// "Tag" pages were renamed to "portal" pages; keep old links working.
9+
async redirects() {
10+
return [
11+
{source: '/tag/:slug', destination: '/portal/:slug', permanent: true},
12+
{source: '/tags', destination: '/portals', permanent: true},
13+
];
14+
},
815
// Path aliases are configured in tsconfig.json and automatically used by Next.js
916
webpack: (config, {isServer, webpack}) => {
1017
// Exclude Node.js modules from client-side bundles

app/package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,6 @@
8888
"react-google-recaptcha": "^3.1.0",
8989
"react-intersection-observer": "^9.16.0",
9090
"react-map-gl": "^7.1.3",
91-
"react-relative-time": "^0.0.9",
9291
"react-resizable": "^3.0.5",
9392
"sharp": "^0.34.1",
9493
"simple-statistics": "^7.8.7",

app/src/app/(static)/data/page.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,13 @@ export default function GuidePage() {
7373
</Link>{' '}
7474
database, which stores all sorts of geospatial data.
7575
</Text>
76+
<Text size="3">
77+
Election results and voter history data are provided courtesy of{' '}
78+
<Link href="https://davesredistricting.org" target="_blank">
79+
Dave&apos;s Redistricting
80+
</Link>
81+
.
82+
</Text>
7683
<CTA />
7784
</Flex>
7885
);

app/src/app/(static)/page.tsx

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {Flex, Heading, Text, Link, Box} from '@radix-ui/themes';
33
import Image from 'next/image';
44
import {ContentSection} from '../components/Static/ContentSection';
55
import {ResponsivePlaceMap} from '../components/Static/PlaceMap/PlaceMap';
6+
import {ImportBlockAssignments} from '../components/Static/Interactions/ImportBlockAssignments';
67
import {DevTeam} from '../components/Static/Content/DevTeam';
78
import {CTA} from '../components/Static/Content/CTA';
89

@@ -137,9 +138,15 @@ const Main: React.FC = () => {
137138
</Flex>
138139
</ContentSection>
139140
<ContentSection title="Where would you like to start?">
140-
<Box className="w-full aspect-square mx-auto lg:aspect-video">
141-
<ResponsivePlaceMap />
142-
</Box>
141+
<Flex direction="column" gapY="3">
142+
<Text size="5">
143+
Pick a state on the map, or upload a block-assignment file from another tool.
144+
</Text>
145+
<ImportBlockAssignments />
146+
<Box className="w-full aspect-square mx-auto lg:aspect-video">
147+
<ResponsivePlaceMap />
148+
</Box>
149+
</Flex>
143150
</ContentSection>
144151
<ContentSection title="About Districtr">
145152
<Flex direction="column" gapY="4" py="4">

app/src/app/(static)/place/[slug]/page.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {PlaceMapGrid} from '@/app/components/Static/Interactions/PlaceMapGrid';
55
import {getAvailableDistrictrMaps} from '@/app/utils/api/apiHandlers/getAvailableDistrictrMaps';
66
import {getCMSContent} from '@/app/utils/api/cms';
77
import {Flex, Heading} from '@radix-ui/themes';
8+
import {ImportBlockAssignments} from '@/app/components/Static/Interactions/ImportBlockAssignments';
89
import {cookies} from 'next/headers';
910

1011
export const revalidate = 3600;
@@ -25,8 +26,11 @@ export default async function Page({params}: {params: Promise<{slug: string}>})
2526
);
2627
}
2728

29+
// Preserve the order saved in the CMS, not the order of the available-maps list.
2830
const availableMaps = maps.ok
29-
? maps.response.filter(m => cmsData.content.districtr_map_slugs!.includes(m.districtr_map_slug))
31+
? (cmsData.content.districtr_map_slugs ?? [])
32+
.map(slug => maps.response.find(m => m.districtr_map_slug === slug))
33+
.filter((m): m is NonNullable<typeof m> => m !== undefined)
3034
: null;
3135

3236
return (
@@ -40,6 +44,9 @@ export default async function Page({params}: {params: Promise<{slug: string}>})
4044
/>
4145
<ContentSection title="Draw a plan from scratch">
4246
{Boolean(availableMaps?.length) && <PlaceMapGrid maps={availableMaps!} />}
47+
<Flex direction="column" align="start" pt="3">
48+
<ImportBlockAssignments />
49+
</Flex>
4350
</ContentSection>
4451

4552
<RichTextRenderer content={cmsData.content.published_content.body} className="my-4" />
File renamed without changes.
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {Card, Flex, Grid, Heading, Text, Link} from '@radix-ui/themes';
55
export const dynamic = 'force-dynamic';
66
export const revalidate = 3600;
77

8-
export default async function TagsPage() {
8+
export default async function PortalsPage() {
99
const cmsContent = await listCMSContent('tags');
1010
const cmsContentWithPublishedContent = cmsContent?.filter(content => content.published_content);
1111
if (!cmsContentWithPublishedContent) return null;
@@ -19,7 +19,7 @@ export default async function TagsPage() {
1919
return (
2020
<Flex direction={'column'}>
2121
<Heading as="h1" size="6" mb="4">
22-
Tags
22+
Portals
2323
</Heading>
2424
<Grid
2525
columns={{
@@ -29,13 +29,13 @@ export default async function TagsPage() {
2929
}}
3030
gap="4"
3131
>
32-
{entries.length === 0 && <Text>No tags found</Text>}
32+
{entries.length === 0 && <Text>No portals found</Text>}
3333
{entries.map(content => (
3434
<Card key={content.slug}>
3535
<Heading as="h3" size="4">
3636
{content.published_content!.title}
3737
</Heading>
38-
<Link href={`/tag/${content.slug}`}>Go to tag</Link>
38+
<Link href={`/portal/${content.slug}`}>Go to portal</Link>
3939
</Card>
4040
))}
4141
</Grid>

0 commit comments

Comments
 (0)