Skip to content

Commit

Permalink
Merge pull request #529 from PacoVK/feature/message-attributes
Browse files Browse the repository at this point in the history
Feature/message attributes
  • Loading branch information
PacoVK committed Jul 13, 2023
2 parents 41a15be + f452be0 commit c33c830
Show file tree
Hide file tree
Showing 15 changed files with 587 additions and 58 deletions.
3 changes: 0 additions & 3 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,6 @@ on:
- main
tags:
- "v*.*.*"
pull_request:
branches:
- "main"

jobs:
docker:
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ To configure the backend for local development you can set the following environ
| HTTP_PORT | Port that the internal backend binds to and is serving | 3999 |

## Designed and tested with

![Localstack](https://raw.githubusercontent.com/localstack/.github/main/assets/localstack-readme-banner.svg)

### Legal note
Expand Down
25 changes: 0 additions & 25 deletions esbuild/serve.js

This file was deleted.

15 changes: 15 additions & 0 deletions esbuild/serve.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import * as esbuild from "esbuild";

const ctx = await esbuild.context({
bundle: true,
entryPoints: ["frontend/index.tsx"],
minify: false,
outfile: "public/assets/app.js",
});

await ctx.watch();

let { host, port } = await ctx.serve({
servedir: "public",
port: 3000,
});
4 changes: 3 additions & 1 deletion frontend/api/Http.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { ApiCall } from "../types";

const callApi = async (apiCall: ApiCall) => {
fetch("/sqs", {
const baseUrl =
process.env.NODE_ENV === "development" ? "http://localhost:3999" : "";
fetch(`${baseUrl}/sqs`, {
method: apiCall.method,
headers: {
Accept: "application/json",
Expand Down
4 changes: 2 additions & 2 deletions frontend/components/CreateQueueDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,13 @@ const CreateQueueDialog = (props: CreateQueueDialogProps) => {
};

const handleChangeQueueName = (
event: React.ChangeEvent<HTMLInputElement>
event: React.ChangeEvent<HTMLInputElement>,
) => {
setQueueName(event.target.value);
};

const handleChangeFifoSwitch = (
event: React.ChangeEvent<HTMLInputElement>
event: React.ChangeEvent<HTMLInputElement>,
) => {
enableFifoQueue(event.target.checked);
};
Expand Down
61 changes: 54 additions & 7 deletions frontend/components/MessageItem.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
import React from "react";
import { Card, CardContent, CardHeader } from "@mui/material";
import {
Accordion,
AccordionDetails,
AccordionSummary,
Box,
Card,
CardContent,
CardHeader,
Divider,
Stack,
Typography,
} from "@mui/material";
import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
import { SqsMessage } from "../types";
import { JSONTree } from "react-json-tree";

Expand All @@ -23,10 +35,10 @@ const MessageItem = (props: { data: SqsMessage }) => {
title={`MessageId: ${props.data.messageId}`}
subheader={`Sent on: ${toLocaleString(
// @ts-ignore
props.data.messageAttributes.SentTimestamp
props.data.messageAttributes.SentTimestamp,
)}, Received at: ${toLocaleString(
// @ts-ignore
props.data.messageAttributes.ApproximateFirstReceiveTimestamp
props.data.messageAttributes.ApproximateFirstReceiveTimestamp,
)}
${
props.data.messageAttributes?.MessageGroupId
Expand All @@ -37,10 +49,45 @@ const MessageItem = (props: { data: SqsMessage }) => {
`}
/>
<CardContent>
<JSONTree
data={getJsonOrRawData(props.data.messageBody)}
keyPath={["message"]}
/>
{props.data.messageAttributes?.CustomAttributes ? (
<Accordion>
<AccordionSummary
expandIcon={<ExpandMoreIcon />}
aria-controls="panel1a-content"
id="panel1a-header"
>
<Typography>Message Attributes</Typography>
</AccordionSummary>
<AccordionDetails>
{
// @ts-ignore
Object.entries(
JSON.parse(props.data.messageAttributes.CustomAttributes),
).map(([key, value]) => {
return (
<Box key={key}>
<Divider />
<Stack direction="row" sx={{ ml: 0 }} spacing={2}>
<Typography>Key: {key}</Typography>
<Typography>Value: {value as string}</Typography>
</Stack>
<Divider />
</Box>
);
})
}
</AccordionDetails>
</Accordion>
) : null}

<Accordion expanded={true}>
<AccordionDetails sx={{ pt: 1, pb: 1 }}>
<JSONTree
data={getJsonOrRawData(props.data.messageBody)}
keyPath={["message"]}
/>
</AccordionDetails>
</Accordion>
</CardContent>
</Card>
</>
Expand Down
99 changes: 99 additions & 0 deletions frontend/components/SendMessageDialog.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,30 @@
import React, { useState } from "react";
import {
Box,
Button,
Dialog,
DialogActions,
DialogContent,
DialogContentText,
DialogTitle,
Divider,
Fab,
TextField,
Typography,
} from "@mui/material";
import AddIcon from "@mui/icons-material/Add";
import DeleteIcon from "@mui/icons-material/Delete";
import { SendMessageDialogProps, SqsMessage } from "../types";

const SendMessageDialog = (props: SendMessageDialogProps) => {
const [open, setOpen] = useState(false);
const [messageBody, setMessageBody] = useState("");
const [messageGroupId, setMessageGroupId] = useState("");
const [messageAttributes, setMessageAttributes] = useState(
{} as { [key: string]: string },
);
const [attributeKey, setAttributeKey] = useState("");
const [attributeValue, setAttributeValue] = useState("");

const handleClickOpen = () => {
setMessageBody("");
Expand All @@ -22,6 +33,7 @@ const SendMessageDialog = (props: SendMessageDialogProps) => {
};

const handleClose = () => {
setMessageAttributes({});
setOpen(false);
};

Expand All @@ -36,6 +48,12 @@ const SendMessageDialog = (props: SendMessageDialogProps) => {
const submitSendRequest = () => {
let sqsMessage: SqsMessage = {
messageBody: messageBody,
messageAttributes: {
CustomAttributes:
Object.entries(messageAttributes).length > 0
? JSON.stringify(messageAttributes)
: undefined,
},
};
if (messageGroupId !== "") {
sqsMessage.messageAttributes = {
Expand Down Expand Up @@ -88,6 +106,87 @@ const SendMessageDialog = (props: SendMessageDialogProps) => {
}}
variant="standard"
/>
<Typography variant="h6" sx={{ mt: 2 }}>
Custom Message Attributes
</Typography>
<TextField
margin="dense"
id="addNewAttribute-key"
label="Attribute key"
type="text"
onChange={(event) => {
setAttributeKey(event.target.value);
}}
fullWidth
value={attributeKey}
variant="standard"
/>
<TextField
margin="dense"
id="addNewAttribute-value"
label="Attribute value"
type="text"
onChange={(event) => {
setAttributeValue(event.target.value);
}}
fullWidth
value={attributeValue}
variant="standard"
/>
<Box sx={{ direction: "rtl" }}>
<Fab
size="small"
color="primary"
aria-label="add"
sx={{ alignSelf: "end" }}
onClick={() => {
if (attributeKey.trim() === "" || attributeValue.trim() === "")
return;
setMessageAttributes({
...messageAttributes,
[attributeKey]: attributeValue,
});
setAttributeKey("");
setAttributeValue("");
}}
>
<AddIcon />
</Fab>
</Box>
<Divider sx={{ mt: "1em", mb: "1em" }} />
{Object.keys(messageAttributes).map((key) => {
return (
<Box
key={key}
sx={{ display: "flex", justifyContent: "space-between" }}
>
<TextField
margin="dense"
key={key}
id={key}
label={key}
type="text"
onChange={(event) => {
setMessageAttributes({
...messageAttributes,
[key]: event.target.value,
});
}}
fullWidth
value={messageAttributes[key]}
variant="standard"
/>
<DeleteIcon
sx={{ m: "auto" }}
onClick={() => {
const { [key]: value, ...newAttributes } =
messageAttributes;
setMessageAttributes(newAttributes);
}}
/>
</Box>
);
})}
</DialogContent>
<DialogActions>
<Button onClick={handleClose}>Cancel</Button>
Expand Down
1 change: 1 addition & 0 deletions frontend/types/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export interface SqsMessage {
SenderId?: string;
SentTimestamp?: string;
SequenceNumber?: string;
CustomAttributes?: string | { [key: string]: string };
}
| undefined;
}
Expand Down
2 changes: 1 addition & 1 deletion frontend/views/Overview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ const Overview = () => {
!message.messageAttributes?.MessageGroupId
) {
setError(
"You need to set a MessageGroupID when sending Messages to a FIFO queue"
"You need to set a MessageGroupID when sending Messages to a FIFO queue",
);
return;
}
Expand Down
9 changes: 6 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@
"react-json-tree": "^0.18.0"
},
"scripts": {
"start": "node esbuild/serve.js",
"start": "node esbuild/serve.mjs",
"build": "node esbuild/build.js",
"prettier": "prettier --write ."
"prettier": "prettier --write .",
"test": "react-scripts test"
},
"eslintConfig": {
"extends": [
Expand All @@ -41,14 +42,16 @@
]
},
"devDependencies": {
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^14.0.0",
"@types/jest": "^29.5.2",
"@types/node": "^20.4.1",
"@types/react": "^18.2.14",
"@types/react-dom": "^18.2.6",
"chokidar": "^3.5.3",
"esbuild": "^0.18.11",
"live-server": "^1.2.2",
"prettier": "2.8.8",
"prettier": "3.0.0",
"react-scripts": "5.0.1",
"typescript": "^5.1.6"
}
Expand Down
2 changes: 1 addition & 1 deletion public/index.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!DOCTYPE html>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
Expand Down
Loading

0 comments on commit c33c830

Please sign in to comment.