From 87f35571fabc42cd26b5eaae91b6ba3b376f721f Mon Sep 17 00:00:00 2001 From: simon987 Date: Sat, 21 Apr 2018 13:27:13 -0400 Subject: [PATCH] Code cleanup --- config.py | 3 +- crawler.py | 8 +- indexer.py | 10 +- parsing.py | 13 +- run.py | 10 +- search.py | 2 +- spec/MediaFileParser_spec.py | 4 - spec/PictureFileParser_spec.py | 8 +- static/css/fa-brands.min.css | 5 + static/css/fa-regular.min.css | 5 + static/css/fa-solid.min.css | 5 + static/css/fontawesome.min.css | 5 + static/css/search.css | 147 ++++++ static/js/search.js | 604 +++++++++++++++++++++++++ storage.py | 2 +- templates/layout.html | 4 +- templates/search.html | 793 +-------------------------------- templates/task.html | 8 +- thumbnail.py | 3 +- tmp_specs | 28 -- 20 files changed, 811 insertions(+), 856 deletions(-) create mode 100644 static/css/fa-brands.min.css create mode 100644 static/css/fa-regular.min.css create mode 100644 static/css/fa-solid.min.css create mode 100644 static/css/fontawesome.min.css create mode 100644 static/css/search.css create mode 100644 static/js/search.js delete mode 100644 tmp_specs diff --git a/config.py b/config.py index a2de785..7a0f32d 100644 --- a/config.py +++ b/config.py @@ -8,9 +8,10 @@ default_options = { "EbookContentLength": "2000", "MimeGuesser": "extension", # extension, content "CheckSumCalculators": "", # md5, sha1, sha256 - "FileParsers": "media, text, picture, font" # media, text, picture + "FileParsers": "media, text, picture, font, pdf, docx, spreadsheet, ebook" } index_every = 10000 nGramMin = 3 nGramMax = 3 +bcrypt_rounds = 14 diff --git a/crawler.py b/crawler.py index b535873..df44406 100644 --- a/crawler.py +++ b/crawler.py @@ -12,6 +12,7 @@ from thumbnail import ThumbnailGenerator from storage import Directory import shutil import config +from ctypes import c_char_p class RunningTask: @@ -166,15 +167,13 @@ class TaskManager: done.value = 1 def cancel_task(self): - self.current_task = None - self.current_process.terminate() + self.current_task.done.value = 1 def check_new_task(self): if self.current_task is None: for i in sorted(self.storage.tasks(), reverse=True): - if not self.storage.tasks()[i].completed: - self.start_task(self.storage.tasks()[i]) + self.start_task(self.storage.tasks()[i]) else: if self.current_task.done.value == 1: @@ -183,3 +182,4 @@ class TaskManager: self.current_task = None + diff --git a/indexer.py b/indexer.py index 1f541aa..0effd28 100644 --- a/indexer.py +++ b/indexer.py @@ -78,8 +78,14 @@ class Indexer: self.es.indices.put_mapping(body={"properties": { "path": {"type": "text", "analyzer": "path_analyser", "copy_to": "suggest-path"}, "suggest-path": {"type": "completion", "analyzer": "keyword"}, - "mime": {"type": "text", "analyzer": "path_analyser", "copy_to": "mime_kw"}, - "mime_kw": {"type": "keyword"}, + "mime": {"type": "keyword"}, + "encoding": {"type": "keyword"}, + "format_name": {"type": "keyword"}, + "format_long_name": {"type": "keyword"}, + "duration": {"type": "float"}, + "width": {"type": "integer"}, + "height": {"type": "integer"}, + "mtime": {"type": "integer"}, "directory": {"type": "short"}, "name": {"analyzer": "my_nGram", "type": "text"}, "album": {"analyzer": "my_nGram", "type": "text"}, diff --git a/parsing.py b/parsing.py index ae80329..981ca8e 100644 --- a/parsing.py +++ b/parsing.py @@ -181,18 +181,9 @@ class MediaFileParser(GenericFileParser): if "format" in metadata: - if "bit_rate" in metadata["format"]: - info["bit_rate"] = int(metadata["format"]["bit_rate"]) - - if "nb_streams" in metadata["format"]: - info["nb_streams"] = int(metadata["format"]["nb_streams"]) - if "duration" in metadata["format"]: info["duration"] = float(metadata["format"]["duration"]) - if "format_name" in metadata["format"]: - info["format_name"] = metadata["format"]["format_name"] - if "format_long_name" in metadata["format"]: info["format_long_name"] = metadata["format"]["format_long_name"] @@ -243,10 +234,10 @@ class PictureFileParser(GenericFileParser): with open(full_path, "rb") as image_file: with Image.open(image_file) as image: info["mode"] = image.mode - info["format"] = image.format + info["format_name"] = image.format info["width"] = image.width info["height"] = image.height - except (OSError, ValueError) as e: + except (OSError, ValueError): pass return info diff --git a/run.py b/run.py index 5afe1c6..ddbeb43 100644 --- a/run.py +++ b/run.py @@ -263,13 +263,6 @@ def get_current_task(): return "" -@app.route("/task/current/cancel") -def cancel_current_task(): - - tm.cancel_task() - return redirect("/task") - - @app.route("/task/add") def task_add(): type = request.args.get("type") @@ -284,6 +277,9 @@ def task_add(): def task_del(task_id): storage.del_task(task_id) + if tm.current_task is not None and task_id == tm.current_task.task.id: + tm.cancel_task() + return redirect("/task") diff --git a/search.py b/search.py index 9200407..93a59bd 100644 --- a/search.py +++ b/search.py @@ -57,7 +57,7 @@ class Search: "aggs": { "mimeTypes": { "terms": { - "field": "mime_kw", + "field": "mime", "size": 10000 } } diff --git a/spec/MediaFileParser_spec.py b/spec/MediaFileParser_spec.py index 8e8cbb2..06ae47e 100644 --- a/spec/MediaFileParser_spec.py +++ b/spec/MediaFileParser_spec.py @@ -10,7 +10,6 @@ class MediaFileParserTest(TestCase): info = parser.parse("test_files/cat1.wav") - self.assertEqual(info["bit_rate"], 256044) self.assertEqual(info["format_name"], "wav") self.assertEqual(info["format_long_name"], "WAV / WAVE (Waveform Audio)") self.assertEqual(info["duration"], 20.173875) @@ -20,7 +19,6 @@ class MediaFileParserTest(TestCase): info = parser.parse("test_files/vid1.mp4") - self.assertEqual(info["bit_rate"], 513012) self.assertEqual(info["format_name"], "mov,mp4,m4a,3gp,3g2,mj2") self.assertEqual(info["format_long_name"], "QuickTime / MOV") self.assertEqual(info["duration"], 5.334) @@ -30,7 +28,6 @@ class MediaFileParserTest(TestCase): info = parser.parse("test_files/vid2.webm") - self.assertEqual(info["bit_rate"], 343153) self.assertEqual(info["format_name"], "matroska,webm") self.assertEqual(info["format_long_name"], "Matroska / WebM") self.assertEqual(info["duration"], 10.619) @@ -40,7 +37,6 @@ class MediaFileParserTest(TestCase): info = parser.parse("test_files/vid3.ogv") - self.assertEqual(info["bit_rate"], 590261) self.assertEqual(info["format_name"], "ogg") self.assertEqual(info["format_long_name"], "Ogg") self.assertEqual(info["duration"], 10.618867) diff --git a/spec/PictureFileParser_spec.py b/spec/PictureFileParser_spec.py index e94a489..f63edf8 100644 --- a/spec/PictureFileParser_spec.py +++ b/spec/PictureFileParser_spec.py @@ -13,7 +13,7 @@ class PictureFileParserTest(TestCase): self.assertEqual(info["mode"], "RGB") self.assertEqual(info["width"], 420) self.assertEqual(info["height"], 315) - self.assertEqual(info["format"], "JPEG") + self.assertEqual(info["format_name"], "JPEG") def test_parse_png(self): @@ -24,7 +24,7 @@ class PictureFileParserTest(TestCase): self.assertEqual(info["mode"], "RGBA") self.assertEqual(info["width"], 288) self.assertEqual(info["height"], 64) - self.assertEqual(info["format"], "PNG") + self.assertEqual(info["format_name"], "PNG") def test_parse_gif(self): @@ -35,7 +35,7 @@ class PictureFileParserTest(TestCase): self.assertEqual(info["mode"], "P") self.assertEqual(info["width"], 420) self.assertEqual(info["height"], 315) - self.assertEqual(info["format"], "GIF") + self.assertEqual(info["format_name"], "GIF") def test_parse_bmp(self): @@ -46,4 +46,4 @@ class PictureFileParserTest(TestCase): self.assertEqual(info["mode"], "RGB") self.assertEqual(info["width"], 150) self.assertEqual(info["height"], 200) - self.assertEqual(info["format"], "BMP") + self.assertEqual(info["format_name"], "BMP") diff --git a/static/css/fa-brands.min.css b/static/css/fa-brands.min.css new file mode 100644 index 0000000..4da3c2a --- /dev/null +++ b/static/css/fa-brands.min.css @@ -0,0 +1,5 @@ +/*! + * Font Awesome Free 5.0.8 by @fontawesome - https://fontawesome.com + * License - https://fontawesome.com/license (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) + */ +@font-face{font-family:Font Awesome\ 5 Brands;font-style:normal;font-weight:400;src:url(../webfonts/fa-brands-400.eot);src:url(../webfonts/fa-brands-400.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-brands-400.woff2) format("woff2"),url(../webfonts/fa-brands-400.woff) format("woff"),url(../webfonts/fa-brands-400.ttf) format("truetype"),url(../webfonts/fa-brands-400.svg#fontawesome) format("svg")}.fab{font-family:Font Awesome\ 5 Brands} \ No newline at end of file diff --git a/static/css/fa-regular.min.css b/static/css/fa-regular.min.css new file mode 100644 index 0000000..80e6373 --- /dev/null +++ b/static/css/fa-regular.min.css @@ -0,0 +1,5 @@ +/*! + * Font Awesome Free 5.0.8 by @fontawesome - https://fontawesome.com + * License - https://fontawesome.com/license (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) + */ +@font-face{font-family:Font Awesome\ 5 Free;font-style:normal;font-weight:400;src:url(../webfonts/fa-regular-400.eot);src:url(../webfonts/fa-regular-400.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-regular-400.woff2) format("woff2"),url(../webfonts/fa-regular-400.woff) format("woff"),url(../webfonts/fa-regular-400.ttf) format("truetype"),url(../webfonts/fa-regular-400.svg#fontawesome) format("svg")}.far{font-family:Font Awesome\ 5 Free;font-weight:400} \ No newline at end of file diff --git a/static/css/fa-solid.min.css b/static/css/fa-solid.min.css new file mode 100644 index 0000000..0f8a1b3 --- /dev/null +++ b/static/css/fa-solid.min.css @@ -0,0 +1,5 @@ +/*! + * Font Awesome Free 5.0.8 by @fontawesome - https://fontawesome.com + * License - https://fontawesome.com/license (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) + */ +@font-face{font-family:Font Awesome\ 5 Free;font-style:normal;font-weight:900;src:url(../webfonts/fa-solid-900.eot);src:url(../webfonts/fa-solid-900.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-solid-900.woff2) format("woff2"),url(../webfonts/fa-solid-900.woff) format("woff"),url(../webfonts/fa-solid-900.ttf) format("truetype"),url(../webfonts/fa-solid-900.svg#fontawesome) format("svg")}.fa,.fas{font-family:Font Awesome\ 5 Free;font-weight:900} \ No newline at end of file diff --git a/static/css/fontawesome.min.css b/static/css/fontawesome.min.css new file mode 100644 index 0000000..2c97ea0 --- /dev/null +++ b/static/css/fontawesome.min.css @@ -0,0 +1,5 @@ +/*! + * Font Awesome Free 5.0.8 by @fontawesome - https://fontawesome.com + * License - https://fontawesome.com/license (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) + */ +.fa,.fab,.fal,.far,.fas{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1}.fa-lg{font-size:1.33333em;line-height:.75em;vertical-align:-.0667em}.fa-xs{font-size:.75em}.fa-sm{font-size:.875em}.fa-1x{font-size:1em}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-6x{font-size:6em}.fa-7x{font-size:7em}.fa-8x{font-size:8em}.fa-9x{font-size:9em}.fa-10x{font-size:10em}.fa-fw{text-align:center;width:1.25em}.fa-ul{list-style-type:none;margin-left:2.5em;padding-left:0}.fa-ul>li{position:relative}.fa-li{left:-2em;position:absolute;text-align:center;width:2em;line-height:inherit}.fa-border{border:.08em solid #eee;border-radius:.1em;padding:.2em .25em .15em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left,.fab.fa-pull-left,.fal.fa-pull-left,.far.fa-pull-left,.fas.fa-pull-left{margin-right:.3em}.fa.fa-pull-right,.fab.fa-pull-right,.fal.fa-pull-right,.far.fa-pull-right,.fas.fa-pull-right{margin-left:.3em}.fa-spin{-webkit-animation:a 2s infinite linear;animation:a 2s infinite linear}.fa-pulse{-webkit-animation:a 1s infinite steps(8);animation:a 1s infinite steps(8)}@-webkit-keyframes a{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@keyframes a{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scaleX(-1);transform:scaleX(-1)}.fa-flip-vertical{-webkit-transform:scaleY(-1);transform:scaleY(-1)}.fa-flip-horizontal.fa-flip-vertical,.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)"}.fa-flip-horizontal.fa-flip-vertical{-webkit-transform:scale(-1);transform:scale(-1)}:root .fa-flip-horizontal,:root .fa-flip-vertical,:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270{-webkit-filter:none;filter:none}.fa-stack{display:inline-block;height:2em;line-height:2em;position:relative;vertical-align:middle;width:2em}.fa-stack-1x,.fa-stack-2x{left:0;position:absolute;text-align:center;width:100%}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-500px:before{content:"\f26e"}.fa-accessible-icon:before{content:"\f368"}.fa-accusoft:before{content:"\f369"}.fa-address-book:before{content:"\f2b9"}.fa-address-card:before{content:"\f2bb"}.fa-adjust:before{content:"\f042"}.fa-adn:before{content:"\f170"}.fa-adversal:before{content:"\f36a"}.fa-affiliatetheme:before{content:"\f36b"}.fa-algolia:before{content:"\f36c"}.fa-align-center:before{content:"\f037"}.fa-align-justify:before{content:"\f039"}.fa-align-left:before{content:"\f036"}.fa-align-right:before{content:"\f038"}.fa-amazon:before{content:"\f270"}.fa-amazon-pay:before{content:"\f42c"}.fa-ambulance:before{content:"\f0f9"}.fa-american-sign-language-interpreting:before{content:"\f2a3"}.fa-amilia:before{content:"\f36d"}.fa-anchor:before{content:"\f13d"}.fa-android:before{content:"\f17b"}.fa-angellist:before{content:"\f209"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-down:before{content:"\f107"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angrycreative:before{content:"\f36e"}.fa-angular:before{content:"\f420"}.fa-app-store:before{content:"\f36f"}.fa-app-store-ios:before{content:"\f370"}.fa-apper:before{content:"\f371"}.fa-apple:before{content:"\f179"}.fa-apple-pay:before{content:"\f415"}.fa-archive:before{content:"\f187"}.fa-arrow-alt-circle-down:before{content:"\f358"}.fa-arrow-alt-circle-left:before{content:"\f359"}.fa-arrow-alt-circle-right:before{content:"\f35a"}.fa-arrow-alt-circle-up:before{content:"\f35b"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-down:before{content:"\f063"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrows-alt:before{content:"\f0b2"}.fa-arrows-alt-h:before{content:"\f337"}.fa-arrows-alt-v:before{content:"\f338"}.fa-assistive-listening-systems:before{content:"\f2a2"}.fa-asterisk:before{content:"\f069"}.fa-asymmetrik:before{content:"\f372"}.fa-at:before{content:"\f1fa"}.fa-audible:before{content:"\f373"}.fa-audio-description:before{content:"\f29e"}.fa-autoprefixer:before{content:"\f41c"}.fa-avianex:before{content:"\f374"}.fa-aviato:before{content:"\f421"}.fa-aws:before{content:"\f375"}.fa-backward:before{content:"\f04a"}.fa-balance-scale:before{content:"\f24e"}.fa-ban:before{content:"\f05e"}.fa-band-aid:before{content:"\f462"}.fa-bandcamp:before{content:"\f2d5"}.fa-barcode:before{content:"\f02a"}.fa-bars:before{content:"\f0c9"}.fa-baseball-ball:before{content:"\f433"}.fa-basketball-ball:before{content:"\f434"}.fa-bath:before{content:"\f2cd"}.fa-battery-empty:before{content:"\f244"}.fa-battery-full:before{content:"\f240"}.fa-battery-half:before{content:"\f242"}.fa-battery-quarter:before{content:"\f243"}.fa-battery-three-quarters:before{content:"\f241"}.fa-bed:before{content:"\f236"}.fa-beer:before{content:"\f0fc"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-bell:before{content:"\f0f3"}.fa-bell-slash:before{content:"\f1f6"}.fa-bicycle:before{content:"\f206"}.fa-bimobject:before{content:"\f378"}.fa-binoculars:before{content:"\f1e5"}.fa-birthday-cake:before{content:"\f1fd"}.fa-bitbucket:before{content:"\f171"}.fa-bitcoin:before{content:"\f379"}.fa-bity:before{content:"\f37a"}.fa-black-tie:before{content:"\f27e"}.fa-blackberry:before{content:"\f37b"}.fa-blind:before{content:"\f29d"}.fa-blogger:before{content:"\f37c"}.fa-blogger-b:before{content:"\f37d"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-bold:before{content:"\f032"}.fa-bolt:before{content:"\f0e7"}.fa-bomb:before{content:"\f1e2"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-bowling-ball:before{content:"\f436"}.fa-box:before{content:"\f466"}.fa-boxes:before{content:"\f468"}.fa-braille:before{content:"\f2a1"}.fa-briefcase:before{content:"\f0b1"}.fa-btc:before{content:"\f15a"}.fa-bug:before{content:"\f188"}.fa-building:before{content:"\f1ad"}.fa-bullhorn:before{content:"\f0a1"}.fa-bullseye:before{content:"\f140"}.fa-buromobelexperte:before{content:"\f37f"}.fa-bus:before{content:"\f207"}.fa-buysellads:before{content:"\f20d"}.fa-calculator:before{content:"\f1ec"}.fa-calendar:before{content:"\f133"}.fa-calendar-alt:before{content:"\f073"}.fa-calendar-check:before{content:"\f274"}.fa-calendar-minus:before{content:"\f272"}.fa-calendar-plus:before{content:"\f271"}.fa-calendar-times:before{content:"\f273"}.fa-camera:before{content:"\f030"}.fa-camera-retro:before{content:"\f083"}.fa-car:before{content:"\f1b9"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-caret-square-down:before{content:"\f150"}.fa-caret-square-left:before{content:"\f191"}.fa-caret-square-right:before{content:"\f152"}.fa-caret-square-up:before{content:"\f151"}.fa-caret-up:before{content:"\f0d8"}.fa-cart-arrow-down:before{content:"\f218"}.fa-cart-plus:before{content:"\f217"}.fa-cc-amazon-pay:before{content:"\f42d"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-apple-pay:before{content:"\f416"}.fa-cc-diners-club:before{content:"\f24c"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-cc-visa:before{content:"\f1f0"}.fa-centercode:before{content:"\f380"}.fa-certificate:before{content:"\f0a3"}.fa-chart-area:before{content:"\f1fe"}.fa-chart-bar:before{content:"\f080"}.fa-chart-line:before{content:"\f201"}.fa-chart-pie:before{content:"\f200"}.fa-check:before{content:"\f00c"}.fa-check-circle:before{content:"\f058"}.fa-check-square:before{content:"\f14a"}.fa-chess:before{content:"\f439"}.fa-chess-bishop:before{content:"\f43a"}.fa-chess-board:before{content:"\f43c"}.fa-chess-king:before{content:"\f43f"}.fa-chess-knight:before{content:"\f441"}.fa-chess-pawn:before{content:"\f443"}.fa-chess-queen:before{content:"\f445"}.fa-chess-rook:before{content:"\f447"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-down:before{content:"\f078"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-chevron-up:before{content:"\f077"}.fa-child:before{content:"\f1ae"}.fa-chrome:before{content:"\f268"}.fa-circle:before{content:"\f111"}.fa-circle-notch:before{content:"\f1ce"}.fa-clipboard:before{content:"\f328"}.fa-clipboard-check:before{content:"\f46c"}.fa-clipboard-list:before{content:"\f46d"}.fa-clock:before{content:"\f017"}.fa-clone:before{content:"\f24d"}.fa-closed-captioning:before{content:"\f20a"}.fa-cloud:before{content:"\f0c2"}.fa-cloud-download-alt:before{content:"\f381"}.fa-cloud-upload-alt:before{content:"\f382"}.fa-cloudscale:before{content:"\f383"}.fa-cloudsmith:before{content:"\f384"}.fa-cloudversify:before{content:"\f385"}.fa-code:before{content:"\f121"}.fa-code-branch:before{content:"\f126"}.fa-codepen:before{content:"\f1cb"}.fa-codiepie:before{content:"\f284"}.fa-coffee:before{content:"\f0f4"}.fa-cog:before{content:"\f013"}.fa-cogs:before{content:"\f085"}.fa-columns:before{content:"\f0db"}.fa-comment:before{content:"\f075"}.fa-comment-alt:before{content:"\f27a"}.fa-comments:before{content:"\f086"}.fa-compass:before{content:"\f14e"}.fa-compress:before{content:"\f066"}.fa-connectdevelop:before{content:"\f20e"}.fa-contao:before{content:"\f26d"}.fa-copy:before{content:"\f0c5"}.fa-copyright:before{content:"\f1f9"}.fa-cpanel:before{content:"\f388"}.fa-creative-commons:before{content:"\f25e"}.fa-credit-card:before{content:"\f09d"}.fa-crop:before{content:"\f125"}.fa-crosshairs:before{content:"\f05b"}.fa-css3:before{content:"\f13c"}.fa-css3-alt:before{content:"\f38b"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-cut:before{content:"\f0c4"}.fa-cuttlefish:before{content:"\f38c"}.fa-d-and-d:before{content:"\f38d"}.fa-dashcube:before{content:"\f210"}.fa-database:before{content:"\f1c0"}.fa-deaf:before{content:"\f2a4"}.fa-delicious:before{content:"\f1a5"}.fa-deploydog:before{content:"\f38e"}.fa-deskpro:before{content:"\f38f"}.fa-desktop:before{content:"\f108"}.fa-deviantart:before{content:"\f1bd"}.fa-digg:before{content:"\f1a6"}.fa-digital-ocean:before{content:"\f391"}.fa-discord:before{content:"\f392"}.fa-discourse:before{content:"\f393"}.fa-dna:before{content:"\f471"}.fa-dochub:before{content:"\f394"}.fa-docker:before{content:"\f395"}.fa-dollar-sign:before{content:"\f155"}.fa-dolly:before{content:"\f472"}.fa-dolly-flatbed:before{content:"\f474"}.fa-dot-circle:before{content:"\f192"}.fa-download:before{content:"\f019"}.fa-draft2digital:before{content:"\f396"}.fa-dribbble:before{content:"\f17d"}.fa-dribbble-square:before{content:"\f397"}.fa-dropbox:before{content:"\f16b"}.fa-drupal:before{content:"\f1a9"}.fa-dyalog:before{content:"\f399"}.fa-earlybirds:before{content:"\f39a"}.fa-edge:before{content:"\f282"}.fa-edit:before{content:"\f044"}.fa-eject:before{content:"\f052"}.fa-elementor:before{content:"\f430"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-ember:before{content:"\f423"}.fa-empire:before{content:"\f1d1"}.fa-envelope:before{content:"\f0e0"}.fa-envelope-open:before{content:"\f2b6"}.fa-envelope-square:before{content:"\f199"}.fa-envira:before{content:"\f299"}.fa-eraser:before{content:"\f12d"}.fa-erlang:before{content:"\f39d"}.fa-ethereum:before{content:"\f42e"}.fa-etsy:before{content:"\f2d7"}.fa-euro-sign:before{content:"\f153"}.fa-exchange-alt:before{content:"\f362"}.fa-exclamation:before{content:"\f12a"}.fa-exclamation-circle:before{content:"\f06a"}.fa-exclamation-triangle:before{content:"\f071"}.fa-expand:before{content:"\f065"}.fa-expand-arrows-alt:before{content:"\f31e"}.fa-expeditedssl:before{content:"\f23e"}.fa-external-link-alt:before{content:"\f35d"}.fa-external-link-square-alt:before{content:"\f360"}.fa-eye:before{content:"\f06e"}.fa-eye-dropper:before{content:"\f1fb"}.fa-eye-slash:before{content:"\f070"}.fa-facebook:before{content:"\f09a"}.fa-facebook-f:before{content:"\f39e"}.fa-facebook-messenger:before{content:"\f39f"}.fa-facebook-square:before{content:"\f082"}.fa-fast-backward:before{content:"\f049"}.fa-fast-forward:before{content:"\f050"}.fa-fax:before{content:"\f1ac"}.fa-female:before{content:"\f182"}.fa-fighter-jet:before{content:"\f0fb"}.fa-file:before{content:"\f15b"}.fa-file-alt:before{content:"\f15c"}.fa-file-archive:before{content:"\f1c6"}.fa-file-audio:before{content:"\f1c7"}.fa-file-code:before{content:"\f1c9"}.fa-file-excel:before{content:"\f1c3"}.fa-file-image:before{content:"\f1c5"}.fa-file-pdf:before{content:"\f1c1"}.fa-file-powerpoint:before{content:"\f1c4"}.fa-file-video:before{content:"\f1c8"}.fa-file-word:before{content:"\f1c2"}.fa-film:before{content:"\f008"}.fa-filter:before{content:"\f0b0"}.fa-fire:before{content:"\f06d"}.fa-fire-extinguisher:before{content:"\f134"}.fa-firefox:before{content:"\f269"}.fa-first-aid:before{content:"\f479"}.fa-first-order:before{content:"\f2b0"}.fa-firstdraft:before{content:"\f3a1"}.fa-flag:before{content:"\f024"}.fa-flag-checkered:before{content:"\f11e"}.fa-flask:before{content:"\f0c3"}.fa-flickr:before{content:"\f16e"}.fa-flipboard:before{content:"\f44d"}.fa-fly:before{content:"\f417"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-font:before{content:"\f031"}.fa-font-awesome:before{content:"\f2b4"}.fa-font-awesome-alt:before{content:"\f35c"}.fa-font-awesome-flag:before{content:"\f425"}.fa-fonticons:before{content:"\f280"}.fa-fonticons-fi:before{content:"\f3a2"}.fa-football-ball:before{content:"\f44e"}.fa-fort-awesome:before{content:"\f286"}.fa-fort-awesome-alt:before{content:"\f3a3"}.fa-forumbee:before{content:"\f211"}.fa-forward:before{content:"\f04e"}.fa-foursquare:before{content:"\f180"}.fa-free-code-camp:before{content:"\f2c5"}.fa-freebsd:before{content:"\f3a4"}.fa-frown:before{content:"\f119"}.fa-futbol:before{content:"\f1e3"}.fa-gamepad:before{content:"\f11b"}.fa-gavel:before{content:"\f0e3"}.fa-gem:before{content:"\f3a5"}.fa-genderless:before{content:"\f22d"}.fa-get-pocket:before{content:"\f265"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-gift:before{content:"\f06b"}.fa-git:before{content:"\f1d3"}.fa-git-square:before{content:"\f1d2"}.fa-github:before{content:"\f09b"}.fa-github-alt:before{content:"\f113"}.fa-github-square:before{content:"\f092"}.fa-gitkraken:before{content:"\f3a6"}.fa-gitlab:before{content:"\f296"}.fa-gitter:before{content:"\f426"}.fa-glass-martini:before{content:"\f000"}.fa-glide:before{content:"\f2a5"}.fa-glide-g:before{content:"\f2a6"}.fa-globe:before{content:"\f0ac"}.fa-gofore:before{content:"\f3a7"}.fa-golf-ball:before{content:"\f450"}.fa-goodreads:before{content:"\f3a8"}.fa-goodreads-g:before{content:"\f3a9"}.fa-google:before{content:"\f1a0"}.fa-google-drive:before{content:"\f3aa"}.fa-google-play:before{content:"\f3ab"}.fa-google-plus:before{content:"\f2b3"}.fa-google-plus-g:before{content:"\f0d5"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-wallet:before{content:"\f1ee"}.fa-graduation-cap:before{content:"\f19d"}.fa-gratipay:before{content:"\f184"}.fa-grav:before{content:"\f2d6"}.fa-gripfire:before{content:"\f3ac"}.fa-grunt:before{content:"\f3ad"}.fa-gulp:before{content:"\f3ae"}.fa-h-square:before{content:"\f0fd"}.fa-hacker-news:before{content:"\f1d4"}.fa-hacker-news-square:before{content:"\f3af"}.fa-hand-lizard:before{content:"\f258"}.fa-hand-paper:before{content:"\f256"}.fa-hand-peace:before{content:"\f25b"}.fa-hand-point-down:before{content:"\f0a7"}.fa-hand-point-left:before{content:"\f0a5"}.fa-hand-point-right:before{content:"\f0a4"}.fa-hand-point-up:before{content:"\f0a6"}.fa-hand-pointer:before{content:"\f25a"}.fa-hand-rock:before{content:"\f255"}.fa-hand-scissors:before{content:"\f257"}.fa-hand-spock:before{content:"\f259"}.fa-handshake:before{content:"\f2b5"}.fa-hashtag:before{content:"\f292"}.fa-hdd:before{content:"\f0a0"}.fa-heading:before{content:"\f1dc"}.fa-headphones:before{content:"\f025"}.fa-heart:before{content:"\f004"}.fa-heartbeat:before{content:"\f21e"}.fa-hips:before{content:"\f452"}.fa-hire-a-helper:before{content:"\f3b0"}.fa-history:before{content:"\f1da"}.fa-hockey-puck:before{content:"\f453"}.fa-home:before{content:"\f015"}.fa-hooli:before{content:"\f427"}.fa-hospital:before{content:"\f0f8"}.fa-hospital-symbol:before{content:"\f47e"}.fa-hotjar:before{content:"\f3b1"}.fa-hourglass:before{content:"\f254"}.fa-hourglass-end:before{content:"\f253"}.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-start:before{content:"\f251"}.fa-houzz:before{content:"\f27c"}.fa-html5:before{content:"\f13b"}.fa-hubspot:before{content:"\f3b2"}.fa-i-cursor:before{content:"\f246"}.fa-id-badge:before{content:"\f2c1"}.fa-id-card:before{content:"\f2c2"}.fa-image:before{content:"\f03e"}.fa-images:before{content:"\f302"}.fa-imdb:before{content:"\f2d8"}.fa-inbox:before{content:"\f01c"}.fa-indent:before{content:"\f03c"}.fa-industry:before{content:"\f275"}.fa-info:before{content:"\f129"}.fa-info-circle:before{content:"\f05a"}.fa-instagram:before{content:"\f16d"}.fa-internet-explorer:before{content:"\f26b"}.fa-ioxhost:before{content:"\f208"}.fa-italic:before{content:"\f033"}.fa-itunes:before{content:"\f3b4"}.fa-itunes-note:before{content:"\f3b5"}.fa-jenkins:before{content:"\f3b6"}.fa-joget:before{content:"\f3b7"}.fa-joomla:before{content:"\f1aa"}.fa-js:before{content:"\f3b8"}.fa-js-square:before{content:"\f3b9"}.fa-jsfiddle:before{content:"\f1cc"}.fa-key:before{content:"\f084"}.fa-keyboard:before{content:"\f11c"}.fa-keycdn:before{content:"\f3ba"}.fa-kickstarter:before{content:"\f3bb"}.fa-kickstarter-k:before{content:"\f3bc"}.fa-korvue:before{content:"\f42f"}.fa-language:before{content:"\f1ab"}.fa-laptop:before{content:"\f109"}.fa-laravel:before{content:"\f3bd"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-leaf:before{content:"\f06c"}.fa-leanpub:before{content:"\f212"}.fa-lemon:before{content:"\f094"}.fa-less:before{content:"\f41d"}.fa-level-down-alt:before{content:"\f3be"}.fa-level-up-alt:before{content:"\f3bf"}.fa-life-ring:before{content:"\f1cd"}.fa-lightbulb:before{content:"\f0eb"}.fa-line:before{content:"\f3c0"}.fa-link:before{content:"\f0c1"}.fa-linkedin:before{content:"\f08c"}.fa-linkedin-in:before{content:"\f0e1"}.fa-linode:before{content:"\f2b8"}.fa-linux:before{content:"\f17c"}.fa-lira-sign:before{content:"\f195"}.fa-list:before{content:"\f03a"}.fa-list-alt:before{content:"\f022"}.fa-list-ol:before{content:"\f0cb"}.fa-list-ul:before{content:"\f0ca"}.fa-location-arrow:before{content:"\f124"}.fa-lock:before{content:"\f023"}.fa-lock-open:before{content:"\f3c1"}.fa-long-arrow-alt-down:before{content:"\f309"}.fa-long-arrow-alt-left:before{content:"\f30a"}.fa-long-arrow-alt-right:before{content:"\f30b"}.fa-long-arrow-alt-up:before{content:"\f30c"}.fa-low-vision:before{content:"\f2a8"}.fa-lyft:before{content:"\f3c3"}.fa-magento:before{content:"\f3c4"}.fa-magic:before{content:"\f0d0"}.fa-magnet:before{content:"\f076"}.fa-male:before{content:"\f183"}.fa-map:before{content:"\f279"}.fa-map-marker:before{content:"\f041"}.fa-map-marker-alt:before{content:"\f3c5"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-mars:before{content:"\f222"}.fa-mars-double:before{content:"\f227"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-maxcdn:before{content:"\f136"}.fa-medapps:before{content:"\f3c6"}.fa-medium:before{content:"\f23a"}.fa-medium-m:before{content:"\f3c7"}.fa-medkit:before{content:"\f0fa"}.fa-medrt:before{content:"\f3c8"}.fa-meetup:before{content:"\f2e0"}.fa-meh:before{content:"\f11a"}.fa-mercury:before{content:"\f223"}.fa-microchip:before{content:"\f2db"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-microsoft:before{content:"\f3ca"}.fa-minus:before{content:"\f068"}.fa-minus-circle:before{content:"\f056"}.fa-minus-square:before{content:"\f146"}.fa-mix:before{content:"\f3cb"}.fa-mixcloud:before{content:"\f289"}.fa-mizuni:before{content:"\f3cc"}.fa-mobile:before{content:"\f10b"}.fa-mobile-alt:before{content:"\f3cd"}.fa-modx:before{content:"\f285"}.fa-monero:before{content:"\f3d0"}.fa-money-bill-alt:before{content:"\f3d1"}.fa-moon:before{content:"\f186"}.fa-motorcycle:before{content:"\f21c"}.fa-mouse-pointer:before{content:"\f245"}.fa-music:before{content:"\f001"}.fa-napster:before{content:"\f3d2"}.fa-neuter:before{content:"\f22c"}.fa-newspaper:before{content:"\f1ea"}.fa-nintendo-switch:before{content:"\f418"}.fa-node:before{content:"\f419"}.fa-node-js:before{content:"\f3d3"}.fa-npm:before{content:"\f3d4"}.fa-ns8:before{content:"\f3d5"}.fa-nutritionix:before{content:"\f3d6"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-opencart:before{content:"\f23d"}.fa-openid:before{content:"\f19b"}.fa-opera:before{content:"\f26a"}.fa-optin-monster:before{content:"\f23c"}.fa-osi:before{content:"\f41a"}.fa-outdent:before{content:"\f03b"}.fa-page4:before{content:"\f3d7"}.fa-pagelines:before{content:"\f18c"}.fa-paint-brush:before{content:"\f1fc"}.fa-palfed:before{content:"\f3d8"}.fa-pallet:before{content:"\f482"}.fa-paper-plane:before{content:"\f1d8"}.fa-paperclip:before{content:"\f0c6"}.fa-paragraph:before{content:"\f1dd"}.fa-paste:before{content:"\f0ea"}.fa-patreon:before{content:"\f3d9"}.fa-pause:before{content:"\f04c"}.fa-pause-circle:before{content:"\f28b"}.fa-paw:before{content:"\f1b0"}.fa-paypal:before{content:"\f1ed"}.fa-pen-square:before{content:"\f14b"}.fa-pencil-alt:before{content:"\f303"}.fa-percent:before{content:"\f295"}.fa-periscope:before{content:"\f3da"}.fa-phabricator:before{content:"\f3db"}.fa-phoenix-framework:before{content:"\f3dc"}.fa-phone:before{content:"\f095"}.fa-phone-square:before{content:"\f098"}.fa-phone-volume:before{content:"\f2a0"}.fa-php:before{content:"\f457"}.fa-pied-piper:before{content:"\f2ae"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-pied-piper-pp:before{content:"\f1a7"}.fa-pills:before{content:"\f484"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-p:before{content:"\f231"}.fa-pinterest-square:before{content:"\f0d3"}.fa-plane:before{content:"\f072"}.fa-play:before{content:"\f04b"}.fa-play-circle:before{content:"\f144"}.fa-playstation:before{content:"\f3df"}.fa-plug:before{content:"\f1e6"}.fa-plus:before{content:"\f067"}.fa-plus-circle:before{content:"\f055"}.fa-plus-square:before{content:"\f0fe"}.fa-podcast:before{content:"\f2ce"}.fa-pound-sign:before{content:"\f154"}.fa-power-off:before{content:"\f011"}.fa-print:before{content:"\f02f"}.fa-product-hunt:before{content:"\f288"}.fa-pushed:before{content:"\f3e1"}.fa-puzzle-piece:before{content:"\f12e"}.fa-python:before{content:"\f3e2"}.fa-qq:before{content:"\f1d6"}.fa-qrcode:before{content:"\f029"}.fa-question:before{content:"\f128"}.fa-question-circle:before{content:"\f059"}.fa-quidditch:before{content:"\f458"}.fa-quinscape:before{content:"\f459"}.fa-quora:before{content:"\f2c4"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-random:before{content:"\f074"}.fa-ravelry:before{content:"\f2d9"}.fa-react:before{content:"\f41b"}.fa-rebel:before{content:"\f1d0"}.fa-recycle:before{content:"\f1b8"}.fa-red-river:before{content:"\f3e3"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-alien:before{content:"\f281"}.fa-reddit-square:before{content:"\f1a2"}.fa-redo:before{content:"\f01e"}.fa-redo-alt:before{content:"\f2f9"}.fa-registered:before{content:"\f25d"}.fa-rendact:before{content:"\f3e4"}.fa-renren:before{content:"\f18b"}.fa-reply:before{content:"\f3e5"}.fa-reply-all:before{content:"\f122"}.fa-replyd:before{content:"\f3e6"}.fa-resolving:before{content:"\f3e7"}.fa-retweet:before{content:"\f079"}.fa-road:before{content:"\f018"}.fa-rocket:before{content:"\f135"}.fa-rocketchat:before{content:"\f3e8"}.fa-rockrms:before{content:"\f3e9"}.fa-rss:before{content:"\f09e"}.fa-rss-square:before{content:"\f143"}.fa-ruble-sign:before{content:"\f158"}.fa-rupee-sign:before{content:"\f156"}.fa-safari:before{content:"\f267"}.fa-sass:before{content:"\f41e"}.fa-save:before{content:"\f0c7"}.fa-schlix:before{content:"\f3ea"}.fa-scribd:before{content:"\f28a"}.fa-search:before{content:"\f002"}.fa-search-minus:before{content:"\f010"}.fa-search-plus:before{content:"\f00e"}.fa-searchengin:before{content:"\f3eb"}.fa-sellcast:before{content:"\f2da"}.fa-sellsy:before{content:"\f213"}.fa-server:before{content:"\f233"}.fa-servicestack:before{content:"\f3ec"}.fa-share:before{content:"\f064"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-share-square:before{content:"\f14d"}.fa-shekel-sign:before{content:"\f20b"}.fa-shield-alt:before{content:"\f3ed"}.fa-ship:before{content:"\f21a"}.fa-shipping-fast:before{content:"\f48b"}.fa-shirtsinbulk:before{content:"\f214"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-shopping-cart:before{content:"\f07a"}.fa-shower:before{content:"\f2cc"}.fa-sign-in-alt:before{content:"\f2f6"}.fa-sign-language:before{content:"\f2a7"}.fa-sign-out-alt:before{content:"\f2f5"}.fa-signal:before{content:"\f012"}.fa-simplybuilt:before{content:"\f215"}.fa-sistrix:before{content:"\f3ee"}.fa-sitemap:before{content:"\f0e8"}.fa-skyatlas:before{content:"\f216"}.fa-skype:before{content:"\f17e"}.fa-slack:before{content:"\f198"}.fa-slack-hash:before{content:"\f3ef"}.fa-sliders-h:before{content:"\f1de"}.fa-slideshare:before{content:"\f1e7"}.fa-smile:before{content:"\f118"}.fa-snapchat:before{content:"\f2ab"}.fa-snapchat-ghost:before{content:"\f2ac"}.fa-snapchat-square:before{content:"\f2ad"}.fa-snowflake:before{content:"\f2dc"}.fa-sort:before{content:"\f0dc"}.fa-sort-alpha-down:before{content:"\f15d"}.fa-sort-alpha-up:before{content:"\f15e"}.fa-sort-amount-down:before{content:"\f160"}.fa-sort-amount-up:before{content:"\f161"}.fa-sort-down:before{content:"\f0dd"}.fa-sort-numeric-down:before{content:"\f162"}.fa-sort-numeric-up:before{content:"\f163"}.fa-sort-up:before{content:"\f0de"}.fa-soundcloud:before{content:"\f1be"}.fa-space-shuttle:before{content:"\f197"}.fa-speakap:before{content:"\f3f3"}.fa-spinner:before{content:"\f110"}.fa-spotify:before{content:"\f1bc"}.fa-square:before{content:"\f0c8"}.fa-square-full:before{content:"\f45c"}.fa-stack-exchange:before{content:"\f18d"}.fa-stack-overflow:before{content:"\f16c"}.fa-star:before{content:"\f005"}.fa-star-half:before{content:"\f089"}.fa-staylinked:before{content:"\f3f5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-steam-symbol:before{content:"\f3f6"}.fa-step-backward:before{content:"\f048"}.fa-step-forward:before{content:"\f051"}.fa-stethoscope:before{content:"\f0f1"}.fa-sticker-mule:before{content:"\f3f7"}.fa-sticky-note:before{content:"\f249"}.fa-stop:before{content:"\f04d"}.fa-stop-circle:before{content:"\f28d"}.fa-stopwatch:before{content:"\f2f2"}.fa-strava:before{content:"\f428"}.fa-street-view:before{content:"\f21d"}.fa-strikethrough:before{content:"\f0cc"}.fa-stripe:before{content:"\f429"}.fa-stripe-s:before{content:"\f42a"}.fa-studiovinari:before{content:"\f3f8"}.fa-stumbleupon:before{content:"\f1a4"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-subscript:before{content:"\f12c"}.fa-subway:before{content:"\f239"}.fa-suitcase:before{content:"\f0f2"}.fa-sun:before{content:"\f185"}.fa-superpowers:before{content:"\f2dd"}.fa-superscript:before{content:"\f12b"}.fa-supple:before{content:"\f3f9"}.fa-sync:before{content:"\f021"}.fa-sync-alt:before{content:"\f2f1"}.fa-syringe:before{content:"\f48e"}.fa-table:before{content:"\f0ce"}.fa-table-tennis:before{content:"\f45d"}.fa-tablet:before{content:"\f10a"}.fa-tablet-alt:before{content:"\f3fa"}.fa-tachometer-alt:before{content:"\f3fd"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-tasks:before{content:"\f0ae"}.fa-taxi:before{content:"\f1ba"}.fa-telegram:before{content:"\f2c6"}.fa-telegram-plane:before{content:"\f3fe"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-terminal:before{content:"\f120"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-th:before{content:"\f00a"}.fa-th-large:before{content:"\f009"}.fa-th-list:before{content:"\f00b"}.fa-themeisle:before{content:"\f2b2"}.fa-thermometer:before{content:"\f491"}.fa-thermometer-empty:before{content:"\f2cb"}.fa-thermometer-full:before{content:"\f2c7"}.fa-thermometer-half:before{content:"\f2c9"}.fa-thermometer-quarter:before{content:"\f2ca"}.fa-thermometer-three-quarters:before{content:"\f2c8"}.fa-thumbs-down:before{content:"\f165"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbtack:before{content:"\f08d"}.fa-ticket-alt:before{content:"\f3ff"}.fa-times:before{content:"\f00d"}.fa-times-circle:before{content:"\f057"}.fa-tint:before{content:"\f043"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-trademark:before{content:"\f25c"}.fa-train:before{content:"\f238"}.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-trash:before{content:"\f1f8"}.fa-trash-alt:before{content:"\f2ed"}.fa-tree:before{content:"\f1bb"}.fa-trello:before{content:"\f181"}.fa-tripadvisor:before{content:"\f262"}.fa-trophy:before{content:"\f091"}.fa-truck:before{content:"\f0d1"}.fa-tty:before{content:"\f1e4"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-tv:before{content:"\f26c"}.fa-twitch:before{content:"\f1e8"}.fa-twitter:before{content:"\f099"}.fa-twitter-square:before{content:"\f081"}.fa-typo3:before{content:"\f42b"}.fa-uber:before{content:"\f402"}.fa-uikit:before{content:"\f403"}.fa-umbrella:before{content:"\f0e9"}.fa-underline:before{content:"\f0cd"}.fa-undo:before{content:"\f0e2"}.fa-undo-alt:before{content:"\f2ea"}.fa-uniregistry:before{content:"\f404"}.fa-universal-access:before{content:"\f29a"}.fa-university:before{content:"\f19c"}.fa-unlink:before{content:"\f127"}.fa-unlock:before{content:"\f09c"}.fa-unlock-alt:before{content:"\f13e"}.fa-untappd:before{content:"\f405"}.fa-upload:before{content:"\f093"}.fa-usb:before{content:"\f287"}.fa-user:before{content:"\f007"}.fa-user-circle:before{content:"\f2bd"}.fa-user-md:before{content:"\f0f0"}.fa-user-plus:before{content:"\f234"}.fa-user-secret:before{content:"\f21b"}.fa-user-times:before{content:"\f235"}.fa-users:before{content:"\f0c0"}.fa-ussunnah:before{content:"\f407"}.fa-utensil-spoon:before{content:"\f2e5"}.fa-utensils:before{content:"\f2e7"}.fa-vaadin:before{content:"\f408"}.fa-venus:before{content:"\f221"}.fa-venus-double:before{content:"\f226"}.fa-venus-mars:before{content:"\f228"}.fa-viacoin:before{content:"\f237"}.fa-viadeo:before{content:"\f2a9"}.fa-viadeo-square:before{content:"\f2aa"}.fa-viber:before{content:"\f409"}.fa-video:before{content:"\f03d"}.fa-vimeo:before{content:"\f40a"}.fa-vimeo-square:before{content:"\f194"}.fa-vimeo-v:before{content:"\f27d"}.fa-vine:before{content:"\f1ca"}.fa-vk:before{content:"\f189"}.fa-vnv:before{content:"\f40b"}.fa-volleyball-ball:before{content:"\f45f"}.fa-volume-down:before{content:"\f027"}.fa-volume-off:before{content:"\f026"}.fa-volume-up:before{content:"\f028"}.fa-vuejs:before{content:"\f41f"}.fa-warehouse:before{content:"\f494"}.fa-weibo:before{content:"\f18a"}.fa-weight:before{content:"\f496"}.fa-weixin:before{content:"\f1d7"}.fa-whatsapp:before{content:"\f232"}.fa-whatsapp-square:before{content:"\f40c"}.fa-wheelchair:before{content:"\f193"}.fa-whmcs:before{content:"\f40d"}.fa-wifi:before{content:"\f1eb"}.fa-wikipedia-w:before{content:"\f266"}.fa-window-close:before{content:"\f410"}.fa-window-maximize:before{content:"\f2d0"}.fa-window-minimize:before{content:"\f2d1"}.fa-window-restore:before{content:"\f2d2"}.fa-windows:before{content:"\f17a"}.fa-won-sign:before{content:"\f159"}.fa-wordpress:before{content:"\f19a"}.fa-wordpress-simple:before{content:"\f411"}.fa-wpbeginner:before{content:"\f297"}.fa-wpexplorer:before{content:"\f2de"}.fa-wpforms:before{content:"\f298"}.fa-wrench:before{content:"\f0ad"}.fa-xbox:before{content:"\f412"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-y-combinator:before{content:"\f23b"}.fa-yahoo:before{content:"\f19e"}.fa-yandex:before{content:"\f413"}.fa-yandex-international:before{content:"\f414"}.fa-yelp:before{content:"\f1e9"}.fa-yen-sign:before{content:"\f157"}.fa-yoast:before{content:"\f2b1"}.fa-youtube:before{content:"\f167"}.fa-youtube-square:before{content:"\f431"}.sr-only{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.sr-only-focusable:active,.sr-only-focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto} \ No newline at end of file diff --git a/static/css/search.css b/static/css/search.css new file mode 100644 index 0000000..0296723 --- /dev/null +++ b/static/css/search.css @@ -0,0 +1,147 @@ +body {overflow-y:scroll;} +.document { + padding: 0.5rem; +} + +.document p { + margin-bottom: 0; +} + +.document:hover p { + text-decoration: underline; +} + +.badge-video { + color: #FFFFFF; + background-color: #F27761; +} + +.badge-image { + color: #FFFFFF; + background-color: #AA99C9; +} + +.badge-audio { + color: #FFFFFF; + background-color: #00ADEF; +} + +.badge-resolution { + color: #212529; + background-color: #FFC107; +} + +.badge-text { + color: #FFFFFF; + background-color: #FAAB3C; +} + +.card-img-top { + display: block; + min-width: 64px; + max-width: 100%; + max-height: 256px; + width: unset; + margin: 0 auto 0; + padding: 3px 3px 0 3px; +} + +.card-img-overlay { + pointer-events: none; + padding: 0.75rem; + + bottom: 0; + top: unset; + left: unset; + right: unset; +} + +.file-title { + font-size: 10pt; + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; +} + +.badge { + margin-right: 3px; +} + +.fit { + width: 100%; + height: 100%; + padding: 3px; + min-width: 64px; + max-width: 100%; + max-height: 256px; +} + +.audio-fit { + height: 39px; + vertical-align: bottom; +} + +@media (min-width: 1200px) { + .card-columns { + column-count: 4; + } +} + +@media (min-width: 1500px) { + .container { + max-width: 1440px; + } + .card-columns { + column-count: 5; + } +} + +.hl { + background: #fff217; +} + +.content-div { + font-family: SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace; + font-size: 13px; + padding: 1em; + background-color: #f5f5f5; + border: 1px solid #ccc; + border-radius: 4px; + margin: 3px; +} + +.irs-single, .irs-from, .irs-to { + font-size: 13px; +} + +.irs-slider { + cursor: col-resize; +} + +.custom-select { + overflow: auto; +} + +.irs { + margin-top: 1em; + margin-bottom: 1em; +} + +.inspire-tree .selected > .wholerow, .inspire-tree .selected > .title-wrap:hover + .wholerow +{ + background: none; +} + +.inspire-tree { + font-weight: 400; + font-size: 14px; + font-family: Helvetica, Nueue, Verdana, sans-serif; + max-height: 450px; + overflow: auto; +} + +.btn-xs { + padding: .1rem .3rem; + font-size: .875rem; + border-radius: .2rem; +} \ No newline at end of file diff --git a/static/js/search.js b/static/js/search.js new file mode 100644 index 0000000..73178f5 --- /dev/null +++ b/static/js/search.js @@ -0,0 +1,604 @@ +let searchBar = document.getElementById("searchBar"); +let pathBar = document.getElementById("pathBar"); +let must_match = true; +let scroll_id = null; +let docCount = 0; +let searchQueued = false; +let coolingDown = false; +let selectedDirs = []; + +function toggleSearchBar() { + must_match = !must_match; + searchQueued = true; +} + +let tree = new InspireTree({ + selection: { + mode: 'checkbox' + }, + data: mimeMap +}); +new InspireTreeDOM(tree, { + target: '.tree' +}); + +//Select all +tree.select(); +tree.node("any").deselect(); + +tree.on("node.click", function(event, node, handler) { + event.preventTreeDefault(); + + if (node.id === "any") { + + if (!node.itree.state.checked) { + tree.deselect(); + } + } else { + tree.node("any").deselect(); + } + + handler(); + searchQueued = true; +}); + +new autoComplete({ + selector: '#pathBar', + minChars: 1, + delay: 75, + renderItem: function (item){ + return '
' + item + '
'; + }, + source: async function(term, suggest) { + term = term.toLowerCase(); + + const choices = await getPathChoices(); + + let matches = []; + for (let i=0; i= thresh && u < units.length - 1); + + return bytes.toFixed(1) + ' ' + units[u]; +} + + +function initPopover() { + $('[data-toggle="popover"]').popover({ + trigger: "focus", + delay: { "show": 0, "hide": 100 }, + placement: "bottom", + html: true + }); +} + +/** + * Enable gif loading on hover + * @param thumbnail + * @param documentId + */ +function gifOver(thumbnail, documentId) { + let callee = arguments.callee; + + thumbnail.addEventListener("mouseover", function () { + + thumbnail.mouseStayedOver = true; + + window.setTimeout(function() { + if (thumbnail.mouseStayedOver) { + thumbnail.removeEventListener('mouseover', callee, false); + + //Load gif + thumbnail.setAttribute("src", "/file/" + documentId); + } + }, 750); //todo grab hover time from config + + }); + + thumbnail.addEventListener("mouseout", function() { + //Reset timer + thumbnail.mouseStayedOver = false; + thumbnail.setAttribute("src", "/thumb/" + documentId); + + }) +} + +function videoOver(thumbnail, imgWrapper, thumbnailOverlay, documentId, docCard) { + + docCard.addEventListener("focus", function () { + let callee = arguments.callee; + docCard.mouseStayedOver = true; + + window.setTimeout(function() { + + if(docCard.mouseStayedOver) { + docCard.removeEventListener('focus', callee, false); + + imgWrapper.removeChild(thumbnail); + imgWrapper.removeChild(thumbnailOverlay); + + let video = document.createElement("video"); + let vidSource = document.createElement("source"); + vidSource.setAttribute("src", "/file/" + documentId); + vidSource.setAttribute("type", "video/webm"); + video.appendChild(vidSource); + video.setAttribute("class", "fit"); + video.setAttribute("loop", ""); + video.setAttribute("controls", ""); + video.setAttribute("preload", ""); + video.setAttribute("poster", "/thumb/" + documentId); + imgWrapper.appendChild(video); + + video.addEventListener("dblclick", function() { + video.webkitRequestFullScreen(); + }) + } + }, 750); + }); + docCard.addEventListener("blur", function() { + docCard.mouseStayedOver = false; + }); +} + +function downloadPopover(element, documentId) { + element.setAttribute("data-content", + ' Download' + + ' View'); + element.setAttribute("data-toggle", "popover"); + element.addEventListener("mouseover", function() { + element.focus(); + }); +} + +/** + * + * @param hit + * @returns {Element} + */ +function createDocCard(hit) { + + let docCard = document.createElement("div"); + docCard.setAttribute("class", "card"); + docCard.setAttribute("tabindex", "-1"); + + let docCardBody = document.createElement("div"); + docCardBody.setAttribute("class", "card-body document"); + + let link = document.createElement("a"); + link.setAttribute("href", "/document/" + hit["_id"]); + link.setAttribute("target", "_blank"); + + //Title + let title = document.createElement("p"); + title.setAttribute("class", "file-title"); + let extension = hit["_source"].hasOwnProperty("extension") && hit["_source"]["extension"] !== "" ? "." + hit["_source"]["extension"] : ""; + + if (hit.hasOwnProperty("highlight") && hit["highlight"].hasOwnProperty("name")) { + title.insertAdjacentHTML('afterbegin', hit["highlight"]["name"] + extension); + } else { + title.appendChild(document.createTextNode(hit["_source"]["name"] + extension)); + } + + title.setAttribute("title", hit["_source"]["path"] + hit["_source"]["name"] + extension); + docCard.appendChild(title); + + let tagContainer = document.createElement("div"); + tagContainer.setAttribute("class", "card-text"); + + if (hit["_source"].hasOwnProperty("mime") && hit["_source"]["mime"] !== null) { + + let tags = []; + let thumbnail = null; + let thumbnailOverlay = null; + let imgWrapper = document.createElement("div"); + imgWrapper.setAttribute("style", "position: relative"); + + let mimeCategory = hit["_source"]["mime"].split("/")[0]; + + //Thumbnail + switch (mimeCategory) { + + case "video": + case "image": + thumbnail = document.createElement("img"); + thumbnail.setAttribute("class", "card-img-top"); + thumbnail.setAttribute("src", "/thumb/" + hit["_id"]); + break; + } + + //Thumbnail overlay + switch (mimeCategory) { + + case "image": + thumbnailOverlay = document.createElement("div"); + thumbnailOverlay.setAttribute("class", "card-img-overlay"); + + //Resolution + let resolutionBadge = document.createElement("span"); + resolutionBadge.setAttribute("class", "badge badge-resolution"); + if (hit["_source"].hasOwnProperty("width")) { + resolutionBadge.appendChild(document.createTextNode(hit["_source"]["width"] + "x" + hit["_source"]["height"])); + } + thumbnailOverlay.appendChild(resolutionBadge); + + var format = hit["_source"]["format"]; + + //Hover + if(format === "GIF") { + gifOver(thumbnail, hit["_id"]); + } + break; + + case "video": + thumbnailOverlay = document.createElement("div"); + thumbnailOverlay.setAttribute("class", "card-img-overlay"); + + //Duration + let durationBadge = document.createElement("span"); + durationBadge.setAttribute("class", "badge badge-resolution"); + durationBadge.appendChild(document.createTextNode(parseFloat(hit["_source"]["duration"]).toFixed(2) + "s")); + thumbnailOverlay.appendChild(durationBadge); + + //Hover + videoOver(thumbnail, imgWrapper, thumbnailOverlay, hit["_id"], docCard) + + } + + //Tags + switch (mimeCategory) { + + case "video": + if (hit["_source"].hasOwnProperty("format_long_name")) { + let formatTag = document.createElement("span"); + formatTag.setAttribute("class", "badge badge-pill badge-video"); + formatTag.appendChild(document.createTextNode(hit["_source"]["format_long_name"].replace(" ", ""))); + tags.push(formatTag); + } + + break; + case "image": { + let formatTag = document.createElement("span"); + formatTag.setAttribute("class", "badge badge-pill badge-image"); + formatTag.appendChild(document.createTextNode(format)); + tags.push(formatTag); + } + break; + case "audio": { + if (hit["_source"].hasOwnProperty("format_long_name")) { + let formatTag = document.createElement("span"); + formatTag.setAttribute("class", "badge badge-pill badge-audio"); + formatTag.appendChild(document.createTextNode(hit["_source"]["format_long_name"])); + tags.push(formatTag); + } + + } + + break; + case "text": { + let formatTag = document.createElement("span"); + formatTag.setAttribute("class", "badge badge-pill badge-text"); + formatTag.appendChild(document.createTextNode(hit["_source"]["encoding"])); + tags.push(formatTag); + } + + break; + } + + //Content + if (hit.hasOwnProperty("highlight") && hit["highlight"].hasOwnProperty("content")) { + + let contentDiv = document.createElement("div"); + contentDiv.setAttribute("class", "content-div bg-light"); + contentDiv.insertAdjacentHTML('afterbegin', hit["highlight"]["content"][0]); + docCard.appendChild(contentDiv); + } + + //Audio + if (mimeCategory === "audio" && hit["_source"].hasOwnProperty("format_long_name")) { + + let audio = document.createElement("audio"); + audio.setAttribute("preload", "none"); + audio.setAttribute("class", "audio-fit fit"); + audio.setAttribute("controls", ""); + audio.setAttribute("type", hit["_source"]["mime"]); + audio.setAttribute("src", "file/" + hit["_id"]); + + docCard.appendChild(audio) + } + + if (thumbnail !== null) { + imgWrapper.appendChild(thumbnail); + docCard.appendChild(imgWrapper); + } + if (thumbnailOverlay !== null) { + imgWrapper.appendChild(thumbnailOverlay); + } + + for (let i = 0; i < tags.length; i++) { + tagContainer.appendChild(tags[i]); + } + + + } + + //Size tag + let sizeTag = document.createElement("small"); + sizeTag.appendChild(document.createTextNode(humanFileSize(hit["_source"]["size"]))); + sizeTag.setAttribute("class", "text-muted"); + tagContainer.appendChild(sizeTag); + + + //Download button + downloadPopover(docCard, hit["_id"]); + + docCardBody.appendChild(link); + docCard.appendChild(docCardBody); + + link.appendChild(title); + docCardBody.appendChild(tagContainer); + + return docCard; +} + +function makePageIndicator(searchResult) { + let pageIndicator = document.createElement("div"); + pageIndicator.appendChild(document.createTextNode(docCount + " / " +searchResult["hits"]["total"])); + return pageIndicator; +} + + +function insertHits(resultContainer, hits) { + for (let i = 0 ; i < hits.length; i++) { + resultContainer.appendChild(createDocCard(hits[i])); + docCount++; + } +} + +window.addEventListener("scroll", function () { + + if (!coolingDown) { + + let threshold = 350; + + if ((window.innerHeight + window.scrollY) >= document.body.offsetHeight - threshold) { + //load next page + + let xhttp = new XMLHttpRequest(); + xhttp.onreadystatechange = function() { + if (this.readyState === 4 && this.status === 200) { + + let searchResult = JSON.parse(this.responseText); + let searchResults = document.getElementById("searchResults"); + let hits = searchResult["hits"]["hits"]; + + //Page indicator + let pageIndicator = makePageIndicator(searchResult); + searchResults.appendChild(pageIndicator); + + //Result container + let resultContainer = makeResultContainer(); + searchResults.appendChild(resultContainer); + + insertHits(resultContainer, hits); + + initPopover(); + + if (hits.length !== 0) { + coolingDown = false; + } + } + }; + xhttp.open("GET", "/scroll?scroll_id=" + scroll_id, true); + xhttp.send(); + coolingDown = true; + } + } +}); + +function getSelectedMimeTypes() { + let mimeTypes = []; + + let selected = tree.selected(); + + for (let i = 0; i < selected.length; i++) { + + if(selected[i].id === "any") { + return "any" + } + + //Only get children + if (selected[i].text.indexOf("(") !== -1) { + mimeTypes.push(selected[i].id); + } + } + + return mimeTypes +} + +function search() { + + if (searchQueued === true) { + searchQueued = false; + + //Clear old search results + let searchResults = document.getElementById("searchResults"); + while (searchResults.firstChild) { + searchResults.removeChild(searchResults.firstChild); + } + + let query = searchBar.value; + + let xhttp = new XMLHttpRequest(); + xhttp.onreadystatechange = function() { + if (this.readyState === 4 && this.status === 200) { + + let searchResult = JSON.parse(this.responseText); + scroll_id = searchResult["_scroll_id"]; + + //Search stats + searchResults.appendChild(makeStatsCard(searchResult)); + + //Autocomplete + if (searchResult.hasOwnProperty("suggest") && searchResult["suggest"].hasOwnProperty("path")) { + pathAutoComplete = []; + for (let i = 0; i < searchResult["suggest"]["path"][0]["options"].length; i++) { + pathAutoComplete.push(searchResult["suggest"]["path"][0]["options"][i].text) + } + } + + + //Setup page + let resultContainer = makeResultContainer(); + searchResults.appendChild(resultContainer); + + //Insert search results (hits) + docCount = 0; + insertHits(resultContainer, searchResult["hits"]["hits"]); + + //Initialise download/view button popover + initPopover(); + } + }; + + xhttp.open("POST", "/search", true); + + let postBody = {}; + postBody.q = query; + postBody.size_min = size_min; + postBody.size_max = size_max; + postBody.mime_types = getSelectedMimeTypes(); + postBody.must_match = must_match; + postBody.directories = selectedDirs; + postBody.path = pathBar.value.replace(/\/$/, "").toLowerCase(); //remove trailing slashes + xhttp.setRequestHeader('content-type', 'application/json'); + xhttp.send(JSON.stringify(postBody)); + } +} + +let pathAutoComplete = []; +let size_min = 0; +let size_max = 10000000000000; + +searchBar.addEventListener("keyup", function () { + searchQueued = true; +}); + +//Size slider +let sizeSlider = $("#sizeSlider").ionRangeSlider({ + type: "double", + grid: false, + force_edges: true, + min: 0, + max: 3684.03149864, + from: 0, + to: 3684.03149864, + min_interval: 5, + drag_interval: true, + prettify: function (num) { + + if(num === 0) { + return "0 B" + } else if (num >= 3684) { + return humanFileSize(num * num * num) + "+"; + } + + return humanFileSize(num * num * num) + }, + onChange: function(e) { + size_min = (e.from * e.from * e.from); + size_max = (e.to * e.to * e.to); + + if (e.to >= 3684) { + size_max = 10000000000000; + } + + searchQueued = true; + } +})[0]; + +//Directories select +function updateDirectories() { + let selected = $('#directories').find('option:selected'); + selectedDirs = []; + $(selected).each(function(){ + selectedDirs.push(parseInt($(this).val())); + }); + + searchQueued = true; +} +document.getElementById("directories").addEventListener("change", updateDirectories); +updateDirectories(); +searchQueued = false; + +//Suggest +function getPathChoices() { + return new Promise(getPaths => { + + let xhttp = new XMLHttpRequest(); + xhttp.onreadystatechange = function() { + if (this.readyState === 4 && this.status === 200) { + getPaths(JSON.parse(xhttp.responseText)) + } + }; + xhttp.open("GET", "/suggest?prefix=" + pathBar.value, true); + xhttp.send(); + }); +} + + +window.setInterval(search, 75); \ No newline at end of file diff --git a/storage.py b/storage.py index c3584e3..e9464a6 100644 --- a/storage.py +++ b/storage.py @@ -8,7 +8,7 @@ import config class CheckSumCalculator: def checksum(self, string: str): - return flask_bcrypt.generate_password_hash(string, 14) # todo load from config + return flask_bcrypt.generate_password_hash(string, config.bcrypt_rounds) class DuplicateDirectoryException(Exception): diff --git a/templates/layout.html b/templates/layout.html index 0b26f9a..e65b702 100644 --- a/templates/layout.html +++ b/templates/layout.html @@ -11,20 +11,18 @@ - -{# #} - + {% block imports %}{% endblock %} -
-
@@ -168,14 +20,14 @@
Must match  - +
- +
@@ -196,642 +48,15 @@
- - -
- - -
- -
+
+
{% endblock body %} \ No newline at end of file diff --git a/templates/task.html b/templates/task.html index fc22a31..bf80b1d 100644 --- a/templates/task.html +++ b/templates/task.html @@ -74,8 +74,8 @@ return; } - var currentTask = JSON.parse(this.responseText); - var percent = currentTask.parsed / currentTask.total * 100; + let currentTask = JSON.parse(this.responseText); + let percent = currentTask.parsed / currentTask.total * 100; try { @@ -84,7 +84,7 @@ document.getElementById("task-label-" + currentTask.id).innerHTML = "Calculating file count..."; } else { - var bar = document.getElementById("task-bar-" + currentTask.id); + let bar = document.getElementById("task-bar-" + currentTask.id); bar.setAttribute("style", "width: " + percent + "%;"); document.getElementById("task-label-" + currentTask.id).innerHTML = currentTask.parsed + " / " + currentTask.total + " (" + percent.toFixed(2) + "%)"; @@ -93,8 +93,6 @@ } } - - } catch (e) { window.reload(); } diff --git a/thumbnail.py b/thumbnail.py index 038b7b0..da093f6 100644 --- a/thumbnail.py +++ b/thumbnail.py @@ -37,12 +37,13 @@ class ThumbnailGenerator: try: (ffmpeg. input(path) - .overwrite_output("tmp", vframes=1, f="image2", loglevel="error") + .output("tmp", vframes=1, f="image2", loglevel="error") .run() ) self.generate_image("tmp", dest_path) os.remove("tmp") except Exception as e: + print(e) print("Couldn't make thumbnail for " + path) def generate_all(self, docs, dest_path, counter: Value=None): diff --git a/tmp_specs b/tmp_specs deleted file mode 100644 index 3c3947f..0000000 --- a/tmp_specs +++ /dev/null @@ -1,28 +0,0 @@ -Ajouter un utilisateur -mettre admin -Enlever admin - ne marche pas si t'est le seul admin - -y'existe conn.executescript - -Utiliser des functions queries pour afficher genre le total size of query, etc - Utiliser opendirectories-bot pour afficher des info - - - -Plugins - MP3 tags - todo: other music - Font files - images - video tags - -use es filter to filter out folders that the user has no permission to search - -option to toggle auto complete -option to set password loop count -option to chose checksum thingy -option to chose mime guesser -option to toggle search history/stats - -thumbnails are stored in a folder for each folder: easy to delete \ No newline at end of file