diff --git a/bin/qcms b/bin/qcms index 5371120..3f5e6e1 100755 --- a/bin/qcms +++ b/bin/qcms @@ -28,6 +28,8 @@ import cms.engine.project import pandas as pd import requests import plugin_ix +from enum import Enum + from rich.table import Table from rich import print start = index.start @@ -202,78 +204,6 @@ def load(**_args): 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') def create(folder:Annotated[str,typer.Argument(help="path of the project folder")], @@ -348,10 +278,16 @@ def reload ( else: _msg = f"""{FAILED} no secure key found in manifest to request reload""" print (_msg) + +class Platform(str, Enum): + desktop = "desktop" + web = "web" + # cli = "cli" + @cli.command(name="bootup") def bootup ( 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 diff --git a/cms/disk.py b/cms/disk.py index 04228b5..7ac7235 100644 --- a/cms/disk.py +++ b/cms/disk.py @@ -170,28 +170,3 @@ def plugins (**_args): _pointer = loader.get(_args['name']) return _pointer 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 - diff --git a/cms/secure.py b/cms/secure.py index 33aa12c..3b64726 100644 --- a/cms/secure.py +++ b/cms/secure.py @@ -29,8 +29,8 @@ class Manager : _csv = """user,uri,allow\n*,*,1""" self._permissions = pd.read_csv(io.StringIO(_csv)) - - if 'secure' in _args['config']['system']['source'] : + _source = {} if 'source' not in _args['config']['system'] else _args['config']['system']['source'] + if 'secure' in _source : self._authContext = _appConfig['system']['source']['secure']['id'] self._path = _appConfig['system']['source']['secure']['path'] self.inspect(self._path,'authentication configuration') diff --git a/cms/sites/__init__.py b/cms/sites/__init__.py index 6cf4305..7450f16 100644 --- a/cms/sites/__init__.py +++ b/cms/sites/__init__.py @@ -386,24 +386,16 @@ class Site(Initialization) : _plugins['api/oauth2/final'] = cms.oauthFinalize self.set('plugins',_plugins) def exists (self,uri): - path = [] - if self.get('layout.location'): - path.append(self.get('layout.location')) - if self.get('layout.root') not in uri : - path.append(self.get('layout.root')) + # path = [] + # if self.get('layout.location'): + # path.append(self.get('layout.location')) + # if self.get('layout.root') not in uri : + # path.append(self.get('layout.root')) - path.append(uri) - return os.path.exists( os.sep.join(path)) + # path.append(uri) + # 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'
',_html,"
"]) - # else: - # None def mimeType(self,uri): _extension = uri.split('.')[-1].strip().lower() _mimeType = 'application/octet-stream' @@ -482,9 +474,14 @@ class Site(Initialization) : # # We can NOT serve python files over the web (possible security issue) return None - f = open(_uri,_mode) - _content = f.read() - f.close() + # + # If the file doesn't exists we should return 404 + if self.exists(_uri): + f = open(_uri,_mode) + _content = f.read() + f.close() + else: + _content = """
404
File Not Found
""" return _content def read(self,request) : _kwargs = {'allow':0} diff --git a/cms/static/js/qcms/menu.js b/cms/static/js/qcms/menu.js index 8e19192..d0e81d2 100644 --- a/cms/static/js/qcms/menu.js +++ b/cms/static/js/qcms/menu.js @@ -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) // Object.keys(_layout.menu). + var _me = this ; + var tabs = this.tabs ; _names.forEach(function(_text){ _item = _layout.menu[_text] - _tabItem = this._build(_text,_item) + _tabItem = _me._build(_text,_item) $(tabs).append(_tabItem) }) @@ -224,9 +226,9 @@ qcms.menu.init = function(_layout){ }) 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{ - 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') } diff --git a/cms/static/js/qcms/page-loader.js b/cms/static/js/qcms/page-loader.js index cf0a872..76d047b 100644 --- a/cms/static/js/qcms/page-loader.js +++ b/cms/static/js/qcms/page-loader.js @@ -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 if(!bootup){ diff --git a/cms/static/js/qcms/utils.js b/cms/static/js/qcms/utils.js new file mode 100644 index 0000000..4502f39 --- /dev/null +++ b/cms/static/js/qcms/utils.js @@ -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 = $('
') + var _frame = $('
') + _data.forEach((_row,_index) =>{ + // _div = $('
').html(_row.alias).append($('
').html(_row.description) ) + // _div = $(`
${_row.alias}
${_row.description}
`) + _div = $(`
${_row.alias}
${_row.description}
`) + $(_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($('
')) + $(_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) + } +} diff --git a/cms/templates/header.html b/cms/templates/header.html index 4b86142..79798b9 100644 --- a/cms/templates/header.html +++ b/cms/templates/header.html @@ -1,9 +1,9 @@ -
+
-
{{layout.header.title}}
-
{{layout.header.subtitle}}
+
{{layout.header.title}}
+
{{layout.header.subtitle}}
diff --git a/cms/templates/index.html b/cms/templates/index.html index 5d2ab29..784a579 100644 --- a/cms/templates/index.html +++ b/cms/templates/index.html @@ -46,24 +46,24 @@ Vanderbilt University Medical Center -
-