diff --git a/.github/workflows/.deployer.yml b/.github/workflows/.deployer.yml
index eabd6c8c5..1f44b3860 100644
--- a/.github/workflows/.deployer.yml
+++ b/.github/workflows/.deployer.yml
@@ -146,6 +146,7 @@ jobs:
--set frontend.env.VITE_SSO_CLIENT_ID=${{ secrets.VITE_SSO_CLIENT_ID }} \
--set frontend.env.VITE_SSO_REALM=${{ secrets.VITE_SSO_REALM }} \
--set frontend.env.VITE_SSO_REDIRECT_URI=${{ secrets.VITE_SSO_REDIRECT_URI }} \
+ --set frontend.env.VITE_API_URL=${{ secrets.VITE_API_URL }} \
${{ inputs.params }} \
--install --wait --atomic ${{ steps.vars.outputs.release }} \
--timeout ${{ inputs.timeout-minutes }}m \
diff --git a/backend/src/main/java/ca/bc/gov/nrs/vdyp/backend/api/v1/messaging/NullMessageLog.java b/backend/src/main/java/ca/bc/gov/nrs/vdyp/backend/api/v1/messaging/NullMessageLog.java
index 64f17b691..77290b09d 100644
--- a/backend/src/main/java/ca/bc/gov/nrs/vdyp/backend/api/v1/messaging/NullMessageLog.java
+++ b/backend/src/main/java/ca/bc/gov/nrs/vdyp/backend/api/v1/messaging/NullMessageLog.java
@@ -2,28 +2,18 @@
import java.io.ByteArrayInputStream;
import java.io.InputStream;
-import java.text.MessageFormat;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import org.slf4j.event.Level;
public class NullMessageLog implements IMessageLog {
- private static final Logger logger = LoggerFactory.getLogger(NullMessageLog.class);
-
- private final Level loggerLevel;
-
public NullMessageLog(Level loggerLevel) {
- this.loggerLevel = loggerLevel;
+ /* do nothing */
}
@Override
public void addMessage(String message, Object... arguments) {
- if (arguments.length > 0) {
- message = MessageFormat.format(message, arguments);
- }
- logger.atLevel(loggerLevel).log(loggerLevel + " message: " + message);
+ /* do nothing */
}
@Override
diff --git a/backend/src/main/java/ca/bc/gov/nrs/vdyp/backend/projection/StubProjectionRunner.java b/backend/src/main/java/ca/bc/gov/nrs/vdyp/backend/projection/StubProjectionRunner.java
index db6f932f2..71d0b52ab 100644
--- a/backend/src/main/java/ca/bc/gov/nrs/vdyp/backend/projection/StubProjectionRunner.java
+++ b/backend/src/main/java/ca/bc/gov/nrs/vdyp/backend/projection/StubProjectionRunner.java
@@ -1,15 +1,14 @@
package ca.bc.gov.nrs.vdyp.backend.projection;
-import java.io.IOException;
+import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.Map;
-import ca.bc.gov.nrs.vdyp.backend.api.v1.exceptions.ProjectionExecutionException;
-import ca.bc.gov.nrs.vdyp.backend.api.v1.exceptions.ProjectionRequestValidationException;
-import ca.bc.gov.nrs.vdyp.backend.model.v1.Parameters;
-import ca.bc.gov.nrs.vdyp.backend.model.v1.ProjectionRequestKind;
-import ca.bc.gov.nrs.vdyp.backend.projection.input.AbstractPolygonStream;
-import ca.bc.gov.nrs.vdyp.backend.utils.FileHelper;
+import ca.bc.gov.nrs.vdyp.backend.v1.api.impl.exceptions.ProjectionExecutionException;
+import ca.bc.gov.nrs.vdyp.backend.v1.api.impl.exceptions.ProjectionRequestValidationException;
+import ca.bc.gov.nrs.vdyp.backend.v1.gen.model.Parameters;
+import ca.bc.gov.nrs.vdyp.backend.v1.gen.model.ProjectionRequestKind;
+import jakarta.validation.Valid;
public class StubProjectionRunner implements IProjectionRunner {
@@ -39,28 +38,17 @@ public ProjectionState getState() {
@Override
public InputStream getYieldTable() throws ProjectionExecutionException {
- try {
- return FileHelper.getStubResourceFile("Output_YldTbl.csv");
- } catch (IOException e) {
- throw new ProjectionExecutionException(e);
- }
+ // No projection was done; therefore, there's no yield table.
+ return new ByteArrayInputStream(new byte[0]);
}
@Override
- public InputStream getProgressStream() throws ProjectionExecutionException {
- try {
- return FileHelper.getStubResourceFile("Output_Log.txt");
- } catch (IOException e) {
- throw new ProjectionExecutionException(e);
- }
+ public InputStream getProgressStream() {
+ return state.getProgressLog().getAsStream();
}
@Override
- public InputStream getErrorStream() throws ProjectionExecutionException {
- try {
- return FileHelper.getStubResourceFile("Output_Error.txt");
- } catch (IOException e) {
- throw new ProjectionExecutionException(e);
- }
+ public InputStream getErrorStream() {
+ return state.getErrorLog().getAsStream();
}
}
diff --git a/backend/src/test/java/ca/bc/gov/nrs/vdyp/backend/endpoints/v1/StubHcsvProjectionEndpointTest.java b/backend/src/test/java/ca/bc/gov/nrs/vdyp/backend/endpoints/v1/StubHcsvProjectionEndpointTest.java
new file mode 100644
index 000000000..b042c2bd5
--- /dev/null
+++ b/backend/src/test/java/ca/bc/gov/nrs/vdyp/backend/endpoints/v1/StubHcsvProjectionEndpointTest.java
@@ -0,0 +1,139 @@
+package ca.bc.gov.nrs.api.v1.endpoints;
+
+import static io.restassured.RestAssured.given;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+import org.hamcrest.Matchers;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import ca.bc.gov.nrs.api.helpers.TestHelper;
+import ca.bc.gov.nrs.vdyp.backend.v1.gen.api.ParameterNames;
+import ca.bc.gov.nrs.vdyp.backend.v1.gen.model.Parameters;
+import io.quarkus.test.junit.QuarkusTest;
+import jakarta.inject.Inject;
+import jakarta.ws.rs.core.MediaType;
+
+@QuarkusTest
+class StubHcsvProjectionEndpointTest {
+
+ private final TestHelper testHelper;
+
+ @Inject
+ StubHcsvProjectionEndpointTest(TestHelper testHelper) {
+ this.testHelper = testHelper;
+ }
+
+ @BeforeEach
+ void setup() {
+ }
+
+ @Test
+ void testProjectionHscv_shouldReturnStatusOK() throws IOException {
+
+ Path resourceFolderPath = Path.of("VDYP7Console-sample-files", "hcsv", "vdyp-240");
+
+ Parameters parameters = testHelper.addSelectedOptions(
+ new Parameters(), //
+ Parameters.SelectedExecutionOptionsEnum.DO_ENABLE_DEBUG_LOGGING,
+ Parameters.SelectedExecutionOptionsEnum.DO_ENABLE_PROGRESS_LOGGING,
+ Parameters.SelectedExecutionOptionsEnum.DO_ENABLE_ERROR_LOGGING
+ );
+
+ // Included to generate JSON text of parameters as needed
+// ObjectMapper mapper = new ObjectMapper();
+// String serializedParametersText = mapper.writeValueAsString(parameters);
+
+ InputStream zipInputStream = given().basePath(TestHelper.ROOT_PATH).when() //
+ .multiPart(ParameterNames.PROJECTION_PARAMETERS, parameters, MediaType.APPLICATION_JSON) //
+ .multiPart(
+ ParameterNames.POLYGON_INPUT_DATA,
+ Files.readAllBytes(testHelper.getResourceFile(resourceFolderPath, "VDYP7_INPUT_POLY.csv"))
+ ) //
+ .multiPart(
+ ParameterNames.LAYERS_INPUT_DATA,
+ Files.readAllBytes(testHelper.getResourceFile(resourceFolderPath, "VDYP7_INPUT_LAYER.csv"))
+ ) //
+ .post("/projection/hcsv?trialRun=true") //
+ .then().statusCode(201) //
+ .and().contentType("application/octet-stream") //
+ .and().header("content-disposition", Matchers.startsWith("attachment;filename=\"vdyp-output-")) //
+ .extract().body().asInputStream();
+
+ ZipInputStream zipFile = new ZipInputStream(zipInputStream);
+ ZipEntry entry1 = zipFile.getNextEntry();
+ assertEquals("YieldTable.csv", entry1.getName());
+ String entry1Content = new String(testHelper.readZipEntry(zipFile, entry1));
+ assertTrue(entry1Content.length() == 0);
+
+ ZipEntry entry2 = zipFile.getNextEntry();
+ assertEquals("ProgressLog.txt", entry2.getName());
+ String entry2Content = new String(testHelper.readZipEntry(zipFile, entry2));
+ assertTrue(entry2Content.startsWith("Running Projection"));
+
+ ZipEntry entry3 = zipFile.getNextEntry();
+ assertEquals("ErrorLog.txt", entry3.getName());
+ String entry3Content = new String(testHelper.readZipEntry(zipFile, entry3));
+ assertTrue(entry3Content.isBlank());
+
+ ZipEntry entry4 = zipFile.getNextEntry();
+ assertEquals("DebugLog.txt", entry4.getName());
+ String entry4Content = new String(testHelper.readZipEntry(zipFile, entry4));
+ assertTrue(entry4Content.startsWith(LocalDate.now().format(DateTimeFormatter.ISO_DATE)));
+ }
+
+ @Test
+ void testProjectionHscv_testNoProgressLogging() throws IOException {
+
+ Path resourceFolderPath = Path.of("VDYP7Console-sample-files", "hcsv", "vdyp-240");
+
+ Parameters parameters = new Parameters();
+
+ InputStream zipInputStream = given().basePath(TestHelper.ROOT_PATH).when() //
+ .multiPart(ParameterNames.PROJECTION_PARAMETERS, parameters, MediaType.APPLICATION_JSON) //
+ .multiPart(
+ ParameterNames.POLYGON_INPUT_DATA,
+ Files.readAllBytes(testHelper.getResourceFile(resourceFolderPath, "VDYP7_INPUT_POLY.csv"))
+ ) //
+ .multiPart(
+ ParameterNames.LAYERS_INPUT_DATA,
+ Files.readAllBytes(testHelper.getResourceFile(resourceFolderPath, "VDYP7_INPUT_LAYER.csv"))
+ ) //
+ .post("/projection/hcsv?trialRun=true") //
+ .then().statusCode(201) //
+ .and().contentType("application/octet-stream") //
+ .and().header("content-disposition", Matchers.startsWith("attachment;filename=\"vdyp-output-")) //
+ .extract().body().asInputStream();
+
+ ZipInputStream zipFile = new ZipInputStream(zipInputStream);
+ ZipEntry entry1 = zipFile.getNextEntry();
+ assertEquals("YieldTable.csv", entry1.getName());
+ String entry1Content = new String(testHelper.readZipEntry(zipFile, entry1));
+ assertTrue(entry1Content.length() == 0);
+
+ ZipEntry entry2 = zipFile.getNextEntry();
+ assertEquals("ProgressLog.txt", entry2.getName());
+ String entry2Content = new String(testHelper.readZipEntry(zipFile, entry2));
+ assertTrue(entry2Content.isBlank());
+
+ ZipEntry entry3 = zipFile.getNextEntry();
+ assertEquals("ErrorLog.txt", entry3.getName());
+ String entry3Content = new String(testHelper.readZipEntry(zipFile, entry3));
+ assertTrue(entry3Content.isBlank());
+
+ ZipEntry entry4 = zipFile.getNextEntry();
+ assertEquals("DebugLog.txt", entry4.getName());
+ String entry4Content = new String(testHelper.readZipEntry(zipFile, entry4));
+ assertTrue(entry4Content.isBlank());
+ }
+}
diff --git a/charts/app/templates/frontend/templates/deployment.yaml b/charts/app/templates/frontend/templates/deployment.yaml
index 4ceeecf9b..56134a956 100644
--- a/charts/app/templates/frontend/templates/deployment.yaml
+++ b/charts/app/templates/frontend/templates/deployment.yaml
@@ -47,7 +47,9 @@ spec:
- name: VITE_SSO_REALM
value: {{ .Values.frontend.env.VITE_SSO_REALM | quote }}
- name: VITE_SSO_REDIRECT_URI
- value: {{ .Values.frontend.env.VITE_SSO_REDIRECT_URI | quote }}
+ value: {{ .Values.frontend.env.VITE_SSO_REDIRECT_URI | quote }}
+ - name: VITE_API_URL
+ value: {{ .Values.frontend.env.VITE_API_URL | quote }}
ports:
- name: http
containerPort: 3000
diff --git a/charts/app/values-dev.yaml b/charts/app/values-dev.yaml
index a25c25e9f..1bc5d1e94 100644
--- a/charts/app/values-dev.yaml
+++ b/charts/app/values-dev.yaml
@@ -111,11 +111,12 @@ frontend:
pdb:
enabled: false # enable it in PRODUCTION for having pod disruption budget.
minAvailable: 1 # the minimum number of pods that must be available during the disruption budget.
- env:
+ env:
VITE_SSO_AUTH_SERVER_URL: ~
VITE_SSO_CLIENT_ID: ~
VITE_SSO_REALM: ~
VITE_SSO_REDIRECT_URI: ~
+ VITE_API_URL: ~
crunchy: # enable it for TEST and PROD, for PR based pipelines simply use single postgres
enabled: false
diff --git a/frontend/Caddyfile b/frontend/Caddyfile
index a73702f89..37222e810 100644
--- a/frontend/Caddyfile
+++ b/frontend/Caddyfile
@@ -18,7 +18,7 @@
header {
Content-Type text/javascript
}
- respond `window.config={"VITE_SSO_AUTH_SERVER_URL":"{$VITE_SSO_AUTH_SERVER_URL}", "VITE_SSO_CLIENT_ID":"{$VITE_SSO_CLIENT_ID}", "VITE_SSO_REALM":"{$VITE_SSO_REALM}", "VITE_SSO_REDIRECT_URI":"{$VITE_SSO_REDIRECT_URI}"};`
+ respond `window.config={"VITE_SSO_AUTH_SERVER_URL":"{$VITE_SSO_AUTH_SERVER_URL}", "VITE_SSO_CLIENT_ID":"{$VITE_SSO_CLIENT_ID}", "VITE_SSO_REALM":"{$VITE_SSO_REALM}", "VITE_SSO_REDIRECT_URI":"{$VITE_SSO_REDIRECT_URI}", "VITE_API_URL":"{$VITE_API_URL}"};`
}
root * /srv
encode zstd gzip
@@ -31,10 +31,12 @@
}
rewrite @spa_router {http.matchers.file.relative}
# Proxy requests to API service
- reverse_proxy /api/* {$BACKEND_URL} {
- header_up Host {http.reverse_proxy.upstream.hostport}
- header_up X-Real-IP {remote_host}
- header_up X-Forwarded-For {remote_host}
+ handle_path /api/* {
+ reverse_proxy {$VITE_API_URL} {
+ header_up Host {http.reverse_proxy.upstream.hostport}
+ header_up X-Real-IP {remote_host}
+ header_up X-Forwarded-For {remote_host}
+ }
}
header {
X-Frame-Options "SAMEORIGIN"
@@ -42,7 +44,7 @@
Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate"
X-Content-Type-Options "nosniff"
Strict-Transport-Security "max-age=31536000"
- Content-Security-Policy "default-src 'self' https://spt.apps.gov.bc.ca data:; script-src 'self' 'unsafe-eval' https://www2.gov.bc.ca; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com https://use.fontawesome.com https://cdn.jsdelivr.net; font-src 'self' https://fonts.gstatic.com https://cdn.jsdelivr.net; img-src 'self' data: https://fonts.googleapis.com http://www.w3.org https://*.gov.bc.ca; frame-src 'self' https://dev.loginproxy.gov.bc.ca https://login.microsoftonline.com; connect-src 'self' https://dev.loginproxy.gov.bc.ca"
+ Content-Security-Policy "default-src 'self' https://spt.apps.gov.bc.ca data:; script-src 'self' 'unsafe-eval' https://www2.gov.bc.ca; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com https://use.fontawesome.com https://cdn.jsdelivr.net; font-src 'self' https://fonts.gstatic.com https://cdn.jsdelivr.net; img-src 'self' data: https://fonts.googleapis.com http://www.w3.org https://*.gov.bc.ca; frame-src 'self' https://*.gov.bc.ca https://login.microsoftonline.com; connect-src 'self' https://*.gov.bc.ca"
Referrer-Policy "same-origin"
Feature-Policy "fullscreen 'self'; camera 'none'; microphone 'none'"
}
diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index b032f5990..fa6027b9b 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -18,6 +18,7 @@
"axios": "1.7.7",
"file-saver": "2.0.5",
"http-status-codes": "2.3.0",
+ "jszip": "3.10.1",
"keycloak-js": "25.0.2",
"papaparse": "5.4.1",
"pinia": "2.2.2",
@@ -26,7 +27,6 @@
"vite-plugin-package-version": "1.1.0",
"vue": "3.4.29",
"vue-router": "4.3.3",
- "vue-slider-component": "4.1.0-beta.7",
"vuetify": "3.6.14"
},
"devDependencies": {
@@ -1583,10 +1583,15 @@
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
"dev": true
},
+ "node_modules/core-util-is": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
+ "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="
+ },
"node_modules/cross-spawn": {
- "version": "7.0.3",
- "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
- "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
+ "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
"dev": true,
"dependencies": {
"path-key": "^3.1.0",
@@ -2285,6 +2290,11 @@
"node": ">= 4"
}
},
+ "node_modules/immediate": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
+ "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ=="
+ },
"node_modules/immutable": {
"version": "4.3.7",
"resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.7.tgz",
@@ -2330,8 +2340,7 @@
"node_modules/inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
- "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
- "dev": true
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
"node_modules/is-binary-path": {
"version": "2.1.0",
@@ -2384,6 +2393,11 @@
"node": ">=8"
}
},
+ "node_modules/isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="
+ },
"node_modules/isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
@@ -2434,6 +2448,17 @@
"integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
"dev": true
},
+ "node_modules/jszip": {
+ "version": "3.10.1",
+ "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz",
+ "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==",
+ "dependencies": {
+ "lie": "~3.3.0",
+ "pako": "~1.0.2",
+ "readable-stream": "~2.3.6",
+ "setimmediate": "^1.0.5"
+ }
+ },
"node_modules/jwt-decode": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz",
@@ -2473,6 +2498,14 @@
"node": ">= 0.8.0"
}
},
+ "node_modules/lie": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz",
+ "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==",
+ "dependencies": {
+ "immediate": "~3.0.5"
+ }
+ },
"node_modules/locate-path": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
@@ -2738,6 +2771,11 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/pako": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
+ "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw=="
+ },
"node_modules/papaparse": {
"version": "5.4.1",
"resolved": "https://registry.npmjs.org/papaparse/-/papaparse-5.4.1.tgz",
@@ -2958,6 +2996,11 @@
"resolved": "https://registry.npmjs.org/print-js/-/print-js-1.6.0.tgz",
"integrity": "sha512-BfnOIzSKbqGRtO4o0rnj/K3681BSd2QUrsIZy/+WdCIugjIswjmx3lDEZpXB2ruGf9d4b3YNINri81+J0FsBWg=="
},
+ "node_modules/process-nextick-args": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
+ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
+ },
"node_modules/proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
@@ -3005,6 +3048,20 @@
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
}
},
+ "node_modules/readable-stream": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
+ "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
+ "dependencies": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
"node_modules/readdirp": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
@@ -3111,6 +3168,11 @@
"queue-microtask": "^1.2.2"
}
},
+ "node_modules/safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
+ },
"node_modules/sass": {
"version": "1.77.6",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.77.6.tgz",
@@ -3180,6 +3242,11 @@
"node": ">=10"
}
},
+ "node_modules/setimmediate": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
+ "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA=="
+ },
"node_modules/shebang-command": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
@@ -3227,6 +3294,14 @@
"node": ">=0.10.0"
}
},
+ "node_modules/string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "dependencies": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
"node_modules/strip-ansi": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
@@ -3380,9 +3455,7 @@
"node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
- "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
- "dev": true,
- "peer": true
+ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
},
"node_modules/vdyp": {
"resolved": "",
@@ -3537,11 +3610,6 @@
"vue": "^3.2.0"
}
},
- "node_modules/vue-slider-component": {
- "version": "4.1.0-beta.7",
- "resolved": "https://registry.npmjs.org/vue-slider-component/-/vue-slider-component-4.1.0-beta.7.tgz",
- "integrity": "sha512-Qb7K920ZG7PoQswoF6Ias+i3W2rd3k4fpk04JUl82kEUcN86Yg6et7bVSKWt/7VpQe8a5IT3BqCKSCOZ7AJgCA=="
- },
"node_modules/vue-tsc": {
"version": "2.1.10",
"resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-2.1.10.tgz",
diff --git a/frontend/package.json b/frontend/package.json
index d1897f2f8..6b38ea6a4 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -27,6 +27,7 @@
"axios": "1.7.7",
"file-saver": "2.0.5",
"http-status-codes": "2.3.0",
+ "jszip": "3.10.1",
"keycloak-js": "25.0.2",
"papaparse": "5.4.1",
"pinia": "2.2.2",
@@ -35,7 +36,6 @@
"vite-plugin-package-version": "1.1.0",
"vue": "3.4.29",
"vue-router": "4.3.3",
- "vue-slider-component": "4.1.0-beta.7",
"vuetify": "3.6.14"
},
"devDependencies": {
diff --git a/frontend/src/components/JobTypeSelection.vue b/frontend/src/components/JobTypeSelection.vue
index 462f57bcd..e314c0eb6 100644
--- a/frontend/src/components/JobTypeSelection.vue
+++ b/frontend/src/components/JobTypeSelection.vue
@@ -4,8 +4,8 @@
=> {
- const response = await get(
- `/codeTables/${codeTableName}/codes/${codeName}`,
- )
-
- if (!response || !response.status || !response.data || !response.headers) {
- console.warn('Unexpected response format or status')
- return null
- }
-
- if (response.status === StatusCodes.OK) {
- const codeJson = response.data
- const etagQuoted = response.headers['etag']
- const etag = etagQuoted ? parseInt(etagQuoted.replace(/"/g, '')) : 0
-
- return new Code({ ...codeJson, codeTableName, etagQuoted, etag })
- } else {
- return null
- }
-}
diff --git a/frontend/src/services/apiFetchAxios.ts b/frontend/src/services/apiFetchAxios.ts
new file mode 100644
index 000000000..8cdca4cf3
--- /dev/null
+++ b/frontend/src/services/apiFetchAxios.ts
@@ -0,0 +1,44 @@
+import axiosInstance from './axiosInstance'
+import { StatusCodes } from 'http-status-codes'
+
+export default class ApiFetchAxios {
+ static async getHelp(): Promise {
+ const response = await axiosInstance.get('/api/v8/help')
+
+ if (!response || !response.status || !response.data) {
+ console.warn('Unexpected response format or status')
+ return null
+ }
+
+ return response.status === StatusCodes.OK ? response.data : null
+ }
+
+ static async projectionHcsvPost(): Promise {
+ const body = {
+ projectionParameters: {
+ startingAge: null,
+ finishingAge: null,
+ ageIncrement: null,
+ },
+ layerInputData: null,
+ polygonInputData: null,
+ }
+
+ const response = await axiosInstance.post(
+ '/api/v8/projection/hcsv',
+ body,
+ {
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ responseType: 'blob',
+ },
+ )
+
+ if (response.status === StatusCodes.CREATED) {
+ return response.data
+ } else {
+ throw new Error(`Unexpected status code: ${response.status}`)
+ }
+ }
+}
diff --git a/frontend/src/services/apiFetchDirect.ts b/frontend/src/services/apiFetchDirect.ts
new file mode 100644
index 000000000..133df1d94
--- /dev/null
+++ b/frontend/src/services/apiFetchDirect.ts
@@ -0,0 +1,85 @@
+import { StatusCodes } from 'http-status-codes'
+import { useAuthStore } from '@/stores/common/authStore'
+
+export default class ApiFetchDirect {
+ getRequest(path: string, headers: any): Promise {
+ return this.request(path, 'GET', null, headers)
+ }
+
+ request(
+ path: string,
+ type: string,
+ body: any,
+ headers: any,
+ ): Promise {
+ const request: any = {
+ method: type,
+ headers: headers,
+ }
+
+ if (body && (type === 'POST' || type === 'PUT')) {
+ request.body = JSON.stringify(body)
+ }
+
+ console.log(`path: ${path}`)
+ console.log(`request: ${JSON.stringify(request)}`)
+
+ return fetch(path, request)
+ }
+
+ async getHelp(): Promise {
+ const apiUrl = '/api/v8/help'
+ const authStore = useAuthStore()
+ let token
+ if (authStore && authStore.user && authStore.user.accessToken) {
+ token = authStore.user.accessToken
+ } else {
+ console.warn('Authorization token or authStore is not available.')
+ }
+ console.log(token)
+
+ const response = await this.getRequest(apiUrl, {
+ 'Content-Type': 'application/json',
+ Authorization: `Bearer ${token}`,
+ })
+
+ if (response.status === StatusCodes.OK) {
+ return response.json()
+ } else {
+ return null
+ }
+ }
+
+ async projectionHcsvPost(): Promise {
+ const apiUrl = '/api/v8/projection/hcsv'
+ const authStore = useAuthStore()
+ let token
+
+ if (authStore && authStore.user && authStore.user.accessToken) {
+ token = authStore.user.accessToken
+ } else {
+ console.warn('Authorization token or authStore is not available.')
+ }
+
+ const body = {
+ projectionParameters: {
+ startingAge: null,
+ finishingAge: null,
+ ageIncrement: null,
+ },
+ layerInputData: null,
+ polygonInputData: null,
+ }
+
+ const response = await this.request(apiUrl, 'POST', body, {
+ 'Content-Type': 'application/json',
+ Authorization: `Bearer ${token}`,
+ })
+
+ if (response.status === StatusCodes.CREATED) {
+ return response.blob()
+ } else {
+ throw new Error(`Error: ${response.status} ${response.statusText}`)
+ }
+ }
+}
diff --git a/frontend/src/services/apiModules.ts b/frontend/src/services/apiModules.ts
deleted file mode 100644
index 5b5878a50..000000000
--- a/frontend/src/services/apiModules.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import * as apiSearch from './apiSearch'
-import * as apiFetch from './apiFetch'
-import * as apiCreate from './apiCreate'
-import * as apiUpdate from './apiUpdate'
-import * as apiDelete from './apiDelete'
-
-export const API = {
- search: apiSearch,
- fetch: apiFetch,
- create: apiCreate,
- update: apiUpdate,
- delete: apiDelete,
-}
diff --git a/frontend/src/services/apiSearch.ts b/frontend/src/services/apiSearch.ts
deleted file mode 100644
index 2fcd6ce94..000000000
--- a/frontend/src/services/apiSearch.ts
+++ /dev/null
@@ -1,52 +0,0 @@
-import { get } from '@/services/apiService'
-import type { CodeSearchParams } from '@/interfaces/interfaces'
-
-function buildQueryString(params: Record): string {
- const query = Object.entries(params)
- .filter(([, value]) => value !== undefined && value !== null)
- .map(
- ([key, value]) =>
- `${encodeURIComponent(key)}=${encodeURIComponent(value)}`,
- )
- .join('&')
-
- return query ? `?${query}` : ''
-}
-
-export const code = async (param: CodeSearchParams): Promise => {
- const queryString = buildQueryString({
- pageNumber:
- typeof param.pageNumber === 'number' && param.pageNumber >= 0
- ? param.pageNumber
- : 0,
- pageSize:
- typeof param.pageSize === 'number' && param.pageSize >= 0
- ? param.pageSize
- : 10,
- })
-
- const response = await get(`/codeTables${queryString}`)
- if (!response || !response.data) {
- console.warn('Unexpected response format')
- return null
- }
-
- return response.data
-}
-
-export const csvExport = async (): Promise => {
- const response = await get(`/contactsExport?exportOption=All`, {
- headers: {
- Accept: 'text/csv',
- },
- responseType: 'blob',
- timeout: 5000,
- })
-
- if (!response || !response.data) {
- console.warn('Unexpected response format')
- return null
- }
-
- return response.data
-}
diff --git a/frontend/src/services/apiService.ts b/frontend/src/services/apiService.ts
deleted file mode 100644
index 00bafe3d9..000000000
--- a/frontend/src/services/apiService.ts
+++ /dev/null
@@ -1,32 +0,0 @@
-import axiosInstance from './axiosInstance'
-import type { AxiosRequestConfig, AxiosResponse } from 'axios'
-
-export const get = async (
- url: string,
- config?: AxiosRequestConfig,
-): Promise> => {
- return axiosInstance.get(url, config)
-}
-
-export const post = async (
- url: string,
- data: any,
- config?: AxiosRequestConfig,
-): Promise> => {
- return axiosInstance.post(url, data, config)
-}
-
-export const put = async (
- url: string,
- data: any,
- config?: AxiosRequestConfig,
-): Promise> => {
- return axiosInstance.put(url, data, config)
-}
-
-export const del = async (
- url: string,
- config?: AxiosRequestConfig,
-): Promise> => {
- return axiosInstance.delete(url, config)
-}
diff --git a/frontend/src/services/apiUpdate.ts b/frontend/src/services/apiUpdate.ts
deleted file mode 100644
index 7e2f33fe0..000000000
--- a/frontend/src/services/apiUpdate.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-import { put } from '@/services/apiService'
-import Code from '@/models/code'
-
-export const code = async (code: Code, ifMatch: string): Promise => {
- if (!code || !code.codeTableName || !code.codeName) {
- console.warn('Invalid Code object or missing required properties')
- return null
- }
-
- const config = {
- headers: {
- 'If-Match': `"${ifMatch}"`,
- },
- }
-
- return put(
- `/codeTables/${code.codeTableName}/codes/${code.codeName}`,
- code,
- config,
- )
-}
diff --git a/frontend/src/services/axiosInstance.ts b/frontend/src/services/axiosInstance.ts
index ff54afe46..885600431 100644
--- a/frontend/src/services/axiosInstance.ts
+++ b/frontend/src/services/axiosInstance.ts
@@ -6,10 +6,10 @@ import type {
} from 'axios'
import { useAuthStore } from '@/stores/common/authStore'
import { AXIOS } from '@/constants/constants'
-import { env } from '@/env'
+import { logErrorMessage } from '@/utils/messageHandler'
+import { AXIOS_INST_ERR } from '@/constants/message'
const axiosInstance: AxiosInstance = axios.create({
- baseURL: env.VITE_API_BASE_URL,
headers: {
Accept: AXIOS.ACCEPT,
'Content-Type': AXIOS.CONTENT_TYPE,
@@ -30,7 +30,10 @@ axiosInstance.interceptors.request.use(
config.headers.Authorization = `Bearer ${token}`
}
} else {
- console.warn('Authorization token or authStore is not available.')
+ logErrorMessage(
+ AXIOS_INST_ERR.SESSION_INACTIVE,
+ 'Authorization token or authStore is not available.',
+ )
}
return config
diff --git a/frontend/src/services/vdyp-api/api.ts b/frontend/src/services/vdyp-api/api.ts
new file mode 100644
index 000000000..97f4bc0c5
--- /dev/null
+++ b/frontend/src/services/vdyp-api/api.ts
@@ -0,0 +1,5 @@
+/* tslint:disable */
+/* eslint-disable */
+export * from './apis/help-endpoint-api'
+export * from './apis/projection-endpoint-api'
+export * from './apis/root-endpoint-api'
diff --git a/frontend/src/services/vdyp-api/apis/help-endpoint-api.ts b/frontend/src/services/vdyp-api/apis/help-endpoint-api.ts
new file mode 100644
index 000000000..994f64b1d
--- /dev/null
+++ b/frontend/src/services/vdyp-api/apis/help-endpoint-api.ts
@@ -0,0 +1,151 @@
+/* tslint:disable */
+/* eslint-disable */
+import globalAxios from 'axios'
+import type { AxiosResponse, AxiosInstance, AxiosRequestConfig } from 'axios'
+import { Configuration } from '../configuration'
+// Some imports not used depending on template conditions
+// @ts-ignore
+import { BASE_PATH, COLLECTION_FORMATS, BaseAPI, RequiredError } from '../base'
+import type { RequestArgs } from '../base'
+import type { ParameterDetailsMessage } from '../models'
+
+/**
+ * HelpEndpointApi - axios parameter creator
+ * @export
+ */
+export const HelpEndpointApiAxiosParamCreator = function (
+ configuration?: Configuration,
+) {
+ return {
+ /**
+ *
+ * @param {*} [options] Override http request option.
+ * @throws {RequiredError}
+ */
+ v8HelpGet: async (
+ options: AxiosRequestConfig = {},
+ ): Promise => {
+ const localVarPath = `/api/v8/help` /* edited */
+ // use dummy base URL string because the URL constructor only accepts absolute URLs.
+ const localVarUrlObj = new URL(localVarPath, 'https://example.com')
+ let baseOptions
+ if (configuration) {
+ baseOptions = configuration.baseOptions
+ }
+ const localVarRequestOptions: AxiosRequestConfig = {
+ method: 'GET',
+ ...baseOptions,
+ ...options,
+ responseType: 'json' /* edited */,
+ }
+ const localVarHeaderParameter = {} as any
+ const localVarQueryParameter = {} as any
+
+ const query = new URLSearchParams(localVarUrlObj.search)
+ for (const key in localVarQueryParameter) {
+ query.set(key, localVarQueryParameter[key])
+ }
+ for (const key in options.params) {
+ query.set(key, options.params[key])
+ }
+ localVarUrlObj.search = new URLSearchParams(query).toString()
+ let headersFromBaseOptions =
+ baseOptions && baseOptions.headers ? baseOptions.headers : {}
+ localVarRequestOptions.headers = {
+ ...localVarHeaderParameter,
+ ...headersFromBaseOptions,
+ ...options.headers,
+ }
+
+ return {
+ url:
+ localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
+ options: localVarRequestOptions,
+ }
+ },
+ }
+}
+
+/**
+ * HelpEndpointApi - functional programming interface
+ * @export
+ */
+export const HelpEndpointApiFp = function (configuration?: Configuration) {
+ return {
+ /**
+ *
+ * @param {*} [options] Override http request option.
+ * @throws {RequiredError}
+ */
+ async v8HelpGet(
+ options?: AxiosRequestConfig,
+ ): Promise<
+ (
+ axios?: AxiosInstance,
+ basePath?: string,
+ ) => Promise >
+ > {
+ const localVarAxiosArgs =
+ await HelpEndpointApiAxiosParamCreator(configuration).v8HelpGet(options)
+ return (
+ axios: AxiosInstance = globalAxios,
+ basePath: string = BASE_PATH,
+ ) => {
+ const axiosRequestArgs: AxiosRequestConfig = {
+ ...localVarAxiosArgs.options,
+ url: /* edited */ localVarAxiosArgs.url,
+ }
+ return axios.request (
+ axiosRequestArgs,
+ )
+ }
+ },
+ }
+}
+
+/**
+ * HelpEndpointApi - factory interface
+ * @export
+ */
+export const HelpEndpointApiFactory = function (
+ configuration?: Configuration,
+ basePath?: string,
+ axios?: AxiosInstance,
+) {
+ return {
+ /**
+ *
+ * @param {*} [options] Override http request option.
+ * @throws {RequiredError}
+ */
+ async v8HelpGet(
+ options?: AxiosRequestConfig,
+ ): Promise > {
+ return HelpEndpointApiFp(configuration)
+ .v8HelpGet(options)
+ .then((request) => request(axios /* edited */))
+ },
+ }
+}
+
+/**
+ * HelpEndpointApi - object-oriented interface
+ * @export
+ * @class HelpEndpointApi
+ * @extends {BaseAPI}
+ */
+export class HelpEndpointApi extends BaseAPI {
+ /**
+ *
+ * @param {*} [options] Override http request option.
+ * @throws {RequiredError}
+ * @memberof HelpEndpointApi
+ */
+ public async v8HelpGet(
+ options?: AxiosRequestConfig,
+ ): Promise > {
+ return HelpEndpointApiFp(this.configuration)
+ .v8HelpGet(options)
+ .then((request) => request(this.axios /* edited */))
+ }
+}
diff --git a/frontend/src/services/vdyp-api/apis/projection-endpoint-api.ts b/frontend/src/services/vdyp-api/apis/projection-endpoint-api.ts
new file mode 100644
index 000000000..24aa183ae
--- /dev/null
+++ b/frontend/src/services/vdyp-api/apis/projection-endpoint-api.ts
@@ -0,0 +1,395 @@
+/* tslint:disable */
+/* eslint-disable */
+import globalAxios from 'axios'
+import type { AxiosResponse, AxiosInstance, AxiosRequestConfig } from 'axios'
+import { Configuration } from '../configuration'
+// Some imports not used depending on template conditions
+// @ts-ignore
+import { BASE_PATH, COLLECTION_FORMATS, BaseAPI, RequiredError } from '../base'
+import type { RequestArgs } from '../base'
+import type {
+ ProjectionDcsvPostRequest,
+ ProjectionHcsvPostRequest,
+ ProjectionScsvPostRequest,
+} from '../models'
+
+/**
+ * ProjectionEndpointApi - axios parameter creator
+ * @export
+ */
+export const ProjectionEndpointApiAxiosParamCreator = function (
+ configuration?: Configuration,
+) {
+ return {
+ /**
+ *
+ * @param {ProjectionDcsvPostRequest} [body]
+ * @param {*} [options] Override http request option.
+ * @throws {RequiredError}
+ */
+ v8ProjectionDcsvPost: async (
+ body?: ProjectionDcsvPostRequest,
+ options: AxiosRequestConfig = {},
+ ): Promise => {
+ const localVarPath = `/v8/projection/dcsv`
+ // use dummy base URL string because the URL constructor only accepts absolute URLs.
+ const localVarUrlObj = new URL(localVarPath, 'https://example.com')
+ let baseOptions
+ if (configuration) {
+ baseOptions = configuration.baseOptions
+ }
+ const localVarRequestOptions: AxiosRequestConfig = {
+ method: 'POST',
+ ...baseOptions,
+ ...options,
+ }
+ const localVarHeaderParameter = {} as any
+ const localVarQueryParameter = {} as any
+
+ localVarHeaderParameter['Content-Type'] = 'application/json'
+
+ const query = new URLSearchParams(localVarUrlObj.search)
+ for (const key in localVarQueryParameter) {
+ query.set(key, localVarQueryParameter[key])
+ }
+ for (const key in options.params) {
+ query.set(key, options.params[key])
+ }
+ localVarUrlObj.search = new URLSearchParams(query).toString()
+ let headersFromBaseOptions =
+ baseOptions && baseOptions.headers ? baseOptions.headers : {}
+ localVarRequestOptions.headers = {
+ ...localVarHeaderParameter,
+ ...headersFromBaseOptions,
+ ...options.headers,
+ }
+ const needsSerialization =
+ typeof body !== 'string' ||
+ (localVarRequestOptions.headers &&
+ localVarRequestOptions.headers['Content-Type'] === 'application/json')
+ localVarRequestOptions.data = needsSerialization
+ ? JSON.stringify(body !== undefined ? body : {})
+ : body || ''
+
+ return {
+ url:
+ localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
+ options: localVarRequestOptions,
+ }
+ },
+ /**
+ *
+ * @param {ProjectionHcsvPostRequest} [body]
+ * @param {*} [options] Override http request option.
+ * @throws {RequiredError}
+ */
+ v8ProjectionHcsvPost: async (
+ body?: ProjectionHcsvPostRequest,
+ options: AxiosRequestConfig = {},
+ ): Promise => {
+ const localVarPath = `/api/v8/projection/hcsv` /* edited */
+ // use dummy base URL string because the URL constructor only accepts absolute URLs.
+ const localVarUrlObj = new URL(localVarPath, 'https://example.com')
+ let baseOptions
+ if (configuration) {
+ baseOptions = configuration.baseOptions
+ }
+ const localVarRequestOptions: AxiosRequestConfig = {
+ method: 'POST',
+ ...baseOptions,
+ ...options,
+ responseType: 'blob' /* edited */,
+ }
+ const localVarHeaderParameter = {} as any
+ const localVarQueryParameter = {} as any
+
+ localVarHeaderParameter['Content-Type'] = 'application/json'
+
+ const query = new URLSearchParams(localVarUrlObj.search)
+ for (const key in localVarQueryParameter) {
+ query.set(key, localVarQueryParameter[key])
+ }
+ for (const key in options.params) {
+ query.set(key, options.params[key])
+ }
+ localVarUrlObj.search = new URLSearchParams(query).toString()
+ let headersFromBaseOptions =
+ baseOptions && baseOptions.headers ? baseOptions.headers : {}
+ localVarRequestOptions.headers = {
+ ...localVarHeaderParameter,
+ ...headersFromBaseOptions,
+ ...options.headers,
+ }
+ const needsSerialization =
+ typeof body !== 'string' ||
+ (localVarRequestOptions.headers &&
+ localVarRequestOptions.headers['Content-Type'] === 'application/json')
+ localVarRequestOptions.data = needsSerialization
+ ? JSON.stringify(body !== undefined ? body : {})
+ : body || ''
+
+ return {
+ url:
+ localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
+ options: localVarRequestOptions,
+ }
+ },
+ /**
+ *
+ * @param {ProjectionScsvPostRequest} [body]
+ * @param {*} [options] Override http request option.
+ * @throws {RequiredError}
+ */
+ v8ProjectionScsvPost: async (
+ body?: ProjectionScsvPostRequest,
+ options: AxiosRequestConfig = {},
+ ): Promise => {
+ const localVarPath = `/v8/projection/scsv`
+ // use dummy base URL string because the URL constructor only accepts absolute URLs.
+ const localVarUrlObj = new URL(localVarPath, 'https://example.com')
+ let baseOptions
+ if (configuration) {
+ baseOptions = configuration.baseOptions
+ }
+ const localVarRequestOptions: AxiosRequestConfig = {
+ method: 'POST',
+ ...baseOptions,
+ ...options,
+ }
+ const localVarHeaderParameter = {} as any
+ const localVarQueryParameter = {} as any
+
+ localVarHeaderParameter['Content-Type'] = 'application/json'
+
+ const query = new URLSearchParams(localVarUrlObj.search)
+ for (const key in localVarQueryParameter) {
+ query.set(key, localVarQueryParameter[key])
+ }
+ for (const key in options.params) {
+ query.set(key, options.params[key])
+ }
+ localVarUrlObj.search = new URLSearchParams(query).toString()
+ let headersFromBaseOptions =
+ baseOptions && baseOptions.headers ? baseOptions.headers : {}
+ localVarRequestOptions.headers = {
+ ...localVarHeaderParameter,
+ ...headersFromBaseOptions,
+ ...options.headers,
+ }
+ const needsSerialization =
+ typeof body !== 'string' ||
+ (localVarRequestOptions.headers &&
+ localVarRequestOptions.headers['Content-Type'] === 'application/json')
+ localVarRequestOptions.data = needsSerialization
+ ? JSON.stringify(body !== undefined ? body : {})
+ : body || ''
+
+ return {
+ url:
+ localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
+ options: localVarRequestOptions,
+ }
+ },
+ }
+}
+
+/**
+ * ProjectionEndpointApi - functional programming interface
+ * @export
+ */
+export const ProjectionEndpointApiFp = function (
+ configuration?: Configuration,
+) {
+ return {
+ /**
+ *
+ * @param {ProjectionDcsvPostRequest} [body]
+ * @param {*} [options] Override http request option.
+ * @throws {RequiredError}
+ */
+ async v8ProjectionDcsvPost(
+ body?: ProjectionDcsvPostRequest,
+ options?: AxiosRequestConfig,
+ ): Promise<
+ (axios?: AxiosInstance, basePath?: string) => Promise>
+ > {
+ const localVarAxiosArgs = await ProjectionEndpointApiAxiosParamCreator(
+ configuration,
+ ).v8ProjectionDcsvPost(body, options)
+ return (
+ axios: AxiosInstance = globalAxios,
+ basePath: string = BASE_PATH,
+ ) => {
+ const axiosRequestArgs: AxiosRequestConfig = {
+ ...localVarAxiosArgs.options,
+ url: basePath + localVarAxiosArgs.url,
+ }
+ return axios.request(axiosRequestArgs)
+ }
+ },
+ /**
+ *
+ * @param {ProjectionHcsvPostRequest} [body]
+ * @param {*} [options] Override http request option.
+ * @throws {RequiredError}
+ */
+ async v8ProjectionHcsvPost(
+ body?: ProjectionHcsvPostRequest,
+ options?: AxiosRequestConfig,
+ ): Promise<
+ (
+ axios?: AxiosInstance,
+ basePath?: string,
+ ) => Promise> /* edited */
+ > {
+ const localVarAxiosArgs = await ProjectionEndpointApiAxiosParamCreator(
+ configuration,
+ ).v8ProjectionHcsvPost(body, options)
+ return (
+ axios: AxiosInstance = globalAxios,
+ basePath: string = BASE_PATH,
+ ) => {
+ const axiosRequestArgs: AxiosRequestConfig = {
+ ...localVarAxiosArgs.options,
+ url: /* edited */ localVarAxiosArgs.url,
+ }
+ return axios.request(axiosRequestArgs)
+ }
+ },
+ /**
+ *
+ * @param {ProjectionScsvPostRequest} [body]
+ * @param {*} [options] Override http request option.
+ * @throws {RequiredError}
+ */
+ async v8ProjectionScsvPost(
+ body?: ProjectionScsvPostRequest,
+ options?: AxiosRequestConfig,
+ ): Promise<
+ (axios?: AxiosInstance, basePath?: string) => Promise>
+ > {
+ const localVarAxiosArgs = await ProjectionEndpointApiAxiosParamCreator(
+ configuration,
+ ).v8ProjectionScsvPost(body, options)
+ return (
+ axios: AxiosInstance = globalAxios,
+ basePath: string = BASE_PATH,
+ ) => {
+ const axiosRequestArgs: AxiosRequestConfig = {
+ ...localVarAxiosArgs.options,
+ url: basePath + localVarAxiosArgs.url,
+ }
+ return axios.request(axiosRequestArgs)
+ }
+ },
+ }
+}
+
+/**
+ * ProjectionEndpointApi - factory interface
+ * @export
+ */
+export const ProjectionEndpointApiFactory = function (
+ configuration?: Configuration,
+ basePath?: string,
+ axios?: AxiosInstance,
+) {
+ return {
+ /**
+ *
+ * @param {ProjectionDcsvPostRequest} [body]
+ * @param {*} [options] Override http request option.
+ * @throws {RequiredError}
+ */
+ async v8ProjectionDcsvPost(
+ body?: ProjectionDcsvPostRequest,
+ options?: AxiosRequestConfig,
+ ): Promise> {
+ return ProjectionEndpointApiFp(configuration)
+ .v8ProjectionDcsvPost(body, options)
+ .then((request) => request(axios, basePath))
+ },
+ /**
+ *
+ * @param {ProjectionHcsvPostRequest} [body]
+ * @param {*} [options] Override http request option.
+ * @throws {RequiredError}
+ */
+ async v8ProjectionHcsvPost(
+ body?: ProjectionHcsvPostRequest,
+ options?: AxiosRequestConfig,
+ ): Promise> {
+ return ProjectionEndpointApiFp(configuration)
+ .v8ProjectionHcsvPost(body, options)
+ .then((request) => request(axios /* edited */))
+ },
+ /**
+ *
+ * @param {ProjectionScsvPostRequest} [body]
+ * @param {*} [options] Override http request option.
+ * @throws {RequiredError}
+ */
+ async v8ProjectionScsvPost(
+ body?: ProjectionScsvPostRequest,
+ options?: AxiosRequestConfig,
+ ): Promise> {
+ return ProjectionEndpointApiFp(configuration)
+ .v8ProjectionScsvPost(body, options)
+ .then((request) => request(axios, basePath))
+ },
+ }
+}
+
+/**
+ * ProjectionEndpointApi - object-oriented interface
+ * @export
+ * @class ProjectionEndpointApi
+ * @extends {BaseAPI}
+ */
+export class ProjectionEndpointApi extends BaseAPI {
+ /**
+ *
+ * @param {ProjectionDcsvPostRequest} [body]
+ * @param {*} [options] Override http request option.
+ * @throws {RequiredError}
+ * @memberof ProjectionEndpointApi
+ */
+ public async v8ProjectionDcsvPost(
+ body?: ProjectionDcsvPostRequest,
+ options?: AxiosRequestConfig,
+ ): Promise> {
+ return ProjectionEndpointApiFp(this.configuration)
+ .v8ProjectionDcsvPost(body, options)
+ .then((request) => request(this.axios, this.basePath))
+ }
+ /**
+ *
+ * @param {ProjectionHcsvPostRequest} [body]
+ * @param {*} [options] Override http request option.
+ * @throws {RequiredError}
+ * @memberof ProjectionEndpointApi
+ */
+ public async v8ProjectionHcsvPost(
+ body?: ProjectionHcsvPostRequest,
+ options?: AxiosRequestConfig,
+ ): Promise> /* edited */ {
+ return ProjectionEndpointApiFp(this.configuration)
+ .v8ProjectionHcsvPost(body, options)
+ .then((request) => request(this.axios /* edited */))
+ }
+ /**
+ *
+ * @param {ProjectionScsvPostRequest} [body]
+ * @param {*} [options] Override http request option.
+ * @throws {RequiredError}
+ * @memberof ProjectionEndpointApi
+ */
+ public async v8ProjectionScsvPost(
+ body?: ProjectionScsvPostRequest,
+ options?: AxiosRequestConfig,
+ ): Promise> {
+ return ProjectionEndpointApiFp(this.configuration)
+ .v8ProjectionScsvPost(body, options)
+ .then((request) => request(this.axios, this.basePath))
+ }
+}
diff --git a/frontend/src/services/vdyp-api/apis/root-endpoint-api.ts b/frontend/src/services/vdyp-api/apis/root-endpoint-api.ts
new file mode 100644
index 000000000..874bd6460
--- /dev/null
+++ b/frontend/src/services/vdyp-api/apis/root-endpoint-api.ts
@@ -0,0 +1,139 @@
+/* tslint:disable */
+/* eslint-disable */
+import globalAxios from 'axios'
+import type { AxiosResponse, AxiosInstance, AxiosRequestConfig } from 'axios'
+import { Configuration } from '../configuration'
+// Some imports not used depending on template conditions
+// @ts-ignore
+import { BASE_PATH, COLLECTION_FORMATS, BaseAPI, RequiredError } from '../base'
+import type { RequestArgs } from '../base'
+/**
+ * RootEndpointApi - axios parameter creator
+ * @export
+ */
+export const RootEndpointApiAxiosParamCreator = function (
+ configuration?: Configuration,
+) {
+ return {
+ /**
+ *
+ * @param {*} [options] Override http request option.
+ * @throws {RequiredError}
+ */
+ v8Get: async (options: AxiosRequestConfig = {}): Promise => {
+ const localVarPath = `/api/v8` /* edited */
+ // use dummy base URL string because the URL constructor only accepts absolute URLs.
+ const localVarUrlObj = new URL(localVarPath, 'https://example.com')
+ let baseOptions
+ if (configuration) {
+ baseOptions = configuration.baseOptions
+ }
+ const localVarRequestOptions: AxiosRequestConfig = {
+ method: 'GET',
+ ...baseOptions,
+ ...options,
+ }
+ const localVarHeaderParameter = {} as any
+ const localVarQueryParameter = {} as any
+
+ const query = new URLSearchParams(localVarUrlObj.search)
+ for (const key in localVarQueryParameter) {
+ query.set(key, localVarQueryParameter[key])
+ }
+ for (const key in options.params) {
+ query.set(key, options.params[key])
+ }
+ localVarUrlObj.search = new URLSearchParams(query).toString()
+ let headersFromBaseOptions =
+ baseOptions && baseOptions.headers ? baseOptions.headers : {}
+ localVarRequestOptions.headers = {
+ ...localVarHeaderParameter,
+ ...headersFromBaseOptions,
+ ...options.headers,
+ }
+
+ return {
+ url:
+ localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
+ options: localVarRequestOptions,
+ }
+ },
+ }
+}
+
+/**
+ * RootEndpointApi - functional programming interface
+ * @export
+ */
+export const RootEndpointApiFp = function (configuration?: Configuration) {
+ return {
+ /**
+ *
+ * @param {*} [options] Override http request option.
+ * @throws {RequiredError}
+ */
+ async v8Get(
+ options?: AxiosRequestConfig,
+ ): Promise<
+ (axios?: AxiosInstance, basePath?: string) => Promise>
+ > {
+ const localVarAxiosArgs =
+ await RootEndpointApiAxiosParamCreator(configuration).v8Get(options)
+ return (
+ axios: AxiosInstance = globalAxios,
+ basePath: string = BASE_PATH,
+ ) => {
+ const axiosRequestArgs: AxiosRequestConfig = {
+ ...localVarAxiosArgs.options,
+ url: /* edited */ localVarAxiosArgs.url,
+ }
+ return axios.request(axiosRequestArgs)
+ }
+ },
+ }
+}
+
+/**
+ * RootEndpointApi - factory interface
+ * @export
+ */
+export const RootEndpointApiFactory = function (
+ configuration?: Configuration,
+ basePath?: string,
+ axios?: AxiosInstance,
+) {
+ return {
+ /**
+ *
+ * @param {*} [options] Override http request option.
+ * @throws {RequiredError}
+ */
+ async v8Get(options?: AxiosRequestConfig): Promise> {
+ return RootEndpointApiFp(configuration)
+ .v8Get(options)
+ .then((request) => request(axios /* edited */))
+ },
+ }
+}
+
+/**
+ * RootEndpointApi - object-oriented interface
+ * @export
+ * @class RootEndpointApi
+ * @extends {BaseAPI}
+ */
+export class RootEndpointApi extends BaseAPI {
+ /**
+ *
+ * @param {*} [options] Override http request option.
+ * @throws {RequiredError}
+ * @memberof RootEndpointApi
+ */
+ public async v8Get(
+ options?: AxiosRequestConfig,
+ ): Promise> {
+ return RootEndpointApiFp(this.configuration)
+ .v8Get(options)
+ .then((request) => request(this.axios /* edited */))
+ }
+}
diff --git a/frontend/src/services/vdyp-api/base.ts b/frontend/src/services/vdyp-api/base.ts
new file mode 100644
index 000000000..94cb189a0
--- /dev/null
+++ b/frontend/src/services/vdyp-api/base.ts
@@ -0,0 +1,67 @@
+/* tslint:disable */
+/* eslint-disable */
+import { Configuration } from './configuration'
+// Some imports not used depending on template conditions
+// @ts-ignore
+import globalAxios from 'axios'
+import type { AxiosRequestConfig, AxiosInstance } from 'axios'
+import { env } from '@/env'
+
+export const BASE_PATH = env.VITE_API_URL.replace(/\/+$/, '')
+
+/**
+ *
+ * @export
+ */
+export const COLLECTION_FORMATS = {
+ csv: ',',
+ ssv: ' ',
+ tsv: '\t',
+ pipes: '|',
+}
+
+/**
+ *
+ * @export
+ * @interface RequestArgs
+ */
+export interface RequestArgs {
+ url: string
+ options: AxiosRequestConfig
+}
+
+/**
+ *
+ * @export
+ * @class BaseAPI
+ */
+export class BaseAPI {
+ protected configuration: Configuration | undefined
+
+ constructor(
+ configuration?: Configuration,
+ protected basePath: string = BASE_PATH,
+ protected axios: AxiosInstance = globalAxios,
+ ) {
+ if (configuration) {
+ this.configuration = configuration
+ this.basePath = configuration.basePath || this.basePath
+ }
+ }
+}
+
+/**
+ *
+ * @export
+ * @class RequiredError
+ * @extends {Error}
+ */
+export class RequiredError extends Error {
+ name: 'RequiredError' = 'RequiredError'
+ constructor(
+ public field: string,
+ msg?: string,
+ ) {
+ super(msg)
+ }
+}
diff --git a/frontend/src/services/vdyp-api/configuration.ts b/frontend/src/services/vdyp-api/configuration.ts
new file mode 100644
index 000000000..d146482ee
--- /dev/null
+++ b/frontend/src/services/vdyp-api/configuration.ts
@@ -0,0 +1,86 @@
+/* tslint:disable */
+/* eslint-disable */
+export interface ConfigurationParameters {
+ apiKey?:
+ | string
+ | Promise
+ | ((name: string) => string)
+ | ((name: string) => Promise)
+ username?: string
+ password?: string
+ accessToken?:
+ | string
+ | Promise
+ | ((name?: string, scopes?: string[]) => string)
+ | ((name?: string, scopes?: string[]) => Promise)
+ basePath?: string
+ baseOptions?: any
+}
+
+export class Configuration {
+ /**
+ * parameter for apiKey security
+ *
+ * @param name security name
+ * @memberof Configuration
+ */
+ apiKey?:
+ | string
+ | Promise
+ | ((name: string) => string)
+ | ((name: string) => Promise)
+
+ /**
+ * parameter for basic security
+ *
+ * @type {string}
+ * @memberof Configuration
+ */
+ username?: string
+
+ /**
+ * parameter for basic security
+ *
+ * @type {string}
+ * @memberof Configuration
+ */
+ password?: string
+
+ /**
+ * parameter for oauth2 security
+ *
+ * @param name security name
+ * @param scopes oauth2 scope
+ * @memberof Configuration
+ */
+ accessToken?:
+ | string
+ | Promise
+ | ((name?: string, scopes?: string[]) => string)
+ | ((name?: string, scopes?: string[]) => Promise)
+
+ /**
+ * override base path
+ *
+ * @type {string}
+ * @memberof Configuration
+ */
+ basePath?: string
+
+ /**
+ * base options for axios calls
+ *
+ * @type {any}
+ * @memberof Configuration
+ */
+ baseOptions?: any
+
+ constructor(param: ConfigurationParameters = {}) {
+ this.apiKey = param.apiKey
+ this.username = param.username
+ this.password = param.password
+ this.accessToken = param.accessToken
+ this.basePath = param.basePath
+ this.baseOptions = param.baseOptions
+ }
+}
diff --git a/frontend/src/services/vdyp-api/index.ts b/frontend/src/services/vdyp-api/index.ts
new file mode 100644
index 000000000..5e6ba1006
--- /dev/null
+++ b/frontend/src/services/vdyp-api/index.ts
@@ -0,0 +1,5 @@
+/* tslint:disable */
+/* eslint-disable */
+export * from './api'
+export * from './configuration'
+export * from './models'
diff --git a/frontend/src/services/vdyp-api/models/combine-age-year-range-enum.ts b/frontend/src/services/vdyp-api/models/combine-age-year-range-enum.ts
new file mode 100644
index 000000000..a5fcd834e
--- /dev/null
+++ b/frontend/src/services/vdyp-api/models/combine-age-year-range-enum.ts
@@ -0,0 +1,7 @@
+/* tslint:disable */
+/* eslint-disable */
+export enum CombineAgeYearRangeEnum {
+ Union = 'union',
+ Intersect = 'intersect',
+ Difference = 'difference',
+}
diff --git a/frontend/src/services/vdyp-api/models/filters.ts b/frontend/src/services/vdyp-api/models/filters.ts
new file mode 100644
index 000000000..e31a18a7e
--- /dev/null
+++ b/frontend/src/services/vdyp-api/models/filters.ts
@@ -0,0 +1,27 @@
+/* tslint:disable */
+/* eslint-disable */
+export interface Filters {
+ /**
+ * @type {string}
+ * @memberof Filters
+ */
+ maintainer?: string
+
+ /**
+ * @type {string}
+ * @memberof Filters
+ */
+ mapsheet?: string
+
+ /**
+ * @type {string}
+ * @memberof Filters
+ */
+ polygon?: string
+
+ /**
+ * @type {string}
+ * @memberof Filters
+ */
+ polygonId?: string
+}
diff --git a/frontend/src/services/vdyp-api/models/index.ts b/frontend/src/services/vdyp-api/models/index.ts
new file mode 100644
index 000000000..e0c0ac108
--- /dev/null
+++ b/frontend/src/services/vdyp-api/models/index.ts
@@ -0,0 +1,14 @@
+export * from './combine-age-year-range-enum'
+export * from './filters'
+export * from './metadata-to-output-enum'
+export * from './output-format-enum'
+export * from './parameters'
+export * from './parameter-details-message' /* added */
+export * from './parameters-progress-frequency'
+export * from './parameters-utils-inner'
+export * from './projection-dcsv-post-request'
+export * from './projection-hcsv-post-request'
+export * from './projection-scsv-post-request'
+export * from './selected-debug-options-enum'
+export * from './selected-execution-options-enum'
+export * from './value-enum'
diff --git a/frontend/src/services/vdyp-api/models/metadata-to-output-enum.ts b/frontend/src/services/vdyp-api/models/metadata-to-output-enum.ts
new file mode 100644
index 000000000..331614ba3
--- /dev/null
+++ b/frontend/src/services/vdyp-api/models/metadata-to-output-enum.ts
@@ -0,0 +1,9 @@
+/* tslint:disable */
+/* eslint-disable */
+export enum MetadataToOutputEnum {
+ ALL = 'ALL',
+ MAIN = 'MAIN',
+ VERSION = 'VERSION',
+ MINIDENT = 'MIN_IDENT',
+ NONE = 'NONE',
+}
diff --git a/frontend/src/services/vdyp-api/models/output-format-enum.ts b/frontend/src/services/vdyp-api/models/output-format-enum.ts
new file mode 100644
index 000000000..a7baa29aa
--- /dev/null
+++ b/frontend/src/services/vdyp-api/models/output-format-enum.ts
@@ -0,0 +1,7 @@
+/* tslint:disable */
+/* eslint-disable */
+export enum OutputFormatEnum {
+ YieldTable = 'YieldTable',
+ CSVYieldTable = 'CSVYieldTable',
+ DCSV = 'DCSV',
+}
diff --git a/frontend/src/services/vdyp-api/models/parameter-details-message.ts b/frontend/src/services/vdyp-api/models/parameter-details-message.ts
new file mode 100644
index 000000000..29a6d71e9
--- /dev/null
+++ b/frontend/src/services/vdyp-api/models/parameter-details-message.ts
@@ -0,0 +1,43 @@
+/* tslint:disable */
+/* eslint-disable */
+export interface ParameterDetailsMessage {
+ /**
+ * the parameter name
+ *
+ * @type {string}
+ * @memberof ParameterDetailsMessage
+ */
+ field?: string
+
+ /**
+ * a brief description of the parameter's purpose
+ *
+ * @type {string}
+ * @memberof ParameterDetailsMessage
+ */
+ shortDescription?: string
+
+ /**
+ * if the parameter has a value, a description of the value
+ *
+ * @type {string}
+ * @memberof ParameterDetailsMessage
+ */
+ parameterValue?: string
+
+ /**
+ * a description of the parameter
+ *
+ * @type {string}
+ * @memberof ParameterDetailsMessage
+ */
+ longDescription?: string
+
+ /**
+ * the default value used if the parameter is not specified
+ *
+ * @type {string}
+ * @memberof ParameterDetailsMessage
+ */
+ defaultValue?: string
+}
diff --git a/frontend/src/services/vdyp-api/models/parameters-progress-frequency.ts b/frontend/src/services/vdyp-api/models/parameters-progress-frequency.ts
new file mode 100644
index 000000000..63164dd78
--- /dev/null
+++ b/frontend/src/services/vdyp-api/models/parameters-progress-frequency.ts
@@ -0,0 +1,3 @@
+/* tslint:disable */
+/* eslint-disable */
+export interface ParametersProgressFrequency {}
diff --git a/frontend/src/services/vdyp-api/models/parameters-utils-inner.ts b/frontend/src/services/vdyp-api/models/parameters-utils-inner.ts
new file mode 100644
index 000000000..9ba95556b
--- /dev/null
+++ b/frontend/src/services/vdyp-api/models/parameters-utils-inner.ts
@@ -0,0 +1,16 @@
+/* tslint:disable */
+/* eslint-disable */
+import { ValueEnum } from './value-enum'
+export interface ParametersUtilsInner {
+ /**
+ * @type {string}
+ * @memberof ParametersUtilsInner
+ */
+ speciesName?: string
+
+ /**
+ * @type {ValueEnum}
+ * @memberof ParametersUtilsInner
+ */
+ value?: ValueEnum
+}
diff --git a/frontend/src/services/vdyp-api/models/parameters.ts b/frontend/src/services/vdyp-api/models/parameters.ts
new file mode 100644
index 000000000..c6d83bde6
--- /dev/null
+++ b/frontend/src/services/vdyp-api/models/parameters.ts
@@ -0,0 +1,149 @@
+/* tslint:disable */
+/* eslint-disable */
+import { CombineAgeYearRangeEnum } from './combine-age-year-range-enum'
+import type { Filters } from './filters'
+import { MetadataToOutputEnum } from './metadata-to-output-enum'
+import { OutputFormatEnum } from './output-format-enum'
+import type { ParametersProgressFrequency } from './parameters-progress-frequency'
+import type { ParametersUtilsInner } from './parameters-utils-inner'
+import { SelectedDebugOptionsEnum } from './selected-debug-options-enum'
+import { SelectedExecutionOptionsEnum } from './selected-execution-options-enum'
+export interface Parameters {
+ /**
+ * @type {OutputFormatEnum}
+ * @memberof Parameters
+ */
+ outputFormat?: OutputFormatEnum
+
+ /**
+ * @type {Array}
+ * @memberof Parameters
+ */
+ selectedExecutionOptions?: Array
+
+ /**
+ * @type {boolean}
+ * @memberof Parameters
+ */
+ doEnableProgressLogging?: boolean
+
+ /**
+ * @type {boolean}
+ * @memberof Parameters
+ */
+ doEnableErrorLogging?: boolean
+
+ /**
+ * @type {boolean}
+ * @memberof Parameters
+ */
+ doEnableDebugLogging?: boolean
+
+ /**
+ * @type {Array}
+ * @memberof Parameters
+ */
+ selectedDebugOptions?: Array
+
+ /**
+ * @type {number}
+ * @memberof Parameters
+ */
+ ageStart?: number
+
+ /**
+ * @type {number}
+ * @memberof Parameters
+ */
+ minAgeStart?: number
+
+ /**
+ * @type {number}
+ * @memberof Parameters
+ */
+ maxAgeStart?: number
+
+ /**
+ * @type {number}
+ * @memberof Parameters
+ */
+ ageEnd?: number
+
+ /**
+ * @type {number}
+ * @memberof Parameters
+ */
+ minAgeEnd?: number
+
+ /**
+ * @type {number}
+ * @memberof Parameters
+ */
+ maxAgeEnd?: number
+
+ /**
+ * @type {number}
+ * @memberof Parameters
+ */
+ yearStart?: number
+
+ /**
+ * @type {number}
+ * @memberof Parameters
+ */
+ yearEnd?: number
+
+ /**
+ * @type {number}
+ * @memberof Parameters
+ */
+ forceYear?: number
+
+ /**
+ * @type {number}
+ * @memberof Parameters
+ */
+ ageIncrement?: number
+
+ /**
+ * @type {number}
+ * @memberof Parameters
+ */
+ minAgeIncrement?: number
+
+ /**
+ * @type {number}
+ * @memberof Parameters
+ */
+ maxAgeIncrement?: number
+
+ /**
+ * @type {CombineAgeYearRangeEnum}
+ * @memberof Parameters
+ */
+ combineAgeYearRange?: CombineAgeYearRangeEnum
+
+ /**
+ * @type {ParametersProgressFrequency}
+ * @memberof Parameters
+ */
+ progressFrequency?: ParametersProgressFrequency
+
+ /**
+ * @type {MetadataToOutputEnum}
+ * @memberof Parameters
+ */
+ metadataToOutput?: MetadataToOutputEnum
+
+ /**
+ * @type {Filters}
+ * @memberof Parameters
+ */
+ filters?: Filters
+
+ /**
+ * @type {Array}
+ * @memberof Parameters
+ */
+ utils?: Array
+}
diff --git a/frontend/src/services/vdyp-api/models/projection-dcsv-post-request.ts b/frontend/src/services/vdyp-api/models/projection-dcsv-post-request.ts
new file mode 100644
index 000000000..856435343
--- /dev/null
+++ b/frontend/src/services/vdyp-api/models/projection-dcsv-post-request.ts
@@ -0,0 +1,16 @@
+/* tslint:disable */
+/* eslint-disable */
+import type { Parameters } from './parameters'
+export interface ProjectionDcsvPostRequest {
+ /**
+ * @type {Parameters}
+ * @memberof ProjectionDcsvPostRequest
+ */
+ projectionParameters?: Parameters
+
+ /**
+ * @type {Blob}
+ * @memberof ProjectionDcsvPostRequest
+ */
+ inputData?: Blob
+}
diff --git a/frontend/src/services/vdyp-api/models/projection-hcsv-post-request.ts b/frontend/src/services/vdyp-api/models/projection-hcsv-post-request.ts
new file mode 100644
index 000000000..6fb9d22e0
--- /dev/null
+++ b/frontend/src/services/vdyp-api/models/projection-hcsv-post-request.ts
@@ -0,0 +1,22 @@
+/* tslint:disable */
+/* eslint-disable */
+import type { Parameters } from './parameters'
+export interface ProjectionHcsvPostRequest {
+ /**
+ * @type {Parameters}
+ * @memberof ProjectionHcsvPostRequest
+ */
+ projectionParameters?: Parameters
+
+ /**
+ * @type {Blob}
+ * @memberof ProjectionHcsvPostRequest
+ */
+ polygonInputData?: Blob
+
+ /**
+ * @type {Blob}
+ * @memberof ProjectionHcsvPostRequest
+ */
+ layerInputData?: Blob
+}
diff --git a/frontend/src/services/vdyp-api/models/projection-scsv-post-request.ts b/frontend/src/services/vdyp-api/models/projection-scsv-post-request.ts
new file mode 100644
index 000000000..1756c2bbc
--- /dev/null
+++ b/frontend/src/services/vdyp-api/models/projection-scsv-post-request.ts
@@ -0,0 +1,58 @@
+/* tslint:disable */
+/* eslint-disable */
+import type { Parameters } from './parameters'
+export interface ProjectionScsvPostRequest {
+ /**
+ * @type {Parameters}
+ * @memberof ProjectionScsvPostRequest
+ */
+ projectionParameters?: Parameters
+
+ /**
+ * @type {Blob}
+ * @memberof ProjectionScsvPostRequest
+ */
+ polygonInputData?: Blob
+
+ /**
+ * @type {Blob}
+ * @memberof ProjectionScsvPostRequest
+ */
+ layerInputData?: Blob
+
+ /**
+ * @type {Blob}
+ * @memberof ProjectionScsvPostRequest
+ */
+ historyInputData?: Blob
+
+ /**
+ * @type {Blob}
+ * @memberof ProjectionScsvPostRequest
+ */
+ nonVegetationInputData?: Blob
+
+ /**
+ * @type {Blob}
+ * @memberof ProjectionScsvPostRequest
+ */
+ otherVegetationInputData?: Blob
+
+ /**
+ * @type {Blob}
+ * @memberof ProjectionScsvPostRequest
+ */
+ polygonIdInputData?: Blob
+
+ /**
+ * @type {Blob}
+ * @memberof ProjectionScsvPostRequest
+ */
+ speciesInputData?: Blob
+
+ /**
+ * @type {Blob}
+ * @memberof ProjectionScsvPostRequest
+ */
+ vriAdjustInputData?: Blob
+}
diff --git a/frontend/src/services/vdyp-api/models/selected-debug-options-enum.ts b/frontend/src/services/vdyp-api/models/selected-debug-options-enum.ts
new file mode 100644
index 000000000..3b5dc889d
--- /dev/null
+++ b/frontend/src/services/vdyp-api/models/selected-debug-options-enum.ts
@@ -0,0 +1,8 @@
+/* tslint:disable */
+/* eslint-disable */
+export enum SelectedDebugOptionsEnum {
+ DoIncludeDebugTimestamps = 'doIncludeDebugTimestamps',
+ DoIncludeDebugRoutineNames = 'doIncludeDebugRoutineNames',
+ DoIncludeDebugEntryExit = 'doIncludeDebugEntryExit',
+ DoIncludeDebugIndentBlocks = 'doIncludeDebugIndentBlocks',
+}
diff --git a/frontend/src/services/vdyp-api/models/selected-execution-options-enum.ts b/frontend/src/services/vdyp-api/models/selected-execution-options-enum.ts
new file mode 100644
index 000000000..a0563bb96
--- /dev/null
+++ b/frontend/src/services/vdyp-api/models/selected-execution-options-enum.ts
@@ -0,0 +1,24 @@
+/* tslint:disable */
+/* eslint-disable */
+export enum SelectedExecutionOptionsEnum {
+ BackGrowEnabled = 'backGrowEnabled',
+ ForwardGrowEnabled = 'forwardGrowEnabled',
+ DoSaveIntermediateFiles = 'doSaveIntermediateFiles',
+ DoForceReferenceYearInclusionInYieldTables = 'doForceReferenceYearInclusionInYieldTables',
+ DoForceCurrentYearInclusionInYieldTables = 'doForceCurrentYearInclusionInYieldTables',
+ DoForceCalendarYearInclusionInYieldTables = 'doForceCalendarYearInclusionInYieldTables',
+ DoIncludeFileHeader = 'doIncludeFileHeader',
+ DoIncludeProjectionModeInYieldTable = 'doIncludeProjectionModeInYieldTable',
+ DoIncludeAgeRowsInYieldTable = 'doIncludeAgeRowsInYieldTable',
+ DoIncludeYearRowsInYieldTable = 'doIncludeYearRowsInYieldTable',
+ DoIncludePolygonRecordIdInYieldTable = 'doIncludePolygonRecordIdInYieldTable',
+ DoSummarizeProjectionByPolygon = 'doSummarizeProjectionByPolygon',
+ DoSummarizeProjectionByLayer = 'doSummarizeProjectionByLayer',
+ DoIncludeSpeciesProjection = 'doIncludeSpeciesProjection',
+ DoIncludeProjectedMOFVolumes = 'doIncludeProjectedMOFVolumes',
+ DoIncludeProjectedMOFBiomass = 'doIncludeProjectedMOFBiomass',
+ DoIncludeProjectedCFSBiomass = 'doIncludeProjectedCFSBiomass',
+ DoIncludeColumnHeadersInYieldTable = 'doIncludeColumnHeadersInYieldTable',
+ DoAllowBasalAreaAndTreesPerHectareValueSubstitution = 'doAllowBasalAreaAndTreesPerHectareValueSubstitution',
+ DoIncludeSecondarySpeciesDominantHeightInYieldTable = 'doIncludeSecondarySpeciesDominantHeightInYieldTable',
+}
diff --git a/frontend/src/services/vdyp-api/models/value-enum.ts b/frontend/src/services/vdyp-api/models/value-enum.ts
new file mode 100644
index 000000000..67388f166
--- /dev/null
+++ b/frontend/src/services/vdyp-api/models/value-enum.ts
@@ -0,0 +1,10 @@
+/* tslint:disable */
+/* eslint-disable */
+export enum ValueEnum {
+ Excl = 'Excl',
+ _40 = '4.0',
+ _75 = '7.5',
+ _125 = '12.5',
+ _175 = '17.5',
+ _225 = '22.5',
+}
diff --git a/frontend/src/stores/appStore.ts b/frontend/src/stores/appStore.ts
index 8dce8fe63..05e1ac768 100644
--- a/frontend/src/stores/appStore.ts
+++ b/frontend/src/stores/appStore.ts
@@ -1,21 +1,17 @@
import { defineStore } from 'pinia'
import { ref } from 'vue'
-import { MODEL_SELECTION, ENGINE_VERSION } from '@/constants/constants'
+import { MODEL_SELECTION } from '@/constants/constants'
export const useAppStore = defineStore('appStore', () => {
// Model Parameter Selection bar
- const modelType = ref(MODEL_SELECTION.FILE_UPLOAD)
- const engineVersion = ref(ENGINE_VERSION.VDYP8)
- const jobId = ref('')
+ const modelSelection = ref(MODEL_SELECTION.FILE_UPLOAD)
// Tabs
const currentTab = ref(0)
return {
// Model Parameter Selection bar
- modelType,
- engineVersion,
- jobId,
+ modelSelection,
// Tabs
currentTab,
}
diff --git a/frontend/src/stores/modelParameterStore.ts b/frontend/src/stores/modelParameterStore.ts
index e4122c92d..780b78485 100644
--- a/frontend/src/stores/modelParameterStore.ts
+++ b/frontend/src/stores/modelParameterStore.ts
@@ -2,7 +2,6 @@ import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import {
PANEL,
- FLOATING,
MODEL_PARAMETER_PANEL,
NUM_INPUT_LIMITS,
} from '@/constants/constants'
@@ -16,7 +15,6 @@ export const useModelParameterStore = defineStore('modelParameter', () => {
speciesInfo: PANEL.OPEN,
siteInfo: PANEL.CLOSE,
standDensity: PANEL.CLOSE,
- addtStandAttrs: PANEL.CLOSE,
reportInfo: PANEL.CLOSE,
})
@@ -24,14 +22,12 @@ export const useModelParameterStore = defineStore('modelParameter', () => {
const panelState = ref<
Record
>({
- speciesInfo: { confirmed: false, editable: true }, // Only speciesInfo is editable initially
+ speciesInfo: { confirmed: false, editable: true },
siteInfo: { confirmed: false, editable: false },
standDensity: { confirmed: false, editable: false },
- addtStandAttrs: { confirmed: false, editable: false },
reportInfo: { confirmed: false, editable: false },
})
- // Run Model button state
const runModelEnabled = ref(false)
//
@@ -57,7 +53,6 @@ export const useModelParameterStore = defineStore('modelParameter', () => {
MODEL_PARAMETER_PANEL.SPECIES_INFO,
MODEL_PARAMETER_PANEL.SITE_INFO,
MODEL_PARAMETER_PANEL.STAND_DENSITY,
- MODEL_PARAMETER_PANEL.ADDT_STAND_ATTRS,
MODEL_PARAMETER_PANEL.REPORT_INFO,
]
const currentIndex = panelOrder.indexOf(panelName)
@@ -84,7 +79,6 @@ export const useModelParameterStore = defineStore('modelParameter', () => {
MODEL_PARAMETER_PANEL.SPECIES_INFO,
MODEL_PARAMETER_PANEL.SITE_INFO,
MODEL_PARAMETER_PANEL.STAND_DENSITY,
- MODEL_PARAMETER_PANEL.ADDT_STAND_ATTRS,
MODEL_PARAMETER_PANEL.REPORT_INFO,
]
const currentIndex = panelOrder.indexOf(panelName)
@@ -119,7 +113,6 @@ export const useModelParameterStore = defineStore('modelParameter', () => {
group: string
percent: number
siteSpecies: string
- minimumDBHLimit: string
}[]
>([])
@@ -164,7 +157,6 @@ export const useModelParameterStore = defineStore('modelParameter', () => {
group: key,
percent: groupMap[key],
siteSpecies: key,
- minimumDBHLimit: DEFAULT_VALUES.MINIMUM_DBH_LIMIT,
}))
speciesGroups.value.sort((a, b) => b.percent - a.percent)
@@ -178,31 +170,11 @@ export const useModelParameterStore = defineStore('modelParameter', () => {
const becZone = ref(null)
const ecoZone = ref(null)
const incSecondaryHeight = ref(false)
- const siteIndexCurve = ref(null)
const siteSpeciesValues = ref(null)
- const ageType = ref(null)
- const percentStockableArea = ref(null)
- const age = ref(null)
- const height = ref(null)
const bha50SiteIndex = ref(null)
- const floating = ref(null)
// stand density
- const basalArea = ref(null)
- const treesPerHectare = ref(null)
- const minimumDBHLimit = ref(null)
- const currentDiameter = ref(null)
- const percentCrownClosure = ref(null)
-
- // additional stand attributes
- const computedValues = ref(null)
- const loreyHeight = ref(null)
- const wholeStemVol75 = ref(null)
- const basalArea125 = ref(null)
- const wholeStemVol125 = ref(null)
- const cuVol = ref(null)
- const cuNetDecayVol = ref(null)
- const cuNetDecayWasteVol = ref(null)
+ const percentStockableArea = ref(null)
// report info
const startingAge = ref(null)
@@ -229,28 +201,12 @@ export const useModelParameterStore = defineStore('modelParameter', () => {
speciesGroups.value = speciesGroups.value.map((group) => ({
...group,
- minimumDBHLimit: DEFAULT_VALUES.MINIMUM_DBH_LIMIT,
}))
becZone.value = DEFAULT_VALUES.BEC_ZONE
siteSpeciesValues.value = DEFAULT_VALUES.SITE_SPECIES_VALUES
- ageType.value = DEFAULT_VALUES.AGE_TYPE
- percentStockableArea.value = DEFAULT_VALUES.PERCENT_STOCKABLE_AREA
- age.value = DEFAULT_VALUES.AGE
- height.value = DEFAULT_VALUES.HEIGHT
bha50SiteIndex.value = DEFAULT_VALUES.BHA50_SITE_INDEX
- floating.value = FLOATING.SITEINDEX
- minimumDBHLimit.value = DEFAULT_VALUES.MINIMUM_DBH_LIMIT
- currentDiameter.value = DEFAULT_VALUES.CURRENT_DIAMETER
- percentCrownClosure.value = DEFAULT_VALUES.PERCENT_CROWN_CLOSURE
- computedValues.value = DEFAULT_VALUES.COMPUTED_VALUES
- loreyHeight.value = DEFAULT_VALUES.LOREY_HEIGHT
- wholeStemVol75.value = DEFAULT_VALUES.WHOLE_STEM_VOL75
- basalArea125.value = DEFAULT_VALUES.BASAL_AREA125
- wholeStemVol125.value = DEFAULT_VALUES.WHOLE_STEM_VOL125
- cuVol.value = DEFAULT_VALUES.CU_VOL
- cuNetDecayVol.value = DEFAULT_VALUES.CU_NET_DECAY_VOL
- cuNetDecayWasteVol.value = DEFAULT_VALUES.CU_NET_DECAY_WASTE_VOL
+ percentStockableArea.value = DEFAULT_VALUES.PERCENT_STOCKABLE_AREA
startingAge.value = DEFAULT_VALUES.STARTING_AGE
finishingAge.value = DEFAULT_VALUES.FINISHING_AGE
ageIncrement.value = DEFAULT_VALUES.AGE_INCREMENT
@@ -280,29 +236,10 @@ export const useModelParameterStore = defineStore('modelParameter', () => {
becZone,
ecoZone,
incSecondaryHeight,
- siteIndexCurve,
siteSpeciesValues,
- ageType,
- percentStockableArea,
- age,
- height,
bha50SiteIndex,
- floating,
// stand density
- basalArea,
- treesPerHectare,
- minimumDBHLimit,
- percentCrownClosure,
- currentDiameter,
- // additional stand attributes
- computedValues,
- loreyHeight,
- wholeStemVol75,
- basalArea125,
- wholeStemVol125,
- cuVol,
- cuNetDecayVol,
- cuNetDecayWasteVol,
+ percentStockableArea,
// report info
startingAge,
diff --git a/frontend/src/stores/projectionStore.ts b/frontend/src/stores/projectionStore.ts
new file mode 100644
index 000000000..583c4ae8d
--- /dev/null
+++ b/frontend/src/stores/projectionStore.ts
@@ -0,0 +1,53 @@
+import { defineStore } from 'pinia'
+import { ref } from 'vue'
+import * as JSZip from 'jszip'
+import { messageResult } from '@/utils/messageHandler'
+import { FILE_UPLOAD_ERR } from '@/constants/message'
+
+export const useProjectionStore = defineStore('projectionStore', () => {
+ const errorMessages = ref([])
+ const logMessages = ref([])
+ const yieldTable = ref('')
+
+ const handleZipResponse = async (zipData: Blob) => {
+ try {
+ const zip = await JSZip.loadAsync(zipData)
+ const requiredFiles = {
+ error: 'Output_Error.txt',
+ log: 'Output_Log.txt',
+ yield: 'Output_YldTbl.csv',
+ }
+
+ const errorFile = zip.file(requiredFiles.error)
+ const logFile = zip.file(requiredFiles.log)
+ const yieldFile = zip.file(requiredFiles.yield)
+
+ if (!errorFile || !logFile || !yieldFile) {
+ const missingFiles = Object.values(requiredFiles).filter(
+ (file) => !zip.file(file),
+ )
+ messageResult(
+ false,
+ '',
+ `${FILE_UPLOAD_ERR.MISSING_RESPONSED_FILE}: ${missingFiles.join(', ')}`,
+ )
+ throw new Error(`Missing files: ${missingFiles.join(', ')}`)
+ }
+
+ errorMessages.value = (await errorFile.async('string')).split(/\r?\n/)
+ logMessages.value = (await logFile.async('string')).split(/\r?\n/)
+ yieldTable.value = await yieldFile.async('string')
+ } catch (error) {
+ console.error('Error processing ZIP file:', error)
+ messageResult(false, '', FILE_UPLOAD_ERR.INVALID_RESPONSED_FILE)
+ throw error
+ }
+ }
+
+ return {
+ errorMessages,
+ logMessages,
+ yieldTable,
+ handleZipResponse,
+ }
+})
diff --git a/frontend/src/styles/style.scss b/frontend/src/styles/style.scss
index c2ec1312b..507cdd2dd 100644
--- a/frontend/src/styles/style.scss
+++ b/frontend/src/styles/style.scss
@@ -105,6 +105,14 @@ body {
padding: 1rem !important;
}
+/* FILE-INPUT */
+.v-input--center-affix .v-input__prepend,
+.v-input--center-affix .v-input__append {
+ align-items: center;
+ padding-top: 0;
+ display: none;
+}
+
/* TABS */
// tab
.v-tab.v-tab.v-btn {
diff --git a/frontend/src/types/types.ts b/frontend/src/types/types.ts
index f3bbe91b6..b48778d92 100644
--- a/frontend/src/types/types.ts
+++ b/frontend/src/types/types.ts
@@ -16,7 +16,6 @@ export type PanelName =
| typeof MODEL_PARAMETER_PANEL.SPECIES_INFO
| typeof MODEL_PARAMETER_PANEL.SITE_INFO
| typeof MODEL_PARAMETER_PANEL.STAND_DENSITY
- | typeof MODEL_PARAMETER_PANEL.ADDT_STAND_ATTRS
| typeof MODEL_PARAMETER_PANEL.REPORT_INFO
export type PanelState = typeof PANEL.OPEN | typeof PANEL.CLOSE
diff --git a/frontend/src/utils/messageHandler.ts b/frontend/src/utils/messageHandler.ts
index ab81423ad..797974fc8 100644
--- a/frontend/src/utils/messageHandler.ts
+++ b/frontend/src/utils/messageHandler.ts
@@ -1,6 +1,7 @@
import { useNotificationStore } from '@/stores/common/notificationStore'
import type { MessageType } from '@/types/types'
import { MESSAGE_TYPE } from '@/constants/constants'
+import { getActivePinia } from 'pinia'
/**
* Displays job success or failure messages to notification and/or console.
@@ -15,14 +16,25 @@ export const messageResult = (
failMessage: string,
error: Error | null = null,
) => {
- const notificationStore = useNotificationStore()
+ const pinia = getActivePinia()
+ let notificationStore
+
+ if (pinia) {
+ notificationStore = useNotificationStore()
+ } else {
+ console.warn('Pinia is not active. Message will only be logged.')
+ }
if (isSuccess) {
console.info(successMessage)
- notificationStore.showSuccessMessage(successMessage)
+ if (notificationStore) {
+ notificationStore.showSuccessMessage(successMessage)
+ }
} else {
console.warn(failMessage, error)
- notificationStore.showWarningMessage(failMessage)
+ if (notificationStore) {
+ notificationStore.showWarningMessage(failMessage)
+ }
}
}
@@ -34,14 +46,21 @@ export const messageResult = (
* @param {boolean} [disableConsole=false] - Whether to disable console logging.
* @param {boolean} [disableNotification=false] - Whether to disable notification messages.
*/
-export const logMessage = (
+const logMessage = (
message: string,
messageType: MessageType = MESSAGE_TYPE.INFO,
optionalMessage?: string | null,
disableConsole: boolean = false,
disableNotification: boolean = false,
) => {
- const notificationStore = useNotificationStore()
+ const pinia = getActivePinia()
+ let notificationStore
+
+ if (pinia) {
+ notificationStore = useNotificationStore()
+ } else {
+ console.warn('Pinia is not active. Message will only be logged.')
+ }
const consoleMessage = optionalMessage
? `${message} (${optionalMessage})`
@@ -69,19 +88,25 @@ export const logMessage = (
if (!disableNotification) {
switch (messageType) {
case MESSAGE_TYPE.ERROR:
- notificationStore.showErrorMessage(message)
+ if (notificationStore) {
+ notificationStore.showErrorMessage(message)
+ }
break
case MESSAGE_TYPE.WARNING:
- notificationStore.showWarningMessage(message)
- break
- case MESSAGE_TYPE.INFO:
- notificationStore.showInfoMessage(message)
+ if (notificationStore) {
+ notificationStore.showWarningMessage(message)
+ }
break
case MESSAGE_TYPE.SUCCESS:
- notificationStore.showSuccessMessage(message)
+ if (notificationStore) {
+ notificationStore.showSuccessMessage(message)
+ }
break
+ case MESSAGE_TYPE.INFO:
default:
- notificationStore.showInfoMessage(message)
+ if (notificationStore) {
+ notificationStore.showInfoMessage(message)
+ }
}
}
}
diff --git a/frontend/src/validation/addtStandAttrsValidation.ts b/frontend/src/validation/addtStandAttrsValidation.ts
deleted file mode 100644
index d3c8cc157..000000000
--- a/frontend/src/validation/addtStandAttrsValidation.ts
+++ /dev/null
@@ -1,142 +0,0 @@
-import { ValidationBase } from './validationBase'
-import { COMPUTED_VALUES, NUM_INPUT_LIMITS } from '@/constants/constants'
-import { Util } from '@/utils/util'
-import { MDL_PRM_INPUT_ERR } from '@/constants/message'
-
-export class AddtStandAttrsValidation extends ValidationBase {
- validateFieldPresence(fieldValue: string | null): boolean {
- return !Util.isBlank(fieldValue)
- }
-
- validateAllFields(fields: { value: string | null }[]): boolean {
- return fields.every((field) => this.validateFieldPresence(field.value))
- }
-
- validateComputedValuesModification(
- computedValues: string | null,
- fields: { original: { value: string | null }; current: string | null }[],
- ): boolean {
- if (computedValues === COMPUTED_VALUES.MODIFY) {
- const hasModification = fields.some((field) => {
- return field.original.value !== field.current
- })
-
- return hasModification
- }
- return true
- }
-
- validateComparison(
- basalArea125: string | null,
- basalArea: string | null,
- wholeStemVol125: string | null,
- wholeStemVol75: string | null,
- cuVol: string | null,
- cuNetDecayVol: string | null,
- cuNetDecayWasteVol: string | null,
- ): string | null {
- if (
- basalArea125 !== null &&
- basalArea !== null &&
- parseFloat(basalArea125) > parseFloat(basalArea)
- ) {
- return MDL_PRM_INPUT_ERR.ATTR_VLD_COMP_BSL_AREA(basalArea)
- }
-
- if (
- wholeStemVol125 !== null &&
- wholeStemVol75 !== null &&
- wholeStemVol125 > wholeStemVol75
- ) {
- return MDL_PRM_INPUT_ERR.ATTR_VLD_COMP_WSV
- }
-
- if (cuVol !== null && wholeStemVol125 !== null && cuVol > wholeStemVol125) {
- return MDL_PRM_INPUT_ERR.ATTR_VLD_COMP_CUV
- }
-
- if (cuNetDecayVol !== null && cuVol !== null && cuNetDecayVol > cuVol) {
- return MDL_PRM_INPUT_ERR.ATTR_VLD_COMP_CUNDV
- }
-
- if (
- cuNetDecayWasteVol !== null &&
- cuNetDecayVol !== null &&
- cuNetDecayWasteVol > cuNetDecayVol
- ) {
- return MDL_PRM_INPUT_ERR.ATTR_VLD_COMP_CUNDWV
- }
-
- return null
- }
-
- validateValueRange(
- loreyHeight: string | null,
- wholeStemVol75: string | null,
- basalArea125: string | null,
- wholeStemVol125: string | null,
- cuVol: string | null,
- cuNetDecayVol: string | null,
- cuNetDecayWasteVol: string | null,
- ): string | null {
- if (
- loreyHeight !== null &&
- (parseFloat(loreyHeight) < NUM_INPUT_LIMITS.LOREY_HEIGHT_MIN ||
- parseFloat(loreyHeight) > NUM_INPUT_LIMITS.LOREY_HEIGHT_MAX)
- ) {
- return MDL_PRM_INPUT_ERR.ATTR_VLD_LRY_HEIGHT_RNG
- }
-
- if (
- wholeStemVol75 !== null &&
- (parseFloat(wholeStemVol75) < NUM_INPUT_LIMITS.WHOLE_STEM_VOL75_MIN ||
- parseFloat(wholeStemVol75) > NUM_INPUT_LIMITS.WHOLE_STEM_VOL75_MAX)
- ) {
- return MDL_PRM_INPUT_ERR.ATTR_VLD_WSV75_RNG
- }
-
- if (
- basalArea125 !== null &&
- (parseFloat(basalArea125) < NUM_INPUT_LIMITS.BASAL_AREA125_MIN ||
- parseFloat(basalArea125) > NUM_INPUT_LIMITS.BASAL_AREA125_MAX)
- ) {
- return MDL_PRM_INPUT_ERR.ATTR_VLD_BSL_AREA_RNG
- }
-
- if (
- wholeStemVol125 !== null &&
- (parseFloat(wholeStemVol125) < NUM_INPUT_LIMITS.WHOLE_STEM_VOL125_MIN ||
- parseFloat(wholeStemVol125) > NUM_INPUT_LIMITS.WHOLE_STEM_VOL125_MAX)
- ) {
- return MDL_PRM_INPUT_ERR.ATTR_VLD_WSV125_RNG
- }
-
- if (
- cuVol !== null &&
- (parseFloat(cuVol) < NUM_INPUT_LIMITS.CU_VOL_MIN ||
- parseFloat(cuVol) > NUM_INPUT_LIMITS.CU_VOL_MAX)
- ) {
- return MDL_PRM_INPUT_ERR.ATTR_VLD_CUV_RNG
- }
-
- if (
- cuNetDecayVol !== null &&
- (parseFloat(cuNetDecayVol) < NUM_INPUT_LIMITS.CU_NET_DECAY_VOL_MIN ||
- parseFloat(cuNetDecayVol) > NUM_INPUT_LIMITS.CU_NET_DECAY_VOL_MAX)
- ) {
- return MDL_PRM_INPUT_ERR.ATTR_VLD_CUNDV_RNG
- }
-
- if (
- cuNetDecayWasteVol !== null &&
- (parseFloat(cuNetDecayWasteVol) <
- NUM_INPUT_LIMITS.CU_NET_DECAY_WASTE_VOL_MIN ||
- parseFloat(cuNetDecayWasteVol) >
- NUM_INPUT_LIMITS.CU_NET_DECAY_WASTE_VOL_MAX)
- ) {
- return MDL_PRM_INPUT_ERR.ATTR_VLD_CUNDWV_RNG
- }
-
- return null
- }
-}
diff --git a/frontend/src/validation/fileUploadValidation.ts b/frontend/src/validation/fileUploadValidation.ts
new file mode 100644
index 000000000..c8c934cbe
--- /dev/null
+++ b/frontend/src/validation/fileUploadValidation.ts
@@ -0,0 +1,66 @@
+import { ValidationBase } from './validationBase'
+import { NUM_INPUT_LIMITS } from '@/constants/constants'
+import Papa from 'papaparse'
+
+export class FileUploadValidation extends ValidationBase {
+ validateRequiredFields(
+ startingAge: number | null,
+ finishingAge: number | null,
+ ageIncrement: number | null,
+ ): boolean {
+ return (
+ startingAge !== null && finishingAge !== null && ageIncrement !== null
+ )
+ }
+
+ validateAgeComparison(
+ finishingAge: number | null,
+ startingAge: number | null,
+ ): boolean {
+ if (finishingAge !== null && startingAge !== null) {
+ return finishingAge >= startingAge
+ }
+ return true
+ }
+
+ validateStartingAgeRange(startingAge: number | null): boolean {
+ if (startingAge !== null) {
+ return (
+ startingAge >= NUM_INPUT_LIMITS.STARTING_AGE_MIN &&
+ startingAge <= NUM_INPUT_LIMITS.STARTING_AGE_MAX
+ )
+ }
+ return true
+ }
+
+ validateFinishingAgeRange(finishingAge: number | null): boolean {
+ if (finishingAge !== null) {
+ return (
+ finishingAge >= NUM_INPUT_LIMITS.FINISHING_AGE_MIN &&
+ finishingAge <= NUM_INPUT_LIMITS.FINISHING_AGE_MAX
+ )
+ }
+ return true
+ }
+
+ validateAgeIncrementRange(ageIncrement: number | null): boolean {
+ if (ageIncrement !== null) {
+ return (
+ ageIncrement >= NUM_INPUT_LIMITS.AGE_INC_MIN &&
+ ageIncrement <= NUM_INPUT_LIMITS.AGE_INC_MAX
+ )
+ }
+ return true
+ }
+
+ async isCSVFile(file: File): Promise {
+ return new Promise((resolve) => {
+ Papa.parse(file, {
+ complete: (results: any) => {
+ resolve(results.errors.length === 0)
+ },
+ error: () => resolve(false),
+ })
+ })
+ }
+}
diff --git a/frontend/src/validation/siteInfoValidation.ts b/frontend/src/validation/siteInfoValidation.ts
index 1030d5882..94c15a028 100644
--- a/frontend/src/validation/siteInfoValidation.ts
+++ b/frontend/src/validation/siteInfoValidation.ts
@@ -1,56 +1,10 @@
import { ValidationBase } from './validationBase'
-import { SITE_SPECIES_VALUES, NUM_INPUT_LIMITS } from '@/constants/constants'
+import { NUM_INPUT_LIMITS } from '@/constants/constants'
import { Util } from '@/utils/util'
export class SiteInfoValidation extends ValidationBase {
- validateRequiredFields(
- siteSpeciesValues: string | null,
- age: number | null,
- height: string | null,
- bha50SiteIndex: string | null,
- ): boolean {
- if (siteSpeciesValues === SITE_SPECIES_VALUES.COMPUTED) {
- return !(
- Util.isEmptyOrZero(age) ||
- Util.isEmptyOrZero(height) ||
- Util.isEmptyOrZero(bha50SiteIndex)
- )
- } else if (siteSpeciesValues === SITE_SPECIES_VALUES.SUPPLIED) {
- return !Util.isEmptyOrZero(bha50SiteIndex)
- }
- return true
- }
-
- validatePercentStockableAreaRange(psa: number | null): boolean {
- if (!psa) return true
-
- return this.validateRange(
- psa,
- NUM_INPUT_LIMITS.PERCENT_STOCKABLE_AREA_MIN,
- NUM_INPUT_LIMITS.PERCENT_STOCKABLE_AREA_MAX,
- )
- }
-
- validateAgeRange(age: number | null): boolean {
- if (!age) return true
-
- return this.validateRange(
- age,
- NUM_INPUT_LIMITS.AGE_MIN,
- NUM_INPUT_LIMITS.AGE_MAX,
- )
- }
-
- validateHeightRange(height: string | null): boolean {
- if (!height) return true
-
- const numericHeight = parseFloat(height)
-
- return this.validateRange(
- numericHeight,
- NUM_INPUT_LIMITS.HEIGHT_MIN,
- NUM_INPUT_LIMITS.HEIGHT_MAX,
- )
+ validateRequiredFields(bha50SiteIndex: string | null): boolean {
+ return !Util.isEmptyOrZero(bha50SiteIndex)
}
validateBha50SiteIndexRange(bha50SiteIndex: string | null): boolean {
diff --git a/frontend/src/validation/standDensityValidation.ts b/frontend/src/validation/standDensityValidation.ts
index 514ce0fc3..20443fe6c 100644
--- a/frontend/src/validation/standDensityValidation.ts
+++ b/frontend/src/validation/standDensityValidation.ts
@@ -1,363 +1,14 @@
import { ValidationBase } from './validationBase'
import { NUM_INPUT_LIMITS } from '@/constants/constants'
-import { Util } from '@/utils/util'
-import * as MAP from '@/constants/mappings'
export class StandDensityValidation extends ValidationBase {
- validateBasalAreaRange(basalArea: string | null): boolean {
- const numericBasalArea = Util.toNumber(basalArea)
- if (!numericBasalArea) return true
+ validatePercentStockableAreaRange(psa: number | null): boolean {
+ if (!psa) return true
return this.validateRange(
- numericBasalArea,
- NUM_INPUT_LIMITS.BASAL_AREA_MIN,
- NUM_INPUT_LIMITS.BASAL_AREA_MAX,
+ psa,
+ NUM_INPUT_LIMITS.PERCENT_STOCKABLE_AREA_MIN,
+ NUM_INPUT_LIMITS.PERCENT_STOCKABLE_AREA_MAX,
)
}
-
- validateTreesPerHectareRange(tph: string | null): boolean {
- const numericTph = Util.toNumber(tph)
- if (!numericTph) return true
-
- return this.validateRange(
- numericTph,
- NUM_INPUT_LIMITS.TPH_MIN,
- NUM_INPUT_LIMITS.TPH_MAX,
- )
- }
-
- validatePercentCrownClosureRange(pcc: number | null): boolean {
- if (!pcc) return true
-
- return this.validateRange(
- pcc,
- NUM_INPUT_LIMITS.CROWN_CLOSURE_MIN,
- NUM_INPUT_LIMITS.CROWN_CLOSURE_MAX,
- )
- }
-
- validateBALimits(
- selectedSiteSpecies: string | null,
- becZone: string | null,
- basalArea: string | null,
- height: string | null,
- ): boolean {
- if (selectedSiteSpecies && becZone && basalArea && height) {
- const isValid = this.validateBasalAreaLimits(
- selectedSiteSpecies,
- this.isCoastalZone(becZone),
- basalArea,
- height,
- )
-
- return isValid
- }
- return true
- }
-
- validateTPHLimits(
- basalArea: string | null,
- treesPerHectare: string | null,
- height: string | null,
- selectedSiteSpecies: string | null,
- becZone: string | null,
- ): string | null {
- if (
- basalArea &&
- treesPerHectare &&
- height &&
- selectedSiteSpecies &&
- becZone
- ) {
- return this.validateTreePerHectareLimits(
- basalArea,
- treesPerHectare,
- height,
- selectedSiteSpecies,
- this.isCoastalZone(becZone),
- )
- }
-
- return null
- }
-
- validateQuadDiameter(
- basalArea: string | null,
- treesPerHectare: string | null,
- minimumDBHLimit: string | null,
- ): string | null {
- if (basalArea && treesPerHectare && minimumDBHLimit) {
- return this.validateQuadraticDiameter(
- basalArea,
- treesPerHectare,
- minimumDBHLimit,
- )
- }
-
- return null
- }
-
- /**
- * Function that validates whether the given basal area is within acceptable limits for the species.
- * It calculates the maximum allowable basal area using species-specific coefficients and height.
- * @param species - The species code to look up the basal area coefficients.
- * @param isCoastal - Boolean indicating whether the region is coastal (true) or interior (false).
- * @param basalArea - The basal area to be validated.
- * @param height - The height of the stand used in the calculation.
- * @returns true if the basal area is within the valid limit, false otherwise.
- * Returns true on errors for input arguments that cannot be validated.
- * @example speceis:'H', coastal, ba: 50, height: 8
- */
- validateBasalAreaLimits(
- species: string,
- isCoastal: boolean,
- basalArea: string,
- height: string,
- ): boolean {
- if (!(species in MAP.BA_LIMIT_COEFFICIENTS)) {
- console.warn(`Species ${species} not found in BA_LIMIT_COEFFICIENTS.`)
- return true
- }
-
- const speciesData =
- MAP.BA_LIMIT_COEFFICIENTS[
- species as keyof typeof MAP.BA_LIMIT_COEFFICIENTS
- ]
-
- const region = isCoastal ? 'coastal' : 'interior'
- const coeffs = speciesData[region]
-
- // -999 indicates unavailable coefficient
- if (coeffs.coeff1 === -999 || coeffs.coeff2 === -999) {
- return true
- }
-
- // Ensure these arguments are valid, handle invalid input
- const parsedHeight = parseFloat(height)
- const parsedBasalArea = parseFloat(basalArea)
-
- if (isNaN(parsedHeight) || parsedHeight <= 0) {
- console.warn(
- `Invalid height value: ${height}. Unable to perform calculation.`,
- )
- return true
- }
-
- if (isNaN(parsedBasalArea) || parsedBasalArea <= 0) {
- console.warn(
- `Invalid basal area value: ${basalArea}. Unable to perform calculation.`,
- )
- return true
- }
-
- // Equation constants
- const { const1, const2 } = MAP.BA_EQUATION_CONSTANTS
-
- // Validate the basal area against the calculated limit
- const fBALimit =
- Math.exp(coeffs.coeff2 / (parseFloat(height) - const2)) * coeffs.coeff1 +
- const1
-
- return parseFloat(basalArea) <= fBALimit
- }
-
- /**
- * Function that takes in a BEC Zone and returns whether the Zone is coastal or not
- * @param becZone BEC Zone code
- * @returns true if the BEC Zone is coastal, false if interior
- */
- isCoastalZone(becZone: string): boolean {
- const normalizedBecZone = becZone.trim().toUpperCase()
-
- if (normalizedBecZone in MAP.BEC_ZONE_COASTAL_MAP) {
- return MAP.BEC_ZONE_COASTAL_MAP[normalizedBecZone]
- } else {
- console.warn(`BEC Zone ${becZone} is not recognized.`)
- return false
- }
- }
-
- /**
- * Validates the Trees per Hectare (TPH) limits based on the basal area, TPH, height, species, and region.
- * This function calculates the likely minimum and maximum TPH values using species-specific coefficients
- * for coastal or interior regions and compares the input TPH with those limits.
- *
- * @param basalArea - The basal area in square meters per hectare.
- * @param tph - Trees per hectare.
- * @param height - The height of the trees in meters.
- * @param species - The species code to look up TPH limit coefficients.
- * @param coastal - Boolean indicating whether the region is coastal (true) or interior (false).
- * @returns A string with an error message if TPH is outside the calculated limits, or null if valid.
- *
- * @example
- * tph < tphMin: species = AC, coastal, height = 10.0, ba = 25.0, TPH = 50
- * tph > tphMax: species = AC, coastal, height = 10.0, ba = 5.0, TPH = 4000
- */
- validateTreePerHectareLimits(
- basalArea: string,
- tph: string,
- height: string,
- species: string,
- coastal: boolean,
- ): string | null {
- // Handle unknown species
- if (!(species in MAP.TPH_LIMIT_COEFFICIENTS)) {
- console.warn('Unknown species')
- return null
- }
-
- const speciesCoefficients = MAP.TPH_LIMIT_COEFFICIENTS[
- species as keyof typeof MAP.TPH_LIMIT_COEFFICIENTS
- ] as { coastal?: any; interior?: any }
-
- // Set region based on whether it's Coastal or not
- const region = coastal ? 'coastal' : 'interior'
-
- // Check if the region data exists
- if (!speciesCoefficients[region]) {
- console.warn('No data for region')
- return null
- }
-
- const regionCoefficients = speciesCoefficients[region]
- const { P10, P90 } = regionCoefficients || {}
-
- // Verify that P10 and P90 data are present
- if (!P10 || !P90) {
- console.warn('No data for region')
- return null
- }
-
- // Ensure these input arguments are valid, handle invalid input
- const parsedHeight = parseFloat(height)
- const parsedBasalArea = parseFloat(basalArea)
- const parsedTph = parseFloat(tph)
-
- if (isNaN(parsedHeight) || parsedHeight <= 0) {
- console.warn(
- `Invalid height value: ${height}. Unable to perform calculation.`,
- )
- return null
- }
-
- if (isNaN(parsedBasalArea) || parsedBasalArea <= 0) {
- console.warn(
- `Invalid basal area value: ${basalArea}. Unable to perform calculation.`,
- )
- return null
- }
-
- if (isNaN(parsedTph) || parsedTph <= 0) {
- console.warn(
- `Invalid trees per hectare value: ${tph}. Unable to perform calculation.`,
- )
- return null
- }
-
- // Defining constants
- const const1 = MAP.TPH_EQUATION_CONSTANTS.const1
- const const2 = MAP.TPH_EQUATION_CONSTANTS.const2
- const const3 = MAP.TPH_EQUATION_CONSTANTS.const3
- const unavailable = -999 // Handle when data is unavailable
-
- let tphMin: number | null = null
- let tphMax: number | null = null
-
- // Return null if P10, P90 values are invalid
- if (P10.a0 === unavailable || P90.a0 === unavailable) {
- console.warn('Unavailable TPH coefficients for this region')
- return null
- }
-
- // Minimum TPH calculation
- const dqMax =
- const1 +
- P90.a0 +
- P90.b0 * (parseFloat(height) - const2) +
- P90.b1 * (parseFloat(height) - const2) ** 2
-
- if (dqMax > 0) {
- tphMin = parseFloat(basalArea) / (const3 * dqMax ** 2)
- }
-
- // Maximum TPH calculation
- const dqMin =
- -const1 +
- P10.a0 +
- P10.b0 * (parseFloat(height) - const2) +
- P10.b1 * (parseFloat(height) - const2) ** 2
-
- if (dqMin > 0) {
- tphMax = parseFloat(basalArea) / (const3 * dqMin ** 2)
- }
-
- // Minimum and maximum TPH values not calculated correctly
- if (tphMin === null || tphMax === null) {
- console.warn('TPH calculation failed')
- return null
- }
-
- if (parseFloat(tph) < tphMin) {
- return 'Trees/ha is less than a likely minimum for entered height. Do you wish to proceed?'
- }
-
- if (parseFloat(tph) > tphMax) {
- return 'Trees/ha is above a likely maximum for entered height. Do you wish to proceed?'
- }
-
- // Return null if in range (valid value)
- return null
- }
-
- /**
- * Validates the quadratic mean diameter based on the basal area, trees per hectare (TPH), and minimum DBH limit.
- * If the calculated quadratic diameter is less than the required minimum DBH limit, an error message is returned.
- *
- * @param basalArea - The basal area in m²/ha.
- * @param tph - Trees per hectare.
- * @param minDBHLimit - The minimum DBH limit in cm, provided as a string.
- * @returns - Returns an error message if the quadratic diameter is less than the minimum limit, otherwise null.
- *
- * @example
- * basalArea: 4, tph: 1000, minDBHLimit: 7.5 cm+
- */
- validateQuadraticDiameter(
- basalArea: string,
- tph: string,
- minDBHLimit: string | null,
- ): string | null {
- if (!minDBHLimit) {
- console.warn('Unknown minDBHLimit')
- return null
- }
-
- const parsedBasalArea = parseFloat(basalArea)
- const parsedTph = parseFloat(tph)
-
- if (isNaN(parsedBasalArea) || parsedBasalArea <= 0) {
- console.warn(
- `Invalid basal area value: ${basalArea}. Unable to perform calculation.`,
- )
- return null
- }
-
- if (isNaN(parsedTph) || parsedTph <= 0) {
- console.warn(
- `Invalid trees per hectare value: ${tph}. Unable to perform calculation.`,
- )
- return null
- }
-
- let diam = 0
- if (parseFloat(tph) > 0) {
- diam = Math.sqrt(parseFloat(basalArea) / parseFloat(tph) / 0.00007854)
- }
-
- if (diam < Util.extractNumeric(minDBHLimit)) {
- return `Quadratic Mean Diameter of ${diam.toFixed(1)} cm is less than the required diameter of: ${minDBHLimit}\nModify one or both of Basal Area or Trees per Hectare.`
- }
-
- // Return null if in range (valid value)
- return null
- }
}
diff --git a/frontend/src/views/input-model-parameters/FileUpload.vue b/frontend/src/views/input-model-parameters/FileUpload.vue
index 847f681df..4463a45d0 100644
--- a/frontend/src/views/input-model-parameters/FileUpload.vue
+++ b/frontend/src/views/input-model-parameters/FileUpload.vue
@@ -1,8 +1,8 @@
-
-
-
+
+
+
-
-
- Volume Reported
+
+
+
+ Volume Reported
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
- Include in Report
+
+
+ Include in Report
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Report Title
+
+
+ Report Title
+
+
+
+
+
+
-
-
-
-
-
-
-
-
- Upload Files
+
+
+ Attachments
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Run Model
-
+
+
+
+ Run Model
+
+
@@ -177,10 +180,8 @@
-
-
+
diff --git a/frontend/src/views/input-model-parameters/ModelParameterInput.vue b/frontend/src/views/input-model-parameters/ModelParameterInput.vue
index cb4a91b3c..48d49b536 100644
--- a/frontend/src/views/input-model-parameters/ModelParameterInput.vue
+++ b/frontend/src/views/input-model-parameters/ModelParameterInput.vue
@@ -15,51 +15,54 @@
-
- {{ tab.label }}
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Run Model
-
-
+ {{ tab.label }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Run Model
+
+
+
+
+
+
@@ -79,7 +82,6 @@ import ViewErrorMessages from '@/views/input-model-parameters/ViewErrorMessages.
import SiteInfo from '@/components/model-param-selection-panes/SiteInfo.vue'
import StandDensity from '@/components/model-param-selection-panes/StandDensity.vue'
-import AddtStandAttrs from '@/components/model-param-selection-panes/AddtStandAttrs.vue'
import ReportInfo from '@/components/model-param-selection-panes/ReportInfo.vue'
import FileUpload from '@/views/input-model-parameters/FileUpload.vue'
@@ -89,35 +91,26 @@ import { MODEL_SELECTION, MODEL_PARAM_TAB_NAME } from '@/constants/constants'
const appStore = useAppStore()
const modelParameterStore = useModelParameterStore()
-const { currentTab, modelType } = storeToRefs(appStore)
-
-const tabs = computed(() => {
- if (modelType.value === MODEL_SELECTION.FILE_UPLOAD) {
- return [
- {
- label: MODEL_PARAM_TAB_NAME.FILE_UPLOAD,
- component: FileUpload,
- },
- { label: MODEL_PARAM_TAB_NAME.MODEL_REPORT, component: ModelReport },
- { label: MODEL_PARAM_TAB_NAME.VIEW_LOG_FILE, component: ViewLogFile },
- {
- label: MODEL_PARAM_TAB_NAME.VIEW_ERROR_MESSAGES,
- component: ViewErrorMessages,
- },
- ]
- }
- return [
- {
- label: MODEL_PARAM_TAB_NAME.MODEL_PARAM_SELECTION,
- component: ModelParameterSelection,
- },
- { label: MODEL_PARAM_TAB_NAME.MODEL_REPORT, component: ModelReport },
- { label: MODEL_PARAM_TAB_NAME.VIEW_LOG_FILE, component: ViewLogFile },
- {
- label: MODEL_PARAM_TAB_NAME.VIEW_ERROR_MESSAGES,
- component: ViewErrorMessages,
- },
- ]
+const { currentTab, modelSelection } = storeToRefs(appStore)
+
+const tabs = [
+ {
+ label: MODEL_PARAM_TAB_NAME.MODEL_PARAM_SELECTION,
+ component: ModelParameterSelection,
+ },
+ { label: MODEL_PARAM_TAB_NAME.MODEL_REPORT, component: ModelReport },
+ { label: MODEL_PARAM_TAB_NAME.VIEW_LOG_FILE, component: ViewLogFile },
+ {
+ label: MODEL_PARAM_TAB_NAME.VIEW_ERROR_MESSAGES,
+ component: ViewErrorMessages,
+ },
+]
+
+const isModelParameterPanelsVisible = computed(() => {
+ return (
+ modelSelection.value === MODEL_SELECTION.INPUT_MODEL_PARAMETERS &&
+ currentTab.value === 0
+ )
})
onMounted(() => {
@@ -127,7 +120,7 @@ onMounted(() => {
const runModel = () => {}
-
diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts
index e2d5ac4d0..bc71fcdf0 100644
--- a/frontend/vite.config.ts
+++ b/frontend/vite.config.ts
@@ -1,39 +1,52 @@
import { fileURLToPath, URL } from 'node:url'
-import { defineConfig } from 'vite'
+import { defineConfig, loadEnv } from 'vite'
import Vue from '@vitejs/plugin-vue'
import Vuetify from 'vite-plugin-vuetify'
import packageVersion from 'vite-plugin-package-version'
// https://vitejs.dev/config/
-export default defineConfig({
- plugins: [
- {
- name: 'build-html',
- apply: 'build',
- transformIndexHtml: (html) => {
- return {
- html,
- tags: [
- {
- tag: 'script',
- attrs: {
- src: '/env.js',
+export default defineConfig(({ mode }) => {
+ process.env = { ...process.env, ...loadEnv(mode, process.cwd()) }
+ return {
+ plugins: [
+ {
+ name: 'build-html',
+ apply: 'build',
+ transformIndexHtml: (html) => {
+ return {
+ html,
+ tags: [
+ {
+ tag: 'script',
+ attrs: {
+ src: '/env.js',
+ },
+ injectTo: 'head',
},
- injectTo: 'head',
- },
- ],
- }
+ ],
+ }
+ },
+ },
+ Vue(),
+ packageVersion(),
+ Vuetify({
+ autoImport: true,
+ }),
+ ],
+ resolve: {
+ alias: {
+ '@': fileURLToPath(new URL('./src', import.meta.url)),
},
},
- Vue(),
- packageVersion(),
- Vuetify({
- autoImport: true,
- }),
- ],
- resolve: {
- alias: {
- '@': fileURLToPath(new URL('./src', import.meta.url)),
+ server: {
+ proxy: {
+ // Proxy API requests to the backend
+ '/api': {
+ target: process.env.VITE_API_URL,
+ changeOrigin: true,
+ rewrite: (path) => path.replace(/^\/api/, ''),
+ },
+ },
},
- },
+ }
})