mirror of
https://github.com/BobbyWibowo/lolisafe.git
synced 2024-12-14 00:16:21 +00:00
Updated
Upgraded dependencies. Stop adding cache-control header to album zip files unless config.cacheControl is enabled. Updated CSS files. Moved thumbnail-related styling to thumbs.css. Various other fixes & improvements. Moved render.js from public/js to public/js/s. Removed sharex.js in favor of public/js/s/utils.js. Moved getPrettyDate() & getPrettyBytes() to that JS file as well. Added lsKeys global variable wherever applicable. Previously the idea was only used in dashboard.js. Added No-JS version of album public pages. You'll only have to add ?nojs to the URL. Viewing the regular version with JS disabled will show a notice with a link to the No-JS version of the particular album. Overall page size of the regular version will now be lower as well, since there'll be no need to add noscript tag for each thumbs. No longer show Administrator section to non-admin in the dashboard. Moderators will ONLY be able to see manage users menu as well. Simplified FAQ wherever applicable. Added a new FAQ about bug report or feature request. Updated link for Firefox extension. Also pushed Firefox link before Chrome, cause I like it more. Added browser settings menu to dashboard. This allows you to choose file size unit (kilobyte vs kibibyte) for that specific browser. The preference will be used on homepage, dashboard and album pages. This also allows you to set chunk size and maximum parallel uploads for the homepage uploader. All menu links in the dashboard will now scroll to the content once loaded. Previously it would only do so with manage uploads/users when switching pages. Refactored all instances of for-in & for-of loop from browser JS files. For the sake of uniformity, for now.
This commit is contained in:
parent
b77d4b7c65
commit
05b905bc9b
@ -321,11 +321,11 @@ albumsController.get = async (req, res, next) => {
|
|||||||
albumsController.generateZip = async (req, res, next) => {
|
albumsController.generateZip = async (req, res, next) => {
|
||||||
const versionString = parseInt(req.query.v)
|
const versionString = parseInt(req.query.v)
|
||||||
const download = (filePath, fileName) => {
|
const download = (filePath, fileName) => {
|
||||||
const headers = { 'Access-Control-Allow-Origin': '*' }
|
const headers = {}
|
||||||
if (versionString > 0)
|
if (config.cacheControl && versionString > 0) {
|
||||||
// Cache-Control header is useful when using CDN (max-age: 30 days)
|
headers['Access-Control-Allow-Origin'] = '*'
|
||||||
headers['Cache-Control'] = 'public, max-age=2592000, must-revalidate, proxy-revalidate, immutable, stale-while-revalidate=86400, stale-if-error=604800'
|
headers['Cache-Control'] = 'public, max-age=2592000, must-revalidate, proxy-revalidate, immutable, stale-while-revalidate=86400, stale-if-error=604800'
|
||||||
|
}
|
||||||
return res.download(filePath, fileName, { headers })
|
return res.download(filePath, fileName, { headers })
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -351,7 +351,7 @@ albumsController.generateZip = async (req, res, next) => {
|
|||||||
else if (album.download === 0)
|
else if (album.download === 0)
|
||||||
return res.json({ success: false, description: 'Download for this album is disabled.' })
|
return res.json({ success: false, description: 'Download for this album is disabled.' })
|
||||||
|
|
||||||
if ((!versionString || versionString <= 0) && album.editedAt)
|
if ((isNaN(versionString) || versionString <= 0) && album.editedAt)
|
||||||
return res.redirect(`${album.identifier}?v=${album.editedAt}`)
|
return res.redirect(`${album.identifier}?v=${album.editedAt}`)
|
||||||
|
|
||||||
if (album.zipGeneratedAt > album.editedAt) {
|
if (album.zipGeneratedAt > album.editedAt) {
|
||||||
|
10
package.json
10
package.json
@ -29,9 +29,9 @@
|
|||||||
"express": "^4.17.1",
|
"express": "^4.17.1",
|
||||||
"express-rate-limit": "^5.0.0",
|
"express-rate-limit": "^5.0.0",
|
||||||
"fluent-ffmpeg": "^2.1.2",
|
"fluent-ffmpeg": "^2.1.2",
|
||||||
"helmet": "^3.20.0",
|
"helmet": "^3.20.1",
|
||||||
"jszip": "^3.2.2",
|
"jszip": "^3.2.2",
|
||||||
"knex": "^0.19.2",
|
"knex": "^0.19.3",
|
||||||
"multer": "^1.4.2",
|
"multer": "^1.4.2",
|
||||||
"node-fetch": "^2.6.0",
|
"node-fetch": "^2.6.0",
|
||||||
"nunjucks": "^3.2.0",
|
"nunjucks": "^3.2.0",
|
||||||
@ -42,10 +42,10 @@
|
|||||||
"sqlite3": "^4.1.0"
|
"sqlite3": "^4.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"eslint": "^6.2.2",
|
"eslint": "^6.3.0",
|
||||||
"eslint-config-standard": "^14.0.1",
|
"eslint-config-standard": "^14.1.0",
|
||||||
"eslint-plugin-import": "^2.18.2",
|
"eslint-plugin-import": "^2.18.2",
|
||||||
"eslint-plugin-node": "^9.1.0",
|
"eslint-plugin-node": "^9.2.0",
|
||||||
"eslint-plugin-promise": "^4.2.1",
|
"eslint-plugin-promise": "^4.2.1",
|
||||||
"eslint-plugin-standard": "^4.0.1"
|
"eslint-plugin-standard": "^4.0.1"
|
||||||
}
|
}
|
||||||
|
@ -2,99 +2,8 @@
|
|||||||
background: none;
|
background: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.message {
|
|
||||||
background-color: #31363b;
|
|
||||||
}
|
|
||||||
|
|
||||||
.message-body {
|
|
||||||
color: #eff0f1;
|
|
||||||
border: 0;
|
|
||||||
-webkit-box-shadow: 0 20px 60px rgba(10, 10, 10, 0.05), 0 5px 10px rgba(10, 10, 10, 0.1), 0 1px 1px rgba(10, 10, 10, 0.2);
|
|
||||||
box-shadow: 0 20px 60px rgba(10, 10, 10, 0.05), 0 5px 10px rgba(10, 10, 10, 0.1), 0 1px 1px rgba(10, 10, 10, 0.2);
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (max-width: 768px) {
|
@media screen and (max-width: 768px) {
|
||||||
.description {
|
.description {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
This is the same sheets used in dashboard.css, minus the on-hover ones.
|
|
||||||
I should probably put this in a file named _thumbs.css, remove the ones in dashboard.css,
|
|
||||||
and use it for both album and dashboard (which means dashboard will have to load an extra css).
|
|
||||||
But oh well, that's something for the future me to think further about.
|
|
||||||
*/
|
|
||||||
|
|
||||||
.image-container {
|
|
||||||
display: -webkit-box;
|
|
||||||
display: -ms-flexbox;
|
|
||||||
display: flex;
|
|
||||||
width: 200px;
|
|
||||||
height: 200px;
|
|
||||||
margin: 9px;
|
|
||||||
background-color: #31363b;
|
|
||||||
overflow: hidden;
|
|
||||||
-webkit-box-align: center;
|
|
||||||
-ms-flex-align: center;
|
|
||||||
align-items: center;
|
|
||||||
position: relative;
|
|
||||||
-webkit-box-shadow: 0 20px 60px rgba(10, 10, 10, 0.05), 0 5px 10px rgba(10, 10, 10, 0.1), 0 1px 1px rgba(10, 10, 10, 0.2);
|
|
||||||
box-shadow: 0 20px 60px rgba(10, 10, 10, 0.05), 0 5px 10px rgba(10, 10, 10, 0.1), 0 1px 1px rgba(10, 10, 10, 0.2);
|
|
||||||
}
|
|
||||||
|
|
||||||
.image-container .title {
|
|
||||||
font-weight: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
.image-container .image {
|
|
||||||
overflow: hidden;
|
|
||||||
max-width: 100%;
|
|
||||||
max-height: 100%;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.image-container .file-checkbox {
|
|
||||||
position: absolute;
|
|
||||||
top: .75rem;
|
|
||||||
left: .75rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.image-container .controls {
|
|
||||||
display: -webkit-box;
|
|
||||||
display: -ms-flexbox;
|
|
||||||
display: flex;
|
|
||||||
position: absolute;
|
|
||||||
top: .75rem;
|
|
||||||
right: .75rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.image-container .controls .button {
|
|
||||||
border-radius: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.image-container .controls .button:not(:active):not(:hover) {
|
|
||||||
color: #fff;
|
|
||||||
background-color: rgba(49, 54, 59, .75);
|
|
||||||
}
|
|
||||||
|
|
||||||
.image-container .details {
|
|
||||||
position: absolute;
|
|
||||||
left: .75rem;
|
|
||||||
bottom: .75rem;
|
|
||||||
right: .75rem;
|
|
||||||
background-color: rgba(49, 54, 59, .75);
|
|
||||||
color: #eff0f1;
|
|
||||||
padding: .25rem;
|
|
||||||
font-size: .75rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.image-container .details p {
|
|
||||||
display: block;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.image-container .details p span {
|
|
||||||
font-weight: 800;
|
|
||||||
}
|
|
||||||
|
@ -94,96 +94,12 @@ li[data-action="page-ellipsis"] {
|
|||||||
border-left-color: #898b8d;
|
border-left-color: #898b8d;
|
||||||
}
|
}
|
||||||
|
|
||||||
.image-container {
|
|
||||||
display: -webkit-box;
|
|
||||||
display: -ms-flexbox;
|
|
||||||
display: flex;
|
|
||||||
width: 200px;
|
|
||||||
height: 200px;
|
|
||||||
margin: 9px;
|
|
||||||
background-color: #31363b;
|
|
||||||
overflow: hidden;
|
|
||||||
-webkit-box-align: center;
|
|
||||||
-ms-flex-align: center;
|
|
||||||
align-items: center;
|
|
||||||
position: relative;
|
|
||||||
-webkit-box-shadow: 0 20px 60px rgba(10, 10, 10, 0.05), 0 5px 10px rgba(10, 10, 10, 0.1), 0 1px 1px rgba(10, 10, 10, 0.2);
|
|
||||||
box-shadow: 0 20px 60px rgba(10, 10, 10, 0.05), 0 5px 10px rgba(10, 10, 10, 0.1), 0 1px 1px rgba(10, 10, 10, 0.2);
|
|
||||||
}
|
|
||||||
|
|
||||||
.image-container .title {
|
|
||||||
font-weight: normal;
|
|
||||||
word-break: break-all;
|
|
||||||
}
|
|
||||||
|
|
||||||
.image-container .image {
|
|
||||||
display: -webkit-box;
|
|
||||||
display: -ms-flexbox;
|
|
||||||
display: flex;
|
|
||||||
height: 100%;
|
|
||||||
width: 100%;
|
|
||||||
-webkit-box-align: center;
|
|
||||||
-ms-flex-align: center;
|
|
||||||
align-items: center;
|
|
||||||
-webkit-box-pack: center;
|
|
||||||
-ms-flex-pack: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.image-container .image img {
|
|
||||||
max-height: 100%;
|
|
||||||
max-width: 100%;
|
|
||||||
height: auto;
|
|
||||||
width: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.image-container .checkbox {
|
.image-container .checkbox {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: .75rem;
|
top: .75rem;
|
||||||
left: .75rem;
|
left: .75rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.image-container .controls {
|
|
||||||
display: -webkit-box;
|
|
||||||
display: -ms-flexbox;
|
|
||||||
display: flex;
|
|
||||||
position: absolute;
|
|
||||||
top: .75rem;
|
|
||||||
right: .75rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.image-container .controls .button {
|
|
||||||
border-radius: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.image-container .controls .button:not(:active):not(:hover) {
|
|
||||||
color: #fff;
|
|
||||||
background-color: rgba(49, 54, 59, .75);
|
|
||||||
}
|
|
||||||
|
|
||||||
.image-container .details {
|
|
||||||
position: absolute;
|
|
||||||
left: .75rem;
|
|
||||||
bottom: .75rem;
|
|
||||||
right: .75rem;
|
|
||||||
background-color: rgba(49, 54, 59, .75);
|
|
||||||
color: #eff0f1;
|
|
||||||
padding: .25rem;
|
|
||||||
font-size: .75rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.image-container .details p {
|
|
||||||
display: block;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.image-container .details p span {
|
|
||||||
font-weight: 800;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Make extra info appear on hover only on non-touch devices */
|
|
||||||
|
|
||||||
.no-touch .image-container .checkbox {
|
.no-touch .image-container .checkbox {
|
||||||
opacity: .5;
|
opacity: .5;
|
||||||
-webkit-transition: opacity .25s;
|
-webkit-transition: opacity .25s;
|
||||||
|
@ -106,14 +106,14 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.uploads {
|
|
||||||
padding-top: 1rem;
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.uploads>div {
|
.uploads>div {
|
||||||
-webkit-animation: fadeInOpacity .5s;
|
-webkit-animation: fadeInOpacity .5s;
|
||||||
animation: fadeInOpacity .5s;
|
animation: fadeInOpacity .5s;
|
||||||
|
margin: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uploads>div:first-child {
|
||||||
|
margin-top: 1.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.uploads.nojs {
|
.uploads.nojs {
|
||||||
@ -211,3 +211,29 @@
|
|||||||
display: inline-block;
|
display: inline-block;
|
||||||
word-break: break-all;
|
word-break: break-all;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#urlMaxSize {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.render {
|
||||||
|
position: fixed;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
font-size: 1rem;
|
||||||
|
color: #bdc3c7;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.render.button {
|
||||||
|
border-bottom-left-radius: 0;
|
||||||
|
border-bottom-right-radius: 0;
|
||||||
|
right: 1%;
|
||||||
|
opacity: .25;
|
||||||
|
-webkit-transition: opacity .25s;
|
||||||
|
transition: opacity .25s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.render.button:hover {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
@ -103,30 +103,24 @@ hr {
|
|||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.checkbox:hover,
|
||||||
|
.radio:hover {
|
||||||
|
color: #7f8c8d;
|
||||||
|
}
|
||||||
|
|
||||||
.progress.is-breeze:indeterminate {
|
.progress.is-breeze:indeterminate {
|
||||||
background-image: linear-gradient(to right,#60a8dc 30%,#eff0f1 30%);
|
background-image: linear-gradient(to right,#60a8dc 30%,#eff0f1 30%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.render {
|
.message {
|
||||||
position: fixed;
|
background-color: #31363b;
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
font-size: 1rem;
|
|
||||||
color: #bdc3c7;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.render.button {
|
.message-body {
|
||||||
border-bottom-left-radius: 0;
|
color: #eff0f1;
|
||||||
border-bottom-right-radius: 0;
|
border: 0;
|
||||||
right: 1%;
|
-webkit-box-shadow: 0 20px 60px rgba(10, 10, 10, 0.05), 0 5px 10px rgba(10, 10, 10, 0.1), 0 1px 1px rgba(10, 10, 10, 0.2);
|
||||||
opacity: .25;
|
box-shadow: 0 20px 60px rgba(10, 10, 10, 0.05), 0 5px 10px rgba(10, 10, 10, 0.1), 0 1px 1px rgba(10, 10, 10, 0.2);
|
||||||
-webkit-transition: opacity .25s;
|
|
||||||
transition: opacity .25s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.render.button:hover {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@-webkit-keyframes fadeInOpacity {
|
@-webkit-keyframes fadeInOpacity {
|
||||||
|
81
public/css/thumbs.css
Normal file
81
public/css/thumbs.css
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
.image-container {
|
||||||
|
display: -webkit-box;
|
||||||
|
display: -ms-flexbox;
|
||||||
|
display: flex;
|
||||||
|
width: 200px;
|
||||||
|
height: 200px;
|
||||||
|
margin: 9px;
|
||||||
|
background-color: #31363b;
|
||||||
|
overflow: hidden;
|
||||||
|
-webkit-box-align: center;
|
||||||
|
-ms-flex-align: center;
|
||||||
|
align-items: center;
|
||||||
|
position: relative;
|
||||||
|
-webkit-box-shadow: 0 20px 60px rgba(10, 10, 10, 0.05), 0 5px 10px rgba(10, 10, 10, 0.1), 0 1px 1px rgba(10, 10, 10, 0.2);
|
||||||
|
box-shadow: 0 20px 60px rgba(10, 10, 10, 0.05), 0 5px 10px rgba(10, 10, 10, 0.1), 0 1px 1px rgba(10, 10, 10, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-container .title {
|
||||||
|
font-weight: normal;
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-container .image {
|
||||||
|
display: -webkit-box;
|
||||||
|
display: -ms-flexbox;
|
||||||
|
display: flex;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
-webkit-box-align: center;
|
||||||
|
-ms-flex-align: center;
|
||||||
|
align-items: center;
|
||||||
|
-webkit-box-pack: center;
|
||||||
|
-ms-flex-pack: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-container .image img {
|
||||||
|
max-height: 100%;
|
||||||
|
max-width: 100%;
|
||||||
|
height: auto;
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-container .controls {
|
||||||
|
display: -webkit-box;
|
||||||
|
display: -ms-flexbox;
|
||||||
|
display: flex;
|
||||||
|
position: absolute;
|
||||||
|
top: .75rem;
|
||||||
|
right: .75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-container .controls .button {
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-container .controls .button:not(:active):not(:hover) {
|
||||||
|
color: #fff;
|
||||||
|
background-color: rgba(49, 54, 59, .75);
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-container .details {
|
||||||
|
position: absolute;
|
||||||
|
left: .75rem;
|
||||||
|
bottom: .75rem;
|
||||||
|
right: .75rem;
|
||||||
|
background-color: rgba(49, 54, 59, .75);
|
||||||
|
color: #eff0f1;
|
||||||
|
padding: .25rem;
|
||||||
|
font-size: .75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-container .details p {
|
||||||
|
display: block;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-container .details p span {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
@ -1,25 +1,12 @@
|
|||||||
/* global LazyLoad */
|
/* global LazyLoad */
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
const lsKeys = {}
|
||||||
|
|
||||||
const page = {
|
const page = {
|
||||||
lazyLoad: null
|
lazyLoad: null
|
||||||
}
|
}
|
||||||
|
|
||||||
page.getPrettyBytes = function (num, si) {
|
|
||||||
// MIT License
|
|
||||||
// Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
|
|
||||||
if (!Number.isFinite(num)) return num
|
|
||||||
|
|
||||||
const neg = num < 0 ? '-' : ''
|
|
||||||
const scale = si ? 1000 : 1024
|
|
||||||
if (neg) num = -num
|
|
||||||
if (num < scale) return `${neg}${num} B`
|
|
||||||
|
|
||||||
const exponent = Math.min(Math.floor(Math.log10(num) / 3), 8) // 8 is count of KMGTPEZY
|
|
||||||
const numStr = Number((num / Math.pow(scale, exponent)).toPrecision(3))
|
|
||||||
const pre = (si ? 'kMGTPEZY' : 'KMGTPEZY').charAt(exponent - 1) + (si ? '' : 'i')
|
|
||||||
return `${neg}${numStr} ${pre}B`
|
|
||||||
}
|
|
||||||
|
|
||||||
window.onload = function () {
|
window.onload = function () {
|
||||||
const elements = document.querySelectorAll('.file-size')
|
const elements = document.querySelectorAll('.file-size')
|
||||||
for (let i = 0; i < elements.length; i++)
|
for (let i = 0; i < elements.length; i++)
|
||||||
|
@ -1,8 +1,12 @@
|
|||||||
/* global swal, axios */
|
/* global swal, axios */
|
||||||
|
|
||||||
|
const lsKeys = {
|
||||||
|
token: 'token'
|
||||||
|
}
|
||||||
|
|
||||||
const page = {
|
const page = {
|
||||||
// user token
|
// user token
|
||||||
token: localStorage.token,
|
token: localStorage[lsKeys.token],
|
||||||
|
|
||||||
// HTML elements
|
// HTML elements
|
||||||
user: null,
|
user: null,
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
/* global swal, axios, ClipboardJS, LazyLoad */
|
/* global swal, axios, ClipboardJS, LazyLoad */
|
||||||
|
|
||||||
// keys for localStorage
|
|
||||||
const lsKeys = {
|
const lsKeys = {
|
||||||
token: 'token',
|
token: 'token',
|
||||||
viewType: {
|
viewType: {
|
||||||
@ -11,7 +10,9 @@ const lsKeys = {
|
|||||||
uploads: 'selectedUploads',
|
uploads: 'selectedUploads',
|
||||||
uploadsAll: 'selectedUploadsAll',
|
uploadsAll: 'selectedUploadsAll',
|
||||||
users: 'selectedUsers'
|
users: 'selectedUsers'
|
||||||
}
|
},
|
||||||
|
chunkSize: 'chunkSize',
|
||||||
|
parallelUploads: 'parallelUploads'
|
||||||
}
|
}
|
||||||
|
|
||||||
const page = {
|
const page = {
|
||||||
@ -127,8 +128,9 @@ page.prepareDashboard = function () {
|
|||||||
document.querySelector('#dashboard').style.display = 'block'
|
document.querySelector('#dashboard').style.display = 'block'
|
||||||
|
|
||||||
if (page.permissions.moderator) {
|
if (page.permissions.moderator) {
|
||||||
|
document.querySelector('#itemLabelAdmin').style.display = 'block'
|
||||||
|
document.querySelector('#itemListAdmin').style.display = 'block'
|
||||||
const itemManageUploads = document.querySelector('#itemManageUploads')
|
const itemManageUploads = document.querySelector('#itemManageUploads')
|
||||||
itemManageUploads.removeAttribute('disabled')
|
|
||||||
itemManageUploads.addEventListener('click', function () {
|
itemManageUploads.addEventListener('click', function () {
|
||||||
page.setActiveMenu(this)
|
page.setActiveMenu(this)
|
||||||
page.getUploads({ all: true })
|
page.getUploads({ all: true })
|
||||||
@ -137,18 +139,19 @@ page.prepareDashboard = function () {
|
|||||||
|
|
||||||
if (page.permissions.admin) {
|
if (page.permissions.admin) {
|
||||||
const itemServerStats = document.querySelector('#itemServerStats')
|
const itemServerStats = document.querySelector('#itemServerStats')
|
||||||
itemServerStats.removeAttribute('disabled')
|
|
||||||
itemServerStats.addEventListener('click', function () {
|
itemServerStats.addEventListener('click', function () {
|
||||||
page.setActiveMenu(this)
|
page.setActiveMenu(this)
|
||||||
page.getServerStats()
|
page.getServerStats()
|
||||||
})
|
})
|
||||||
|
|
||||||
const itemManageUsers = document.querySelector('#itemManageUsers')
|
const itemManageUsers = document.querySelector('#itemManageUsers')
|
||||||
itemManageUsers.removeAttribute('disabled')
|
|
||||||
itemManageUsers.addEventListener('click', function () {
|
itemManageUsers.addEventListener('click', function () {
|
||||||
page.setActiveMenu(this)
|
page.setActiveMenu(this)
|
||||||
page.getUsers()
|
page.getUsers()
|
||||||
})
|
})
|
||||||
|
} else {
|
||||||
|
document.querySelector('#itemServerStats').style.display = 'none'
|
||||||
|
document.querySelector('#itemManageUsers').style.display = 'none'
|
||||||
}
|
}
|
||||||
|
|
||||||
document.querySelector('#itemUploads').addEventListener('click', function () {
|
document.querySelector('#itemUploads').addEventListener('click', function () {
|
||||||
@ -166,6 +169,11 @@ page.prepareDashboard = function () {
|
|||||||
page.getAlbums()
|
page.getAlbums()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
document.querySelector('#itemBrowserSettings').addEventListener('click', function () {
|
||||||
|
page.setActiveMenu(this)
|
||||||
|
page.browserSettings()
|
||||||
|
})
|
||||||
|
|
||||||
document.querySelector('#itemFileLength').addEventListener('click', function () {
|
document.querySelector('#itemFileLength').addEventListener('click', function () {
|
||||||
page.setActiveMenu(this)
|
page.setActiveMenu(this)
|
||||||
page.changeFileLength()
|
page.changeFileLength()
|
||||||
@ -286,7 +294,7 @@ page.isLoading = function (element, state) {
|
|||||||
element.classList.remove('is-loading')
|
element.classList.remove('is-loading')
|
||||||
}
|
}
|
||||||
|
|
||||||
page.fadeIn = function (content) {
|
page.fadeAndScroll = function (content) {
|
||||||
if (page.fadingIn) {
|
if (page.fadingIn) {
|
||||||
clearTimeout(page.fadingIn)
|
clearTimeout(page.fadingIn)
|
||||||
page.dom.classList.remove('fade-in')
|
page.dom.classList.remove('fade-in')
|
||||||
@ -295,10 +303,11 @@ page.fadeIn = function (content) {
|
|||||||
page.fadingIn = setTimeout(function () {
|
page.fadingIn = setTimeout(function () {
|
||||||
page.dom.classList.remove('fade-in')
|
page.dom.classList.remove('fade-in')
|
||||||
}, 500)
|
}, 500)
|
||||||
|
page.dom.scrollIntoView(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
page.switchPage = function (action, element) {
|
page.switchPage = function (action, element) {
|
||||||
const views = { scroll: true }
|
const views = {}
|
||||||
let func = null
|
let func = null
|
||||||
|
|
||||||
if (page.currentView === 'users') {
|
if (page.currentView === 'users') {
|
||||||
@ -338,7 +347,7 @@ page.focusJumpToPage = function () {
|
|||||||
element.select()
|
element.select()
|
||||||
}
|
}
|
||||||
|
|
||||||
page.getUploads = function ({ pageNum, album, all, filters, scroll } = {}, element) {
|
page.getUploads = function ({ pageNum, album, all, filters } = {}, element) {
|
||||||
if (element) page.isLoading(element, true)
|
if (element) page.isLoading(element, true)
|
||||||
|
|
||||||
if ((all || filters) && !page.permissions.moderator)
|
if ((all || filters) && !page.permissions.moderator)
|
||||||
@ -497,7 +506,7 @@ page.getUploads = function ({ pageNum, album, all, filters, scroll } = {}, eleme
|
|||||||
<hr>
|
<hr>
|
||||||
${pagination}
|
${pagination}
|
||||||
`
|
`
|
||||||
page.fadeIn()
|
page.fadeAndScroll()
|
||||||
|
|
||||||
const table = document.querySelector('#table')
|
const table = document.querySelector('#table')
|
||||||
|
|
||||||
@ -570,7 +579,7 @@ page.getUploads = function ({ pageNum, album, all, filters, scroll } = {}, eleme
|
|||||||
<hr>
|
<hr>
|
||||||
${pagination}
|
${pagination}
|
||||||
`
|
`
|
||||||
page.fadeIn()
|
page.fadeAndScroll()
|
||||||
|
|
||||||
const table = document.querySelector('#table')
|
const table = document.querySelector('#table')
|
||||||
|
|
||||||
@ -615,8 +624,6 @@ page.getUploads = function ({ pageNum, album, all, filters, scroll } = {}, eleme
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (scroll) page.dom.scrollIntoView(true)
|
|
||||||
|
|
||||||
if (allSelected && files.length) {
|
if (allSelected && files.length) {
|
||||||
const selectAll = document.querySelector('#selectAll')
|
const selectAll = document.querySelector('#selectAll')
|
||||||
if (selectAll) selectAll.checked = true
|
if (selectAll) selectAll.checked = true
|
||||||
@ -961,7 +968,7 @@ page.deleteByNames = function () {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
page.fadeIn()
|
page.fadeAndScroll()
|
||||||
}
|
}
|
||||||
|
|
||||||
page.deleteFileByNames = function () {
|
page.deleteFileByNames = function () {
|
||||||
@ -1200,7 +1207,7 @@ page.getAlbums = function () {
|
|||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
page.fadeIn()
|
page.fadeAndScroll()
|
||||||
|
|
||||||
const homeDomain = response.data.homeDomain
|
const homeDomain = response.data.homeDomain
|
||||||
const table = document.querySelector('#table')
|
const table = document.querySelector('#table')
|
||||||
@ -1458,6 +1465,111 @@ page.getAlbum = function (album) {
|
|||||||
page.getUploads({ album: album.id })
|
page.getUploads({ album: album.id })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
page.browserSettings = function () {
|
||||||
|
const selectionMap = { uploads: 'Selected uploads' }
|
||||||
|
|
||||||
|
if (page.permissions.moderator)
|
||||||
|
selectionMap.uploadsAll = 'Selected uploads (manager)'
|
||||||
|
|
||||||
|
if (page.permissions.admin)
|
||||||
|
selectionMap.users = 'Selected users'
|
||||||
|
|
||||||
|
let selectionSection = ''
|
||||||
|
const keys = Object.keys(selectionMap)
|
||||||
|
for (let i = 0; i < keys.length; i++)
|
||||||
|
selectionSection += `
|
||||||
|
<p>${selectionMap[keys[i]]}: ${page.selected[keys[i]].length}
|
||||||
|
`
|
||||||
|
|
||||||
|
const maxChunkSize = 95
|
||||||
|
const siBytes = localStorage[lsKeys.siBytes] !== '0'
|
||||||
|
|
||||||
|
page.dom.innerHTML = `
|
||||||
|
<h2 class="subtitle">Browser settings</h2>
|
||||||
|
<article class="message has-text-left">
|
||||||
|
<div class="message-body">
|
||||||
|
${selectionSection}
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
<article class="message has-text-left">
|
||||||
|
<div class="message-body">
|
||||||
|
<form class="prevent-default" id="browserSettingsForm">
|
||||||
|
<div class="field">
|
||||||
|
<label class="label">File size unit</label>
|
||||||
|
<div class="control">
|
||||||
|
<label class="radio">
|
||||||
|
<input type="radio" name="siBytes" value="default"${siBytes ? ' checked' : ''}>
|
||||||
|
1 Kilobyte = 1 kB = 1000 B (default)
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="radio">
|
||||||
|
<input type="radio" name="siBytes" value="0"${siBytes ? '' : ' checked'}>
|
||||||
|
1 Kibibyte = 1 KiB = 1024 B
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="field">
|
||||||
|
<label class="label">Upload chunk size (MB)</label>
|
||||||
|
<div class="control">
|
||||||
|
<input class="input" type="number" name="chunkSize" min="0" max="${maxChunkSize}" step="5" value="${localStorage[lsKeys.chunkSize] || '0'}">
|
||||||
|
</div>
|
||||||
|
<p class="help">Default is 0, which means to use server's setting. Max is ${maxChunkSize} MB.</p>
|
||||||
|
</div>
|
||||||
|
<div class="field">
|
||||||
|
<label class="label">Parallel uploads</label>
|
||||||
|
<div class="control">
|
||||||
|
<input class="input" type="number" name="parallelUploads" min="0" value="${localStorage[lsKeys.parallelUploads] || '0'}">
|
||||||
|
</div>
|
||||||
|
<p class="help">Default is 0, which means to use hard-coded Dropzone setting.</p>
|
||||||
|
</div>
|
||||||
|
<div class="field is-grouped">
|
||||||
|
<p class="control">
|
||||||
|
<button type="submit" id="saveBrowserSettings" class="button is-breeze">
|
||||||
|
Save
|
||||||
|
</button>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
`
|
||||||
|
page.fadeAndScroll()
|
||||||
|
|
||||||
|
document.querySelector('#saveBrowserSettings').addEventListener('click', function () {
|
||||||
|
const form = document.querySelector('#browserSettingsForm')
|
||||||
|
|
||||||
|
const prefKeys = ['siBytes']
|
||||||
|
for (let i = 0; i < prefKeys.length; i++) {
|
||||||
|
const value = form.elements[prefKeys[i]].value
|
||||||
|
if (value !== '0')
|
||||||
|
localStorage.removeItem(lsKeys[prefKeys[i]])
|
||||||
|
else
|
||||||
|
localStorage[lsKeys[prefKeys[i]]] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
const numKeys = ['chunkSize', 'parallelUploads']
|
||||||
|
for (let i = 0; i < numKeys.length; i++) {
|
||||||
|
const parsed = parseInt(form.elements[numKeys[i]].value)
|
||||||
|
let value = isNaN(parsed) ? 0 : Math.max(parsed, 0)
|
||||||
|
if (numKeys[i] === 'chunkSize') value = Math.min(value, maxChunkSize)
|
||||||
|
value = Math.min(value, Number.MAX_SAFE_INTEGER)
|
||||||
|
if (value > 0)
|
||||||
|
localStorage[lsKeys[numKeys[i]]] = value
|
||||||
|
else
|
||||||
|
localStorage.removeItem(lsKeys[numKeys[i]])
|
||||||
|
}
|
||||||
|
|
||||||
|
swal({
|
||||||
|
title: 'Woohoo!',
|
||||||
|
text: 'Browser settings saved.',
|
||||||
|
icon: 'success'
|
||||||
|
}).then(function () {
|
||||||
|
page.browserSettings()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
page.changeFileLength = function () {
|
page.changeFileLength = function () {
|
||||||
axios.get('api/filelength/config').then(function (response) {
|
axios.get('api/filelength/config').then(function (response) {
|
||||||
if (response.data.success === false)
|
if (response.data.success === false)
|
||||||
@ -1496,7 +1608,7 @@ page.changeFileLength = function () {
|
|||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
`
|
`
|
||||||
page.fadeIn()
|
page.fadeAndScroll()
|
||||||
|
|
||||||
document.querySelector('#setFileLength').addEventListener('click', function () {
|
document.querySelector('#setFileLength').addEventListener('click', function () {
|
||||||
page.setFileLength(document.querySelector('#fileLength').value, this)
|
page.setFileLength(document.querySelector('#fileLength').value, this)
|
||||||
@ -1564,7 +1676,7 @@ page.changeToken = function () {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
page.fadeIn()
|
page.fadeAndScroll()
|
||||||
}).catch(function (error) {
|
}).catch(function (error) {
|
||||||
console.log(error)
|
console.log(error)
|
||||||
return swal('An error occurred!', 'There was an error with the request, please check the console for more information.', 'error')
|
return swal('An error occurred!', 'There was an error with the request, please check the console for more information.', 'error')
|
||||||
@ -1629,7 +1741,7 @@ page.changePassword = function () {
|
|||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
`
|
`
|
||||||
page.fadeIn()
|
page.fadeAndScroll()
|
||||||
|
|
||||||
document.querySelector('#sendChangePassword').addEventListener('click', function () {
|
document.querySelector('#sendChangePassword').addEventListener('click', function () {
|
||||||
if (document.querySelector('#password').value === document.querySelector('#passwordConfirm').value)
|
if (document.querySelector('#password').value === document.querySelector('#passwordConfirm').value)
|
||||||
@ -1679,7 +1791,7 @@ page.setActiveMenu = function (activeItem) {
|
|||||||
activeItem.classList.add('is-active')
|
activeItem.classList.add('is-active')
|
||||||
}
|
}
|
||||||
|
|
||||||
page.getUsers = function ({ pageNum, scroll } = {}, element) {
|
page.getUsers = function ({ pageNum } = {}, element) {
|
||||||
if (element) page.isLoading(element, true)
|
if (element) page.isLoading(element, true)
|
||||||
if (pageNum === undefined) pageNum = 0
|
if (pageNum === undefined) pageNum = 0
|
||||||
|
|
||||||
@ -1780,7 +1892,7 @@ page.getUsers = function ({ pageNum, scroll } = {}, element) {
|
|||||||
<hr>
|
<hr>
|
||||||
${pagination}
|
${pagination}
|
||||||
`
|
`
|
||||||
page.fadeIn()
|
page.fadeAndScroll()
|
||||||
|
|
||||||
const table = document.querySelector('#table')
|
const table = document.querySelector('#table')
|
||||||
|
|
||||||
@ -1790,9 +1902,10 @@ page.getUsers = function ({ pageNum, scroll } = {}, element) {
|
|||||||
if (!selected && allSelected) allSelected = false
|
if (!selected && allSelected) allSelected = false
|
||||||
|
|
||||||
let displayGroup = null
|
let displayGroup = null
|
||||||
for (const group of Object.keys(user.groups)) {
|
const groups = Object.keys(user.groups)
|
||||||
if (!user.groups[group]) break
|
for (let i = 0; i < groups.length; i++) {
|
||||||
displayGroup = group
|
if (!user.groups[groups[i]]) break
|
||||||
|
displayGroup = groups[i]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Server-side explicitly expects either of these two values to consider a user as disabled
|
// Server-side explicitly expects either of these two values to consider a user as disabled
|
||||||
@ -1842,8 +1955,6 @@ page.getUsers = function ({ pageNum, scroll } = {}, element) {
|
|||||||
page.checkboxes.users = Array.from(table.querySelectorAll('.checkbox[data-action="select"]'))
|
page.checkboxes.users = Array.from(table.querySelectorAll('.checkbox[data-action="select"]'))
|
||||||
}
|
}
|
||||||
|
|
||||||
if (scroll) page.dom.scrollIntoView(true)
|
|
||||||
|
|
||||||
if (allSelected && response.data.users.length) {
|
if (allSelected && response.data.users.length) {
|
||||||
const selectAll = document.querySelector('#selectAll')
|
const selectAll = document.querySelector('#selectAll')
|
||||||
if (selectAll) selectAll.checked = true
|
if (selectAll) selectAll.checked = true
|
||||||
@ -2055,7 +2166,7 @@ page.getServerStats = function (element) {
|
|||||||
Please wait, this may take a while\u2026
|
Please wait, this may take a while\u2026
|
||||||
<progress class="progress is-breeze" max="100" style="margin-top: 10px"></progress>
|
<progress class="progress is-breeze" max="100" style="margin-top: 10px"></progress>
|
||||||
`
|
`
|
||||||
page.fadeIn()
|
page.fadeAndScroll()
|
||||||
|
|
||||||
const url = 'api/stats'
|
const url = 'api/stats'
|
||||||
axios.get(url).then(function (response) {
|
axios.get(url).then(function (response) {
|
||||||
@ -2067,39 +2178,42 @@ page.getServerStats = function (element) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let content = ''
|
let content = ''
|
||||||
for (const key of Object.keys(response.data.stats)) {
|
const keys = Object.keys(response.data.stats)
|
||||||
|
for (let i = 0; i < keys.length; i++) {
|
||||||
let rows = ''
|
let rows = ''
|
||||||
if (!response.data.stats[key])
|
if (!response.data.stats[keys[i]]) {
|
||||||
rows += `
|
rows += `
|
||||||
<tr>
|
<tr>
|
||||||
<td>Generating, please try again later\u2026</td>
|
<td>Generating, please try again later\u2026</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
`
|
`
|
||||||
else
|
} else {
|
||||||
for (const valKey of Object.keys(response.data.stats[key])) {
|
const valKeys = Object.keys(response.data.stats[keys[i]])
|
||||||
const _value = response.data.stats[key][valKey]
|
for (let j = 0; j < valKeys.length; j++) {
|
||||||
|
const _value = response.data.stats[keys[i]][valKeys[j]]
|
||||||
let value = _value
|
let value = _value
|
||||||
if (['albums', 'users', 'uploads'].includes(key))
|
if (['albums', 'users', 'uploads'].includes(keys[i]))
|
||||||
value = _value.toLocaleString()
|
value = _value.toLocaleString()
|
||||||
if (['memoryUsage', 'size'].includes(valKey))
|
if (['memoryUsage', 'size'].includes(valKeys[j]))
|
||||||
value = page.getPrettyBytes(_value)
|
value = page.getPrettyBytes(_value)
|
||||||
if (valKey === 'systemMemory')
|
if (valKeys[j] === 'systemMemory')
|
||||||
value = `${page.getPrettyBytes(_value.used)} / ${page.getPrettyBytes(_value.total)} (${Math.round(_value.used / _value.total * 100)}%)`
|
value = `${page.getPrettyBytes(_value.used)} / ${page.getPrettyBytes(_value.total)} (${Math.round(_value.used / _value.total * 100)}%)`
|
||||||
rows += `
|
rows += `
|
||||||
<tr>
|
<tr>
|
||||||
<th>${valKey.replace(/([A-Z])/g, ' $1').toUpperCase()}</th>
|
<th>${valKeys[j].replace(/([A-Z])/g, ' $1').toUpperCase()}</th>
|
||||||
<td>${value}</td>
|
<td>${value}</td>
|
||||||
</tr>
|
</tr>
|
||||||
`
|
`
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
content += `
|
content += `
|
||||||
<div class="table-container">
|
<div class="table-container">
|
||||||
<table class="table is-fullwidth is-hoverable">
|
<table class="table is-fullwidth is-hoverable">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>${key.toUpperCase()}</th>
|
<th>${keys[i].toUpperCase()}</th>
|
||||||
<td style="width: 50%"></td>
|
<td style="width: 50%"></td>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
@ -2116,49 +2230,19 @@ page.getServerStats = function (element) {
|
|||||||
${content}
|
${content}
|
||||||
`
|
`
|
||||||
|
|
||||||
page.fadeIn()
|
page.fadeAndScroll()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
page.getPrettyDate = function (date) {
|
|
||||||
return date.getFullYear() + '-' +
|
|
||||||
(date.getMonth() < 9 ? '0' : '') + // month's index starts from zero
|
|
||||||
(date.getMonth() + 1) + '-' +
|
|
||||||
(date.getDate() < 10 ? '0' : '') +
|
|
||||||
date.getDate() + ' ' +
|
|
||||||
(date.getHours() < 10 ? '0' : '') +
|
|
||||||
date.getHours() + ':' +
|
|
||||||
(date.getMinutes() < 10 ? '0' : '') +
|
|
||||||
date.getMinutes() + ':' +
|
|
||||||
(date.getSeconds() < 10 ? '0' : '') +
|
|
||||||
date.getSeconds()
|
|
||||||
}
|
|
||||||
|
|
||||||
page.getPrettyBytes = function (num, si) {
|
|
||||||
// MIT License
|
|
||||||
// Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
|
|
||||||
if (!Number.isFinite(num)) return num
|
|
||||||
|
|
||||||
const neg = num < 0 ? '-' : ''
|
|
||||||
const scale = si ? 1000 : 1024
|
|
||||||
if (neg) num = -num
|
|
||||||
if (num < scale) return `${neg}${num} B`
|
|
||||||
|
|
||||||
const exponent = Math.min(Math.floor(Math.log10(num) / 3), 8) // 8 is count of KMGTPEZY
|
|
||||||
const numStr = Number((num / Math.pow(scale, exponent)).toPrecision(3))
|
|
||||||
const pre = (si ? 'kMGTPEZY' : 'KMGTPEZY').charAt(exponent - 1) + (si ? '' : 'i')
|
|
||||||
return `${neg}${numStr} ${pre}B`
|
|
||||||
}
|
|
||||||
|
|
||||||
window.onload = function () {
|
window.onload = function () {
|
||||||
// Add 'no-touch' class to non-touch devices
|
// Add 'no-touch' class to non-touch devices
|
||||||
if (!('ontouchstart' in document.documentElement))
|
if (!('ontouchstart' in document.documentElement))
|
||||||
document.documentElement.classList.add('no-touch')
|
document.documentElement.classList.add('no-touch')
|
||||||
|
|
||||||
const selectedKeys = ['uploads', 'uploadsAll', 'users']
|
const selectedKeys = ['uploads', 'uploadsAll', 'users']
|
||||||
for (const selectedKey of selectedKeys) {
|
for (let i = 0; i < selectedKeys.length; i++) {
|
||||||
const ls = localStorage[lsKeys.selected[selectedKey]]
|
const ls = localStorage[lsKeys.selected[selectedKeys[i]]]
|
||||||
if (ls) page.selected[selectedKey] = JSON.parse(ls)
|
if (ls) page.selected[selectedKeys[i]] = JSON.parse(ls)
|
||||||
}
|
}
|
||||||
|
|
||||||
page.preparePage()
|
page.preparePage()
|
||||||
|
@ -1,8 +1,15 @@
|
|||||||
/* global swal, axios, Dropzone, ClipboardJS, LazyLoad */
|
/* global swal, axios, Dropzone, ClipboardJS, LazyLoad */
|
||||||
|
|
||||||
|
const lsKeys = {
|
||||||
|
token: 'token',
|
||||||
|
chunkSize: 'chunkSize',
|
||||||
|
parallelUploads: 'parallelUploads',
|
||||||
|
ufBehavior: 'ufBehavior'
|
||||||
|
}
|
||||||
|
|
||||||
const page = {
|
const page = {
|
||||||
// user token
|
// user token
|
||||||
token: localStorage.token,
|
token: localStorage[lsKeys.token],
|
||||||
|
|
||||||
// configs from api/check
|
// configs from api/check
|
||||||
private: null,
|
private: null,
|
||||||
@ -13,6 +20,10 @@ const page = {
|
|||||||
// store album id that will be used with upload requests
|
// store album id that will be used with upload requests
|
||||||
album: null,
|
album: null,
|
||||||
|
|
||||||
|
maxSizeBytes: null,
|
||||||
|
urlMaxSize: null,
|
||||||
|
urlMaxSizeBytes: null,
|
||||||
|
|
||||||
albumSelect: null,
|
albumSelect: null,
|
||||||
previewTemplate: null,
|
previewTemplate: null,
|
||||||
|
|
||||||
@ -27,7 +38,8 @@ page.checkIfPublic = function () {
|
|||||||
axios.get('api/check').then(function (response) {
|
axios.get('api/check').then(function (response) {
|
||||||
page.private = response.data.private
|
page.private = response.data.private
|
||||||
page.enableUserAccounts = response.data.enableUserAccounts
|
page.enableUserAccounts = response.data.enableUserAccounts
|
||||||
page.maxSize = response.data.maxSize
|
page.maxSize = parseInt(response.data.maxSize)
|
||||||
|
page.maxSizeBytes = page.maxSize * 1e6
|
||||||
page.chunkSize = response.data.chunkSize
|
page.chunkSize = response.data.chunkSize
|
||||||
page.preparePage()
|
page.preparePage()
|
||||||
}).catch(function (error) {
|
}).catch(function (error) {
|
||||||
@ -96,9 +108,14 @@ page.prepareUpload = function () {
|
|||||||
document.querySelector('#albumDiv').style.display = 'flex'
|
document.querySelector('#albumDiv').style.display = 'flex'
|
||||||
}
|
}
|
||||||
|
|
||||||
document.querySelector('#maxSize').innerHTML = `Maximum upload size per file is ${page.maxSize}`
|
document.querySelector('#maxSize').innerHTML = `Maximum upload size per file is ${page.getPrettyBytes(page.maxSizeBytes)}`
|
||||||
document.querySelector('#loginToUpload').style.display = 'none'
|
document.querySelector('#loginToUpload').style.display = 'none'
|
||||||
|
|
||||||
|
const urlMaxSize = document.querySelector('#urlMaxSize')
|
||||||
|
page.urlMaxSize = parseInt(urlMaxSize.innerHTML)
|
||||||
|
page.urlMaxSizeBytes = page.urlMaxSize * 1e6
|
||||||
|
urlMaxSize.innerHTML = page.getPrettyBytes(page.urlMaxSizeBytes)
|
||||||
|
|
||||||
if (!page.token && page.enableUserAccounts)
|
if (!page.token && page.enableUserAccounts)
|
||||||
document.querySelector('#loginLinkText').innerHTML = 'Create an account and keep track of your uploads'
|
document.querySelector('#loginLinkText').innerHTML = 'Create an account and keep track of your uploads'
|
||||||
|
|
||||||
@ -190,16 +207,16 @@ page.prepareDropzone = function () {
|
|||||||
`
|
`
|
||||||
tabDiv.querySelector('.dz-container').appendChild(div)
|
tabDiv.querySelector('.dz-container').appendChild(div)
|
||||||
|
|
||||||
const maxSize = parseInt(page.maxSize)
|
|
||||||
const maxSizeBytes = maxSize * 1e6
|
|
||||||
|
|
||||||
const previewsContainer = tabDiv.querySelector('#tab-files .field.uploads')
|
const previewsContainer = tabDiv.querySelector('#tab-files .field.uploads')
|
||||||
|
|
||||||
|
const chunkSize = (localStorage[lsKeys.chunkSize] || parseInt(page.chunkSize)) * 1e6
|
||||||
|
const parallelUploads = localStorage[lsKeys.parallelUploads] || 2
|
||||||
|
|
||||||
page.dropzone = new Dropzone('#dropzone', {
|
page.dropzone = new Dropzone('#dropzone', {
|
||||||
url: 'api/upload',
|
url: 'api/upload',
|
||||||
paramName: 'files[]',
|
paramName: 'files[]',
|
||||||
maxFilesize: maxSizeBytes / 1024 / 1024, // this option expects MiB
|
maxFilesize: page.maxSizeBytes / 1024 / 1024, // this option expects MiB
|
||||||
parallelUploads: 2,
|
parallelUploads,
|
||||||
uploadMultiple: false,
|
uploadMultiple: false,
|
||||||
previewsContainer,
|
previewsContainer,
|
||||||
previewTemplate: page.previewTemplate,
|
previewTemplate: page.previewTemplate,
|
||||||
@ -207,7 +224,7 @@ page.prepareDropzone = function () {
|
|||||||
autoProcessQueue: true,
|
autoProcessQueue: true,
|
||||||
headers: { token: page.token },
|
headers: { token: page.token },
|
||||||
chunking: Boolean(page.chunkSize),
|
chunking: Boolean(page.chunkSize),
|
||||||
chunkSize: (parseInt(page.chunkSize) * 1e6), // the option below expects Bytes
|
chunkSize, // the option below expects Bytes
|
||||||
parallelChunkUploads: false, // when set to true, it often hangs with hundreds of parallel uploads
|
parallelChunkUploads: false, // when set to true, it often hangs with hundreds of parallel uploads
|
||||||
chunksUploaded (file, done) {
|
chunksUploaded (file, done) {
|
||||||
file.previewElement.querySelector('.progress').setAttribute('value', 100)
|
file.previewElement.querySelector('.progress').setAttribute('value', 100)
|
||||||
@ -280,7 +297,7 @@ page.prepareDropzone = function () {
|
|||||||
page.dropzone.on('error', function (file, error) {
|
page.dropzone.on('error', function (file, error) {
|
||||||
if ((typeof error === 'string' && /^File is too big/.test(error)) ||
|
if ((typeof error === 'string' && /^File is too big/.test(error)) ||
|
||||||
error.description === 'MulterError: File too large')
|
error.description === 'MulterError: File too large')
|
||||||
error = `File too large (${(file.size / 1e6).toFixed(2)}MB).`
|
error = `File too large (${page.getPrettyBytes(file.size)}).`
|
||||||
page.updateTemplateIcon(file.previewElement, 'icon-block')
|
page.updateTemplateIcon(file.previewElement, 'icon-block')
|
||||||
file.previewElement.querySelector('.progress').style.display = 'none'
|
file.previewElement.querySelector('.progress').style.display = 'none'
|
||||||
file.previewElement.querySelector('.name').innerHTML = file.name
|
file.previewElement.querySelector('.name').innerHTML = file.name
|
||||||
@ -475,8 +492,9 @@ page.createAlbum = function () {
|
|||||||
// Handle image paste event
|
// Handle image paste event
|
||||||
window.addEventListener('paste', function (event) {
|
window.addEventListener('paste', function (event) {
|
||||||
const items = (event.clipboardData || event.originalEvent.clipboardData).items
|
const items = (event.clipboardData || event.originalEvent.clipboardData).items
|
||||||
for (const index in items) {
|
const index = Object.keys(items)
|
||||||
const item = items[index]
|
for (let i = 0; i < index.length; i++) {
|
||||||
|
const item = items[index[i]]
|
||||||
if (item.kind === 'file') {
|
if (item.kind === 'file') {
|
||||||
const blob = item.getAsFile()
|
const blob = item.getAsFile()
|
||||||
const file = new File([blob], `pasted-image.${blob.type.match(/(?:[^/]*\/)([^;]*)/)[1]}`)
|
const file = new File([blob], `pasted-image.${blob.type.match(/(?:[^/]*\/)([^;]*)/)[1]}`)
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
/* global page, swal */
|
/* global lsKeys, page, swal */
|
||||||
|
|
||||||
|
// keys for localStorage
|
||||||
|
lsKeys.render = 'render'
|
||||||
|
|
||||||
page.renderType = 'miku'
|
page.renderType = 'miku'
|
||||||
page.renderConfig = {
|
page.renderConfig = {
|
||||||
@ -66,7 +69,7 @@ page.doRenderSwal = function () {
|
|||||||
<div class="field">
|
<div class="field">
|
||||||
<div class="control">
|
<div class="control">
|
||||||
<label class="checkbox">
|
<label class="checkbox">
|
||||||
<input id="swalRender" type="checkbox" ${localStorage.render === '0' ? '' : 'checked'}>
|
<input id="swalRender" type="checkbox" ${localStorage[lsKeys.render] === '0' ? '' : 'checked'}>
|
||||||
Enable random render of ${page.config.name}
|
Enable random render of ${page.config.name}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
@ -82,8 +85,11 @@ page.doRenderSwal = function () {
|
|||||||
}).then(function (value) {
|
}).then(function (value) {
|
||||||
if (!value) return
|
if (!value) return
|
||||||
const newValue = div.querySelector('#swalRender').checked ? undefined : '0'
|
const newValue = div.querySelector('#swalRender').checked ? undefined : '0'
|
||||||
if (newValue !== localStorage.render) {
|
if (newValue !== localStorage[lsKeys.render]) {
|
||||||
newValue ? localStorage.render = newValue : localStorage.removeItem('render')
|
if (newValue)
|
||||||
|
localStorage[lsKeys.render] = newValue
|
||||||
|
else
|
||||||
|
localStorage.removeItem(lsKeys.render)
|
||||||
swal('Success!', `Random render is now ${newValue ? 'disabled' : 'enabled'}.`, 'success')
|
swal('Success!', `Random render is now ${newValue ? 'disabled' : 'enabled'}.`, 'success')
|
||||||
const element = document.querySelector('body > .render')
|
const element = document.querySelector('body > .render')
|
||||||
element.remove()
|
element.remove()
|
||||||
@ -104,7 +110,7 @@ page.doRender = function () {
|
|||||||
if (!page.config || !page.config.array.length) return
|
if (!page.config || !page.config.array.length) return
|
||||||
|
|
||||||
let element
|
let element
|
||||||
if (localStorage.render === '0') {
|
if (localStorage[lsKeys.render] === '0') {
|
||||||
element = document.createElement('a')
|
element = document.createElement('a')
|
||||||
element.className = 'button is-breeze is-hidden-mobile'
|
element.className = 'button is-breeze is-hidden-mobile'
|
||||||
element.title = page.config.name
|
element.title = page.config.name
|
58
public/js/s/utils.js
Normal file
58
public/js/s/utils.js
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/* global lsKeys, page */
|
||||||
|
|
||||||
|
// keys for localStorage
|
||||||
|
lsKeys.siBytes = 'siBytes'
|
||||||
|
|
||||||
|
page.prepareShareX = function () {
|
||||||
|
if (!page.token) return
|
||||||
|
const origin = (location.hostname + location.pathname).replace(/\/(dashboard)?$/, '')
|
||||||
|
const originClean = origin.replace(/\//g, '_')
|
||||||
|
const sharexElement = document.querySelector('#ShareX')
|
||||||
|
const sharexFile = `{
|
||||||
|
"Name": "${originClean}",
|
||||||
|
"DestinationType": "ImageUploader, FileUploader",
|
||||||
|
"RequestType": "POST",
|
||||||
|
"RequestURL": "${location.protocol}//${origin}/api/upload",
|
||||||
|
"FileFormName": "files[]",
|
||||||
|
"Headers": {
|
||||||
|
"token": "${page.token}"
|
||||||
|
},
|
||||||
|
"ResponseType": "Text",
|
||||||
|
"URL": "$json:files[0].url$",
|
||||||
|
"ThumbnailURL": "$json:files[0].url$"
|
||||||
|
}\n`
|
||||||
|
const sharexBlob = new Blob([sharexFile], { type: 'application/octet-binary' })
|
||||||
|
sharexElement.setAttribute('href', URL.createObjectURL(sharexBlob))
|
||||||
|
sharexElement.setAttribute('download', `${originClean}.sxcu`)
|
||||||
|
}
|
||||||
|
|
||||||
|
page.getPrettyDate = function (date) {
|
||||||
|
return date.getFullYear() + '-' +
|
||||||
|
(date.getMonth() < 9 ? '0' : '') + // month's index starts from zero
|
||||||
|
(date.getMonth() + 1) + '-' +
|
||||||
|
(date.getDate() < 10 ? '0' : '') +
|
||||||
|
date.getDate() + ' ' +
|
||||||
|
(date.getHours() < 10 ? '0' : '') +
|
||||||
|
date.getHours() + ':' +
|
||||||
|
(date.getMinutes() < 10 ? '0' : '') +
|
||||||
|
date.getMinutes() + ':' +
|
||||||
|
(date.getSeconds() < 10 ? '0' : '') +
|
||||||
|
date.getSeconds()
|
||||||
|
}
|
||||||
|
|
||||||
|
page.getPrettyBytes = function (num) {
|
||||||
|
// MIT License
|
||||||
|
// Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
|
||||||
|
if (!Number.isFinite(num)) return num
|
||||||
|
|
||||||
|
const si = localStorage[lsKeys.siBytes] !== '0'
|
||||||
|
const neg = num < 0 ? '-' : ''
|
||||||
|
const scale = si ? 1000 : 1024
|
||||||
|
if (neg) num = -num
|
||||||
|
if (num < scale) return `${neg}${num} B`
|
||||||
|
|
||||||
|
const exponent = Math.min(Math.floor(Math.log10(num) / 3), 8) // 8 is count of KMGTPEZY
|
||||||
|
const numStr = Number((num / Math.pow(scale, exponent)).toPrecision(3))
|
||||||
|
const pre = (si ? 'kMGTPEZY' : 'KMGTPEZY').charAt(exponent - 1) + (si ? '' : 'i')
|
||||||
|
return `${neg}${numStr} ${pre}B`
|
||||||
|
}
|
@ -1,24 +0,0 @@
|
|||||||
/* global page */
|
|
||||||
|
|
||||||
page.prepareShareX = function () {
|
|
||||||
if (!page.token) return
|
|
||||||
const origin = (location.hostname + location.pathname).replace(/\/(dashboard)?$/, '')
|
|
||||||
const originClean = origin.replace(/\//g, '_')
|
|
||||||
const sharexElement = document.querySelector('#ShareX')
|
|
||||||
const sharexFile = `{
|
|
||||||
"Name": "${originClean}",
|
|
||||||
"DestinationType": "ImageUploader, FileUploader",
|
|
||||||
"RequestType": "POST",
|
|
||||||
"RequestURL": "${location.protocol}//${origin}/api/upload",
|
|
||||||
"FileFormName": "files[]",
|
|
||||||
"Headers": {
|
|
||||||
"token": "${page.token}"
|
|
||||||
},
|
|
||||||
"ResponseType": "Text",
|
|
||||||
"URL": "$json:files[0].url$",
|
|
||||||
"ThumbnailURL": "$json:files[0].url$"
|
|
||||||
}\n`
|
|
||||||
const sharexBlob = new Blob([sharexFile], { type: 'application/octet-binary' })
|
|
||||||
sharexElement.setAttribute('href', URL.createObjectURL(sharexBlob))
|
|
||||||
sharexElement.setAttribute('download', `${originClean}.sxcu`)
|
|
||||||
}
|
|
@ -64,7 +64,8 @@ routes.get('/a/:identifier', async (req, res, next) => {
|
|||||||
downloadLink: album.download === 0 ? null : `../api/album/zip/${album.identifier}?v=${album.editedAt}`,
|
downloadLink: album.download === 0 ? null : `../api/album/zip/${album.identifier}?v=${album.editedAt}`,
|
||||||
editedAt: album.editedAt,
|
editedAt: album.editedAt,
|
||||||
url: `${homeDomain}/a/${album.identifier}`,
|
url: `${homeDomain}/a/${album.identifier}`,
|
||||||
totalSize
|
totalSize,
|
||||||
|
nojs: req.query.nojs !== undefined
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
v3: CSS and JS files (libs such as bulma, lazyload, etc).
|
v3: CSS and JS files (libs such as bulma, lazyload, etc).
|
||||||
v4: Renders in /public/render/* directories (to be used by render.js).
|
v4: Renders in /public/render/* directories (to be used by render.js).
|
||||||
#}
|
#}
|
||||||
{% set v1 = "UOoSqCmggh" %}
|
{% set v1 = "Jlu03caLZN" %}
|
||||||
{% set v2 = "hiboQUzAzp" %}
|
{% set v2 = "hiboQUzAzp" %}
|
||||||
{% set v3 = "f0nYw5J15T" %}
|
{% set v3 = "f0nYw5J15T" %}
|
||||||
{% set v4 = "S3TAWpPeFS" %}
|
{% set v4 = "S3TAWpPeFS" %}
|
||||||
@ -58,6 +58,15 @@
|
|||||||
},
|
},
|
||||||
icon: 'icon-sharex icon-2x'
|
icon: 'icon-sharex icon-2x'
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
attrs: {
|
||||||
|
title: 'Firefox extension',
|
||||||
|
href: 'https://addons.mozilla.org/en-US/firefox/addon/lolisafe/',
|
||||||
|
target: '_blank',
|
||||||
|
rel: 'noopener'
|
||||||
|
},
|
||||||
|
icon: 'icon-firefox icon-2x'
|
||||||
|
},
|
||||||
{
|
{
|
||||||
attrs: {
|
attrs: {
|
||||||
title: 'Chrome extension',
|
title: 'Chrome extension',
|
||||||
@ -67,15 +76,6 @@
|
|||||||
},
|
},
|
||||||
icon: 'icon-chrome icon-2x'
|
icon: 'icon-chrome icon-2x'
|
||||||
},
|
},
|
||||||
{
|
|
||||||
attrs: {
|
|
||||||
title: 'Firefox extension',
|
|
||||||
href: 'https://github.com/BobbyWibowo/loli-safe-extension/releases',
|
|
||||||
target: '_blank',
|
|
||||||
rel: 'noopener'
|
|
||||||
},
|
|
||||||
icon: 'icon-firefox icon-2x'
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
attrs: {
|
attrs: {
|
||||||
title: 'Bash uploader',
|
title: 'Bash uploader',
|
||||||
|
@ -4,13 +4,17 @@
|
|||||||
<!-- Stylesheets -->
|
<!-- Stylesheets -->
|
||||||
<link rel="stylesheet" href="../libs/bulma/bulma.min.css?v={{ globals.v3 }}">
|
<link rel="stylesheet" href="../libs/bulma/bulma.min.css?v={{ globals.v3 }}">
|
||||||
<link rel="stylesheet" href="../css/style.css?v={{ globals.v1 }}">
|
<link rel="stylesheet" href="../css/style.css?v={{ globals.v1 }}">
|
||||||
|
<link rel="stylesheet" href="../css/thumbs.css?v={{ globals.v1 }}">
|
||||||
<link rel="stylesheet" href="../css/album.css?v={{ globals.v1 }}">
|
<link rel="stylesheet" href="../css/album.css?v={{ globals.v1 }}">
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block scripts %}
|
{% block scripts %}
|
||||||
|
{% if not nojs -%}
|
||||||
<!-- Scripts -->
|
<!-- Scripts -->
|
||||||
<script src="../libs/lazyload/lazyload.min.js?v={{ globals.v3 }}"></script>
|
<script src="../libs/lazyload/lazyload.min.js?v={{ globals.v3 }}"></script>
|
||||||
<script src="../js/album.js?v={{ globals.v1 }}"></script>
|
<script src="../js/album.js?v={{ globals.v1 }}"></script>
|
||||||
|
<script src="../js/s/utils.js?v={{ globals.v1 }}"></script>
|
||||||
|
{% endif %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block opengraph %}
|
{% block opengraph %}
|
||||||
@ -59,25 +63,34 @@
|
|||||||
</div>
|
</div>
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
{% if description -%}
|
{% if description -%}
|
||||||
<h2 class="subtitle description">
|
<h2 class="subtitle description">
|
||||||
{{ description | safe }}
|
{{ description | safe }}
|
||||||
</h2>
|
</h2>
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
|
{% if nojs -%}
|
||||||
|
<article class="message">
|
||||||
|
<div class="message-body">
|
||||||
|
<p>You are viewing No-JS version of this album, so file size will be displayed in bytes.</p>
|
||||||
|
<p>Please <a href="{{ url }}">click here</a> if you want to its regular version.</p>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
{%- endif %}
|
||||||
|
|
||||||
{% if files.length -%}
|
{% if files.length -%}
|
||||||
<div id="table" class="columns is-multiline is-mobile is-centered has-text-centered">
|
<div id="table" class="columns is-multiline is-mobile is-centered has-text-centered">
|
||||||
{% for file in files %}
|
{% for file in files %}
|
||||||
<div class="image-container column is-narrow">
|
<div class="image-container column is-narrow">
|
||||||
<a class="image" href="{{ file.file }}" target="_blank" rel="noopener">
|
<a class="image" href="{{ file.file }}" target="_blank" rel="noopener">
|
||||||
{% if file.thumb -%}
|
{% if file.thumb -%}
|
||||||
|
{% if nojs -%}
|
||||||
|
<img alt="{{ file.name }}" src="{{ file.thumb }}">
|
||||||
|
{%- else -%}
|
||||||
<img alt="{{ file.name }}" data-src="{{ file.thumb }}">
|
<img alt="{{ file.name }}" data-src="{{ file.thumb }}">
|
||||||
{#-
|
{%- endif %}
|
||||||
This will kinda increase the overall page size,
|
|
||||||
but this will still benefit users with JavaScript enabled by lazyloading images,
|
|
||||||
and not causing those who have JavaScript disabled be unable to view the images.
|
|
||||||
#}
|
|
||||||
<noscript><img alt="{{ file.name }}" src="{{ file.thumb }}" style="display: none"></noscript>
|
|
||||||
{%- else -%}
|
{%- else -%}
|
||||||
<h1 class="title">{{ file.extname | default('N/A') }}</h1>
|
<h1 class="title">{{ file.extname | default('N/A') }}</h1>
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
@ -99,11 +112,17 @@
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{# Hide lazyload img tags and show noscript img tags #}
|
{% if not nojs -%}
|
||||||
<noscript>
|
<noscript>
|
||||||
<style>
|
<style>body > section:not(#noscript) { display: none !important; }</style>
|
||||||
img[data-src] { display: none; }
|
<section id="noscript" class="hero is-fullheight">
|
||||||
img[src] { display: block !important; }
|
<div class="hero-body">
|
||||||
</style>
|
<div class="container has-text-centered">
|
||||||
|
<p>You have JavaScript disabled, but this page requires JavaScript to function.</p>
|
||||||
|
<p>Please <a href="{{ url }}?nojs">click here</a> if you want to view its No-JS version.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
</noscript>
|
</noscript>
|
||||||
|
{%- endif %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
{{ super() }}
|
{{ super() }}
|
||||||
<link rel="stylesheet" href="libs/fontello/fontello.css?v={{ globals.v3 }}">
|
<link rel="stylesheet" href="libs/fontello/fontello.css?v={{ globals.v3 }}">
|
||||||
<link rel="stylesheet" href="css/sweetalert.css?v={{ globals.v1 }}">
|
<link rel="stylesheet" href="css/sweetalert.css?v={{ globals.v1 }}">
|
||||||
|
<link rel="stylesheet" href="css/thumbs.css?v={{ globals.v1 }}">
|
||||||
<link rel="stylesheet" href="css/dashboard.css?v={{ globals.v1 }}">
|
<link rel="stylesheet" href="css/dashboard.css?v={{ globals.v1 }}">
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
@ -14,7 +15,7 @@
|
|||||||
<script src="libs/clipboard.js/clipboard.min.js?v={{ globals.v3 }}"></script>
|
<script src="libs/clipboard.js/clipboard.min.js?v={{ globals.v3 }}"></script>
|
||||||
<script src="libs/lazyload/lazyload.min.js?v={{ globals.v3 }}"></script>
|
<script src="libs/lazyload/lazyload.min.js?v={{ globals.v3 }}"></script>
|
||||||
<script src="js/dashboard.js?v={{ globals.v1 }}"></script>
|
<script src="js/dashboard.js?v={{ globals.v1 }}"></script>
|
||||||
<script src="js/sharex.js?v={{ globals.v1 }}"></script>
|
<script src="js/s/utils.js?v={{ globals.v1 }}"></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
@ -53,16 +54,16 @@
|
|||||||
<ul id="albumsContainer"></ul>
|
<ul id="albumsContainer"></ul>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p class="menu-label">Administration</p>
|
<p id="itemLabelAdmin" class="menu-label" style="display: none">Administration</p>
|
||||||
<ul class="menu-list">
|
<ul id="itemListAdmin" class="menu-list" style="display: none">
|
||||||
<li>
|
<li>
|
||||||
<a id="itemServerStats" disabled>Statistics</a>
|
<a id="itemServerStats">Statistics</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a id="itemManageUploads" disabled>Manage uploads</a>
|
<a id="itemManageUploads">Manage uploads</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a id="itemManageUsers" disabled>Manage users</a>
|
<a id="itemManageUsers">Manage users</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p class="menu-label">Configuration</p>
|
<p class="menu-label">Configuration</p>
|
||||||
@ -70,6 +71,9 @@
|
|||||||
<li>
|
<li>
|
||||||
<a id="ShareX">ShareX user profile</a>
|
<a id="ShareX">ShareX user profile</a>
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<a id="itemBrowserSettings">Browser settings</a>
|
||||||
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a id="itemFileLength">File name length</a>
|
<a id="itemFileLength">File name length</a>
|
||||||
</li>
|
</li>
|
||||||
|
@ -1,21 +1,5 @@
|
|||||||
{% extends "_layout.njk" %}
|
{% extends "_layout.njk" %}
|
||||||
|
|
||||||
{% block stylesheets %}
|
|
||||||
{{ super() }}
|
|
||||||
<style>
|
|
||||||
.message {
|
|
||||||
background-color: #31363b;
|
|
||||||
}
|
|
||||||
|
|
||||||
.message-body {
|
|
||||||
color: #eff0f1;
|
|
||||||
border: 0;
|
|
||||||
-webkit-box-shadow: 0 20px 60px rgba(10, 10, 10, 0.05), 0 5px 10px rgba(10, 10, 10, 0.1), 0 1px 1px rgba(10, 10, 10, 0.2);
|
|
||||||
box-shadow: 0 20px 60px rgba(10, 10, 10, 0.05), 0 5px 10px rgba(10, 10, 10, 0.1), 0 1px 1px rgba(10, 10, 10, 0.2);
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
{{ super() }}
|
{{ super() }}
|
||||||
<section class="section">
|
<section class="section">
|
||||||
@ -23,7 +7,7 @@
|
|||||||
<h2 class='subtitle'>What is safe.fiery.me?</h2>
|
<h2 class='subtitle'>What is safe.fiery.me?</h2>
|
||||||
<article class="message">
|
<article class="message">
|
||||||
<div class="message-body">
|
<div class="message-body">
|
||||||
safe.fiery.me is a fork of <a href="https://github.com/WeebDev/lolisafe" target="_blank" rel="noopener">lolisafe</a>. You can check out the fork <a href="https://github.com/BobbyWibowo/lolisafe" target="_blank" rel="noopener">here</a>.
|
This is a fork of <a href="https://github.com/WeebDev/lolisafe" target="_blank" rel="noopener">lolisafe</a>. GitHub repository of the fork is located <a href="https://github.com/BobbyWibowo/lolisafe" target="_blank" rel="noopener">here</a>.
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
@ -45,9 +29,9 @@
|
|||||||
<article class="message">
|
<article class="message">
|
||||||
<div class="message-body">
|
<div class="message-body">
|
||||||
Albums are a simple way of sorting uploads together.<br>
|
Albums are a simple way of sorting uploads together.<br>
|
||||||
Right now you can create albums through the dashboard (and the homepage if you are logged in),<br>
|
As long as you are logged in, you can create albums through the homepage or the dashboard,<br>
|
||||||
then afterwards you can use them with our <a href="https://chrome.google.com/webstore/detail/loli-safe-uploader/enkkmplljfjppcdaancckgilmgoiofnj" target="_blank" rel="noopener">Chrome extension</a> or <a href="https://github.com/BobbyWibowo/loli-safe-extension/releases" target="_blank" rel="noopener">Firefox extension</a>,<br>
|
then afterwards you can use them with our <a href="https://addons.mozilla.org/en-US/firefox/addon/lolisafe/" target="_blank" rel="noopener">Firefox extension</a> or <a href="https://chrome.google.com/webstore/detail/loli-safe-uploader/enkkmplljfjppcdaancckgilmgoiofnj" target="_blank" rel="noopener">Chrome extension</a>,<br>
|
||||||
which will enable you to <strong>right click -> send to safe</strong> or to a desired album if you have any.<br>
|
which will enable you to <strong>right click -> send file to safe</strong> or to a desired album if you have any.<br>
|
||||||
You will have to set the domain in the extension's settings to <strong>https://safe.fiery.me</strong> though.
|
You will have to set the domain in the extension's settings to <strong>https://safe.fiery.me</strong> though.
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
@ -66,39 +50,53 @@
|
|||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
|
<h2 class='subtitle'>I found a bug! -or- I want to request a feature!</h2>
|
||||||
|
<article class="message">
|
||||||
|
<div class="message-body">
|
||||||
|
Feel free to create a GitHub issue <a href="https://github.com/BobbyWibowo/lolisafe/issues/new/choose" target="_blank" rel="noopener">here</a>.</br>
|
||||||
|
Or if you don't want to use GitHub, then you can also contact me through my email above.
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
|
||||||
<h2 class='subtitle'>Where is the server located at?</h2>
|
<h2 class='subtitle'>Where is the server located at?</h2>
|
||||||
<article class="message">
|
<article class="message">
|
||||||
<div class="message-body">
|
<div class="message-body">
|
||||||
Paris, France.<br>
|
Paris, France.<br>
|
||||||
Expect high First Time Byte (FTB) everywhere else, especially anywhere on the other side of the planet Earth (generally can be over 1000ms).<br>
|
We are using Cloudflare though, so you can expect your uploads to be delivered quickly all over the world after they have been cached.
|
||||||
I believe it is mostly due to the fact that we are using Cloudflare, since your requests have to go through them first.<br>
|
|
||||||
However, since Cloudflare will cache your uploads too, the uploads should have much better FTB afterwards (and generally faster download speed too).
|
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
<h2 class='subtitle'>Since my uploads are being cached, what about after I delete them from the dashboard?</h2>
|
<h2 class='subtitle'>Since my uploads are cached, what about after I delete them from the dashboard?</h2>
|
||||||
<article class="message">
|
<article class="message">
|
||||||
<div class="message-body">
|
<div class="message-body">
|
||||||
No need to worry.<br>
|
|
||||||
We will send API requests to Cloudflare to purge their cache immediately after you delete your uploads from the dashboard.<br>
|
We will send API requests to Cloudflare to purge their cache immediately after you delete your uploads from the dashboard.<br>
|
||||||
Cache of thumbnails will also be purged, so no need to worry about them either.
|
Cache of their thumbnails will also be purged, if applicable.
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
<h2 class='subtitle'>Do you have a No-JS uploader form?</h2>
|
<h2 class='subtitle'>Do you have a No-JS uploader form?</h2>
|
||||||
<article class="message">
|
<article class="message">
|
||||||
<div class="message-body">
|
<div class="message-body">
|
||||||
Yes, check out <a href="nojs" target="_blank" rel="noopener">this page</a>.<br>
|
Yes, check out <a href="nojs" target="_blank" rel="noopener">this page</a>.
|
||||||
Unfortunately you will not be able to associate your uploads to your account, if you have any.
|
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
|
{% if noJsMaxSize and chunkSize -%}
|
||||||
|
<h2 class='subtitle'>Why is the maximum file size in the No-JS uploader form smaller?</h2>
|
||||||
|
<article class="message">
|
||||||
|
<div class="message-body">
|
||||||
|
This site is using Cloudflare, which limits the maximum upload size.<br>
|
||||||
|
Since the homepage uploader chunks your uploads through JS magic, it is possible to increase the maximum file size there.
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
{%- endif %}
|
||||||
|
|
||||||
{% if chunkSize -%}
|
{% if chunkSize -%}
|
||||||
<h2 class='subtitle'>Does your API support chunked uploads?</h2>
|
<h2 class='subtitle'>Does your API support chunked uploads?</h2>
|
||||||
<article class="message">
|
<article class="message">
|
||||||
<div class="message-body">
|
<div class="message-body">
|
||||||
Yes, the homepage uploader will chunk your uploads into {{ chunkSize }} pieces by default.<br>
|
Yes, the homepage uploader is hard-coded to chunk uploads into {{ chunkSize }} pieces by default.<br>
|
||||||
If you want to utilize chunked uploads with the API, then feel free to inspect the HTTP requests.
|
If you want to chunk your API uploads, feel free to read the source code to see how it works.
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
@ -116,26 +114,16 @@
|
|||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
<h2 class='subtitle'>How are the file URLs going to be determined?</h2>
|
<h2 class='subtitle'>How are the file URLs be determined?</h2>
|
||||||
<article class="message">
|
<article class="message">
|
||||||
<div class="message-body">
|
<div class="message-body">
|
||||||
Random {{ fileLength.default }}-letter strings will automatically be generated for your uploads.
|
The safe will generate random {{ fileLength.default }}-letter identifiers.
|
||||||
{% if fileLength.userChangeable %}<br>
|
{% if fileLength.userChangeable %}<br>
|
||||||
If you think that is too {{ "short" if tooShort else "long" }}, you can create an account, which will let you to set a preferred length.<br>
|
If you find that too {{ "short" if tooShort else "long" }}, you can create an account which will let you to set your preferred length.<br>
|
||||||
At the moment you can choose from {{ fileLength.min }} to {{ fileLength.max }} letters.
|
You can choose from {{ fileLength.min }} to {{ fileLength.max }} letters.
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
{% if noJsMaxSize and chunkSize -%}
|
|
||||||
<h2 class='subtitle'>Why is the maximum file size in the No-JS uploader form smaller?</h2>
|
|
||||||
<article class="message">
|
|
||||||
<div class="message-body">
|
|
||||||
This site is using Cloudflare, which limits the maximum upload size.<br>
|
|
||||||
The homepage uploader will automatically chunk your uploads into {{ chunkSize }} pieces, so it is possible to increase the maximum file size there, but not in the No-JS uploader form.
|
|
||||||
</div>
|
|
||||||
</article>
|
|
||||||
{%- endif %}
|
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -22,9 +22,9 @@
|
|||||||
<script src="libs/clipboard.js/clipboard.min.js?v={{ globals.v3 }}"></script>
|
<script src="libs/clipboard.js/clipboard.min.js?v={{ globals.v3 }}"></script>
|
||||||
<script src="libs/lazyload/lazyload.min.js?v={{ globals.v3 }}"></script>
|
<script src="libs/lazyload/lazyload.min.js?v={{ globals.v3 }}"></script>
|
||||||
<script src="js/home.js?v={{ globals.v1 }}"></script>
|
<script src="js/home.js?v={{ globals.v1 }}"></script>
|
||||||
<script src="js/sharex.js?v={{ globals.v1 }}"></script>
|
<script src="js/s/utils.js?v={{ globals.v1 }}"></script>
|
||||||
<!-- We assign an ID for this so that the script can find out version string for render images -->
|
<!-- We assign an ID for this so that the script can find out version string for render images -->
|
||||||
<script id="renderScript" data-version="{{ globals.v4 }}" src="js/render.js?v={{ globals.v1 }}"></script>
|
<script id="renderScript" data-version="{{ globals.v4 }}" src="js/s/render.js?v={{ globals.v1 }}"></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
@ -66,7 +66,7 @@
|
|||||||
{%- endif %}
|
{%- endif %}
|
||||||
<div id="tab-files" class="tab-content" style="display: none">
|
<div id="tab-files" class="tab-content" style="display: none">
|
||||||
<div class="field dz-container"></div>
|
<div class="field dz-container"></div>
|
||||||
<div class="field uploads" style="display: none"></div>
|
<div class="field uploads"></div>
|
||||||
</div>
|
</div>
|
||||||
{% if urlMaxSize -%}
|
{% if urlMaxSize -%}
|
||||||
<div id="tab-urls" class="tab-content" style="display: none">
|
<div id="tab-urls" class="tab-content" style="display: none">
|
||||||
@ -76,7 +76,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<p class="help">
|
<p class="help">
|
||||||
{% if urlMaxSize !== maxSize -%}
|
{% if urlMaxSize !== maxSize -%}
|
||||||
Maximum file size for URL upload is <span style="font-weight: bold">{{ urlMaxSize }}</span>.
|
Maximum file size for URL upload is <span id="urlMaxSize">{{ urlMaxSize }}</span>.
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
|
|
||||||
{% if urlExtensionsFilter.length and (urlExtensionsFilterMode === 'blacklist') -%}
|
{% if urlExtensionsFilter.length and (urlExtensionsFilterMode === 'blacklist') -%}
|
||||||
@ -100,7 +100,7 @@
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="field uploads" style="display: none"></div>
|
<div class="field uploads"></div>
|
||||||
</div>
|
</div>
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
</div>
|
</div>
|
||||||
@ -112,7 +112,7 @@
|
|||||||
<i class="icon" style="display: none"></i>
|
<i class="icon" style="display: none"></i>
|
||||||
<img class="is-unselectable" style="display: none">
|
<img class="is-unselectable" style="display: none">
|
||||||
<p class="name is-unselectable"></p>
|
<p class="name is-unselectable"></p>
|
||||||
<progress class="progress is-small is-danger" value="0" max="100">0%</progress>
|
<progress class="progress is-small is-danger" max="100"></progress>
|
||||||
<p class="error"></p>
|
<p class="error"></p>
|
||||||
<p class="link">
|
<p class="link">
|
||||||
<a target="_blank" rel="noopener"></a>
|
<a target="_blank" rel="noopener"></a>
|
||||||
|
118
yarn.lock
118
yarn.lock
@ -288,6 +288,11 @@ body-parser@1.19.0, body-parser@^1.19.0:
|
|||||||
raw-body "2.4.0"
|
raw-body "2.4.0"
|
||||||
type-is "~1.6.17"
|
type-is "~1.6.17"
|
||||||
|
|
||||||
|
bowser@2.5.3:
|
||||||
|
version "2.5.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/bowser/-/bowser-2.5.3.tgz#811b0a24219c566c9a6ab3402bc8a13f35a18a96"
|
||||||
|
integrity sha512-aWCA+CKfKNL/WGzNgjmK+Whp57JMzboZMwJ5gy2jDj2bEIjbMCb3ImGX+V++5wsJftyFiDIbOjRXl60ycniVqg==
|
||||||
|
|
||||||
brace-expansion@^1.1.7:
|
brace-expansion@^1.1.7:
|
||||||
version "1.1.11"
|
version "1.1.11"
|
||||||
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
|
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
|
||||||
@ -503,10 +508,10 @@ color@^3.1.2:
|
|||||||
color-convert "^1.9.1"
|
color-convert "^1.9.1"
|
||||||
color-string "^1.5.2"
|
color-string "^1.5.2"
|
||||||
|
|
||||||
colorette@1.0.8:
|
colorette@1.1.0:
|
||||||
version "1.0.8"
|
version "1.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.0.8.tgz#421ff11c80b7414027ebed922396bc1833d1903c"
|
resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.1.0.tgz#1f943e5a357fac10b4e0f5aaef3b14cdc1af6ec7"
|
||||||
integrity sha512-X6Ck90ReaF+EfKdVGB7vdIQ3dr651BbIrBwY5YBKg13fjH+940sTtp7/Pkx33C6ntYfQcRumOs/aUQhaRPpbTQ==
|
integrity sha512-6S062WDQUXi6hOfkO/sBPVwE5ASXY4G2+b4atvhJfSsuUUhIaUKlkjLe9692Ipyt5/a+IPF5aVTu3V5gvXq5cg==
|
||||||
|
|
||||||
combined-stream@^1.0.6, combined-stream@~1.0.6:
|
combined-stream@^1.0.6, combined-stream@~1.0.6:
|
||||||
version "1.0.8"
|
version "1.0.8"
|
||||||
@ -823,10 +828,10 @@ escape-string-regexp@^1.0.5:
|
|||||||
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
|
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
|
||||||
integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
|
integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
|
||||||
|
|
||||||
eslint-config-standard@^14.0.1:
|
eslint-config-standard@^14.1.0:
|
||||||
version "14.0.1"
|
version "14.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-14.0.1.tgz#375c3636fb4bd453cb95321d873de12e4eef790b"
|
resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-14.1.0.tgz#b23da2b76fe5a2eba668374f246454e7058f15d4"
|
||||||
integrity sha512-1RWsAKTDTZgA8bIM6PSC9aTGDAUlKqNkYNJlTZ5xYD/HYkIM6GlcefFvgcJ8xi0SWG5203rttKYX28zW+rKNOg==
|
integrity sha512-EF6XkrrGVbvv8hL/kYa/m6vnvmUT+K82pJJc4JJVMM6+Qgqh0pnwprSxdduDLB9p/7bIxD+YV5O0wfb8lmcPbA==
|
||||||
|
|
||||||
eslint-import-resolver-node@^0.3.2:
|
eslint-import-resolver-node@^0.3.2:
|
||||||
version "0.3.2"
|
version "0.3.2"
|
||||||
@ -844,12 +849,12 @@ eslint-module-utils@^2.4.0:
|
|||||||
debug "^2.6.8"
|
debug "^2.6.8"
|
||||||
pkg-dir "^2.0.0"
|
pkg-dir "^2.0.0"
|
||||||
|
|
||||||
eslint-plugin-es@^1.4.0:
|
eslint-plugin-es@^1.4.1:
|
||||||
version "1.4.0"
|
version "1.4.1"
|
||||||
resolved "https://registry.yarnpkg.com/eslint-plugin-es/-/eslint-plugin-es-1.4.0.tgz#475f65bb20c993fc10e8c8fe77d1d60068072da6"
|
resolved "https://registry.yarnpkg.com/eslint-plugin-es/-/eslint-plugin-es-1.4.1.tgz#12acae0f4953e76ba444bfd1b2271081ac620998"
|
||||||
integrity sha512-XfFmgFdIUDgvaRAlaXUkxrRg5JSADoRC8IkKLc/cISeR3yHVMefFHQZpcyXXEUUPHfy5DwviBcrfqlyqEwlQVw==
|
integrity sha512-5fa/gR2yR3NxQf+UXkeLeP8FBBl6tSgdrAz1+cF84v1FMM4twGwQoqTnn+QxFLcPOrF4pdKEJKDB/q9GoyJrCA==
|
||||||
dependencies:
|
dependencies:
|
||||||
eslint-utils "^1.3.0"
|
eslint-utils "^1.4.2"
|
||||||
regexpp "^2.0.1"
|
regexpp "^2.0.1"
|
||||||
|
|
||||||
eslint-plugin-import@^2.18.2:
|
eslint-plugin-import@^2.18.2:
|
||||||
@ -869,13 +874,13 @@ eslint-plugin-import@^2.18.2:
|
|||||||
read-pkg-up "^2.0.0"
|
read-pkg-up "^2.0.0"
|
||||||
resolve "^1.11.0"
|
resolve "^1.11.0"
|
||||||
|
|
||||||
eslint-plugin-node@^9.1.0:
|
eslint-plugin-node@^9.2.0:
|
||||||
version "9.1.0"
|
version "9.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-9.1.0.tgz#f2fd88509a31ec69db6e9606d76dabc5adc1b91a"
|
resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-9.2.0.tgz#b1911f111002d366c5954a6d96d3cd5bf2a3036a"
|
||||||
integrity sha512-ZwQYGm6EoV2cfLpE1wxJWsfnKUIXfM/KM09/TlorkukgCAwmkgajEJnPCmyzoFPQQkmvo5DrW/nyKutNIw36Mw==
|
integrity sha512-2abNmzAH/JpxI4gEOwd6K8wZIodK3BmHbTxz4s79OIYwwIt2gkpEXlAouJXu4H1c9ySTnRso0tsuthSOZbUMlA==
|
||||||
dependencies:
|
dependencies:
|
||||||
eslint-plugin-es "^1.4.0"
|
eslint-plugin-es "^1.4.1"
|
||||||
eslint-utils "^1.3.1"
|
eslint-utils "^1.4.2"
|
||||||
ignore "^5.1.1"
|
ignore "^5.1.1"
|
||||||
minimatch "^3.0.4"
|
minimatch "^3.0.4"
|
||||||
resolve "^1.10.1"
|
resolve "^1.10.1"
|
||||||
@ -899,7 +904,7 @@ eslint-scope@^5.0.0:
|
|||||||
esrecurse "^4.1.0"
|
esrecurse "^4.1.0"
|
||||||
estraverse "^4.1.1"
|
estraverse "^4.1.1"
|
||||||
|
|
||||||
eslint-utils@^1.3.0, eslint-utils@^1.3.1, eslint-utils@^1.4.2:
|
eslint-utils@^1.4.2:
|
||||||
version "1.4.2"
|
version "1.4.2"
|
||||||
resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.2.tgz#166a5180ef6ab7eb462f162fd0e6f2463d7309ab"
|
resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.2.tgz#166a5180ef6ab7eb462f162fd0e6f2463d7309ab"
|
||||||
integrity sha512-eAZS2sEUMlIeCjBeubdj45dmBHQwPHWyBcT1VSYB7o9x9WRRqKxyUoiXlRjyAwzN7YEzHJlYg0NmzDRWx6GP4Q==
|
integrity sha512-eAZS2sEUMlIeCjBeubdj45dmBHQwPHWyBcT1VSYB7o9x9WRRqKxyUoiXlRjyAwzN7YEzHJlYg0NmzDRWx6GP4Q==
|
||||||
@ -911,10 +916,10 @@ eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0:
|
|||||||
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2"
|
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2"
|
||||||
integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==
|
integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==
|
||||||
|
|
||||||
eslint@^6.2.2:
|
eslint@^6.3.0:
|
||||||
version "6.2.2"
|
version "6.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.2.2.tgz#03298280e7750d81fcd31431f3d333e43d93f24f"
|
resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.3.0.tgz#1f1a902f67bfd4c354e7288b81e40654d927eb6a"
|
||||||
integrity sha512-mf0elOkxHbdyGX1IJEUsNBzCDdyoUgljF3rRlgfyYh0pwGnreLc0jjD6ZuleOibjmnUWZLY2eXwSooeOgGJ2jw==
|
integrity sha512-ZvZTKaqDue+N8Y9g0kp6UPZtS4FSY3qARxBs7p4f0H0iof381XHduqVerFWtK8DPtKmemqbqCFENWSQgPR/Gow==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/code-frame" "^7.0.0"
|
"@babel/code-frame" "^7.0.0"
|
||||||
ajv "^6.10.0"
|
ajv "^6.10.0"
|
||||||
@ -1335,10 +1340,10 @@ get-value@^2.0.3, get-value@^2.0.6:
|
|||||||
resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28"
|
resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28"
|
||||||
integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=
|
integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=
|
||||||
|
|
||||||
getopts@2.2.4:
|
getopts@2.2.5:
|
||||||
version "2.2.4"
|
version "2.2.5"
|
||||||
resolved "https://registry.yarnpkg.com/getopts/-/getopts-2.2.4.tgz#3137fe8a5fddf304904059a851bdc1c22f0f54fb"
|
resolved "https://registry.yarnpkg.com/getopts/-/getopts-2.2.5.tgz#67a0fe471cacb9c687d817cab6450b96dde8313b"
|
||||||
integrity sha512-Rz7DGyomZjrenu9Jx4qmzdlvJgvrEFHXHvjK0FcZtcTC1U5FmES7OdZHUwMuSnEE6QvBvwse1JODKj7TgbSEjQ==
|
integrity sha512-9jb7AW5p3in+IiJWhQiZmmwkpLaR/ccTWdWQCtZM66HJcHHLegowh4q4tSD7gouUyeNvFWRavfK9GXosQHDpFA==
|
||||||
|
|
||||||
getpass@^0.1.1:
|
getpass@^0.1.1:
|
||||||
version "0.1.7"
|
version "0.1.7"
|
||||||
@ -1480,20 +1485,20 @@ helmet-crossdomain@0.4.0:
|
|||||||
resolved "https://registry.yarnpkg.com/helmet-crossdomain/-/helmet-crossdomain-0.4.0.tgz#5f1fe5a836d0325f1da0a78eaa5fd8429078894e"
|
resolved "https://registry.yarnpkg.com/helmet-crossdomain/-/helmet-crossdomain-0.4.0.tgz#5f1fe5a836d0325f1da0a78eaa5fd8429078894e"
|
||||||
integrity sha512-AB4DTykRw3HCOxovD1nPR16hllrVImeFp5VBV9/twj66lJ2nU75DP8FPL0/Jp4jj79JhTfG+pFI2MD02kWJ+fA==
|
integrity sha512-AB4DTykRw3HCOxovD1nPR16hllrVImeFp5VBV9/twj66lJ2nU75DP8FPL0/Jp4jj79JhTfG+pFI2MD02kWJ+fA==
|
||||||
|
|
||||||
helmet-csp@2.8.0:
|
helmet-csp@2.9.0:
|
||||||
version "2.8.0"
|
version "2.9.0"
|
||||||
resolved "https://registry.yarnpkg.com/helmet-csp/-/helmet-csp-2.8.0.tgz#746d329e24ef39c4ebc00278a48abd3c209e0378"
|
resolved "https://registry.yarnpkg.com/helmet-csp/-/helmet-csp-2.9.0.tgz#8524886b08c7f7d611cb5f36eae453dd604efd4c"
|
||||||
integrity sha512-MlCPeM0Sm3pS9RACRihx70VeTHmkQwa7sum9EK1tfw1VZyvFU0dBWym9nHh3CRkTRNlyNm/WFCMvuh9zXkOjNw==
|
integrity sha512-DGGOQtOLM7ZQpjbf/uvUonq1yG/rFgsBuK10ZJt2AtxUJxqfkPvfmP9aLUmgH9IactiRiYoiFY72YYSPl1TLTQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
|
bowser "2.5.3"
|
||||||
camelize "1.0.0"
|
camelize "1.0.0"
|
||||||
content-security-policy-builder "2.1.0"
|
content-security-policy-builder "2.1.0"
|
||||||
dasherize "2.0.0"
|
dasherize "2.0.0"
|
||||||
platform "1.3.5"
|
|
||||||
|
|
||||||
helmet@^3.20.0:
|
helmet@^3.20.1:
|
||||||
version "3.20.0"
|
version "3.20.1"
|
||||||
resolved "https://registry.yarnpkg.com/helmet/-/helmet-3.20.0.tgz#8a9383bf8230a461cafe8bc763423fbde110d2fc"
|
resolved "https://registry.yarnpkg.com/helmet/-/helmet-3.20.1.tgz#802fcb39ac6865208cbc6879d3502e582c6f777e"
|
||||||
integrity sha512-Ob+TqmQFZ5f7WgP8kBbAzNPsbf6p1lOj5r+327/ymw/IILWih3wcx9u/u/S8Mwv5wbBkO7Li6x5s23t3COhUKw==
|
integrity sha512-em+X5Wz/f0yqoRsBnpnVy3wJHSiIeskX3FQn30szBh1tILaOeSRRLkShuUVFlk/o4qTYjWxdHg4FrRe45iBWHg==
|
||||||
dependencies:
|
dependencies:
|
||||||
depd "2.0.0"
|
depd "2.0.0"
|
||||||
dns-prefetch-control "0.2.0"
|
dns-prefetch-control "0.2.0"
|
||||||
@ -1502,7 +1507,7 @@ helmet@^3.20.0:
|
|||||||
feature-policy "0.3.0"
|
feature-policy "0.3.0"
|
||||||
frameguard "3.1.0"
|
frameguard "3.1.0"
|
||||||
helmet-crossdomain "0.4.0"
|
helmet-crossdomain "0.4.0"
|
||||||
helmet-csp "2.8.0"
|
helmet-csp "2.9.0"
|
||||||
hide-powered-by "1.1.0"
|
hide-powered-by "1.1.0"
|
||||||
hpkp "2.0.0"
|
hpkp "2.0.0"
|
||||||
hsts "2.2.0"
|
hsts "2.2.0"
|
||||||
@ -1975,25 +1980,25 @@ kind-of@^6.0.0, kind-of@^6.0.2:
|
|||||||
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051"
|
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051"
|
||||||
integrity sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==
|
integrity sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==
|
||||||
|
|
||||||
knex@^0.19.2:
|
knex@^0.19.3:
|
||||||
version "0.19.2"
|
version "0.19.3"
|
||||||
resolved "https://registry.yarnpkg.com/knex/-/knex-0.19.2.tgz#056efdb33fb8c77d3d76266b5d1d12dc483c21b5"
|
resolved "https://registry.yarnpkg.com/knex/-/knex-0.19.3.tgz#b5d85b29a127f631a6924e8727c76e53e26cc713"
|
||||||
integrity sha512-TVYvlp2esS4LjjJSz8XuE48bPJq4N3lWnETQVgJ3hXPEqjiDjxcTa3bCn6F5ipQuBaMAAaFHNrqsZm7BttogdA==
|
integrity sha512-HN32QB5PVkUYfvE4UoK/Tbf6UQ7CLEgS0PL8EP6xfonsP0IPZr2M84dy1dIy2KnB5dx+XO6NNEPgfzo8Y8BYzA==
|
||||||
dependencies:
|
dependencies:
|
||||||
bluebird "^3.5.5"
|
bluebird "^3.5.5"
|
||||||
colorette "1.0.8"
|
colorette "1.1.0"
|
||||||
commander "^2.20.0"
|
commander "^2.20.0"
|
||||||
debug "4.1.1"
|
debug "4.1.1"
|
||||||
getopts "2.2.4"
|
getopts "2.2.5"
|
||||||
inherits "~2.0.4"
|
inherits "~2.0.4"
|
||||||
interpret "^1.2.0"
|
interpret "^1.2.0"
|
||||||
liftoff "3.1.0"
|
liftoff "3.1.0"
|
||||||
lodash "^4.17.15"
|
lodash "^4.17.15"
|
||||||
mkdirp "^0.5.1"
|
mkdirp "^0.5.1"
|
||||||
pg-connection-string "2.0.0"
|
pg-connection-string "2.1.0"
|
||||||
tarn "^2.0.0"
|
tarn "^2.0.0"
|
||||||
tildify "2.0.0"
|
tildify "2.0.0"
|
||||||
uuid "^3.3.2"
|
uuid "^3.3.3"
|
||||||
v8flags "^3.1.3"
|
v8flags "^3.1.3"
|
||||||
|
|
||||||
lcid@^1.0.0:
|
lcid@^1.0.0:
|
||||||
@ -2153,9 +2158,9 @@ minimist@^1.2.0:
|
|||||||
integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=
|
integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=
|
||||||
|
|
||||||
minipass@^2.2.1, minipass@^2.3.5:
|
minipass@^2.2.1, minipass@^2.3.5:
|
||||||
version "2.4.0"
|
version "2.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.4.0.tgz#38f0af94f42fb6f34d3d7d82a90e2c99cd3ff485"
|
resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.5.0.tgz#dddb1d001976978158a05badfcbef4a771612857"
|
||||||
integrity sha512-6PmOuSP4NnZXzs2z6rbwzLJu/c5gdzYg1mRI/WIYdx45iiX7T+a4esOzavD6V/KmBzAaopFSTZPZcUx73bqKWA==
|
integrity sha512-9FwMVYhn6ERvMR8XFdOavRz4QK/VJV8elU1x50vYexf9lslDcWe/f4HBRxCPd185ekRSjU6CfYyJCECa/CQy7Q==
|
||||||
dependencies:
|
dependencies:
|
||||||
safe-buffer "^5.1.2"
|
safe-buffer "^5.1.2"
|
||||||
yallist "^3.0.0"
|
yallist "^3.0.0"
|
||||||
@ -2640,10 +2645,10 @@ performance-now@^2.1.0:
|
|||||||
resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
|
resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
|
||||||
integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=
|
integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=
|
||||||
|
|
||||||
pg-connection-string@2.0.0:
|
pg-connection-string@2.1.0:
|
||||||
version "2.0.0"
|
version "2.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-2.0.0.tgz#3eefe5997e06d94821e4d502e42b6a1c73f8df82"
|
resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-2.1.0.tgz#e07258f280476540b24818ebb5dca29e101ca502"
|
||||||
integrity sha1-Pu/lmX4G2Ugh5NUC5CtqHHP434I=
|
integrity sha512-bhlV7Eq09JrRIvo1eKngpwuqKtJnNhZdpdOlvrPrA4dxqXPjxSrbNrfnIDmTpwMyRszrcV4kU5ZA4mMsQUrjdg==
|
||||||
|
|
||||||
pify@^2.0.0:
|
pify@^2.0.0:
|
||||||
version "2.3.0"
|
version "2.3.0"
|
||||||
@ -2657,11 +2662,6 @@ pkg-dir@^2.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
find-up "^2.1.0"
|
find-up "^2.1.0"
|
||||||
|
|
||||||
platform@1.3.5:
|
|
||||||
version "1.3.5"
|
|
||||||
resolved "https://registry.yarnpkg.com/platform/-/platform-1.3.5.tgz#fb6958c696e07e2918d2eeda0f0bc9448d733444"
|
|
||||||
integrity sha512-TuvHS8AOIZNAlE77WUDiR4rySV/VMptyMfcfeoMgs4P8apaZM3JrnbzBiixKUv+XR6i+BXrQh8WAnjaSPFO65Q==
|
|
||||||
|
|
||||||
posix-character-classes@^0.1.0:
|
posix-character-classes@^0.1.0:
|
||||||
version "0.1.1"
|
version "0.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab"
|
resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab"
|
||||||
@ -3558,7 +3558,7 @@ utils-merge@1.0.1:
|
|||||||
resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
|
resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
|
||||||
integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=
|
integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=
|
||||||
|
|
||||||
uuid@^3.3.2:
|
uuid@^3.3.2, uuid@^3.3.3:
|
||||||
version "3.3.3"
|
version "3.3.3"
|
||||||
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.3.tgz#4568f0216e78760ee1dbf3a4d2cf53e224112866"
|
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.3.tgz#4568f0216e78760ee1dbf3a4d2cf53e224112866"
|
||||||
integrity sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==
|
integrity sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==
|
||||||
|
Loading…
Reference in New Issue
Block a user