diff --git a/packages/api/generated-schema-clean.gql b/packages/api/generated-schema-clean.gql index 5d0ab111..ead2992e 100644 --- a/packages/api/generated-schema-clean.gql +++ b/packages/api/generated-schema-clean.gql @@ -3388,6 +3388,7 @@ enum DataUploadOutputType { FLAT_GEOBUF GEO_JSON GEO_TIFF + NET_CDF PMTILES PNG XMLMETADATA diff --git a/packages/api/generated-schema.gql b/packages/api/generated-schema.gql index 5d0ab111..ead2992e 100644 --- a/packages/api/generated-schema.gql +++ b/packages/api/generated-schema.gql @@ -3388,6 +3388,7 @@ enum DataUploadOutputType { FLAT_GEOBUF GEO_JSON GEO_TIFF + NET_CDF PMTILES PNG XMLMETADATA diff --git a/packages/api/migrations/committed/000336.sql b/packages/api/migrations/committed/000336.sql new file mode 100644 index 00000000..d6158636 --- /dev/null +++ b/packages/api/migrations/committed/000336.sql @@ -0,0 +1,5 @@ +--! Previous: sha1:fc2579e6e5275d22de4e81f534d1666a014721f8 +--! Hash: sha1:b8cbc01e7d5166e77a68f5e3072082b77ff40769 + +-- Enter migration here +alter type data_upload_output_type add value if not exists 'NetCDF'; diff --git a/packages/api/schema.sql b/packages/api/schema.sql index d9d1596e..2c1a2b21 100644 --- a/packages/api/schema.sql +++ b/packages/api/schema.sql @@ -265,7 +265,8 @@ CREATE TYPE public.data_upload_output_type AS ENUM ( 'PMTiles', 'GeoTIFF', 'PNG', - 'XMLMetadata' + 'XMLMetadata', + 'NetCDF' ); @@ -2919,12 +2920,12 @@ CREATE TABLE public.archived_data_sources ( sprite_ids integer[] GENERATED ALWAYS AS (public.extract_sprite_ids((mapbox_gl_style)::text)) STORED, changelog text, source_layer text, + project_id integer NOT NULL, bounds numeric[], created_at timestamp with time zone DEFAULT now(), sublayer text, sublayer_type public.sublayer_type, - dynamic_metadata boolean DEFAULT false NOT NULL, - project_id integer NOT NULL + dynamic_metadata boolean DEFAULT false NOT NULL ); @@ -6459,6 +6460,7 @@ CREATE TABLE public.table_of_contents_items ( translated_props jsonb DEFAULT '{}'::jsonb NOT NULL, fts_simple tsvector GENERATED ALWAYS AS (public.toc_to_tsvector('simple'::text, title, metadata, translated_props)) STORED, fts_en tsvector GENERATED ALWAYS AS (public.toc_to_tsvector('english'::text, title, metadata, translated_props)) STORED, + fts_es tsvector GENERATED ALWAYS AS (public.toc_to_tsvector('spanish'::text, title, metadata, translated_props)) STORED, fts_pt tsvector GENERATED ALWAYS AS (public.toc_to_tsvector('portuguese'::text, title, metadata, translated_props)) STORED, fts_ar tsvector GENERATED ALWAYS AS (public.toc_to_tsvector('arabic'::text, title, metadata, translated_props)) STORED, fts_da tsvector GENERATED ALWAYS AS (public.toc_to_tsvector('danish'::text, title, metadata, translated_props)) STORED, @@ -6472,7 +6474,6 @@ CREATE TABLE public.table_of_contents_items ( fts_ro tsvector GENERATED ALWAYS AS (public.toc_to_tsvector('romanian'::text, title, metadata, translated_props)) STORED, fts_ru tsvector GENERATED ALWAYS AS (public.toc_to_tsvector('russian'::text, title, metadata, translated_props)) STORED, fts_sv tsvector GENERATED ALWAYS AS (public.toc_to_tsvector('swedish'::text, title, metadata, translated_props)) STORED, - fts_es tsvector GENERATED ALWAYS AS (public.toc_to_tsvector('spanish'::text, title, metadata, translated_props)) STORED, data_source_type text, original_source_upload_available boolean DEFAULT false NOT NULL, CONSTRAINT table_of_contents_items_metadata_check CHECK (((metadata IS NULL) OR (char_length((metadata)::text) < 100000))), @@ -9656,7 +9657,7 @@ COMMENT ON FUNCTION public.get_sprite_data_for_screenshot(bookmark public.map_bo CREATE FUNCTION public.get_supported_languages() RETURNS jsonb LANGUAGE sql IMMUTABLE AS $$ - select '{"simple": "simple", "english": "EN", "spanish": "es", "portuguese": "pt", "arabic": "ar", "danish": "da", "dutch": "nl", "french": "fr", "german": "de", "indonesian": "id", "italian": "it", "lithuanian": "lt", "norwegian": "no", "romanian": "ro", "russian": "ru", "swedish": "sv"}'::jsonb; + select '{"simple": "simple", "english": "en", "spanish": "es", "portuguese": "pt", "arabic": "ar", "danish": "da", "dutch": "nl", "french": "fr", "german": "de", "greek": "el", "indonesian": "id", "italian": "it", "lithuanian": "lt", "norwegian": "no", "romanian": "ro", "russian": "ru", "swedish": "sv"}'::jsonb; $$; @@ -9731,23 +9732,6 @@ CREATE FUNCTION public.has_session() RETURNS boolean COMMENT ON FUNCTION public.has_session() IS '@omit'; --- --- Name: id_lookup_get_key(integer); Type: FUNCTION; Schema: public; Owner: - --- - -CREATE FUNCTION public.id_lookup_get_key(key integer) RETURNS integer - LANGUAGE plpgsql - AS $$ - begin - if lookup is null then - raise exception 'lookup is null'; - else - return (lookup->key)::int; - end if; - end; - $$; - - -- -- Name: id_lookup_get_key(jsonb, integer); Type: FUNCTION; Schema: public; Owner: - -- @@ -13997,25 +13981,309 @@ CREATE FUNCTION public.search_overlays(lang text, query text, "projectId" intege LANGUAGE plpgsql STABLE SECURITY DEFINER AS $$ declare - q tsquery := websearch_to_tsquery('english'::regconfig, query); + supported_languages jsonb := get_supported_languages(); + config regconfig; + q tsquery := websearch_to_tsquery(config, query); begin + select key::regconfig into config from jsonb_each_text(get_supported_languages()) where value = lower(lang); IF position(' ' in query) <= 0 THEN - q := to_tsquery('english'::regconfig, query || ':*'); + q := to_tsquery(config, query || ':*'); + end if; + if config is null then + q = plainto_tsquery('simple', query); + IF position(' ' in query) <= 0 THEN + q := to_tsquery('simple', query || ':*'); + end if; + -- use the simple index + return query select + id, + stable_id, + ts_headline('simple', title, q, 'StartSel=<<<, StopSel=>>>') as title_headline, + ts_headline('simple', jsonb_array_to_string(collect_prosemirror_text_nodes(metadata)), q, 'MaxFragments=10, MaxWords=7, MinWords=3, StartSel=<<<, StopSel=>>>') as metadata_headline, + is_folder + from + table_of_contents_items + where + project_id = "projectId" and + is_draft = draft and + fts_simple @@ q + limit + coalesce("limit", 10); + elsif config = 'english'::regconfig then + return query select + id, + stable_id, + ts_headline(config, coalesce( + translated_props->lang->>'title'::text, title + ), q, 'StartSel=<<<, StopSel=>>>') as title_headline, + ts_headline(config, jsonb_array_to_string(collect_prosemirror_text_nodes(metadata)), q, 'MaxFragments=10, MaxWords=7, MinWords=3, StartSel=<<<, StopSel=>>>') as metadata_headline, + is_folder + from + table_of_contents_items + where + project_id = "projectId" and + is_draft = draft and + fts_en @@ q + limit + coalesce("limit", 10); + elsif lower(lang) = 'es' then + return query select + id, + stable_id, + ts_headline(config, coalesce( + translated_props->lang->>'title'::text, title + ), q, 'StartSel=<<<, StopSel=>>>') as title_headline, + ts_headline(config, jsonb_array_to_string(collect_prosemirror_text_nodes(metadata)), q, 'MaxFragments=10, MaxWords=7, MinWords=3, StartSel=<<<, StopSel=>>>') as metadata_headline, + is_folder + from + table_of_contents_items + where + project_id = "projectId" and + is_draft = draft and + fts_es @@ q + limit + coalesce("limit", 10); + elsif lower(lang) = 'pt' then + return query select + id, + stable_id, + ts_headline(config, coalesce( + translated_props->lang->>'title'::text, title + ), q, 'StartSel=<<<, StopSel=>>>') as title_headline, + ts_headline('portuguese', jsonb_array_to_string(collect_prosemirror_text_nodes(metadata)), q, 'MaxFragments=10, MaxWords=7, MinWords=3, StartSel=<<<, StopSel=>>>') as metadata_headline, + is_folder + from + table_of_contents_items + where + project_id = "projectId" and + is_draft = draft and + fts_pt @@ q + limit + coalesce("limit", 10); + elsif lower(lang) = 'ar' then + return query select + id, + stable_id, + ts_headline(config, coalesce( + translated_props->lang->>'title'::text, title + ), q, 'StartSel=<<<, StopSel=>>>') as title_headline, + ts_headline('arabic', jsonb_array_to_string(collect_prosemirror_text_nodes(metadata)), q, 'MaxFragments=10, MaxWords=7, MinWords=3, StartSel=<<<, StopSel=>>>') as metadata_headline, + is_folder + from + table_of_contents_items + where + project_id = "projectId" and + is_draft = draft and + fts_ar @@ q + limit + coalesce("limit", 10); + elsif lower(lang) = 'da' then + return query select + id, + stable_id, + ts_headline(config, coalesce( + translated_props->lang->>'title'::text, title + ), q, 'StartSel=<<<, StopSel=>>>') as title_headline, + ts_headline(config, jsonb_array_to_string(collect_prosemirror_text_nodes(metadata)), q, 'MaxFragments=10, MaxWords=7, MinWords=3, StartSel=<<<, StopSel=>>>') as metadata_headline, + is_folder + from + table_of_contents_items + where + project_id = "projectId" and + is_draft = draft and + fts_da @@ q + limit + coalesce("limit", 10); + elsif lower(lang) = 'nl' then + return query select + id, + stable_id, + ts_headline(config, coalesce( + translated_props->lang->>'title'::text, title + ), q, 'StartSel=<<<, StopSel=>>>') as title_headline, + ts_headline(config, jsonb_array_to_string(collect_prosemirror_text_nodes(metadata)), q, 'MaxFragments=10, MaxWords=7, MinWords=3, StartSel=<<<, StopSel=>>>') as metadata_headline, + is_folder + from + table_of_contents_items + where + project_id = "projectId" and + is_draft = draft and + fts_nl @@ q + limit + coalesce("limit", 10); + elsif lower(lang) = 'fr' then + return query select + id, + stable_id, + ts_headline(config, coalesce( + translated_props->lang->>'title'::text, title + ), q, 'StartSel=<<<, StopSel=>>>') as title_headline, + ts_headline(config, jsonb_array_to_string(collect_prosemirror_text_nodes(metadata)), q, 'MaxFragments=10, MaxWords=7, MinWords=3, StartSel=<<<, StopSel=>>>') as metadata_headline, + is_folder + from + table_of_contents_items + where + project_id = "projectId" and + is_draft = draft and + fts_fr @@ q + limit + coalesce("limit", 10); + elsif lower(lang) = 'de' then + return query select + id, + stable_id, + ts_headline(config, coalesce( + translated_props->lang->>'title'::text, title + ), q, 'StartSel=<<<, StopSel=>>>') as title_headline, + ts_headline(config, jsonb_array_to_string(collect_prosemirror_text_nodes(metadata)), q, 'MaxFragments=10, MaxWords=7, MinWords=3, StartSel=<<<, StopSel=>>>') as metadata_headline, + is_folder + from + table_of_contents_items + where + project_id = "projectId" and + is_draft = draft and + fts_de @@ q + limit + coalesce("limit", 10); + elsif lower(lang) = 'el' then + return query select + id, + stable_id, + ts_headline(config, coalesce( + translated_props->lang->>'title'::text, title + ), q, 'StartSel=<<<, StopSel=>>>') as title_headline, + ts_headline(config, jsonb_array_to_string(collect_prosemirror_text_nodes(metadata)), q, 'MaxFragments=10, MaxWords=7, MinWords=3, StartSel=<<<, StopSel=>>>') as metadata_headline, + is_folder + from + table_of_contents_items + where + project_id = "projectId" and + is_draft = draft and + fts_el @@ q + limit + coalesce("limit", 10); + elsif lower(lang) = 'id' then + return query select + id, + stable_id, + ts_headline(config, coalesce( + translated_props->lang->>'title'::text, title + ), q, 'StartSel=<<<, StopSel=>>>') as title_headline, + ts_headline(config, jsonb_array_to_string(collect_prosemirror_text_nodes(metadata)), q, 'MaxFragments=10, MaxWords=7, MinWords=3, StartSel=<<<, StopSel=>>>') as metadata_headline, + is_folder + from + table_of_contents_items + where + project_id = "projectId" and + is_draft = draft and + fts_id @@ q + limit + coalesce("limit", 10); + elsif lower(lang) = 'it' then + return query select + id, + stable_id, + ts_headline(config, coalesce( + translated_props->lang->>'title'::text, title + ), q, 'StartSel=<<<, StopSel=>>>') as title_headline, + ts_headline(config, jsonb_array_to_string(collect_prosemirror_text_nodes(metadata)), q, 'MaxFragments=10, MaxWords=7, MinWords=3, StartSel=<<<, StopSel=>>>') as metadata_headline, + is_folder + from + table_of_contents_items + where + project_id = "projectId" and + is_draft = draft and + fts_it @@ q + limit + coalesce("limit", 10); + elsif lower(lang) = 'lt' then + return query select + id, + stable_id, + ts_headline(config, coalesce( + translated_props->lang->>'title'::text, title + ), q, 'StartSel=<<<, StopSel=>>>') as title_headline, + ts_headline(config, jsonb_array_to_string(collect_prosemirror_text_nodes(metadata)), q, 'MaxFragments=10, MaxWords=7, MinWords=3, StartSel=<<<, StopSel=>>>') as metadata_headline, + is_folder + from + table_of_contents_items + where + project_id = "projectId" and + is_draft = draft and + fts_lt @@ q + limit + coalesce("limit", 10); + elsif lower(lang) = 'no' then + return query select + id, + stable_id, + ts_headline(config, coalesce( + translated_props->lang->>'title'::text, title + ), q, 'StartSel=<<<, StopSel=>>>') as title_headline, + ts_headline(config, jsonb_array_to_string(collect_prosemirror_text_nodes(metadata)), q, 'MaxFragments=10, MaxWords=7, MinWords=3, StartSel=<<<, StopSel=>>>') as metadata_headline, + is_folder + from + table_of_contents_items + where + project_id = "projectId" and + is_draft = draft and + fts_no @@ q + limit + coalesce("limit", 10); + elsif lower(lang) = 'ro' then + return query select + id, + stable_id, + ts_headline(config, coalesce( + translated_props->lang->>'title'::text, title + ), q, 'StartSel=<<<, StopSel=>>>') as title_headline, + ts_headline(config, jsonb_array_to_string(collect_prosemirror_text_nodes(metadata)), q, 'MaxFragments=10, MaxWords=7, MinWords=3, StartSel=<<<, StopSel=>>>') as metadata_headline, + is_folder + from + table_of_contents_items + where + project_id = "projectId" and + is_draft = draft and + fts_ro @@ q + limit + coalesce("limit", 10); + elsif lower(lang) = 'ru' then + return query select + id, + stable_id, + ts_headline(config, coalesce( + translated_props->lang->>'title'::text, title + ), q, 'StartSel=<<<, StopSel=>>>') as title_headline, + ts_headline(config, jsonb_array_to_string(collect_prosemirror_text_nodes(metadata)), q, 'MaxFragments=10, MaxWords=7, MinWords=3, StartSel=<<<, StopSel=>>>') as metadata_headline, + is_folder + from + table_of_contents_items + where + project_id = "projectId" and + is_draft = draft and + fts_ru @@ q + limit + coalesce("limit", 10); + elsif lower(lang) = 'sv' then + return query select + id, + stable_id, + ts_headline(config, coalesce( + translated_props->lang->>'title'::text, title + ), q, 'StartSel=<<<, StopSel=>>>') as title_headline, + ts_headline(config, jsonb_array_to_string(collect_prosemirror_text_nodes(metadata)), q, 'MaxFragments=10, MaxWords=7, MinWords=3, StartSel=<<<, StopSel=>>>') as metadata_headline, + is_folder + from + table_of_contents_items + where + project_id = "projectId" and + is_draft = draft and + fts_sv @@ q + limit + coalesce("limit", 10); + else + raise exception 'Unsupported language: %', lang; end if; - return query select - id, - stable_id, - ts_headline('english', title, q, 'StartSel=<<<, StopSel=>>>') as title_headline, - ts_headline('english', jsonb_array_to_string(collect_prosemirror_text_nodes(metadata)), q, 'MaxFragments=10, MaxWords=7, MinWords=3, StartSel=<<<, StopSel=>>>') as metadata_headline, - is_folder - from - table_of_contents_items - where - project_id = "projectId" and - is_draft = draft and - fts_en @@ q - limit - coalesce("limit", 10); end; $$; @@ -14027,40 +14295,6 @@ CREATE FUNCTION public.search_overlays(lang text, query text, "projectId" intege COMMENT ON FUNCTION public.search_overlays(lang text, query text, "projectId" integer, draft boolean, "limit" integer) IS '@simpleCollections only'; --- --- Name: search_overlays2(text, text, integer, boolean, integer); Type: FUNCTION; Schema: public; Owner: - --- - -CREATE FUNCTION public.search_overlays2(lang text, query text, "projectId" integer, draft boolean, "limit" integer) RETURNS public.search_result[] - LANGUAGE plpgsql STABLE SECURITY DEFINER - AS $$ - declare - q tsquery := websearch_to_tsquery('english'::regconfig, query); - results search_result[]; - begin - IF position(' ' in query) <= 0 THEN - q := to_tsquery('english'::regconfig, query || ':*'); - end if; - select - id, - stable_id, - ts_headline('english', title, q, 'StartSel=<<<, StopSel=>>>') as title_headline, - ts_headline('english', jsonb_array_to_string(collect_prosemirror_text_nodes(metadata)), q, 'MaxFragments=10, MaxWords=7, MinWords=3, StartSel=<<<, StopSel=>>>') as metadata_headline, - is_folder - into results - from - table_of_contents_items - where - project_id = "projectId" and - is_draft = draft and - fts_en @@ q - limit - coalesce("limit", 10); - return results; - end; - $$; - - -- -- Name: invite_emails; Type: TABLE; Schema: public; Owner: - -- @@ -23747,8 +23981,8 @@ GRANT UPDATE(hide_overlays) ON TABLE public.projects TO seasketch_user; -- Name: COLUMN projects.enable_download_by_default; Type: ACL; Schema: public; Owner: - -- +GRANT SELECT(enable_download_by_default),UPDATE(enable_download_by_default) ON TABLE public.projects TO seasketch_user; GRANT SELECT(enable_download_by_default) ON TABLE public.projects TO anon; -GRANT UPDATE(enable_download_by_default) ON TABLE public.projects TO seasketch_user; -- @@ -27390,13 +27624,6 @@ REVOKE ALL ON FUNCTION public.hmac(bytea, bytea, text) FROM PUBLIC; REVOKE ALL ON FUNCTION public.hmac(text, text, text) FROM PUBLIC; --- --- Name: FUNCTION id_lookup_get_key(key integer); Type: ACL; Schema: public; Owner: - --- - -REVOKE ALL ON FUNCTION public.id_lookup_get_key(key integer) FROM PUBLIC; - - -- -- Name: FUNCTION id_lookup_get_key(lookup jsonb, key integer); Type: ACL; Schema: public; Owner: - -- @@ -29366,13 +29593,6 @@ REVOKE ALL ON FUNCTION public.search_overlays(lang text, query text, "projectId" GRANT ALL ON FUNCTION public.search_overlays(lang text, query text, "projectId" integer, draft boolean, "limit" integer) TO anon; --- --- Name: FUNCTION search_overlays2(lang text, query text, "projectId" integer, draft boolean, "limit" integer); Type: ACL; Schema: public; Owner: - --- - -REVOKE ALL ON FUNCTION public.search_overlays2(lang text, query text, "projectId" integer, draft boolean, "limit" integer) FROM PUBLIC; - - -- -- Name: COLUMN invite_emails.id; Type: ACL; Schema: public; Owner: - -- diff --git a/packages/client/src/admin/data/QuotaUsageTreemap.tsx b/packages/client/src/admin/data/QuotaUsageTreemap.tsx index 7b30f5e2..5ef383f4 100644 --- a/packages/client/src/admin/data/QuotaUsageTreemap.tsx +++ b/packages/client/src/admin/data/QuotaUsageTreemap.tsx @@ -396,6 +396,8 @@ export function humanizeOutputType(type: DataUploadOutputType | "Archives") { return "Shapefile"; case DataUploadOutputType.Png: return "PNG Image"; + case DataUploadOutputType.NetCdf: + return "NetCDF"; case "Archives": return "Archived Versions"; case DataUploadOutputType.Xmlmetadata: diff --git a/packages/client/src/generated/graphql.ts b/packages/client/src/generated/graphql.ts index 2684fa43..106d7959 100644 --- a/packages/client/src/generated/graphql.ts +++ b/packages/client/src/generated/graphql.ts @@ -2893,6 +2893,7 @@ export enum DataUploadOutputType { FlatGeobuf = 'FLAT_GEOBUF', GeoJson = 'GEO_JSON', GeoTiff = 'GEO_TIFF', + NetCdf = 'NET_CDF', Pmtiles = 'PMTILES', Png = 'PNG', Xmlmetadata = 'XMLMETADATA', diff --git a/packages/client/src/generated/queries.ts b/packages/client/src/generated/queries.ts index c0487311..d647d618 100644 --- a/packages/client/src/generated/queries.ts +++ b/packages/client/src/generated/queries.ts @@ -2891,6 +2891,7 @@ export enum DataUploadOutputType { FlatGeobuf = 'FLAT_GEOBUF', GeoJson = 'GEO_JSON', GeoTiff = 'GEO_TIFF', + NetCdf = 'NET_CDF', Pmtiles = 'PMTILES', Png = 'PNG', Xmlmetadata = 'XMLMETADATA', diff --git a/packages/spatial-uploads-handler/src/handleUpload.ts b/packages/spatial-uploads-handler/src/handleUpload.ts index 15294c36..f0c0502a 100644 --- a/packages/spatial-uploads-handler/src/handleUpload.ts +++ b/packages/spatial-uploads-handler/src/handleUpload.ts @@ -27,7 +27,8 @@ export type SupportedTypes = | "GeoJSON" | "FlatGeobuf" | "ZippedShapefile" - | "GeoTIFF"; + | "GeoTIFF" + | "NetCDF"; export interface ResponseOutput { /** Remote location string as used in rclone */ diff --git a/packages/spatial-uploads-handler/src/processRasterUpload.ts b/packages/spatial-uploads-handler/src/processRasterUpload.ts index cdc21139..dbc0c928 100644 --- a/packages/spatial-uploads-handler/src/processRasterUpload.ts +++ b/packages/spatial-uploads-handler/src/processRasterUpload.ts @@ -90,7 +90,12 @@ export async function processRasterUpload(options: { // Add original file to outputs outputs.push({ - type: ext === ".tif" || ext === ".tiff" ? "GeoTIFF" : "PNG", + type: + ext === ".tif" || ext === ".tiff" + ? "GeoTIFF" + : ext === ".nc" + ? "NetCDF" + : "PNG", remote: `${process.env.RESOURCES_REMOTE}/${baseKey}/${jobId}${ext}`, local: path, size: statSync(path).size,