Skip to content

Commit 986c283

Browse files
authored
[ui] Feat/add unit size (#286)
2 parents 395841a + b1d9e00 commit 986c283

15 files changed

+619
-163
lines changed

app/src/app/BaseDataServer.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { ClientBaseDataProvider } from "./BaseDataClient";
88
export interface BaseData {
99
statDefinitions: Tables<"stat_definition_active">[];
1010
externalIdentTypes: Tables<"external_ident_type_active">[];
11+
statbusUsers: Tables<"statbus_user_with_email_and_role">[];
1112
timeContexts: Tables<"time_context">[];
1213
defaultTimeContext: Tables<"time_context">;
1314
hasStatisticalUnits: boolean;
@@ -19,16 +20,18 @@ export async function getBaseData(client: SupabaseClient): Promise<BaseData> {
1920
throw new Error('Supabase client is not properly initialized.');
2021
}
2122

22-
let maybeStatDefinitions, maybeExternalIdentTypes, maybeTimeContexts, maybeStatisticalUnit;
23+
let maybeStatDefinitions, maybeExternalIdentTypes, maybeStatbusUsers, maybeTimeContexts, maybeStatisticalUnit;
2324
try {
2425
[
2526
{ data: maybeStatDefinitions },
2627
{ data: maybeExternalIdentTypes },
28+
{ data: maybeStatbusUsers },
2729
{ data: maybeTimeContexts },
2830
{ data: maybeStatisticalUnit },
2931
] = await Promise.all([
3032
client.from("stat_definition_active").select(),
3133
client.from("external_ident_type_active").select(),
34+
client.from("statbus_user_with_email_and_role").select(),
3235
client.from("time_context").select(),
3336
client.from("statistical_unit").select("*").limit(1),
3437
]);
@@ -45,13 +48,15 @@ export async function getBaseData(client: SupabaseClient): Promise<BaseData> {
4548
}
4649
const statDefinitions = maybeStatDefinitions as NonNullable<typeof maybeStatDefinitions>;
4750
const externalIdentTypes = maybeExternalIdentTypes as NonNullable<typeof maybeExternalIdentTypes>;
51+
const statbusUsers = maybeStatbusUsers as NonNullable<typeof maybeStatbusUsers>;
4852
const timeContexts = maybeTimeContexts as NonNullable<typeof maybeTimeContexts>;
4953
const defaultTimeContext = timeContexts[0];
5054
const hasStatisticalUnits = maybeStatisticalUnit !== null && maybeStatisticalUnit.length > 0;
5155

5256
return {
5357
statDefinitions,
5458
externalIdentTypes,
59+
statbusUsers,
5560
timeContexts,
5661
defaultTimeContext,
5762
hasStatisticalUnits,

app/src/app/api/search/export/route.ts

Lines changed: 46 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@ export async function GET(request: NextRequest) {
1111
searchParams.set("order", "name.asc");
1212
}
1313

14+
const unitTypeFilter = searchParams.get("unit_type") || "";
15+
16+
const unitType = unitTypeFilter.replace(/in\.\(|\)/g, "");
17+
const hasSingleUnitType = unitType && !unitType.includes(",");
18+
const isEstablishment = unitType === "establishment";
19+
1420
const client = await createSupabaseSSRClient();
1521
const { externalIdentTypes, statDefinitions } = await getBaseData(client);
1622

@@ -23,18 +29,45 @@ export async function GET(request: NextRequest) {
2329
externalIdentColumns,
2430
[
2531
"name",
26-
"unit_type",
32+
...(hasSingleUnitType ? [] : ["unit_type"]),
33+
"birth_date",
34+
"death_date",
2735
"primary_activity_category_code",
2836
"secondary_activity_category_code",
37+
...(isEstablishment ? [] : ["sector_code", "legal_form_code"]),
38+
"physical_address_part1",
39+
"physical_address_part2",
40+
"physical_address_part3",
41+
"physical_postcode",
42+
"physical_postplace",
2943
"physical_region_code",
44+
"physical_country_iso_2",
45+
"physical_latitude",
46+
"physical_longitude",
47+
"physical_altitude",
48+
"postal_address_part1",
49+
"postal_address_part2",
50+
"postal_address_part3",
51+
"postal_postcode",
52+
"postal_postplace",
53+
"postal_region_code",
54+
"postal_country_iso_2",
55+
"postal_latitude",
56+
"postal_longitude",
57+
"postal_altitude",
58+
"web_address",
59+
"email_address",
60+
"phone_number",
61+
"landline",
62+
"mobile_number",
63+
"fax_number",
64+
"status_code",
65+
"unit_size_code",
3066
],
3167
statDefinitionColumns,
32-
[
33-
"physical_country_iso_2",
34-
"sector_code",
35-
"legal_form_code",
36-
]
37-
].flat().join(",")
68+
]
69+
.flat()
70+
.join(",")
3871
);
3972

4073
searchParams.set("limit", "100000");
@@ -44,10 +77,15 @@ export async function GET(request: NextRequest) {
4477
try {
4578
const response = await getStatisticalUnits(client, searchParams);
4679
const { header, body } = toCSV(response.statisticalUnits);
80+
81+
const filename = hasSingleUnitType
82+
? `${unitType}s.csv`
83+
: "statistical_units.csv";
84+
4785
return new Response(header + body, {
4886
headers: {
4987
"Content-Type": "text/csv",
50-
"Content-Disposition": 'attachment; filename="statistical_units.csv"',
88+
"Content-Disposition": `attachment; filename="${filename}"`,
5189
},
5290
});
5391
} catch (error) {

app/src/app/search/SearchResults.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import {
2424
sectorDeriveStateUpdateFromSearchParams,
2525
statisticalVariablesDeriveStateUpdateFromSearchParams,
2626
statusDeriveStateUpdateFromSearchParams,
27+
unitSizeDeriveStateUpdateFromSearchParams,
2728
unitTypeDeriveStateUpdateFromSearchParams,
2829
} from "./filters/url-search-params";
2930

@@ -67,6 +68,7 @@ function initializeSearchStateFromUrlSearchParams(
6768
sectorDeriveStateUpdateFromSearchParams(initialUrlSearchParams),
6869
activityCategoryDeriveStateUpdateFromSearchParams(initialUrlSearchParams),
6970
statusDeriveStateUpdateFromSearchParams(initialUrlSearchParams),
71+
unitSizeDeriveStateUpdateFromSearchParams(initialUrlSearchParams),
7072
dataSourceDeriveStateUpdateFromSearchParams(
7173
initialUrlSearchParams,
7274
allDataSources
@@ -93,6 +95,7 @@ interface SearchResultsProps {
9395
readonly allRegions: Tables<"region_used">[];
9496
readonly allActivityCategories: Tables<"activity_category_used">[];
9597
readonly allStatuses: Tables<"status">[];
98+
readonly allUnitSizes: Tables<"unit_size">[];
9699
readonly allDataSources: Tables<"data_source">[];
97100
readonly initialUrlSearchParamsDict: URLSearchParamsDict;
98101
}
@@ -105,6 +108,7 @@ export function SearchResults({
105108
allRegions,
106109
allActivityCategories,
107110
allStatuses,
111+
allUnitSizes,
108112
allDataSources,
109113
initialUrlSearchParamsDict,
110114
}: SearchResultsProps) {
@@ -182,6 +186,7 @@ export function SearchResults({
182186
allRegions: allRegions ?? [],
183187
allActivityCategories: allActivityCategories ?? [],
184188
allStatuses: allStatuses ?? [],
189+
allUnitSizes: allUnitSizes ?? [],
185190
allDataSources: allDataSources ?? [],
186191
selectedTimeContext,
187192
isLoading,
@@ -194,6 +199,7 @@ export function SearchResults({
194199
allRegions,
195200
allActivityCategories,
196201
allStatuses,
202+
allUnitSizes,
197203
allDataSources,
198204
selectedTimeContext,
199205
isLoading,

app/src/app/search/components/column-selector.tsx

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -25,28 +25,6 @@ export function ColumnSelector({
2525
<Command>
2626
<CommandInput placeholder="Columns" />
2727
<CommandList>
28-
<CommandGroup heading="Toggle Columns">
29-
{columns.map((column) => (
30-
<CommandItem
31-
key={`column-selector-${column.code}${column.type === "Adaptable" ? "-" + column.stat_code : ""}`}
32-
value={column.label}
33-
onSelect={() => onToggleColumn(column)}
34-
disabled={column.type == "Always" ? true : false}
35-
className="space-x-2"
36-
>
37-
<Check
38-
size={14}
39-
className={
40-
column.type === "Always" || column.visible
41-
? "opacity-100"
42-
: "opacity-0"
43-
}
44-
/>
45-
<span>{column.label}</span>
46-
</CommandItem>
47-
))}
48-
</CommandGroup>
49-
<CommandSeparator />
5028
<CommandGroup heading="Profiles">
5129
<CommandItem
5230
onSelect={() => setProfile("Brief")}
@@ -94,6 +72,28 @@ export function ColumnSelector({
9472
<span>All</span>
9573
</CommandItem>
9674
</CommandGroup>
75+
<CommandSeparator />
76+
<CommandGroup heading="Toggle Columns">
77+
{columns.map((column) => (
78+
<CommandItem
79+
key={`column-selector-${column.code}${column.type === "Adaptable" ? "-" + column.stat_code : ""}`}
80+
value={column.label}
81+
onSelect={() => onToggleColumn(column)}
82+
disabled={column.type == "Always" ? true : false}
83+
className="space-x-2"
84+
>
85+
<Check
86+
size={14}
87+
className={
88+
column.type === "Always" || column.visible
89+
? "opacity-100"
90+
: "opacity-0"
91+
}
92+
/>
93+
<span>{column.label}</span>
94+
</CommandItem>
95+
))}
96+
</CommandGroup>
9797
</CommandList>
9898
</Command>
9999
);

app/src/app/search/components/statistical-unit-table-header.tsx

Lines changed: 44 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,19 @@ export function StatisticalUnitTableHeader({
2525
<TableRow key={`h-row-${headerRowSuffix}`}>
2626
{visibleColumns.map(column => {
2727
switch (column.code) {
28-
case 'name':
28+
case "name":
2929
return (
30-
<SortableTableHead name="name" label="Name" key={`h-cell-${headerCellSuffix(column)}`}>
30+
<SortableTableHead
31+
name="name"
32+
label="Name"
33+
key={`h-cell-${headerCellSuffix(column)}`}
34+
>
3135
<small className="flex">
3236
{externalIdentTypes.map(({ name }) => name).join(" | ")}
3337
</small>
3438
</SortableTableHead>
3539
);
36-
case 'activity_section':
40+
case "activity_section":
3741
return (
3842
<TableHead
3943
className="text-left hidden lg:table-cell"
@@ -42,7 +46,7 @@ export function StatisticalUnitTableHeader({
4246
Activity Section
4347
</TableHead>
4448
);
45-
case 'top_region':
49+
case "top_region":
4650
return (
4751
<TableHead
4852
className="text-left hidden lg:table-cell"
@@ -51,7 +55,7 @@ export function StatisticalUnitTableHeader({
5155
Top Region
5256
</TableHead>
5357
);
54-
case 'region':
58+
case "region":
5559
return (
5660
<SortableTableHead
5761
className="text-left hidden lg:table-cell [&>*]:align-middle"
@@ -82,21 +86,25 @@ export function StatisticalUnitTableHeader({
8286
</small>
8387
</SortableTableHead>
8488
);
85-
case 'statistic':
86-
if (column.type === 'Adaptable' && column.stat_code) {
89+
case "statistic":
90+
if (column.type === "Adaptable" && column.stat_code) {
8791
// Retrieve the matching stat definition based on stat_code
88-
const statDefinition = statDefinitions.find(statDefinition => statDefinition.code === column.stat_code);
92+
const statDefinition = statDefinitions.find(
93+
(statDefinition) => statDefinition.code === column.stat_code
94+
);
8995

90-
return (statDefinition &&
91-
<SortableTableHead
92-
key={`h-cell-${headerCellSuffix(column)}`}
93-
className="text-right hidden lg:table-cell [&>*]:capitalize"
94-
name={statDefinition.code!}
96+
return (
97+
statDefinition && (
98+
<SortableTableHead
99+
key={`h-cell-${headerCellSuffix(column)}`}
100+
className="text-right hidden lg:table-cell [&>*]:capitalize"
101+
name={statDefinition.code!}
95102
label={statDefinition.name!}
96-
/>
103+
/>
104+
)
97105
);
98106
}
99-
case 'unit_counts':
107+
case "unit_counts":
100108
return (
101109
<TableHead
102110
className="text-left hidden lg:table-cell"
@@ -106,7 +114,7 @@ export function StatisticalUnitTableHeader({
106114
</TableHead>
107115
);
108116

109-
case 'sector':
117+
case "sector":
110118
return (
111119
<SortableTableHead
112120
className="text-left hidden lg:table-cell"
@@ -178,14 +186,33 @@ export function StatisticalUnitTableHeader({
178186
Status
179187
</TableHead>
180188
);
189+
case "unit_size":
190+
return (
191+
<TableHead
192+
className="text-left hidden lg:table-cell"
193+
key={`h-cell-${headerCellSuffix(column)}`}
194+
>
195+
Unit Size
196+
</TableHead>
197+
);
181198
case "data_sources":
182199
return (
183200
<TableHead
184201
className="text-left hidden lg:table-cell"
185202
key={`h-cell-${headerCellSuffix(column)}`}
186-
>Data Sources
203+
>
204+
Data Sources
187205
</TableHead>
188206
);
207+
case "last_edit":
208+
return (
209+
<SortableTableHead
210+
className="text-left hidden lg:table-cell"
211+
key={`h-cell-${headerCellSuffix(column)}`}
212+
name="last_edit_at"
213+
label="Last Edit"
214+
/>
215+
);
189216
}
190217
})}
191218
<TableHead />

0 commit comments

Comments
 (0)