Skip to content

Commit

Permalink
Vueify footer (#4520)
Browse files Browse the repository at this point in the history
* Convert footer into a Vue SFC

* Add render test

* [bundle]

* Remove unused stuff from `server.web.core.base`

* Updates
  • Loading branch information
sharkykh authored and medariox committed Jun 16, 2019
1 parent d3c4608 commit a551865
Show file tree
Hide file tree
Showing 24 changed files with 597 additions and 213 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#### New Features

#### Improvements
- Converted the footer to a Vue component ([#4520](https://github.com/pymedusa/Medusa/pull/4520))

#### Fixes

Expand Down
20 changes: 5 additions & 15 deletions medusa/server/web/core/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@
import os
import re
import sys
import time
import traceback
from builtins import str
from concurrent.futures import ThreadPoolExecutor

from mako.exceptions import RichTraceback
Expand All @@ -28,6 +26,7 @@

from six import (
iteritems,
text_type,
viewitems,
)

Expand Down Expand Up @@ -75,8 +74,8 @@ def __init__(self, rh, filename):
lookup = get_lookup()
self.template = lookup.get_template(filename)

base_url = (rh.request.headers.get('X-Forwarded-Proto', rh.request.protocol) + '://' +
rh.request.headers.get('X-Forwarded-Host', rh.request.host))
base_url = (rh.request.headers.get('X-Forwarded-Proto', rh.request.protocol) + '://'
+ rh.request.headers.get('X-Forwarded-Host', rh.request.host))

self.arguments = {
'sbHttpPort': app.WEB_PORT,
Expand All @@ -85,8 +84,7 @@ def __init__(self, rh, filename):
'sbHandleReverseProxy': app.HANDLE_REVERSE_PROXY,
'sbDefaultPage': app.DEFAULT_PAGE,
'loggedIn': rh.get_current_user(),
'sbStartTime': rh.startTime,
'sbPID': str(app.PID),
'sbPID': text_type(app.PID),
'title': 'FixME',
'header': 'FixME',
'controller': 'FixME',
Expand Down Expand Up @@ -114,7 +112,6 @@ def render(self, *args, **kwargs):
if key not in kwargs:
kwargs[key] = self.arguments[key]

kwargs['makoStartTime'] = time.time()
try:
return self.template.render_unicode(*args, **kwargs)
except Exception:
Expand All @@ -130,15 +127,8 @@ def render(self, *args, **kwargs):
class BaseHandler(RequestHandler):
"""Base Handler for the server."""

startTime = 0.

def __init__(self, *args, **kwargs):
self.startTime = time.time()

super(BaseHandler, self).__init__(*args, **kwargs)

def write_error(self, status_code, **kwargs):
"""Base error Handler for 404's."""
"""Error handler for 404's."""
# handle 404 http errors
if status_code == 404:
url = self.request.uri
Expand Down
7 changes: 5 additions & 2 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ multiline-quotes = double
docstring-quotes = double
; flake8
max-line-length = 160
; If per-file ignores are needed, use: https://github.com/snoack/flake8-per-file-ignores
per-file-ignores =
; http://flake8.pycqa.org/en/latest/user/options.html#cmdoption-flake8-per-file-ignores
; [Example]
; medusa/server/web/core/base.py:D100,D101,D102,D103,D107
ignore =
; Error codes reference: https://git.io/fNlTP
; Q002: Handled by flake8-docstrings
Expand Down Expand Up @@ -131,7 +134,7 @@ flake8-ignore =
medusa/server/web/config/subtitles.py D102 D200 D204 D400 E501 N802
medusa/server/web/core/__init__.py D104 F401
medusa/server/web/core/authentication.py D102 D200 D202 D204 D205 D400
medusa/server/web/core/base.py D100 D101 D102 D103 D200 D204 D210 D400 D401 N802 N815
medusa/server/web/core/base.py D100 D101 D102 D103 N802
medusa/server/web/core/calendar.py D200 D204 D205 D400 D401
medusa/server/web/core/file_browser.py D100 D101 D102 N803
medusa/server/web/core/history.py D100 D101 D102 N802
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ def packages():
},
cmdclass={'test': PyTest},
tests_require=tests_runtime_require + [
'flake8>=3.5.0',
'flake8>=3.7.7',
'flake8-docstrings>=1.3.0',
'flake8-import-order>=0.18',
'flake8-quotes>=1.0.0',
Expand Down
1 change: 1 addition & 0 deletions themes-default/slim/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@
"optimize-css-assets-webpack-plugin": "5.0.1",
"stylelint": "10.1.0",
"stylelint-config-standard": "18.3.0",
"timekeeper": "2.2.0",
"vue-jest": "3.0.4",
"vue-loader": "15.7.0",
"webpack": "4.34.0",
Expand Down
3 changes: 2 additions & 1 deletion themes-default/slim/src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ const app = new Vue({
const { $store } = this;
Promise.all([
$store.dispatch('login', { username: window.username }),
$store.dispatch('getConfig')
$store.dispatch('getConfig'),
$store.dispatch('getStats')
]).then(([_, config]) => {
if (isDevelopment) {
console.log('App Loaded!');
Expand Down
113 changes: 113 additions & 0 deletions themes-default/slim/src/components/app-footer.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
<template>
<footer>
<div class="footer clearfix">
<span class="footerhighlight">{{ stats.overall.shows.total }}</span> Shows (<span class="footerhighlight">{{ stats.overall.shows.active }}</span> Active)
| <span class="footerhighlight">{{ stats.overall.episodes.downloaded }}</span>
<template v-if="stats.overall.episodes.snatched">
<span class="footerhighlight"><app-link :href="`manage/episodeStatuses?whichStatus=${snatchedStatus}`" title="View overview of snatched episodes">+{{ stats.overall.episodes.snatched }}</app-link></span>
Snatched
</template>
/ <span class="footerhighlight">{{ stats.overall.episodes.total }}</span> Episodes Downloaded <span v-if="episodePercentage" class="footerhighlight">({{ episodePercentage }})</span>
| Daily Search: <span class="footerhighlight">{{ schedulerNextRun('dailySearch') }}</span>
| Backlog Search: <span class="footerhighlight">{{ schedulerNextRun('backlog') }}</span>
<div>
<template v-if="system.memoryUsage">
Memory used: <span class="footerhighlight">{{ system.memoryUsage }}</span> |
</template>
<!-- Load time: <span class="footerhighlight">{{ loadTime }}s</span> / Mako: <span class="footerhighlight">{{ makoTime }}s</span> | -->
Branch: <span class="footerhighlight">{{ config.branch || 'Unknown' }}</span> |
Now: <span class="footerhighlight">{{ nowInUserPreset }}</span>
</div>
</div>
</footer>
</template>

<script>
import { mapGetters, mapState } from 'vuex';
import formatDate from 'date-fns/format';
import { convertDateFormat } from '../utils/core';
import { AppLink } from './helpers';
export default {
name: 'app-footer',
components: {
AppLink
},
computed: {
...mapState([
'config',
'stats',
'system'
]),
...mapGetters([
'getStatus',
'getScheduler'
]),
snatchedStatus() {
const status = this.getStatus({ key: 'snatched' });
return status ? status.value : '';
},
episodePercentage() {
const { downloaded, total } = this.stats.overall.episodes;
if (!total) {
return '';
}
const raw = (downloaded / total) * 100;
return raw.toFixed(1) + '%';
},
nowInUserPreset() {
const { datePreset, timePreset } = this.config;
const preset = convertDateFormat(`${datePreset} ${timePreset}`);
return formatDate(new Date(), preset);
}
},
methods: {
/**
* Return a formatted next run time of the scheduler matching the provided key.
*
* @param {string} scheduler A scheduler key.
* @returns {string} The formatted next run time.
*/
schedulerNextRun(scheduler) {
/** @type {import('../store/modules/system').Scheduler} */
const { nextRun } = this.getScheduler(scheduler);
// The next run can be `undefined` when the scheduler was not initialized
// on the backend, and `null` when the scheduler is not enabled.
if (nextRun === undefined) {
return '??:??:??';
}
if (nextRun === null) {
return 'Disabled';
}
return this.formatTimeDuration(nextRun);
},
/**
* Return a formatted string representing the provided duration.
*
* This function will not use any units greater than a day.
* @param {number} durationInMs Duration of time in milliseconds.
* @returns {string} The formatted duration.
*
* @example
*/
formatTimeDuration(durationInMs) {
const days = parseInt(durationInMs / 86400000, 10);
let daysText = '';
if (days > 0) {
daysText = String(days) + (days > 1 ? ' days, ' : ' day, ');
}
const date = new Date(durationInMs % 86400000);
const zeroPad = (num, len = 2) => String(num).padStart(len, '0');
const hours = String(date.getUTCHours());
const minutes = zeroPad(date.getUTCMinutes());
const seconds = zeroPad(date.getUTCSeconds() + Math.round(date.getUTCMilliseconds() / 1000));
return daysText + [hours, minutes, seconds].join(':');
}
}
};
</script>

<style scoped>
</style>
1 change: 1 addition & 0 deletions themes-default/slim/src/components/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export { default as AddRecommended } from './add-recommended.vue';
export { default as AddShowOptions } from './add-show-options.vue';
export { default as AddShows } from './add-shows.vue';
export { default as AnidbReleaseGroupUi } from './anidb-release-group-ui.vue';
export { default as AppFooter } from './app-footer.vue';
export { default as AppHeader } from './app-header.vue';
export { default as Backstretch } from './backstretch.vue';
export { default as Config } from './config.vue';
Expand Down
5 changes: 4 additions & 1 deletion themes-default/slim/src/global-vue-shim.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import Snotify from 'vue-snotify';
import {
AddShowOptions,
AnidbReleaseGroupUi,
AppFooter,
AppHeader,
AppLink,
Asset,
Expand Down Expand Up @@ -46,6 +47,7 @@ export const registerGlobalComponents = () => {
// @TODO: These should be registered in an `App.vue` component when possible,
// along with some of the `main.mako` template
components = components.concat([
AppFooter,
AppHeader,
ScrollButtons,
SubMenu
Expand Down Expand Up @@ -119,7 +121,8 @@ export default () => {
/* This is used by the `app-header` component
to only show the logout button if a username is set */
store.dispatch('login', { username }),
store.dispatch('getConfig')
store.dispatch('getConfig'),
store.dispatch('getStats')
]).then(([_, config]) => {
this.$emit('loaded');
// Legacy - send config.main to jQuery (received by index.js)
Expand Down
40 changes: 37 additions & 3 deletions themes-default/slim/src/store/modules/system.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,33 @@
import { ADD_CONFIG } from '../mutation-types';

/**
* An object representing a scheduler.
*
* If a scheduler isn't initialized on the backend,
* this object will only have the `key` and `name` properties.
* @typedef {object} Scheduler
* @property {string} key
* A camelCase key representing this scheduler.
* @property {string} name
* The scheduler's name.
* @property {boolean} [isAlive]
* Is the scheduler alive?
* @property {boolean|string} [isEnabled]
* Is the scheduler enabled? For the `backlog` scheduler, the value might be `Paused`.
* @property {boolean} [isActive]
* Is the scheduler's action currently running?
* @property {string|null} [startTime]
* The time of day in which this scheduler runs (format: ISO-8601 time), or `null` if not applicable.
* @property {number} [cycleTime]
* The duration in milliseconds between each run, or `null` if not applicable.
* @property {number} [nextRun]
* The duration in milliseconds until the next run.
* @property {string} [lastRun]
* The date and time of the previous run (format: ISO-8601 date-time).
* @property {boolean} [isSilent]
* Is the scheduler silent?
*/

const state = {
memoryUsage: null,
schedulers: [],
Expand All @@ -15,9 +43,15 @@ const mutations = {
};

const getters = {
// Get a scheduler object using a key
getScheduler: state => key => {
return state.schedulers.find(scheduler => key === scheduler.key);
getScheduler: state => {
/**
* Get a scheduler object using a key.
*
* @param {string} key The combined quality to split.
* @returns {Scheduler|object} The scheduler object or an empty object if not found.
*/
const _getScheduler = key => state.schedulers.find(scheduler => key === scheduler.key) || {};
return _getScheduler;
}
};

Expand Down

0 comments on commit a551865

Please sign in to comment.