From 0510ba65c10cc716220f9f27df112892dda0a7d5 Mon Sep 17 00:00:00 2001 From: Jonathan Baecker Date: Fri, 31 Jan 2020 13:45:56 +0100 Subject: [PATCH] working on file browser --- ffplayout/api/utils.py | 23 +++++++- ffplayout/api/views.py | 26 +++++++-- ffplayout/ffplayout/settings.py | 2 + ffplayout/ffplayout/urls.py | 1 + ffplayout/frontend/pages/index.vue | 4 +- ffplayout/frontend/pages/media.vue | 91 +++++++++++++++++++++++++++++- ffplayout/frontend/store/media.js | 51 +++++++++++++++++ requirements-base.txt | 1 + requirements.txt | 1 + 9 files changed, 190 insertions(+), 10 deletions(-) create mode 100644 ffplayout/frontend/store/media.js diff --git a/ffplayout/api/utils.py b/ffplayout/api/utils.py index 18baa6ea..cf19ef67 100644 --- a/ffplayout/api/utils.py +++ b/ffplayout/api/utils.py @@ -1,11 +1,12 @@ import configparser - +import os from platform import uname from time import sleep from django.conf import settings import psutil +from natsort import natsorted def sizeof_fmt(num, suffix='B'): @@ -117,8 +118,26 @@ class SystemStats: } +def set_root(path): + # prevent access to root file system + root = os.path.dirname(settings.MEDIA_FOLDER) + return path.lstrip(root) + + +def get_media_path(dir=None): + if not dir: + if not os.path.isdir(settings.MEDIA_FOLDER): + return '' + dir = settings.MEDIA_FOLDER + else: + dir = os.path.join(os.path.dirname(settings.MEDIA_FOLDER), dir) + for root, dirs, files in os.walk(dir, topdown=True): + return [set_root(root), natsorted(dirs), natsorted(files)] + + if __name__ == '__main__': - print('ALL: ', SystemStats().all()) + result = hasattr(SystemStats(), 'system') + print(result) exit() print('CPU: ', SystemStats.cpu()) print('RAM: ', SystemStats.ram()) diff --git a/ffplayout/api/views.py b/ffplayout/api/views.py index b5823772..c93fec46 100644 --- a/ffplayout/api/views.py +++ b/ffplayout/api/views.py @@ -4,7 +4,7 @@ from django.conf import settings from rest_framework.views import APIView from rest_framework.response import Response -from .utils import IniParser, SystemStats +from .utils import IniParser, SystemStats, get_media_path class Config(APIView): @@ -35,8 +35,26 @@ class Statistics(APIView): """ def get(self, request, *args, **kwargs): - if 'stats' in request.GET.dict() \ - and request.GET.dict()['stats'] == 'all': - return Response(SystemStats().all()) + if 'stats' in request.GET.dict() and request.GET.dict()['stats'] \ + and hasattr(SystemStats(), request.GET.dict()['stats']): + return Response( + getattr(SystemStats(), request.GET.dict()['stats'])()) + else: + return Response({"success": False}) + + +class Media(APIView): + """ + get folder/files tree, for building a file explorer + for reading, endpoint is: http://127.0.0.1:8000/api/media/?path + """ + + def get(self, request, *args, **kwargs): + if 'path' in request.GET.dict() and request.GET.dict()['path']: + return Response({'tree': get_media_path( + request.GET.dict()['path'] + )}) + elif 'path' in request.GET.dict(): + return Response({'tree': get_media_path()}) else: return Response({"success": False}) diff --git a/ffplayout/ffplayout/settings.py b/ffplayout/ffplayout/settings.py index bab71e1e..62758190 100644 --- a/ffplayout/ffplayout/settings.py +++ b/ffplayout/ffplayout/settings.py @@ -157,3 +157,5 @@ FFPLAYOUT_CONFIG = '/etc/ffplayout/ffplayout.conf' # used network interface for statistics: eth0, eno1, etc. NET_INTERFACE = 'br0' + +MEDIA_FOLDER = '/mnt/playout/ADtvMedia' diff --git a/ffplayout/ffplayout/urls.py b/ffplayout/ffplayout/urls.py index f52ca97d..b7e16e2f 100644 --- a/ffplayout/ffplayout/urls.py +++ b/ffplayout/ffplayout/urls.py @@ -31,6 +31,7 @@ urlpatterns = [ path('api/', include(router.urls)), path('api/config/', views.Config.as_view()), path('api/stats/', views.Statistics.as_view()), + path('api/media/', views.Media.as_view()), path('api-auth/', include( 'rest_framework.urls', namespace='rest_framework')), path('auth/token/', TokenObtainPairView.as_view(), diff --git a/ffplayout/frontend/pages/index.vue b/ffplayout/frontend/pages/index.vue index 6df727aa..43cde7a5 100644 --- a/ffplayout/frontend/pages/index.vue +++ b/ffplayout/frontend/pages/index.vue @@ -131,7 +131,9 @@
Control - Media + + Media + Logging Configure diff --git a/ffplayout/frontend/pages/media.vue b/ffplayout/frontend/pages/media.vue index 8e559a84..7d1a3173 100644 --- a/ffplayout/frontend/pages/media.vue +++ b/ffplayout/frontend/pages/media.vue @@ -1,26 +1,111 @@ diff --git a/ffplayout/frontend/store/media.js b/ffplayout/frontend/store/media.js new file mode 100644 index 00000000..7f3c7d08 --- /dev/null +++ b/ffplayout/frontend/store/media.js @@ -0,0 +1,51 @@ +export const state = () => ({ + currentPath: null, + crumbs: [], + folderTree: {} +}) + +export const mutations = { + UPDATE_CURRENT_PATH (state, path) { + state.currentPath = path + }, + UPDATE_CRUMBS (state, crumbs) { + state.crumbs = crumbs + }, + UPDATE_FOLDER_TREE (state, tree) { + state.folderTree = tree + } +} + +export const actions = { + async getTree ({ commit, dispatch, state, rootState }, path) { + if ((path !== state.currentPath || !state.folderTree)) { + const crumbs = [] + let root = '/' + const response = await this.$axios.get(`api/media/?path=${path}`, { headers: { Authorization: 'Bearer ' + rootState.auth.jwtToken } }) + + if (response.data.tree) { + const pathArr = response.data.tree[0].split('/') + + if (response.data.tree[1].length === 0) { + response.data.tree[1].push(pathArr[pathArr.length - 1]) + } + + if (path) { + for (const crumb of pathArr) { + if (crumb) { + root += crumb + '/' + crumbs.push({ text: crumb, path: root }) + } + } + } else { + crumbs.push({ text: pathArr[pathArr.length - 1], path: '' }) + } + + // console.log(crumbs) + commit('UPDATE_CURRENT_PATH', path) + commit('UPDATE_CRUMBS', crumbs) + commit('UPDATE_FOLDER_TREE', response.data) + } + } + } +} diff --git a/requirements-base.txt b/requirements-base.txt index 74c3cd27..a2004811 100644 --- a/requirements-base.txt +++ b/requirements-base.txt @@ -2,4 +2,5 @@ Django<=3.1 django-cors-headers djangorestframework djangorestframework-simplejwt +natsort psutil diff --git a/requirements.txt b/requirements.txt index f888e0bd..9a1ad966 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,6 +3,7 @@ Django==3.0.2 django-cors-headers==3.2.1 djangorestframework==3.11.0 djangorestframework-simplejwt==4.4.0 +natsort==7.0.1 psutil==5.6.7 PyJWT==1.7.1 pytz==2019.3