Add in entries for other mojo input tags

This commit is contained in:
Brian Read 2024-09-15 12:06:34 +01:00
parent 3b6e1930a0
commit 4d7cc1f076
18 changed files with 821 additions and 754 deletions

View File

@ -2,7 +2,7 @@
# Routines to be edited by the developer to provide validation for parameters # Routines to be edited by the developer to provide validation for parameters
# and provison of the control data for table(s) # and provison of the control data for table(s)
# #
# Generated by SM2Gen version:0.8 Chameleon version:4.5.4 On Python:3.12.3 at 2024-09-14 17:41 # Generated by SM2Gen version:0.8 Chameleon version:4.5.4 On Python:3.12.3 at 2024-09-15 12:03
# #
use esmith::util; use esmith::util;

View File

@ -1,6 +1,6 @@
package SrvMngr::Controller::CreateStarterWebsite; package SrvMngr::Controller::CreateStarterWebsite;
# #
# Generated by version:SM2Gen version:0.8 Chameleon version:4.5.4 On Python:3.12.3 at 2024-09-14 17:41 # Generated by version:SM2Gen version:0.8 Chameleon version:4.5.4 On Python:3.12.3 at 2024-09-15 12:03
# #
#---------------------------------------------------------------------- #----------------------------------------------------------------------
# heading : Miscellaneous # heading : Miscellaneous

View File

@ -1,5 +1,5 @@
%# %#
%# Generated by SM2Gen version:0.8 Chameleon version:4.5.4 On Python:3.12.3 at 2024-09-13 19:20 %# Generated by SM2Gen version:0.8 Chameleon version:4.5.4 On Python:3.12.3 at 2024-09-15 12:03
%# %#
<div id="CreateStarterWebsite-PARAMS" class="partial CreateStarterWebsite-PARAMS"> <div id="CreateStarterWebsite-PARAMS" class="partial CreateStarterWebsite-PARAMS">
<script> <script>
@ -20,48 +20,39 @@
<h2><%=l('csw_Manage_CreateStarterWebsite_settings:')%></h2> <h2><%=l('csw_Manage_CreateStarterWebsite_settings:')%></h2>
<p> <p>
%= l('To create a simple web page for your company, fill %=l('csw_To_create_a_simple_web')
in the fields below and click onCreate.')
</p> </p>
<p> <p>
%= l('csw_You_can_leave_any_field') %=l('csw_You_can_leave_any_field')
</p> </p>
<p> <p>
%= l('The text that you enter below will be line wrapped %=l('csw_The_text_that_you_enter')
for a nicer appearance in your web page. Leave a blank line
whenever you want to start a new paragraph. If you need
to force a line break without starting a new paragraph (for
example after each line of a mailing address), then type
the four-character sequence')
</p> </p>
<p> <p>
%= l('Do not use this option if you have already customized your web site, since it will %=l('csw_Do_not_use_this_optionif')
overwrite the 'index.htm' file in your web site directory.')
</p> </p>
<p><span class=label> <p><span class=label>
%=l('csw_') %=l('csw_')
</span><span class=data> </span><span class=data>
%= % text_field
</span></p> </span></p>
<p> <p>
%= l('First header, typically used for short phrases such %=l('csw_First_header,_typically_used_for')
as 'Leader in the field of textile manufacturing'')
</p> </p>
<p><span class=label> <p><span class=label>
%=l('csw_') %=l('csw_')
</span><span class=data> </span><span class=data>
%= % text_field
</span></p> </span></p>
<p> <p>
%= l('Text following first header, typically used for a %=l('csw_Text_following_first_header,_typically')
paragraph of marketing information.')
</p> </p>
<span class=label> <span class=label>
@ -72,19 +63,17 @@
</span><br> </span><br>
<p> <p>
%= l('Second header, typically used for short phrases such %=l('csw_Second_header,_typically_used_for')
as 'For more information' or 'To order our products':')
</p> </p>
<p><span class=label> <p><span class=label>
%=l('csw_') %=l('csw_')
</span><span class=data> </span><span class=data>
%= % text_field
</span></p> </span></p>
<p> <p>
%= l('Text following second header, typically used for contact %=l('csw_Text_following_second_header,_typically')
or ordering information:')
</p> </p>
<span class=label> <span class=label>
@ -95,15 +84,17 @@
</span><br> </span><br>
<p> <p>
%= l('When you create this web page, the file %=l('csw_When_you_create_this_web')
'index.htm' will be overwritten
in your web site directory.')
</p> </p>
<p> <p>
%= l('csw_Do_you_wish_to_proceed?') %=l('csw_Do_you_wish_to_proceed?')
</p> </p>
<span class='data'>
%= submit_button l('csw_Create'), class => 'action'
</span>
%# Probably finally by a submit. %# Probably finally by a submit.
%end %end
</div> </div>

View File

@ -1,6 +1,6 @@
% layout 'default', title => "Sme server 2 - Create Starter Website", share_dir => './'; % layout 'default', title => "Sme server 2 - Create Starter Website", share_dir => './';
%# %#
%# Generated by SM2Gen version:0.8 Chameleon version:4.5.4 On Python:3.12.3 at 2024-09-14 17:41 %# Generated by SM2Gen version:0.8 Chameleon version:4.5.4 On Python:3.12.3 at 2024-09-15 12:03
%# %#
% content_for 'module' => begin % content_for 'module' => begin
<div id="module" class="module CreateStarterWebsite-panel"> <div id="module" class="module CreateStarterWebsite-panel">

View File

@ -1,16 +1,17 @@
'csw_Do_not_use_this_optionif' => 'Do not use this optionif you have already customized your web site, Since it will overwrite the \'index. Htm\' file in your web site directory. ', 'csw_Text_following_second_header,_typically' => 'Text following second header, Typically used for contact or ordering information:',
'csw_Second_header,_typically_used_for' => 'Second header, Typically used for short phrases such as \'For more information\' or \'To order our products\':',
'csw_Hello_PARAMS' => 'Hello PARAMS', 'csw_Hello_PARAMS' => 'Hello PARAMS',
'csw_To_create_a_simple_web' => 'To create a simple web page for your company, Fill in the fields below and click onCreate. ',
'csw_The_text_that_you_enter' => 'The text that you enter below will be line wrapped for a nicer appearance in your web page. Leave a blank line whenever you want to start a new paragraph. If you need to force a line break without starting a new paragraph (for example after each line of a mailing address), Then type the four-character sequence',
'csw_You_can_leave_any_field' => 'You can leave any field blank if you do not need it. ',
'csw_Text_following_first_header,_typically' => 'Text following first header, Typically used for a paragraph of marketing information. ',
'csw_Do_you_wish_to_proceed?' => 'Do you wish to proceed?',
'csw_Manage_CreateStarterWebsite_settings:' => 'Manage CreateStarterWebsite settings:',
'csw_When_you_create_this_web' => 'When you create this web page, The file \'index. Htm\' will be overwritten in your web site directory. ',
'csw_PARAMS_panel_action_was_successful' => 'PARAMS panel action was successful', 'csw_PARAMS_panel_action_was_successful' => 'PARAMS panel action was successful',
'csw_Create_Starter_Website' => 'Create Starter Website', 'csw_Do_you_wish_to_proceed?' => 'Do you wish to proceed?',
'csw_First_header,_typically_used_for' => 'First header, Typically used for short phrases such as \'Leader in the field of textile manufacturing\'', 'csw_Create' => 'Create',
'csw_When_you_create_this_web' => 'When you create this web page, The file 'index. Htm' will be overwritten in your web site directory. ',
'csw_Manage_CreateStarterWebsite_settings:' => 'Manage CreateStarterWebsite settings:',
'csw_' => '', 'csw_' => '',
'csw_The_text_that_you_enter' => 'The text that you enter below will be line wrapped for a nicer appearance in your web page. Leave a blank line whenever you want to start a new paragraph. If you need to force a line break without starting a new paragraph (for example after each line of a mailing address), Then type the four-character sequence',
'csw_You_can_leave_any_field' => 'You can leave any field blank if you do not need it. ',
'csw_First_header,_typically_used_for' => 'First header, Typically used for short phrases such as 'Leader in the field of textile manufacturing'',
'csw_Text_following_first_header,_typically' => 'Text following first header, Typically used for a paragraph of marketing information. ',
'csw_Do_not_use_this_optionif' => 'Do not use this optionif you have already customized your web site, Since it will overwrite the 'index. Htm' file in your web site directory. ',
'csw_Create_Starter_Website' => 'Create Starter Website',
'csw_To_create_a_simple_web' => 'To create a simple web page for your company, Fill in the fields below and click onCreate. ',
'csw_APPLY' => 'Apply', 'csw_APPLY' => 'Apply',
'csw_Text_following_second_header,_typically' => 'Text following second header, Typically used for contact or ordering information:', 'csw_Second_header,_typically_used_for' => 'Second header, Typically used for short phrases such as 'For more information' or 'To order our products':',

View File

@ -1,96 +0,0 @@
%#
%# Generated by SM2Gen version:0.8 Chameleon version:4.5.4 On Python:3.12.3 at 2024-09-14 17:41
%#
<div id="CreateStarterWebsite-PARAMS" class="partial CreateStarterWebsite-PARAMS">
<script>
window.onload = function() {
SelectInput();
};
</script>
<h2>
%= l('csw_Hello_PARAMS');
</h2>
% my $btn = l('csw_APPLY');
%= form_for "CreateStarterWebsited" => (method => 'POST') => begin
% param 'trt' => $csw_data->{trt} unless param 'trt';
%= hidden_field 'trt' => $csw_data->{trt}
%# Inputs etc in here.
<h2><%=l('csw_Manage_CreateStarterWebsite_settings:')%></h2>
<p>
%=l('csw_To_create_a_simple_web')
</p>
<p>
%=l('csw_You_can_leave_any_field')
</p>
<p>
%=l('csw_The_text_that_you_enter')
</p>
<p>
%=l('csw_Do_not_use_this_optionif')
</p>
<p><span class=label>
%=l('csw_')
</span><span class=data>
%=
</span></p>
<p>
%=l('csw_First_header,_typically_used_for')
</p>
<p><span class=label>
%=l('csw_')
</span><span class=data>
%=
</span></p>
<p>
%=l('csw_Text_following_first_header,_typically')
</p>
<span class=label>
%=l('csw_')
</span><span class=data>
% param 'text1' => $csw_data->{text1} unless param 'text1';
%= text_area 'text1', cols=>40, rows=>10
</span><br>
<p>
%=l('csw_Second_header,_typically_used_for')
</p>
<p><span class=label>
%=l('csw_')
</span><span class=data>
%=
</span></p>
<p>
%=l('csw_Text_following_second_header,_typically')
</p>
<span class=label>
%=l('csw_')
</span><span class=data>
% param 'text2' => $csw_data->{text2} unless param 'text2';
%= text_area 'text2', cols=>40, rows=>10
</span><br>
<p>
%=l('csw_When_you_create_this_web')
</p>
<p>
%=l('csw_Do_you_wish_to_proceed?')
</p>
%# Probably finally by a submit.
%end
</div>

View File

@ -2,7 +2,7 @@
# Routines to be edited by the developer to provide validation for parameters # Routines to be edited by the developer to provide validation for parameters
# and provison of the control data for table(s) # and provison of the control data for table(s)
# #
# Generated by SM2Gen version:0.8 Chameleon version:4.5.4 On Python:3.12.3 at 2024-09-14 12:09 # Generated by SM2Gen version:0.8 Chameleon version:4.5.4 On Python:3.12.3 at 2024-09-15 10:49
# #
use esmith::util; use esmith::util;
@ -36,7 +36,11 @@ our $ddb = esmith::DomainsDB->open() || die("Couldn't open Domains db");
# Return an array of hashes of the contents for each row and column for Table1 # Return an array of hashes of the contents for each row and column for Table1
# default is a single row of strings "col1header-1, col2header-1, col3Header-1 etc" # default is a single row of strings "col1header-1, col2header-1, col3Header-1 etc"
my $c = shift; my $c = shift;
my @ret = {}; my $control_data = $self->stash('Table1');
my @ret = {}
# foreach my $colHead (@$control_data) {
# my ret{$colHead} = "$colhead-1"
# };
return \@ret return \@ret
} }
@ -44,7 +48,11 @@ our $ddb = esmith::DomainsDB->open() || die("Couldn't open Domains db");
# Return an array of hashes of the contents for each row and column for Table2 # Return an array of hashes of the contents for each row and column for Table2
# default is a single row of strings "col1header-1, col2header-1, col3Header-1 etc" # default is a single row of strings "col1header-1, col2header-1, col3Header-1 etc"
my $c = shift; my $c = shift;
my @ret = {}; my $control_data = $self->stash('Table2');
my @ret = {}
# foreach my $colHead (@$control_data) {
# my ret{$colHead} = "$colhead-1"
# };
return \@ret return \@ret
} }

View File

@ -2,7 +2,7 @@
# Routines to be edited by the developer to provide validation for parameters # Routines to be edited by the developer to provide validation for parameters
# and provison of the control data for table(s) # and provison of the control data for table(s)
# #
# Generated by SM2Gen version:0.8 Chameleon version:4.5.4 On Python:3.12.3 at 2024-09-14 11:53 # Generated by SM2Gen version:0.8 Chameleon version:4.5.4 On Python:3.12.3 at 2024-09-15 11:51
# #
use esmith::util; use esmith::util;
@ -33,14 +33,26 @@ our $ddb = esmith::DomainsDB->open() || die("Couldn't open Domains db");
# Get control data for tables(s) # Get control data for tables(s)
sub get_Table1 { sub get_Table1 {
# Return an array of hashes of the contents for each row and column for Table1
# default is a single row of strings "col1header-1, col2header-1, col3Header-1 etc"
my $c = shift; my $c = shift;
my @ret = {}; my $control_data = $self->stash('Table1');
my @ret = {}
# foreach my $colHead (@$control_data) {
# my ret{$colHead} = "$colhead-1"
# };
return \@ret return \@ret
} }
sub get_Table2 { sub get_Table2 {
# Return an array of hashes of the contents for each row and column for Table2
# default is a single row of strings "col1header-1, col2header-1, col3Header-1 etc"
my $c = shift; my $c = shift;
my @ret = {}; my $control_data = $self->stash('Table2');
my @ret = {}
# foreach my $colHead (@$control_data) {
# my ret{$colHead} = "$colhead-1"
# };
return \@ret return \@ret
} }

View File

@ -1,19 +1,19 @@
package SrvMngr::Controller::Diskusage; package SrvMngr::Controller::DiskUsage;
# #
# Generated by version:SM2Gen version:0.8 Chameleon version:4.5.4 On Python:3.12.3 at 2024-09-14 12:09 # Generated by version:SM2Gen version:0.8 Chameleon version:4.5.4 On Python:3.12.3 at 2024-09-15 11:51
# #
#---------------------------------------------------------------------- #----------------------------------------------------------------------
# heading : Miscellaneous # heading : Miscellaneous
# description : Disk Usage # description : Disk Usage
# navigation : 2000 400 # navigation : 2000 400
# #
# name : diskusage, method : get, url : /diskusage, ctlact : Diskusage#main # name : diskusage, method : get, url : /diskusage, ctlact : DiskUsage#main
# name : diskusageu, method : post, url : /diskusageu, ctlact : Diskusage#do_update # name : diskusageu, method : post, url : /diskusageu, ctlact : DiskUsage#do_update
# name : diskusaged, method : get, url : /diskusaged, ctlact : Diskusage#do_display # name : diskusaged, method : get, url : /diskusaged, ctlact : DiskUsage#do_display
# #
# routes : end # routes : end
# #
# Documentation: https://wiki.contribs.org/Diskusage # Documentation: https://wiki.contribs.org/DiskUsage
#---------------------------------------------------------------------- #----------------------------------------------------------------------
# #
@ -49,7 +49,7 @@ our $ndb = esmith::NetworksDB->open() || die("Couldn't open Network db");
our $hdb = esmith::HostsDB->open() || die("Couldn't open Hosts db"); our $hdb = esmith::HostsDB->open() || die("Couldn't open Hosts db");
our $ddb = esmith::DomainsDB->open() || die("Couldn't open Domains db"); our $ddb = esmith::DomainsDB->open() || die("Couldn't open Domains db");
require '/usr/share/smanager/lib/SrvMngr/Controller/Diskusage-Custom.pm'; #The code that is to be added by the developer require '/usr/share/smanager/lib/SrvMngr/Controller/DiskUsage-Custom.pm'; #The code that is to be added by the developer
sub main { sub main {
# #

View File

@ -1,7 +1,7 @@
%# %#
%# Generated by SM2Gen version:0.8 Chameleon version:4.5.4 On Python:3.12.3 at 2024-09-14 12:09 %# Generated by SM2Gen version:0.8 Chameleon version:4.5.4 On Python:3.12.3 at 2024-09-15 11:51
%# %#
<div id="Diskusage-PARAMS" class="partial Diskusage-PARAMS"> <div id="DiskUsage-PARAMS" class="partial DiskUsage-PARAMS">
<script> <script>
window.onload = function() { window.onload = function() {
SelectInput(); SelectInput();
@ -11,7 +11,7 @@
%= l('du_Hello_PARAMS'); %= l('du_Hello_PARAMS');
</h2> </h2>
% my $btn = l('du_APPLY'); % my $btn = l('du_APPLY');
%= form_for "Diskusaged" => (method => 'POST') => begin %= form_for "DiskUsaged" => (method => 'POST') => begin
% param 'trt' => $du_data->{trt} unless param 'trt'; % param 'trt' => $du_data->{trt} unless param 'trt';
%= hidden_field 'trt' => $du_data->{trt} %= hidden_field 'trt' => $du_data->{trt}
@ -20,11 +20,11 @@
<h2><%=l('du_Manage_DiskUsage_settings:')%></h2> <h2><%=l('du_Manage_DiskUsage_settings:')%></h2>
<p> <p>
%= l('du_&amp;nbsp') %=l('du_')
</p> </p>
<p> <p>
%= l('du_Wed_Sep_11_19:01:00_BST') %=l('du_Wed_Sep_11_19:01:00_BST')
</p> </p>
<pre> <pre>
@ -60,7 +60,7 @@ tmpfs 2.0G 648K 2.0G 1% /run
<p> <p>
%= l('du_&amp;nbsp') %=l('du_')
</p> </p>
<br /><table class="sme-border TableSort sme-table"> <br /><table class="sme-border TableSort sme-table">

View File

@ -1,9 +1,9 @@
% layout 'default', title => "Sme server 2 - Disk Usage", share_dir => './'; % layout 'default', title => "Sme server 2 - Disk Usage", share_dir => './';
%# %#
%# Generated by SM2Gen version:0.8 Chameleon version:4.5.4 On Python:3.12.3 at 2024-09-14 12:09 %# Generated by SM2Gen version:0.8 Chameleon version:4.5.4 On Python:3.12.3 at 2024-09-15 11:51
%# %#
% content_for 'module' => begin % content_for 'module' => begin
<div id="module" class="module Diskusage-panel"> <div id="module" class="module DiskUsage-panel">
% if ($config->{debug} == 1) { % if ($config->{debug} == 1) {
<p> <p>

View File

@ -1,11 +1,11 @@
'du_&amp;nbsp' => '&amp;nbsp', 'du_' => '',
'du_I-bays' => 'I-bays',
'du_Usage' => 'Usage',
'du_Disk_Usage' => 'Disk Usage',
'du_Path' => 'Path',
'du_Wed_Sep_11_19:01:00_BST' => 'Wed Sep 11 19:01:00 BST 2024',
'du_Users' => 'Users',
'du_APPLY' => 'Apply',
'du_Hello_PARAMS' => 'Hello PARAMS',
'du_Manage_DiskUsage_settings:' => 'Manage DiskUsage settings:', 'du_Manage_DiskUsage_settings:' => 'Manage DiskUsage settings:',
'du_PARAMS_panel_action_was_successful' => 'PARAMS panel action was successful', 'du_PARAMS_panel_action_was_successful' => 'PARAMS panel action was successful',
'du_Wed_Sep_11_19:01:00_BST' => 'Wed Sep 11 19:01:00 BST 2024',
'du_Path' => 'Path',
'du_I-bays' => 'I-bays',
'du_Hello_PARAMS' => 'Hello PARAMS',
'du_Usage' => 'Usage',
'du_Users' => 'Users',
'du_Disk_Usage' => 'Disk Usage',
'du_APPLY' => 'Apply',

View File

@ -36,7 +36,7 @@ our $ddb = esmith::DomainsDB->open() || die("Couldn't open Domains db");
# Return an array of hashes of the contents for each row and column for ${tablecontrol} # Return an array of hashes of the contents for each row and column for ${tablecontrol}
# default is a single row of strings "col1header-1, col2header-1, col3Header-1 etc" # default is a single row of strings "col1header-1, col2header-1, col3Header-1 etc"
my $c = shift; my $c = shift;
my $control_data = $self->stash('${TableControl}'); my $control_data = $self->stash('${tablecontrol}');
my @ret = {} my @ret = {}
# foreach my $colHead (@$control_data) { # foreach my $colHead (@$control_data) {
# my ret{$colHead} = "$colhead-1" # my ret{$colHead} = "$colhead-1"

View File

@ -3,7 +3,7 @@
<p><span class=label> <p><span class=label>
%=l('${prefix}_${Label}') %=l('${prefix}_${Label}')
</span><span class=data> </span><span class=data>
%= ${Value} % text_field ${Value}
</span></p> </span></p>
]]></Text> ]]></Text>
@ -17,6 +17,8 @@
<br></span> </p> <br></span> </p>
]]></Selection> ]]></Selection>
<Textarea><![CDATA[ <Textarea><![CDATA[
<span class=label> <span class=label>
%=l('${prefix}_${Label}') %=l('${prefix}_${Label}')
@ -34,6 +36,15 @@
</span><br> </span><br>
]]></Date> ]]></Date>
<Time><![CDATA[
<span class=label>
%=l('${prefix}_${Label}')
</span><span class=data>
%=time_field '${Name}' =>$$${Name}, pattern=>${regexp | .*}
</span><br>
]]></Time>
<Textinput><![CDATA[ <Textinput><![CDATA[
<p><span class=label> <p><span class=label>
%=l('${prefix}_${Label}') %=l('${prefix}_${Label}')
@ -55,7 +66,7 @@
<Submit><![CDATA[ <Submit><![CDATA[
<span class='data'> <span class='data'>
%= submit_button l('${value}'), class => 'action' %= submit_button l('${Value}'), class => 'action'
</span>]]> </span>]]>
</Submit> </Submit>
@ -63,6 +74,8 @@
<p><span class=label> <p><span class=label>
%=l('${prefix}_${Label}') %=l('${prefix}_${Label}')
</span><span class=data> </span><span class=data>
%=Search field
%=search field
</span>span></p> </span>span></p>
]]> ]]>
</search> </search>
@ -71,6 +84,7 @@
<p><span class=label> <p><span class=label>
%=l('${Label}') %=l('${Label}')
</span><span class=data> </span><span class=data>
%=URL field
</span>span></p> </span>span></p>
]]> ]]>
</url> </url>
@ -79,6 +93,7 @@
<p><span class=label> <p><span class=label>
%=l('${Label}') %=l('${Label}')
</span><span class=data> </span><span class=data>
%=tel field
</span>span></p> </span>span></p>
]]> ]]>
</tel> </tel>
@ -87,6 +102,7 @@
<p><span class=label> <p><span class=label>
%=l('${Label}') %=l('${Label}')
</span><span class=data> </span><span class=data>
%=email field
</span>span></p> </span>span></p>
]]> ]]>
</email> </email>
@ -95,10 +111,92 @@
<p><span class='label'> <p><span class='label'>
%=l('${Label}') %=l('${Label}')
</span><span class=data> </span><span class=data>
%=password field
</span>span></p> </span>span></p>
]]> ]]>
</password> </password>
<timedate><![CDATA[
<p><span class='label'>
%=l('${Label}')
</span><span class=data>
%=timedate field
</span>span></p>
]]>
</timedate>
<week><![CDATA[
<p><span class='label'>
%=l('${Label}')
</span><span class=data>
%=week field
</span>span></p>
]]>
</week>
<month><![CDATA[
<p><span class='label'>
%=l('${Label}')
</span><span class=data>
%=month field
</span>span></p>
]]>
</month>
<range><![CDATA[
<p><span class='label'>
%=l('${Label}')
</span><span class=data>
%=range field
</span>span></p>
]]>
</range>
<radio><![CDATA[
<p><span class='label'>
%=l('${Label}')
</span><span class=data>
%=radio field
</span>span></p>
]]>
</radio>
<number><![CDATA[
<p><span class='label'>
%=l('${Label}')
</span><span class=data>
%=number field
</span>span></p>
]]>
</number>
<file><![CDATA[
<p><span class='label'>
%=l('${Label}')
</span><span class=data>
%=file field
</span>span></p>
]]>
</file>
<color><![CDATA[
<p><span class='label'>
%=l('${Label}')
</span><span class=data>
%=color field
</span>span></p>
]]>
</color>
<checkbox><![CDATA[
<p><span class='label'>
%=l('${Label}')
</span><span class=data>
%=checkbox field
</span>span></p>
]]>
</checkbox>
<Table><![CDATA[ <Table><![CDATA[
<br /><table class="sme-border TableSort sme-table"> <br /><table class="sme-border TableSort sme-table">
<thead> <thead>
@ -125,11 +223,5 @@
]]> ]]>
</Preformatted> </Preformatted>
<submit><![CDATA[
<p> <br>
%= submit_button "${Value}", class => 'action'
</p>
]]>
</submit>
</root> </root>

View File

@ -6,57 +6,58 @@
'MenuNavigation': '2000 400', 'MenuNavigation': '2000 400',
'firstPanel': 'PARAMS', 'firstPanel': 'PARAMS',
'signalEvent': 'smeserver-createstarterwebsite-update', 'signalEvent': 'smeserver-createstarterwebsite-update',
'html':[ { 'html': [
'Name': 'params', {
'route': 'PARAMS', 'Name': 'params',
'Header': 'Create a starter website', 'route': 'PARAMS',
'SubHeader': 'Manage CreateStarterWebsite settings:', 'Header': 'Create a starter website',
'Paragraph1': 'To create a simple web page for your company, fill in the fields below and click onCreate.', 'SubHeader': 'Manage CreateStarterWebsite settings:',
'Paragraph2': 'You can leave any field blank if you do not need it.', 'Paragraph1': 'To create a simple web page for your company, fill in the fields below and click onCreate.',
'Paragraph3': 'The text that you enter below will be line wrapped for a nicer appearance in your web page. Leave a blank line whenever you want to start a new paragraph. If you need to force a line break without starting a new paragraph (for example after each line of a mailing address), then type the four-character sequence', 'Paragraph2': 'You can leave any field blank if you do not need it.',
'Paragraph4': 'Do not use this optionif you have already customized your web site, since it will overwrite the index.htm file in your web site directory.', 'Paragraph3': 'The text that you enter below will be line wrapped for a nicer appearance in your web page. Leave a blank line whenever you want to start a new paragraph. If you need to force a line break without starting a new paragraph (for example after each line of a mailing address), then type the four-character sequence',
'Input1': { 'Paragraph4': 'Do not use this optionif you have already customized your web site, since it will overwrite the \'index.htm\' file in your web site directory.',
'Type': 'Text', 'Input1': {
'Value': '', 'Type': 'Text',
'Name': 'companyName', 'Value': '',
'Label': null 'Name': 'companyName',
}, 'Label': null
'Paragraph5': 'First header, typically used for short phrases such as Leader in the field of textile manufacturing', },
'Input2': { 'Paragraph5': 'First header, typically used for short phrases such as \'Leader in the field of textile manufacturing\'',
'Type': 'Text', 'Input2': {
'Value': '', 'Type': 'Text',
'Name': 'header1', 'Value': '',
'Label': null 'Name': 'header1',
}, 'Label': null
'Paragraph6': 'Text following first header, typically used for a paragraph of marketing information.', },
'Input3': { 'Paragraph6': 'Text following first header, typically used for a paragraph of marketing information.',
'Type': 'Textarea', 'Input3': {
'Value': '', 'Type': 'Textarea',
'Name': 'text1', 'Value': '',
'Label': null 'Name': 'text1',
}, 'Label': null
'Paragraph7': 'Second header, typically used for short phrases such as For more information or To order our products:', },
'Input4': { 'Paragraph7': 'Second header, typically used for short phrases such as \'For more information\' or \'To order our products\':',
'Type': 'Text', 'Input4': {
'Value': '', 'Type': 'Text',
'Name': 'header2', 'Value': '',
'Label': null 'Name': 'header2',
}, 'Label': null
'Paragraph8': 'Text following second header, typically used for contact or ordering information:', },
'Input5': { 'Paragraph8': 'Text following second header, typically used for contact or ordering information:',
'Type': 'Textarea', 'Input5': {
'Value': '', 'Type': 'Textarea',
'Name': 'text2', 'Value': '',
'Label': null 'Name': 'text2',
}, 'Label': null
'Paragraph9': 'When you create this web page, the file index.htm will be overwritten in your web site directory.', },
'Paragraph10': 'Do you wish to proceed?', 'Paragraph9': 'When you create this web page, the file \'index.htm\' will be overwritten in your web site directory.',
'Input6': { 'Paragraph10': 'Do you wish to proceed?',
'Type': 'Submit', 'Input6': {
'Value': 'Create', 'Type': 'Submit',
'Name': 'Next', 'Value': 'Create',
'Label': null 'Name': 'Next',
'Label': null
}
} }
}
] ]
} }

View File

@ -1,47 +1,49 @@
{ {
PackageName: 'Diskusage', 'PackageName': 'DiskUsage',
prefix: 'du', 'prefix': 'du',
MenuHeading: 'Miscellaneous', 'MenuHeading': 'Miscellaneous',
MenuDescription: 'Disk Usage', 'MenuDescription': 'Disk Usage',
MenuNavigation: '2000 400', 'MenuNavigation': '2000 400',
firstPanel: 'PARAMS', 'firstPanel': 'PARAMS',
signalEvent: 'smeserver-diskusage-update', 'signalEvent': 'smeserver-diskusage-update',
html: [{ 'html': [
Name: 'params', {
route: 'PARAMS', 'Name': 'params',
Header: 'Disk usage', 'route': 'PARAMS',
SubHeader: 'Manage DiskUsage settings:', 'Header': 'Disk usage',
Paragraph1: '&nbsp', 'SubHeader': 'Manage DiskUsage settings:',
Paragraph2: 'Wed Sep 11 19:01:00 BST 2024', 'Paragraph1': '',
Preformatted1: 'Filesystem Size Used Avail Use% Mounted on\n/dev/mapper/main-root 29G 4.8G 24G 17% /\ndevtmpfs 2.0G 0 2.0G 0% /dev\ntmpfs 2.0G 12K 2.0G 1% /dev/shm\ntmpfs 2.0G 0 2.0G 0% /sys/fs/cgroup\ntmpfs 2.0G 648K 2.0G 1% /run\n/dev/sda1 497M 111M 386M 23% /boot', 'Paragraph2': 'Wed Sep 11 19:01:00 BST 2024',
Table1: { 'Preformatted1': 'Filesystem Size Used Avail Use% Mounted on\n/dev/mapper/main-root 29G 4.8G 24G 17% /\ndevtmpfs 2.0G 0 2.0G 0% /dev\ntmpfs 2.0G 12K 2.0G 1% /dev/shm\ntmpfs 2.0G 0 2.0G 0% /sys/fs/cgroup\ntmpfs 2.0G 648K 2.0G 1% /run\n/dev/sda1 497M 111M 386M 23% /boot',
Type: 'Table', 'Table1': {
TableControl: 'Table1', 'Type': 'Table',
TopHeadings: [ 'TableControl': 'Table1',
'I-bays', 'TopHeadings': [
'Usage', 'I-bays',
'Path' 'Usage',
], 'Path'
Columns: [ ],
'Table1-I-bays', 'Columns': [
'Table1-Usage', 'Table1-I-bays',
'Table1-Path' 'Table1-Usage',
] 'Table1-Path'
}, ]
Paragraph3: '&nbsp', },
Table2: { 'Paragraph3': '',
Type: 'Table', 'Table2': {
TableControl: 'Table2', 'Type': 'Table',
TopHeadings: [ 'TableControl': 'Table2',
'Users', 'TopHeadings': [
'Usage', 'Users',
'Path' 'Usage',
], 'Path'
Columns: [ ],
'Table2-Users', 'Columns': [
'Table2-Usage', 'Table2-Users',
'Table2-Path' 'Table2-Usage',
] 'Table2-Path'
]
}
} }
}] ]
} }

View File

@ -3,12 +3,16 @@ import os
import re import re
from bs4 import BeautifulSoup from bs4 import BeautifulSoup
from lxml import etree # Import lxml for HTML validation from lxml import etree # Import lxml for HTML validation
import html
import argparse
def read_html_file(filename): def read_html_file(filename):
"""Read HTML content from a file.""" """Read HTML content from a file."""
with open(filename, 'r', encoding='utf-8') as file: with open(filename, "r", encoding="utf-8") as file:
return file.read() return file.read()
def validate_html(html): def validate_html(html):
"""Validate the HTML content.""" """Validate the HTML content."""
try: try:
@ -17,13 +21,19 @@ def validate_html(html):
except Exception as e: except Exception as e:
raise ValueError("Invalid HTML document") from e raise ValueError("Invalid HTML document") from e
def sanitize_text(text): def sanitize_text(text):
# Replace newlines with spaces # Replace newlines with spaces
sanitized_text = text.replace('\n', ' ').replace('\r', ' ') # Handle both Unix and Windows line endings decoded_text = html.unescape(text)
sanitized_text = decoded_text.replace("\n", "").replace(
"\r", " "
) # Handle both Unix and Windows line endings
# Replace tabs with spaces # Replace tabs with spaces
sanitized_text = sanitized_text.replace('\t', ' ') sanitized_text = sanitized_text.replace("\t", "")
# Escape quote characters # map single quotes to double
sanitized_text = sanitized_text.replace('"', '\\"').replace("'", "\\'") sanitized_text = sanitized_text.replace("'", '"')
#Take out any multiple spaces - reduce to one.
sanitized_text = ' '.join(sanitized_text.split())
# Strip leading and trailing whitespace # Strip leading and trailing whitespace
sanitized_text = sanitized_text.strip() sanitized_text = sanitized_text.strip()
return sanitized_text return sanitized_text
@ -31,15 +41,10 @@ def sanitize_text(text):
def extract_data(html): def extract_data(html):
"""Extract paragraphs, inputs, tables, and pre blocks from HTML and organize them in order.""" """Extract paragraphs, inputs, tables, and pre blocks from HTML and organize them in order."""
soup = BeautifulSoup(html, 'lxml') soup = BeautifulSoup(html, "lxml")
records = [] records = []
hidden_input_names = [ hidden_input_names = ["page", "page_stack", ".id", "csrf_token"]
'page',
'page_stack',
'.id',
'csrf_token'
]
header_text = None header_text = None
sub_header_text = None sub_header_text = None
@ -48,81 +53,81 @@ def extract_data(html):
table_counter = 0 table_counter = 0
# Extract elements while preserving order # Extract elements while preserving order
for element in soup.find_all(['h1', 'h2', 'p', 'pre', 'input', 'select', 'textarea', 'button', 'table']): for element in soup.find_all(
if element.name == 'h1': ["h1", "h2", "p", "pre", "input", "select", "textarea", "button", "table"]
):
if element.name == "h1":
header_text = element.get_text(strip=True) header_text = element.get_text(strip=True)
records.append({ records.append({"Type": "Header", "Text": header_text})
'Type': 'Header',
'Text': header_text
})
elif element.name == 'h2': elif element.name == "h2":
sub_header_text = element.get_text(strip=True) sub_header_text = element.get_text(strip=True)
records.append({ records.append({"Type": "SubHeader", "Text": sub_header_text})
'Type': 'SubHeader',
'Text': sub_header_text
})
elif element.name == 'p': elif element.name == "p":
text = element.get_text(strip=True) text = element.get_text(strip=True)
if text: # Ignore empty paragraphs if text: # Ignore empty paragraphs
#Sanitise text freom newlines,tabs and escape quotes. # Sanitise text freom newlines,tabs and escape quotes.
records.append({ records.append({"Type": "Paragraph", "Text": sanitize_text(text)})
'Type': 'Paragraph',
'Text': sanitize_text(text)
})
elif element.name == 'pre': elif element.name == "pre":
text = element.get_text(strip=True) text = element.get_text(strip=True)
if text: # Ensure non-empty before adding if text: # Ensure non-empty before adding
records.append({ records.append({"Type": "Preformatted", "Text": text})
'Type': 'Preformatted',
'Text': text
})
elif element.name == 'input': elif element.name == "input":
if element.get('type') == 'hidden' or element.get('name') in hidden_input_names: if (
element.get("type") == "hidden"
or element.get("name") in hidden_input_names
):
continue continue
input_info = { input_info = {
'Type': element.get('type', 'text').capitalize(), "Type": element.get("type", "text").capitalize(),
'Name': element.get('name'), "Name": element.get("name"),
'Value': element.get('value', ''), "Value": element.get("value", ""),
} }
label = element.find_next('label') label = element.find_next("label")
input_info['Label'] = label.get_text(strip=True) if label else None input_info["Label"] = label.get_text(strip=True) if label else None
records.append(input_info) records.append(input_info)
elif element.name == 'select': elif element.name == "select":
options = [{'Value': option.get('value'), 'Text': option.get_text(strip=True)} for option in element.find_all('option')] options = [
{"Value": option.get("value"), "Text": option.get_text(strip=True)}
for option in element.find_all("option")
]
select_info = { select_info = {
'Type': 'Select', "Type": "Select",
'Name': element.get('name'), "Name": element.get("name"),
'Options': options, "Options": options,
'Label': element.find_previous('label').get_text(strip=True) if element.find_previous('label') else None, "Label": element.find_previous("label").get_text(strip=True)
if element.find_previous("label")
else None,
} }
records.append(select_info) records.append(select_info)
elif element.name == 'textarea': elif element.name == "textarea":
textarea_info = { textarea_info = {
'Type': 'Textarea', "Type": "Textarea",
'Name': element.get('name'), "Name": element.get("name"),
'Value': element.get_text(strip=True), "Value": element.get_text(strip=True),
} }
label = element.find_previous('label') label = element.find_previous("label")
textarea_info['Label'] = label.get_text(strip=True) if label else None textarea_info["Label"] = label.get_text(strip=True) if label else None
records.append(textarea_info) records.append(textarea_info)
elif element.name == 'button': elif element.name == "button":
button_info = { button_info = {
'Type': 'Button', "Type": "Button",
'Name': element.get('name'), "Name": element.get("name"),
'Value': element.get_text(strip=True), "Value": element.get_text(strip=True),
'Label': element.find_previous('label').get_text(strip=True) if label else None, "Label": element.find_previous("label").get_text(strip=True)
if label
else None,
} }
records.append(button_info) records.append(button_info)
elif element.name == 'table' and 'sme-border' in element.get('class', []): elif element.name == "table" and "sme-border" in element.get("class", []):
# Increment the table counter # Increment the table counter
table_counter += 1 table_counter += 1
@ -132,37 +137,47 @@ def extract_data(html):
columns = [] columns = []
# Extract headings from the first row # Extract headings from the first row
first_row = element.find('tr') first_row = element.find("tr")
if first_row: if first_row:
for th in first_row.find_all('th'): for th in first_row.find_all("th"):
top_headings.append(th.get_text(strip=True)) top_headings.append(th.get_text(strip=True))
# Extract only the first data row's cell values for Columns # Extract only the first data row's cell values for Columns
data_rows = element.find_all('tr')[1:] # Skip the heading row data_rows = element.find_all("tr")[1:] # Skip the heading row
if data_rows: if data_rows:
first_data_row = data_rows[0] # Take the first row of data first_data_row = data_rows[0] # Take the first row of data
for idx, th in enumerate(first_row.find_all('th')): for idx, th in enumerate(first_row.find_all("th")):
td = first_data_row.find_all('td')[idx] if idx < len(first_data_row.find_all('td')) else None td = (
first_data_row.find_all("td")[idx]
if idx < len(first_data_row.find_all("td"))
else None
)
if td: if td:
columns.append(f"{table_control}-{th.get_text(strip=True)}") # Format as desired columns.append(
f"{table_control}-{th.get_text(strip=True)}"
) # Format as desired
records.append({ records.append(
'Type': 'Table', {
'TableControl': table_control, "Type": "Table",
'TopHeadings': top_headings, "TableControl": table_control,
'Columns': columns, "TopHeadings": top_headings,
}) "Columns": columns,
}
)
return records, header_text, sub_header_text return records, header_text, sub_header_text
def insert_spaces_before_caps(text): def insert_spaces_before_caps(text):
"""Insert spaces before each capital letter in a given string.""" """Insert spaces before each capital letter in a given string."""
return re.sub(r'(?<!^)(?=[A-Z])', ' ', text) return re.sub(r"(?<!^)(?=[A-Z])", " ", text)
def save_to_json5(data, output_filename, package_name, header, sub_header): def save_to_json5(data, output_filename, package_name, header, sub_header):
"""Save extracted data to a JSON5 file with a specific structure.""" """Save extracted data to a JSON5 file with a specific structure."""
# Generate prefix from uppercase letters in PackageName made into lowercase # Generate prefix from uppercase letters in PackageName made into lowercase
prefix = ''.join(re.findall(r'[A-Z]', package_name)).lower() prefix = "".join(re.findall(r"[A-Z]", package_name)).lower()
# Prepare structured html list # Prepare structured html list
structured_html = [] structured_html = []
@ -172,103 +187,131 @@ def save_to_json5(data, output_filename, package_name, header, sub_header):
table_count = 1 table_count = 1
for record in data: for record in data:
if record['Type'] == 'Paragraph': if record["Type"] == "Paragraph":
structured_html.append({ structured_html.append({f"Paragraph{paragraph_count}": record["Text"]})
f'Paragraph{paragraph_count}': record['Text']
})
paragraph_count += 1 paragraph_count += 1
elif record['Type'] == 'Preformatted': elif record["Type"] == "Preformatted":
structured_html.append({ structured_html.append(
f'Preformatted{preformatted_count}': record['Text'] {f"Preformatted{preformatted_count}": record["Text"]}
}) )
preformatted_count += 1 preformatted_count += 1
elif record['Type'] == 'Header' or record['Type'] == 'SubHeader': elif record["Type"] == "Header" or record["Type"] == "SubHeader":
continue # Skip headers for input count continue # Skip headers for input count
elif record['Type'] == 'Table': elif record["Type"] == "Table":
# Construct the table entry # Construct the table entry
table_structure = { table_structure = {
'Type': record['Type'], "Type": record["Type"],
'TableControl': record['TableControl'], "TableControl": record["TableControl"],
'TopHeadings': record['TopHeadings'], "TopHeadings": record["TopHeadings"],
'Columns': record['Columns'] "Columns": record["Columns"],
} }
structured_html.append({ structured_html.append({f"Table{table_count}": table_structure})
f'Table{table_count}': table_structure
})
table_count += 1 table_count += 1
else: # For inputs, selects, textareas, and buttons else: # For inputs, selects, textareas, and buttons
input_structure = { input_structure = {
'Type': record['Type'], "Type": record["Type"],
'Value': record.get('Value', ''), # Safely access Value "Value": record.get("Value", ""), # Safely access Value
} }
# Use .get() for the Name key to avoid KeyError # Use .get() for the Name key to avoid KeyError
input_structure['Name'] = record.get('Name', None) # Set to None if not present input_structure["Name"] = record.get(
input_structure['Label'] = record.get('Label', None) # Set to None if not present "Name", None
) # Set to None if not present
input_structure["Label"] = record.get(
"Label", None
) # Set to None if not present
# Handle specific case for Select options # Handle specific case for Select options
if 'Options' in record: if "Options" in record:
input_structure['Options'] = record['Options'] input_structure["Options"] = record["Options"]
structured_html.append({ structured_html.append({f"Input{input_count}": input_structure})
f'Input{input_count}': input_structure
})
input_count += 1 input_count += 1
# Wrap the records with the required fields # Wrap the records with the required fields
json5_data = { json5_data = {
'PackageName': package_name, "PackageName": package_name,
'prefix': prefix, "prefix": prefix,
'MenuHeading': 'Miscellaneous', "MenuHeading": "Miscellaneous",
'MenuDescription': insert_spaces_before_caps(package_name), "MenuDescription": insert_spaces_before_caps(package_name),
'MenuNavigation': '2000 400', "MenuNavigation": "2000 400",
'firstPanel': 'PARAMS', "firstPanel": "PARAMS",
'signalEvent': f'smeserver-{package_name.lower()}-update', "signalEvent": f"smeserver-{package_name.lower()}-update",
'html': { "html": [{
'Name': 'params', "Name": "params",
'route': 'PARAMS', "route": "PARAMS",
'Header': header if header else f'{package_name} Contrib', "Header": header if header else f"{package_name} Contrib",
'SubHeader': sub_header if sub_header else f'Manage {package_name} settings:', "SubHeader": sub_header
**{k: v for item in structured_html for k, v in item.items()} # Flatten the structured_html into the dict if sub_header
} else f"Manage {package_name} settings:",
**{
k: v for item in structured_html for k, v in item.items()
}, # Flatten the structured_html into the dict
}],
} }
# Save in JSON5 format (JSON with comments and unquoted keys) # Save in JSON5 format (JSON with comments and unquoted keys)
with open(output_filename, 'w', encoding='utf-8') as json_file: with open(output_filename, "w", encoding="utf-8") as json_file:
json.dump(json5_data, json_file, ensure_ascii=False, indent=4) json.dump(json5_data, json_file, ensure_ascii=False, indent=4)
# Manually format as JSON5 by adding single quotes (for simplicity) # Manually format as JSON5 by adding single quotes (for simplicity)
with open(output_filename, 'r+', encoding='utf-8') as json_file: with open(output_filename, "r+", encoding="utf-8") as json_file:
content = json_file.read() content = json_file.read()
content = content.replace('"', "'") # Replace double quotes with single quotes for JSON5 content = content.replace(
'"', "'"
) # Replace double quotes with single quotes for JSON5
json_file.seek(0) json_file.seek(0)
json_file.write(content) json_file.write(content)
json_file.truncate() # Remove any old content beyond the new content length json_file.truncate() # Remove any old content beyond the new content length
def main(): def main():
input_file = '/home/brianr/clients/SM2/SM2Gen/venv/html/CreateStarterWebsite.html' # Specify the input HTML file path # command line parameters
parser = argparse.ArgumentParser(description="sm1--html-2-jsopn5")
parser.add_argument(
"-f",
"--filename",
help="Specify a filename for the html file",
default="CreateStarterWebsite.html",
)
args = parser.parse_args()
input_file = "/home/brianr/clients/SM2/SM2Gen/venv/html/" + args.filename
if not input_file.lower().endswith(".html"):
# Add .html extension
input_file += ".html"
print(input_file)
# Read HTML content # Read HTML content
html_content = read_html_file(input_file) html_content = read_html_file(input_file)
# Validate the HTML before extracting data # Validate the HTML before extracting data
validate_html(html_content) validate_html(html_content)
# Extract data from HTML # Extract data from HTML
data, header, sub_header = extract_data(html_content) data, header, sub_header = extract_data(html_content)
#
# Generate output JSON5 filename based on input file name
#
# Split the original path into directory and file name
directory, filename = os.path.split(input_file)
# Generate output JSON5 filename based on input file name # Replace 'html' with 'json5' in the directory path
base_name = os.path.basename(input_file) # Get the file name (with extension) new_directory = directory.replace('/html', '/json5')
package_name = os.path.splitext(base_name)[0] # Use the filename without extension #print(new_directory)
json_filename = package_name + '.json5' # Change extension to .json5
# Create the output file path in the same directory # Construct the new path
output_directory = os.path.dirname(input_file) output_file = os.path.join(new_directory, filename.replace('.html', '.json5'))
output_file = os.path.join(output_directory, json_filename) print(output_file)
#quit(1)
# Save extracted data to JSON5 # Generate output JSON5 filename based on input file name
save_to_json5(data, output_file, package_name, header, sub_header) base_name = os.path.basename(input_file) # Get the file name (with extension)
print(f"Extracted data saved to '{output_file}'.") package_name = os.path.splitext(base_name)[0] # Use the filename without extension
if __name__ == '__main__': # Save extracted data to JSON5
save_to_json5(data, output_file, package_name, header, sub_header)
print(f"Extracted data saved to '{output_file}'.")
if __name__ == "__main__":
main() main()

697
sm2gen.py
View File

@ -306,371 +306,384 @@ def convert_lex_to_dict(pairs_string):
if __name__ == "__main__": if __name__ == "__main__":
try: try:
chameleon_version = pkg_resources.get_distribution("Chameleon").version chameleon_version = pkg_resources.get_distribution("Chameleon").version
except pkg_resources.DistributionNotFound: except pkg_resources.DistributionNotFound:
chameleon_version = "Version information not available" chameleon_version = "Version information not available"
python_version = sys.version python_version = sys.version
version_pattern = r'(\d{1,3}\.\d{1,3}\.\d{1,3})' version_pattern = r"(\d{1,3}\.\d{1,3}\.\d{1,3})"
version_match = re.search(version_pattern, python_version) version_match = re.search(version_pattern, python_version)
python_version = version_match.group(0) if version_match else 'Unknown' python_version = version_match.group(0) if version_match else "Unknown"
current_datetime = datetime.now() current_datetime = datetime.now()
formatted_datetime = current_datetime.strftime("%Y-%m-%d %H:%M") formatted_datetime = current_datetime.strftime("%Y-%m-%d %H:%M")
strVersion = ( strVersion = (
"SM2Gen version:" "SM2Gen version:"
+ SME2Gen_version + SME2Gen_version
+ " Chameleon version:" + " Chameleon version:"
+ chameleon_version + chameleon_version
+ " On Python:" + " On Python:"
+ python_version + python_version
+ " at " + " at "
+ formatted_datetime + formatted_datetime
) )
json5_dict: dict = {} json5_dict: dict = {}
json5_html_list: list = [] json5_html_list: list = []
print(f"SM2 code from JSON5 - {strVersion}") print(f"SM2 code from JSON5 - {strVersion}")
home_dir = "/home/brianr/clients/SM2/SM2Gen/" home_dir = "/home/brianr/clients/SM2/SM2Gen/"
json_filename = f"{home_dir}/json5/nfsshare.json5" #CreateStarterWebsite.json5" json_filename = f"{home_dir}/json5/nfsshare.json5" # CreateStarterWebsite.json5"
# read open ai key from ini file # read open ai key from ini file
# Check if the file exists # Check if the file exists
if os.path.exists(ini_file_path): if os.path.exists(ini_file_path):
# Create a configparser object and read the file # Create a configparser object and read the file
config = configparser.ConfigParser() config = configparser.ConfigParser()
config.read(ini_file_path) config.read(ini_file_path)
# Read the value of "OPENAI_API_KEY" # Read the value of "OPENAI_API_KEY"
if "OPENAI_API_KEY" in config["smegit"]: if "OPENAI_API_KEY" in config["smegit"]:
OPENAI_API_KEY = config["smegit"]["OPENAI_API_KEY"] OPENAI_API_KEY = config["smegit"]["OPENAI_API_KEY"]
# print("API Key:", OPENAI_API_KEY) # print("API Key:", OPENAI_API_KEY)
client = OpenAI(api_key=OPENAI_API_KEY) client = OpenAI(api_key=OPENAI_API_KEY)
else: else:
print("OPENAI_API_KEY not found in the configuration file.") print("OPENAI_API_KEY not found in the configuration file.")
else: else:
print("Configuration file not found at:", file_path) print("Configuration file not found at:", file_path)
# Command line parameters - not in use # Command line parameters - not in use
parser = argparse.ArgumentParser(description="SM2Gen") parser = argparse.ArgumentParser(description="SM2Gen")
parser.add_argument( parser.add_argument(
"-f", "-f",
"--filename", "--filename",
help="Specify a filename for the JSON5 file", help="Specify a filename for the JSON5 file",
default=json_filename, default=json_filename,
) )
parser.add_argument( parser.add_argument(
"-nco", "-nco",
"--noController", "--noController",
help="Stop it creating a controller file", help="Stop it creating a controller file",
default="yes", default="yes",
) )
parser.add_argument( parser.add_argument(
"-nh", "--noHtml", help="Stop it creating html files(s)", default="yes" "-nh", "--noHtml", help="Stop it creating html files(s)", default="yes"
) )
parser.add_argument( parser.add_argument(
"-nl", "-nl",
"--noLang", "--noLang",
help="Stop it creating language localise files(s)", help="Stop it creating language localise files(s)",
default="yes", default="yes",
) )
parser.add_argument( parser.add_argument(
"-ncu", "--noCust", help="Stop it creating Custom controller file", default="yes" "-ncu",
) "--noCust",
args = parser.parse_args() help="Stop it creating Custom controller file",
json_filename = args.filename default="yes",
print( )
f"JSON5 from {json_filename} with noController={args.noController}, noHtml={args.noHtml} and noLang={args.noLang}" args = parser.parse_args()
) # Not yet activated json_filename = args.filename
print(
f"JSON5 from {json_filename} with noController={args.noController}, noHtml={args.noHtml} and noLang={args.noLang}"
) # Not yet activated
#check if json5 file exists # check if json5 file exists
json_file_path = Path(json_filename) json_file_path = Path(json_filename)
if not json_file_path.exists(): if not json_file_path.exists():
print(f"json5 file: {json_filename} not found") print(f"json5 file: {json_filename} not found")
quit(1) quit(1)
# check syntax of JSON5 # check syntax of JSON5
lint_json5(json_filename) lint_json5(json_filename)
# Get dict of it all # Get dict of it all
json5_dict = json5_to_dict(json_filename) json5_dict = json5_to_dict(json_filename)
# Get dict of just the html bit # Get dict of just the html bit
json5_html_list = json5_dict["html"] json5_html_list = json5_dict["html"]
# Identify message # Identify message
print(f"\nGenerating mojo panels for {hl('PackageName')}") print(f"\nGenerating mojo panels for {hl('PackageName')}")
print("-----------------------------------") print("-----------------------------------")
# Routes for each panel # Routes for each panel
routes = get_all_routes() routes = get_all_routes()
lc_routes = lc_get_all_routes() lc_routes = lc_get_all_routes()
# File names # File names
# Define the path for the generated files # Define the path for the generated files
directory_path = Path("Targets/" + hl("PackageName")) directory_path = Path("Targets/" + hl("PackageName"))
# Create the directory if it doesn't exist # Create the directory if it doesn't exist
directory_path.mkdir(parents=True, exist_ok=True) directory_path.mkdir(parents=True, exist_ok=True)
target_directory_path = "Targets/" + hl("PackageName")+"/" target_directory_path = "Targets/" + hl("PackageName") + "/"
controller_file = target_directory_path + hl("PackageName") + ".pm" controller_file = target_directory_path + hl("PackageName") + ".pm"
custom_controller_file = target_directory_path + hl("PackageName") + "-Custom.pm" custom_controller_file = target_directory_path + hl("PackageName") + "-Custom.pm"
# Call it .new if one is already there (and may have been editted by the developer) # Call it .new if one is already there (and may have been editted by the developer)
if os.path.exists(custom_controller_file): if os.path.exists(custom_controller_file):
custom_controller_file = custom_controller_file + ".new" custom_controller_file = custom_controller_file + ".new"
layout_file = target_directory_path + hl("PackageName").lower() + ".html.ep" layout_file = target_directory_path + hl("PackageName").lower() + ".html.ep"
partial_files = list() partial_files = list()
for panel in routes: for panel in routes:
partial_files.append(target_directory_path + hl("prefix") + "_" + panel + ".html.ep") partial_files.append(
print(f"Partial files to be created:{partial_files}") target_directory_path + '_' + hl("prefix") + "_" + panel + ".html.ep"
lex_file = target_directory_path + hl("PackageName").lower() + "_en.lex" )
tablecontrols = ( print(f"Partial files to be created:{partial_files}")
get_table_control_data() lex_file = target_directory_path + hl("PackageName").lower() + "_en.lex"
) # arrays of hashes used to drive rows in tables tablecontrols = (
get_table_control_data()
) # arrays of hashes used to drive rows in tables
# print(strVersion,tablecontrols,routes) # print(strVersion,tablecontrols,routes)
# Generate controller file # Generate controller file
try: try:
controller_template = PageTemplateFile("Templates/controller.pm.tem",CHAMELEON_DEBUG="true") controller_template = PageTemplateFile(
dbentries = get_db_fields() # Params which correspond to Db fields "Templates/controller.pm.tem", CHAMELEON_DEBUG="true"
try: )
controller_perl = controller_template.render( dbentries = get_db_fields() # Params which correspond to Db fields
version=strVersion, try:
tablecontrols=tablecontrols, controller_perl = controller_template.render(
dbentries=dbentries, version=strVersion,
**json5_dict, tablecontrols=tablecontrols,
panels=routes, dbentries=dbentries,
lcPackageName=json5_dict["PackageName"].lower(), **json5_dict,
) panels=routes,
with open(controller_file, "w") as file: lcPackageName=json5_dict["PackageName"].lower(),
file.write(controller_perl) )
print(f"{controller_file} controller generated ok") with open(controller_file, "w") as file:
except Exception as e: file.write(controller_perl)
print(f"A Chameleon controller render error occurred: {e}") print(f"{controller_file} controller generated ok")
except Exception as e: except Exception as e:
print(f"A Chameleon controller template error occurred: {e}") print(f"A Chameleon controller render error occurred: {e}")
except Exception as e:
print(f"A Chameleon controller template error occurred: {e}")
# Generate Custom controller file # Generate Custom controller file
try: try:
custom_controller_template = PageTemplateFile("Templates/custom.pm.tem") custom_controller_template = PageTemplateFile("Templates/custom.pm.tem")
try: try:
custom_controller_perl = custom_controller_template.render( custom_controller_perl = custom_controller_template.render(
version=strVersion, panels=routes, tablecontrols=tablecontrols version=strVersion, panels=routes, tablecontrols=tablecontrols
) )
# We must be careful to not overwrite the custom file if the developer has already written to it - TBD # 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: with open(custom_controller_file, "w") as file:
file.write(custom_controller_perl) file.write(custom_controller_perl)
print(f"{custom_controller_file} custom controller generated ok") print(f"{custom_controller_file} custom controller generated ok")
except Exception as e: except Exception as e:
print(f"A Chameleon custom controller render error occurred: {e}") print(f"A Chameleon custom controller render error occurred: {e}")
except Exception as e: except Exception as e:
print(f"A Chameleon custom controller template error occurred: {e}") print(f"A Chameleon custom controller template error occurred: {e}")
# generate Layout file # generate Layout file
layout_template = PageTemplateFile("Templates/layout.html.ep.tem") layout_template = PageTemplateFile("Templates/layout.html.ep.tem")
try: try:
try: try:
layout_mojo = layout_template.render( layout_mojo = layout_template.render(
version=strVersion, **json5_dict, conditions=routes version=strVersion, **json5_dict, conditions=routes
) )
with open(layout_file, "w") as file: with open(layout_file, "w") as file:
file.write(layout_mojo) file.write(layout_mojo)
print(f"{layout_file} mojo template layout file generated ok") print(f"{layout_file} mojo template layout file generated ok")
except Exception as e: except Exception as e:
print(f"A Chameleon render on layout file error occurred: {e}") print(f"A Chameleon render on layout file error occurred: {e}")
except Exception as e: except Exception as e:
print(f"A Chameleon template layout file error occurred: {e}") print(f"A Chameleon template layout file error occurred: {e}")
# Generate a partial file for each of the entries in the html list # Generate a partial file for each of the entries in the html list
# Pull in the template code for each of the input types # Pull in the template code for each of the input types
# html_controls = json5_to_dict('Templates/html_controls.html.ep.tem') # html_controls = json5_to_dict('Templates/html_controls.html.ep.tem')
html_controls = parse_xml_to_dict("Templates/html_controls.html.ep.xml") html_controls = parse_xml_to_dict("Templates/html_controls.html.ep.xml")
i = 0 i = 0
for html in json5_html_list: for html in json5_html_list:
# Generate a mojo template file, and then add in the controls # Generate a mojo template file, and then add in the controls
# main file first # main file first
try: try:
partial_template = PageTemplateFile("Templates/partial.html.ep.tem") partial_template = PageTemplateFile("Templates/partial.html.ep.tem")
partial_mojo_context = {**json5_dict, **html} partial_mojo_context = {**json5_dict, **html}
try: try:
partial_mojo_template = partial_template.render( partial_mojo_template = partial_template.render(
version=strVersion, **partial_mojo_context version=strVersion, **partial_mojo_context
) )
with open(partial_files[i], "w") as file: with open(partial_files[i], "w") as file:
file.write(partial_mojo_template) file.write(partial_mojo_template)
print(f"{partial_files[i]} mojo template generated ok - phase 1") print(f"{partial_files[i]} mojo template generated ok - phase 1")
except Exception as e: except Exception as e:
print( print(
f"A Chameleon render error on partial file {html['route']} occurred: {e}" f"A Chameleon render error on partial file {html['route']} occurred: {e}"
) )
except Exception as e: except Exception as e:
print(f"A Chameleon html {html['route']} error occurred: {e}") print(f"A Chameleon html {html['route']} error occurred: {e}")
# Now generate the controls from the rest of the entries in the dict. # Now generate the controls from the rest of the entries in the dict.
all_controls_html = "" all_controls_html = ""
prefix_is = hl("prefix") prefix_is = hl("prefix")
for html_control in html: for html_control in html:
inner_html = html[html_control] inner_html = html[html_control]
if isinstance(inner_html, dict): if isinstance(inner_html, dict):
try: try:
control_template = PageTemplate(html_controls[inner_html["Type"]]) control_template = PageTemplate(html_controls[inner_html["Type"]])
try: try:
control_html = control_template.render( control_html = control_template.render(
version=strVersion, **inner_html, prefix=prefix_is version=strVersion, **inner_html, prefix=prefix_is
) )
all_controls_html = all_controls_html + control_html all_controls_html = all_controls_html + control_html
except Exception as e: except Exception as e:
print( print(
f"A Chameleon render on partial file control {inner_html['Name']} error occurred: {e}" f"A Chameleon render on partial file control {inner_html['Name']} error occurred: {e}"
) )
except Exception as e: except Exception as e:
print( print(
f"A Chameleon render on partial file control {inner_html['Name']} error occurred: {e}" f"A Chameleon render on partial file control {inner_html['Name']} error occurred: {e}"
) )
else: else:
# just a simple entry - name less numerics is type # just a simple entry - name less numerics is type
html_Type = "".join(char for char in html_control if not char.isdigit()) html_Type = "".join(char for char in html_control if not char.isdigit())
try: try:
simple_control_template = PageTemplate(html_controls[html_Type]) simple_control_template = PageTemplate(html_controls[html_Type])
try: try:
simple_control_html = simple_control_template.render( simple_control_html = simple_control_template.render(
version=strVersion, value=inner_html, prefix=prefix_is version=strVersion, value=inner_html, prefix=prefix_is
) )
all_controls_html = all_controls_html + simple_control_html all_controls_html = all_controls_html + simple_control_html
except Exception as e: except Exception as e:
print( print(
f"A Chameleon render on partial file control {html_control} error occurred: {e}" f"A Chameleon render on partial file control {html_control} error occurred: {e}"
) )
except Exception as e: except Exception as e:
print( print(
f"A Chameleon template partial file control {html_control} error occurred: {e}" f"A Chameleon template partial file control {html_control} error occurred: {e}"
) )
# Now insert it into the partial file in the correct place. # Now insert it into the partial file in the correct place.
# Read in the text file and split at "%# Inputs etc in here." # Read in the text file and split at "%# Inputs etc in here."
with open(partial_files[i], "r") as file: with open(partial_files[i], "r") as file:
lines = file.readlines() lines = file.readlines()
index = next( index = next(
(i for i, line in enumerate(lines) if "%# Inputs etc in here." in line), (i for i, line in enumerate(lines) if "%# Inputs etc in here." in line),
len(lines), len(lines),
) )
# Insert the string at the specified index # Insert the string at the specified index
lines.insert(index + 1, all_controls_html + "\n") lines.insert(index + 1, all_controls_html + "\n")
# Write the modified content back to the file # Write the modified content back to the file
with open(partial_files[i], "w") as file: with open(partial_files[i], "w") as file:
file.writelines(lines) file.writelines(lines)
print(f"Content modified and saved to {partial_files[i]}") print(f"Content modified and saved to {partial_files[i]}")
i += 1 i += 1
# Now generate the <name>.en file # Now generate the <name>.en file
# Look through the generated files for the /l[\s|(]['|"](.*)['|"]\)/ strings. # Look through the generated files for the /l[\s|(]['|"](.*)['|"]\)/ strings.
# create a combined list of all the files # create a combined list of all the files
all_files = [controller_file, layout_file] + partial_files all_files = [controller_file, layout_file] + partial_files
all_strings = [] all_strings = []
for filename in all_files: for filename in all_files:
with open(filename, "r") as file: with open(filename, "r") as file:
file_content = file.read() file_content = file.read()
# Define the regular expression pattern to match the strings you want to extract # Define the regular expression pattern to match the strings you want to extract
pattern = r"l[\s|(][\'|\"](.*)[\'|\"]\)" pattern = r"l[\s|(][\'|\"](.*)[\'|\"]\)"
# Use re.findall to extract all occurrences of the pattern from the file content # Use re.findall to extract all occurrences of the pattern from the file content
extracted_strings = re.findall(pattern, file_content) extracted_strings = re.findall(pattern, file_content)
all_strings = all_strings + extracted_strings all_strings = all_strings + extracted_strings
# Take out any duplicates # Take out any duplicates
all_strings = deduplicate_array(all_strings) all_strings = deduplicate_array(all_strings)
# '<prefix>_english-message' => 'English Message', # '<prefix>_english-message' => 'English Message',
string_lib = [] # Array of dicts string_lib = [] # Array of dicts
for lex_message in all_strings: for lex_message in all_strings:
# If has a prefix - leave it for left hand side but delete it for the right # If has a prefix - leave it for left hand side but delete it for the right
# If has no prefix - add one for left hand side but and leave it for the right # If has no prefix - add one for left hand side but and leave it for the right
# Map all spaces to "_" on left hand side # Map all spaces to "_" on left hand side
# amd truncate it to max five words # amd truncate it to max five words
original_str = lex_message original_str = lex_message
# Checkif it starts with the prefix (any case|) # Checkif it starts with the prefix (any case|)
if lex_message.lower().startswith(hl("prefix").lower()): if lex_message.lower().startswith(hl("prefix").lower()):
left_str = lex_message left_str = lex_message
right_str = lex_message[len(hl("prefix")) + 1 :] right_str = lex_message[len(hl("prefix")) + 1 :]
# And take out any "_", map to " " # And take out any "_", map to " "
else: else:
left_str = hl("prefix") + "_" + lex_message left_str = hl("prefix") + "_" + lex_message
right_str = lex_message right_str = lex_message
right_str = right_str.replace("_", " ") right_str = right_str.replace("_", " ")
# print(f"Right:{right_str}") # print(f"Right:{right_str}")
right_str = format_text(right_str) right_str = format_text(right_str)
left_str = left_str.replace(" ", "_") left_str = left_str.replace(" ", "_")
words = left_str.split("_")[:6] words = left_str.split("_")[:6]
left_str = "_".join(words) left_str = "_".join(words)
next_lex_str = {"orig": original_str, "left": left_str, "right": right_str} next_lex_str = {"orig": original_str, "left": left_str, "right": right_str}
string_lib.append(next_lex_str) string_lib.append(next_lex_str)
# And write it to lex file # And write it to lex file
# Now process them one by one into the lexical file # Now process them one by one into the lexical file
lex_all = "" lex_all = ""
for lex_str in string_lib: for lex_str in string_lib:
lex_all += f"'{lex_str['left']}' => '{lex_str['right']}',\n" lex_all += f"'{lex_str['left']}' => '{lex_str['right']}',\n"
print(f"Writing {lex_file}") print(f"Writing {lex_file}")
with open(lex_file, "w") as file: with open(lex_file, "w") as file:
file.write(lex_all) file.write(lex_all)
# and then play the strings back into the partials and the layout file # and then play the strings back into the partials and the layout file
print("..and feed the lex string names back into other files") print("..and feed the lex string names back into other files")
for filename in all_files: for filename in all_files:
with open(filename, "r") as file: with open(filename, "r") as file:
file_content = file.read() file_content = file.read()
# Scan through # Scan through
for item in string_lib: for item in string_lib:
original_str = item["orig"] original_str = item["orig"]
left_str = item["left"] left_str = item["left"]
right_str = item["right"] right_str = item["right"]
# Replace all occurrences of original string with left string in 'contents' # Replace all occurrences of original string with left string in 'contents'
file_content = file_content.replace( file_content = file_content.replace(
"l('" + original_str + "')", "l('" + left_str + "')" "l('" + original_str + "')", "l('" + left_str + "')"
) )
# and write it back # and write it back
with open(filename, "w") as file: with open(filename, "w") as file:
file.write(file_content) file.write(file_content)
print(f"Write out modified:{filename}") print(f"Write out modified:{filename}")
# Now generate all the translated lex files from a list of the languages and codes # Now generate all the translated lex files from a list of the languages and codes
# if specifically requested # if specifically requested
if not args.noLang: if not args.noLang:
languages_path = "Templates/languages.json" languages_path = "Templates/languages.json"
with open(languages_path, "r") as file: with open(languages_path, "r") as file:
languages_str = file.read() languages_str = file.read()
lang_dict = json.loads(languages_str) lang_dict = json.loads(languages_str)
with open(lex_file, "r") as file: with open(lex_file, "r") as file:
lex_str = file.read() lex_str = file.read()
eng_lex_dict = convert_lex_to_dict(lex_str) eng_lex_dict = convert_lex_to_dict(lex_str)
for lang_item in lang_dict: for lang_item in lang_dict:
print(f"Translating from english lex file to {lang_item['language']}") print(f"Translating from english lex file to {lang_item['language']}")
code = lang_item["code"] code = lang_item["code"]
translated_lex_file = f"{target_directory_path}{hl('PackageName').lower()}_{code}.lex" translated_lex_file = (
# Only do it if the lex file is missing f"{target_directory_path}{hl('PackageName').lower()}_{code}.lex"
if not os.path.exists(translated_lex_file): )
translated_dict = [] # Only do it if the lex file is missing
for lex_item in eng_lex_dict: if not os.path.exists(translated_lex_file):
# Get it from ChatGPT translated_dict = []
translated_text = get_translation( for lex_item in eng_lex_dict:
lex_item["text"], lang_item["language"] # Get it from ChatGPT
) translated_text = get_translation(
translated_dict.append({"id": lex_item["id"], "text": translated_text}) lex_item["text"], lang_item["language"]
print(f"Writing out lex file for {lang_item['code']}") )
with open(translated_lex_file, "w") as file: translated_dict.append(
for item in translated_dict: {"id": lex_item["id"], "text": translated_text}
# escape any nasties )
translated_text = ( print(f"Writing out lex file for {lang_item['code']}")
item["text"] with open(translated_lex_file, "w") as file:
.replace("\\", r"\\") for item in translated_dict:
.replace('"', r"\"") # escape any nasties
.replace("'", r"\'") translated_text = (
) item["text"]
line = "'" + item["id"] + "' => " + '"' + translated_text + '",\n' .replace("\\", r"\\")
file.write(line) .replace('"', r"\"")
# print(f"{item['id']} => {item['text']}\n") .replace("'", r"\'")
else: )
print( line = (
f"Skipping the creation of {translated_lex_file} as it exists already" "'" + item["id"] + "' => " + '"' + translated_text + '",\n'
) )
quit() # end of the program file.write(line)
# print(f"{item['id']} => {item['text']}\n")
else:
print(
f"Skipping the creation of {translated_lex_file} as it exists already"
)
quit() # end of the program