working on file browser

This commit is contained in:
Jonathan Baecker 2020-01-31 13:45:56 +01:00
parent 2623a6decf
commit 0510ba65c1
9 changed files with 190 additions and 10 deletions

View File

@ -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())

View File

@ -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})

View File

@ -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'

View File

@ -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(),

View File

@ -131,7 +131,9 @@
<div class="actions">
<b-button-group class="actions-grp">
<b-button>Control</b-button>
<b-button to="/media">Media</b-button>
<b-button to="/media">
Media
</b-button>
<b-button>Logging</b-button>
<b-button>Configure</b-button>
<b-button @click="logout()">

View File

@ -1,26 +1,111 @@
<template>
<div>
<b-container class="browser">
<div v-if="folderTree.tree" class="browser">
<div>
<b-breadcrumb>
<b-breadcrumb-item
v-for="(crumb, index) in crumbs"
:active="index === crumbs.length - 1"
:key="crumb.key"
@click="getPath(crumb.path)"
>
{{ crumb.text }}
</b-breadcrumb-item>
</b-breadcrumb>
</div>
<b-row>
<b-col class="folder-col">
<div class="browser-div">
<b-list-group>
<b-list-group-item
v-for="folder in folderTree.tree[1]"
:key="folder.key"
class="browser-item"
>
<b-link @click="getPath(`${folderTree.tree[0]}/${folder}`)">
{{ folder }}
</b-link>
</b-list-group-item>
</b-list-group>
</div>
</b-col>
<b-col class="files-col">
<div class="browser-div">
<b-list-group>
<b-list-group-item
v-for="file in folderTree.tree[2]"
:key="file.key"
class="browser-item"
>
<b-link>
{{ file }}
</b-link>
</b-list-group-item>
</b-list-group>
</div>
</b-col>
</b-row>
</div>
</b-container>
</div>
</template>
<script>
import { mapState } from 'vuex'
export default {
name: 'Media',
components: {},
computed: {
...mapState('media', ['crumbs', 'folderTree'])
},
created () {
this.getPath()
this.getPath('')
},
methods: {
async getPath () {
async getPath (path) {
await this.$store.dispatch('auth/inspectToken')
// const response = await this.$axios.get('apt/')
await this.$store.dispatch('media/getTree', path)
}
}
}
</script>
<style>
.browser {
width: 100%;
max-width: 100%;
}
.folder-col {
min-width: 320px;
max-width: 460px;
}
.folder {
padding: .3em;
}
.files-col {
min-width: 320px;
}
.browser-div {
background: #30363d;
height: 100%;
border: 1px solid #000;
border-radius: 5px;
}
.browser-item {
background: none;
padding: .3em;
border: none;
}
</style>

View File

@ -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)
}
}
}
}

View File

@ -2,4 +2,5 @@ Django<=3.1
django-cors-headers
djangorestframework
djangorestframework-simplejwt
natsort
psutil

View File

@ -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