Skip to content

Commit

Permalink
[add] React Web UI (Flexget#1854)
Browse files Browse the repository at this point in the history
* Moving ui to old_ui and starting new ui

* Missed a thing

* Fixed a few bugs in the webpack configs, added some dependencies, updated dev_tools.py and __init__.py based on new webui

* Added eslint

* Trying to add support for ui linting and testing to travis

* Fixing travis.yml hopefully

* Third times the charm. Fixing .travis.yml

* Info card made

* Reorg. Also add support so that you can specify web_server version in config

* Added the Navbar

* Fixing .travis.yml after the reorg

* Created the Sidebar.

* Fix linter errors

* Login Works

* Started writing tests

* reducer tests

* Made the login page look better on mobile and fix the .travis.yml

* Updates to reducer tests and middleware tests

* Some re org. Lots of component tests. So many snapshots...

* Added Version to the Sidenav

* Log WIP

* More WIP

* Add highlighting to the log view

* A whole bunch of tests

* Update material-ui, fix snapshots

* actions and reducers for the server stuff

* Reload Server and Shutdown Server Work. Need to add a status bar

* Added the Status Snackbar

* Broken splash screen...wil figure that out later

* Updating some verisons and what not

* Update material-ui and simplify the createAction and loading functions

* Change the get series endpoint to also be filterable by show name

* Fix linting errors

* Added Redux Saga in place of redux thunk

* Fix linting errors:

* Minor tweaks to the side bar, updated material-ui, started making series card

* Rewrote the styles in Emotion and got the splash screen working

* Update travis.yml

* First part of reorg

* Use the /api/cache for series images

* Styled components over emotion. Also wrote some more tests

* Update the default series parameters

* Fix a few things with the status reducer and the fetch wrapper

* Back to emotion because it's better

* Rebuilt the Navbar using the new Material-ui drawer

* Update side nav order

* Started the history plugin

* More tests

* Update snapshots

* History page

* Linting

* Component reorg

* Update to react 16

* update emoiton

* Fix linting

* Update snapshots

* Bump api version

* Update travis.yml

* Get v1 and v2 running along side each other
  • Loading branch information
kristenmills authored and liiight committed Oct 18, 2017
1 parent 7abdb9e commit fb622fb
Show file tree
Hide file tree
Showing 452 changed files with 27,323 additions and 101 deletions.
1 change: 1 addition & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
root = true
10 changes: 5 additions & 5 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,10 @@ pip-*.tar.gz
*.noseids
.coverage
tests/cover/
flexget/ui/node_modules/
flexget/ui/bower_components/
flexget/ui/.tmp/
flexget/ui/app/
flexget/ui/coverage/
bower_components/
.tmp
app/
coverage/
cherrypy
pip-selfcheck.json
npm-debug.log
Expand All @@ -45,5 +44,6 @@ npm-debug.log
node_modules/
!raw_config.yml
!variables.yml
!.travis.yml
cached_resources/
pyvenv.cfg
12 changes: 12 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,18 @@ script: py.test --cov flexget --cov-report xml -n 3
after_success:
- python-codacy-coverage -r coverage.xml
env: VCR_RECORD_MODE=none
jobs:
include:
- python: "2.7" # don't want to run this for each python version so picking one
before_install:
- nvm install 8
- cd flexget/ui/v2/
install:
- npm install
script:
- npm run lint
- npm test -- --coverage
after_success: npm run cov
notifications:
email: false
webhooks:
Expand Down
25 changes: 22 additions & 3 deletions dev_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,12 @@ def bump_version(bump_type):
@cli.command()
def build_webui():
"""Build webui for release packaging"""
cwd = os.path.join('flexget', 'ui')
click.echo('Building webui v1...')
cwd = os.path.join('flexget', 'ui', 'v1')

# Cleanup previous builds
click.echo('cleaning previous builds')
for folder in ['bower_components' 'node_modules']:
for folder in ['bower_components', 'node_modules']:
folder = os.path.join(cwd, folder)
if os.path.exists(folder):
click.echo('Deleting recursively {}'.format(folder))
Expand All @@ -82,14 +83,32 @@ def build_webui():
click.echo('running `npm install`')
subprocess.check_call('npm install', cwd=cwd, shell=True)

# Build the ui
# Install bower packages
click.echo('running `bower install`')
subprocess.check_call('bower install -p', cwd=cwd, shell=True)

# Build the ui
click.echo('running `gulp buildapp`')
subprocess.check_call('gulp buildapp', cwd=cwd, shell=True)

click.echo('building webui v2...')
cwd = os.path.join('flexget', 'ui', 'v2')

# Cleanup previous builds
click.echo('cleaning previous builds')
for folder in ['node_modules']:
folder = os.path.join(cwd, folder)
if os.path.exists(folder):
click.echo('Deleting recursively {}'.format(folder))
shutil.rmtree(folder)

# Install npm packages
click.echo('running `npm install`')
subprocess.check_call('npm install', cwd=cwd, shell=True)

# Build the ui
click.echo('running `npm run build`')
subprocess.check_call('npm run build', cwd=cwd, shell=True)

if __name__ == '__main__':
cli()
2 changes: 1 addition & 1 deletion flexget/api/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
from flexget.webserver import User
from . import __path__

__version__ = '1.3.0'
__version__ = '1.3.1'

log = logging.getLogger('api')

Expand Down
5 changes: 4 additions & 1 deletion flexget/api/plugins/series.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ class ObjectsContainer(object):
help="Filter status by number of days.")
series_list_parser.add_argument('lookup', choices=('tvdb', 'tvmaze'), action='append',
help="Get lookup result for every show by sending another request to lookup API")
series_list_parser.add_argument('query', help="Search by name based on the query")

ep_identifier_doc = "'episode_identifier' should be one of SxxExx, integer or date formatted such as 2012-12-12"

Expand All @@ -170,6 +171,7 @@ def get(self, session=None):
per_page = args['per_page']
sort_by = args['sort_by']
sort_order = args['order']
name = series.normalize_series_name(args['query']) if args['query'] else None

# Handle max size limit
if per_page > 100:
Expand All @@ -194,7 +196,8 @@ def get(self, session=None):
'stop': stop,
'sort_by': sort_by,
'descending': descending,
'session': session
'session': session,
'name': name
}

total_items = series.get_series_summary(count=True, **kwargs)
Expand Down
16 changes: 12 additions & 4 deletions flexget/plugins/daemon/web_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
from flexget.api import api_app
from flexget.utils.tools import get_config_hash
from flexget.webserver import get_secret, register_app, setup_server
from flexget.ui import register_web_ui
from flexget.ui.v1 import register_web_ui as register_web_ui_v1
from flexget.ui.v2 import register_web_ui as register_web_ui_v2

log = logging.getLogger("web_server_daemon")
config_hash = ''
Expand All @@ -31,6 +32,7 @@
'ssl_private_key': {'type': 'string'},
'web_ui': {'type': 'boolean'},
'base_url': {'type': 'string'},
'run_v2': {'type': 'boolean'}
},
'additionalProperties': False,
'dependencies': {
Expand All @@ -55,12 +57,13 @@ def prepare_config(config):
config.setdefault('ssl_private_key', None)
config.setdefault('web_ui', True)
config.setdefault('base_url', '')
config.setdefault('run_v2', False)
if config['base_url']:
if not config['base_url'].startswith('/'):
config['base_url'] = '/' + config['base_url']
if config['base_url'].endswith('/'):
config['base_url'] = config['base_url'][:-1]

return config


Expand Down Expand Up @@ -101,8 +104,13 @@ def register_web_server(manager):

# Register WebUI
if web_server_config.get('web_ui'):
log.info('Registering WebUI')
register_web_ui(manager)
if web_server_config.get('run_v2'):
log.info('Registering WebUI v2')
register_web_ui_v2(manager)

log.info('Registering WebUI v1')
register_web_ui_v1(manager)


web_server = setup_server(web_server_config)

Expand Down
4 changes: 3 additions & 1 deletion flexget/plugins/filter/series.py
Original file line number Diff line number Diff line change
Expand Up @@ -657,7 +657,7 @@ def __init__(self, name):

@with_session
def get_series_summary(configured=None, premieres=None, status=None, days=None, start=None, stop=None, count=False,
sort_by='show_name', descending=None, session=None):
sort_by='show_name', descending=None, session=None, name=None):
"""
Return a query with results for all series.
:param configured: 'configured' for shows in config, 'unconfigured' for shows not in config, 'all' for both.
Expand All @@ -681,6 +681,8 @@ def get_series_summary(configured=None, premieres=None, status=None, days=None,
query = query.having(func.count(SeriesTask.id) >= 1)
elif configured == 'unconfigured':
query = query.having(func.count(SeriesTask.id) < 1)
if name:
query = query.filter(Series._name_normalized.contains(name))
if premieres:
query = (query.having(func.max(Episode.season) <= 1).having(func.max(Episode.number) <= 2)).filter(
EpisodeRelease.downloaded == True)
Expand Down
86 changes: 0 additions & 86 deletions flexget/ui/__init__.py
Original file line number Diff line number Diff line change
@@ -1,86 +0,0 @@
from __future__ import unicode_literals, division, absolute_import
from builtins import * # noqa pylint: disable=unused-import, redefined-builtin

import logging
import os
import fnmatch

from flask import send_from_directory, Flask

from flexget.webserver import register_app, register_home
from flask_compress import Compress

log = logging.getLogger('webui')

manager = None
debug = False
app_base = None

ui_base = os.path.dirname(os.path.realpath(__file__))
ui_src = os.path.join(ui_base, 'src')
ui_dist = os.path.join(ui_base, 'app')
bower_components = os.path.join(ui_base, 'bower_components')

webui_app = Flask(__name__)
Compress(webui_app)
webui_app.url_path = '/'


@webui_app.route('/<path:path>')
def serve_app(path):
if debug:
if path.startswith('bower_components'):
return send_from_directory(bower_components, path.lstrip('bower_components').lstrip('/'))

if os.path.exists(os.path.join(ui_src, path)):
return send_from_directory(ui_src, path)

return send_from_directory(app_base, path)


@webui_app.route('/')
def root():
if not app_base:
return send_from_directory(ui_base, 'load.failure.html')

return send_from_directory(app_base, 'app.html')


def _find(path, f):
matches = []
for root_dir, _, file_names in os.walk(path):
for filename in fnmatch.filter(file_names, f):
matches.append(os.path.join(root_dir, filename))
return matches


def _strip_trailing_sep(path):
return path.rstrip('\\/')


def register_web_ui(mgr):
global manager, app_base, debug
manager = mgr

if 'debug' in manager.args:
debug = True

if debug:
app_base = os.path.join(ui_base, '.tmp', 'serve')
if not os.path.exists(app_base):
log.warning('Unable to start web ui in debug mode. To enable debug mode please run the debug build, '
'see http://flexget.com/wiki/Web-UI for instructions')
log.warning('Attempting to serve web ui from complied directory')
app_base = None

if not app_base:
app_base = ui_dist
if not os.path.exists(app_base):
log.fatal('Failed to start web ui,'
' this can happen if you are running from GitHub version and forgot to run the web ui build, '
'see http://flexget.com/wiki/Web-UI for instructions')

app_base = None

register_app(webui_app.url_path, webui_app)
register_home('%s/' % webui_app.url_path)
File renamed without changes.
File renamed without changes.
86 changes: 86 additions & 0 deletions flexget/ui/v1/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
from __future__ import unicode_literals, division, absolute_import
from builtins import * # noqa pylint: disable=unused-import, redefined-builtin

import logging
import os
import fnmatch

from flask import send_from_directory, Flask

from flexget.webserver import register_app, register_home
from flask_compress import Compress

log = logging.getLogger('webui')

manager = None
debug = False
app_base = None

ui_base = os.path.dirname(os.path.realpath(__file__))
ui_src = os.path.join(ui_base, 'src')
ui_dist = os.path.join(ui_base, 'app')
bower_components = os.path.join(ui_base, 'bower_components')

webui_app = Flask(__name__)
Compress(webui_app)
webui_app.url_path = '/'


@webui_app.route('/<path:path>')
def serve_app(path):
if debug:
if path.startswith('bower_components'):
return send_from_directory(bower_components, path.lstrip('bower_components').lstrip('/'))

if os.path.exists(os.path.join(ui_src, path)):
return send_from_directory(ui_src, path)

return send_from_directory(app_base, path)


@webui_app.route('/')
def root():
if not app_base:
return send_from_directory(ui_base, 'load.failure.html')

return send_from_directory(app_base, 'app.html')


def _find(path, f):
matches = []
for root_dir, _, file_names in os.walk(path):
for filename in fnmatch.filter(file_names, f):
matches.append(os.path.join(root_dir, filename))
return matches


def _strip_trailing_sep(path):
return path.rstrip('\\/')


def register_web_ui(mgr):
global manager, app_base, debug
manager = mgr

if 'debug' in manager.args:
debug = True

if debug:
app_base = os.path.join(ui_base, '.tmp', 'serve')
if not os.path.exists(app_base):
log.warning('Unable to start web ui in debug mode. To enable debug mode please run the debug build, '
'see http://flexget.com/wiki/Web-UI for instructions')
log.warning('Attempting to serve web ui from complied directory')
app_base = None

if not app_base:
app_base = ui_dist
if not os.path.exists(app_base):
log.fatal('Failed to start web ui,'
' this can happen if you are running from GitHub version and forgot to run the web ui build, '
'see http://flexget.com/wiki/Web-UI for instructions')

app_base = None

register_app(webui_app.url_path, webui_app)
register_home('%s/' % webui_app.url_path)
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
26 changes: 26 additions & 0 deletions flexget/ui/v2/.babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"presets": [
[ "env", {
"loose": true,
"modules": false
}],
"stage-0",
"react"
],
"plugins": ["emotion", "syntax-dynamic-import"],
"env": {
"production": {
"plugins": [
"emotion",
"transform-react-remove-prop-types",
]
},
"test": {
"plugins": [
"emotion",
"transform-es2015-modules-commonjs",
"dynamic-import-node",
]
}
}
}
Loading

0 comments on commit fb622fb

Please sign in to comment.