From 515fb1a997e29f583b147bc8eff2c531975c6448 Mon Sep 17 00:00:00 2001 From: Steve Nyemba Date: Thu, 24 Jul 2025 09:32:29 -0500 Subject: [PATCH 01/11] dependency handling --- cms/engine/config/structure.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) 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 + From 74e0e2faf93123d84fd0811a3e445e47e02c1158 Mon Sep 17 00:00:00 2001 From: Steve Nyemba Date: Thu, 24 Jul 2025 09:33:04 -0500 Subject: [PATCH 02/11] dependency clean up --- cms/index.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cms/index.py b/cms/index.py index 96ce449..f83e5a7 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 From 588e7897f4f82b9ed1e07ba198493bd6c403a5e7 Mon Sep 17 00:00:00 2001 From: Steve Nyemba Date: Thu, 24 Jul 2025 09:36:05 -0500 Subject: [PATCH 03/11] dependency clean up --- cms/engine/project/__init__.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) 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__}

From 015c981373e8989336a8dc89cbfdf08f49f54598 Mon Sep 17 00:00:00 2001 From: Steve Nyemba Date: Thu, 24 Jul 2025 10:18:14 -0500 Subject: [PATCH 04/11] bug fix, qcms.context --- cms/templates/index.html | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/cms/templates/index.html b/cms/templates/index.html index c08f957..05b47fa 100644 --- a/cms/templates/index.html +++ b/cms/templates/index.html @@ -75,7 +75,10 @@ Vanderbilt University Medical Center // sessionStorage.setItem('{{system.id}}','{{system.context|safe}}') var _layout = {{layout|tojson}} - + if (!qcms){ + var qcms = {} + } + qcms.context = '{{system.context}}' //sessionStorage.setItem('{{system.id}}','{{system.context|safe}}') $(document).ready( function(){ From 1e9d925f98e296d4addf6c99092a38ca0fb83f05 Mon Sep 17 00:00:00 2001 From: Steve Nyemba Date: Thu, 24 Jul 2025 11:05:08 -0500 Subject: [PATCH 05/11] bug fixes, print and search code js --- cms/index.py | 2 +- cms/static/js/search.js | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/cms/index.py b/cms/index.py index f83e5a7..d11ba06 100644 --- a/cms/index.py +++ b/cms/index.py @@ -95,7 +95,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("//") diff --git a/cms/static/js/search.js b/cms/static/js/search.js index 10d33cc..8cdeaea 100644 --- a/cms/static/js/search.js +++ b/cms/static/js/search.js @@ -5,10 +5,15 @@ var Search = function(_searchBoxId,_paneId,_bind){ $(_paneId).slideUp() (_paneId).children().each(_index=>{ _div = $(_paneId).children()[_index] - if (_div._data.match(_regex)){ + if (_div.html().match(_regex)){ $(_div).slideDown() } }) -} \ No newline at end of file +} + +if (!qcms) { + var qcms = {} +} +qcms.search = Search \ No newline at end of file From 89b52700c3a090b1710ebf39473428617835af5f Mon Sep 17 00:00:00 2001 From: Steve Nyemba Date: Thu, 24 Jul 2025 11:34:51 -0500 Subject: [PATCH 06/11] bug fix: js search, --- cms/static/js/search.js | 40 +++++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/cms/static/js/search.js b/cms/static/js/search.js index 8cdeaea..8f3ad1d 100644 --- a/cms/static/js/search.js +++ b/cms/static/js/search.js @@ -1,19 +1,33 @@ -var 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=>{ - _div = $(_paneId).children()[_index] - if (_div.html().match(_regex)){ - $(_div).slideDown() - } - }) +// 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 = Search \ No newline at end of file +qcms.search = function(_searchBoxId,_paneId,_bind){ + var _text = jx.dom.get.value(_searchBoxId) + _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).html().toLowerCase().match(_regex)){ + $(_div).slideDown() + }else{ + $(_div).css({display:'none'}) + } + }) +} \ No newline at end of file From 373690c10a5a15d978241e8f4f2ef62eabdf0afb Mon Sep 17 00:00:00 2001 From: Steve Nyemba Date: Thu, 21 Aug 2025 15:45:10 -0500 Subject: [PATCH 07/11] refactored: menu/tabs, bootup and dialog --- cms/__init__.py | 6 +- cms/index.py | 1 + cms/static/js/bootup.js | 87 ------ cms/static/js/dialog.js | 44 --- cms/static/js/menu.js | 449 ------------------------------ cms/static/js/qcms/dialog.js | 43 +++ cms/static/js/qcms/menu.js | 221 +++++++++++++++ cms/static/js/qcms/page-loader.js | 77 +++++ cms/static/js/qcms/qcms.js | 44 +++ cms/templates/index.html | 21 +- 10 files changed, 404 insertions(+), 589 deletions(-) delete mode 100644 cms/static/js/bootup.js delete mode 100644 cms/static/js/dialog.js delete mode 100644 cms/static/js/menu.js create mode 100644 cms/static/js/qcms/dialog.js create mode 100644 cms/static/js/qcms/menu.js create mode 100644 cms/static/js/qcms/page-loader.js create mode 100644 cms/static/js/qcms/qcms.js 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/index.py b/cms/index.py index d11ba06..df91057 100644 --- a/cms/index.py +++ b/cms/index.py @@ -167,6 +167,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/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..bc7bda1 --- /dev/null +++ b/cms/static/js/qcms/menu.js @@ -0,0 +1,221 @@ +/** + * 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() + } + $(`${_parentId}`).children().slideUp('fast',()=>{ + $(`${_parentId}`).append(_dom) + + this._finalize(`${_parentId} #${_domId}`) + // + // we should finalize the scripts + + }) + + + }) + } + 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.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) + }) + + return [_button,_label] + } + + + 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 = this._build(_key,_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..1412b6d --- /dev/null +++ b/cms/static/js/qcms/page-loader.js @@ -0,0 +1,77 @@ +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}` + + var http = HttpClient.instance() + http.setHeader('dom',this._domId) + http.setHeader('uri',this._uri) + + http.post(`${qcms.context}/page`,function(x){ + var _dom = $(x.responseText) + $(_id).append (_dom) + + _finalize(_id) + + _caller.notify() + // // console.log(['*** ',_uri, ' on ',_domId]) + }) + + + + + } + + +} +qcms.page.loader = function(_parentId,_layout){ + // console.log(_parentId,_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 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..1f0a3b0 --- /dev/null +++ b/cms/static/js/qcms/qcms.js @@ -0,0 +1,44 @@ +if (!qcms){ + var qcms = {} +} + +qcms.html = {} +qcms.html.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() + } + $(`${_parentId}`).children().slideUp('fast',()=>{ + $(`${_parentId}`).append(_dom) + + this._finalize(`${_parentId} #${_domId}`) + // + // we should finalize the scripts + + }) + + + }) + } + this._finalize = function (_id){ + var _script = $(`${_id} script`) + + if (_script.lenth > 0){ + _script.each( (_index)=>{ + var _code = $(_script)[_index].text + eval(_code) + }) + } + } +} \ No newline at end of file diff --git a/cms/templates/index.html b/cms/templates/index.html index 05b47fa..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,15 +78,17 @@ Vanderbilt University Medical Center // sessionStorage.setItem('{{system.id}}','{{system.context|safe}}') var _layout = {{layout|tojson}} - if (!qcms){ - var qcms = {} - } + // 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}}) }) From 76b35b49a76a987c7c64e434fd91b854964bc77d Mon Sep 17 00:00:00 2001 From: Steve Nyemba Date: Thu, 21 Aug 2025 15:45:47 -0500 Subject: [PATCH 08/11] version update --- cms/meta/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cms/meta/__init__.py b/cms/meta/__init__.py index 83083b8..8a04cf9 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.2.24" __email__ = "steve@the-phi.com" __license__=""" Copyright 2010 - 2024, Steve L. Nyemba, Vanderbilt University Medical Center From 1b3a458b239b0a350641abb4b07b40460c865a90 Mon Sep 17 00:00:00 2001 From: Steve Nyemba Date: Sat, 23 Aug 2025 11:57:10 -0500 Subject: [PATCH 09/11] bug fix: menu handling (tabs, window open) --- bin/qcms | 2 +- cms/disk.py | 6 ++++ cms/static/js/qcms/menu.js | 52 ++++++++++++++++++++----------- cms/static/js/qcms/page-loader.js | 18 ++++++----- 4 files changed, 51 insertions(+), 27 deletions(-) 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/cms/disk.py b/cms/disk.py index 74b1a0a..917a191 100644 --- a/cms/disk.py +++ b/cms/disk.py @@ -69,6 +69,12 @@ def _realpath (uri,_config) : _layout = _config['layout'] _uri = copy.copy(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:]) + print (' *********************************** ') + _uri = os.sep.join([_layout['location'],_uri]) return _uri diff --git a/cms/static/js/qcms/menu.js b/cms/static/js/qcms/menu.js index bc7bda1..14e0209 100644 --- a/cms/static/js/qcms/menu.js +++ b/cms/static/js/qcms/menu.js @@ -72,23 +72,36 @@ qcms.menu.Basic = function (_layout,_outputId,_domId){ $(_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) + 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{ - _me._open(_me._format(this.data.text),this.data.uri,_parentId) - } + }else if (this.data.type == 'open'){ + window.open(this.data.uri,'_self') }else{ - // - // redirecting - if (this.data.uri != null){ - window.open(this.data.uri,'_self') - }else{ - window.open(this.data.url,_format(this.data.text)) - } + _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)) + // } + // } }) @@ -160,8 +173,10 @@ qcms.menu.Tabs = function (_layout,_outputId,_domId){ // var _parentId = this._parentId var _me = this ; $(_label).on('click',function (){ - - _me._open(this.data.id,this.data.uri,_me._parentId) + alert('....') + // _me._open(this.data.id,this.data.uri,_me._parentId) + console.log([_me._format(this.data.text),this.data.uri,_parentId]) + _me._open(_me._format(this.data.text),this.data.uri,_parentId) }) return [_button,_label] @@ -170,10 +185,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). - _names.forEach(function(_key){ - _item = _layout.menu[_key] + _names.forEach(function(_text){ + _item = _layout.menu[_text] // console.log([_item]) - _tabItem = this._build(_key,_item) + _tabItem = this._build(_text,_item) + $(tabs).append(_tabItem) }) diff --git a/cms/static/js/qcms/page-loader.js b/cms/static/js/qcms/page-loader.js index 1412b6d..b55baad 100644 --- a/cms/static/js/qcms/page-loader.js +++ b/cms/static/js/qcms/page-loader.js @@ -22,20 +22,18 @@ qcms.page.Observer = function (_parentId,_domId,_uri){ _finalize = this.finalize _domId = this._domId - var _id = `${this._parentId} #${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) $(_id).append (_dom) - - _finalize(_id) - - _caller.notify() - // // console.log(['*** ',_uri, ' on ',_domId]) + _finalize(_id) + _caller.notify() }) @@ -46,7 +44,11 @@ qcms.page.Observer = function (_parentId,_domId,_uri){ } qcms.page.loader = function(_parentId,_layout){ - // console.log(_parentId,_layout) + + if (_parentId.constructor == Object) { + _layout = _parentId + _parentId = null + } if (!_layout) { return ; } From 5180838e1854fe22ec88e519440165c907658b39 Mon Sep 17 00:00:00 2001 From: Steve Nyemba Date: Fri, 29 Aug 2025 13:56:23 -0500 Subject: [PATCH 10/11] bug fixes and updates (menu) and added file references --- bin/qcms.bat | 3 +- cms/disk.py | 11 +++++-- cms/index.py | 19 ++++++++++- cms/sites/__init__.py | 4 ++- cms/static/js/qcms/menu.js | 21 ++++++------ cms/static/js/qcms/page-loader.js | 11 +++++-- cms/static/js/qcms/qcms.js | 53 ++++++++++--------------------- cms/templates/menu.html | 10 +++--- 8 files changed, 70 insertions(+), 62 deletions(-) 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/disk.py b/cms/disk.py index 917a191..18cbbb3 100644 --- a/cms/disk.py +++ b/cms/disk.py @@ -68,14 +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:]) - print (' *********************************** ') _uri = os.sep.join([_layout['location'],_uri]) + return _uri def _format (uri,_config): @@ -88,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() @@ -141,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/index.py b/cms/index.py index df91057..15ec13e 100644 --- a/cms/index.py +++ b/cms/index.py @@ -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): @@ -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): 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/qcms/menu.js b/cms/static/js/qcms/menu.js index 14e0209..95bdf19 100644 --- a/cms/static/js/qcms/menu.js +++ b/cms/static/js/qcms/menu.js @@ -21,14 +21,14 @@ qcms.menu.Common = function (){ if($(`${_parentId} #${_domId}`).length){ $(`${_parentId} #${_domId}`).remove() } - $(`${_parentId}`).children().slideUp('fast',()=>{ - $(`${_parentId}`).append(_dom) - - this._finalize(`${_parentId} #${_domId}`) - // - // we should finalize the scripts - - }) + var _found = qcms.html.hasNode ($(`${_parentId}`),$(_domId)) + if (_found == 0){ + $(`${_parentId}`).children().slideUp('fast',()=>{ + $(`${_parentId}`).append(_dom) + this._finalize(`${_parentId} #${_domId}`) + + }) + } }) @@ -72,7 +72,6 @@ qcms.menu.Basic = function (_layout,_outputId,_domId){ $(_div).on('click', function (){ // // how do we process this ... - console.log(this.data) if (this.data.type == 'redirect') { window.open(this.data.url,_me._format(this.data.text)) }else if (this.data.type == 'dialog'){ @@ -173,9 +172,8 @@ qcms.menu.Tabs = function (_layout,_outputId,_domId){ // var _parentId = this._parentId var _me = this ; $(_label).on('click',function (){ - alert('....') + // _me._open(this.data.id,this.data.uri,_me._parentId) - console.log([_me._format(this.data.text),this.data.uri,_parentId]) _me._open(_me._format(this.data.text),this.data.uri,_parentId) }) @@ -187,7 +185,6 @@ qcms.menu.Tabs = function (_layout,_outputId,_domId){ // Object.keys(_layout.menu). _names.forEach(function(_text){ _item = _layout.menu[_text] - // console.log([_item]) _tabItem = this._build(_text,_item) $(tabs).append(_tabItem) diff --git a/cms/static/js/qcms/page-loader.js b/cms/static/js/qcms/page-loader.js index b55baad..b778e7b 100644 --- a/cms/static/js/qcms/page-loader.js +++ b/cms/static/js/qcms/page-loader.js @@ -31,8 +31,15 @@ qcms.page.Observer = function (_parentId,_domId,_uri){ http.post(`${qcms.context}/page`,function(x){ var _dom = $(x.responseText) - $(_id).append (_dom) - _finalize(_id) + var _found = qcms.html.hasNode( $(_id), $(_dom)) + + if (_found == 0){ + + + $(_id).append (_dom) + _finalize(_id) + + } _caller.notify() }) diff --git a/cms/static/js/qcms/qcms.js b/cms/static/js/qcms/qcms.js index 1f0a3b0..da68da1 100644 --- a/cms/static/js/qcms/qcms.js +++ b/cms/static/js/qcms/qcms.js @@ -3,42 +3,21 @@ if (!qcms){ } qcms.html = {} -qcms.html.Common = function (){ - this._format = function (text){ - return text.replace(/(-|_)/g,' ').trim() +qcms.html.hasNode = function (_parent,_child){ + var _found = 0 + if ($(_child).length == 0){ + return 0 } - 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() - } - $(`${_parentId}`).children().slideUp('fast',()=>{ - $(`${_parentId}`).append(_dom) - - this._finalize(`${_parentId} #${_domId}`) - // - // we should finalize the scripts - - }) - - - }) - } - this._finalize = function (_id){ - var _script = $(`${_id} script`) - - if (_script.lenth > 0){ - _script.each( (_index)=>{ - var _code = $(_script)[_index].text - eval(_code) - }) + $(_parent).each((_index)=>{ + var _node = $(_parent)[_index] + + if ( $(_node)[0].innerHTML == $(_child)[0].outerHTML){ + _found = 1 } - } -} \ No newline at end of file + + }) + + return _found + +} + 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 %} -
-
- - +
+
+
+ + +
{% else %} From 602d764505db6f035721860c6c1f7c3533158b61 Mon Sep 17 00:00:00 2001 From: Steve Nyemba Date: Fri, 29 Aug 2025 13:57:07 -0500 Subject: [PATCH 11/11] version update --- cms/meta/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cms/meta/__init__.py b/cms/meta/__init__.py index 8a04cf9..4e7cd7b 100644 --- a/cms/meta/__init__.py +++ b/cms/meta/__init__.py @@ -1,5 +1,5 @@ __author__ = "Steve L. Nyemba" -__version__= "2.2.24" +__version__= "2.4.0" __email__ = "steve@the-phi.com" __license__=""" Copyright 2010 - 2024, Steve L. Nyemba, Vanderbilt University Medical Center