From ec2ec1915e9c549536947ee88944c9c858407976 Mon Sep 17 00:00:00 2001 From: Brian Read Date: Thu, 25 Apr 2024 16:23:07 +0100 Subject: [PATCH] Table display working - added custom controller file --- Targets/Nfsshare-Custom.pm | 59 ++++++++++++++++ Targets/Nfsshare.pm | 106 ++++++++++++++++++---------- Targets/_nfs_TABLE.html.ep | 16 ++--- Targets/nfsshare_en.lex | 35 +++++---- Templates/controller.pm.tem | 97 +++++++++++++++++-------- Templates/custom.pm.tem | 44 ++++++++++++ Templates/html_controls.html.ep.tem | 10 --- Templates/html_controls.html.ep.xml | 6 +- nfsshare.json5 | 2 +- sm2gen-ImportJSON5.py | 89 ++++++++++++++++++----- 10 files changed, 338 insertions(+), 126 deletions(-) create mode 100644 Targets/Nfsshare-Custom.pm create mode 100644 Templates/custom.pm.tem delete mode 100644 Templates/html_controls.html.ep.tem diff --git a/Targets/Nfsshare-Custom.pm b/Targets/Nfsshare-Custom.pm new file mode 100644 index 0000000..41b9843 --- /dev/null +++ b/Targets/Nfsshare-Custom.pm @@ -0,0 +1,59 @@ +# +# Routines to be editted by the developer to provide validation for parameters +# and provison of the control data for table(s) +# +#$cdb=$main::cdb; +#$adb=$main::adb; +#$ndb=$main::ndb; +#$hdb=$main::hdb; +#$ddb=$main::ddb; + +use esmith::util; +use esmith::HostsDB; +use esmith::AccountsDB; +use esmith::NetworksDB; +use esmith::HostsDB; +use esmith::DomainsDB; + + +#The most common ones +our $cdb = esmith::ConfigDB->open() || die("Couldn't open config db"); +our $adb = esmith::AccountsDB->open() || die("Couldn't open Accounts db"); +our $ndb = esmith::NetworksDB->open() || die("Couldn't open Network db"); +our $hdb = esmith::HostsDB->open() || die("Couldn't open Hosts db"); +our $ddb = esmith::DomainsDB->open() || die("Couldn't open Domains db"); + +# Validation routines - parameters for each panel + + sub validate_PARAMS { + $ret = 'ok'; + return $ret; + } + + sub validate_TABLE { + $ret = 'ok'; + return $ret; + } + + +# Get control data for tables(s) + +sub get_ibays { + my @res; + my @ibays = $adb->ibays(); + foreach my $i (@ibays){ + my %hash = ('Name'=> $i->prop('Name'), + 'Description' => $i->prop('Description'), + 'Flag' => 1, + 'PARAMS' => 'Modify' + ); + push(@res,\%hash); + } + return \@res +} + +1; + + + + diff --git a/Targets/Nfsshare.pm b/Targets/Nfsshare.pm index 093ff16..6def024 100644 --- a/Targets/Nfsshare.pm +++ b/Targets/Nfsshare.pm @@ -13,6 +13,38 @@ package SrvMngr::Controller::Nfsshare; # Documentation: https://wiki.contribs.org/{PackageName} #---------------------------------------------------------------------- +# +# Scheme of things: +# +#main: +## +## Initial entry +## +#set initial panel +#for initial panel: +# load up _data hash with DB fields +# load up stash with pointer(s) to control fields hash(= get-)) +#render initial panel +# +#do_display +## +## Return after submit pushed on panel +## +#load up all params into local hash +# by panel: +# by param: +# validate param (return ret = ok or error message) - call validate- +# break out on error +#if validation not ok +# render back to current panel with error message in stash +#otherwise +# By panel: +# Copy back to DB any that have changed (how to easily tell if it has changed?) +# do whatever is required (inc signal_event smeserver--update?) +# set success +# call main? + + use strict; use warnings; use Mojo::Base 'Mojolicious::Controller'; @@ -41,6 +73,8 @@ our $ndb = esmith::NetworksDB->open() || die("Couldn't open Network db"); our $hdb = esmith::HostsDB->open() || die("Couldn't open Hosts db"); our $ddb = esmith::DomainsDB->open() || die("Couldn't open Domains db"); +require '/usr/share/smanager/lib/SrvMngr/Controller/Nfsshare-Custom.pm'; #The code that is to be added by the developer + sub main { my $c = shift; @@ -50,13 +84,17 @@ sub main { my $title = $c->l("nfs_NFS data share"); my $modul = ''; - $nfs_data{trt} = 'TABLE'; + $nfs_data{'trt'} = 'TABLE'; #Load any DB entries into the _data area so as they are preset in the form # which DB - my $db = $cdb; #Default to config + my $db = $cdb; #pickup local or global db or Default to config + # and table control fields + $c->stash(ibays=>get_ibays()); + + $c->stash( title => $title, modul => $modul, @@ -80,8 +118,10 @@ sub do_update { #Params are available in the hash "params" # you may use: + my @result; foreach my $key (keys %params) { my $value = $params{$key}; + push @result, { $key => $value }; $c->app->log->debug("$key: $value"); } @@ -89,48 +129,36 @@ sub do_update { my $trt = $c->param('trt') || 'TABLE' ; #hidden control on every form. my $ret = 'ok'; #Validate the parameters accordingly + my $thispanel; - if ($trt eq 'PARAMS'){ - #Validate form parameters for panel PARAMS - # and set $ret = $c->l('Error message') if invalid' - # otherwise set $ret to "ok" - if ($ret ne "ok"){ - $c->stash(error => $c->l($ret)) - } else { - #Do whatever is needed, including writing values to the DB - my $db = $cdb; #Default to config - - - } $c->stash( success => $c->l('ok message')) - } + if ($trt eq 'PARAMS'){ + #Validate form parameters for panel PARAMS + $ret = validate_PARAMS(); + $thispanel = 'PARAMS'; + } - if ($trt eq 'TABLE'){ - #Validate form parameters for panel TABLE - # and set $ret = $c->l('Error message') if invalid' - # otherwise set $ret to "ok" - if ($ret ne "ok"){ - $c->stash(error => $c->l($ret)) - } else { - #Do whatever is needed, including writing values to the DB - my $db = $cdb; #Default to config - - - } $c->stash( success => $c->l('ok message')) - } + if ($trt eq 'TABLE'){ + #Validate form parameters for panel TABLE + $ret = validate_TABLE(); + $thispanel = 'TABLE'; + } - # set nfs_data{trt} = ; - $c->stash( - title => $title, - nfs_data => \%nfs_data - # Extra data in here - repeat for each stash data entry needed for panels - ); - - $c->render("Nfsshare") + if ($ret eq "ok") { + #Do whatever is needed, including writing values to the DB + my $db = $cdb; #pickup local or global db or Default to config + + # anything else here... + $c->stash( success => $c->l("$thispanel successfull message")); + $c->stash( + title => $title, + nfs_data => \%nfs_data + # Extra data in here - repeat for each stash data entry needed for panels + ); + nfs_data{'trt'} = 'TABLE'; + $c->render("Nfsshare"); + } } -# get routines for the stash contents here. - - 1; diff --git a/Targets/_nfs_TABLE.html.ep b/Targets/_nfs_TABLE.html.ep index c0b0137..a87a4f2 100644 --- a/Targets/_nfs_TABLE.html.ep +++ b/Targets/_nfs_TABLE.html.ep @@ -17,20 +17,20 @@ - - - - + + + + % my $control_data = $self->stash('ibays'); % foreach my $row (@$control_data) { - - - - + + + + %} diff --git a/Targets/nfsshare_en.lex b/Targets/nfsshare_en.lex index d8d393c..1cd7e23 100644 --- a/Targets/nfsshare_en.lex +++ b/Targets/nfsshare_en.lex @@ -1,23 +1,22 @@ -'nfs_Set the UID.' => 'Set the UID.' -'nfs_Requests on secure ports' => 'Requests on secure ports' 'nfs_These parameters will be effective only if the share is enabled. The share is in /home/e-smith/files/ibays//files' => 'These parameters will be effective only if the share is enabled. The share is in /home/e-smith/files/ibays//files' -'nfs_Delays the disk writing' => 'Delays the disk writing' -'nfs_Information Bay name' => 'Information Bay name' -'nfs_EnableShare on local network' => 'EnableShare on local network' 'nfs_For writing permissions,allowing the root user and using insecure ports, you must configure a list of one IP per line, being part of the local network(s).' => 'For writing permissions,allowing the root user and using insecure ports, you must configure a list of one IP per line, being part of the local network(s).' -'nfs Hello TABLE' => 'Hello TABLE' -'nfs_NFS Client(s) allowed' => 'NFS Client(s) allowed' -'nfs_Error message' => 'Error message' -'nfs_Browse the parent folders' => 'Browse the parent folders' -'nfs_APPLY' => 'APPLY' -'nfs_Save' => 'Save' 'nfs_Share owner Group' => 'Share owner Group' -'nfs_File system permissions' => 'File system permissions' -'nfs_Set the uid and gid if you want all requests appear to be from one user or one group, otherwise leave blank' => 'Set the uid and gid if you want all requests appear to be from one user or one group, otherwise leave blank' -'nfs_Enable the NFS Share' => 'Enable the NFS Share' -'nfs_Write (a)synchronously' => 'Write (a)synchronously' -'nfs_ok message' => 'ok message' -'nfs Hello PARAMS' => 'Hello PARAMS' -'nfs_Set the GID.' => 'Set the GID.' 'nfs_Squash the power of users' => 'Squash the power of users' +'nfs_$thispanel successfull message' => '$thispanel successfull message' +'nfs Hello TABLE' => 'Hello TABLE' +'nfs_Set the UID.' => 'Set the UID.' +'nfs_NFS Client(s) allowed' => 'NFS Client(s) allowed' +'nfs Hello PARAMS' => 'Hello PARAMS' +'nfs_Save' => 'Save' +'nfs_Set the uid and gid if you want all requests appear to be from one user or one group, otherwise leave blank' => 'Set the uid and gid if you want all requests appear to be from one user or one group, otherwise leave blank' +'nfs_EnableShare on local network' => 'EnableShare on local network' +'nfs_Set the GID.' => 'Set the GID.' +'nfs_APPLY' => 'APPLY' 'nfs_NFS data share' => 'NFS data share' +'nfs_File system permissions' => 'File system permissions' +'nfs_Requests on secure ports' => 'Requests on secure ports' +'nfs_Write (a)synchronously' => 'Write (a)synchronously' +'nfs_Delays the disk writing' => 'Delays the disk writing' +'nfs_Enable the NFS Share' => 'Enable the NFS Share' +'nfs_Browse the parent folders' => 'Browse the parent folders' +'nfs_Information Bay name' => 'Information Bay name' diff --git a/Templates/controller.pm.tem b/Templates/controller.pm.tem index da044ae..019955b 100644 --- a/Templates/controller.pm.tem +++ b/Templates/controller.pm.tem @@ -13,6 +13,38 @@ package SrvMngr::Controller::${PackageName}; # Documentation: https://wiki.contribs.org/{PackageName} #---------------------------------------------------------------------- +# +# Scheme of things: +# +#main: +## +## Initial entry +## +#set initial panel +#for initial panel: +# load up _data hash with DB fields +# load up stash with pointer(s) to control fields hash(= get-)) +#render initial panel +# +#do_display +## +## Return after submit pushed on panel +## +#load up all params into local hash +# by panel: +# by param: +# validate param (return ret = ok or error message) - call validate- +# break out on error +#if validation not ok +# render back to current panel with error message in stash +#otherwise +# By panel: +# Copy back to DB any that have changed (how to easily tell if it has changed?) +# do whatever is required (inc signal_event smeserver--update?) +# set success +# call main? + + use strict; use warnings; use Mojo::Base 'Mojolicious::Controller'; @@ -41,6 +73,8 @@ our $ndb = esmith::NetworksDB->open() || die("Couldn't open Network db"); our $hdb = esmith::HostsDB->open() || die("Couldn't open Hosts db"); our $ddb = esmith::DomainsDB->open() || die("Couldn't open Domains db"); +require '/usr/share/smanager/lib/SrvMngr/Controller/${PackageName}-Custom.pm'; #The code that is to be added by the developer + sub main { my $c = shift; @@ -50,15 +84,18 @@ sub main { my $title = $c->l("${prefix}_${MenuDescription}"); my $modul = ''; - $$${prefix}_data{trt} = '${firstPanel}'; + $$${prefix}_data{'trt'} = '${firstPanel}'; #Load any DB entries into the _data area so as they are preset in the form # which DB - my $db = $$${db | 'cdb'}; #Default to config - - $$${prefix}_data{${dbentry}} = $db->prop('${dbentry}') || ${dbdefault} + my $db = $$${controldb | db | 'cdb'}; #pickup local or global db or Default to config + $$${prefix}_data{${dbentry}} = $db->prop('${dbentry}') || ${dbdefault}; + # and table control fields + $c->stash(${tablecontrol}=>get_${tablecontrol}()); + + $c->stash( title => $title, modul => $modul, @@ -82,8 +119,10 @@ sub do_update { #Params are available in the hash "params" # you may use: + my @result; foreach my $key (keys %params) { my $value = $params{$key}; + push @result, { $key => $value }; $c->app->log->debug("$key: $value"); } @@ -91,37 +130,33 @@ sub do_update { my $trt = $c->param('trt') || '${firstPanel}' ; #hidden control on every form. my $ret = 'ok'; #Validate the parameters accordingly - - if ($trt eq '${condition}'){ - #Validate form parameters for panel ${condition} - # and set $ret = $c->l('Error message') if invalid' - # otherwise set $ret to "ok" - if ($ret ne "ok"){ - $c->stash(error => $c->l($ret)) - } else { - #Do whatever is needed, including writing values to the DB - my $db = $$${db | 'cdb'}; #Default to config - + my $thispanel; + + if ($trt eq '${panel}'){ + #Validate form parameters for panel ${panel} + $ret = validate_${panel}(); + $thispanel = '${panel}'; + } + + if ($ret eq "ok") { + #Do whatever is needed, including writing values to the DB + my $db = $$${controldb | db | 'cdb'}; #pickup local or global db or Default to config + $db->set_prop('${dbentry}'=> param{'${dbentry}'}; #Copy back into db $$${prefix}_data{${dbentry}} = $db->prop('${dbentry}'); #Copy out into stash - - - } $c->stash( success => $c->l('ok message')) - } - - # set ${prefix}_data{trt} = ; - $c->stash( - title => $title, - ${prefix}_data => \%${prefix}_data - # Extra data in here - repeat for each stash data entry needed for panels - ); - - $c->render("${PackageName}") + + # anything else here... + $c->stash( success => $c->l("$thispanel successfull message")); + $c->stash( + title => $title, + ${prefix}_data => \%${prefix}_data + # Extra data in here - repeat for each stash data entry needed for panels + ); + ${prefix}_data{'trt'} = '${firstPanel}'; + $c->render("${PackageName}"); + } } -# get routines for the stash contents here. - - 1; diff --git a/Templates/custom.pm.tem b/Templates/custom.pm.tem new file mode 100644 index 0000000..e7a98b6 --- /dev/null +++ b/Templates/custom.pm.tem @@ -0,0 +1,44 @@ +# +# Routines to be editted by the developer to provide validation for parameters +# and provison of the control data for table(s) +# +#$cdb=$main::cdb; +#$adb=$main::adb; +#$ndb=$main::ndb; +#$hdb=$main::hdb; +#$ddb=$main::ddb; + +use esmith::util; +use esmith::HostsDB; +use esmith::AccountsDB; +use esmith::NetworksDB; +use esmith::HostsDB; +use esmith::DomainsDB; + + +#The most common ones +our $cdb = esmith::ConfigDB->open() || die("Couldn't open config db"); +our $adb = esmith::AccountsDB->open() || die("Couldn't open Accounts db"); +our $ndb = esmith::NetworksDB->open() || die("Couldn't open Network db"); +our $hdb = esmith::HostsDB->open() || die("Couldn't open Hosts db"); +our $ddb = esmith::DomainsDB->open() || die("Couldn't open Domains db"); + +# Validation routines - parameters for each panel + + sub validate_${panel} { + $ret = 'ok'; + return $ret; + } + + +# Get control data for tables(s) + +sub get_${tablecontrol} { + return [] +} + +1; + + + + diff --git a/Templates/html_controls.html.ep.tem b/Templates/html_controls.html.ep.tem deleted file mode 100644 index 192c70f..0000000 --- a/Templates/html_controls.html.ep.tem +++ /dev/null @@ -1,10 +0,0 @@ -{ -Text:"\n

\n\n%=l('${Label}'), class => 'label'\n\n%= ${Value}, class => 'data'\n\n

", -Selection:"\n\n

\n%=l('${Label}')\n\n% my @${Name}_options = ${Value};\n% param '${Name}' => $$${prefix}_data->{${Name}} unless param '${Name}';\n%= select_field '${Name}' => @${Name}_options, class => 'input'\n

", -Textarea:"\n\n\n%=l('${Label}')\n\n% param '${Name}' => $$${prefix}_data->{${Name}} unless param '${Name}';\n%= text_area '${Name}', cols=>50, rows=>15\n
", -Date:"\n\n\n%=$%=l('${Label}')\n\n%=date_field '${Name}' =>$$${Name}\n
", -Textinput:"\n\n

\n%=l('${Label}')\n\n% param '${Name}' => $$${prefix}_data->{${Name}} unless param '${Name}';\n%= text_field '${Name}', size => '60', class => 'input'\n

", -SubHeader:"\n

${value}

", -Paragraph:"\n

${value}

", -Submit:"\n\n%= submit_button l('${value}'), class => 'action'\n" -} diff --git a/Templates/html_controls.html.ep.xml b/Templates/html_controls.html.ep.xml index 357c05b..ebf5512 100644 --- a/Templates/html_controls.html.ep.xml +++ b/Templates/html_controls.html.ep.xml @@ -101,14 +101,14 @@
NameDescriptionNfs statusActionNameDescriptionNfs statusAction
<%=$row->Name%><%=$row->Description%><%=$row->flag%><%=$row->PARAMS%><%=$row->{Name}%><%=$row->{Description}%><%=$row->{flag}%><%=$row->{PARAMS}%>
- + - % my $control_data = $self->stash('${Control}'); + % my $control_data = $self->stash('${TableControl}'); % foreach my $row (@$control_data) { - + %} diff --git a/nfsshare.json5 b/nfsshare.json5 index fadc08b..0e7a149 100644 --- a/nfsshare.json5 +++ b/nfsshare.json5 @@ -136,7 +136,7 @@ SubHeader: 'Manage NFS Ibay settings:', Table1: { Type:"Table", - Control:"ibays", + TableControl:"ibays", TopHeadings: ['Name','Description','Nfs status', 'Action'], Columns: ['Name','Description','flag','PARAMS'] } diff --git a/sm2gen-ImportJSON5.py b/sm2gen-ImportJSON5.py index fe13bcb..7b19e64 100644 --- a/sm2gen-ImportJSON5.py +++ b/sm2gen-ImportJSON5.py @@ -6,8 +6,10 @@ from chameleon import PageTemplateFile,PageTemplate import pkg_resources import xml.etree.ElementTree as ET import re +import os -version = 0.5 + +version = 0.6 json5_dict: dict = {} json5_html_list: list = [] @@ -70,15 +72,34 @@ def find_item(nested_dict, target_key): elif isinstance(val, dict): result = find_item(val, target_key) if result is not None: - return result + return result -def find_dicts_with_key(nested_dict, target_key): +def find_dicts_with_key(data, target_key): results = [] - for key, val in nested_dict.items(): - if isinstance(val, dict): - if target_key in val: - results.append(val) - results.extend(find_dicts_with_key(val, target_key)) + if isinstance(data, dict): + if target_key in data: + results.append(data) + for val in data.values(): + if isinstance(val, (dict, list)): + results.extend(find_dicts_with_key(val, target_key)) + elif isinstance(data, list): + for item in data: + if isinstance(item, (dict, list)): + results.extend(find_dicts_with_key(item, target_key)) + return results + +def find_values_with_key(data, target_key): + results = [] + if isinstance(data, dict): + if target_key in data: + results.append(data[target_key]) + for val in data.values(): + if isinstance(val, (dict, list)): + results.extend(find_values_with_key(val, target_key)) + elif isinstance(data, list): + for item in data: + if isinstance(item, (dict, list)): + results.extend(find_values_with_key(item, target_key)) return results def lint_json5(filename): @@ -120,6 +141,18 @@ def lc_get_all_routes(): # All routes in lower case route_list = [html_block.get('route').lower() for html_block in json5_dict.get('html', [])] return route_list + +def has_file_been_modified(file_path): + # Get the file's creation time and last modification time in Unix timestamp + creation_time = os.path.getctime(file_path) + last_modification_time = os.path.getmtime(file_path) + + # Compare the creation time and last modification time + if creation_time < last_modification_time: + return True # File has been modified after creation + else: + return False # File has not been modified after creation + import xml.etree.ElementTree as ET @@ -150,6 +183,11 @@ def deduplicate_array(arr): return deduplicated_list +def get_db_fields(): + return [] + +def get_table_control_data(): + return find_values_with_key(json5_html_list,'TableControl') if __name__ == "__main__": filename = '/home/brianr/clients/SM2/SM2Gen/nfsshare.json5' @@ -182,25 +220,30 @@ if __name__ == "__main__": # Routes for each panel routes = get_all_routes(); - #print(routes) - lc_routes =lc_get_all_routes(); #File names controller_file = 'Targets/'+hl('PackageName')+'.pm' + custom_controller_file = 'Targets/'+hl('PackageName')+'-Custom.pm' + # see if it has been modified by developer + if has_file_been_modified(custom_controller_file): + custom_controller_file = custom_controller_file+'.new' layout_file = 'Targets/'+hl('PackageName')+'.html.ep' partial_files = list() for panel in routes: partial_files.append('Targets/_'+hl('prefix')+"_"+panel+'.html.ep') print(partial_files) lex_file = 'Targets/'+hl('PackageName').lower()+'_en.lex' + tablecontrols = get_table_control_data() #arrays of hashes used to drive rows in tables + #print(tablecontrols) + #quit() #Generate controller file try: controller_template = PageTemplateFile("Templates/controller.pm.tem") - dbentries = [] + dbentries = get_db_fields() #Params which correspond to Db fields try: - controller_perl = controller_template.render(dbentries=dbentries,**json5_dict,conditions=routes,lcPackageName=json5_dict['PackageName'].lower()) + controller_perl = controller_template.render(tablecontrols=tablecontrols, dbentries=dbentries,**json5_dict,panels=routes,lcPackageName=json5_dict['PackageName'].lower()) #print() #print(controller_perl) # Map '$ 'to '$' to overcome problem with escaping $ signs @@ -212,6 +255,20 @@ if __name__ == "__main__": print(f"An chameleon controller render error occurred: {e}") except Exception as e: print(f"An chameleon controller template error occurred: {e}") + + #Generate Custom controller file + try: + custom_controller_template = PageTemplateFile("Templates/custom.pm.tem") + try: + custom_controller_perl = custom_controller_template.render(panels=routes,tablecontrols=tablecontrols) + # We must be careful to not overwrite the custom file if the developer has already written to it - TBD + with open(custom_controller_file, 'w') as file: + file.write(custom_controller_perl) + print(f"{custom_controller_file} custom controller generated ok") + except Exception as e: + print(f"An chameleon custom controller render error occurred: {e}") + except Exception as e: + print(f"An chameleon custom controller template error occurred: {e}") #generate Layout file layout_template = PageTemplateFile("Templates/layout.html.ep.tem") @@ -323,7 +380,7 @@ if __name__ == "__main__": # create a combined list of all the files all_files = [controller_file,layout_file]+partial_files - print(all_files) + #print(all_files) all_strings = [] for filename in all_files: with open(filename, 'r') as file: @@ -332,12 +389,12 @@ if __name__ == "__main__": pattern = r"l[\s|(][\'|\"](.*)[\'|\"]\)" # Use re.findall to extract all occurrences of the pattern from the file content extracted_strings = re.findall(pattern, file_content) - print(len(extracted_strings)) + #print(len(extracted_strings)) all_strings = all_strings + extracted_strings - print(len(all_strings)) + #print(len(all_strings)) #Take out any duplicates all_strings = deduplicate_array(all_strings) - print(len(all_strings)) + #print(len(all_strings)) # Now process them one by one into the lexical file lex_all = ""; # '_english-message' => 'English Message',
${ColHead}${ColHead}
<%=$row->${ColContent}%><%=$row->{${ColContent}}%>