Skip to content

Commit

Permalink
Merge pull request #20 from smswithoutborders/staging
Browse files Browse the repository at this point in the history
[Feature(UI)] Implement Responsive Design with On-Page Help Notice
  • Loading branch information
PromiseFru authored May 8, 2024
2 parents 3709d80 + ee8ff5f commit fcf50c6
Show file tree
Hide file tree
Showing 16 changed files with 499 additions and 95 deletions.
1 change: 0 additions & 1 deletion .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ on:
- staging
pull_request:
branches:
- main
- staging

jobs:
Expand Down
45 changes: 45 additions & 0 deletions .github/workflows/staging-deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
name: Deploy SMSWithoutBorders Visibility Dashboard on Server (staging)
on:
push:
branches:
- staging
jobs:
deploy:
name: Execute Deployment Script on Server
runs-on: ubuntu-latest
environment:
name: staging
url: https://staging.smswithoutborders.com:18550
steps:
- name: Execute Remote SSH Commands
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
password: ${{ secrets.PASSWORD }}
script: |
set -e
echo "============================"
echo "🚀 Updating repository ..."
echo "============================"
cd ${{ secrets.PROJECT_PATH }}
if ! git pull; then
echo "❌ Error updating repository!"
exit 1
fi
echo "==============================="
echo "✅ Repository update complete"
echo "==============================="
echo "========================="
echo "🚀 Building project ..."
echo "========================="
if ! ${{ secrets.BUILD_CMD }}; then
echo "❌ Error building project!"
exit 1
fi
echo "==========================="
echo "✅ Project build complete"
echo "==========================="
40 changes: 40 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Stage 1: Build environment
FROM node:18-alpine as build
WORKDIR /app

# Copy only necessary files
COPY package.json yarn.lock ./
COPY scripts ./scripts

# Install dependencies
RUN yarn install --frozen-lockfile

# Copy the rest of the application
COPY . .

# Build the application
ARG RELIABILITY_URL
ARG RESILIENCE_URL
RUN export REACT_APP_RELIABILITY_URL=${RELIABILITY_URL} REACT_APP_RESILIENCE_URL=${RESILIENCE_URL} && \
./scripts/generate_env.sh && \
yarn build

# Stage 2: Production environment
FROM nginx:stable-alpine

# Copy built files from the build stage to NGINX html directory
COPY --from=build /app/build /usr/share/nginx/html

# Copy NGINX configuration template
COPY nginx/nginx.conf.template /etc/nginx/conf.d/default.template

# Copy entry script and make it executable
COPY scripts/docker-entrypoint.sh /docker-entrypoint.sh
RUN chmod +x /docker-entrypoint.sh

# Expose ports
EXPOSE 80
EXPOSE 443

# Start NGINX using entry script
CMD ["/docker-entrypoint.sh"]
18 changes: 18 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
services:
homepage:
container_name: visibility-dashboard
build:
context: .
dockerfile: Dockerfile
args:
- RELIABILITY_URL=${RELIABILITY_URL}
- RESILIENCE_URL=${RESILIENCE_URL}
ports:
- ${PORT:-80}:80
- ${SSL_PORT:-443}:443
environment:
- SERVER_NAME=${SERVER_NAME:-localhost}
volumes:
- ${SSL_CERTIFICATE_PATH:?err}:/etc/nginx/ssl/cert.pem
- ${SSL_KEY_PATH:?err}:/etc/nginx/ssl/key.pem
- ${SSL_CHAIN_PATH:?err}:/etc/nginx/ssl/chain.pem
43 changes: 43 additions & 0 deletions nginx/nginx.conf.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
server {
listen 80;
server_name {{SERVER_NAME}};
return 301 https://$host$request_uri;
}

server {
listen 443 ssl http2;
server_name {{SERVER_NAME}};

ssl_certificate /etc/nginx/ssl/cert.pem;
ssl_certificate_key /etc/nginx/ssl/key.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
ssl_ecdh_curve secp384r1;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/nginx/ssl/chain.pem;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload";
add_header X-XSS-Protection "1; mode=block";
add_header Referrer-Policy "strict-origin";
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://cdnjs.cloudflare.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com https://cdnjs.cloudflare.com; font-src 'self' https://fonts.gstatic.com https://cdnjs.cloudflare.com; img-src 'self' data: https://www.google-analytics.com; connect-src 'self' https://www.google-analytics.com https://6616b7bbed6b8fa4348132c4.mockapi.io/api/v1/reliability https://6616b7bbed6b8fa4348132c4.mockapi.io/api/v1/resilience;";
add_header Permissions-Policy "geolocation=(),midi=(),sync-xhr=(),microphone=(),camera=(),magnetometer=(),gyroscope=(),fullscreen=(self),payment=()";
add_header X-Frame-Options "SAMEORIGIN";
add_header X-Content-Type-Options nosniff;

server_tokens off;

access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;

root /usr/share/nginx/html;
index index.html;

location / {
try_files $uri $uri.html $uri/ /index.html;
}
}
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"name": "gateway-client-reliability-dashboard",
"name": "visibility-dashboard",
"license": "GPL-3.0-only",
"version": "0.1.0",
"private": true,
"dependencies": {
Expand Down Expand Up @@ -28,7 +29,7 @@
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject",
"prepare": "husky install"
"prepare": "husky"
},
"eslintConfig": {
"extends": [
Expand Down
11 changes: 11 additions & 0 deletions scripts/docker-entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/bin/sh
set -e

# Replace placeholders in NGINX configuration template with environment variable values
sed -i "s|{{SERVER_NAME}}|${SERVER_NAME}|g" /etc/nginx/conf.d/default.template

# Copy the modified NGINX configuration from template
cp /etc/nginx/conf.d/default.template /etc/nginx/conf.d/default.conf

# Start NGINX
nginx -g "daemon off;"
7 changes: 7 additions & 0 deletions scripts/generate_env.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/sh

# Generate the .env.local file
cat <<EOF > .env.local
REACT_APP_RELIABILITY_URL=$REACT_APP_RELIABILITY_URL
REACT_APP_RESILIENCE_URL=$REACT_APP_RESILIENCE_URL
EOF
2 changes: 2 additions & 0 deletions src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import Data from "./Pages/TableDialog";
import PageNotFound from "./Pages/404";
import Reliability from "./Pages/Reliability";
import Resilience from "./Pages/Resilience";
import MobileNav from "./Components/MobileNav";

function App() {
const [darkMode, setDarkMode] = useState(
Expand Down Expand Up @@ -64,6 +65,7 @@ function App() {
<ThemeProvider theme={theme}>
<CssBaseline />
<Router>
<MobileNav darkMode={darkMode} toggleDarkMode={toggleDarkMode} />
<ResponsiveDrawer darkMode={darkMode} toggleDarkMode={toggleDarkMode} />
<Toggle darkMode={darkMode} toggleDarkMode={toggleDarkMode} />
<Routes>
Expand Down
37 changes: 34 additions & 3 deletions src/Components/Footer.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,43 @@ import { Box, Divider, Grid, Typography } from "@mui/material";
import React from "react";
import { FaFacebook, FaGithub, FaXTwitter } from "react-icons/fa6";

const drawerWidth = 240;

export default function Footer() {
return (
<Box component="footer" sx={{ position: "relative", bottom: 0 }}>
<Box
component="footer"
sx={{
px: { md: 3, sm: 3, xs: 2 },
pb: { md: 3, sm: 3, xs: 14 },
flexGrow: 1,
bottom: 0,
position: "static"
}}
>
<Grid container sx={{ p: 2 }}>
<Grid item md={2} xs={12} sm={12}></Grid>
<Grid item md={9} xs={12} sm={12}>
<Grid
item
lg={2}
md={3}
xs={0}
sm={3}
sx={{
display: { xs: "none", sm: "none", md: "block" },
"& .MuiDrawer-paper": { boxSizing: "border-box", width: drawerWidth }
}}
></Grid>
<Grid
item
lg={10}
md={9}
xs={12}
sm={12}
sx={{
p: { md: 3, sm: 2, xs: 0 },
width: { sm: `calc(100% - ${drawerWidth}px)`, md: `calc(100% - ${drawerWidth}px)` }
}}
>
<Divider sx={{ width: "100%" }} />
<Box display="flex" justifyContent="space-between" sx={{ p: 2 }}>
<Typography variant="body2">© {new Date().getFullYear()} SMSWithoutBorders</Typography>
Expand Down
102 changes: 102 additions & 0 deletions src/Components/MobileNav.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import * as React from "react";
import Box from "@mui/material/Box";
import Toolbar from "@mui/material/Toolbar";
import IconButton from "@mui/material/IconButton";
import Typography from "@mui/material/Typography";
import Menu from "@mui/material/Menu";
import MenuIcon from "@mui/icons-material/Menu";
import Container from "@mui/material/Container";
import MenuItem from "@mui/material/MenuItem";
import Brightness4Icon from "@mui/icons-material/Brightness4";
import Brightness7Icon from "@mui/icons-material/Brightness7";
import { Link } from "react-router-dom";

function MobileNav({ darkMode, toggleDarkMode }) {
const [anchorElNav, setAnchorElNav] = React.useState(null);

const handleOpenNavMenu = (event) => {
setAnchorElNav(event.currentTarget);
};

const handleCloseNavMenu = () => {
setAnchorElNav(null);
};

return (
<nav style={{ backgroundColor: "transparent" }}>
<Container
maxWidth="sm"
sx={{
display: { xs: "flex", md: "none" },
justifyContent: "space-between",
alignItems: "center"
}}
>
<Box display="flex">
<Typography variant="body1" sx={{ fontWeight: 600, px: 2 }}>
SWOB Dashboard
</Typography>
</Box>{" "}
<Toolbar disableGutters>
<Box sx={{ flexGrow: 0, left: 0 }}>
<IconButton
size="large"
aria-label="menu"
aria-controls="menu-appbar"
aria-haspopup="true"
onClick={handleOpenNavMenu}
color="inherit"
>
<MenuIcon />
</IconButton>
<Menu
id="menu-appbar"
anchorEl={anchorElNav}
anchorOrigin={{
vertical: "bottom",
horizontal: "right"
}}
keepMounted
transformOrigin={{
vertical: "top",
horizontal: "right"
}}
open={Boolean(anchorElNav)}
onClose={handleCloseNavMenu}
sx={{
display: { xs: "block", md: "none" }
}}
>
<MenuItem onClick={handleCloseNavMenu}>
<Typography textAlign="center" component={Link} href="/reliability">
Reliability
</Typography>
</MenuItem>

<MenuItem onClick={handleCloseNavMenu} component={Link} href="/resilience">
<Typography textAlign="center">Resilience</Typography>
</MenuItem>

<MenuItem onClick={handleCloseNavMenu} component={Link} href="/help">
<Typography textAlign="center">Help</Typography>
</MenuItem>

<MenuItem onClick={handleCloseNavMenu} component={Link} href="/contact">
<Typography textAlign="center">Contact</Typography>
</MenuItem>
</Menu>
<IconButton
onClick={toggleDarkMode}
sx={{ ml: 2 }}
aria-label={darkMode ? "Light Mode" : "Dark Mode"}
color="inherit"
>
{darkMode ? <Brightness7Icon /> : <Brightness4Icon />}
</IconButton>
</Box>
</Toolbar>
</Container>
</nav>
);
}
export default MobileNav;
Loading

0 comments on commit fcf50c6

Please sign in to comment.