Skip to content

Commit

Permalink
feat: Support downloading helicorder images in frontend
Browse files Browse the repository at this point in the history
  • Loading branch information
bclswl0827 committed Oct 11, 2024
1 parent 81a493a commit 9d0d6cf
Show file tree
Hide file tree
Showing 35 changed files with 846 additions and 174 deletions.
24 changes: 24 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,30 @@

Starting from v2.2.5, all notable changes to this project will be documented in this file.

## v3.4.0

### New Features

- Support downloading helicorder images in frontend.
- Plot helicorder image periodically.
- Added event data source of KRADE.

### Bug Fixes

- Fixed parsing errors on data sources of CENC, CWA.
- Fixed malformed serial number in legacy mode.

### Refactor

- Changed the cache data type to any.
- Made some tricks to make TypeScript happy.

### Chore

- Attach station information when exporting miniSEED data.
- Disable captcha input until captcha image is loaded.
- Clean expired miniSEED files every hour.

## v3.3.3

### New Features
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v3.3.3
v3.4.0
39 changes: 38 additions & 1 deletion docs/docs.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,43 @@ const docTemplate = `{
"responses": {}
}
},
"/helicorder": {
"post": {
"security": [
{
"ApiKeyAuth": []
}
],
"description": "This API returns a list of helicorders or exports a specific helicorder image. This API requires a valid JWT token if the server is in restricted mode.",
"produces": [
"application/json",
"application/octet-stream"
],
"summary": "Helicorder Image",
"parameters": [
{
"type": "string",
"description": "Action to be performed, Use ` + "`" + `list` + "`" + ` to get list of helicorders, ` + "`" + `export` + "`" + ` to export a specific helicorder image.",
"name": "action",
"in": "formData",
"required": true
},
{
"type": "string",
"description": "A valid filename of the helicorder image to be exported, only required when action is ` + "`" + `export` + "`" + `.",
"name": "name",
"in": "formData"
},
{
"type": "string",
"description": "Bearer JWT token, only required when the server is in restricted mode.",
"name": "Authorization",
"in": "header"
}
],
"responses": {}
}
},
"/history": {
"post": {
"security": [
Expand Down Expand Up @@ -138,7 +175,7 @@ const docTemplate = `{
"responses": {}
}
},
"/mseed": {
"/miniseed": {
"post": {
"security": [
{
Expand Down
39 changes: 38 additions & 1 deletion docs/swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,43 @@
"responses": {}
}
},
"/helicorder": {
"post": {
"security": [
{
"ApiKeyAuth": []
}
],
"description": "This API returns a list of helicorders or exports a specific helicorder image. This API requires a valid JWT token if the server is in restricted mode.",
"produces": [
"application/json",
"application/octet-stream"
],
"summary": "Helicorder Image",
"parameters": [
{
"type": "string",
"description": "Action to be performed, Use `list` to get list of helicorders, `export` to export a specific helicorder image.",
"name": "action",
"in": "formData",
"required": true
},
{
"type": "string",
"description": "A valid filename of the helicorder image to be exported, only required when action is `export`.",
"name": "name",
"in": "formData"
},
{
"type": "string",
"description": "Bearer JWT token, only required when the server is in restricted mode.",
"name": "Authorization",
"in": "header"
}
],
"responses": {}
}
},
"/history": {
"post": {
"security": [
Expand Down Expand Up @@ -130,7 +167,7 @@
"responses": {}
}
},
"/mseed": {
"/miniseed": {
"post": {
"security": [
{
Expand Down
31 changes: 30 additions & 1 deletion docs/swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,35 @@ paths:
security:
- ApiKeyAuth: []
summary: User Authentication
/helicorder:
post:
description: This API returns a list of helicorders or exports a specific helicorder
image. This API requires a valid JWT token if the server is in restricted
mode.
parameters:
- description: Action to be performed, Use `list` to get list of helicorders,
`export` to export a specific helicorder image.
in: formData
name: action
required: true
type: string
- description: A valid filename of the helicorder image to be exported, only
required when action is `export`.
in: formData
name: name
type: string
- description: Bearer JWT token, only required when the server is in restricted
mode.
in: header
name: Authorization
type: string
produces:
- application/json
- application/octet-stream
responses: {}
security:
- ApiKeyAuth: []
summary: Helicorder Image
/history:
post:
description: Get seismic waveform data from database in specified time range,
Expand Down Expand Up @@ -112,7 +141,7 @@ paths:
security:
- ApiKeyAuth: []
summary: Station Inventory
/mseed:
/miniseed:
post:
description: This API returns a list of MiniSEED files or exports a specific
MiniSEED file. This API requires a valid JWT token if the server is in restricted
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/src/components/Container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export const Container = forwardRef((props: ContainerProps, ref: ForwardedRef<HT
<div
className={
main
? "bg-gray-50 min-h-screen ml-10 p-20 px-4 flex flex-col space-y-3"
? "bg-gray-50 min-h-screen ml-10 p-20 px-4 flex flex-col space-y-4"
: className ?? ""
}
ref={ref}
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/src/components/Panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ export const Panel = (props: PanelProps) => {
return (
<div className="w-full text-gray-800">
<div className="flex flex-col shadow-lg rounded-lg">
<div className="px-4 py-3 font-bold">
{sublabel && <h6 className="text-gray-500 text-xs">{sublabel}</h6>}
<div className="mt-4 px-6 py-2 font-bold">
{sublabel && <h5 className="text-gray-500 text-xs">{sublabel}</h5>}
<h2 className={embedded ? "text-md" : "text-lg"}>{label}</h2>
</div>
<div className={`p-4 m-2 flex flex-col justify-center gap-4 ${className ?? ""}`}>
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/src/components/TableList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export const TableList = ({
}
}}
initialState={{
pagination: { paginationModel: { page: 0, pageSize: 10 } },
pagination: { paginationModel: { page: 0, pageSize: 5 } },
sorting: { sortModel: [{ field: sortField ?? "id", sort: sortDirection ?? "asc" }] }
}}
onCellClick={({ field }, event) => {
Expand Down
65 changes: 47 additions & 18 deletions frontend/src/src/config/api.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
import authRequestModel0 from "../models/request/auth/0.json";
import helicorderRequestModel0 from "../models/request/helicorder/0.json";
import helicorderRequestModel1 from "../models/request/helicorder/1.json";
import historyRequestModel0 from "../models/request/history/0.json";
import inventoryRequestModel0 from "../models/request/inventory/0.json";
import mseedRequestModel0 from "../models/request/mseed/0.json";
import mseedRequestModel1 from "../models/request/mseed/1.json";
import miniseedRequestModel0 from "../models/request/miniseed/0.json";
import miniseedRequestModel1 from "../models/request/miniseed/1.json";
import socketRequestModel0 from "../models/request/socket/0.json";
import stationRequestModel0 from "../models/request/station/0.json";
import traceRequestModel0 from "../models/request/trace/0.json";
import userRequestModel0 from "../models/request/user/0.json";
import authCommonResponseModel0 from "../models/response/common/auth/0.json";
import authCommonResponseModel1 from "../models/response/common/auth/1.json";
import authCommonResponseModel2 from "../models/response/common/auth/2.json";
import helicorderCommonResponseModel0 from "../models/response/common/helicorder/0.json";
import historyCommonResponseModel0 from "../models/response/common/history/0.json";
import inventoryCommonResponseModel0 from "../models/response/common/inventory/0.json";
import mseedCommonResponseModel0 from "../models/response/common/mseed/0.json";
import miniseedCommonResponseModel0 from "../models/response/common/miniseed/0.json";
import socketCommonResponseModel0 from "../models/response/common/socket/0.json";
import stationCommonResponseModel0 from "../models/response/common/station/0.json";
import traceCommonResponseModel0 from "../models/response/common/trace/0.json";
Expand All @@ -22,9 +25,10 @@ import userCommonResponseModel1 from "../models/response/common/user/1.json";
import userCommonResponseModel2 from "../models/response/common/user/2.json";
import userCommonResponseModel3 from "../models/response/common/user/3.json";
import authErrorResponseModel from "../models/response/error/auth.json";
import helicorderErrorResponseModel from "../models/response/error/helicorder.json";
import historyErrorResponseModel from "../models/response/error/history.json";
import mseedErrorResponseModel from "../models/response/error/mseed.json";
import inventoryErrorResponseModel from "../models/response/error/mseed.json";
import inventoryErrorResponseModel from "../models/response/error/inventory.json";
import miniseedErrorResponseModel from "../models/response/error/miniseed.json";
import stationErrorResponseModel from "../models/response/error/station.json";
import traceErrorResponseModel from "../models/response/error/trace.json";
import userErrorResponseModel from "../models/response/error/user.json";
Expand Down Expand Up @@ -138,25 +142,49 @@ const trace: Endpoint<
};

export {
mseedCommonResponseModel0,
mseedErrorResponseModel,
mseedRequestModel0,
mseedRequestModel1
miniseedCommonResponseModel0,
miniseedErrorResponseModel,
miniseedRequestModel0,
miniseedRequestModel1
};

const mseed: Endpoint<
typeof mseedRequestModel0 | typeof mseedRequestModel1,
typeof mseedCommonResponseModel0,
typeof mseedErrorResponseModel
const miniseed: Endpoint<
typeof miniseedRequestModel0 | typeof miniseedRequestModel1,
typeof miniseedCommonResponseModel0,
typeof miniseedErrorResponseModel
> = {
path: "/api/v1/mseed",
path: "/api/v1/miniseed",
method: "post",
type: "http",
model: {
request: { ...mseedRequestModel0, ...mseedRequestModel1 },
request: { ...miniseedRequestModel0, ...miniseedRequestModel1 },
response: {
common: { ...mseedCommonResponseModel0 },
error: mseedErrorResponseModel
common: { ...miniseedCommonResponseModel0 },
error: miniseedErrorResponseModel
}
}
};

export {
helicorderCommonResponseModel0,
helicorderErrorResponseModel,
helicorderRequestModel0,
helicorderRequestModel1
};

const helicorder: Endpoint<
typeof helicorderRequestModel0 | typeof helicorderRequestModel1,
typeof helicorderCommonResponseModel0,
typeof helicorderErrorResponseModel
> = {
path: "/api/v1/helicorder",
method: "post",
type: "http",
model: {
request: { ...helicorderRequestModel0, ...helicorderRequestModel1 },
response: {
common: { ...helicorderCommonResponseModel0 },
error: helicorderErrorResponseModel
}
}
};
Expand Down Expand Up @@ -234,7 +262,8 @@ export const apiConfig = {
station,
history,
trace,
mseed,
miniseed,
helicorder,
socket,
inventory,
user
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/src/config/global.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export const globalConfig: GlobalConfig = {
retention: { default: 120, maximum: 600, minimum: 10 },
footer: {
"en-US": "Listen to the whispering earth.",
"zh-CN": "听见地球",
"zh-TW": "聽見地球",
"zh-CN": "听见地球",
"zh-TW": "聽見地球",
}
};
37 changes: 28 additions & 9 deletions frontend/src/src/locales/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -278,29 +278,48 @@
}
},
"export": {
"forms": {
"search_miniseed": {
"placeholder": "Enter keyword or time"
},
"search_helicorder": {
"placeholder": "Enter keyword or time"
}
},
"buttons": {
"refresh_list": "Refresh List",
"reset_filter": "Reset Filter"
},
"panels": {
"file_list": "File List"
"miniseed_list": "miniSEED File List",
"helicorder_list": "Helicorder Scroll List"
},
"table": {
"columns": {
"id": "ID",
"name": "File Name",
"size": "File Size",
"time": "Modified Date",
"ttl": "TTL (in days)",
"time": "Modified Time",
"ttl": "Validity (Days)",
"actions": "Actions"
},
"actions": {
"export": "Export"
"export": "Export",
"download": "Download"
}
},
"toasts": {
"is_fetching_files": "Fetching file list, please wait...",
"fetch_files_success": "File list retrieved successfully",
"fetch_files_error": "Failed to retrieve file list",
"is_exporting_mseed": "Exporting MiniSEED format file, it may take some time",
"export_mseed_success": "MiniSEED format file exported successfully",
"is_fetching_mseed": "Fetching MiniSEED format file list, please wait..."
"fetch_files_success": "File list fetched successfully",
"fetch_files_error": "Failed to fetch file list",
"search_no_result": "No matching results found",
"search_n_results": "{{count}} results found",
"search_filter_reset": "Filter reset successfully",
"is_exporting_mseed": "Exporting MiniSEED file, this may take a while",
"export_mseed_success": "MiniSEED file exported successfully",
"is_downloading_helicorder": "Downloading Helicorder scroll file, this may take a while",
"download_helicorder_success": "Helicorder scroll file downloaded successfully",
"download_helicorder_error": "Failed to download Helicorder scroll file"
}
},
"setting": {
Expand Down
Loading

0 comments on commit 9d0d6cf

Please sign in to comment.