fix: stop use int key in local
This commit is contained in:
@@ -24,7 +24,7 @@ import {
|
|||||||
Geometry,
|
Geometry,
|
||||||
useEditorState,
|
useEditorState,
|
||||||
} from "@/uhm/lib/editor/state/useEditorState";
|
} from "@/uhm/lib/editor/state/useEditorState";
|
||||||
import { GEO_TYPE_KEYS, geoTypeCodeToTypeKey } from "@/uhm/lib/map/geo/geoTypeMap";
|
import { GEO_TYPE_KEYS } from "@/uhm/lib/map/geo/geoTypeMap";
|
||||||
import {
|
import {
|
||||||
BackgroundLayerId,
|
BackgroundLayerId,
|
||||||
BackgroundLayerVisibility,
|
BackgroundLayerVisibility,
|
||||||
@@ -1080,7 +1080,7 @@ export default function Page() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const bindingIds = normalizeGeoSearchBindingIds(geo.binding);
|
const bindingIds = normalizeGeoSearchBindingIds(geo.binding);
|
||||||
const typeKey = geoTypeCodeToTypeKey(Number(geo.geo_type)) || null;
|
const typeKey = geo.type || null;
|
||||||
|
|
||||||
const feature: Feature = {
|
const feature: Feature = {
|
||||||
type: "Feature",
|
type: "Feature",
|
||||||
@@ -1537,7 +1537,7 @@ export default function Page() {
|
|||||||
#{geo.id}
|
#{geo.id}
|
||||||
</div>
|
</div>
|
||||||
<div style={{ color: "#94a3b8", fontSize: 11 }}>
|
<div style={{ color: "#94a3b8", fontSize: 11 }}>
|
||||||
type: {String(geo.geo_type)}{" "}
|
type: {geo.type || "unknown"}{" "}
|
||||||
{geo.time_start != null || geo.time_end != null
|
{geo.time_start != null || geo.time_end != null
|
||||||
? `| time: ${geo.time_start ?? "?"} → ${geo.time_end ?? "?"}`
|
? `| time: ${geo.time_start ?? "?"} → ${geo.time_end ?? "?"}`
|
||||||
: ""}
|
: ""}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ export type { GeometriesBBoxQuery } from "@/uhm/types/api";
|
|||||||
|
|
||||||
export type EntityGeometrySearchGeo = {
|
export type EntityGeometrySearchGeo = {
|
||||||
id: string;
|
id: string;
|
||||||
geo_type: number;
|
type: string | null;
|
||||||
draw_geometry: unknown;
|
draw_geometry: unknown;
|
||||||
binding?: unknown;
|
binding?: unknown;
|
||||||
time_start?: number | null;
|
time_start?: number | null;
|
||||||
@@ -27,6 +27,18 @@ export type SearchGeometriesByEntityNameResponse = {
|
|||||||
next_cursor?: string;
|
next_cursor?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type EntityGeometrySearchGeoRow = Omit<EntityGeometrySearchGeo, "type"> & {
|
||||||
|
geo_type: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
type EntityGeometriesSearchItemRow = Omit<EntityGeometriesSearchItem, "geometries"> & {
|
||||||
|
geometries: EntityGeometrySearchGeoRow[];
|
||||||
|
};
|
||||||
|
|
||||||
|
type SearchGeometriesByEntityNameApiResponse = Omit<SearchGeometriesByEntityNameResponse, "items"> & {
|
||||||
|
items: EntityGeometriesSearchItemRow[];
|
||||||
|
};
|
||||||
|
|
||||||
function buildBBoxQueryString(params: GeometriesBBoxQuery): string {
|
function buildBBoxQueryString(params: GeometriesBBoxQuery): string {
|
||||||
const query = new URLSearchParams({
|
const query = new URLSearchParams({
|
||||||
// API mới dùng snake_case
|
// API mới dùng snake_case
|
||||||
@@ -71,7 +83,24 @@ export async function searchGeometriesByEntityName(
|
|||||||
params.set("limit", String(Math.trunc(options.limit)));
|
params.set("limit", String(Math.trunc(options.limit)));
|
||||||
}
|
}
|
||||||
|
|
||||||
return requestJson<SearchGeometriesByEntityNameResponse>(`${API_ENDPOINTS.geometries}/entity?${params.toString()}`);
|
const response = await requestJson<SearchGeometriesByEntityNameApiResponse>(
|
||||||
|
`${API_ENDPOINTS.geometries}/entity?${params.toString()}`
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
...response,
|
||||||
|
items: (response.items || []).map((item) => ({
|
||||||
|
...item,
|
||||||
|
geometries: (item.geometries || []).map((geometry) => ({
|
||||||
|
id: geometry.id,
|
||||||
|
type: geoTypeCodeToTypeKey(geometry.geo_type) || null,
|
||||||
|
draw_geometry: geometry.draw_geometry,
|
||||||
|
binding: geometry.binding,
|
||||||
|
time_start: geometry.time_start ?? null,
|
||||||
|
time_end: geometry.time_end ?? null,
|
||||||
|
})),
|
||||||
|
})),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
type GeometryRow = {
|
type GeometryRow = {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { API_BASE_URL, API_ENDPOINTS } from "@/uhm/api/config";
|
import { API_BASE_URL, API_ENDPOINTS } from "@/uhm/api/config";
|
||||||
import { ApiError, jsonRequestInit, requestJson } from "@/uhm/api/http";
|
import { ApiError, jsonRequestInit, requestJson } from "@/uhm/api/http";
|
||||||
|
import { toApiEditorSnapshot } from "@/uhm/lib/editor/snapshot/editorSnapshot";
|
||||||
import type {
|
import type {
|
||||||
CreateCommitInput,
|
CreateCommitInput,
|
||||||
CreateProjectInput,
|
CreateProjectInput,
|
||||||
@@ -76,10 +77,11 @@ export async function createProjectCommit(
|
|||||||
input: CreateCommitInput
|
input: CreateCommitInput
|
||||||
): Promise<{ commit: ProjectCommit; state: ProjectState }> {
|
): Promise<{ commit: ProjectCommit; state: ProjectState }> {
|
||||||
// POST /projects/{id}/commits
|
// POST /projects/{id}/commits
|
||||||
|
const snapshot = toApiEditorSnapshot(input.snapshot);
|
||||||
const commit = await requestJson<ProjectCommit>(
|
const commit = await requestJson<ProjectCommit>(
|
||||||
`${API_ENDPOINTS.projects}/${encodeURIComponent(projectId)}/commits`,
|
`${API_ENDPOINTS.projects}/${encodeURIComponent(projectId)}/commits`,
|
||||||
jsonRequestInit("POST", {
|
jsonRequestInit("POST", {
|
||||||
snapshot_json: input.snapshot,
|
snapshot_json: snapshot,
|
||||||
edit_summary: input.edit_summary,
|
edit_summary: input.edit_summary,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import {
|
|||||||
findGeometryTypeOption,
|
findGeometryTypeOption,
|
||||||
groupGeometryTypeOptions,
|
groupGeometryTypeOptions,
|
||||||
} from "@/uhm/lib/map/geo/geometryTypeOptions";
|
} from "@/uhm/lib/map/geo/geometryTypeOptions";
|
||||||
|
import { normalizeGeoTypeKey } from "@/uhm/lib/map/geo/geoTypeMap";
|
||||||
import type { GeometryMetaFormState } from "@/uhm/lib/editor/session/sessionTypes";
|
import type { GeometryMetaFormState } from "@/uhm/lib/editor/session/sessionTypes";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@@ -288,9 +289,7 @@ function normalizeGeometryPreset(value: unknown): GeometryPreset | null {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function normalizeTypeId(value: unknown): string | null {
|
function normalizeTypeId(value: unknown): string | null {
|
||||||
if (typeof value !== "string") return null;
|
return normalizeGeoTypeKey(value);
|
||||||
const normalized = value.trim().toLowerCase();
|
|
||||||
return normalized.length ? normalized : null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapGeometryTypeToPreset(
|
function mapGeometryTypeToPreset(
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import {
|
|||||||
import { PATH_RENDER_BY_TYPE } from "@/uhm/lib/map/styles/style";
|
import { PATH_RENDER_BY_TYPE } from "@/uhm/lib/map/styles/style";
|
||||||
import { getRasterTileTemplateUrl } from "@/uhm/api/tiles";
|
import { getRasterTileTemplateUrl } from "@/uhm/api/tiles";
|
||||||
import { newId } from "@/uhm/lib/utils/id";
|
import { newId } from "@/uhm/lib/utils/id";
|
||||||
|
import { normalizeGeoTypeKey } from "@/uhm/lib/map/geo/geoTypeMap";
|
||||||
|
|
||||||
type Coordinate = [number, number];
|
type Coordinate = [number, number];
|
||||||
type PolygonCoordinates = Coordinate[][];
|
type PolygonCoordinates = Coordinate[][];
|
||||||
@@ -342,18 +343,22 @@ export function collectCoordinatePairs(value: unknown): Array<[number, number]>
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function buildPathArrowFeatureCollection(fc: FeatureCollection): FeatureCollection {
|
export function buildPathArrowFeatureCollection(fc: FeatureCollection): FeatureCollection {
|
||||||
const features = fc.features
|
const features: Feature[] = [];
|
||||||
.map((feature) => {
|
|
||||||
if (!isPathFeature(feature) || feature.geometry.type !== "LineString") return null;
|
for (const feature of fc.features) {
|
||||||
const geometry = buildPathArrowGeometry(feature.geometry.coordinates);
|
if (!isPathFeature(feature)) continue;
|
||||||
if (!geometry) return null;
|
|
||||||
return {
|
const coordinateGroups = getLineCoordinateGroups(feature.geometry);
|
||||||
type: "Feature" as const,
|
for (const coordinates of coordinateGroups) {
|
||||||
|
const geometry = buildPathArrowGeometry(coordinates);
|
||||||
|
if (!geometry) continue;
|
||||||
|
features.push({
|
||||||
|
type: "Feature",
|
||||||
properties: { ...feature.properties },
|
properties: { ...feature.properties },
|
||||||
geometry,
|
geometry,
|
||||||
};
|
});
|
||||||
})
|
}
|
||||||
.filter((feature): feature is Feature => feature !== null);
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
type: "FeatureCollection",
|
type: "FeatureCollection",
|
||||||
@@ -368,9 +373,7 @@ export function isPathFeature(feature: Feature): boolean {
|
|||||||
|
|
||||||
export function getFeatureSemanticType(feature: Feature): string | null {
|
export function getFeatureSemanticType(feature: Feature): string | null {
|
||||||
const value = feature.properties.type || feature.properties.entity_type_id || null;
|
const value = feature.properties.type || feature.properties.entity_type_id || null;
|
||||||
if (!value) return null;
|
return normalizeGeoTypeKey(value);
|
||||||
const normalized = String(value).trim().toLowerCase();
|
|
||||||
return normalized.length ? normalized : null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function buildPathArrowGeometry(coords: [number, number][]): Geometry | null {
|
export function buildPathArrowGeometry(coords: [number, number][]): Geometry | null {
|
||||||
@@ -719,6 +722,12 @@ function isLineGeometry(geometry: Geometry): boolean {
|
|||||||
return geometry.type === "LineString" || geometry.type === "MultiLineString";
|
return geometry.type === "LineString" || geometry.type === "MultiLineString";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getLineCoordinateGroups(geometry: Geometry): Coordinate[][] {
|
||||||
|
if (geometry.type === "LineString") return [geometry.coordinates];
|
||||||
|
if (geometry.type === "MultiLineString") return geometry.coordinates;
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
function getPolygonLabelPoint(geometry: Geometry): Coordinate | null {
|
function getPolygonLabelPoint(geometry: Geometry): Coordinate | null {
|
||||||
if (geometry.type === "Polygon") {
|
if (geometry.type === "Polygon") {
|
||||||
return getPolygonLabelCandidate(geometry.coordinates)?.point || null;
|
return getPolygonLabelCandidate(geometry.coordinates)?.point || null;
|
||||||
|
|||||||
@@ -384,7 +384,11 @@ export function setupMapLayers(
|
|||||||
id: "entity-focus-fill",
|
id: "entity-focus-fill",
|
||||||
type: "fill",
|
type: "fill",
|
||||||
source: "entity-focus",
|
source: "entity-focus",
|
||||||
filter: ["==", ["geometry-type"], "Polygon"],
|
filter: [
|
||||||
|
"any",
|
||||||
|
["==", ["geometry-type"], "Polygon"],
|
||||||
|
["==", ["geometry-type"], "MultiPolygon"],
|
||||||
|
],
|
||||||
paint: {
|
paint: {
|
||||||
"fill-color": "#fde047",
|
"fill-color": "#fde047",
|
||||||
"fill-opacity": 0.2,
|
"fill-opacity": 0.2,
|
||||||
@@ -413,7 +417,11 @@ export function setupMapLayers(
|
|||||||
id: "entity-focus-points",
|
id: "entity-focus-points",
|
||||||
type: "circle",
|
type: "circle",
|
||||||
source: "entity-focus",
|
source: "entity-focus",
|
||||||
filter: ["==", ["geometry-type"], "Point"],
|
filter: [
|
||||||
|
"any",
|
||||||
|
["==", ["geometry-type"], "Point"],
|
||||||
|
["==", ["geometry-type"], "MultiPoint"],
|
||||||
|
],
|
||||||
paint: {
|
paint: {
|
||||||
"circle-color": "#f8fafc",
|
"circle-color": "#f8fafc",
|
||||||
"circle-radius": 8,
|
"circle-radius": 8,
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import {
|
|||||||
openSectionEditor,
|
openSectionEditor,
|
||||||
submitSection,
|
submitSection,
|
||||||
} from "@/uhm/api/projects";
|
} from "@/uhm/api/projects";
|
||||||
import { buildEditorSnapshot, normalizeEditorSnapshot } from "@/uhm/lib/editor/snapshot/editorSnapshot";
|
import { buildEditorSnapshot, normalizeEditorSnapshot, toApiEditorSnapshot } from "@/uhm/lib/editor/snapshot/editorSnapshot";
|
||||||
import type { Change } from "@/uhm/lib/editor/draft/editorTypes";
|
import type { Change } from "@/uhm/lib/editor/draft/editorTypes";
|
||||||
import type { Feature, FeatureCollection, FeatureId, GeometryEntitySnapshot, GeometrySnapshot } from "@/uhm/types/geo";
|
import type { Feature, FeatureCollection, FeatureId, GeometryEntitySnapshot, GeometrySnapshot } from "@/uhm/types/geo";
|
||||||
import type { EditorSnapshot, Project, ProjectCommit, ProjectState, EntityWikiLinkSnapshot } from "@/uhm/types/projects";
|
import type { EditorSnapshot, Project, ProjectCommit, ProjectState, EntityWikiLinkSnapshot } from "@/uhm/types/projects";
|
||||||
@@ -110,7 +110,7 @@ export function useProjectCommands(options: Options) {
|
|||||||
// Guardrail: commit payload can get large and some deployments reject/close connections for big bodies.
|
// Guardrail: commit payload can get large and some deployments reject/close connections for big bodies.
|
||||||
// When that happens, browsers often surface it as "TypeError: Failed to fetch".
|
// When that happens, browsers often surface it as "TypeError: Failed to fetch".
|
||||||
try {
|
try {
|
||||||
const payloadText = JSON.stringify({ snapshot_json: snapshot, edit_summary: editSummary });
|
const payloadText = JSON.stringify({ snapshot_json: toApiEditorSnapshot(snapshot), edit_summary: editSummary });
|
||||||
const bytes = typeof Blob !== "undefined" ? new Blob([payloadText]).size : payloadText.length;
|
const bytes = typeof Blob !== "undefined" ? new Blob([payloadText]).size : payloadText.length;
|
||||||
const limitBytes = 3_500_000; // ~3.5MB (conservative vs common default body limits)
|
const limitBytes = 3_500_000; // ~3.5MB (conservative vs common default body limits)
|
||||||
if (bytes > limitBytes) {
|
if (bytes > limitBytes) {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { DEFAULT_GEOMETRY_TYPE_ID } from "@/uhm/lib/map/geo/geometryTypeOptions";
|
import { DEFAULT_GEOMETRY_TYPE_ID } from "@/uhm/lib/map/geo/geometryTypeOptions";
|
||||||
import { geoTypeCodeToTypeKey, typeKeyToGeoTypeCode } from "@/uhm/lib/map/geo/geoTypeMap";
|
import { normalizeGeoTypeKey, typeKeyToGeoTypeCode } from "@/uhm/lib/map/geo/geoTypeMap";
|
||||||
import type { Change } from "@/uhm/lib/editor/draft/editorTypes";
|
import type { Change } from "@/uhm/lib/editor/draft/editorTypes";
|
||||||
import type { EntitySnapshot } from "@/uhm/types/entities";
|
import type { EntitySnapshot } from "@/uhm/types/entities";
|
||||||
import type { EntitySnapshotOperation } from "@/uhm/types/entities";
|
import type { EntitySnapshotOperation } from "@/uhm/types/entities";
|
||||||
@@ -86,12 +86,15 @@ export function normalizeEditorSnapshot(raw: unknown): EditorSnapshot | null {
|
|||||||
const source: "inline" | "ref" = existingSource || (refId || !hasInlineGeometry ? "ref" : "inline");
|
const source: "inline" | "ref" = existingSource || (refId || !hasInlineGeometry ? "ref" : "inline");
|
||||||
const rest: UnknownRecord = { ...g };
|
const rest: UnknownRecord = { ...g };
|
||||||
delete rest.ref;
|
delete rest.ref;
|
||||||
|
const typeKey = normalizeGeoTypeKey(rest.type) || normalizeGeoTypeKey(rest.geo_type);
|
||||||
|
delete rest.geo_type;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...(rest as unknown as Omit<GeometrySnapshot, "id" | "source" | "operation">),
|
...(rest as unknown as Omit<GeometrySnapshot, "id" | "source" | "operation">),
|
||||||
id,
|
id,
|
||||||
source,
|
source,
|
||||||
operation,
|
operation,
|
||||||
|
type: typeKey,
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
: undefined;
|
: undefined;
|
||||||
@@ -210,30 +213,39 @@ export function normalizeEditorSnapshot(raw: unknown): EditorSnapshot | null {
|
|||||||
for (const feature of cloned.features) {
|
for (const feature of cloned.features) {
|
||||||
const gid = String(feature.properties.id);
|
const gid = String(feature.properties.id);
|
||||||
const entity_ids = byGeom.get(gid) || [];
|
const entity_ids = byGeom.get(gid) || [];
|
||||||
|
const p = feature.properties as unknown as UnknownRecord;
|
||||||
|
|
||||||
|
const existingTypeKey = normalizeGeoTypeKey(p.type) || normalizeGeoTypeKey(p.entity_type_id);
|
||||||
|
const fallbackTypeKey = getDefaultTypeIdForFeature(feature);
|
||||||
|
if (existingTypeKey) p.type = existingTypeKey;
|
||||||
|
|
||||||
if (entity_ids.length || hasLinks) {
|
if (entity_ids.length || hasLinks) {
|
||||||
const props = feature.properties as unknown as UnknownRecord;
|
p.entity_ids = entity_ids;
|
||||||
props.entity_ids = entity_ids;
|
p.entity_id = entity_ids[0] || null;
|
||||||
props.entity_id = entity_ids[0] || null;
|
|
||||||
|
|
||||||
// Generate denormalized names for UI/map usage.
|
// Generate denormalized names for UI/map usage.
|
||||||
const primaryId = entity_ids[0] || null;
|
const primaryId = entity_ids[0] || null;
|
||||||
const primaryName = primaryId ? (entityNameById.get(primaryId) || "") : "";
|
const primaryName = primaryId ? (entityNameById.get(primaryId) || "") : "";
|
||||||
const names = entity_ids.map((id) => entityNameById.get(id) || "").filter((n) => n.length > 0);
|
const names = entity_ids.map((id) => entityNameById.get(id) || "").filter((n) => n.length > 0);
|
||||||
props.entity_name = primaryName || null;
|
p.entity_name = primaryName || null;
|
||||||
props.entity_names = names;
|
p.entity_names = names;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate geometry metadata onto feature properties (optional in persisted snapshot).
|
// Generate geometry metadata onto feature properties (optional in persisted snapshot).
|
||||||
const geo = geometryById.get(gid) || null;
|
const geo = geometryById.get(gid) || null;
|
||||||
if (geo) {
|
if (geo) {
|
||||||
const p = feature.properties as unknown as UnknownRecord;
|
const geoRecord = geo as unknown as UnknownRecord;
|
||||||
// type (semantic key) is derived from geometries[].type (numeric code in string form).
|
// type can arrive as numeric geo_type, numeric string, or semantic key depending on backend version.
|
||||||
const typeCode = typeof geo.type === "string" && geo.type.trim().length ? Number(geo.type) : NaN;
|
const typeKey = normalizeGeoTypeKey(geoRecord.type)
|
||||||
const typeKey = geoTypeCodeToTypeKey(Number.isFinite(typeCode) ? typeCode : null);
|
|| normalizeGeoTypeKey(geoRecord.geo_type)
|
||||||
|
|| existingTypeKey
|
||||||
|
|| fallbackTypeKey;
|
||||||
if (typeKey) p.type = typeKey;
|
if (typeKey) p.type = typeKey;
|
||||||
if (Array.isArray(geo.binding) && geo.binding.length) p.binding = geo.binding;
|
if (Array.isArray(geo.binding) && geo.binding.length) p.binding = geo.binding;
|
||||||
if (typeof geo.time_start === "number") p.time_start = geo.time_start;
|
if (typeof geo.time_start === "number") p.time_start = geo.time_start;
|
||||||
if (typeof geo.time_end === "number") p.time_end = geo.time_end;
|
if (typeof geo.time_end === "number") p.time_end = geo.time_end;
|
||||||
|
} else if (!existingTypeKey) {
|
||||||
|
p.type = fallbackTypeKey;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return cloned;
|
return cloned;
|
||||||
@@ -375,14 +387,12 @@ export function buildEditorSnapshot(options: {
|
|||||||
? "update"
|
? "update"
|
||||||
: "reference";
|
: "reference";
|
||||||
const bbox = getFeatureBBox(feature);
|
const bbox = getFeatureBBox(feature);
|
||||||
const typeKey = feature.properties.type || getDefaultTypeIdForFeature(feature);
|
const typeKey = normalizeGeoTypeKey(feature.properties.type) || getDefaultTypeIdForFeature(feature);
|
||||||
const typeCode = typeKeyToGeoTypeCode(typeKey);
|
|
||||||
return {
|
return {
|
||||||
id,
|
id,
|
||||||
operation,
|
operation,
|
||||||
source: "inline",
|
source: "inline",
|
||||||
// BE currently expects geometries[].type as a string. We send the geo_type SMALLINT code as a string.
|
type: typeKey,
|
||||||
type: String(typeCode ?? 0),
|
|
||||||
draw_geometry: feature.geometry,
|
draw_geometry: feature.geometry,
|
||||||
binding: normalizeFeatureBindingIds(feature),
|
binding: normalizeFeatureBindingIds(feature),
|
||||||
time_start: feature.properties.time_start ?? null,
|
time_start: feature.properties.time_start ?? null,
|
||||||
@@ -600,6 +610,29 @@ export function buildEditorSnapshot(options: {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function toApiEditorSnapshot(snapshot: EditorSnapshot): EditorSnapshot {
|
||||||
|
const cloned = JSON.parse(JSON.stringify(snapshot)) as EditorSnapshot;
|
||||||
|
|
||||||
|
if (Array.isArray(cloned.geometries)) {
|
||||||
|
cloned.geometries = cloned.geometries.map((geometry) => {
|
||||||
|
const row = { ...(geometry as unknown as UnknownRecord) };
|
||||||
|
const typeKey = normalizeGeoTypeKey(row.type) || normalizeGeoTypeKey(row.geo_type);
|
||||||
|
delete row.geo_type;
|
||||||
|
|
||||||
|
if (typeKey) {
|
||||||
|
const typeCode = typeKeyToGeoTypeCode(typeKey);
|
||||||
|
row.type = typeCode == null ? null : String(typeCode);
|
||||||
|
} else if ("type" in row) {
|
||||||
|
row.type = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return row as unknown as GeometrySnapshot;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return cloned;
|
||||||
|
}
|
||||||
|
|
||||||
function dedupeAndSortGeometryEntity(rows: GeometryEntitySnapshot[]): GeometryEntitySnapshot[] {
|
function dedupeAndSortGeometryEntity(rows: GeometryEntitySnapshot[]): GeometryEntitySnapshot[] {
|
||||||
const seen = new Set<string>();
|
const seen = new Set<string>();
|
||||||
const deduped: GeometryEntitySnapshot[] = [];
|
const deduped: GeometryEntitySnapshot[] = [];
|
||||||
|
|||||||
@@ -39,3 +39,20 @@ export function geoTypeCodeToTypeKey(code: number | null | undefined): string |
|
|||||||
if (!Number.isFinite(code)) return null;
|
if (!Number.isFinite(code)) return null;
|
||||||
return KEY_BY_CODE.get(Math.trunc(code)) ?? null;
|
return KEY_BY_CODE.get(Math.trunc(code)) ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function normalizeGeoTypeKey(value: unknown): string | null {
|
||||||
|
if (typeof value === "number") {
|
||||||
|
return geoTypeCodeToTypeKey(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof value !== "string") return null;
|
||||||
|
|
||||||
|
const normalized = value.trim().toLowerCase();
|
||||||
|
if (!normalized.length) return null;
|
||||||
|
|
||||||
|
if (/^-?\d+$/.test(normalized)) {
|
||||||
|
return geoTypeCodeToTypeKey(Number(normalized));
|
||||||
|
}
|
||||||
|
|
||||||
|
return normalized;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,68 +1,13 @@
|
|||||||
import { LayerSpecification } from "maplibre-gl";
|
import { LayerSpecification } from "maplibre-gl";
|
||||||
import { TYPE_MATCH_EXPR } from "./index";
|
import { buildLineGeotypeLayers } from "./styleBuilders";
|
||||||
|
|
||||||
export function getAttackRouteLayers(sourceId: string, pathArrowSourceId?: string, pointSourceId?: string): LayerSpecification[] {
|
export function getAttackRouteLayers(sourceId: string, pathArrowSourceId?: string, pointSourceId?: string): LayerSpecification[] {
|
||||||
return [
|
void pointSourceId;
|
||||||
{
|
return buildLineGeotypeLayers(sourceId, pathArrowSourceId, {
|
||||||
id: "attack_route-line",
|
typeId: "attack_route",
|
||||||
type: "line",
|
color: "#ef4444",
|
||||||
source: sourceId,
|
strokeColor: "#7f1d1d",
|
||||||
filter: ["all", ["==", ["geometry-type"], "LineString"], ["==", TYPE_MATCH_EXPR, "attack_route"]],
|
width: { z1: 2.6, z4: 3.8, z6: 5 },
|
||||||
paint: {
|
arrowOpacity: 0.9,
|
||||||
"line-color": [
|
});
|
||||||
"case",
|
|
||||||
["boolean", ["feature-state", "selected"], false], "#22c55e",
|
|
||||||
["==", ["coalesce", ["get", "entity_id"], ""], ""], "#ef4444",
|
|
||||||
"#ef4444"
|
|
||||||
],
|
|
||||||
"line-width": ["interpolate", ["linear"], ["zoom"], 1, 2.2, 4, 3.2, 6, 4.2],
|
|
||||||
"line-opacity": 0.9
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "attack_route-hit",
|
|
||||||
type: "line",
|
|
||||||
source: sourceId,
|
|
||||||
filter: ["all", ["==", ["geometry-type"], "LineString"], ["==", TYPE_MATCH_EXPR, "attack_route"]],
|
|
||||||
paint: {
|
|
||||||
"line-color": "#ffffff",
|
|
||||||
"line-width": ["interpolate", ["linear"], ["zoom"], 1, 12, 4, 18, 6, 24],
|
|
||||||
"line-opacity": 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "attack_route-path-arrow-fill",
|
|
||||||
type: "fill",
|
|
||||||
source: pathArrowSourceId!,
|
|
||||||
filter: ["==", TYPE_MATCH_EXPR, "attack_route"],
|
|
||||||
paint: {
|
|
||||||
"fill-color": [
|
|
||||||
"case",
|
|
||||||
["boolean", ["feature-state", "selected"], false], "#22c55e",
|
|
||||||
["==", ["coalesce", ["get", "entity_id"], ""], ""], "#ef4444",
|
|
||||||
"#ef4444"
|
|
||||||
],
|
|
||||||
"fill-opacity": [
|
|
||||||
"case",
|
|
||||||
["boolean", ["feature-state", "selected"], false], 0.92,
|
|
||||||
0.82
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "attack_route-path-arrow-line",
|
|
||||||
type: "line",
|
|
||||||
source: pathArrowSourceId!,
|
|
||||||
filter: ["==", TYPE_MATCH_EXPR, "attack_route"],
|
|
||||||
paint: {
|
|
||||||
"line-color": [
|
|
||||||
"case",
|
|
||||||
["boolean", ["feature-state", "selected"], false], "#14532d",
|
|
||||||
"#0f172a"
|
|
||||||
],
|
|
||||||
"line-width": ["interpolate", ["linear"], ["zoom"], 1, 0.45, 4, 0.8, 6, 1.2],
|
|
||||||
"line-opacity": 0.9
|
|
||||||
}
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,40 +1,14 @@
|
|||||||
import { LayerSpecification } from "maplibre-gl";
|
import { LayerSpecification } from "maplibre-gl";
|
||||||
import { TYPE_MATCH_EXPR } from "./index";
|
import { buildPolygonGeotypeLayers } from "./styleBuilders";
|
||||||
|
|
||||||
export function getBattleLayers(sourceId: string, pathArrowSourceId?: string, pointSourceId?: string): LayerSpecification[] {
|
export function getBattleLayers(sourceId: string, pathArrowSourceId?: string, pointSourceId?: string): LayerSpecification[] {
|
||||||
return [
|
void pathArrowSourceId;
|
||||||
{
|
void pointSourceId;
|
||||||
id: "battle-fill",
|
return buildPolygonGeotypeLayers(sourceId, {
|
||||||
type: "fill",
|
typeId: "battle",
|
||||||
source: sourceId,
|
fillColor: "#f43f5e",
|
||||||
filter: ["all", ["==", ["geometry-type"], "Polygon"], ["==", TYPE_MATCH_EXPR, "battle"]],
|
strokeColor: "#9f1239",
|
||||||
paint: {
|
fillOpacity: 0.3,
|
||||||
"fill-color": [
|
strokeWidth: { z1: 1.5, z4: 2.2, z6: 3 },
|
||||||
"case",
|
});
|
||||||
["boolean", ["feature-state", "selected"], false], "#22c55e",
|
|
||||||
["==", ["coalesce", ["get", "entity_id"], ""], ""], "#ef4444",
|
|
||||||
"#f43f5e"
|
|
||||||
],
|
|
||||||
"fill-opacity": [
|
|
||||||
"case",
|
|
||||||
["boolean", ["feature-state", "selected"], false], 0.6,
|
|
||||||
0.34
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "battle-line",
|
|
||||||
type: "line",
|
|
||||||
source: sourceId,
|
|
||||||
filter: ["all", ["==", ["geometry-type"], "Polygon"], ["==", TYPE_MATCH_EXPR, "battle"]],
|
|
||||||
paint: {
|
|
||||||
"line-color": [
|
|
||||||
"case",
|
|
||||||
["boolean", ["feature-state", "selected"], false], "#14532d",
|
|
||||||
"#9f1239"
|
|
||||||
],
|
|
||||||
"line-width": 2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,40 +1,13 @@
|
|||||||
import { LayerSpecification } from "maplibre-gl";
|
import { LayerSpecification } from "maplibre-gl";
|
||||||
import { TYPE_MATCH_EXPR } from "./index";
|
import { buildPolygonGeotypeLayers } from "./styleBuilders";
|
||||||
|
|
||||||
export function getCivilizationLayers(sourceId: string, pathArrowSourceId?: string, pointSourceId?: string): LayerSpecification[] {
|
export function getCivilizationLayers(sourceId: string, pathArrowSourceId?: string, pointSourceId?: string): LayerSpecification[] {
|
||||||
return [
|
void pathArrowSourceId;
|
||||||
{
|
void pointSourceId;
|
||||||
id: "civilization-fill",
|
return buildPolygonGeotypeLayers(sourceId, {
|
||||||
type: "fill",
|
typeId: "civilization",
|
||||||
source: sourceId,
|
fillColor: "#14b8a6",
|
||||||
filter: ["all", ["==", ["geometry-type"], "Polygon"], ["==", TYPE_MATCH_EXPR, "civilization"]],
|
strokeColor: "#134e4a",
|
||||||
paint: {
|
fillOpacity: 0.34,
|
||||||
"fill-color": [
|
});
|
||||||
"case",
|
|
||||||
["boolean", ["feature-state", "selected"], false], "#22c55e",
|
|
||||||
["==", ["coalesce", ["get", "entity_id"], ""], ""], "#ef4444",
|
|
||||||
"#14b8a6"
|
|
||||||
],
|
|
||||||
"fill-opacity": [
|
|
||||||
"case",
|
|
||||||
["boolean", ["feature-state", "selected"], false], 0.6,
|
|
||||||
0.38
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "civilization-line",
|
|
||||||
type: "line",
|
|
||||||
source: sourceId,
|
|
||||||
filter: ["all", ["==", ["geometry-type"], "Polygon"], ["==", TYPE_MATCH_EXPR, "civilization"]],
|
|
||||||
paint: {
|
|
||||||
"line-color": [
|
|
||||||
"case",
|
|
||||||
["boolean", ["feature-state", "selected"], false], "#14532d",
|
|
||||||
"#134e4a"
|
|
||||||
],
|
|
||||||
"line-width": 2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,40 +1,13 @@
|
|||||||
import { LayerSpecification } from "maplibre-gl";
|
import { LayerSpecification } from "maplibre-gl";
|
||||||
import { TYPE_MATCH_EXPR } from "./index";
|
import { buildPolygonGeotypeLayers } from "./styleBuilders";
|
||||||
|
|
||||||
export function getCountryLayers(sourceId: string, pathArrowSourceId?: string, pointSourceId?: string): LayerSpecification[] {
|
export function getCountryLayers(sourceId: string, pathArrowSourceId?: string, pointSourceId?: string): LayerSpecification[] {
|
||||||
return [
|
void pathArrowSourceId;
|
||||||
{
|
void pointSourceId;
|
||||||
id: "country-fill",
|
return buildPolygonGeotypeLayers(sourceId, {
|
||||||
type: "fill",
|
typeId: "country",
|
||||||
source: sourceId,
|
fillColor: "#2563eb",
|
||||||
filter: ["all", ["==", ["geometry-type"], "Polygon"], ["==", TYPE_MATCH_EXPR, "country"]],
|
strokeColor: "#1e40af",
|
||||||
paint: {
|
fillOpacity: 0.34,
|
||||||
"fill-color": [
|
});
|
||||||
"case",
|
|
||||||
["boolean", ["feature-state", "selected"], false], "#22c55e",
|
|
||||||
["==", ["coalesce", ["get", "entity_id"], ""], ""], "#ef4444",
|
|
||||||
"#2563eb"
|
|
||||||
],
|
|
||||||
"fill-opacity": [
|
|
||||||
"case",
|
|
||||||
["boolean", ["feature-state", "selected"], false], 0.6,
|
|
||||||
0.5
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "country-line",
|
|
||||||
type: "line",
|
|
||||||
source: sourceId,
|
|
||||||
filter: ["all", ["==", ["geometry-type"], "Polygon"], ["==", TYPE_MATCH_EXPR, "country"]],
|
|
||||||
paint: {
|
|
||||||
"line-color": [
|
|
||||||
"case",
|
|
||||||
["boolean", ["feature-state", "selected"], false], "#14532d",
|
|
||||||
"#1e3a8a"
|
|
||||||
],
|
|
||||||
"line-width": 2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,35 +1,13 @@
|
|||||||
import { LayerSpecification } from "maplibre-gl";
|
import { LayerSpecification } from "maplibre-gl";
|
||||||
import { TYPE_MATCH_EXPR } from "./index";
|
import { buildLineGeotypeLayers } from "./styleBuilders";
|
||||||
|
|
||||||
export function getDefenseLineLayers(sourceId: string, pathArrowSourceId?: string, pointSourceId?: string): LayerSpecification[] {
|
export function getDefenseLineLayers(sourceId: string, pathArrowSourceId?: string, pointSourceId?: string): LayerSpecification[] {
|
||||||
return [
|
void pointSourceId;
|
||||||
{
|
return buildLineGeotypeLayers(sourceId, pathArrowSourceId, {
|
||||||
id: "defense_line-line",
|
typeId: "defense_line",
|
||||||
type: "line",
|
color: "#38bdf8",
|
||||||
source: sourceId,
|
strokeColor: "#075985",
|
||||||
filter: ["all", ["==", ["geometry-type"], "LineString"], ["==", TYPE_MATCH_EXPR, "defense_line"]],
|
dasharray: [3, 2],
|
||||||
paint: {
|
arrow: false,
|
||||||
"line-color": [
|
});
|
||||||
"case",
|
|
||||||
["boolean", ["feature-state", "selected"], false], "#22c55e",
|
|
||||||
["==", ["coalesce", ["get", "entity_id"], ""], ""], "#ef4444",
|
|
||||||
"#f97316"
|
|
||||||
],
|
|
||||||
"line-width": ["interpolate", ["linear"], ["zoom"], 1, 2.2, 4, 3.2, 6, 4.2],
|
|
||||||
"line-dasharray": [3, 2],
|
|
||||||
"line-opacity": 0.9
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "defense_line-hit",
|
|
||||||
type: "line",
|
|
||||||
source: sourceId,
|
|
||||||
filter: ["all", ["==", ["geometry-type"], "LineString"], ["==", TYPE_MATCH_EXPR, "defense_line"]],
|
|
||||||
paint: {
|
|
||||||
"line-color": "#ffffff",
|
|
||||||
"line-width": ["interpolate", ["linear"], ["zoom"], 1, 12, 4, 18, 6, 24],
|
|
||||||
"line-opacity": 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,40 +1,14 @@
|
|||||||
import { LayerSpecification } from "maplibre-gl";
|
import { LayerSpecification } from "maplibre-gl";
|
||||||
import { TYPE_MATCH_EXPR } from "./index";
|
import { buildPolygonGeotypeLayers } from "./styleBuilders";
|
||||||
|
|
||||||
export function getEmpireLayers(sourceId: string, pathArrowSourceId?: string, pointSourceId?: string): LayerSpecification[] {
|
export function getEmpireLayers(sourceId: string, pathArrowSourceId?: string, pointSourceId?: string): LayerSpecification[] {
|
||||||
return [
|
void pathArrowSourceId;
|
||||||
{
|
void pointSourceId;
|
||||||
id: "empire-fill",
|
return buildPolygonGeotypeLayers(sourceId, {
|
||||||
type: "fill",
|
typeId: "empire",
|
||||||
source: sourceId,
|
fillColor: "#f59e0b",
|
||||||
filter: ["all", ["==", ["geometry-type"], "Polygon"], ["==", TYPE_MATCH_EXPR, "empire"]],
|
strokeColor: "#92400e",
|
||||||
paint: {
|
fillOpacity: 0.36,
|
||||||
"fill-color": [
|
strokeWidth: { z1: 1.8, z4: 2.6, z6: 3.4 },
|
||||||
"case",
|
});
|
||||||
["boolean", ["feature-state", "selected"], false], "#22c55e",
|
|
||||||
["==", ["coalesce", ["get", "entity_id"], ""], ""], "#ef4444",
|
|
||||||
"#f59e0b"
|
|
||||||
],
|
|
||||||
"fill-opacity": [
|
|
||||||
"case",
|
|
||||||
["boolean", ["feature-state", "selected"], false], 0.6,
|
|
||||||
0.5
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "empire-line",
|
|
||||||
type: "line",
|
|
||||||
source: sourceId,
|
|
||||||
filter: ["all", ["==", ["geometry-type"], "Polygon"], ["==", TYPE_MATCH_EXPR, "empire"]],
|
|
||||||
paint: {
|
|
||||||
"line-color": [
|
|
||||||
"case",
|
|
||||||
["boolean", ["feature-state", "selected"], false], "#14532d",
|
|
||||||
"#7c2d12"
|
|
||||||
],
|
|
||||||
"line-width": 2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,68 +1,13 @@
|
|||||||
import { LayerSpecification } from "maplibre-gl";
|
import { LayerSpecification } from "maplibre-gl";
|
||||||
import { TYPE_MATCH_EXPR } from "./index";
|
import { buildLineGeotypeLayers } from "./styleBuilders";
|
||||||
|
|
||||||
export function getInvasionRouteLayers(sourceId: string, pathArrowSourceId?: string, pointSourceId?: string): LayerSpecification[] {
|
export function getInvasionRouteLayers(sourceId: string, pathArrowSourceId?: string, pointSourceId?: string): LayerSpecification[] {
|
||||||
return [
|
void pointSourceId;
|
||||||
{
|
return buildLineGeotypeLayers(sourceId, pathArrowSourceId, {
|
||||||
id: "invasion_route-line",
|
typeId: "invasion_route",
|
||||||
type: "line",
|
color: "#be123c",
|
||||||
source: sourceId,
|
strokeColor: "#4c0519",
|
||||||
filter: ["all", ["==", ["geometry-type"], "LineString"], ["==", TYPE_MATCH_EXPR, "invasion_route"]],
|
width: { z1: 2.8, z4: 4.1, z6: 5.4 },
|
||||||
paint: {
|
arrowOpacity: 0.9,
|
||||||
"line-color": [
|
});
|
||||||
"case",
|
|
||||||
["boolean", ["feature-state", "selected"], false], "#22c55e",
|
|
||||||
["==", ["coalesce", ["get", "entity_id"], ""], ""], "#ef4444",
|
|
||||||
"#b91c1c"
|
|
||||||
],
|
|
||||||
"line-width": ["interpolate", ["linear"], ["zoom"], 1, 2.2, 4, 3.2, 6, 4.2],
|
|
||||||
"line-opacity": 0.9
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "invasion_route-hit",
|
|
||||||
type: "line",
|
|
||||||
source: sourceId,
|
|
||||||
filter: ["all", ["==", ["geometry-type"], "LineString"], ["==", TYPE_MATCH_EXPR, "invasion_route"]],
|
|
||||||
paint: {
|
|
||||||
"line-color": "#ffffff",
|
|
||||||
"line-width": ["interpolate", ["linear"], ["zoom"], 1, 12, 4, 18, 6, 24],
|
|
||||||
"line-opacity": 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "invasion_route-path-arrow-fill",
|
|
||||||
type: "fill",
|
|
||||||
source: pathArrowSourceId!,
|
|
||||||
filter: ["==", TYPE_MATCH_EXPR, "invasion_route"],
|
|
||||||
paint: {
|
|
||||||
"fill-color": [
|
|
||||||
"case",
|
|
||||||
["boolean", ["feature-state", "selected"], false], "#22c55e",
|
|
||||||
["==", ["coalesce", ["get", "entity_id"], ""], ""], "#ef4444",
|
|
||||||
"#b91c1c"
|
|
||||||
],
|
|
||||||
"fill-opacity": [
|
|
||||||
"case",
|
|
||||||
["boolean", ["feature-state", "selected"], false], 0.92,
|
|
||||||
0.82
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "invasion_route-path-arrow-line",
|
|
||||||
type: "line",
|
|
||||||
source: pathArrowSourceId!,
|
|
||||||
filter: ["==", TYPE_MATCH_EXPR, "invasion_route"],
|
|
||||||
paint: {
|
|
||||||
"line-color": [
|
|
||||||
"case",
|
|
||||||
["boolean", ["feature-state", "selected"], false], "#14532d",
|
|
||||||
"#0f172a"
|
|
||||||
],
|
|
||||||
"line-width": ["interpolate", ["linear"], ["zoom"], 1, 0.45, 4, 0.8, 6, 1.2],
|
|
||||||
"line-opacity": 0.9
|
|
||||||
}
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,40 +1,13 @@
|
|||||||
import { LayerSpecification } from "maplibre-gl";
|
import { LayerSpecification } from "maplibre-gl";
|
||||||
import { TYPE_MATCH_EXPR } from "./index";
|
import { buildPolygonGeotypeLayers } from "./styleBuilders";
|
||||||
|
|
||||||
export function getKingdomLayers(sourceId: string, pathArrowSourceId?: string, pointSourceId?: string): LayerSpecification[] {
|
export function getKingdomLayers(sourceId: string, pathArrowSourceId?: string, pointSourceId?: string): LayerSpecification[] {
|
||||||
return [
|
void pathArrowSourceId;
|
||||||
{
|
void pointSourceId;
|
||||||
id: "kingdom-fill",
|
return buildPolygonGeotypeLayers(sourceId, {
|
||||||
type: "fill",
|
typeId: "kingdom",
|
||||||
source: sourceId,
|
fillColor: "#8b5cf6",
|
||||||
filter: ["all", ["==", ["geometry-type"], "Polygon"], ["==", TYPE_MATCH_EXPR, "kingdom"]],
|
strokeColor: "#6d28d9",
|
||||||
paint: {
|
fillOpacity: 0.34,
|
||||||
"fill-color": [
|
});
|
||||||
"case",
|
|
||||||
["boolean", ["feature-state", "selected"], false], "#22c55e",
|
|
||||||
["==", ["coalesce", ["get", "entity_id"], ""], ""], "#ef4444",
|
|
||||||
"#d97706"
|
|
||||||
],
|
|
||||||
"fill-opacity": [
|
|
||||||
"case",
|
|
||||||
["boolean", ["feature-state", "selected"], false], 0.6,
|
|
||||||
0.5
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "kingdom-line",
|
|
||||||
type: "line",
|
|
||||||
source: sourceId,
|
|
||||||
filter: ["all", ["==", ["geometry-type"], "Polygon"], ["==", TYPE_MATCH_EXPR, "kingdom"]],
|
|
||||||
paint: {
|
|
||||||
"line-color": [
|
|
||||||
"case",
|
|
||||||
["boolean", ["feature-state", "selected"], false], "#14532d",
|
|
||||||
"#9a3412"
|
|
||||||
],
|
|
||||||
"line-width": 2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,68 +1,13 @@
|
|||||||
import { LayerSpecification } from "maplibre-gl";
|
import { LayerSpecification } from "maplibre-gl";
|
||||||
import { TYPE_MATCH_EXPR } from "./index";
|
import { buildLineGeotypeLayers } from "./styleBuilders";
|
||||||
|
|
||||||
export function getMigrationRouteLayers(sourceId: string, pathArrowSourceId?: string, pointSourceId?: string): LayerSpecification[] {
|
export function getMigrationRouteLayers(sourceId: string, pathArrowSourceId?: string, pointSourceId?: string): LayerSpecification[] {
|
||||||
return [
|
void pointSourceId;
|
||||||
{
|
return buildLineGeotypeLayers(sourceId, pathArrowSourceId, {
|
||||||
id: "migration_route-line",
|
typeId: "migration_route",
|
||||||
type: "line",
|
color: "#10b981",
|
||||||
source: sourceId,
|
strokeColor: "#065f46",
|
||||||
filter: ["all", ["==", ["geometry-type"], "LineString"], ["==", TYPE_MATCH_EXPR, "migration_route"]],
|
dasharray: [4, 3],
|
||||||
paint: {
|
arrowOpacity: 0.76,
|
||||||
"line-color": [
|
});
|
||||||
"case",
|
|
||||||
["boolean", ["feature-state", "selected"], false], "#22c55e",
|
|
||||||
["==", ["coalesce", ["get", "entity_id"], ""], ""], "#ef4444",
|
|
||||||
"#0ea5e9"
|
|
||||||
],
|
|
||||||
"line-width": ["interpolate", ["linear"], ["zoom"], 1, 2.2, 4, 3.2, 6, 4.2],
|
|
||||||
"line-opacity": 0.9
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "migration_route-hit",
|
|
||||||
type: "line",
|
|
||||||
source: sourceId,
|
|
||||||
filter: ["all", ["==", ["geometry-type"], "LineString"], ["==", TYPE_MATCH_EXPR, "migration_route"]],
|
|
||||||
paint: {
|
|
||||||
"line-color": "#ffffff",
|
|
||||||
"line-width": ["interpolate", ["linear"], ["zoom"], 1, 12, 4, 18, 6, 24],
|
|
||||||
"line-opacity": 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "migration_route-path-arrow-fill",
|
|
||||||
type: "fill",
|
|
||||||
source: pathArrowSourceId!,
|
|
||||||
filter: ["==", TYPE_MATCH_EXPR, "migration_route"],
|
|
||||||
paint: {
|
|
||||||
"fill-color": [
|
|
||||||
"case",
|
|
||||||
["boolean", ["feature-state", "selected"], false], "#22c55e",
|
|
||||||
["==", ["coalesce", ["get", "entity_id"], ""], ""], "#ef4444",
|
|
||||||
"#0ea5e9"
|
|
||||||
],
|
|
||||||
"fill-opacity": [
|
|
||||||
"case",
|
|
||||||
["boolean", ["feature-state", "selected"], false], 0.92,
|
|
||||||
0.82
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "migration_route-path-arrow-line",
|
|
||||||
type: "line",
|
|
||||||
source: pathArrowSourceId!,
|
|
||||||
filter: ["==", TYPE_MATCH_EXPR, "migration_route"],
|
|
||||||
paint: {
|
|
||||||
"line-color": [
|
|
||||||
"case",
|
|
||||||
["boolean", ["feature-state", "selected"], false], "#14532d",
|
|
||||||
"#0f172a"
|
|
||||||
],
|
|
||||||
"line-width": ["interpolate", ["linear"], ["zoom"], 1, 0.45, 4, 0.8, 6, 1.2],
|
|
||||||
"line-opacity": 0.9
|
|
||||||
}
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,40 +1,14 @@
|
|||||||
import { LayerSpecification } from "maplibre-gl";
|
import { LayerSpecification } from "maplibre-gl";
|
||||||
import { TYPE_MATCH_EXPR } from "./index";
|
import { buildPolygonGeotypeLayers } from "./styleBuilders";
|
||||||
|
|
||||||
export function getRebellionZoneLayers(sourceId: string, pathArrowSourceId?: string, pointSourceId?: string): LayerSpecification[] {
|
export function getRebellionZoneLayers(sourceId: string, pathArrowSourceId?: string, pointSourceId?: string): LayerSpecification[] {
|
||||||
return [
|
void pathArrowSourceId;
|
||||||
{
|
void pointSourceId;
|
||||||
id: "rebellion_zone-fill",
|
return buildPolygonGeotypeLayers(sourceId, {
|
||||||
type: "fill",
|
typeId: "rebellion_zone",
|
||||||
source: sourceId,
|
fillColor: "#a21caf",
|
||||||
filter: ["all", ["==", ["geometry-type"], "Polygon"], ["==", TYPE_MATCH_EXPR, "rebellion_zone"]],
|
strokeColor: "#701a75",
|
||||||
paint: {
|
fillOpacity: 0.26,
|
||||||
"fill-color": [
|
dasharray: [3, 2],
|
||||||
"case",
|
});
|
||||||
["boolean", ["feature-state", "selected"], false], "#22c55e",
|
|
||||||
["==", ["coalesce", ["get", "entity_id"], ""], ""], "#ef4444",
|
|
||||||
"#7c3aed"
|
|
||||||
],
|
|
||||||
"fill-opacity": [
|
|
||||||
"case",
|
|
||||||
["boolean", ["feature-state", "selected"], false], 0.6,
|
|
||||||
0.32
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "rebellion_zone-line",
|
|
||||||
type: "line",
|
|
||||||
source: sourceId,
|
|
||||||
filter: ["all", ["==", ["geometry-type"], "Polygon"], ["==", TYPE_MATCH_EXPR, "rebellion_zone"]],
|
|
||||||
paint: {
|
|
||||||
"line-color": [
|
|
||||||
"case",
|
|
||||||
["boolean", ["feature-state", "selected"], false], "#14532d",
|
|
||||||
"#4c1d95"
|
|
||||||
],
|
|
||||||
"line-width": 2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,68 +1,14 @@
|
|||||||
import { LayerSpecification } from "maplibre-gl";
|
import { LayerSpecification } from "maplibre-gl";
|
||||||
import { TYPE_MATCH_EXPR } from "./index";
|
import { buildLineGeotypeLayers } from "./styleBuilders";
|
||||||
|
|
||||||
export function getRefugeeRouteLayers(sourceId: string, pathArrowSourceId?: string, pointSourceId?: string): LayerSpecification[] {
|
export function getRefugeeRouteLayers(sourceId: string, pathArrowSourceId?: string, pointSourceId?: string): LayerSpecification[] {
|
||||||
return [
|
void pointSourceId;
|
||||||
{
|
return buildLineGeotypeLayers(sourceId, pathArrowSourceId, {
|
||||||
id: "refugee_route-line",
|
typeId: "refugee_route",
|
||||||
type: "line",
|
color: "#f97316",
|
||||||
source: sourceId,
|
strokeColor: "#9a3412",
|
||||||
filter: ["all", ["==", ["geometry-type"], "LineString"], ["==", TYPE_MATCH_EXPR, "refugee_route"]],
|
dasharray: [1, 2],
|
||||||
paint: {
|
opacity: 0.84,
|
||||||
"line-color": [
|
arrowOpacity: 0.72,
|
||||||
"case",
|
});
|
||||||
["boolean", ["feature-state", "selected"], false], "#22c55e",
|
|
||||||
["==", ["coalesce", ["get", "entity_id"], ""], ""], "#ef4444",
|
|
||||||
"#06b6d4"
|
|
||||||
],
|
|
||||||
"line-width": ["interpolate", ["linear"], ["zoom"], 1, 2.2, 4, 3.2, 6, 4.2],
|
|
||||||
"line-opacity": 0.9
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "refugee_route-hit",
|
|
||||||
type: "line",
|
|
||||||
source: sourceId,
|
|
||||||
filter: ["all", ["==", ["geometry-type"], "LineString"], ["==", TYPE_MATCH_EXPR, "refugee_route"]],
|
|
||||||
paint: {
|
|
||||||
"line-color": "#ffffff",
|
|
||||||
"line-width": ["interpolate", ["linear"], ["zoom"], 1, 12, 4, 18, 6, 24],
|
|
||||||
"line-opacity": 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "refugee_route-path-arrow-fill",
|
|
||||||
type: "fill",
|
|
||||||
source: pathArrowSourceId!,
|
|
||||||
filter: ["==", TYPE_MATCH_EXPR, "refugee_route"],
|
|
||||||
paint: {
|
|
||||||
"fill-color": [
|
|
||||||
"case",
|
|
||||||
["boolean", ["feature-state", "selected"], false], "#22c55e",
|
|
||||||
["==", ["coalesce", ["get", "entity_id"], ""], ""], "#ef4444",
|
|
||||||
"#06b6d4"
|
|
||||||
],
|
|
||||||
"fill-opacity": [
|
|
||||||
"case",
|
|
||||||
["boolean", ["feature-state", "selected"], false], 0.92,
|
|
||||||
0.82
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "refugee_route-path-arrow-line",
|
|
||||||
type: "line",
|
|
||||||
source: pathArrowSourceId!,
|
|
||||||
filter: ["==", TYPE_MATCH_EXPR, "refugee_route"],
|
|
||||||
paint: {
|
|
||||||
"line-color": [
|
|
||||||
"case",
|
|
||||||
["boolean", ["feature-state", "selected"], false], "#14532d",
|
|
||||||
"#0f172a"
|
|
||||||
],
|
|
||||||
"line-width": ["interpolate", ["linear"], ["zoom"], 1, 0.45, 4, 0.8, 6, 1.2],
|
|
||||||
"line-opacity": 0.9
|
|
||||||
}
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,68 +1,14 @@
|
|||||||
import { LayerSpecification } from "maplibre-gl";
|
import { LayerSpecification } from "maplibre-gl";
|
||||||
import { TYPE_MATCH_EXPR } from "./index";
|
import { buildLineGeotypeLayers } from "./styleBuilders";
|
||||||
|
|
||||||
export function getRetreatRouteLayers(sourceId: string, pathArrowSourceId?: string, pointSourceId?: string): LayerSpecification[] {
|
export function getRetreatRouteLayers(sourceId: string, pathArrowSourceId?: string, pointSourceId?: string): LayerSpecification[] {
|
||||||
return [
|
void pointSourceId;
|
||||||
{
|
return buildLineGeotypeLayers(sourceId, pathArrowSourceId, {
|
||||||
id: "retreat_route-line",
|
typeId: "retreat_route",
|
||||||
type: "line",
|
color: "#94a3b8",
|
||||||
source: sourceId,
|
strokeColor: "#475569",
|
||||||
filter: ["all", ["==", ["geometry-type"], "LineString"], ["==", TYPE_MATCH_EXPR, "retreat_route"]],
|
dasharray: [6, 3],
|
||||||
paint: {
|
opacity: 0.82,
|
||||||
"line-color": [
|
arrowOpacity: 0.68,
|
||||||
"case",
|
});
|
||||||
["boolean", ["feature-state", "selected"], false], "#22c55e",
|
|
||||||
["==", ["coalesce", ["get", "entity_id"], ""], ""], "#ef4444",
|
|
||||||
"#94a3b8"
|
|
||||||
],
|
|
||||||
"line-width": ["interpolate", ["linear"], ["zoom"], 1, 2.2, 4, 3.2, 6, 4.2],
|
|
||||||
"line-opacity": 0.9
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "retreat_route-hit",
|
|
||||||
type: "line",
|
|
||||||
source: sourceId,
|
|
||||||
filter: ["all", ["==", ["geometry-type"], "LineString"], ["==", TYPE_MATCH_EXPR, "retreat_route"]],
|
|
||||||
paint: {
|
|
||||||
"line-color": "#ffffff",
|
|
||||||
"line-width": ["interpolate", ["linear"], ["zoom"], 1, 12, 4, 18, 6, 24],
|
|
||||||
"line-opacity": 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "retreat_route-path-arrow-fill",
|
|
||||||
type: "fill",
|
|
||||||
source: pathArrowSourceId!,
|
|
||||||
filter: ["==", TYPE_MATCH_EXPR, "retreat_route"],
|
|
||||||
paint: {
|
|
||||||
"fill-color": [
|
|
||||||
"case",
|
|
||||||
["boolean", ["feature-state", "selected"], false], "#22c55e",
|
|
||||||
["==", ["coalesce", ["get", "entity_id"], ""], ""], "#ef4444",
|
|
||||||
"#94a3b8"
|
|
||||||
],
|
|
||||||
"fill-opacity": [
|
|
||||||
"case",
|
|
||||||
["boolean", ["feature-state", "selected"], false], 0.92,
|
|
||||||
0.82
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "retreat_route-path-arrow-line",
|
|
||||||
type: "line",
|
|
||||||
source: pathArrowSourceId!,
|
|
||||||
filter: ["==", TYPE_MATCH_EXPR, "retreat_route"],
|
|
||||||
paint: {
|
|
||||||
"line-color": [
|
|
||||||
"case",
|
|
||||||
["boolean", ["feature-state", "selected"], false], "#14532d",
|
|
||||||
"#0f172a"
|
|
||||||
],
|
|
||||||
"line-width": ["interpolate", ["linear"], ["zoom"], 1, 0.45, 4, 0.8, 6, 1.2],
|
|
||||||
"line-opacity": 0.9
|
|
||||||
}
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,68 +1,14 @@
|
|||||||
import { LayerSpecification } from "maplibre-gl";
|
import { LayerSpecification } from "maplibre-gl";
|
||||||
import { TYPE_MATCH_EXPR } from "./index";
|
import { buildLineGeotypeLayers } from "./styleBuilders";
|
||||||
|
|
||||||
export function getShippingRouteLayers(sourceId: string, pathArrowSourceId?: string, pointSourceId?: string): LayerSpecification[] {
|
export function getShippingRouteLayers(sourceId: string, pathArrowSourceId?: string, pointSourceId?: string): LayerSpecification[] {
|
||||||
return [
|
void pointSourceId;
|
||||||
{
|
return buildLineGeotypeLayers(sourceId, pathArrowSourceId, {
|
||||||
id: "shipping_route-line",
|
typeId: "shipping_route",
|
||||||
type: "line",
|
color: "#0ea5e9",
|
||||||
source: sourceId,
|
strokeColor: "#075985",
|
||||||
filter: ["all", ["==", ["geometry-type"], "LineString"], ["==", TYPE_MATCH_EXPR, "shipping_route"]],
|
width: { z1: 2.4, z4: 3.5, z6: 4.7 },
|
||||||
paint: {
|
dasharray: [7, 4],
|
||||||
"line-color": [
|
arrowOpacity: 0.8,
|
||||||
"case",
|
});
|
||||||
["boolean", ["feature-state", "selected"], false], "#22c55e",
|
|
||||||
["==", ["coalesce", ["get", "entity_id"], ""], ""], "#ef4444",
|
|
||||||
"#2563eb"
|
|
||||||
],
|
|
||||||
"line-width": ["interpolate", ["linear"], ["zoom"], 1, 2.2, 4, 3.2, 6, 4.2],
|
|
||||||
"line-opacity": 0.9
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "shipping_route-hit",
|
|
||||||
type: "line",
|
|
||||||
source: sourceId,
|
|
||||||
filter: ["all", ["==", ["geometry-type"], "LineString"], ["==", TYPE_MATCH_EXPR, "shipping_route"]],
|
|
||||||
paint: {
|
|
||||||
"line-color": "#ffffff",
|
|
||||||
"line-width": ["interpolate", ["linear"], ["zoom"], 1, 12, 4, 18, 6, 24],
|
|
||||||
"line-opacity": 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "shipping_route-path-arrow-fill",
|
|
||||||
type: "fill",
|
|
||||||
source: pathArrowSourceId!,
|
|
||||||
filter: ["==", TYPE_MATCH_EXPR, "shipping_route"],
|
|
||||||
paint: {
|
|
||||||
"fill-color": [
|
|
||||||
"case",
|
|
||||||
["boolean", ["feature-state", "selected"], false], "#22c55e",
|
|
||||||
["==", ["coalesce", ["get", "entity_id"], ""], ""], "#ef4444",
|
|
||||||
"#2563eb"
|
|
||||||
],
|
|
||||||
"fill-opacity": [
|
|
||||||
"case",
|
|
||||||
["boolean", ["feature-state", "selected"], false], 0.92,
|
|
||||||
0.82
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "shipping_route-path-arrow-line",
|
|
||||||
type: "line",
|
|
||||||
source: pathArrowSourceId!,
|
|
||||||
filter: ["==", TYPE_MATCH_EXPR, "shipping_route"],
|
|
||||||
paint: {
|
|
||||||
"line-color": [
|
|
||||||
"case",
|
|
||||||
["boolean", ["feature-state", "selected"], false], "#14532d",
|
|
||||||
"#0f172a"
|
|
||||||
],
|
|
||||||
"line-width": ["interpolate", ["linear"], ["zoom"], 1, 0.45, 4, 0.8, 6, 1.2],
|
|
||||||
"line-opacity": 0.9
|
|
||||||
}
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,40 +1,14 @@
|
|||||||
import { LayerSpecification } from "maplibre-gl";
|
import { LayerSpecification } from "maplibre-gl";
|
||||||
import { TYPE_MATCH_EXPR } from "./index";
|
import { buildPolygonGeotypeLayers } from "./styleBuilders";
|
||||||
|
|
||||||
export function getStateLayers(sourceId: string, pathArrowSourceId?: string, pointSourceId?: string): LayerSpecification[] {
|
export function getStateLayers(sourceId: string, pathArrowSourceId?: string, pointSourceId?: string): LayerSpecification[] {
|
||||||
return [
|
void pathArrowSourceId;
|
||||||
{
|
void pointSourceId;
|
||||||
id: "state-fill",
|
return buildPolygonGeotypeLayers(sourceId, {
|
||||||
type: "fill",
|
typeId: "state",
|
||||||
source: sourceId,
|
fillColor: "#0891b2",
|
||||||
filter: ["all", ["==", ["geometry-type"], "Polygon"], ["==", TYPE_MATCH_EXPR, "state"]],
|
strokeColor: "#0e7490",
|
||||||
paint: {
|
fillOpacity: 0.28,
|
||||||
"fill-color": [
|
strokeWidth: { z1: 1.1, z4: 1.7, z6: 2.4 },
|
||||||
"case",
|
});
|
||||||
["boolean", ["feature-state", "selected"], false], "#22c55e",
|
|
||||||
["==", ["coalesce", ["get", "entity_id"], ""], ""], "#ef4444",
|
|
||||||
"#0ea5e9"
|
|
||||||
],
|
|
||||||
"fill-opacity": [
|
|
||||||
"case",
|
|
||||||
["boolean", ["feature-state", "selected"], false], 0.6,
|
|
||||||
0.5
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "state-line",
|
|
||||||
type: "line",
|
|
||||||
source: sourceId,
|
|
||||||
filter: ["all", ["==", ["geometry-type"], "Polygon"], ["==", TYPE_MATCH_EXPR, "state"]],
|
|
||||||
paint: {
|
|
||||||
"line-color": [
|
|
||||||
"case",
|
|
||||||
["boolean", ["feature-state", "selected"], false], "#14532d",
|
|
||||||
"#0c4a6e"
|
|
||||||
],
|
|
||||||
"line-width": 2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,68 +1,13 @@
|
|||||||
import { LayerSpecification } from "maplibre-gl";
|
import { LayerSpecification } from "maplibre-gl";
|
||||||
import { TYPE_MATCH_EXPR } from "./index";
|
import { buildLineGeotypeLayers } from "./styleBuilders";
|
||||||
|
|
||||||
export function getTradeRouteLayers(sourceId: string, pathArrowSourceId?: string, pointSourceId?: string): LayerSpecification[] {
|
export function getTradeRouteLayers(sourceId: string, pathArrowSourceId?: string, pointSourceId?: string): LayerSpecification[] {
|
||||||
return [
|
void pointSourceId;
|
||||||
{
|
return buildLineGeotypeLayers(sourceId, pathArrowSourceId, {
|
||||||
id: "trade_route-line",
|
typeId: "trade_route",
|
||||||
type: "line",
|
color: "#eab308",
|
||||||
source: sourceId,
|
strokeColor: "#854d0e",
|
||||||
filter: ["all", ["==", ["geometry-type"], "LineString"], ["==", TYPE_MATCH_EXPR, "trade_route"]],
|
dasharray: [5, 3],
|
||||||
paint: {
|
arrowOpacity: 0.78,
|
||||||
"line-color": [
|
});
|
||||||
"case",
|
|
||||||
["boolean", ["feature-state", "selected"], false], "#22c55e",
|
|
||||||
["==", ["coalesce", ["get", "entity_id"], ""], ""], "#ef4444",
|
|
||||||
"#eab308"
|
|
||||||
],
|
|
||||||
"line-width": ["interpolate", ["linear"], ["zoom"], 1, 2.2, 4, 3.2, 6, 4.2],
|
|
||||||
"line-opacity": 0.9
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "trade_route-hit",
|
|
||||||
type: "line",
|
|
||||||
source: sourceId,
|
|
||||||
filter: ["all", ["==", ["geometry-type"], "LineString"], ["==", TYPE_MATCH_EXPR, "trade_route"]],
|
|
||||||
paint: {
|
|
||||||
"line-color": "#ffffff",
|
|
||||||
"line-width": ["interpolate", ["linear"], ["zoom"], 1, 12, 4, 18, 6, 24],
|
|
||||||
"line-opacity": 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "trade_route-path-arrow-fill",
|
|
||||||
type: "fill",
|
|
||||||
source: pathArrowSourceId!,
|
|
||||||
filter: ["==", TYPE_MATCH_EXPR, "trade_route"],
|
|
||||||
paint: {
|
|
||||||
"fill-color": [
|
|
||||||
"case",
|
|
||||||
["boolean", ["feature-state", "selected"], false], "#22c55e",
|
|
||||||
["==", ["coalesce", ["get", "entity_id"], ""], ""], "#ef4444",
|
|
||||||
"#eab308"
|
|
||||||
],
|
|
||||||
"fill-opacity": [
|
|
||||||
"case",
|
|
||||||
["boolean", ["feature-state", "selected"], false], 0.92,
|
|
||||||
0.82
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "trade_route-path-arrow-line",
|
|
||||||
type: "line",
|
|
||||||
source: pathArrowSourceId!,
|
|
||||||
filter: ["==", TYPE_MATCH_EXPR, "trade_route"],
|
|
||||||
paint: {
|
|
||||||
"line-color": [
|
|
||||||
"case",
|
|
||||||
["boolean", ["feature-state", "selected"], false], "#14532d",
|
|
||||||
"#0f172a"
|
|
||||||
],
|
|
||||||
"line-width": ["interpolate", ["linear"], ["zoom"], 1, 0.45, 4, 0.8, 6, 1.2],
|
|
||||||
"line-opacity": 0.9
|
|
||||||
}
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,40 +1,14 @@
|
|||||||
import { LayerSpecification } from "maplibre-gl";
|
import { LayerSpecification } from "maplibre-gl";
|
||||||
import { TYPE_MATCH_EXPR } from "./index";
|
import { buildPolygonGeotypeLayers } from "./styleBuilders";
|
||||||
|
|
||||||
export function getWarLayers(sourceId: string, pathArrowSourceId?: string, pointSourceId?: string): LayerSpecification[] {
|
export function getWarLayers(sourceId: string, pathArrowSourceId?: string, pointSourceId?: string): LayerSpecification[] {
|
||||||
return [
|
void pathArrowSourceId;
|
||||||
{
|
void pointSourceId;
|
||||||
id: "war-fill",
|
return buildPolygonGeotypeLayers(sourceId, {
|
||||||
type: "fill",
|
typeId: "war",
|
||||||
source: sourceId,
|
fillColor: "#dc2626",
|
||||||
filter: ["all", ["==", ["geometry-type"], "Polygon"], ["==", TYPE_MATCH_EXPR, "war"]],
|
strokeColor: "#7f1d1d",
|
||||||
paint: {
|
fillOpacity: 0.26,
|
||||||
"fill-color": [
|
dasharray: [5, 2],
|
||||||
"case",
|
});
|
||||||
["boolean", ["feature-state", "selected"], false], "#22c55e",
|
|
||||||
["==", ["coalesce", ["get", "entity_id"], ""], ""], "#ef4444",
|
|
||||||
"#dc2626"
|
|
||||||
],
|
|
||||||
"fill-opacity": [
|
|
||||||
"case",
|
|
||||||
["boolean", ["feature-state", "selected"], false], 0.6,
|
|
||||||
0.3
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "war-line",
|
|
||||||
type: "line",
|
|
||||||
source: sourceId,
|
|
||||||
filter: ["all", ["==", ["geometry-type"], "Polygon"], ["==", TYPE_MATCH_EXPR, "war"]],
|
|
||||||
paint: {
|
|
||||||
"line-color": [
|
|
||||||
"case",
|
|
||||||
["boolean", ["feature-state", "selected"], false], "#14532d",
|
|
||||||
"#7f1d1d"
|
|
||||||
],
|
|
||||||
"line-width": 2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user