bug fix: menu, added search scripts

v3.0
Steve Nyemba 3 days ago
parent 2697bea668
commit 056d490cab

@ -28,6 +28,8 @@ import cms.engine.project
import pandas as pd import pandas as pd
import requests import requests
import plugin_ix import plugin_ix
from enum import Enum
from rich.table import Table from rich.table import Table
from rich import print from rich import print
start = index.start start = index.start
@ -202,78 +204,6 @@ def load(**_args):
return getattr(module,_name) if hasattr(module,_name) else None return getattr(module,_name) if hasattr(module,_name) else None
# @cli.command(name='plugins')
# def plugin_manager (manifest:Annotated[str,typer.Argument(help="path to manifest file")],
# show:bool=typer.Option(default=False,help="list plugins loaded"),
# add: Annotated[Optional[bool],typer.Option("--register/--unregister",help="add/remove a plugin to manifest use with --pointer option")] = None,
# pointer:str=typer.Option(default=None,help="pointer is structured as 'filename.function'")
# ) :
# """
# Manage plugins list loaded plugins,
# """
# manifest = get_manifest(manifest)
# _config = cms.engine.config.get(manifest)
# if _config :
# _root = os.sep.join(manifest.split(os.sep)[:-1] + [_config['layout']['root'],'_plugins'])
# else :
# _root = None
# if _root and os.path.exists(_root) :
# # files = os.listdir(_root)
# _msg = f"""{FAILED} no operation was specified, please use --help option"""
# # if 'plugins' in _config :
# _plugins = _config['plugins'] if 'plugins' in _config else {}
# if show :
# if not _plugins :
# _msg = f"""{FAILED} no plugins are loaded\n\t{manifest}"""
# else:
# _data = []
# _plugConf = _config['plugins']
# for _name in _plugConf :
# _log = {"files":_name,"loaded":len(_plugConf[_name]),"functions":json.dumps(_plugConf[_name])}
# _data.append(_log)
# _data= pd.DataFrame(_data)
# # # # _data = plugins.stats(_plugins)
# # # _data = cms.Plugin.stats(_plugins)
# print (to_Table(_data))
# _msg = f"""{PASSED} [bold]{_config['layout']['header']['title']}[/bold]: found a total of {_data.loaded.sum()} plugins loaded from {_data.shape[0]} file(s)\n\t{_root}"""
# if add in [True,False] and pointer :
# file,fnName = pointer.split('.')
# # _fnpointer = plugins.load(_root,file+'.py',fnName)
# # _fnpointer = cms.Plugin.load(_root,file+'.py',fnName)
# _ploader = plugin_ix.Loader(file = os.sep.join([_root,file+'.py']))
# if add and _ploader.has(fnName):
# if file not in _plugins :
# _plugins[file] = []
# if fnName not in _plugins[file] :
# _plugins[file].append(fnName)
# _msg = f"""{PASSED} [bold]{_config['layout']['header']['title']}[/bold]: registered {pointer}, use the --show option to list loaded plugins"""
# else:
# _msg = f"""{FAILED} [bold]{_config['layout']['header']['title']}[/bold]: could not register {pointer}, it already exists"""
# elif add is False and file in _plugins:
# _plugins[file] = [_name.strip() for _name in _plugins[file] if _name.strip() != fnName.strip() ]
# _msg = f"""{PASSED} [bold]{_config['layout']['header']['title']}[/bold]: unregistered {pointer}, use the --show option to list loaded plugins """
# # #
# # # We need to write this down !!
# if add in [True,False] :
# _config['plugins'] = _plugins
# cms.engine.config.write(_config,manifest)
# # else:
# # _msg = f"""{FAILED} [bold]{_config['layout']['header']['title']}[/bold]: no plugins are loaded """
# print()
# print(_msg)
# else:
# _msg = f"""{FAILED} No plugin folder could be found in {manifest}"""
# print (_msg)
@cli.command (name='create') @cli.command (name='create')
def create(folder:Annotated[str,typer.Argument(help="path of the project folder")], def create(folder:Annotated[str,typer.Argument(help="path of the project folder")],
@ -348,10 +278,16 @@ def reload (
else: else:
_msg = f"""{FAILED} no secure key found in manifest to request reload""" _msg = f"""{FAILED} no secure key found in manifest to request reload"""
print (_msg) print (_msg)
class Platform(str, Enum):
desktop = "desktop"
web = "web"
# cli = "cli"
@cli.command(name="bootup") @cli.command(name="bootup")
def bootup ( def bootup (
manifest:Annotated[str,typer.Argument(help="path of the manifest file")]='qcms-manifest.json', manifest:Annotated[str,typer.Argument(help="path of the manifest file")]='qcms-manifest.json',
port:int=typer.Option(default=None, help="port number to serve on (will override configuration)") port:int=typer.Option(default=None, help="port number to serve on (will override configuration)"),
): ):
""" """
This function will launch a site/project given the location of the manifest file This function will launch a site/project given the location of the manifest file

@ -170,28 +170,3 @@ def plugins (**_args):
_pointer = loader.get(_args['name']) _pointer = loader.get(_args['name'])
return _pointer return _pointer
return None return None
# if os.path.isdir(_path):
# files = os.listdir(_path)
# if files :
# files = [name for name in files if name.endswith('.py')]
# if files:
# _uri = [_path,files[0]]
# if _context :
# _uri = [_context] + _uri
# _path = os.sep.join(_uri)
# else:
# return None
# else:
# #
# # LOG: not a file
# return None
# #-- We have a file ...
# _name = _args['name']
# spec = importlib.util.spec_from_file_location(_name, _path)
# module = importlib.util.module_from_spec(spec)
# spec.loader.exec_module(module)
# #
# # LOG This plugin ....
# return getattr(module,_name) if hasattr(module,_name) else None

@ -29,8 +29,8 @@ class Manager :
_csv = """user,uri,allow\n*,*,1""" _csv = """user,uri,allow\n*,*,1"""
self._permissions = pd.read_csv(io.StringIO(_csv)) self._permissions = pd.read_csv(io.StringIO(_csv))
_source = {} if 'source' not in _args['config']['system'] else _args['config']['system']['source']
if 'secure' in _args['config']['system']['source'] : if 'secure' in _source :
self._authContext = _appConfig['system']['source']['secure']['id'] self._authContext = _appConfig['system']['source']['secure']['id']
self._path = _appConfig['system']['source']['secure']['path'] self._path = _appConfig['system']['source']['secure']['path']
self.inspect(self._path,'authentication configuration') self.inspect(self._path,'authentication configuration')

@ -386,24 +386,16 @@ class Site(Initialization) :
_plugins['api/oauth2/final'] = cms.oauthFinalize _plugins['api/oauth2/final'] = cms.oauthFinalize
self.set('plugins',_plugins) self.set('plugins',_plugins)
def exists (self,uri): def exists (self,uri):
path = [] # path = []
if self.get('layout.location'): # if self.get('layout.location'):
path.append(self.get('layout.location')) # path.append(self.get('layout.location'))
if self.get('layout.root') not in uri : # if self.get('layout.root') not in uri :
path.append(self.get('layout.root')) # path.append(self.get('layout.root'))
path.append(uri) # path.append(uri)
return os.path.exists( os.sep.join(path)) # return os.path.exists( os.sep.join(path))
return os.path.exists(uri)
# def _html(self,_uri,_id,request) :
# if self.secure.allow(request=request):
# _handler = cloud if self.get('system.source.id') == 'cloud' else disk
# _html = _handler.html(_uri, self.get(None))
# #
# # maybe apply the environment here ??
# return " ".join([f'<div id="{_id}"> ',_html,"</div>"])
# else:
# None
def mimeType(self,uri): def mimeType(self,uri):
_extension = uri.split('.')[-1].strip().lower() _extension = uri.split('.')[-1].strip().lower()
_mimeType = 'application/octet-stream' _mimeType = 'application/octet-stream'
@ -482,9 +474,14 @@ class Site(Initialization) :
# #
# We can NOT serve python files over the web (possible security issue) # We can NOT serve python files over the web (possible security issue)
return None return None
f = open(_uri,_mode) #
_content = f.read() # If the file doesn't exists we should return 404
f.close() if self.exists(_uri):
f = open(_uri,_mode)
_content = f.read()
f.close()
else:
_content = """<div align="center"><div class="large-text">404</div><div>File Not Found</div></div>"""
return _content return _content
def read(self,request) : def read(self,request) :
_kwargs = {'allow':0} _kwargs = {'allow':0}

@ -189,9 +189,11 @@ qcms.menu.Tabs = function (_layout,_outputId,_domId){
var _names = _layout.order.menu.length > 0 ? _layout.order.menu : Object.keys(_layout.menu) var _names = _layout.order.menu.length > 0 ? _layout.order.menu : Object.keys(_layout.menu)
// Object.keys(_layout.menu). // Object.keys(_layout.menu).
var _me = this ;
var tabs = this.tabs ;
_names.forEach(function(_text){ _names.forEach(function(_text){
_item = _layout.menu[_text] _item = _layout.menu[_text]
_tabItem = this._build(_text,_item) _tabItem = _me._build(_text,_item)
$(tabs).append(_tabItem) $(tabs).append(_tabItem)
}) })
@ -224,9 +226,9 @@ qcms.menu.init = function(_layout){
}) })
if (_count == _items){ if (_count == _items){
var _menuObject = new qcms.menu.Tabs (_layout,'.main #content','.main .menu') var _menuObject = new qcms.menu.Tabs (_layout,'..qcms-main .qcms-content','.qcms-main .qcms-menu')
}else{ }else{
var _menuObject = new qcms.menu.Basic (_layout,'.main #content','.main .menu') var _menuObject = new qcms.menu.Basic (_layout,'.qcms-main .qcms-content','.qcms-main .qcms-menu')
} }

@ -82,7 +82,15 @@ qcms.page.loader = function(_parentId,_layout){
}) })
} }
} }
qcms.page.load = function (_uri,_id){
console.log([_uri,' *** ',_id])
var http = HttpClient.instance()
http.get(_uri,(_x)=>{
// var _id = _id[0] == '#' || _id[0] == '.'?_id : (jx.dom.exists(_id)?`#${_id}`:`.${_id}`)
// alert(_id)
$(_id).html(_x.responseText)
})
}
// //
// making backwards compatibility // making backwards compatibility
if(!bootup){ if(!bootup){

@ -0,0 +1,103 @@
/**
* This file contains utilities for performing various tasks
*/
if (!qcms){
var qcms = {}
}
qcms.utils = {}
qcms.utils.csv = function (_dhandler){ //(uri,_render,_error) {
var http = HttpClient.instance()
var format = (_value)=>{return _value.trim()}
var _error = (_error == null)? console.log: _error
http.get(_dhandler._uri,(_x)=>{
if (_x.status == 200){
var _data = []
_x.responseText.split('\n').forEach((_row,_index)=>{
values = jx.utils.patterns.visitor(_row.split(','),format)
if(_index == 0){
_attr = values
}else{
//
// Let's build the object here
var _object = {}
_attr.forEach((_field,_index)=>{
_object[_field] = values[_index]
})
_data.push(_object)
}
})
//--
// At this point we have formatted csv to an array of JSON objects
if (_data.length && _dhandler.render != null){
_dhandler.render (_data)
}else{
//
// @TODO: We need an error handler otherwise we will have to handle it ourselves
_error (_data)
}
}
})
}
qcms.code = {}
qcms.code.documentation= function(_uri,_id) {
this._uri = _uri
this._id = _id[0] == '#'?_id :( _id[0] == '.' ?_id: '#'+_id)
this.events = {_open:{},_find:{}}
this.events._open = function(_uri){
qcms.page.load(_uri,`${_id} .content`)
}
this.render = function (_data){
//
//NOTE: Because this function will be a callback, it will lose reference to the class members but will be able to access them without 'this'
//
var _open = this.events._open
var _menu = $('<div class="toc"><div class="border-round"><input type="text" class="doc-find" placeholder="[keyword, term]"/></div></div>')
var _frame = $('<div class="items"></div>')
_data.forEach((_row,_index) =>{
// _div = $('<div class="active label bold"></div>').html(_row.alias).append($('<div class="small"></div>').html(_row.description) )
// _div = $(`<div class="active bold label">${_row.alias}</div><div class="small">${_row.description}</div>`)
_div = $(`<div class="active bold label" align="left">${_row.alias}</div><div class="small" style="padding-left:8px;">${_row.description}</div>`)
$(_div).attr('file',_row.file)
_div[0].onclick = function (){
//
// we need to load the area with the given page
console.log($(this).attr('file'))
var _uri = $(this).attr('file')
// qcms.page.load(_uri,'')
console.log([_uri ,_id, ' ########'])
_open(_uri,_id)
}
$(_frame).append(_div)
})
//
// adding the menu to the location specified
$(_id).empty()
$(_menu).append(_frame)
$(_id).append(_menu)
$(_id).append($('<div class="content"></div>'))
$(_id).attr('class','doc-browser')
$(_id).show()
//
// click the first item on the list
$(_frame).children()[0].click()
}
this.reload = function (){
// var _id = this._id
// var events = this.events
// var _openEvent =this._openEvent
// var _find = this.events._find ;
qcms.utils.csv(this) //(this._uri,this.render)
}
}

@ -1,9 +1,9 @@
<div class="icon"> <div class="qcms-icon">
<img src="{{system.icon}}"> <img src="{{system.icon}}">
</div> </div>
<div> <div>
<div class="title">{{layout.header.title}}</div> <div class="qcms-title">{{layout.header.title}}</div>
<div class="subtitle">{{layout.header.subtitle}}</div> <div class="qcms-subtitle">{{layout.header.subtitle}}</div>
</div> </div>

@ -46,24 +46,24 @@ Vanderbilt University Medical Center
</script> </script>
<body> <body>
<div class="main {{system.theme}}" > <div class="qcms-main {{system.theme}}" >
<div id="header" class="header" onclick="window.location.href='{{system.context}}'" style="cursor:pointer"> <div id="qcms-header" class="qcms-header" onclick="window.location.href='{{system.context}}'" style="cursor:pointer">
{%include "header.html" %} {%include "header.html" %}
</div> </div>
<div id="menu" class="menu">{%include "menu.html" %}</div> <div id="qcms-menu" class="qcms-menu">{%include "menu.html" %}</div>
<div id="content" class="content"> <div id="qcms-content" class="qcms-content">
{%include "content.html" %} {%include "content.html" %}
</div> </div>
<div id="pane" class="pane"> <div id="qcms-pane" class="qcms-pane">
{%include "pane.html" %} {%include "pane.html" %}
</div> </div>
<div id="footer" class="footer"> <div id="footer" class="qcms-footer">
{%include "footer.html" %} {%include "footer.html" %}
</div> </div>
</div> </div>

@ -24,6 +24,7 @@
<meta property="og:description" content="{{layout.header.title}}; {{layout.header.subtitle}}, version {{system.version}}" /> <meta property="og:description" content="{{layout.header.title}}; {{layout.header.subtitle}}, version {{system.version}}" />
<meta property="og:site_name" content="{{layout.header.title}}" /> <meta property="og:site_name" content="{{layout.header.title}}" />
<script src="{{system.parentContext}}/static/js/qcms/qcms.js"></script> <script src="{{system.parentContext}}/static/js/qcms/qcms.js"></script>
<script src="{{system.parentContext}}/static/js/qcms/utils.js"></script>
<script src="{{system.parentContext}}/static/js/qcms/menu.js"></script> <script src="{{system.parentContext}}/static/js/qcms/menu.js"></script>
<script src="{{system.parentContext}}/static/js/qcms/page-loader.js"></script> <script src="{{system.parentContext}}/static/js/qcms/page-loader.js"></script>
<script src="{{system.parentContext}}/static/js/qcms/dialog.js"></script> <script src="{{system.parentContext}}/static/js/qcms/dialog.js"></script>

@ -6,8 +6,8 @@
{% set _backURI = system.parentContext%} {% set _backURI = system.parentContext%}
{% endif %} {% endif %}
<div class="icon" style="margin:0px" > <div class="qcms-icon" style="margin:0px" >
<div align="left" class="back-button active" onclick="window.open('{{_backURI}}','_self')" > <div align="left" class="qcms-back-button active" onclick="window.open('{{_backURI}}','_self')" >
<div style="display:grid; align-items:center; grid-template-columns: auto auto;"> <div style="display:grid; align-items:center; grid-template-columns: auto auto;">
<i class="fa-solid fa-chevron-left" style="color:darkgray;"></i> <i class="fa-solid fa-chevron-left" style="color:darkgray;"></i>
<img src="{{system.caller.icon}}"/> <img src="{{system.caller.icon}}"/>
@ -15,7 +15,7 @@
</div> </div>
</div> </div>
{% else %} {% else %}
<div class="icon"> <div class="qcms-icon">
<i class="fa-solid fa-home"></i> <i class="fa-solid fa-home"></i>
</div> </div>
{% endif %} {% endif %}

@ -25,22 +25,22 @@
<body> <body>
<div class="main" style=""> <div class="qcms-main" style="">
<div class="header" onclick="window.location.href='{{system.context}}/'" style="cursor:pointer"> <div class="qcms-header" onclick="window.location.href='{{system.context}}/'" style="cursor:pointer">
{%include "header.html" %} {%include "header.html" %}
</div> </div>
<div class="menu"> <div class="qcms-menu">
{% include "menu.html" %} {% include "menu.html" %}
</div> </div>
<div class="content"> <div class="qcms-content">
<div id="me">{{html|safe}}</div> <div id="me">{{html|safe}}</div>
{%include "content.html" %} {%include "content.html" %}
</div> </div>
<div class="footer"> <div class="qcms-footer">
{%include "footer.html" %} {%include "footer.html" %}
</div> </div>
</div> </div>

Loading…
Cancel
Save