mirror of http://localhost:9400/cloud/cms
parent
8bfa773195
commit
d450779557
@ -0,0 +1,112 @@
|
||||
"""
|
||||
Reads from nextcloud
|
||||
"""
|
||||
|
||||
import nextcloud_client as nc
|
||||
import copy
|
||||
from mistune import markdown
|
||||
|
||||
|
||||
_CLOUDHANDLER = None
|
||||
def _format_root_folder (_root):
|
||||
if _root[0] == '/' :
|
||||
_root = _root[1:]
|
||||
if _root[-1] == '/' :
|
||||
_root = _root[:-1]
|
||||
return _root
|
||||
def content(_args):
|
||||
"""
|
||||
:url
|
||||
:uid
|
||||
:token
|
||||
:folder
|
||||
"""
|
||||
global _CLOUDHANDLER
|
||||
_handler = nc.Client(_args['url'])
|
||||
_handler.login(_args['uid'],_args['token'])
|
||||
_CLOUDHANDLER = _handler
|
||||
_files = _handler.list(_args['folder'],10)
|
||||
_root = _args['folder']
|
||||
if _root.startswith('/') :
|
||||
_root = _root[1:]
|
||||
if _root.endswith('/') :
|
||||
_root = _root[:-1]
|
||||
_menu = {} #[_args['folder']] + [_item for _item in _files if _item.file_type == 'dir' and _item.name[0] not in ['.','_']]
|
||||
_menu = {} #dict.fromkeys(_menu,[])
|
||||
for _item in _files :
|
||||
_folder = _item.path.split(_item.name)[0].strip()
|
||||
_folder = _folder.replace(_root,'').replace('/','')
|
||||
|
||||
if _item.name[0] in ['.','_'] or _folder == '':
|
||||
continue ;
|
||||
|
||||
if _item.file_type == 'file' and _item.get_content_type() in ['text/markdown','text/html'] :
|
||||
# _folder = _item.path.split(_item.name)[0].strip()
|
||||
# _folder = _folder.replace(_root,'').replace('//','')
|
||||
if _folder == '' :
|
||||
_folder = str(_root)
|
||||
_folder = _folder.replace('/' ,' ').strip()
|
||||
if _folder not in _menu :
|
||||
_menu [_folder] = []
|
||||
# print ([_item.name,_key, _key in _menu])
|
||||
|
||||
# _menuItem = _ref[_key]
|
||||
# uri = '/'.join([_args['url'],_item.path])
|
||||
# uri = _item
|
||||
# print ([_menuItem, _menuItem in _menu])
|
||||
uri = '/'.join(_item.path.split('/')[2:])
|
||||
_menu[_folder].append({'text':_item.name.split('.')[0],'uri':uri})
|
||||
#
|
||||
# clean up the content ...
|
||||
_keys = [_name for _name in _menu.keys() if _name.startswith('_')]
|
||||
[_menu.pop(_name) for _name in _keys]
|
||||
return _menu
|
||||
|
||||
|
||||
def build(_config):
|
||||
"""
|
||||
The function will build a menu based on a folder structure in nextcloud
|
||||
:_args authentication arguments for nextcloud
|
||||
:_config configuration for the cms
|
||||
"""
|
||||
_args = copy.deepcopy(_config['system']['source']['auth'])
|
||||
_args['folder'] = _config['layout']['root']
|
||||
# update(_config)
|
||||
return content(_args)
|
||||
def html (uri,_config) :
|
||||
global _CLOUDHANDLER
|
||||
_handler = _CLOUDHANDLER
|
||||
_root = _format_root_folder(_config['layout']['root'])
|
||||
uri = _format_root_folder (uri)
|
||||
|
||||
|
||||
_prefix = '/'.join (uri.split('/')[:-1])
|
||||
_link = '/'.join(['{{context}}api/cloud/download?doc='+_prefix,'.attachments.'])
|
||||
# _link = '/'.join(['api/cloud/download?doc='+_prefix,'_images'])
|
||||
_html = _handler.get_file_contents(uri).decode('utf-8').replace('.attachments.',_link)
|
||||
# print ([uri,uri[-2:] ,uri[-2:] in ['md','MD','markdown']])
|
||||
return markdown(_html) if uri[-2:] in ['md','MD','Md','mD'] else _html.replace(_root,('{{context}}api/cloud/download?doc='+_root))
|
||||
# def update (_config):
|
||||
# """
|
||||
# This function updates the configuration provided by loading default plugins
|
||||
# """
|
||||
# if 'plugins' not in _config :
|
||||
# _config['plugins'] = {}
|
||||
# _config['plugins'] = plugins ()
|
||||
# return _config
|
||||
def download(**_args):
|
||||
_handler = _CLOUDHANDLER
|
||||
|
||||
if _args['doc'][-2:] in ['md','ht']:
|
||||
_stream = html(_args['doc'],_args['config'])
|
||||
else:
|
||||
_stream = _handler.get_file_contents(_args['doc'])
|
||||
|
||||
return _stream
|
||||
pass
|
||||
|
||||
def plugins ():
|
||||
"""
|
||||
This function publishes the plugins associated with this module
|
||||
"""
|
||||
return {'api/cloud/download':download}
|
@ -0,0 +1,40 @@
|
||||
"""
|
||||
This file pulls the content from the disk
|
||||
"""
|
||||
import os
|
||||
def folders (_path):
|
||||
"""
|
||||
This function reads the content of a folder (no depth, it must be simple)
|
||||
"""
|
||||
_content = os.listdir(_path)
|
||||
return [_name for _name in _content if os.path.isdir(os.sep.join([_path,_name])) if not _name.startswith('_')]
|
||||
|
||||
def content(_folder):
|
||||
"""
|
||||
:content of the folder
|
||||
"""
|
||||
|
||||
if os.path.exists(_folder) :
|
||||
_menuItems = os.listdir(_folder)
|
||||
# return [{'text':_name.split('.')[0].replace('_', ' ').replace('-',' ').strip(),'uri': os.sep.join([_folder,_name])} for _name in os.listdir(_folder) if not _name.startswith('_') and os.path.isfile( os.sep.join([_folder,_name]))]
|
||||
return [{'text':_name.split('.')[0].replace('_', ' ').replace('-',' ').strip(),'uri': os.sep.join([_folder,_name])} for _name in os.listdir(_folder) if not _name.startswith('_') and os.path.isfile( os.sep.join([_folder,_name]))]
|
||||
else:
|
||||
return []
|
||||
def build (_config): #(_path,_content):
|
||||
"""
|
||||
building the menu for the site given the content is on disk
|
||||
:path path of the files on disk
|
||||
:config configuration associated with the
|
||||
"""
|
||||
_path = _config['layout']['root']
|
||||
_items = folders(_path)
|
||||
_subItems = [ content (os.sep.join([_path,_name]))for _name in _items ]
|
||||
# return dict(zip())
|
||||
return dict.fromkeys(_items,_subItems)
|
||||
|
||||
def html(uri) :
|
||||
_html = (open(uri)).read()
|
||||
return _html
|
||||
def plugins ():
|
||||
return {}
|
||||
|
@ -0,0 +1,16 @@
|
||||
"""
|
||||
These are a few default plugins that will be exported and made available to the calling code
|
||||
The purpose of plugins is to perform data processing
|
||||
"""
|
||||
|
||||
|
||||
|
||||
|
||||
def copyright (_args) :
|
||||
return {"author":"Steve L. Nyemba","email":"steve@the-phi.com","organization":"The Phi Technology","license":"MIT", "site":"https://dev.the-phi.com/git/cloud/qcms"}
|
||||
|
||||
def log (_args):
|
||||
"""
|
||||
perform logging against duckdb
|
||||
"""
|
||||
pass
|
@ -0,0 +1,5 @@
|
||||
/**
|
||||
* This is the default window and we will have to hide the pane (side)
|
||||
*/
|
||||
|
||||
body .pane { display:none}
|
@ -0,0 +1,90 @@
|
||||
.main {
|
||||
margin:10px;
|
||||
padding:4px;
|
||||
display:grid;
|
||||
grid-template-columns: 50% 50% ; gap:4px;
|
||||
grid-template-rows: 48px 48px auto 32px;
|
||||
font-family: helvetica;
|
||||
font-weight: lighter;
|
||||
font-size:18px;
|
||||
line-height: 1.5;
|
||||
justify-items: normal;
|
||||
;
|
||||
}
|
||||
.main .header {
|
||||
height:48px;
|
||||
grid-row:1;
|
||||
grid-column: 1 / span 2;
|
||||
|
||||
|
||||
}
|
||||
|
||||
.main .header img { width:40px; margin:4px;}
|
||||
.main .menu { grid-row:2; grid-column: 1 / span 2; background-color: #f3f3f3; }
|
||||
.main .content {
|
||||
grid-row:3;
|
||||
grid-column: 1 ;
|
||||
text-wrap: wrap;
|
||||
height:100%;
|
||||
display:grid;
|
||||
align-content: start;
|
||||
|
||||
|
||||
|
||||
}
|
||||
.main .content #index {
|
||||
text-align: left;
|
||||
text-wrap: wrap;
|
||||
}
|
||||
/* .main .content #index{
|
||||
text-align:left;
|
||||
align-content:normal;
|
||||
display:grid;
|
||||
background-color: green;
|
||||
} */
|
||||
|
||||
.main .pane {
|
||||
border-left:3px dotted gray;
|
||||
grid-column: 2;
|
||||
font-family: sans-serif;
|
||||
|
||||
|
||||
}
|
||||
.pane iframe {
|
||||
border:1px solid transparent;
|
||||
width:99%;
|
||||
height:100%;
|
||||
|
||||
}
|
||||
.main .footer {grid-row:4; grid-column: 1 / span 2; font-size:13px; font-weight: lighter;}
|
||||
|
||||
/**
|
||||
* styling tables here
|
||||
*/
|
||||
p {
|
||||
margin-top:22px;
|
||||
}
|
||||
table {
|
||||
width:99%;
|
||||
border: 1px solid #CAD5E0;
|
||||
}
|
||||
table td {padding:4px; margin:4px;}
|
||||
table thead {
|
||||
|
||||
font-weight:bold;
|
||||
background-color:#f3f3f3;
|
||||
}
|
||||
/* table tbody tr:hover {
|
||||
background-color: #4682B4;
|
||||
color:white ;
|
||||
cursor:pointer;
|
||||
} */
|
||||
|
||||
#gallery img {
|
||||
justify-content: left;
|
||||
width:70px;
|
||||
|
||||
|
||||
}
|
||||
|
||||
#gallery table {width:100%;}
|
Loading…
Reference in new issue