feat(config): inject frontend runtime config
This commit is contained in:
@@ -3,6 +3,8 @@ node_modules
|
|||||||
out
|
out
|
||||||
build
|
build
|
||||||
.git
|
.git
|
||||||
|
.env
|
||||||
|
.env.*
|
||||||
.env*.local
|
.env*.local
|
||||||
README.md
|
README.md
|
||||||
docker-compose.yml
|
docker-compose.yml
|
||||||
|
|||||||
@@ -105,15 +105,6 @@ jobs:
|
|||||||
-t "${IMAGE_NAME}:${IMAGE_TAG}" \
|
-t "${IMAGE_NAME}:${IMAGE_TAG}" \
|
||||||
-t "${IMAGE_NAME}:latest" \
|
-t "${IMAGE_NAME}:latest" \
|
||||||
--build-arg NPM_CONFIG_REGISTRY="https://registry.npmmirror.com" \
|
--build-arg NPM_CONFIG_REGISTRY="https://registry.npmmirror.com" \
|
||||||
--build-arg NEXT_PUBLIC_BACKEND_URL="${{ vars.NEXT_PUBLIC_BACKEND_URL }}" \
|
|
||||||
--build-arg NEXT_PUBLIC_AGENT_URL="${{ vars.NEXT_PUBLIC_AGENT_URL }}" \
|
|
||||||
--build-arg NEXT_PUBLIC_AUDIO_SERVICE_URL="${{ vars.NEXT_PUBLIC_AUDIO_SERVICE_URL }}" \
|
|
||||||
--build-arg NEXT_PUBLIC_MAP_URL="${{ vars.NEXT_PUBLIC_MAP_URL }}" \
|
|
||||||
--build-arg NEXT_PUBLIC_MAP_WORKSPACE="${{ vars.NEXT_PUBLIC_MAP_WORKSPACE }}" \
|
|
||||||
--build-arg NEXT_PUBLIC_MAP_EXTENT="${{ vars.NEXT_PUBLIC_MAP_EXTENT }}" \
|
|
||||||
--build-arg NEXT_PUBLIC_NETWORK_NAME="${{ vars.NEXT_PUBLIC_NETWORK_NAME }}" \
|
|
||||||
--build-arg NEXT_PUBLIC_MAPBOX_TOKEN="${{ secrets.NEXT_PUBLIC_MAPBOX_TOKEN }}" \
|
|
||||||
--build-arg NEXT_PUBLIC_TIANDITU_TOKEN="${{ secrets.NEXT_PUBLIC_TIANDITU_TOKEN }}" \
|
|
||||||
.
|
.
|
||||||
push_with_retry "${IMAGE_NAME}:${IMAGE_TAG}"
|
push_with_retry "${IMAGE_NAME}:${IMAGE_TAG}"
|
||||||
push_with_retry "${IMAGE_NAME}:latest"
|
push_with_retry "${IMAGE_NAME}:latest"
|
||||||
|
|||||||
+4
-13
@@ -18,18 +18,6 @@ RUN \
|
|||||||
|
|
||||||
FROM base AS builder
|
FROM base AS builder
|
||||||
|
|
||||||
# 只定义 ARG 接收来自构建命令或 docker-compose.yaml 的参数
|
|
||||||
# Next.js 在 build 时会自动读取同名的 ARG 作为环境变量
|
|
||||||
ARG NEXT_PUBLIC_BACKEND_URL
|
|
||||||
ARG NEXT_PUBLIC_AGENT_URL
|
|
||||||
ARG NEXT_PUBLIC_AUDIO_SERVICE_URL
|
|
||||||
ARG NEXT_PUBLIC_MAP_URL
|
|
||||||
ARG NEXT_PUBLIC_MAP_WORKSPACE
|
|
||||||
ARG NEXT_PUBLIC_MAP_EXTENT
|
|
||||||
ARG NEXT_PUBLIC_NETWORK_NAME
|
|
||||||
ARG NEXT_PUBLIC_MAPBOX_TOKEN
|
|
||||||
ARG NEXT_PUBLIC_TIANDITU_TOKEN
|
|
||||||
|
|
||||||
COPY --from=deps /app/refine/node_modules ./node_modules
|
COPY --from=deps /app/refine/node_modules ./node_modules
|
||||||
|
|
||||||
COPY . .
|
COPY . .
|
||||||
@@ -40,7 +28,9 @@ FROM base AS runner
|
|||||||
|
|
||||||
ENV NODE_ENV=production
|
ENV NODE_ENV=production
|
||||||
|
|
||||||
COPY --from=builder /app/refine/public ./public
|
COPY --from=builder --chown=node:node /app/refine/public ./public
|
||||||
|
COPY --chown=node:node docker/entrypoint.sh /entrypoint.sh
|
||||||
|
RUN chmod +x /entrypoint.sh
|
||||||
|
|
||||||
RUN mkdir .next
|
RUN mkdir .next
|
||||||
RUN chown node:node .next
|
RUN chown node:node .next
|
||||||
@@ -55,4 +45,5 @@ EXPOSE 3000
|
|||||||
ENV PORT=3000
|
ENV PORT=3000
|
||||||
ENV HOSTNAME="0.0.0.0"
|
ENV HOSTNAME="0.0.0.0"
|
||||||
|
|
||||||
|
ENTRYPOINT ["/entrypoint.sh"]
|
||||||
CMD ["node", "server.js"]
|
CMD ["node", "server.js"]
|
||||||
|
|||||||
+8
-12
@@ -6,19 +6,15 @@ services:
|
|||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
dockerfile: Dockerfile
|
dockerfile: Dockerfile
|
||||||
args:
|
|
||||||
NEXT_PUBLIC_BACKEND_URL: ${NEXT_PUBLIC_BACKEND_URL}
|
|
||||||
NEXT_PUBLIC_AGENT_URL: ${NEXT_PUBLIC_AGENT_URL}
|
|
||||||
NEXT_PUBLIC_AUDIO_SERVICE_URL: ${NEXT_PUBLIC_AUDIO_SERVICE_URL}
|
|
||||||
NEXT_PUBLIC_MAP_URL: ${NEXT_PUBLIC_MAP_URL}
|
|
||||||
NEXT_PUBLIC_MAP_WORKSPACE: ${NEXT_PUBLIC_MAP_WORKSPACE}
|
|
||||||
NEXT_PUBLIC_MAP_EXTENT: ${NEXT_PUBLIC_MAP_EXTENT}
|
|
||||||
NEXT_PUBLIC_NETWORK_NAME: ${NEXT_PUBLIC_NETWORK_NAME}
|
|
||||||
NEXT_PUBLIC_MAPBOX_TOKEN: ${NEXT_PUBLIC_MAPBOX_TOKEN}
|
|
||||||
NEXT_PUBLIC_TIANDITU_TOKEN: ${NEXT_PUBLIC_TIANDITU_TOKEN}
|
|
||||||
env_file:
|
|
||||||
- .env
|
|
||||||
environment:
|
environment:
|
||||||
|
BACKEND_URL: ${BACKEND_URL}
|
||||||
|
AGENT_URL: ${AGENT_URL}
|
||||||
|
MAP_URL: ${MAP_URL}
|
||||||
|
MAP_WORKSPACE: ${MAP_WORKSPACE}
|
||||||
|
MAP_EXTENT: ${MAP_EXTENT}
|
||||||
|
NETWORK_NAME: ${NETWORK_NAME}
|
||||||
|
MAPBOX_TOKEN: ${MAPBOX_TOKEN}
|
||||||
|
TIANDITU_TOKEN: ${TIANDITU_TOKEN}
|
||||||
KEYCLOAK_CLIENT_ID: ${KEYCLOAK_CLIENT_ID}
|
KEYCLOAK_CLIENT_ID: ${KEYCLOAK_CLIENT_ID}
|
||||||
KEYCLOAK_CLIENT_SECRET: ${KEYCLOAK_CLIENT_SECRET}
|
KEYCLOAK_CLIENT_SECRET: ${KEYCLOAK_CLIENT_SECRET}
|
||||||
KEYCLOAK_ISSUER: ${KEYCLOAK_ISSUER}
|
KEYCLOAK_ISSUER: ${KEYCLOAK_ISSUER}
|
||||||
|
|||||||
Executable
+35
@@ -0,0 +1,35 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
node <<'NODE'
|
||||||
|
const fs = require("fs");
|
||||||
|
|
||||||
|
const parseExtent = (value) => {
|
||||||
|
if (!value) {
|
||||||
|
return [13508849, 3608036, 13555781, 3633813];
|
||||||
|
}
|
||||||
|
|
||||||
|
const extent = value.split(",").map(Number);
|
||||||
|
return extent.length === 4 && extent.every(Number.isFinite)
|
||||||
|
? extent
|
||||||
|
: [13508849, 3608036, 13555781, 3633813];
|
||||||
|
};
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
BACKEND_URL: process.env.BACKEND_URL || "http://127.0.0.1:8000",
|
||||||
|
AGENT_URL: process.env.AGENT_URL || "http://127.0.0.1:8788",
|
||||||
|
MAP_URL: process.env.MAP_URL || "http://127.0.0.1:8080/geoserver",
|
||||||
|
MAP_WORKSPACE: process.env.MAP_WORKSPACE || "tjwater",
|
||||||
|
MAP_EXTENT: parseExtent(process.env.MAP_EXTENT),
|
||||||
|
NETWORK_NAME: process.env.NETWORK_NAME || "tjwater",
|
||||||
|
MAPBOX_TOKEN: process.env.MAPBOX_TOKEN || "",
|
||||||
|
TIANDITU_TOKEN: process.env.TIANDITU_TOKEN || "",
|
||||||
|
};
|
||||||
|
|
||||||
|
fs.writeFileSync(
|
||||||
|
"/app/refine/public/runtime-config.js",
|
||||||
|
`window.__TJWATER_RUNTIME_CONFIG__ = ${JSON.stringify(config)};\n`,
|
||||||
|
);
|
||||||
|
NODE
|
||||||
|
|
||||||
|
exec "$@"
|
||||||
@@ -9,16 +9,26 @@ type KeycloakTokenResponse = {
|
|||||||
refresh_token?: string;
|
refresh_token?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
const keycloakIssuer = process.env.KEYCLOAK_ISSUER!;
|
const getKeycloakTokenEndpoint = () => {
|
||||||
const keycloakClientId = process.env.KEYCLOAK_CLIENT_ID!;
|
const issuer = process.env.KEYCLOAK_ISSUER;
|
||||||
const keycloakClientSecret = process.env.KEYCLOAK_CLIENT_SECRET!;
|
return issuer
|
||||||
const keycloakTokenEndpoint = `${keycloakIssuer.replace(/\/$/, "")}/protocol/openid-connect/token`;
|
? `${issuer.replace(/\/$/, "")}/protocol/openid-connect/token`
|
||||||
|
: undefined;
|
||||||
|
};
|
||||||
|
|
||||||
const refreshAccessToken = async (token: JWT): Promise<JWT> => {
|
const refreshAccessToken = async (token: JWT): Promise<JWT> => {
|
||||||
if (!token.refreshToken) {
|
if (!token.refreshToken) {
|
||||||
return { ...token, error: "RefreshAccessTokenError" };
|
return { ...token, error: "RefreshAccessTokenError" };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const keycloakClientId = process.env.KEYCLOAK_CLIENT_ID;
|
||||||
|
const keycloakClientSecret = process.env.KEYCLOAK_CLIENT_SECRET;
|
||||||
|
const keycloakTokenEndpoint = getKeycloakTokenEndpoint();
|
||||||
|
|
||||||
|
if (!keycloakClientId || !keycloakClientSecret || !keycloakTokenEndpoint) {
|
||||||
|
return { ...token, error: "RefreshAccessTokenError" };
|
||||||
|
}
|
||||||
|
|
||||||
const body = new URLSearchParams({
|
const body = new URLSearchParams({
|
||||||
grant_type: "refresh_token",
|
grant_type: "refresh_token",
|
||||||
client_id: keycloakClientId,
|
client_id: keycloakClientId,
|
||||||
@@ -50,9 +60,9 @@ const authOptions: NextAuthOptions = {
|
|||||||
// Configure one or more authentication providers
|
// Configure one or more authentication providers
|
||||||
providers: [
|
providers: [
|
||||||
KeycloakProvider({
|
KeycloakProvider({
|
||||||
clientId: keycloakClientId,
|
clientId: process.env.KEYCLOAK_CLIENT_ID ?? "",
|
||||||
clientSecret: keycloakClientSecret,
|
clientSecret: process.env.KEYCLOAK_CLIENT_SECRET ?? "",
|
||||||
issuer: keycloakIssuer,
|
issuer: process.env.KEYCLOAK_ISSUER ?? "",
|
||||||
profile(profile) {
|
profile(profile) {
|
||||||
return {
|
return {
|
||||||
id: profile.sub,
|
id: profile.sub,
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import type { Metadata } from "next";
|
import type { Metadata } from "next";
|
||||||
import { cookies } from "next/headers";
|
import { cookies } from "next/headers";
|
||||||
|
import Script from "next/script";
|
||||||
import React, { Suspense } from "react";
|
import React, { Suspense } from "react";
|
||||||
import { RefineContext } from "./RefineContext";
|
import { RefineContext } from "./RefineContext";
|
||||||
import { META_DATA } from "@config/config";
|
import { META_DATA } from "@config/config";
|
||||||
@@ -18,6 +19,7 @@ export default async function RootLayout({
|
|||||||
return (
|
return (
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<body>
|
<body>
|
||||||
|
<Script src="/runtime-config.js" strategy="beforeInteractive" />
|
||||||
<Suspense>
|
<Suspense>
|
||||||
<RefineContext defaultMode={defaultMode}>{children}</RefineContext>
|
<RefineContext defaultMode={defaultMode}>{children}</RefineContext>
|
||||||
</Suspense>
|
</Suspense>
|
||||||
|
|||||||
@@ -27,6 +27,10 @@ import { GlobalChatbox } from "@components/chat/GlobalChatbox";
|
|||||||
import { setMapExtent, setMapWorkspace, setNetworkName } from "@config/config";
|
import { setMapExtent, setMapWorkspace, setNetworkName } from "@config/config";
|
||||||
import { useProjectStore } from "@/store/projectStore";
|
import { useProjectStore } from "@/store/projectStore";
|
||||||
|
|
||||||
|
const MAP_WORKSPACE_STORAGE_KEY = "MAP_WORKSPACE";
|
||||||
|
const NETWORK_NAME_STORAGE_KEY = "NETWORK_NAME";
|
||||||
|
const MAP_EXTENT_STORAGE_KEY = "MAP_EXTENT";
|
||||||
|
|
||||||
type IUser = {
|
type IUser = {
|
||||||
id?: string;
|
id?: string;
|
||||||
name?: string;
|
name?: string;
|
||||||
@@ -70,9 +74,9 @@ export const Header: React.FC<RefineThemedLayoutHeaderProps> = ({
|
|||||||
setMapWorkspace(workspace);
|
setMapWorkspace(workspace);
|
||||||
setNetworkName(networkName);
|
setNetworkName(networkName);
|
||||||
setMapExtent(extent);
|
setMapExtent(extent);
|
||||||
localStorage.setItem("NEXT_PUBLIC_MAP_WORKSPACE", workspace);
|
localStorage.setItem(MAP_WORKSPACE_STORAGE_KEY, workspace);
|
||||||
localStorage.setItem("NEXT_PUBLIC_NETWORK_NAME", networkName);
|
localStorage.setItem(NETWORK_NAME_STORAGE_KEY, networkName);
|
||||||
localStorage.setItem("NEXT_PUBLIC_MAP_EXTENT", extent.join(","));
|
localStorage.setItem(MAP_EXTENT_STORAGE_KEY, extent.join(","));
|
||||||
localStorage.removeItem(`${workspace}_map_view`);
|
localStorage.removeItem(`${workspace}_map_view`);
|
||||||
setCurrentProjectId(projectId || networkName || workspace);
|
setCurrentProjectId(projectId || networkName || workspace);
|
||||||
setShowProjectSelector(false);
|
setShowProjectSelector(false);
|
||||||
|
|||||||
+40
-15
@@ -1,13 +1,41 @@
|
|||||||
|
type RuntimeConfig = {
|
||||||
|
BACKEND_URL?: string;
|
||||||
|
AGENT_URL?: string;
|
||||||
|
MAP_URL?: string;
|
||||||
|
MAP_WORKSPACE?: string;
|
||||||
|
MAP_EXTENT?: number[] | string;
|
||||||
|
NETWORK_NAME?: string;
|
||||||
|
MAPBOX_TOKEN?: string;
|
||||||
|
TIANDITU_TOKEN?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface Window {
|
||||||
|
__TJWATER_RUNTIME_CONFIG__?: RuntimeConfig;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const runtimeConfig =
|
||||||
|
typeof window === "undefined" ? {} : window.__TJWATER_RUNTIME_CONFIG__ ?? {};
|
||||||
|
|
||||||
|
const parseMapExtent = (value: RuntimeConfig["MAP_EXTENT"]): number[] => {
|
||||||
|
if (Array.isArray(value)) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof value === "string" && value.trim()) {
|
||||||
|
return value.split(",").map(Number);
|
||||||
|
}
|
||||||
|
|
||||||
|
return [13508849, 3608036, 13555781, 3633813];
|
||||||
|
};
|
||||||
|
|
||||||
export const config = {
|
export const config = {
|
||||||
BACKEND_URL: process.env.NEXT_PUBLIC_BACKEND_URL || "http://127.0.0.1:8000",
|
BACKEND_URL: runtimeConfig.BACKEND_URL || "http://127.0.0.1:8000",
|
||||||
AGENT_URL: process.env.NEXT_PUBLIC_AGENT_URL || "http://127.0.0.1:8788",
|
AGENT_URL: runtimeConfig.AGENT_URL || "http://127.0.0.1:8788",
|
||||||
AUDIO_SERVICE_URL:
|
MAP_URL: runtimeConfig.MAP_URL || "http://127.0.0.1:8080/geoserver",
|
||||||
process.env.NEXT_PUBLIC_AUDIO_SERVICE_URL || "http://127.0.0.1:18083",
|
MAP_WORKSPACE: runtimeConfig.MAP_WORKSPACE || "tjwater",
|
||||||
MAP_URL: process.env.NEXT_PUBLIC_MAP_URL || "http://127.0.0.1:8080/geoserver",
|
MAP_EXTENT: parseMapExtent(runtimeConfig.MAP_EXTENT),
|
||||||
MAP_WORKSPACE: process.env.NEXT_PUBLIC_MAP_WORKSPACE || "tjwater",
|
|
||||||
MAP_EXTENT: process.env.NEXT_PUBLIC_MAP_EXTENT
|
|
||||||
? process.env.NEXT_PUBLIC_MAP_EXTENT.split(",").map(Number)
|
|
||||||
: [13508849, 3608036, 13555781, 3633813],
|
|
||||||
MAP_DEFAULT_STYLE: {
|
MAP_DEFAULT_STYLE: {
|
||||||
"stroke-width": 3,
|
"stroke-width": 3,
|
||||||
"stroke-color": "rgba(51, 153, 204, 0.9)",
|
"stroke-color": "rgba(51, 153, 204, 0.9)",
|
||||||
@@ -33,7 +61,7 @@ export const config = {
|
|||||||
"scada",
|
"scada",
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
export let NETWORK_NAME = process.env.NEXT_PUBLIC_NETWORK_NAME || "tjwater";
|
export let NETWORK_NAME = runtimeConfig.NETWORK_NAME || "tjwater";
|
||||||
|
|
||||||
export const setNetworkName = (name: string) => {
|
export const setNetworkName = (name: string) => {
|
||||||
NETWORK_NAME = name;
|
NETWORK_NAME = name;
|
||||||
@@ -47,11 +75,8 @@ export const setMapExtent = (extent: number[]) => {
|
|||||||
config.MAP_EXTENT = extent;
|
config.MAP_EXTENT = extent;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const MAPBOX_TOKEN =
|
export const MAPBOX_TOKEN = runtimeConfig.MAPBOX_TOKEN || "";
|
||||||
process.env.NEXT_PUBLIC_MAPBOX_TOKEN ||
|
export const TIANDITU_TOKEN = runtimeConfig.TIANDITU_TOKEN || "";
|
||||||
"pk.eyJ1IjoiemhpZnUiLCJhIjoiY205azNyNGY1MGkyZDJxcTJleDUwaHV1ZCJ9.wOmSdOnDDdre-mB1Lpy6Fg";
|
|
||||||
export const TIANDITU_TOKEN =
|
|
||||||
process.env.NEXT_PUBLIC_TIANDITU_TOKEN || "e3e8ad95ee911741fa71ed7bff2717ec";
|
|
||||||
export const PROJECT_TITLE = process.env.PROJECT_TITLE || "TJWater Project";
|
export const PROJECT_TITLE = process.env.PROJECT_TITLE || "TJWater Project";
|
||||||
export const META_DATA = {
|
export const META_DATA = {
|
||||||
title: PROJECT_TITLE,
|
title: PROJECT_TITLE,
|
||||||
|
|||||||
@@ -13,6 +13,9 @@ interface ProjectContextType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const ProjectContext = createContext<ProjectContextType | undefined>(undefined);
|
const ProjectContext = createContext<ProjectContextType | undefined>(undefined);
|
||||||
|
const MAP_WORKSPACE_STORAGE_KEY = "MAP_WORKSPACE";
|
||||||
|
const NETWORK_NAME_STORAGE_KEY = "NETWORK_NAME";
|
||||||
|
const MAP_EXTENT_STORAGE_KEY = "MAP_EXTENT";
|
||||||
|
|
||||||
export const ProjectProvider: React.FC<{ children: React.ReactNode }> = ({
|
export const ProjectProvider: React.FC<{ children: React.ReactNode }> = ({
|
||||||
children,
|
children,
|
||||||
@@ -38,15 +41,15 @@ export const ProjectProvider: React.FC<{ children: React.ReactNode }> = ({
|
|||||||
setMapWorkspace(ws);
|
setMapWorkspace(ws);
|
||||||
setNetworkName(net);
|
setNetworkName(net);
|
||||||
setMapExtent(extent);
|
setMapExtent(extent);
|
||||||
localStorage.setItem("NEXT_PUBLIC_MAP_EXTENT", extent.join(","));
|
localStorage.setItem(MAP_EXTENT_STORAGE_KEY, extent.join(","));
|
||||||
// Reset extent cache
|
// Reset extent cache
|
||||||
localStorage.removeItem(`${ws}_map_view`);
|
localStorage.removeItem(`${ws}_map_view`);
|
||||||
setCurrentProject({ workspace: ws, networkName: net, extent: extent });
|
setCurrentProject({ workspace: ws, networkName: net, extent: extent });
|
||||||
setCurrentProjectId(resolvedProjectId);
|
setCurrentProjectId(resolvedProjectId);
|
||||||
|
|
||||||
// Save to localStorage
|
// Save to localStorage
|
||||||
localStorage.setItem("NEXT_PUBLIC_MAP_WORKSPACE", ws);
|
localStorage.setItem(MAP_WORKSPACE_STORAGE_KEY, ws);
|
||||||
localStorage.setItem("NEXT_PUBLIC_NETWORK_NAME", net);
|
localStorage.setItem(NETWORK_NAME_STORAGE_KEY, net);
|
||||||
|
|
||||||
setIsConfigured(true);
|
setIsConfigured(true);
|
||||||
|
|
||||||
@@ -76,10 +79,7 @@ export const ProjectProvider: React.FC<{ children: React.ReactNode }> = ({
|
|||||||
// Update workspace if different
|
// Update workspace if different
|
||||||
if (data?.gs_workspace && data.gs_workspace !== ws) {
|
if (data?.gs_workspace && data.gs_workspace !== ws) {
|
||||||
setMapWorkspace(data.gs_workspace);
|
setMapWorkspace(data.gs_workspace);
|
||||||
localStorage.setItem(
|
localStorage.setItem(MAP_WORKSPACE_STORAGE_KEY, data.gs_workspace);
|
||||||
"NEXT_PUBLIC_MAP_WORKSPACE",
|
|
||||||
data.gs_workspace,
|
|
||||||
);
|
|
||||||
setCurrentProject((prev) => ({
|
setCurrentProject((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
workspace: data.gs_workspace,
|
workspace: data.gs_workspace,
|
||||||
@@ -92,7 +92,7 @@ export const ProjectProvider: React.FC<{ children: React.ReactNode }> = ({
|
|||||||
: null;
|
: null;
|
||||||
if (bbox && bbox.length === 4) {
|
if (bbox && bbox.length === 4) {
|
||||||
setMapExtent(bbox);
|
setMapExtent(bbox);
|
||||||
localStorage.setItem("NEXT_PUBLIC_MAP_EXTENT", bbox.join(","));
|
localStorage.setItem(MAP_EXTENT_STORAGE_KEY, bbox.join(","));
|
||||||
localStorage.removeItem(`${ws}_map_view`);
|
localStorage.removeItem(`${ws}_map_view`);
|
||||||
setCurrentProject((prev) => ({ ...prev, extent: bbox }));
|
setCurrentProject((prev) => ({ ...prev, extent: bbox }));
|
||||||
}
|
}
|
||||||
@@ -104,9 +104,9 @@ export const ProjectProvider: React.FC<{ children: React.ReactNode }> = ({
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Check localStorage
|
// Check localStorage
|
||||||
const savedWorkspace = localStorage.getItem("NEXT_PUBLIC_MAP_WORKSPACE");
|
const savedWorkspace = localStorage.getItem(MAP_WORKSPACE_STORAGE_KEY);
|
||||||
const savedNetwork = localStorage.getItem("NEXT_PUBLIC_NETWORK_NAME");
|
const savedNetwork = localStorage.getItem(NETWORK_NAME_STORAGE_KEY);
|
||||||
const savedExtent = localStorage.getItem("NEXT_PUBLIC_MAP_EXTENT");
|
const savedExtent = localStorage.getItem(MAP_EXTENT_STORAGE_KEY);
|
||||||
const savedProjectId = localStorage.getItem("active_project");
|
const savedProjectId = localStorage.getItem("active_project");
|
||||||
|
|
||||||
// If we have saved config, use it.
|
// If we have saved config, use it.
|
||||||
|
|||||||
Reference in New Issue
Block a user