-
Notifications
You must be signed in to change notification settings - Fork 1
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
1 parent
d12ea51
commit 0a74cd5
Showing
13 changed files
with
774 additions
and
84 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
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 +1,43 @@ | ||
-- Enter migration here | ||
-- Enter migration here | ||
alter table sketch_classes add column if not exists filter_api_version int not null default 1; | ||
alter table sketch_classes add column if not exists filter_api_server_location text; | ||
|
||
alter type sketch_geometry_type add value if not exists 'FILTERED_PLANNING_UNITS'; | ||
|
||
set role seasketch_superuser; | ||
delete from sketch_classes where project_id = (select id from projects where slug = 'superuser') and name = 'Filtered Planning Units'; | ||
|
||
insert into sketch_classes( | ||
project_id, | ||
name, | ||
geometry_type, | ||
mapbox_gl_style, | ||
is_template, | ||
template_description | ||
) values ( | ||
(select id from projects where slug = 'superuser'), | ||
'Filtered Planning Units', | ||
'FILTERED_PLANNING_UNITS', | ||
'{}'::jsonb, | ||
true, | ||
'Filter polygons by criteria. Requires an API server.' | ||
) on conflict do nothing; | ||
|
||
select initialize_sketch_class_form_from_template((select id from sketch_classes where name = 'Filtered Planning Units' and is_template = true), (select id from forms where is_template = true and template_type = 'SKETCHES' and template_name = 'Basic Template')); | ||
set role postgres; | ||
|
||
GRANT update (filter_api_server_location) on sketch_classes to seasketch_user; | ||
GRANT update (filter_api_version) on sketch_classes to seasketch_user; | ||
|
||
delete from form_element_types where component_name = 'FilterInput'; | ||
insert into form_element_types ( | ||
component_name, | ||
label, | ||
is_input, | ||
is_surveys_only | ||
) values ( | ||
'FilterInput', | ||
'Filter Input', | ||
true, | ||
false | ||
); |
161 changes: 161 additions & 0 deletions
161
packages/client/src/admin/sketchClasses/EvaluateFilterServiceModal.tsx
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,161 @@ | ||
import { Trans, useTranslation } from "react-i18next"; | ||
import Modal from "../../components/Modal"; | ||
import { GeostatsAttribute } from "@seasketch/geostats-types"; | ||
import { useEffect, useState } from "react"; | ||
import Warning from "../../components/Warning"; | ||
|
||
export default function EvaluateFilterServiceModal(props: { | ||
location: string; | ||
onRequestClose: () => void; | ||
}) { | ||
const { t } = useTranslation("admin:sketching"); | ||
const [state, setState] = useState({ | ||
loading: true, | ||
attributes: [] as GeostatsAttribute[], | ||
version: 0, | ||
error: null as Error | null, | ||
featureCount: 0, | ||
}); | ||
|
||
useEffect(() => { | ||
if (props.location) { | ||
setState({ | ||
loading: true, | ||
attributes: [], | ||
version: 0, | ||
error: null, | ||
featureCount: 0, | ||
}); | ||
const abortController = new AbortController(); | ||
fetch(`${props.location.replace(/\/$/, "")}/metadata`, { | ||
signal: abortController.signal, | ||
}) | ||
.then(async (res) => { | ||
if (res.ok) { | ||
const json = await res.json(); | ||
if (!json.version) { | ||
throw new Error( | ||
"Invalid response from filter service. Missing version." | ||
); | ||
} | ||
if (!json.attributes) { | ||
throw new Error( | ||
"Invalid response from filter service. Missing attributes." | ||
); | ||
} | ||
if (!Array.isArray(json.attributes)) { | ||
throw new Error( | ||
"Invalid response from filter service. Attributes must be an array." | ||
); | ||
} | ||
const firstAttr = json.attributes[0]; | ||
if ( | ||
!firstAttr.attribute || | ||
typeof firstAttr.attribute !== "string" | ||
) { | ||
throw new Error( | ||
"Invalid response from filter service. Attribute.attribute must be a string." | ||
); | ||
} | ||
setState({ | ||
loading: true, | ||
attributes: json.attributes, | ||
version: json.version, | ||
error: null, | ||
featureCount: 0, | ||
}); | ||
// next, count features | ||
fetch(`${props.location.replace(/\/$/, "")}/count`, { | ||
signal: abortController.signal, | ||
}) | ||
.then(async (res) => { | ||
if (res.ok) { | ||
const json = await res.json(); | ||
setState((prev) => { | ||
return { | ||
...prev, | ||
featureCount: json.count, | ||
loading: false, | ||
}; | ||
}); | ||
} else { | ||
setState({ | ||
loading: false, | ||
attributes: [], | ||
version: 0, | ||
error: new Error(await res.text()), | ||
featureCount: 0, | ||
}); | ||
} | ||
}) | ||
.catch((err) => { | ||
if (err.name !== "AbortError") { | ||
setState({ | ||
loading: false, | ||
attributes: [], | ||
version: 0, | ||
error: err, | ||
featureCount: 0, | ||
}); | ||
} | ||
}); | ||
} else { | ||
setState({ | ||
loading: false, | ||
attributes: [], | ||
version: 0, | ||
error: new Error(await res.text()), | ||
featureCount: 0, | ||
}); | ||
} | ||
}) | ||
.catch((err) => { | ||
if (err.name !== "AbortError") { | ||
setState({ | ||
loading: false, | ||
attributes: [], | ||
version: 0, | ||
error: err, | ||
featureCount: 0, | ||
}); | ||
} | ||
}); | ||
return () => { | ||
abortController.abort(); | ||
}; | ||
} | ||
}, [props.location]); | ||
|
||
return ( | ||
<Modal | ||
loading={state.loading} | ||
onRequestClose={props.onRequestClose} | ||
title={t("Evaluate Filter Service")} | ||
> | ||
{state.error ? ( | ||
<Warning level="error">{state.error.message}</Warning> | ||
) : ( | ||
<div> | ||
<p> | ||
<Trans ns="admin:sketching"> | ||
This filter service is on version {{ version: state.version }} and | ||
currently contains{" "} | ||
{{ featureCount: state.featureCount.toLocaleString() }} features, | ||
with the following attributes available for filtering: | ||
</Trans> | ||
</p> | ||
|
||
<div className="max-h-64 overflow-y-auto p-2 border"> | ||
<ul> | ||
{state.attributes.map((attr) => ( | ||
<li key={attr.attribute}> | ||
<strong>{attr.attribute}</strong> ({attr.type}) | ||
</li> | ||
))} | ||
</ul> | ||
</div> | ||
</div> | ||
)} | ||
</Modal> | ||
); | ||
} |
Oops, something went wrong.