🔨 Convert list + modal to Bootstrap

This commit is contained in:
Sebastien Clement 2021-01-08 01:49:21 +01:00
parent ae1cc25cb0
commit 59afab1120
10 changed files with 177 additions and 143 deletions

View File

@ -23,8 +23,14 @@ app.use(express.json());
app.use(express.urlencoded({ extended: false })); app.use(express.urlencoded({ extended: false }));
app.use(cookieParser()); app.use(cookieParser());
app.use(express.static(path.join(__dirname, "public"))); app.use(express.static(path.join(__dirname, "public")));
app.use('/js/',express.static(path.join(__dirname, '/node_modules/bootstrap/dist/js')))
app.use('/font/',express.static(path.join(__dirname, '/node_modules/bootstrap-icons/font'))) // Boootstrap JS Files
app.use('/js/', express.static(path.join(__dirname, '/node_modules/bootstrap/dist/js')))
// Fontawesome files
app.use('/css/', express.static(path.join(__dirname, '/node_modules/@fortawesome/fontawesome-free/css')))
app.use('/webfonts/', express.static(path.join(__dirname, '/node_modules/@fortawesome/fontawesome-free/webfonts')))
app.use("/", indexRouter); app.use("/", indexRouter);
app.use("/api", apiRouter); app.use("/api", apiRouter);

View File

@ -88,6 +88,11 @@
} }
} }
}, },
"@fortawesome/fontawesome-free": {
"version": "5.15.1",
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-5.15.1.tgz",
"integrity": "sha512-OEdH7SyC1suTdhBGW91/zBfR6qaIhThbcN8PUXtXilY4GYnSBbVqOntdHbC1vXwsDnX0Qix2m2+DSU1J51ybOQ=="
},
"@sindresorhus/is": { "@sindresorhus/is": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.0.0.tgz", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.0.0.tgz",
@ -356,11 +361,6 @@
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.0.0-beta1.tgz", "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.0.0-beta1.tgz",
"integrity": "sha512-UrHApw/WRmT7l2rlDdn5iXr7Jps/LlMZtJlLn9G41aGDfss48hyDeYyHtX1C6NHKVcmdUarGG+ve0LZB5iHyTQ==" "integrity": "sha512-UrHApw/WRmT7l2rlDdn5iXr7Jps/LlMZtJlLn9G41aGDfss48hyDeYyHtX1C6NHKVcmdUarGG+ve0LZB5iHyTQ=="
}, },
"bootstrap-icons": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/bootstrap-icons/-/bootstrap-icons-1.2.2.tgz",
"integrity": "sha512-7rFICA7E/CgYLvu8zYtd2wMZYhYPQ0GtogZtQyJz/3melCGeQ76qas5wItIEwiUNmtZWg2SP2p8Ekxy3Nk7vvg=="
},
"brace-expansion": { "brace-expansion": {
"version": "1.1.11", "version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@ -481,7 +481,7 @@
"color-convert": { "color-convert": {
"version": "1.9.3", "version": "1.9.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "integrity": "sha1-u3GFBpDh8TZWfeYp0tVHHe2kweg=",
"requires": { "requires": {
"color-name": "1.1.3" "color-name": "1.1.3"
} }

View File

@ -6,9 +6,9 @@
"start": "node --inspect=0.0.0.0:9226 ./bin/www " "start": "node --inspect=0.0.0.0:9226 ./bin/www "
}, },
"dependencies": { "dependencies": {
"@fortawesome/fontawesome-free": "^5.15.1",
"app-root-path": "^3.0.0", "app-root-path": "^3.0.0",
"bootstrap": "^5.0.0-beta1", "bootstrap": "^5.0.0-beta1",
"bootstrap-icons": "^1.2.2",
"cookie-parser": "^1.4.5", "cookie-parser": "^1.4.5",
"cron": "^1.8.2", "cron": "^1.8.2",
"debug": "~2.6.9", "debug": "~2.6.9",

File diff suppressed because one or more lines are too long

View File

@ -1,7 +1,10 @@
.navbar{ .navbar{
background-color: #0091ea ; background-color: #0091ea ;
} }
#header-box{ #header-box{
height: 150px; min-height: 150px;
}
.btn .bi::before{
vertical-align: middle ;
} }

View File

@ -48,6 +48,10 @@ router.get("/formated-local-snap", function (req, res, next) {
if (moment(a.lastmod).isBefore(moment(b.lastmod))) return 1; if (moment(a.lastmod).isBefore(moment(b.lastmod))) return 1;
else return -1; else return -1;
}); });
//TODO Remove this when bug is fixed, etag contain '"' at start and end ?
for(let backup of contents){
backup.etag = backup.etag.replace(/"/g, '');
}
res.render("backupSnaps", { backups: contents, moment: moment, humanFileSize: humanFileSize }); res.render("backupSnaps", { backups: contents, moment: moment, humanFileSize: humanFileSize });
}) })
.catch(() => { .catch(() => {

View File

@ -1,9 +1,9 @@
$body-bg: #222222; $body-bg: #222222;
$dark: #292929; $dark: #292929;
$secondary: #343a40; $secondary: #343a40;
$accent: #b58e51; $accent: #b58e51;
@import "../node_modules/bootstrap/scss/bootstrap"; @import "../node_modules/bootstrap/scss/bootstrap";
@ -11,5 +11,6 @@ $accent: #b58e51;
background-color: $accent; background-color: $accent;
} }
.text-accent{ .text-accent{
color: $accent color: $accent;
} }

View File

@ -1,54 +1,66 @@
<% if (locals.backups) { %> <% if (locals.backups) { %>
<div class="collection"> <div class="list-group ">
<% for(const index in backups) { %> <% for(const index in backups) { %>
<a class="collection-item modal-trigger" href="#modal-<%=backups[index].etag%>" <a class="list-group-item list-group-item-action d-flex justify-content-between align-items-center bg-secondary text-accent"
data-id="<%= backups[index].etag %>"> href="#"
<div><%= backups[index].basename%><div class="secondary-content hide-on-small-and-down"> data-id="<%= backups[index].etag %>"
<%= moment(backups[index].lastmod).format('MMM D, YYYY HH:mm') %></div> data-bs-toggle="modal"
</div> data-bs-target="#modal-<%= backups[index].etag %>">
</a> <%= backups[index].basename %>
<span class="badge bg-primary">
<%= moment(backups[index].lastmod).format('MMM D, YYYY HH:mm') %>
</span>
</a>
<div id="modal-<%=backups[index].etag%>" class="modal modal-fixed-footer blue-grey darken-4 white-text"> <div id="modal-<%= backups[index].etag %>" class="modal fade">
<div class="modal-content"> <div class="modal-dialog modal-lg">
<div class="row"> <div class="modal-content bg-dark">
<div class="col s12 center"> <div class="modal-header border-secondary">
<h4>Backup Detail</h2> <h5 class="modal-title" id="exampleModalLabel"> Backup Detail</h5>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"
aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="mb-3">
<label for="name-<%= backups[index].etag %>" class="form-label">Name</label>
<input disabled type="text" class="form-control bg-secondary border-dark text-accent"
id="name-<%= backups[index].etag %>"
value="<%= backups[index].basename %>"/>
</div>
<div class="mb-3">
<label for="date-<%= backups[index].etag %>" class="form-label">Date</label>
<input disabled type="text" class="form-control bg-secondary border-dark text-accent"
id="date-<%= backups[index].etag %>"
value="<%= moment(backups[index].lastmod).format('MMM D, YYYY HH:mm') %>"/>
</div>
<div class="input-field col s12">
<label for="size-<%= backups[index].etag %>" class="form-label">Size</label>
<input disabled type="text" class="form-control bg-secondary border-dark text-accent"
id="size-<%= backups[index].etag %>"
value="<%= humanFileSize(backups[index].size, false) %>"/>
</div>
</div>
<div class="modal-footer border-secondary">
<button data-bs-dismiss="modal" class="btn btn-danger">Close</button>
<button class="btn btn-success manual-back-list "
data-id="<%= backups[index].filename %>"
data-name='<%= backups[index].basename ? backups[index].basename : backups[index].etag %>'
data-bs-dismiss="modal">
Upload to HA
</button>
</div>
</div>
</div> </div>
</div> </div>
<div class="row">
<div class="col s12 center divider">
</div>
</div>
<div class="row">
<div class="input-field col s12"> <% } %>
<input disabled type="text" id="name-<%=backups[index].etag%>" value="<%= backups[index].basename %>" />
<label for="name-<%=backups[index].etag%>" class="white-text active">Name</label>
</div>
<div class="input-field col s12">
<input disabled type="text" id="date-<%=backups[index].etag%>"
value="<%=moment(backups[index].lastmod).format('MMM D, YYYY HH:mm')%>" />
<label for="date-<%=backups[index].etag%>" class="white-text active">Date</label>
</div>
<div class="input-field col s12">
<input disabled type="text" id="size-<%=backups[index].etag%>"
value="<%=humanFileSize(backups[index].size, false)%>" />
<label for="size-<%=backups[index].etag%>" class="white-text active">Size</label>
</div>
</div>
</div>
<div class="modal-footer blue-grey darken-4">
<a href="#!" class="waves-effect waves-green btn green restore modal-close" data-id="<%=backups[index].filename%>" data-name='<%= backups[index].basename ? backups[index].basename : backups[index].etag %>'>Upload to HA</a>
<a href="#!" class="modal-close waves-effect waves-green btn red">Close</a>
</div>
</div> </div>
<% } %>
</div>
<% } %> <% } %>

View File

@ -10,7 +10,7 @@
<link rel='stylesheet' href='./css/style.css'/> <link rel='stylesheet' href='./css/style.css'/>
<link rel="stylesheet" href="./css/custom_bootstrap.css"> <link rel="stylesheet" href="./css/custom_bootstrap.css">
<link rel="stylesheet" href="./font/bootstrap-icons.css"> <link rel="stylesheet" href="./css/all.css">
<!-- <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">--> <!-- <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">-->
<!-- <style>--> <!-- <style>-->
<!-- .modal input[disabled] {--> <!-- .modal input[disabled] {-->
@ -87,9 +87,10 @@
</a> </a>
<ul class="navbar-nav"> <ul class="navbar-nav">
<li class="nav-item dropdown" id="setting-trigger"> <li class="nav-item dropdown" id="setting-trigger">
<a class="nav-link active dropdown-toggle" href="#" id="dropdown-settings" role="button" <a class="btn btn-outline-light bg-transparent nav-link active" href="#" id="dropdown-settings"
role="button"
data-bs-toggle="dropdown" aria-expanded="false"> data-bs-toggle="dropdown" aria-expanded="false">
<i class="bi bi-gear-fill"></i> <i class="fas fa-cogs"></i>
</a> </a>
<ul class="dropdown-menu dropdown-menu-dark" aria-labelledby="dropdown-settings"> <ul class="dropdown-menu dropdown-menu-dark" aria-labelledby="dropdown-settings">
<li><a href="#modal-settings-nextcloud" id="trigger-nextcloud-settings" <li><a href="#modal-settings-nextcloud" id="trigger-nextcloud-settings"
@ -106,30 +107,31 @@
<div class="container"> <div class="container">
<div class="row mt-3 mb-3" id="header-box"> <div class="row mt-3 mb-3" id="header-box">
<div class="col-12 col-md-3"> <div class="col-12 col-md-3 mb-3 mb-md-0">
<div class="card text-white bg-dark h-100 shadow border-secondary"> <div class="card text-white bg-dark h-100 shadow border-secondary">
<div class="card-header fw-bold h5">Status</div> <div class="card-header fw-bold h5 border-secondary border-bottom">Status</div>
<div class="card-body"> <div class="card-body">
<h6 id="status" class="white-text"></h6> <h6 id="status" class="white-text"></h6>
<div id="status-second-line" class="truncate mb-2 text-accent"></div> <div id="status-second-line" class="truncate mb-2 text-accent"></div>
<div class="progress bg-secondary" id="progress"> <div class="progress bg-secondary invisible" id="progress">
<div class="progress-bar bg-success" role="progressbar" style="width: 15%" aria-valuemin="0" aria-valuemax="100"></div> <div class="progress-bar bg-success" role="progressbar" style="width: 15%" aria-valuemin="0"
aria-valuemax="100"></div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="col-12 col-md-3"> <div class="col-12 col-md-3 mb-3 mb-md-0">
<div class="card text-white bg-dark h-100 shadow border-secondary"> <div class="card text-white bg-dark h-100 shadow border-secondary">
<div class="card-header fw-bold h5">Last Backup</div> <div class="card-header fw-bold h5 border-secondary border-bottom">Last Backup</div>
<div class="card-body"> <div class="card-body">
<h6 class="white-text" id="last_back_status"></h6> <h6 class="white-text" id="last_back_status"></h6>
</div> </div>
</div> </div>
</div> </div>
<div class="col-12 col-md-3"> <div class="col-12 col-md-3 mb-3 mb-md-0">
<div class="card text-white bg-dark h-100 shadow border-secondary"> <div class="card text-white bg-dark h-100 shadow border-secondary">
<div class="card-header fw-bold h5">Next Backup </div> <div class="card-header fw-bold h5 border-secondary border-bottom">Next Backup</div>
<div class="card-body"> <div class="card-body">
<h6 class="white-text" id="next_back_status"></h6> <h6 class="white-text" id="next_back_status"></h6>
</div> </div>
@ -137,14 +139,15 @@
</div> </div>
<div class="col-12 col-md-3"> <div class="col-12 col-md-3">
<div class="card text-white bg-dark h-100 shadow border-secondary"> <div class="card text-white bg-dark h-100 shadow border-secondary">
<div class="card-header fw-bold h5">Manual</div> <div class="card-header fw-bold h5 border-secondary border-bottom">Manual</div>
<div class="card-body py-2"> <div class="card-body py-2">
<div class="center w-100"> <div class="center w-100">
<a class="btn btn-success" id="btn-backup-now" <a class="btn btn-success" id="btn-backup-now" style="margin-top: 7px; display: block;">
style="margin-top: 7px; display: block;">Backup Backup Now
Now</a> </a>
<a class="btn btn-danger" id="btn-clean-now" " <a class="btn btn-danger" id="btn-clean-now" style="margin-top: 7px; display: block;">
style="margin-top: 7px; display: block;">Clean Now</a> Clean Now
</a>
</div> </div>
</div> </div>
@ -154,23 +157,21 @@
</div> </div>
<div class="row"> <div class="row">
<div class="col s12 m12 l6 "> <div class="col-12 col-md-12 col-lg-6 mb-3 mb-lg-0">
<div class="card cyan darken-3"> <div class="card text-white bg-dark h-100 shadow border-secondary">
<div class="card-content"> <div class="card-header fw-bold h4 text-center border-secondary border-bottom">Local Snapshots</div>
<span class="card-title center white-text">Local Snapshots</span> <div class="card-body">
<div id="local_snaps"></div> <div id="local_snaps"></div>
</div> </div>
</div> </div>
</div> </div>
<div class="col s12 m12 l6 "> <div class="col-12 col-md-12 col-lg-6 ">
<div class="card cyan darken-3"> <div class="card text-white bg-dark h-100 shadow border-secondary">
<div class="card-content"> <div class="card-header fw-bold h4 text-center border-secondary border-bottom">Snapshots in Nextcloud</div>
<span class="card-title center white-text">Snapshots in Nextcloud</span> <div class="card-body">
<span class="card-title center white-text">Auto</span> <h5 class="card-title text-center fw-bold border-bottom border-secondary pb-3">Auto</h5>
<span class="card-title center white-text divider"></span>
<div id="auto_backups"></div> <div id="auto_backups"></div>
<span class="card-title center white-text">Manual</span> <h5 class="card-title text-center fw-bold border-bottom border-secondary pb-3">Manual</h5>
<span class="card-title center white-text divider"></span>
<div id="manual_backups"></div> <div id="manual_backups"></div>
</div> </div>
</div> </div>
@ -181,11 +182,8 @@
<%- include('modals/nextcloud-settings-modal') %> <%- include('modals/nextcloud-settings-modal') %>
<%- include('modals/backup-settings-modal') %> <%- include('modals/backup-settings-modal') %>
<!-- <%- include('modals/restore-modal.ejs') %> -->
<div id="modal-loading" class="modal blue-grey darken-4 white-text"> <div id="modal-loading" class="modal blue-grey darken-4 white-text">
<div class="modal-content "> <div class="modal-content ">
<div class="row"> <div class="row">

View File

@ -1,61 +1,71 @@
<% if (locals.snaps) { %> <% if (locals.snaps) { %>
<div class="collection"> <div class="list-group">
<% for(const index in snaps) { %> <% for(const index in snaps) { %>
<a class="collection-item local-snap-listener modal-trigger" href="#modal-<%=snaps[index].slug%>" <a class="list-group-item list-group-item-action d-flex justify-content-between align-items-center bg-secondary text-accent"
data-id="<%= snaps[index].slug %>"> href="#"
<div><%= snaps[index].name ? snaps[index].name : snaps[index].slug %><div class="secondary-content hide-on-small-and-down"> data-id="<%= snaps[index].slug %>"
<%= moment(snaps[index].date).format('MMM D, YYYY HH:mm') %></div> data-bs-toggle="modal"
</div> data-bs-target="#modal-<%= snaps[index].slug %>">
</a> <%= snaps[index].name ? snaps[index].name : snaps[index].slug %>
<span class="badge bg-primary">
<%= moment(snaps[index].date).format('MMM D, YYYY HH:mm') %>
</span>
</a>
<div id="modal-<%= snaps[index].slug %>" class="modal fade">
<div class="modal-dialog modal-lg">
<div class="modal-content bg-dark">
<div class="modal-header border-secondary">
<h5 class="modal-title" id="exampleModalLabel"> Snapshot Detail</h5>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"
aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="mb-3">
<label for="name-<%= snaps[index].slug %>" class="form-label">Name</label>
<input disabled type="text" class="form-control bg-secondary border-dark text-accent" id="name-<%= snaps[index].slug %>"
value="<%= snaps[index].name ? snaps[index].name : snaps[index].slug %>"/>
</div>
<div class="mb-3">
<label for="date-<%= snaps[index].slug %>" class="form-label">Date</label>
<input disabled type="text" class="form-control bg-secondary border-dark text-accent" id="date-<%= snaps[index].slug %>"
value="<%= moment(snaps[index].date).format('MMM D, YYYY HH:mm') %>"/>
</div>
<div class="mb-3">
<label for="protected-<%= snaps[index].slug %>"
class="form-label">Protected</label>
<input disabled type="text" class="form-control bg-secondary border-dark text-accent" id="protected-<%= snaps[index].slug %>"
value="<%= snaps[index].protected %>"/>
</div>
<div >
<label for="type-<%= snaps[index].slug %>" class="form-label">Type</label>
<input disabled type="text" class="form-control bg-secondary border-dark text-accent" id="type-<%= snaps[index].slug %>"
value="<%= snaps[index].type %>"/>
</div>
</div>
<div class="modal-footer border-secondary">
<button data-bs-dismiss="modal" class="btn btn-danger">Close</button>
<button class="btn btn-success manual-back-list"
data-id="<%= snaps[index].slug %>"
data-name='<%= snaps[index].name ? snaps[index].name : snaps[index].slug %>'
data-bs-dismiss="modal">
Backup now
</button>
</div>
</div>
<div id="modal-<%=snaps[index].slug%>" class="modal modal-fixed-footer blue-grey darken-4 white-text">
<div class="modal-content">
<div class="row">
<div class="col s12 center">
<h4>Snapshot Detail</h2>
</div> </div>
</div> </div>
<div class="row">
<div class="col s12 center divider">
</div>
</div>
<div class="row">
<div class="input-field col s12"> <% } %>
<input disabled type="text" id="name-<%=snaps[index].slug%>" value="<%= snaps[index].name ? snaps[index].name : snaps[index].slug %>" />
<label for="name-<%=snaps[index].slug%>" class="white-text active">Name</label>
</div>
<div class="input-field col s12">
<input disabled type="text" id="date-<%=snaps[index].slug%>"
value="<%=moment(snaps[index].date).format('MMM D, YYYY HH:mm')%>" />
<label for="date-<%=snaps[index].slug%>" class="white-text active">Date</label>
</div>
<div class="input-field col s12">
<input disabled type="text" id="protected-<%=snaps[index].slug%>"
value="<%=snaps[index].protected%>" />
<label for="protected-<%=snaps[index].slug%>" class="white-text active">Protected</label>
</div>
<div class="input-field col s12">
<input disabled type="text" id="type-<%=snaps[index].slug%>" value="<%=snaps[index].type%>" />
<label for="type-<%=snaps[index].slug%>" class="white-text active">Type</label>
</div>
</div>
</div> </div>
<div class="modal-footer blue-grey darken-4">
<a href="#!" class="waves-effect waves-green btn green manual-back-list modal-close" data-id="<%=snaps[index].slug%>" data-name='<%= snaps[index].name ? snaps[index].name : snaps[index].slug %>'</a>Backup now</a>
<a href="#!" class="modal-close waves-effect waves-green btn red">Close</a>
</div>
</div>
<% } %>
</div>
<% } %> <% } %>