diff --git a/bin/qcms b/bin/qcms
index 7736054..065541a 100755
--- a/bin/qcms
+++ b/bin/qcms
@@ -293,7 +293,7 @@ def create(folder:Annotated[str,typer.Argument(help="path of the project folder"
#
# Build the configuration for the project
if not os.path.exists(folder) :
- root = 'www/html'
+ root = f'www{os.sep}html'
_system = System()
_layout = Layout()
_layout = _layout.build(root=root, order={'menu':[]}, footer = [{"text":term} for term in footer.split(',')],header={'title':title,'subtitle':subtitle} )
diff --git a/bin/qcms.bat b/bin/qcms.bat
index d3c4114..8de5a63 100644
--- a/bin/qcms.bat
+++ b/bin/qcms.bat
@@ -1,3 +1,2 @@
-REM python .\qcms-sandbox\Scripts\qcms %1 %2 %3 %4 %5 %6
cd /D "%~dp0"
-python qcms %1 %2 %3 %4 %5 %6
\ No newline at end of file
+python qcms %1 %2 %3 %4 %5 %6
diff --git a/cms/__init__.py b/cms/__init__.py
index ab4a503..d6c8aa1 100644
--- a/cms/__init__.py
+++ b/cms/__init__.py
@@ -181,5 +181,9 @@ class delegate:
"""
-
+ # if _mimeType in ['text/html','plain/html'] :
+ # _env = Environment(loader=BaseLoader()).from_string(_data)
+ # _kwargs = {'layout':_config['layout'],'system':_config['system']}
+ # print (_data)
+ # _data = _env.render(**_kwargs)
return _data,_code,{'Content-Type':_mimeType}
diff --git a/cms/disk.py b/cms/disk.py
index 74b1a0a..18cbbb3 100644
--- a/cms/disk.py
+++ b/cms/disk.py
@@ -68,8 +68,16 @@ def build (_config, keep=[]): #(_path,_content):
def _realpath (uri,_config) :
_layout = _config['layout']
_uri = copy.copy(uri)
+ if _layout['root'] not in _uri :
+ _uri = os.sep.join([_layout['root'],_uri])
if 'location' in _layout and _layout['location']:
+ _loc = _layout['location'].strip()
+
+ if _loc.endswith(os.sep) and _uri.endswith(os.sep) :
+ _uri = os.sep.join(_uri.split(os.sep)[1:])
+
_uri = os.sep.join([_layout['location'],_uri])
+
return _uri
def _format (uri,_config):
@@ -82,12 +90,13 @@ def read (**_args):
This will read binary files from disk, and allow the location or not to be read
@TODO: add permissions otherwise there can be disk-wide reads
"""
- request = _args['request']
+ request = _args['request'] if 'request' in _args else None
_layout = _args['config']['layout']
- _uri = request.args['uri'] # if 'location' in _layout :
+ _uri = request.args['uri'] if request else _args['uri'] # if 'location' in _layout :
# _uri = os.sep.join([_layout['location'],_uri])
_uri = _realpath(_uri, _args['config'])
_mimeType = 'text/plain'
+
if os.path.exists(_uri):
f = open(_uri,mode='rb')
_stream = f.read()
@@ -135,6 +144,8 @@ def html(_uri,_config) :
# _html = _html.replace(f'{os.sep}{_layout["root"]}',_layout['root'])
return _html
+
+ pass
def plugins (**_args):
"""
This function will load plugins from disk given where they come from
diff --git a/cms/engine/config/structure.py b/cms/engine/config/structure.py
index 93aca9c..ad11579 100644
--- a/cms/engine/config/structure.py
+++ b/cms/engine/config/structure.py
@@ -2,7 +2,7 @@
This file handles the structure (strict) of the configuration file,
Not all elements are programmatically editable (for now)
"""
-import meta
+# import meta
class Section :
def build (self,**_args):
@@ -36,7 +36,8 @@ class System (Section) :
"""
return 'default' if 'name' not in _args else _args['name']
def version(self,**_args):
- return meta.__version__ if 'version' not in _args else _args['version']
+ import cms
+ return cms.meta.__version__ if 'version' not in _args else _args['version']
def context (self,**_args):
return "" if 'context' not in _args else _args['context']
def app (self,**_args):
@@ -74,4 +75,4 @@ class Layout (Section):
def header (self,**_args):
_data = {"title":"QCMS Project", "subtitle":"Powered by Python Flask"}
return self.update(_data,**_args)
-
\ No newline at end of file
+
diff --git a/cms/engine/project/__init__.py b/cms/engine/project/__init__.py
index 210cd35..65fe2e9 100644
--- a/cms/engine/project/__init__.py
+++ b/cms/engine/project/__init__.py
@@ -2,7 +2,7 @@
import base64
import os
import json
-import meta
+# import meta
from cms.engine import themes
# def make (**_args):
# """
@@ -94,10 +94,11 @@ def _index (_path,root):
"""
Creating a default index.html for the site given the project root location
"""
+ import cms
_html = f"""
Thank you for considering QCMS
-
version {meta.__version__} by {meta.__author__}, {meta.__email__}
+
version {cms.meta.__version__} by {cms.meta.__author__}, {cms.meta.__email__}
diff --git a/cms/index.py b/cms/index.py
index 96ce449..15ec13e 100644
--- a/cms/index.py
+++ b/cms/index.py
@@ -4,8 +4,8 @@ __doc__ = """
"""
from flask import Flask,render_template,send_from_directory,request, redirect, Response, session
import flask
-import transport
-from transport import providers
+#import transport
+#from transport import providers
import cms
from cms import Plugin
import sys
@@ -44,6 +44,14 @@ def _getId(app_id,app_x):
def _setHandler (app_id,resource) :
session['app_id'] = _getId(app_id,resource)
+@_app.route("/favicon.ico")
+@_app.route("//favicon.ico")
+def favicon (app):
+ global _qcms
+ _site = _qcms.get (app)
+ print([' **** ',_site.get('layout.location'),_site.get('system.icon')])
+
+ return
@_app.route("/<_id>/robots.txt")
@_app.route("/robots.txt",defaults={'_id':None})
def robots_txt(_id):
@@ -95,7 +103,7 @@ def _index ():
_app = _qcms.get(None)
_uri = os.sep.join([_app.get('layout.root'),_app.get('layout.index')])
_html = _qcms.render(_uri,'index')
- print (_html)
+
return render_template('index.html',**_html),200 #render_template('index.html',**_qcms.render(_uri,'index')),200
@_app.route("//")
@@ -106,7 +114,16 @@ def _altIndex(app,resource):
_site = _qcms.get(_id)
_uri = os.sep.join([_site.get('layout.root'),_site.get('layout.index')])
return render_template('index.html',**_qcms.render(_uri,'index',_id)),200
-
+@_app.route('/files/',defaults={'app':None,'module':None})
+@_app.route('//files/', defaults=[{'module':None}])
+@_app.route('///files/')
+def _read(app,module,file):
+ global _qcms
+ _id = _getId(app,module)
+ _site = _qcms.get(_id)
+ _stream,_mimeType = _site.read(file)
+
+ return io.BytesIO(_stream),200,{'Content-Type':_mimeType}
@_app.route('//dialog')
@_app.route('/dialog',defaults={'app':None})
def _getdialog(app):
@@ -167,6 +184,7 @@ def getPostedPage(app_id,key):
_id = _getId(app_id,key)
_site = _qcms.get(_id)
_uri = request.headers['uri']
+
if 'dom' not in request.headers :
_id = _uri.split('/')[-1].split('.')[0]
else:
diff --git a/cms/meta/__init__.py b/cms/meta/__init__.py
index 83083b8..4e7cd7b 100644
--- a/cms/meta/__init__.py
+++ b/cms/meta/__init__.py
@@ -1,5 +1,5 @@
__author__ = "Steve L. Nyemba"
-__version__= "2.2.22"
+__version__= "2.4.0"
__email__ = "steve@the-phi.com"
__license__="""
Copyright 2010 - 2024, Steve L. Nyemba, Vanderbilt University Medical Center
diff --git a/cms/sites/__init__.py b/cms/sites/__init__.py
index 8dc2a11..5ceff9d 100644
--- a/cms/sites/__init__.py
+++ b/cms/sites/__init__.py
@@ -318,6 +318,9 @@ class Site(Initialization) :
_handler = cloud if self.get('system.source.id') == 'cloud' else disk
_html = _handler.html(_uri, self.get(None))
return " ".join([f' ',_html,"
"])
+ def read(self,_uri) :
+ _handler = cloud if self.get('system.source.id') == 'cloud' else disk
+ return _handler.read(uri=_uri, config=self.get(None))
class QCMS:
def __init__(self,**_args):
@@ -346,5 +349,4 @@ class QCMS:
def set(self,_id):
self._id = _id
def get(self,_id=None):
-
return self._sites[self._id] if not _id else self._sites[_id]
diff --git a/cms/static/js/bootup.js b/cms/static/js/bootup.js
deleted file mode 100644
index b61f2e9..0000000
--- a/cms/static/js/bootup.js
+++ /dev/null
@@ -1,87 +0,0 @@
-/**
- * This file has functions that allow pages to be fetched and rendered on bootup
-*/
-
-var bootup = {}
-//
-// We implement this function using an observer design pattern
-bootup.CMSObserver = function(_context,_domId,_fileURI){
- this._context = _context
- this._domId = _domId
- this._fileURI = _fileURI
- this.apply = function (_caller){
- var http = HttpClient.instance()
- http.setHeader('uri',_fileURI)
-
-
- uri = '/page'
- if (this._context != '' && this._context != null) {
- uri = this._context + uri
- }
- if (window.location.pathname != '/'){
- uri = ([window.location.pathname,'page']).join('/')
- }
-
- try{
- // var _domElement = jx.dom.get.instance('div')
-
- // _domElement.className = 'busy-loading'
- // jx.dom.append(_domId, _domElement)
- http.post(uri,function(x){
- if (x.status == 200 && x.readyState == 4){
-
- setTimeout(function(){
- _content = $(x.responseText)
- var _id = $(_content).attr('id')
- _pid = (['#',_domId,' #',_id]).join('')
- if( $(_pid).length != 0){
- $(_pid).remove()
- }
- $('#'+_domId).append(x.responseText)
- },10)
-
-
- }
-
- _caller.notify()
- })
-
- }catch(error){
- _caller.notify()
- }
- }
-
-}
-//
-// Finalize the process of rendering the content on the fly
-bootup.finalize = function(_id){
- this.apply = function(_caller){
- // menu.runScript('#'+_id)
- setTimeout(function(){menu.events.finalize(_id);},1000)
- // menu.events.finalize(_id)
- }
-}
-
-bootup.init = function(sys_id,_layout){
- if (!_layout) {
- return ;
- }
- if (_layout.on){
- jx.utils.keys(_layout.on.load).forEach(function(_domId){
-
- var observers =
- jx.utils.patterns.visitor(_layout.on.load[_domId], function(_uri){
- // _uri = _layout.root_prefix != null? (_layout.root_prefix+_uri) : _uri
- return new bootup.CMSObserver(sys_id,_domId,_uri)
- })
- observers.push(new bootup.finalize(_domId))
- //
- // At this point we can execute the observer design pattern
- //
- // console.log(observers)
- jx.utils.patterns.observer(observers,'apply')
-
- })
- }
-
-}
\ No newline at end of file
diff --git a/cms/static/js/dialog.js b/cms/static/js/dialog.js
deleted file mode 100644
index 3dd652d..0000000
--- a/cms/static/js/dialog.js
+++ /dev/null
@@ -1,44 +0,0 @@
-var dialog = {}
-dialog.context = ''
-dialog.show = function(_args,_pointer){
- var http = HttpClient.instance()
-// http.setData({title:_title,html:_message},'application/json')
- var uri = _args.context+'/dialog'
- http.setHeader('dom',_args.title)
- if (_args.uri.match(/=/)){
- _args.uri = _args.uri.split(/=/)[1]
- }
- http.setHeader('uri',_args.uri)
- http.get(uri,function(x){
- $('.jxmodal').remove()
- jx.modal.show({html:x.responseText,id:'body'})
- if(jx.dom.exists('dialog-message') && _args.message != null){
- jx.dom.set.value('dialog-message',_args.message)
-
- }
-
- //
- // In order to perhaps execute any js script that should have been executed on load ...
- //
-
- var scripts = $('.jxmodal script')
- jx.utils.patterns.visitor(scripts,function(_item){
- if(_item.text.trim().length > 0){
- var _routine = eval(_item.text)
- //
- //@TODO:
- // Find a way to add the running function into the page to enable scripts to work
- //
- }
- })
- if (_pointer !=null){
- _pointer()
- }
-
- })
-}
-
-if (! qcms){
- var qcms = {}
-}
-qcms.dialog = dialog
\ No newline at end of file
diff --git a/cms/static/js/menu.js b/cms/static/js/menu.js
deleted file mode 100644
index 7d234a2..0000000
--- a/cms/static/js/menu.js
+++ /dev/null
@@ -1,449 +0,0 @@
-/*
-* Let us load the menu items here ...
-*/
-var menu = {}
-/*
-* This function will load menu items from the configuration file
-* :uri
-* :id
-* :pid parent identifier
-*/
-
-menu.apply = function (uri,id,pid,_context){
- id = id.replace(/ /g,'-')
- if(uri == null){
- return ;
- }
- $('.content').children().hide()
-
- var httpclient = HttpClient.instance()
-
- httpclient.setHeader('uri',uri)
- httpclient.setHeader('dom',id)
- httpclient.post(_context+'/page',function(x){
- var _html = x.responseText
- var template = document.createElement('template');
- template.innerHTML = _html.trim();
- var _dom = template.content.firstChild;
- if(jx.dom.exists(pid) && jx.dom.exists(id)){
- jx.dom.remove(id)
- }
- $('#'+pid).append(_dom)
- // jx.dom.append(pid,_dom)
- // $('#'+id).show('fast',function(){
- // $('#'+pid).slideUp()
- // })
-
- $('#'+pid).children().slideUp('fast', function(){
- $('#'+id).slideDown('fast',function(){
- $('#'+pid).slideDown('fast',function(){
- var input = $('#'+pid).find('input')
- if (input.length > 0 ){
- $(input[0]).focus()
- }
- })
-
- })
-
- })
-
- // $('.content').append(_dom)
- })
-
-}
-
-menu.apply_link =function(_args,_context){
- //
- // type:
- // redirect open new window
- // dialog open in a dialog
- //
-
- var url = _args['url']
- _args.type = (_args.type == null)? 'redirect' :_args.type
-
- if (_args.type.match(/dialog|embed/i) ) {
- //
- // calling jx.modal.show
- if (_args.url){
- jx.modal.show(_args.url)
- }else{
- // _html = jx.dom.get.value(_args.text)
- // console.log(_html)
- // jx.modal.show(_html)
- var http = HttpClient.instance()
- http.setHeader('uri',_args.uri)
- http.setHeader('dom',(_args.title)?_args.title:'dialog')
- // http.setHeader('dom',_args.text)
- http.get(_context+'/dialog',function(x){
-
- jx.modal.show({html:x.responseText,id:'dialog'})
- console.log([$('.jxmodal')])
- menu.runScript ('.jxmodal')
- })
- }
- }else{
- window.open(_args.url,_args.text)
- }
-
-}
-
-var _delegate = {scripts:{}}
-menu.runScript = function(_id){
- var scripts = $(_id+' script')
-
- jx.utils.patterns.visitor(scripts,function(_item){
- if(_item.text.trim().length > 0){
-
- var _code = eval(_item.text)
- var id = _id
- if (_item.parentNode != null){
- var id = _item.parentNode.id == null?_item.parentNode.className : _item.parentNode.id
- }
- id = (id != null)?id : _id
-
- // _delegate.scripts[id] = _code
- }
- })
-}
-menu.events = {}
-menu.events._dialog = function (_item,_context){
- // var url = _args['url']
- _item.type = (_item.type == null)? 'redirect' :_item.type
- var http = HttpClient.instance()
- _regex = /uri=(.+)/;
- if (_item.uri.match(_regex)) {
- _seg = _item.uri.match(_regex)
- _item.uri = _seg[_seg.length - 1]
- }
- http.setHeader('uri',_item.uri)
- http.setHeader('dom',(_item.title)?_item.title:'dialog')
- // http.setHeader('dom',_args.text)
- http.get(_context+'/dialog',function(x){
-
- jx.modal.show({html:x.responseText,id:'dialog'})
- menu.events.finalize ('.jxmodal')
- })
-
-}
-menu.events._openTabs = function (_TabContentPane, _id) {
- _id = _id[0] != '.' ? ('.'+_id) : _id
- $(_TabContentPane).children().slideUp('fast')
- $(_id).slideDown()
-}
-menu.events._open = function (id,uri,_context){
- id = id.replace(/ /g,'-')
-
- var pid = '#content'
- $('.content').children().slideUp()
- // if ( $('#'+id).parent() == null){
- // $('.content').children().slideUp()
- // }else{
- // var parent = $('#'+id).parent()
- // parent.slideUp()
- // if (parent[0].id == null){
- // pid = ('.' + parent[0].className)
- // }else{
- // pid = ('#'+parent[0].id)
- // }
-
- // }
- $('#'+id).remove()
-
- var httpclient = HttpClient.instance()
- _context = (_context == null)?'':_context;
- httpclient.setHeader('uri',uri)
- httpclient.setHeader('dom',id)
- httpclient.post(_context+'/page',function(x){
- if(x.readyState == 4 && x.status == 200){
- var _html = x.responseText
- var _dom = $(_html)
-
- if(jx.dom.exists(pid) && jx.dom.exists(id)){
- jx.dom.remove(id)
-
- }
- $(pid).append(_dom)
- var ref = pid + ' #'+id
- // menu.events.finalize (ref)
- $(pid).children().slideUp('fast', function(){
-
- $(ref ).slideDown('fast',function(){
-
- $(pid).slideDown('fast',function(){
- var input = $(pid).find('input')
- if (input.length > 0 ){
- $(input[0]).focus()
- }
- })
-
- })
-
- })
-
-
- }
-
-
- // $('.content').append(_dom)
- })
-
-}
-
-menu.utils = {}
-menu.utils.format = function(text){
- return text.replace(/(-|_)/g,' ').trim()
-}
-menu.utils._delegate = function (_id,_itemIndex,_index) {
- if ($(_id).children().length >= _itemIndex ){
- var _node = $(_id).children()[_itemIndex ]
- if ($(_node).children().length >= _index ){
- var _node = $(_node).children()[_index]
- _node = $(_node).find('.active')
- if ($(_node).length > 0 ){
- $(_node)[0].click()
- }
- }
-
-
- }
-}
-menu.events.finalize = function (ref) {
- var scripts = $(ref+' script')
-
- jx.utils.patterns.visitor(scripts,function(_item){
- if(_item.text.trim().length > 0){
-
- var _code = eval(_item.text)
- var id = ref
- if (_item.parentNode != null){
- var id = _item.parentNode.id == null?_item.parentNode.className : _item.parentNode.id
- }
- id = (id != null)?id : ref
-
- // _delegate.scripts[id] = _code
- }
- })
-}
-
-/**
- * Let's build the tab handling here ...
- *
- */
-var QCMSBasic= function(_layout,_context,_clickEvent) {
- this._layout = _layout
- this._context= _context
- this._make = function (_items){
- var _panes = []
- var _context = this._context ;
-
- _items.forEach(_item=>{
- var _div = jx.dom.get .instance('DIV')
-
- _div.innerHTML = menu.utils.format(_item.text)
-
- //
- // We need to check for the override text and see if it goes here
- _div.className = 'active'
- _div.data = _item
- _panes.push(_div)
- $(_div).on('click', function (){
- //
- // how do we process this ...
- if(this.data.uri && this.data.type != 'open') {
-
- if (this.data.type == 'dialog') {
- // console.log(this.data)
- menu.events._dialog(this.data,_context)
- }else{
- menu.events._open(menu.utils.format(this.data.text),this.data.uri,_context)
- }
- }else{
- if (this.data.uri != null){
- window.open(this.data.uri,'_self')
- }else{
- window.open(this.data.url,menu.utils.format(this.data.text))
- }
- }
- })
-
-
- })
- return _panes ;
-
- }
- this.init = function (){
- var _me = this ;
- var _make = this._make
- var _layout = this._layout
-
- var _names = _layout.order.menu.length > 0 ? _layout.order.menu : Object.keys(_layout.menu)
-
- // Object.keys(this._layout.menu)
- _names.forEach(function(_name){
- var _div = _me._make(_layout.menu[_name]) ;
-
-
- var _sub = jx.dom.get.instance('DIV')
- var _menuItem = jx.dom.get.instance('DIV')
- _menuItem.innerHTML = menu.utils.format (_name)
- _sub.className = 'sub-menu border-round border '
- _menuItem.className = 'item'
- _div.forEach(_item=>{$(_sub).append(_item) })
- $(_sub).append(_div)
- _menuItem.appendChild(_sub)
-
- $('.main .menu').append(_menuItem)
- })
- }
-}
-
-var QCMSTabs = function(_layout,_context,_id){
- //
- // This object will make tabs in the area of the menu
- // @TODO: we can parameterize where the menu is made to improve flexibility
- //
- this.tabs = jx.dom.get.instance('DIV')
- this.tabs.className = 'tabs'
- this._context = _context
- this._layout = _layout
- this._target = (_id == null)?'.main .menu':_id
- this._make = function (text,_item,_event){
- var text = text.trim().replace(/(_|-)/ig,' ').trim()
- var _context = this._context;
- if (text.match(/\//)){
- text = text.split(/\//g).slice(-1)[0]
- }
- var _button = jx.dom.get.instance('INPUT')
- var _label = jx.dom.get.instance('LABEL')
- _button.type= 'radio'
- _button.id = text+'tab'
- _button.name = 'menu-tabs'
-
- _label.data = {id:text.toLowerCase(),uri:_item[0].uri}
- // _button._uri = _label._uri
-
- // if(this._layout.icons[text] != null) {
-
- if (this._layout.icon){
- var _icon = jx.dom.get.instance('I')
- _icon.className = this._layout.icons[text]
- $(_label).append(_icon)
- }
-
- text = ' ' + text
-
- // }
- $(_label).append(text)
- // _button.value= text.toLowerCase()
- $(_button).val(text.toLowerCase())
- _label.htmlFor = _button.id
- $(_label).on('click',function (){
-
- menu.events._open(this.data.id,this.data.uri,_context)
- })
- // $(_button).on('click',function (){
- // menu.events._open(this.value,this._uri,_context) ;})
-
- return [_button,_label]
-
- }
-
-
- this.init = function (){
- var _me = this;
- var _make = this._make
- var tabs = this.tabs
- var _names = _layout.order.menu.length > 0 ? _layout.order.menu : Object.keys(_layout.menu)
- // Object.keys(_layout.menu).
- _names.forEach(function(_key){
- _item = _layout.menu[_key]
- // console.log([_item])
- _tabItem = _me._make(_key,_item)
- $(tabs).append(_tabItem)
- })
-
- this.tabs.className = 'tabs'
- $(this._target).append(this.tabs)
- $(this._target).css({'border':'1px solid transparent'})
- $(this._target).css({'grid-template-columns':'64px auto'})
- }
- //
- // We need to load the pages here ...
- //
-
-
-
-}
-
-menu.delegate = { }
-
-// menu.tabs.make = function(text,_clickEvent){
-// var _id = text.trim()
-// if (text.match(/\//)){
-// _id = text.split(/\//g).slice(-1)[0]
-// }
-// var _button = jx.dom.get.instance('div')
-// var _label = jx.dom.get.instance('LABEL')
-// _button.type= 'radio'
-// _button.id = _id
-
-// _label.innerHTML = _id.toLowerCase()
-// $(_label).on('click',_clickEvent)
-// return [_button,_label]
-// }
-menu.init =function (_layout,_context){
- //
- // Let us determine what kind of menu is suited for this
- // @TODO: Make menus configurable i.e on other areas of the site
- //
-
- if (_layout.order != null){
- if (_layout.order.length == null && _layout.order.menu == null){
- _layout.order = {menu:[]}
-
- }else if (_layout.order.menu == null){
- _layout.order.menu = []
- }
- }else{
- _layout.order = {menu:[]}
- }
-
-
- var _count = 0
- var _items = 0
- Object.keys(_layout.menu).forEach(_name=>{
- _items += _layout.menu[_name].length
- _count += 1
- })
-
- if (_count == _items){
- var _menuObject = new QCMSTabs (_layout,_context)
- }else{
- var _menuObject = new QCMSBasic (_layout,_context)
- }
-
- _menuObject.init()
-
-}
-
-
-
-
-/***
- *
- * Source Code
- */
-if (! code){
- var code = {}
-}
-code.copy = function(_node) {
- var _code = $(_node.parentNode).text().trim().replace(/ {8}/g,'').replace(/ {4}/g,'\t').replace(/\r/g,'\n')
- navigator.clipboard.writeText(_code);
- $(_node).empty()
- $(_node).html('')
- setTimeout(function(){
- $(_node).empty()
- $(_node).html('')
- },750)
-}
\ No newline at end of file
diff --git a/cms/static/js/qcms/dialog.js b/cms/static/js/qcms/dialog.js
new file mode 100644
index 0000000..d3fcca7
--- /dev/null
+++ b/cms/static/js/qcms/dialog.js
@@ -0,0 +1,43 @@
+if (!qcms){
+ var qcms = {}
+}
+/**
+ * THIS FILE DEPENDS ON qcms.html.Common
+ */
+
+qcms.dialog = {}
+
+qcms.dialog.show = function (_args){
+
+ if (_args.uri.match(/=/)){
+ _args.uri = _args.uri.split(/=/)[1]
+ }
+ var http = HttpClient.instance()
+ http.setHeader('dom',_args.title)
+ http.setHeader('uri',_args.uri)
+ http.get(`${qcms.context}/dialog`,(x)=>{
+ $('.jxmodal').remove()
+ jx.modal.show({html:x.responseText,id:'body'})
+ if(jx.dom.exists('dialog-message') && _args.message != null){
+ jx.dom.set.value('dialog-message',_args.message)
+ }
+ //-- are there scripts in the modal window
+ var scripts = $('.jxmodal script')
+ scripts.each((_index)=>{
+ var _code = $(scripts)[_index].text
+ eval(_code)
+ })
+ })
+
+
+
+
+
+}
+
+
+
+//
+// Make a proxy for backward compatibility (not everything was prefixed by qcms)
+//
+var dialog = qcms.dialog
diff --git a/cms/static/js/qcms/menu.js b/cms/static/js/qcms/menu.js
new file mode 100644
index 0000000..95bdf19
--- /dev/null
+++ b/cms/static/js/qcms/menu.js
@@ -0,0 +1,234 @@
+/**
+ * This file implements 2 types of menus (basic roll down and tabs), they are implemented as objects given
+ */
+if (!qcms){
+ var qcms = {}
+}
+qcms.menu = {}
+qcms.menu.Common = function (){
+ this._format = function (text){
+ return text.replace(/(-|_)/g,' ').trim()
+ }
+ this._open = function (text,uri,_parentId){
+ var _domId = text.replace(/ /g,'-')
+ var http = HttpClient.instance()
+ http.setHeader('dom',_domId)
+ http.setHeader('uri',uri)
+ http.post(`${qcms.context}/page`,(x)=>{
+ //
+ // @TODO: In case of an error
+ var _dom = $(x.responseText)
+ if($(`${_parentId} #${_domId}`).length){
+ $(`${_parentId} #${_domId}`).remove()
+ }
+ var _found = qcms.html.hasNode ($(`${_parentId}`),$(_domId))
+ if (_found == 0){
+ $(`${_parentId}`).children().slideUp('fast',()=>{
+ $(`${_parentId}`).append(_dom)
+ this._finalize(`${_parentId} #${_domId}`)
+
+ })
+ }
+
+
+ })
+ }
+ this._finalize = function (_id){
+ var _script = $(`${_id} script`)
+
+ if (_script.lenth > 0){
+ _script.each( (_index)=>{
+ var _code = $(_script)[_index].text
+ eval(_code)
+ })
+ }
+ }
+}
+qcms.menu.Basic = function (_layout,_outputId,_domId){
+ qcms.menu.Common.call(this)
+ this._layout = _layout
+ this._parentId = _outputId //-- target of the output
+
+ this.init = function (){}
+ this._build = function (_items){
+ var _panes = []
+ var _context = this._context ;
+ var _open = this._open
+ var _parentId = this._parentId
+ // var _format = this._format
+ // var _finalize = this._finalize
+ // var _domId = this._domId
+ var _me = this ;
+ _items.forEach(_item=>{
+ var _div = jx.dom.get .instance('DIV')
+
+ _div.innerHTML = this._format(_item.text)
+
+ //
+ // We need to check for the override text and see if it goes here
+ _div.className = 'active'
+ _div.data = _item
+ _panes.push(_div)
+ $(_div).on('click', function (){
+ //
+ // how do we process this ...
+ if (this.data.type == 'redirect') {
+ window.open(this.data.url,_me._format(this.data.text))
+ }else if (this.data.type == 'dialog'){
+ qcms.dialog.show(this.data)
+
+ }else if (this.data.type == 'open'){
+ window.open(this.data.uri,'_self')
+ }else{
+ _me._open(_me._format(this.data.text),this.data.uri,_parentId)
+
+ }
+ // if(this.data.uri && this.data.type != 'open') {
+
+ // if (this.data.type == 'dialog') {
+ // qcms.dialog.show(this.data)
+ // }else{
+ // _me._open(_me._format(this.data.text),this.data.uri,_parentId)
+ // }
+
+ // }else{
+
+ // //
+ // // redirecting
+ // if (this.data.uri != null){
+ // window.open(this.data.uri,'_self')
+ // }else{
+ // window.open(this.data.url,_format(this.data.text))
+ // }
+ // }
+ })
+
+
+ })
+ return _panes ;
+ }
+
+ /**
+ * This part builds the menu automatically
+ */
+ var _names = _layout.order.menu.length > 0 ? _layout.order.menu : Object.keys(_layout.menu)
+ _names.forEach ((_name)=>{
+ var _div = this._build(_layout.menu[_name]) ;
+
+
+ var _sub = jx.dom.get.instance('DIV')
+ var _menuItem = jx.dom.get.instance('DIV')
+ _menuItem.innerHTML = this._format (_name)
+ _sub.className = 'sub-menu border-round border '
+ _menuItem.className = 'item'
+ _div.forEach(_item=>{$(_sub).append(_item) })
+ $(_sub).append(_div)
+ _menuItem.appendChild(_sub)
+ _domId = (_domId == null || $(_domId).length == 0)?'.main .menu' : _domId
+ $(`${_domId}`).append(_menuItem)
+
+ })
+}
+
+/**
+ * Implementing Tab based menu
+ */
+qcms.menu.Tabs = function (_layout,_outputId,_domId){
+ qcms.menu.Common.call(this) //-- inheriting format and open functions
+ this._layout = _layout
+ this._parentId = _outputId //-- target of the output
+ this._domId = _domId
+ this.tabs = jx.dom.get.instance('DIV')
+ this.tabs.className = 'tabs'
+ this._context = qcms.context
+
+
+ this._build = function (text,_item,event){
+ var text = text.trim().replace(/(_|-)/ig,' ').trim()
+ var _context = this._context;
+ if (text.match(/\//)){
+ text = text.split(/\//g).slice(-1)[0]
+ }
+ var _button = jx.dom.get.instance('INPUT')
+ var _label = jx.dom.get.instance('LABEL')
+ _button.type= 'radio'
+ _button.id = text+'tab'
+ _button.name = 'menu-tabs'
+
+ _label.data = {id:text.toLowerCase(),uri:_item[0].uri}
+
+ if (this._layout.icon){
+ var _icon = jx.dom.get.instance('I')
+ _icon.className = this._layout.icons[text]
+ $(_label).append(_icon)
+ }
+
+ text = ' ' + text
+
+ $(_label).append(text)
+ $(_button).val(text.toLowerCase())
+ _label.htmlFor = _button.id
+ // var _open = this._open
+ // var _parentId = this._parentId
+ var _me = this ;
+ $(_label).on('click',function (){
+
+ // _me._open(this.data.id,this.data.uri,_me._parentId)
+ _me._open(_me._format(this.data.text),this.data.uri,_parentId)
+ })
+
+ return [_button,_label]
+ }
+
+
+ var _names = _layout.order.menu.length > 0 ? _layout.order.menu : Object.keys(_layout.menu)
+ // Object.keys(_layout.menu).
+ _names.forEach(function(_text){
+ _item = _layout.menu[_text]
+ _tabItem = this._build(_text,_item)
+
+ $(tabs).append(_tabItem)
+ })
+
+ this.tabs.className = 'tabs'
+ $(this._domId).append(this.tabs)
+ $(this._domId).css({'border':'1px solid transparent'})
+ $(this._domId).css({'grid-template-columns':'64px auto'})
+
+}
+
+qcms.menu.init = function(_layout){
+ if (_layout.order != null){
+ if (_layout.order.length == null && _layout.order.menu == null){
+ _layout.order = {menu:[]}
+
+ }else if (_layout.order.menu == null){
+ _layout.order.menu = []
+ }
+ }else{
+ _layout.order = {menu:[]}
+ }
+
+
+ var _count = 0
+ var _items = 0
+ Object.keys(_layout.menu).forEach(_name=>{
+ _items += _layout.menu[_name].length
+ _count += 1
+ })
+
+ if (_count == _items){
+ var _menuObject = new qcms.menu.Tabs (_layout,'.main #content','.main .menu')
+ }else{
+ var _menuObject = new qcms.menu.Basic (_layout,'.main #content','.main .menu')
+ }
+
+
+}
+
+//
+// backward compatibility ...
+if(!menu){
+ var menu = {}
+}
+menu.init = qcms.menu.init
\ No newline at end of file
diff --git a/cms/static/js/qcms/page-loader.js b/cms/static/js/qcms/page-loader.js
new file mode 100644
index 0000000..b778e7b
--- /dev/null
+++ b/cms/static/js/qcms/page-loader.js
@@ -0,0 +1,86 @@
+if(!qcms){
+ var qcms = {}
+}
+qcms.page = {}
+qcms.page.Observer = function (_parentId,_domId,_uri){
+ this._parentId = _parentId == null?'':_parentId
+ this._domId = _domId
+ this._uri = _uri
+ this.finalize = function(_id){
+ var _script = $(`${_id} script`)
+
+ if (_script.lenth > 0){
+ _script.each( (_index)=>{
+ var _code = $(_script)[_index].text
+ if (_code){eval(_code)}
+
+ })
+ }
+ }
+ this.apply = function (_caller){
+ _uri = this._uri
+ _finalize = this.finalize
+ _domId = this._domId
+
+ var _id = `${this._parentId} #${this._domId}`.trim()
+
+ var http = HttpClient.instance()
+ http.setHeader('dom',this._domId)
+ http.setHeader('uri',this._uri)
+ var _uri = this._uri
+ http.post(`${qcms.context}/page`,function(x){
+
+ var _dom = $(x.responseText)
+ var _found = qcms.html.hasNode( $(_id), $(_dom))
+
+ if (_found == 0){
+
+
+ $(_id).append (_dom)
+ _finalize(_id)
+
+ }
+ _caller.notify()
+ })
+
+
+
+
+ }
+
+
+}
+qcms.page.loader = function(_parentId,_layout){
+
+ if (_parentId.constructor == Object) {
+ _layout = _parentId
+ _parentId = null
+ }
+ if (!_layout) {
+ return ;
+ }
+
+ if (_layout.on){
+ jx.utils.keys(_layout.on.load).forEach(function(_domId){
+
+ var observers =
+ jx.utils.patterns.visitor(_layout.on.load[_domId], function(_uri){
+ _uri = _layout.root_prefix != null? (_layout.root_prefix+_uri) : _uri
+
+ return new qcms.page.Observer(_parentId,_domId,_uri)
+ })
+
+ jx.utils.patterns.observer(observers,'apply')
+
+
+ })
+ }
+}
+
+//
+// making backwards compatibility
+if(!bootup){
+ var bootup = {}
+}
+bootup.init =qcms.page.loader
+
diff --git a/cms/static/js/qcms/qcms.js b/cms/static/js/qcms/qcms.js
new file mode 100644
index 0000000..da68da1
--- /dev/null
+++ b/cms/static/js/qcms/qcms.js
@@ -0,0 +1,23 @@
+if (!qcms){
+ var qcms = {}
+}
+
+qcms.html = {}
+qcms.html.hasNode = function (_parent,_child){
+ var _found = 0
+ if ($(_child).length == 0){
+ return 0
+ }
+ $(_parent).each((_index)=>{
+ var _node = $(_parent)[_index]
+
+ if ( $(_node)[0].innerHTML == $(_child)[0].outerHTML){
+ _found = 1
+ }
+
+ })
+
+ return _found
+
+}
+
diff --git a/cms/static/js/search.js b/cms/static/js/search.js
index 10d33cc..8f3ad1d 100644
--- a/cms/static/js/search.js
+++ b/cms/static/js/search.js
@@ -1,14 +1,33 @@
-var Search = function(_searchBoxId,_paneId,_bind){
+// var Search = function(_searchBoxId,_paneId,_bind){
+// var _text = jx.dom.get.value(_searchBoxId)
+// _regex = new RegExp(_text.toLowerCase())
+// _paneId = (_paneId[0] == '#')?_paneId:('#'+_paneId)
+// $(_paneId).slideUp()
+// (_paneId).children().each(_index=>{
+// _div = $(_paneId).children()[_index]
+// if (_div.html().match(_regex)){
+// $(_div).slideDown()
+// }
+// })
+
+
+// }
+
+if (!qcms) {
+ var qcms = {}
+}
+qcms.search = function(_searchBoxId,_paneId,_bind){
var _text = jx.dom.get.value(_searchBoxId)
- _regex = new RegExp(_text.toLowerCase())
- _paneId = (_paneId['#'])?_paneId:('#'+_paneId)
- $(_paneId).slideUp()
- (_paneId).children().each(_index=>{
+ _regex = new RegExp(_text.toLowerCase().trim())
+ _paneId = (_paneId[0] == '#')?_paneId:('#'+_paneId)
+ // $(_paneId).children().css({display:'none'})
+ var found = 0
+ $(_paneId).children().each(_index=>{
_div = $(_paneId).children()[_index]
- if (_div._data.match(_regex)){
+ if ($(_div).html().toLowerCase().match(_regex)){
$(_div).slideDown()
+ }else{
+ $(_div).css({display:'none'})
}
- })
-
-
+ })
}
\ No newline at end of file
diff --git a/cms/templates/index.html b/cms/templates/index.html
index c08f957..7a41cf8 100644
--- a/cms/templates/index.html
+++ b/cms/templates/index.html
@@ -56,7 +56,10 @@ Vanderbilt University Medical Center
-
+
+
+
+
@@ -64,10 +67,10 @@ Vanderbilt University Medical Center
-
+
-
-
+
+
@@ -75,12 +78,17 @@ Vanderbilt University Medical Center
// sessionStorage.setItem('{{system.id}}','{{system.context|safe}}')
var _layout = {{layout|tojson}}
-
+ // if (!qcms){
+ // var qcms = {}
+ // }
+ qcms.context = '{{system.context}}'
+ // dialog.context = '{{system.context}}'
//sessionStorage.setItem('{{system.id}}','{{system.context|safe}}')
$(document).ready( function(){
bootup.init('{{system.id}}',_layout)
- menu.init({{layout|tojson}},'{{system.context}}')
+ // menu.init({{layout|tojson}},'{{system.context}}')
+ qcms.menu.init({{layout|tojson}})
})
diff --git a/cms/templates/menu.html b/cms/templates/menu.html
index 6fe5964..4a16155 100644
--- a/cms/templates/menu.html
+++ b/cms/templates/menu.html
@@ -5,10 +5,12 @@
{% else %}
{% set _backURI = system.parentContext%}
{% endif %}
-