Compare commits
	
		
			37 Commits 
		
	
	
	| 
		 After Width: | Height: | Size: 13 KiB  | 
@ -1,3 +1,3 @@ | 
				
			||||
body { margin:0;background-color:black; } | 
				
			||||
body { margin:0;background-color:black; overflow-x:hidden;} | 
				
			||||
 | 
				
			||||
.stashr-button_container {position:fixed;bottom:0;right:0;opacity:.5;z-index:999;} | 
				
			||||
@ -1,72 +1,51 @@ | 
				
			||||
/* START NEW STASHR CLASSES */ | 
				
			||||
 | 
				
			||||
body { background:#444444; } | 
				
			||||
body { display: flex; flex-wrap: nowrap; height: 100vh; height: -webkit-fill-available; overflow-x: auto; overflow-y: hidden; background-color:#2c2d35 !important; } | 
				
			||||
ul { list-style-type: none; } | 
				
			||||
.center { text-align:center; } | 
				
			||||
.login { align-items: center !important; }  | 
				
			||||
 | 
				
			||||
@media screen and (max-width: 800px) { | 
				
			||||
    .stashr-cover_size {max-width:100px;min-width:20px;min-height:150px;} | 
				
			||||
@media screen and (max-width: 768px) { | 
				
			||||
    .stashr-menu { margin-left:-280px; } | 
				
			||||
    .stashr-item_container {max-width:100px;min-width:20px;min-height:150px;} | 
				
			||||
} | 
				
			||||
@media screen and (min-width: 800px) { | 
				
			||||
    .stashr-cover_size {max-width:160px;min-width:100px;min-height:150px;} | 
				
			||||
@media screen and (min-width: 768px) { | 
				
			||||
    .stashr-menu { margin-left:0px; } | 
				
			||||
    .stashr-item_container {max-width:160px;min-width:100px;min-height:150px;} | 
				
			||||
} | 
				
			||||
 | 
				
			||||
#app {margin:0;padding:0;} | 
				
			||||
 | 
				
			||||
body .stashrRead { margin:0;background-color:black; } | 
				
			||||
 | 
				
			||||
.stashr-project_title { font-family: 'Grand Hotel', cursive;font-size:xx-large;line-height:40px;vertical-align: middle; } | 
				
			||||
.stashr-series_title { font-family: 'Oswald', sans-serif;font-weight:bold; } | 
				
			||||
 | 
				
			||||
.stashr-series_info {min-width:30%;max-width:60%;} | 
				
			||||
 | 
				
			||||
.stashr-poster_wrapper {position:relative;background-color:pink;z-index:5;} | 
				
			||||
.stashr-badge_tl {position:absolute;top:-5;left:-5;z-index:4;} | 
				
			||||
.stashr-badge_tr {position:absolute;top:-5;right:-5;z-index:4;} | 
				
			||||
.stashr-badge_bl {position:absolute;bottom:-5;left:-5;z-index:4;} | 
				
			||||
.stashr-badge_br {position:absolute;bottom:-5;right:-5;z-index:4;} | 
				
			||||
.stashr-poster_container {position:relative;overflow:hidden;} | 
				
			||||
.stashr-overlay_top {position:absolute;top:0;background-color:rgba(220,220,220,.9);z-index:5;} | 
				
			||||
.stashr-overlay_bottom {position:absolute;bottom:0;background-color:rgba(220,220,220,.9);z-index:5;} | 
				
			||||
.stashr-poster_background {z-index:0;} | 
				
			||||
.stashr-poster_link {position:absolute;top:0;left:0;width:100%;height:100%;} | 
				
			||||
.stashr-poster_image {margin: 0 auto;display: block;vertical-align: middle;} | 
				
			||||
 | 
				
			||||
.stashr-test_display {position:relative;display:inline-block;vertical-align:middle;} | 
				
			||||
.stashr-test-image {margin:0 auto;display:block;vertical-align:middle;width:100%;} | 
				
			||||
 | 
				
			||||
.swiper-container { width:100%;height:100%;padding:0px;margin:0px; } | 
				
			||||
.swiper-wrapper { padding:0px;margin:0px; } | 
				
			||||
.swiper-slide { width:100%;height:100%;background: black; } | 
				
			||||
.swiper-slide img { height:100%; } | 
				
			||||
 | 
				
			||||
.bg-mine { background: #3e3e44; } | 
				
			||||
 | 
				
			||||
.stashr-menu { transition: 0.5s; } | 
				
			||||
.stashr-submenu { transition: 0.5s; z-index:-5; margin-top:-100% !important; } | 
				
			||||
.stashr-footer { position:fixed; bottom:0; z-index:6; } | 
				
			||||
.stashr-item_container { overflow: hidden; } | 
				
			||||
.stashr-poster_container { position:relative; overflow: hidden; } | 
				
			||||
.stashr-poster_info { position:absolute; top:0; left:0; z-index:3; border-bottom-right-radius: 25%; } | 
				
			||||
.stashr-badge_top_left { position:absolute; top:0; left:0; z-index:3; border-bottom-right-radius: 25%; } | 
				
			||||
.stashr-badge_bottom_left { position:absolute; bottom:0; left:0; z-index:3; border-top-right-radius: 25%; } | 
				
			||||
.stashr-badge_top_right { position:absolute; top:0; right:0; z-index:3; border-bottom-left-radius: 25%; } | 
				
			||||
.stashr-badge_bottom_right { position:absolute; bottom:0; right:0; z-index:3; border-top-left-radius: 25%; } | 
				
			||||
.stashr-poster_tag { position: absolute; height:0; right:0; width:25%; padding-bottom:25%; transform: rotate(45deg); z-index:3; margin-top:-12.5%; margin-right:-12.5%; } | 
				
			||||
.stashr-poster { position:absolute; top:0; left:0; } | 
				
			||||
.stashr-overlay_top { position:absolute; top:0; background-color:rgba(220,220,220,.9); z-index:4; } | 
				
			||||
.stashr-overlay_bottom { position:absolute; bottom:0; background-color:rgba(220,220,220,.9); z-index:4; } | 
				
			||||
.stashr-progress_wrapper { position:absolute; bottom:0; z-index:3; } | 
				
			||||
.stashr-poster_wrapper { position:relative; overflow:hidden; } | 
				
			||||
.stashr-link { text-decoration: none; } | 
				
			||||
.stashr-button_container {position:fixed;bottom:10;right:10;opacity:.7;z-index:999;} | 
				
			||||
.stashr-button_container_reader {position:fixed;bottom:0;right:0;opacity:.7;z-index:999;} | 
				
			||||
.stashr-button { display:table-cell;vertical-align:middle;width:60px;height:60px; } | 
				
			||||
 | 
				
			||||
.stashr-check_box {position:absolute;top:0;right:0;z-index:5;} | 
				
			||||
 | 
				
			||||
.btn-circle.btn-sm {  | 
				
			||||
    width: 30px;  | 
				
			||||
    height: 30px;  | 
				
			||||
    padding: 6px 0px;  | 
				
			||||
    border-radius: 15px;  | 
				
			||||
    font-size: 8px;  | 
				
			||||
    text-align: center;  | 
				
			||||
}  | 
				
			||||
.btn-circle.btn-md {  | 
				
			||||
    width: 50px;  | 
				
			||||
    height: 50px;  | 
				
			||||
    padding: 7px 10px;  | 
				
			||||
    border-radius: 25px;  | 
				
			||||
    font-size: 10px;  | 
				
			||||
    text-align: center;  | 
				
			||||
}  | 
				
			||||
.btn-circle.btn-xl {  | 
				
			||||
    width: 70px;  | 
				
			||||
    height: 70px;  | 
				
			||||
    padding: 10px 16px;  | 
				
			||||
    border-radius: 35px;  | 
				
			||||
    font-size: 12px;  | 
				
			||||
    text-align: center;  | 
				
			||||
}  | 
				
			||||
.stashr-menu_button {position:absolute;bottom:0;border-top-right-radius:25%;border-bottom-right-radius:25%;z-index:999;} | 
				
			||||
.stashr-reader { background:black; } | 
				
			||||
.new-stashr-button_container { opacity:.7; } | 
				
			||||
 | 
				
			||||
.btn-circle.btn-sm { width: 30px; height: 30px; padding: 6px 0px; border-radius: 15px; font-size: 8px; text-align: center; margin:2px; }  | 
				
			||||
.btn-circle.btn-md { width: 50px; height: 50px; padding: 7px 10px; border-radius: 25px; font-size: 10px; text-align: center; margin:2px; }  | 
				
			||||
.btn-circle.btn-xl { width: 70px; height: 70px; padding: 10px 16px; border-radius: 35px; font-size: 12px; text-align: center; margin:2px; }  | 
				
			||||
 | 
				
			||||
.stashr-signin { width: 100%; max-width: 330px; padding: 15px; margin: auto; }   | 
				
			||||
.stashr-signin .checkbox { font-weight: 400; }   | 
				
			||||
.stashr-signin .form-floating:focus-within { z-index: 2; }   | 
				
			||||
.stashr-signin input[type="username"] { margin-bottom: -1px; border-bottom-right-radius: 0; border-bottom-left-radius: 0; } | 
				
			||||
.stashr-signin input[type="password"] { margin-bottom: 10px; border-top-left-radius: 0; border-top-right-radius: 0; }   | 
				
			||||
.stashr-logo { position:relative; top:-85px; width:170px; height:170px; border-radius: 50%; border: 10px solid #2c2d35; margin-bottom:-70px; } | 
				
			||||
 | 
				
			||||
.stashr-firstrun { width: 100%; max-width: 330px; padding: 15px; margin: auto; }   | 
				
			||||
.stashr-firstrun .form-floating:focus-within { z-index: 2; } | 
				
			||||
.stashr-firstrun input { margin-bottom: 5px; } | 
				
			||||
									
										
											File diff suppressed because it is too large
											Load Diff
										
									
								
							
						
									
										
											File diff suppressed because it is too large
											Load Diff
										
									
								
							
						
									
										
											File diff suppressed because it is too large
											Load Diff
										
									
								
							
						@ -0,0 +1,86 @@ | 
				
			||||
/* | 
				
			||||
Copyright 2015, 2019, 2020, 2021 Google LLC. All Rights Reserved. | 
				
			||||
 Licensed under the Apache License, Version 2.0 (the "License"); | 
				
			||||
 you may not use this file except in compliance with the License. | 
				
			||||
 You may obtain a copy of the License at | 
				
			||||
 http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||
 Unless required by applicable law or agreed to in writing, software | 
				
			||||
 distributed under the License is distributed on an "AS IS" BASIS, | 
				
			||||
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
				
			||||
 See the License for the specific language governing permissions and | 
				
			||||
 limitations under the License. | 
				
			||||
*/ | 
				
			||||
 | 
				
			||||
// Incrementing OFFLINE_VERSION will kick off the install event and force
 | 
				
			||||
// previously cached resources to be updated from the network.
 | 
				
			||||
const OFFLINE_VERSION = 2; | 
				
			||||
const CACHE_NAME = "offline"; | 
				
			||||
// Customize this with a different URL if needed.
 | 
				
			||||
const OFFLINE_URL = "/static/offline.html"; | 
				
			||||
 | 
				
			||||
self.addEventListener("install", (event) => { | 
				
			||||
  event.waitUntil( | 
				
			||||
    (async () => { | 
				
			||||
      const cache = await caches.open(CACHE_NAME); | 
				
			||||
      // Setting {cache: 'reload'} in the new request will ensure that the
 | 
				
			||||
      // response isn't fulfilled from the HTTP cache; i.e., it will be from
 | 
				
			||||
      // the network.
 | 
				
			||||
      await cache.add(new Request(OFFLINE_URL, { cache: "reload" })); | 
				
			||||
    })() | 
				
			||||
  ); | 
				
			||||
  // Force the waiting service worker to become the active service worker.
 | 
				
			||||
  self.skipWaiting(); | 
				
			||||
}); | 
				
			||||
 | 
				
			||||
self.addEventListener("activate", (event) => { | 
				
			||||
  event.waitUntil( | 
				
			||||
    (async () => { | 
				
			||||
      // Enable navigation preload if it's supported.
 | 
				
			||||
      // See https://developers.google.com/web/updates/2017/02/navigation-preload
 | 
				
			||||
      if ("navigationPreload" in self.registration) { | 
				
			||||
        await self.registration.navigationPreload.enable(); | 
				
			||||
      } | 
				
			||||
    })() | 
				
			||||
  ); | 
				
			||||
 | 
				
			||||
  // Tell the active service worker to take control of the page immediately.
 | 
				
			||||
  self.clients.claim(); | 
				
			||||
}); | 
				
			||||
 | 
				
			||||
self.addEventListener("fetch", (event) => { | 
				
			||||
  // We only want to call event.respondWith() if this is a navigation request
 | 
				
			||||
  // for an HTML page.
 | 
				
			||||
  if (event.request.mode === "navigate") { | 
				
			||||
    event.respondWith( | 
				
			||||
      (async () => { | 
				
			||||
        try { | 
				
			||||
          // First, try to use the navigation preload response if it's supported.
 | 
				
			||||
          const preloadResponse = await event.preloadResponse; | 
				
			||||
          if (preloadResponse) { | 
				
			||||
            return preloadResponse; | 
				
			||||
          } | 
				
			||||
 | 
				
			||||
          // Always try the network first.
 | 
				
			||||
          const networkResponse = await fetch(event.request); | 
				
			||||
          return networkResponse; | 
				
			||||
        } catch (error) { | 
				
			||||
          // catch is only triggered if an exception is thrown, which is likely
 | 
				
			||||
          // due to a network error.
 | 
				
			||||
          // If fetch() returns a valid HTTP response with a response code in
 | 
				
			||||
          // the 4xx or 5xx range, the catch() will NOT be called.
 | 
				
			||||
          console.log("Fetch failed; returning offline page instead.", error); | 
				
			||||
 | 
				
			||||
          const cache = await caches.open(CACHE_NAME); | 
				
			||||
          const cachedResponse = await cache.match(OFFLINE_URL); | 
				
			||||
          return cachedResponse; | 
				
			||||
        } | 
				
			||||
      })() | 
				
			||||
    ); | 
				
			||||
  } | 
				
			||||
 | 
				
			||||
  // If our if() condition is false, then this fetch handler won't intercept the
 | 
				
			||||
  // request. If there are any other fetch handlers registered, they will get a
 | 
				
			||||
  // chance to call event.respondWith(). If no fetch handlers call
 | 
				
			||||
  // event.respondWith(), the request will be handled by the browser as if there
 | 
				
			||||
  // were no service worker involvement.
 | 
				
			||||
}); | 
				
			||||
@ -0,0 +1,10 @@ | 
				
			||||
<html> | 
				
			||||
<head> | 
				
			||||
<title>Stashr - OFFLINE</title> | 
				
			||||
</head> | 
				
			||||
<body> | 
				
			||||
 | 
				
			||||
Stashr is currently Offline | 
				
			||||
 | 
				
			||||
</body> | 
				
			||||
</html> | 
				
			||||
@ -1,52 +1,92 @@ | 
				
			||||
{% extends "base.html" %} | 
				
			||||
 | 
				
			||||
{% block content %} | 
				
			||||
<div class="d-flex justify-content-center flex-wrap w-80"> | 
				
			||||
    <div class='position-relative my-2'> | 
				
			||||
		<img class="border rounded-circle my-3" src="{{ url_for('static', filename='assets/stashr.svg') }}" width="200" height="200" /> | 
				
			||||
	</div> | 
				
			||||
    <div class="bg-light m-2 px-2 rounded stashr-series_info text-center text-lg-start py-3 px-5"> | 
				
			||||
        <h5 class="text-center">First Run</h5> | 
				
			||||
        <hr /> | 
				
			||||
        <form method="POST"> | 
				
			||||
             | 
				
			||||
<html> | 
				
			||||
<head> | 
				
			||||
 | 
				
			||||
<title>Stashr - {{ title }}</title> | 
				
			||||
 | 
				
			||||
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, shrink-to-fit=no"> | 
				
			||||
 | 
				
			||||
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/bootstrap.css') }}"> | 
				
			||||
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/stashr.css') }}"> | 
				
			||||
 | 
				
			||||
<link href="https://cdn.jsdelivr.net/npm/vue-toast-notification/dist/theme-sugar.css" rel="stylesheet"> | 
				
			||||
 | 
				
			||||
<link rel="manifest" href="{{ url_for('static', filename='manifest/manifest.json') }}"> | 
				
			||||
 | 
				
			||||
<link rel="apple-touch-icon" href="touch-icon-iphone.png"> | 
				
			||||
<link rel="apple-touch-icon" sizes="152x152" href="{{ url_for('static', filename='assets/stashr-152.png') }}"> | 
				
			||||
<link rel="apple-touch-icon" sizes="180x180" href="{{ url_for('static', filename='assets/stashr-180.png') }}"> | 
				
			||||
<link rel="apple-touch-icon" sizes="167x167" href="{{ url_for('static', filename='assets/stashr-167.png') }}"> | 
				
			||||
<meta name="apple-mobile-web-app-title" content="Stashr"> | 
				
			||||
<meta name="apple-mobile-web-app-capable" content="yes"> | 
				
			||||
<meta name="apple-mobile-web-app-status-bar-style" content="default"> | 
				
			||||
 | 
				
			||||
<script src="{{ url_for('static', filename='js/stashr.js') }}"></script> | 
				
			||||
<script src="{{ url_for('static', filename='js/vue.dev.js') }}"></script> | 
				
			||||
 | 
				
			||||
</head> | 
				
			||||
<body class="text-center login"> | 
				
			||||
 | 
				
			||||
<main class="stashr-firstrun"> | 
				
			||||
    <div class="card bg-primary px-3 shadow"> | 
				
			||||
        <form action="{{ url_for('first_run_page') }}" method="post" id="first_run_form"> | 
				
			||||
            {{ first_run_form.csrf_token }} | 
				
			||||
            <img class="stashr-logo" src="{{ url_for('static', filename='assets/stashr.svg') }}" w="170" h="170"> | 
				
			||||
 | 
				
			||||
            <div class="mb-3"> | 
				
			||||
                {{ first_run_form.username.label }} | 
				
			||||
            {% if first_run_form.errors %} | 
				
			||||
            <div class="notification bg-danger rounded m-3 text-white" role="alert" id='error_container'> | 
				
			||||
                {% for field_name, field_errors in first_run_form.errors|dictsort if field_errors %} | 
				
			||||
                <ul> | 
				
			||||
                    {% for error in field_errors %} | 
				
			||||
					<li>{{ error }}</li> | 
				
			||||
					{% endfor %} | 
				
			||||
                </ul> | 
				
			||||
                {% endfor %} | 
				
			||||
            </div> | 
				
			||||
            {% endif %} | 
				
			||||
            <div class="form-floating"> | 
				
			||||
                {{ first_run_form.username(class_='form-control', placeholder=first_run_form.username.label.text) }} | 
				
			||||
                {{ first_run_form.username.label }} | 
				
			||||
            </div> | 
				
			||||
            <div class="mb-3"> | 
				
			||||
                {{ first_run_form.email.label }} | 
				
			||||
            <div class="form-floating"> | 
				
			||||
                {{ first_run_form.email(class_='form-control', placeholder=first_run_form.email.label.text) }} | 
				
			||||
                {{ first_run_form.email.label }} | 
				
			||||
            </div> | 
				
			||||
            <div class="mb-3"> | 
				
			||||
                {{ first_run_form.password.label }} | 
				
			||||
            <div class="form-floating"> | 
				
			||||
                {{ first_run_form.password(type='password', class_='form-control', placeholder=first_run_form.password.label.text) }} | 
				
			||||
                {{ first_run_form.password.label }} | 
				
			||||
            </div> | 
				
			||||
            <div class="mb-3"> | 
				
			||||
                {{ first_run_form.confirm_password.label }} | 
				
			||||
            <div class="form-floating"> | 
				
			||||
                {{ first_run_form.confirm_password(type='password', class_='form-control', placeholder=first_run_form.confirm_password.label.text) }} | 
				
			||||
                {{ first_run_form.confirm_password.label }} | 
				
			||||
            </div> | 
				
			||||
            <hr /> | 
				
			||||
            <div class="mb-3"> | 
				
			||||
                {{ first_run_form.comicvine_api_key.label }} | 
				
			||||
            <div class="form-floating"> | 
				
			||||
                {{ first_run_form.comicvine_api_key(class_='form-control', placeholder=first_run_form.comicvine_api_key.label.text) }} | 
				
			||||
                {{ first_run_form.comicvine_api_key.label }} | 
				
			||||
            </div> | 
				
			||||
            <hr /> | 
				
			||||
            <div class="mb-3"> | 
				
			||||
                {{ first_run_form.open_registration }} | 
				
			||||
                {{ first_run_form.open_registration.label }} | 
				
			||||
            </div> | 
				
			||||
            <div class="mb-3"> | 
				
			||||
                {{ first_run_form.logging_level.label }} | 
				
			||||
            <div class="form-floating"> | 
				
			||||
                {{ first_run_form.logging_level(class_='form-control') }} | 
				
			||||
                {{ first_run_form.logging_level.label }} | 
				
			||||
            </div> | 
				
			||||
            <hr /> | 
				
			||||
            <div class="mb-3 text-end"> | 
				
			||||
                {{ first_run_form.first_run_button(class_='btn btn-success') }} | 
				
			||||
            </div> | 
				
			||||
             | 
				
			||||
            {{ first_run_form.first_run_button(class_='btn btn-success') }} | 
				
			||||
 | 
				
			||||
        </form> | 
				
			||||
    </div> | 
				
			||||
</div> | 
				
			||||
{% endblock %} | 
				
			||||
</main> | 
				
			||||
 | 
				
			||||
<script type="text/javascript"> | 
				
			||||
 | 
				
			||||
Vue.use(VueToast); | 
				
			||||
 | 
				
			||||
{% with flashes = get_flashed_messages(with_categories=true) %} | 
				
			||||
    {% if flashes %} | 
				
			||||
        {% for category, message in flashes %} | 
				
			||||
            stashrToast('{{ message }}', '{{ category }}'); | 
				
			||||
        {% endfor %} | 
				
			||||
    {% endif %} | 
				
			||||
{% endwith %} | 
				
			||||
</script> | 
				
			||||
 | 
				
			||||
</body> | 
				
			||||
</html> | 
				
			||||
@ -1,45 +0,0 @@ | 
				
			||||
{% extends "base.html" %} | 
				
			||||
 | 
				
			||||
{% block content %} | 
				
			||||
 | 
				
			||||
<div class="d-flex justify-content-center flex-wrap w-80"> | 
				
			||||
    <div class='position-relative my-2'> | 
				
			||||
		<img class="border rounded-circle my-3" src="{{ url_for('static', filename='assets/stashr.svg') }}" width="200" height="200" /> | 
				
			||||
	</div> | 
				
			||||
    <div class="bg-light m-2 px-2 rounded stashr-series_info text-center text-lg-start py-3 px-5"> | 
				
			||||
        <h5 class="text-center">Register</h5> | 
				
			||||
        <hr /> | 
				
			||||
        <form action="{{ url_for('register_page') }}" method="post" id="registration_form"> | 
				
			||||
            {% if registration_form.errors %} | 
				
			||||
            <div class="notification bg-danger rounded m-3 text-white" role="alert" id='error_container'> | 
				
			||||
                {% for field_name, field_errors in registration_form.errors|dictsort if field_errors %} | 
				
			||||
                <ul> | 
				
			||||
                    {% for error in field_errors %} | 
				
			||||
					<li>{{ error }}</li> | 
				
			||||
					{% endfor %} | 
				
			||||
                </ul> | 
				
			||||
                {% endfor %} | 
				
			||||
            </div> | 
				
			||||
            {% else %} | 
				
			||||
            {% endif %} | 
				
			||||
            {{ registration_form.csrf_token }} | 
				
			||||
            <div class="mb-3"> | 
				
			||||
                {{ registration_form.username(class_='input form-control', placeholder='Username') }} | 
				
			||||
            </div> | 
				
			||||
            <div class="mb-3"> | 
				
			||||
                {{ registration_form.email(class_='input form-control', placeholder='E-Mail') }} | 
				
			||||
            </div> | 
				
			||||
            <div class="mb-3"> | 
				
			||||
                {{ registration_form.reg_password(class_='input form-control', placeholder='Password', type='password') }} | 
				
			||||
            </div> | 
				
			||||
            <div class="mb-3"> | 
				
			||||
                {{ registration_form.confirm_reg_password(class_='input form-control', placeholder='Confirm Password', type='password') }} | 
				
			||||
            </div> | 
				
			||||
            <div class="mb-3"> | 
				
			||||
                {{ registration_form.register_button(class_='btn btn-outline-success') }} | 
				
			||||
            </div> | 
				
			||||
        </form> | 
				
			||||
    </div> | 
				
			||||
</div> | 
				
			||||
 | 
				
			||||
{% endblock %} | 
				
			||||
@ -1,61 +1,176 @@ | 
				
			||||
{% extends "base.html" %} | 
				
			||||
 | 
				
			||||
{% block content %} | 
				
			||||
 | 
				
			||||
 | 
				
			||||
 | 
				
			||||
<div class="row w-100 m-0"> | 
				
			||||
    <div class="col-12 col-md-10 offset-md-1 bg-light rounded p-2"> | 
				
			||||
        <div class="row"> | 
				
			||||
			{% if current_user.role == 'admin' %} | 
				
			||||
            <div class="col-12 col-md-3 col-lg-2 p-3"> | 
				
			||||
                <ul class="nav flex-column nav-pills"> | 
				
			||||
					<li class="nav-item"> | 
				
			||||
						<a class="nav-link{% if request.path == url_for('settings_app_page') %} active{% endif %}" href="{{ url_for('settings_app_page') }}"> | 
				
			||||
							<i class="fa fa-cogs"></i> | 
				
			||||
							Application | 
				
			||||
						</a> | 
				
			||||
					</li> | 
				
			||||
					<li class="nav-item"> | 
				
			||||
						<a class="nav-link{% if request.path == url_for('settings_directories_page') %} active{% endif %}" href="{{ url_for('settings_directories_page') }}"> | 
				
			||||
							<i class="fas fa-folder"></i> | 
				
			||||
							Directories | 
				
			||||
						</a> | 
				
			||||
					</li> | 
				
			||||
					<li class="nav-item"> | 
				
			||||
						<a class="nav-link{% if request.path == url_for('settings_mail_page') %} active{% endif %}" href="{{ url_for('settings_mail_page') }}"> | 
				
			||||
							<i class="fa fa-envelope"></i> | 
				
			||||
							Mail | 
				
			||||
						</a> | 
				
			||||
					</li> | 
				
			||||
					<li class="nav-item"> | 
				
			||||
						<a class="nav-link{% if request.path == url_for('settings_tasks_page') %} active{% endif %}" href="{{ url_for('settings_tasks_page') }}"> | 
				
			||||
							<i class="fa fa-tasks"></i> | 
				
			||||
							Tasks | 
				
			||||
						</a> | 
				
			||||
					</li> | 
				
			||||
					<li class="nav-item"> | 
				
			||||
						<a class="nav-link{% if request.path == url_for('settings_all_users_page') %} active{% endif %}" href="{{ url_for('settings_all_users_page') }}"> | 
				
			||||
							<i class="fa fa-users"></i> | 
				
			||||
							Users | 
				
			||||
						</a> | 
				
			||||
					</li> | 
				
			||||
					<li class="nav-item"> | 
				
			||||
						<a class="nav-link{% if request.path == url_for('settings_plugins_page') %} active{% endif %}" href="{{ url_for('settings_plugins_page') }}"> | 
				
			||||
							<i class="fa fa-plug"></i> | 
				
			||||
							Plugins | 
				
			||||
						</a> | 
				
			||||
					</li> | 
				
			||||
					{{ emit_tep('settings_menu') }} | 
				
			||||
				</ul> | 
				
			||||
            </div> | 
				
			||||
			{% endif %} | 
				
			||||
            <div class="col-12{% if current_user.role=='admin' %} col-md-9 col-lg-10{% endif %} my-2"> | 
				
			||||
                {% block settings_pane %}{% endblock %} | 
				
			||||
<html> | 
				
			||||
<head> | 
				
			||||
 | 
				
			||||
<meta charset="utf-8"> | 
				
			||||
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, shrink-to-fit=no"> | 
				
			||||
 | 
				
			||||
<title>Stashr - {{ title }}</title> | 
				
			||||
 | 
				
			||||
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/bootstrap.css') }}"> | 
				
			||||
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/new_base.css') }}"> | 
				
			||||
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/stashr.css') }}?v=0.1.0"> | 
				
			||||
 | 
				
			||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/all.css') }}"> | 
				
			||||
 | 
				
			||||
<link href="https://fonts.googleapis.com/css?family=Grand+Hotel" rel="stylesheet"> | 
				
			||||
<link href="https://fonts.googleapis.com/css?family=Oswald" rel="stylesheet"> | 
				
			||||
 | 
				
			||||
<link rel="manifest" href="{{ url_for('static', filename='manifest/manifest.json') }}"> | 
				
			||||
 | 
				
			||||
<link rel="apple-touch-icon" href="touch-icon-iphone.png"> | 
				
			||||
<link rel="apple-touch-icon" sizes="152x152" href="{{ url_for('static', filename='assets/stashr-152.png') }}"> | 
				
			||||
<link rel="apple-touch-icon" sizes="180x180" href="{{ url_for('static', filename='assets/stashr-180.png') }}"> | 
				
			||||
<link rel="apple-touch-icon" sizes="167x167" href="{{ url_for('static', filename='assets/stashr-167.png') }}"> | 
				
			||||
<meta name="apple-mobile-web-app-title" content="Stashr"> | 
				
			||||
<meta name="apple-mobile-web-app-capable" content="yes"> | 
				
			||||
<meta name="apple-mobile-web-app-status-bar-style" content="default"> | 
				
			||||
 | 
				
			||||
<script src="{{ url_for('static', filename='js/stashr.js') }}"></script> | 
				
			||||
<script src="{{ url_for('static', filename='js/vue.dev.js') }}"></script> | 
				
			||||
 | 
				
			||||
<script src="https://cdn.jsdelivr.net/npm/vue-toast-notification@0.6"></script> | 
				
			||||
<link href="https://cdn.jsdelivr.net/npm/vue-toast-notification/@0.6/dist/theme-sugar.css" rel="stylesheet"> | 
				
			||||
 | 
				
			||||
<!-- | 
				
			||||
<script src="https://cdn.jsdelivr.net/npm/vue-toast-notification"></script> | 
				
			||||
<link href="https://cdn.jsdelivr.net/npm/vue-toast-notification/dist/theme-sugar.css" rel="stylesheet">     | 
				
			||||
--> | 
				
			||||
 | 
				
			||||
{% block header_script_files %}{% endblock %} | 
				
			||||
{{ emit_tep('base_page_header_script_files') }} | 
				
			||||
 | 
				
			||||
</head> | 
				
			||||
<body> | 
				
			||||
 | 
				
			||||
<div class="container-fluid d-flex min-vh-100 m-0 p-0"> | 
				
			||||
    <div class="stashr-menu d-flex flex-column p-3 text-white bg-dark text-center min-vh-100 sticky-top overflow-auto" id="sideMenu" style="width:280px;"> | 
				
			||||
        <div class="d-flex flex-row"> | 
				
			||||
            <a class="navbar-brand" href="{{ url_for('index_page') }}"> | 
				
			||||
                <img class="border rounded-circle" src="{{ url_for('static', filename='assets/stashr.svg') }}" width="40" height="40" /> | 
				
			||||
                <img src="{{ url_for('static', filename='assets/title.svg') }}" height="25" /> | 
				
			||||
            </a>          | 
				
			||||
        </div> | 
				
			||||
        <hr/> | 
				
			||||
        <ul class="nav nav-pills flex-column mb-auto text-start"> | 
				
			||||
            {% if current_user.role == 'admin' %} | 
				
			||||
			<li> | 
				
			||||
				<a class="nav-link text-white{% if request.path == url_for('settings_app_page') %} active{% endif %}" href="{{ url_for('settings_app_page') }}"> | 
				
			||||
					<i class="fa fa-cogs"></i> | 
				
			||||
					Application | 
				
			||||
				</a> | 
				
			||||
			</li> | 
				
			||||
			<li> | 
				
			||||
				<a class="nav-link text-white{% if request.path == url_for('settings_directories_page') %} active{% endif %}" href="{{ url_for('settings_directories_page') }}"> | 
				
			||||
					<i class="fas fa-folder"></i> | 
				
			||||
					Directories | 
				
			||||
				</a> | 
				
			||||
			</li> | 
				
			||||
			<li class="nav-item"> | 
				
			||||
				<a class="nav-link text-white{% if request.path == url_for('settings_mail_page') %} active{% endif %}" href="{{ url_for('settings_mail_page') }}"> | 
				
			||||
					<i class="fa fa-envelope"></i> | 
				
			||||
					Mail | 
				
			||||
				</a> | 
				
			||||
			</li> | 
				
			||||
			<li class="nav-item"> | 
				
			||||
				<a class="nav-link text-white{% if request.path == url_for('settings_tasks_page') %} active{% endif %}" href="{{ url_for('settings_tasks_page') }}"> | 
				
			||||
					<i class="fa fa-tasks"></i> | 
				
			||||
					Tasks | 
				
			||||
				</a> | 
				
			||||
			</li> | 
				
			||||
			<li class="nav-item"> | 
				
			||||
				<a class="nav-link text-white{% if request.path == url_for('settings_all_users_page') %} active{% endif %}" href="{{ url_for('settings_all_users_page') }}"> | 
				
			||||
					<i class="fa fa-users"></i> | 
				
			||||
					Users | 
				
			||||
				</a> | 
				
			||||
			</li> | 
				
			||||
			<li class="nav-item"> | 
				
			||||
				<a class="nav-link text-white{% if request.path == url_for('settings_plugins_page') %} active{% endif %}" href="{{ url_for('settings_plugins_page') }}"> | 
				
			||||
					<i class="fa fa-plug"></i> | 
				
			||||
					Plugins | 
				
			||||
				</a> | 
				
			||||
			</li> | 
				
			||||
			{{ emit_tep('settings_menu') }} | 
				
			||||
            {% endif %} | 
				
			||||
        </ul> | 
				
			||||
        <hr /> | 
				
			||||
        <ul class="nav nav-pills d-flex flex-column text-start"> | 
				
			||||
            <li> | 
				
			||||
                <a href="{{ url_for('settings_single_user_page', user_id=current_user.id) }}" class="nav-link text-white"> | 
				
			||||
                    <i class="fa fa-user"></i> | 
				
			||||
                    {{ current_user.username }} | 
				
			||||
                </a> | 
				
			||||
            </li> | 
				
			||||
            {% if current_user.role == 'admin' %} | 
				
			||||
            <li> | 
				
			||||
                <a href="{{ url_for('settings_page') }}" class="nav-link text-white"> | 
				
			||||
                    <i class="fas fa-cogs"></i> | 
				
			||||
                    Settings | 
				
			||||
                </a> | 
				
			||||
            </li> | 
				
			||||
            {% endif %} | 
				
			||||
            <li> | 
				
			||||
                <a href="{{ url_for('logout_page') }}" class="nav-link text-white"> | 
				
			||||
                    <i class="fas fa-sign-out-alt"></i> | 
				
			||||
                    Logout | 
				
			||||
                </a> | 
				
			||||
            </li> | 
				
			||||
        </ul> | 
				
			||||
    </div> | 
				
			||||
    <div class="d-flex flex-column w-100 m-0 px-0 min-vh-100 overflow-auto bg-light"> | 
				
			||||
 | 
				
			||||
        <!-- v HEADER v --> | 
				
			||||
        <!-- ^ HEADER ^ --> | 
				
			||||
 | 
				
			||||
        <!-- v CONTENT v --> | 
				
			||||
        {% block settings_pane %}{% endblock %} | 
				
			||||
        <!-- ^ CONTENT ^ --> | 
				
			||||
 | 
				
			||||
        <!-- v BUTTON CONTAINER v --> | 
				
			||||
        <div> | 
				
			||||
            <div class="d-grid m-0 p-0 stashr-menu_button bg-dark"> | 
				
			||||
                <div class="row d-flex flex-nowrap m-0 p-0 py-2"> | 
				
			||||
                    <i class="text-white fas fa-ellipsis-v fa-2x" onclick="toggleMenu()"></i> | 
				
			||||
                </div> | 
				
			||||
            </div> | 
				
			||||
        </div> | 
				
			||||
        <!-- ^ BUTTON CONTAINER ^ --> | 
				
			||||
    </div> | 
				
			||||
</div> | 
				
			||||
 | 
				
			||||
<!-- v MODALS v --> | 
				
			||||
{% block modals %}{% endblock %} | 
				
			||||
{{ emit_tep('base_page_modals') }} | 
				
			||||
<!-- ^ MODALS ^ --> | 
				
			||||
 | 
				
			||||
<!-- v FOOTER SCRIPT INCLUDES v --> | 
				
			||||
<script src="{{ url_for('static', filename='js/bootstrap.bundle.js') }}"></script> | 
				
			||||
{% block footer_script_files %}{% endblock %} | 
				
			||||
{{ emit_tep('base_page_footer_script_files') }} | 
				
			||||
<!-- ^ FOOTER SCRIPT INCLUDES ^ --> | 
				
			||||
 | 
				
			||||
<!-- v FOOTER SCRIPT v --> | 
				
			||||
<script type="text/javascript"> | 
				
			||||
 | 
				
			||||
Vue.use(VueToast); | 
				
			||||
 | 
				
			||||
// Flashes | 
				
			||||
{% with flashes = get_flashed_messages(with_categories=true) %} | 
				
			||||
    {% if flashes %} | 
				
			||||
        {% for category, message in flashes %} | 
				
			||||
            stashrToast('{{ message }}', '{{ category }}'); | 
				
			||||
        {% endfor %} | 
				
			||||
    {% endif %} | 
				
			||||
{% endwith %} | 
				
			||||
 | 
				
			||||
window.addEventListener("load", () => { | 
				
			||||
    if ("serviceWorker" in navigator) { | 
				
			||||
    navigator.serviceWorker.register("service-worker.js"); | 
				
			||||
    } | 
				
			||||
}); | 
				
			||||
 | 
				
			||||
{% block script %}{% endblock %} | 
				
			||||
</script> | 
				
			||||
<!-- ^ FOOTER SCRIPT ^ --> | 
				
			||||
 | 
				
			||||
{% endblock %} | 
				
			||||
</body> | 
				
			||||
</html> | 
				
			||||
@ -1,39 +1,58 @@ | 
				
			||||
{% extends "settings_page.html" %} | 
				
			||||
 | 
				
			||||
{% block header_script_files %} | 
				
			||||
<script src="https://unpkg.com/axios/dist/axios.min.js"></script> | 
				
			||||
{% endblock %} | 
				
			||||
 | 
				
			||||
{% block settings_pane %} | 
				
			||||
<div class="row r-10 m-2"> | 
				
			||||
    <div class="col col-12"> | 
				
			||||
        <div class="row"> | 
				
			||||
            <div class="col-sm-12 col-md-6 text-center text-md-start"> | 
				
			||||
                <h2>Tasks</h2> | 
				
			||||
            </div> | 
				
			||||
<div class="d-grid w-100 bg-mine m-0 p-0 sticky-top shadow"> | 
				
			||||
    <div class="row w-100 m-0 p-3"> | 
				
			||||
        <div class="col-sm-12 col-md-6 text-center text-md-start text-white "> | 
				
			||||
            <h2>Tasks</h2> | 
				
			||||
        </div> | 
				
			||||
        <hr /> | 
				
			||||
        <div class="row"> | 
				
			||||
            <table class="table table-striped"> | 
				
			||||
                <thead> | 
				
			||||
                    <tr> | 
				
			||||
                        <th scope="col">TASK</th> | 
				
			||||
                        <th scope="col"></th> | 
				
			||||
                    </tr> | 
				
			||||
                </thead> | 
				
			||||
                <tbody> | 
				
			||||
                    <tr> | 
				
			||||
                        <th scope="row">Update New Releases</th><td><i class="fas fa-play"></i></td> | 
				
			||||
                    </tr> | 
				
			||||
                    <tr> | 
				
			||||
                        <th scope="row">Update New Release Subscriptions</th><td><i class="fas fa-play"></i></td> | 
				
			||||
                    </tr> | 
				
			||||
                    <tr> | 
				
			||||
                        <th scope="row">Clean Database</th><td><i class="fas fa-play"></i></td> | 
				
			||||
                    </tr> | 
				
			||||
                    <tr> | 
				
			||||
                        <th scope="row">Restart Server</th><td><i class="fas fa-play"></i></td> | 
				
			||||
                    </tr> | 
				
			||||
                    {{ emit_tep('settings_page_tasks_task') }} | 
				
			||||
                </tbody> | 
				
			||||
            </table> | 
				
			||||
        <div class="col-sm-12 col-md-6 text-center text-md-end"> | 
				
			||||
            <button type="button" class="btn btn-info" data-bs-toggle="modal" data-bs-target="#settingsModal">Modify Settings</button> | 
				
			||||
        </div> | 
				
			||||
    </div> | 
				
			||||
</div> | 
				
			||||
<div class="d-grid w-100 m-0 p-0"> | 
				
			||||
    <div class="row w-100 m-0 p-3"> | 
				
			||||
        <table class="table table-striped"> | 
				
			||||
            <thead> | 
				
			||||
                <tr> | 
				
			||||
                    <th scope="col">TASK</th> | 
				
			||||
                    <th scope="col"></th> | 
				
			||||
                </tr> | 
				
			||||
            </thead> | 
				
			||||
            <tbody> | 
				
			||||
                <tr> | 
				
			||||
                    <th scope="row">Update New Releases</th><td><i class="fas fa-play"></i></td> | 
				
			||||
                </tr> | 
				
			||||
                <tr> | 
				
			||||
                    <th scope="row">Update New Release Subscriptions</th><td><i class="fas fa-play"></i></td> | 
				
			||||
                </tr> | 
				
			||||
                <tr> | 
				
			||||
                    <th scope="row">Clean Database</th><td><i class="fas fa-play"></i></td> | 
				
			||||
                </tr> | 
				
			||||
                <tr> | 
				
			||||
                    <th scope="row">Restart Server</th><td><a onclick="restartServer()"><i class="fas fa-play"></i></a></td> | 
				
			||||
                </tr> | 
				
			||||
                {{ emit_tep('settings_page_tasks_task') }} | 
				
			||||
            </tbody> | 
				
			||||
        </table> | 
				
			||||
    </div> | 
				
			||||
</div> | 
				
			||||
{% endblock %} | 
				
			||||
 | 
				
			||||
{% block script %} | 
				
			||||
 | 
				
			||||
function restartServer() { | 
				
			||||
    axios.post('{{ url_for('api.restart_server') }}') | 
				
			||||
        .then(res=>{ | 
				
			||||
            console.log(res) | 
				
			||||
            stashrToast('Restarting Server', 'info') | 
				
			||||
        }) | 
				
			||||
        .catch() | 
				
			||||
} | 
				
			||||
 | 
				
			||||
{% endblock %} | 
				
			||||
					Loading…
					
					
				
		Reference in new issue