Skip to content

Commit

Permalink
[Frontend] Bootstrap 5 Upgrade (#90)
Browse files Browse the repository at this point in the history
* Update to Bootstrap 5 and FontAwesome

* Add GitHub links
  • Loading branch information
justinh-rahb authored Sep 25, 2023
1 parent 48ac865 commit f303c7b
Show file tree
Hide file tree
Showing 11 changed files with 289 additions and 208 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/dependabot-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ on:

jobs:
release:
if: github.event.pull_request.merged == true && github.event.pull_request.user.login == 'github-actions[bot]'
if: github.event.pull_request.merged == true && github.event.pull_request.user.login == 'dependabot[bot]'
runs-on: ubuntu-latest
steps:
- name: Checkout code
Expand Down
22 changes: 11 additions & 11 deletions .github/workflows/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,14 @@ jobs:
run: |
pylint -E -d import-error $(git ls-files '*.py')
dependabot:
name: 'Dependabot'
needs: [build, test] # After the build and test jobs, if one of them fails, it won't merge the PR.
runs-on: ubuntu-latest
if: ${{ github.actor == 'dependabot[bot]' && github.event_name == 'pull_request'}} # Detect that the PR author is dependabot
steps:
- name: Enable auto-merge for Dependabot PRs
run: gh pr merge --auto --merge "$PR_URL" # Use Github CLI to merge automatically the PR
env:
PR_URL: ${{github.event.pull_request.html_url}}
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
#dependabot:
# name: 'Dependabot'
# needs: [build, test] # After the build and test jobs, if one of them fails, it won't merge the PR.
# runs-on: ubuntu-latest
# if: ${{ github.actor == 'dependabot[bot]' && github.event_name == 'pull_request'}} # Detect that the PR author is dependabot
# steps:
# - name: Enable auto-merge for Dependabot PRs
# run: gh pr merge --auto --merge "$PR_URL" # Use Github CLI to merge automatically the PR
# env:
# PR_URL: ${{github.event.pull_request.html_url}}
# GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
10 changes: 0 additions & 10 deletions app.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,11 @@
app.config.from_object("settings")


@app.route('/sitemap.xml')
def static_from_root():
return send_from_directory(app.static_folder, request.path[1:])


@app.route("/instructions")
def instructions():
return render_template("instructions.html")


@app.route("/contact")
def contact():
return render_template("contact.html")


@app.route("/", methods=["GET", "POST"])
def index():
if request.method == "POST":
Expand Down
47 changes: 47 additions & 0 deletions static/form.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
document.addEventListener('DOMContentLoaded', function() {
const alert = document.getElementById('disclaimer');
const dismissLink = document.getElementById('dismiss');
const fileInput = document.getElementById('file-upload');
const sendBtn = document.getElementById('sendBtn');
const checkmarkSpan = document.getElementById('checkmark');
const sendIcon = document.getElementById("sendIcon");
const spinner = document.getElementById("spinner");

// Check if the alert has been closed.
if (sessionStorage.getItem('alertClosed') === 'true') {
alert.style.display = 'none';
}

// Check if the alert has been dismissed.
if (localStorage.getItem('alertDismissed') === 'true') {
alert.style.display = 'none';
}

// Handle click event on the "Dismiss" link.
dismissLink.addEventListener('click', function(e) {
e.preventDefault(); // Prevent default action (navigation).
localStorage.setItem('alertDismissed', 'true'); // Set item in localStorage.
new bootstrap.Alert(alert).close(); // Close the alert.
});

// Listen for the close event of the alert.
alert.addEventListener('close.bs.alert', function() {
// When the alert is closed, set the item in sessionStorage.
sessionStorage.setItem('alertClosed', 'true');
});

fileInput.addEventListener('change', function() {
if (fileInput.files.length > 0) {
// Show checkmark if a file is uploaded.
checkmarkSpan.classList.remove('d-none');
} else {
// Hide checkmark if no file is uploaded.
checkmarkSpan.classList.add('d-none');
}
});

sendBtn.addEventListener("click", function() {
sendIcon.classList.add("d-none"); // Hide send icon.
spinner.classList.remove("d-none"); // Show spinner.
});
});
21 changes: 0 additions & 21 deletions static/sitemap.xml

This file was deleted.

25 changes: 20 additions & 5 deletions static/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,24 @@
}

.mt-50 {
margin-top: 50px !important;
}
margin-top: 50px !important;
}

.mt-15 {
margin-top: 15px !important;
}

.spinner-border {
width: 1.25rem;
height: 1.25rem;
}

a#dismiss {
font-size: 0.85rem;
color: #41464b;
margin-right: -30px;
}

.mt-15 {
margin-top: 15px !important;
}
a:hover#dismiss,a:focus#dismiss,a:active#dismiss {
color: #000;
}
136 changes: 76 additions & 60 deletions templates/base.html
Original file line number Diff line number Diff line change
@@ -1,64 +1,80 @@
<!doctype html>
<!DOCTYPE html>

<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="shortcut icon" href="{{ url_for('static', filename='favicon.ico') }}">
<title>{% block title %}{% endblock %} - Bulk SMS Sender</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous">
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
<script src="https://code.jquery.com/jquery-1.12.4.min.js" integrity="sha384-nvAa0+6Qg9clwYCGGPpDQLVpLNn0fRaROjHqs13t4Ggj3Ez50XnGQqc/r8MhnRDZ" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js" integrity="sha384-aJ21OjlMXNL5UyIl/XNwTMqvzeRMZH2w8c5cRVpzpU8Y5bApTppSuUkhZXN0VxHd" crossorigin="anonymous"></script>
</head>
<body>
<nav class="navbar navbar-inverse">
<div class="container-fluid ">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="{{ url_for('index') }}"><span class="glyphicon glyphicon-envelope" aria-hidden="true"></span> Bulk SMS Sender</a>
</div>
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
<li><a href="{{ url_for('index') }}">Home <span class="sr-only">(current)</span></a></li>
<li><a href="{{ url_for('instructions') }}">Instructions</a></li>
</ul>
<ul class="nav navbar-nav navbar-right">
</ul>
</div><!-- /.navbar-collapse -->
</div><!-- /.container-fluid -->
</nav>

<div class="container">
{% with messages = get_flashed_messages() %}
{% if messages %}
<div class="panel panel-danger">
<div class="panel-heading">
<h3>Error!</h3>
</div>
<div class="panel-body">
<ul>
{% for message in messages %}
<li>{{ message }}</li>
{% endfor %}
</ul>
</div>
</div>
{% endif %}
{% endwith %}
<div class="jumbotron">
<h1>Bulk SMS Sender</h1>
<p>Send SMS messages to multiple recipients using Twilio's API</p>
<head>
<meta charset="utf-8" />
<meta content="IE=edge" http-equiv="X-UA-Compatible" />
<meta content="width=device-width, initial-scale=1" name="viewport" />
<link href="{{ url_for('static', filename='favicon.ico') }}" rel="shortcut icon" />
<title>{% block title %}{% endblock %} - Bulk SMS Sender</title>
<link crossorigin="anonymous" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"
integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" rel="stylesheet" />
<link href="{{ url_for('static', filename='style.css') }}" rel="stylesheet" />
<script crossorigin="anonymous" src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"
integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4"></script>
<link crossorigin="anonymous" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css"
integrity="sha384-DyZ88mC6Up2uqS4h/KRgHuoeGwBcD4Ng9SiP4dIRy0EXTlnuz47vAwmeGwVChigm" rel="stylesheet" referrerpolicy="no-referrer" />
</head>

<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<div class="container-fluid">
<a class="navbar-brand" href="{{ url_for('index') }}"><span aria-hidden="true" class="fas fa-envelope"></span> Bulk SMS Sender</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<a class="nav-link" href="{{ url_for('index') }}">
<span aria-hidden="true" class="fas fa-paper-plane"></span> Send SMS
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{ url_for('instructions') }}">
<span aria-hidden="true" class="fas fa-info-circle"></span> Instructions
</a>
</li>
</ul>
<ul class="navbar-nav ms-auto">
<li class="nav-item">
<a class="nav-link" href="https://rahb-realtors-association.github.io/sms-sender" target="_blank" rel="noopener noreferrer">
<span aria-hidden="true" class="fas fa-book"></span> Docs
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="https://github.com/RAHB-REALTORS-Association/sms-sender" target="_blank" rel="noopener noreferrer">
<span aria-hidden="true" class="fab fa-github"></span> GitHub
</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="container">
{% with messages = get_flashed_messages() %}
{% if messages %}
<div class="alert alert-danger mb-3 mt-15" role="alert">
<div class="d-flex align-items-center">
<i class="fas fa-exclamation-triangle me-2 pb-2"></i>
<h4>Application Error</h4>
</div>
{% block content %}
{% endblock %}
<ul>
{% for message in messages %}
<p>{{ message }}</p>
{% endfor %}
</ul>
</div>
{% endif %}
{% endwith %}
<div class="container bg-light p-5 my-3 rounded text-center">
<h1 class="display-4">📲📩</h1>
<p class="lead">Send SMS messages to multiple recipients using Twilio's API</p>
</div>
<script src="https://code.jquery.com/jquery-1.12.4.min.js" integrity="sha384-nvAa0+6Qg9clwYCGGPpDQLVpLNn0fRaROjHqs13t4Ggj3Ez50XnGQqc/r8MhnRDZ" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js" integrity="sha384-aJ21OjlMXNL5UyIl/XNwTMqvzeRMZH2w8c5cRVpzpU8Y5bApTppSuUkhZXN0VxHd" crossorigin="anonymous"></script>
</body>
</html>
{% block content %}
{% endblock %}
</div>
</body>

</html>
88 changes: 53 additions & 35 deletions templates/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,40 +3,58 @@
{% block title %}Welcome{% endblock %}

{% block content %}
<div class="panel panel-danger">
<div class="panel-heading">
<h3 class="panel-title"><span class="glyphicon glyphicon-alert" aria-hidden="true"></span> First, some important stuff</h3>
</div>
<div class="panel-body">
<ul>
<li>This site is not related to nor supported or endorsed by Twilio Inc. in any way</li>
<li>This site just provides a simple interface for Twilio's SMS service</li>
<li>This site doesn't store your credentials in any form but it's still safer to use tokens. Please check <a href="https://www.twilio.com/docs/iam/access-tokens#creating-tokens" target="_blank">this page</a> for instructions on how to do it</li>
<li>The source code for this site is available on <a href="https://github.com/RAHB-REALTORS-Association/sms-sender" target="_blank">GitHub</a></li>
<div class="alert alert-secondary alert-dismissible fade show mb-3 mt-15" role="alert" id="disclaimer">
<div class="d-flex align-items-center">
<i class="fas fa-info-circle me-2"></i>
<h4 class="mb-0">Important Notes</h4>
</div>
<ul class="my-2">
<li>This application is not related to nor supported or endorsed by Twilio Inc.</li>
<li>This application just provides a simple interface for Twilio's SMS service</li>
<li>This application doesn't store your credentials. Please check <a
href="https://www.twilio.com/docs/iam/access-tokens#creating-tokens" target="_blank">this page</a> for
instructions on how to create a token</li>
<li>The <a href="https://rahb-realtors-association.github.io/sms-sender" target="_blank">documentation</a> and
<a href="https://github.com/RAHB-REALTORS-Association/sms-sender" target="_blank">source code</a>
for this application is available on GitHub</li>
</ul>
<div class="d-flex align-items-center">
<a href="#" class="text-decoration-none ms-auto" id="dismiss">Don't show again</a>
</div>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
</div>
<p>
Welcome to the Bulk SMS Sender. This tool allows you to send bulk messages via Twilio's API from a simple CSV input file. Please head on over to the <a href="{{ url_for('instructions') }}">instructions page</a> if this is your first time here and let's get
started!
<div id="upload_form" class="form-inline">
<form method="post" enctype="multipart/form-data">
<div class="mt-15">
<input type="text" class="form-control" placeholder="{{ sid_placeholder or 'Twilio Account SID' }}" aria-describedby="basic-addon1" name="sid" size="50">
</div>
<div class="mt-15">
<input type="password" class="form-control" placeholder="{{ token_placeholder or 'Twilio Token' }}" aria-describedby="basic-addon1" name="token" size="50">
</div>
<div class="mt-15">
<input type="text" class="form-control" placeholder="{{ csv_url_placeholder or 'CSV URL' }}" aria-describedby="basic-addon1" name="csv_url" size="50">
</div>
<div class="mt-15">
<input type="file" name="file">
</div>
<div class="mt-15">
<input type="submit" value="Send messages">
</div>
</form>
</div>
</p>
{% endblock %}
<p>
Welcome to the Bulk SMS Sender. This tool allows you to send bulk messages via Twilio's API from a simple CSV input
file. Please see the <a href="{{ url_for('instructions') }}">instructions page</a> if this is your first
time using the application.
<div class="form-inline" id="upload_form">
<form enctype="multipart/form-data" method="post">
<div class="mt-15">
<input aria-describedby="basic-addon1" class="form-control" name="sid" id="sid"
placeholder="{{ sid_placeholder or 'Twilio Account SID' }}" size="50" type="text" />
</div>
<div class="mt-15">
<input aria-describedby="basic-addon1" class="form-control" name="token" id="token"
placeholder="{{ token_placeholder or 'Twilio Token' }}" size="50" type="password" />
</div>
<div class="mt-15">
<input aria-describedby="basic-addon1" class="form-control" name="csv_url" id="csv_url"
placeholder="{{ csv_url_placeholder or 'CSV URL' }}" size="50" type="text" />
</div>
<div class="mb-3 mt-15 d-flex align-items-center justify-content-between">
<label for="file-upload" class="btn btn-primary btn-lg">
<input type="file" id="file-upload" name="file" class="d-none" />
Upload CSV
<span class="d-none" id="checkmark"><i class="fas fa-check-circle"></i></span>
</label>
<button type="submit" class="btn btn-primary btn-lg" id="sendBtn">
Send <i class="fas fa-paper-plane" id="sendIcon"></i>
<div class="spinner-border text-light d-none" role="status" id="spinner">
</div>
</button>
</div>
</form>
</div>
</p>
<script src="{{ url_for('static', filename='form.js') }}"></script>
{% endblock %}
Loading

0 comments on commit f303c7b

Please sign in to comment.