mirror of http://localhost:9400/cloud/cms
				
				
				
			
							parent
							
								
									8b119a7133
								
							
						
					
					
						commit
						9b035b9950
					
				@ -0,0 +1,28 @@
 | 
				
			|||||||
 | 
					"""
 | 
				
			||||||
 | 
					This file handles all things configuration i.e even the parts of the configuration we are interested in
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					import os
 | 
				
			||||||
 | 
					import json
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def get (path) :
 | 
				
			||||||
 | 
					    if os.path.exists(path) :
 | 
				
			||||||
 | 
					        f = open(path) 
 | 
				
			||||||
 | 
					        _conf = json.loads(f.read())
 | 
				
			||||||
 | 
					        f.close()
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        _conf = {}
 | 
				
			||||||
 | 
					    return _conf
 | 
				
			||||||
 | 
					def _isvalid(_allowed,**_args):
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    if not list(set(_allowed) - set(_args.keys())) :
 | 
				
			||||||
 | 
					        _pargs = {}
 | 
				
			||||||
 | 
					        for key in _allowed :
 | 
				
			||||||
 | 
					            _pargs [key] = _args[key]
 | 
				
			||||||
 | 
					        return _pargs
 | 
				
			||||||
 | 
					    return False
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					def write(_config, path):
 | 
				
			||||||
 | 
					    f = open(path,'w')
 | 
				
			||||||
 | 
					    f.write( json.dumps(_config)) ;
 | 
				
			||||||
 | 
					    f.close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -0,0 +1,77 @@
 | 
				
			|||||||
 | 
					"""
 | 
				
			||||||
 | 
					This file handles the structure (strict) of the configuration file,
 | 
				
			||||||
 | 
					Not all elements are programmatically editable (for now)
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					import meta
 | 
				
			||||||
 | 
					class Section :
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def build (self,**_args):
 | 
				
			||||||
 | 
					        _data = {}
 | 
				
			||||||
 | 
					        for _attr in dir(self):
 | 
				
			||||||
 | 
					            if not _attr.startswith('_') and _attr not in ['build','update']:
 | 
				
			||||||
 | 
					                _kwargs = _args if _attr not in _args or type(_args[_attr]) !=dict else _args[_attr]
 | 
				
			||||||
 | 
					                _data[_attr] = getattr(self,_attr)(**_kwargs)
 | 
				
			||||||
 | 
					        _name =  type (self).__name__.lower()
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        return {_name:_data }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					    def update(self,_default,**_args) :
 | 
				
			||||||
 | 
					        for _attr in _default.keys():
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            if _attr in _args :
 | 
				
			||||||
 | 
					                _default[_attr] = _args[_attr]
 | 
				
			||||||
 | 
					        return _default
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					class System (Section) :
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def logo(self,**_args):
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        return 'www/html/_assets/images/logo.png' if 'logo' not in _args else _args['logo']
 | 
				
			||||||
 | 
					    def theme (self,**_args):
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        setting the theme given the name of the theme
 | 
				
			||||||
 | 
					        :name name of the theme to set (optional)
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        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']
 | 
				
			||||||
 | 
					    def context (self,**_args):
 | 
				
			||||||
 | 
					        return "" if 'context' not in _args else _args['context']
 | 
				
			||||||
 | 
					    def app (self,**_args):
 | 
				
			||||||
 | 
					        _data = {'debug':True,'port':8084,'threaded':True,'host':'0.0.0.0'}
 | 
				
			||||||
 | 
					        return self.update(_data,**_args)
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					    def source(self,**_args):
 | 
				
			||||||
 | 
					        _data = {'id':'disk'}
 | 
				
			||||||
 | 
					        if set(['key','auth']) & set(_args.keys()):
 | 
				
			||||||
 | 
					            #
 | 
				
			||||||
 | 
					            # key: reboot the app & auth: for cloud access
 | 
				
			||||||
 | 
					            #
 | 
				
			||||||
 | 
					            for _attr in ['key','auth'] :
 | 
				
			||||||
 | 
					                if _attr in _args:
 | 
				
			||||||
 | 
					                    _data[_attr] = _args[_attr]
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        _data = self.update(_data,**_args)
 | 
				
			||||||
 | 
					        return _data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Layout (Section):
 | 
				
			||||||
 | 
					    def index (self,**_args):
 | 
				
			||||||
 | 
					        return "index.html" if 'index' not in _args else _args['index']
 | 
				
			||||||
 | 
					    def root(self,**_args):
 | 
				
			||||||
 | 
					        return 'wwww/html' if 'root' not in _args else _args['root']
 | 
				
			||||||
 | 
					    def footer(self,**_args):
 | 
				
			||||||
 | 
					        return [{'text':'Powered by QCMS'}] if 'footer' not in _args else _args['footer']
 | 
				
			||||||
 | 
					    def on(self,**_args):
 | 
				
			||||||
 | 
					        return {'load':{}} if 'on' not in _args else _args['on']
 | 
				
			||||||
 | 
					    def order(self,**_args):
 | 
				
			||||||
 | 
					        return {'menu':[]} if 'order' not in _args else _args['order']
 | 
				
			||||||
 | 
					    # def menu (self,**_args):
 | 
				
			||||||
 | 
					    #     return {'menu':[]} if 'menu' not in _args else _args['menu']
 | 
				
			||||||
 | 
					    def overwrite(self,**_args):
 | 
				
			||||||
 | 
					        return {}
 | 
				
			||||||
 | 
					    def header (self,**_args):
 | 
				
			||||||
 | 
					        _data =  {"title":"QCMS Project", "subtitle":"Powered by Python Flask"}
 | 
				
			||||||
 | 
					        return self.update(_data,**_args)
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
@ -0,0 +1,42 @@
 | 
				
			|||||||
 | 
					import json
 | 
				
			||||||
 | 
					import pandas as pd
 | 
				
			||||||
 | 
					import importlib
 | 
				
			||||||
 | 
					import importlib.util
 | 
				
			||||||
 | 
					import os
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def stats (_config) :
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    Returns the statistics of the plugins
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    _data = []
 | 
				
			||||||
 | 
					    for _name in _config :
 | 
				
			||||||
 | 
					        _log = {"files":_name,"loaded":len(_config[_name]),"logs":json.dumps(_config[_name])}
 | 
				
			||||||
 | 
					        _data.append(_log)
 | 
				
			||||||
 | 
					    return pd.DataFrame(_data)
 | 
				
			||||||
 | 
					    pass
 | 
				
			||||||
 | 
					def load(_path,_filename,_name) :
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    This function will load external module form a given location and return a pointer to a function in a given module
 | 
				
			||||||
 | 
					    :path   absolute path of the file (considered plugin) to be loaded
 | 
				
			||||||
 | 
					    :name   name of the function to be applied
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    # _path = _args['path'] #os.sep.join([_args['root'],'plugin'])
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    if os.path.isdir(_path):
 | 
				
			||||||
 | 
					        files = os.listdir(_path)
 | 
				
			||||||
 | 
					        if files :
 | 
				
			||||||
 | 
					            files = [name for name in files if name.endswith('.py') and name == _filename]
 | 
				
			||||||
 | 
					            if files:
 | 
				
			||||||
 | 
					                _path = os.sep.join([_path,files[0]])
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                return None
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            return None
 | 
				
			||||||
 | 
					    #-- We have a file ...  
 | 
				
			||||||
 | 
					    # _name = _args['name']
 | 
				
			||||||
 | 
					    spec = importlib.util.spec_from_file_location(_filename, _path)
 | 
				
			||||||
 | 
					    module = importlib.util.module_from_spec(spec)
 | 
				
			||||||
 | 
					    spec.loader.exec_module(module)
 | 
				
			||||||
 | 
					    return getattr(module,_name) if hasattr(module,_name) else None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
											
												
													File diff suppressed because one or more lines are too long
												
											
										
									
								@ -0,0 +1,44 @@
 | 
				
			|||||||
 | 
					"""
 | 
				
			||||||
 | 
					This class implements the base infrastructure to handle themes, the class must leverage
 | 
				
			||||||
 | 
					default themes will be stored in layout.root._assets.themes, The expected files in a theme are the following:
 | 
				
			||||||
 | 
					    - borders
 | 
				
			||||||
 | 
					    - buttons
 | 
				
			||||||
 | 
					    - layout
 | 
				
			||||||
 | 
					    - menu
 | 
				
			||||||
 | 
					    - header
 | 
				
			||||||
 | 
					If the following are not available then we should load the default one. 
 | 
				
			||||||
 | 
					This would avoid crashes but would come at the expense of a lack of consistent visual layout (alas)
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					import requests
 | 
				
			||||||
 | 
					import os
 | 
				
			||||||
 | 
					URL = os.environ['QCMS_HOME_URL'] if 'QCMS_HOME_URL' in os.environ else 'https://dev.the-phi.com/qcms'
 | 
				
			||||||
 | 
					def current (_system) :
 | 
				
			||||||
 | 
					    return _system['theme']
 | 
				
			||||||
 | 
					def List (_url = URL) :
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    calling qcms to list the available URL
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    try:
 | 
				
			||||||
 | 
					        _url = '/'.join([_url,'api','themes','List'])
 | 
				
			||||||
 | 
					        return requests.get(_url).json()
 | 
				
			||||||
 | 
					    except Exception as e:
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        pass
 | 
				
			||||||
 | 
					    return []
 | 
				
			||||||
 | 
					def Get(theme,_url= URL) :
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    This function retrieves a particular theme from a remote source
 | 
				
			||||||
 | 
					    The name should be in the list provided by the above function
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    try:
 | 
				
			||||||
 | 
					        _url = '/'.join([_url,'api','themes','Get']) +f'?theme={theme}'
 | 
				
			||||||
 | 
					        return requests.get(_url).json()
 | 
				
			||||||
 | 
					    except Exception as e:
 | 
				
			||||||
 | 
					        pass
 | 
				
			||||||
 | 
					    return {}
 | 
				
			||||||
 | 
					def installed (path):
 | 
				
			||||||
 | 
					    return os.listdir(os.sep.join([path,'_assets','themes']))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def Set(theme,_system) :
 | 
				
			||||||
 | 
					    _system['theme'] = theme
 | 
				
			||||||
 | 
					    return _system
 | 
				
			||||||
@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					.dialog-title {
 | 
				
			||||||
 | 
					    background-color:#FF6500;color:#FFFFFF;
 | 
				
			||||||
 | 
					    text-transform:capitalize; font-weight:bold; align-items:center;display:grid; grid-template-columns:auto 32px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.dialog-button {
 | 
				
			||||||
 | 
					    display:grid;
 | 
				
			||||||
 | 
					    grid-template-columns: auto 115px;
 | 
				
			||||||
 | 
					    gap:4px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,18 @@
 | 
				
			|||||||
 | 
					.source-code {
 | 
				
			||||||
 | 
					    background-color: #000000; COLOR:#ffffff;  
 | 
				
			||||||
 | 
					    font-family: 'Courier New', Courier, monospace;
 | 
				
			||||||
 | 
					    padding:8px;
 | 
				
			||||||
 | 
					    padding-left:10px;
 | 
				
			||||||
 | 
					    text-wrap: wrap;
 | 
				
			||||||
 | 
					    width:calc(100% - 40px);
 | 
				
			||||||
 | 
					    border-left:8px solid #CAD5E0; margin-left:10px; font-weight: bold;
 | 
				
			||||||
 | 
					    font-size:14px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.editor {
 | 
				
			||||||
 | 
					    background-color:#f3f3f3;
 | 
				
			||||||
 | 
					    color:#000000;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.editor .keyword {color: #4682b4; font-weight:bold}
 | 
				
			||||||
 | 
					.code-comment { font-style: italic; color:gray; font-size:13px;}
 | 
				
			||||||
					Loading…
					
					
				
		Reference in new issue