From 83825b76a210cf0403763c2955b562c1f9c4439f Mon Sep 17 00:00:00 2001 From: Thierry Parmentelat Date: Fri, 13 Nov 2009 10:52:31 +0000 Subject: [PATCH] (*) slices list has links towards the slice page with the details area closed and the nodes area open (*) slice page reviewed for displaying node status and optional node tags tags displayed are the ones for which the category matches 'node*/ui*' the category may also convey tunings for rendering the column (*) cosmetics in the slice page renewal area (*) nodegroups : UI can now add/delete/update nodegroups managing the contents of a nodegroup still can be tedious though (*) tag page fixed, slice/sliver count was wrong, was not showing nodegroups --- planetlab/common/actions.php | 72 +++++++++++++++++++++++ planetlab/css/my_slice.css | 15 ++++- planetlab/includes/plc_functions.php | 16 +++-- planetlab/slices/slice.php | 88 ++++++++++++++++++++++++---- planetlab/slices/slices.php | 2 +- planetlab/tags/nodegroup.php | 14 ++++- planetlab/tags/nodegroups.php | 48 +++++++++++++-- planetlab/tags/tag.php | 72 ++++++++++++++++++----- planetlab/tags/tags.php | 14 +++-- 9 files changed, 292 insertions(+), 49 deletions(-) diff --git a/planetlab/common/actions.php b/planetlab/common/actions.php index a2dfd11..2717d1e 100644 --- a/planetlab/common/actions.php +++ b/planetlab/common/actions.php @@ -108,6 +108,14 @@ $known_actions []= "delete-node-tags"; $known_actions []= "delete-interface-tags"; // expects: interface_id & interface_tag_ids +//////////////////////////////////////// nodegroups +$known_actions []= "update-nodegroup"; +// expects nodegroup_id groupname value +$known_actions []= "add-nodegroup"; +// expects groupname, tag_type_id, value +$known_actions []= 'delete-nodegroups'; +// expects nodegroup_ids + //////////////////////////////////////////////////////////// $interface_details= array ('method','type', 'ip', 'gateway', 'network', 'broadcast', 'netmask', 'dns1', 'dns2', @@ -717,6 +725,7 @@ Our support team will be glad to answer any question that you might have. else drupal_set_error ("Could not update tag type $tag_type_id\n".$api->error()); plc_redirect(l_tag($tag_type_id)); + break; } case 'add-tag-type': { @@ -740,6 +749,7 @@ Our support team will be glad to answer any question that you might have. else drupal_set_error ("Could not create tag type $tagname"); plc_redirect( l_tags()); + break; } case 'delete-tag-types': { @@ -853,6 +863,68 @@ Our support team will be glad to answer any question that you might have. plc_redirect(l_interface($_POST['interface_id'])); } +//////////////////////////////////////// nodegroups + case 'update-nodegroup': { + $nodegroup_id = $_POST['nodegroup_id']; + $groupname = $_POST['groupname']; + $value = $_POST['value']; + + $fields=array(); + $fields['groupname']=$groupname; + $fields['value']=$value; + if ( $api->UpdateNodeGroup($nodegroup_id,$fields) == 1) + drupal_set_message ('Nodegroup updated'); + else + drupal_set_error ("Could not update nodegroup $groupname"); + + plc_redirect(l_nodegroup($nodegroup_id)); + + } + + case 'add-nodegroup': { + $groupname=$_POST['groupname']; + if ( ! $groupname ) { + drupal_set_error ('Empty groupname'); + plc_redirect (l_nodegroups()); + } + $tag_type_id=intval($_POST['tag_type_id']); + if ( ! $tag_type_id ) { + drupal_set_error ('You must select a tag in the dropdown list'); + plc_redirect (l_nodegroups()); + } + $value=$_POST['value']; + if ( ! $value ) { + drupal_set_message ("Empty value.. let's see .."); + } + if ( $api->AddNodeGroup ($groupname,$tag_type_id,$value) > 0) + drupal_set_message ("Nodegroup $groupname created"); + else + drupal_set_error ("Could not create nodegroup $groupname"); + + plc_redirect (l_nodegroups()); + break; + } + + case 'delete-nodegroups': { + $nodegroup_ids=$_POST['nodegroup_ids']; + if ( ! $nodegroup_ids ) { + drupal_set_message("action=delete-nodegroups - No group selected"); + plc_redirect(l_nodegroups()); + } + $success=true; + $counter=0; + foreach ($nodegroup_ids as $nodegroup_id) + if ($api->DeleteNodeGroup(intval($nodegroup_id)) != 1) + $success=false; + else + $counter++; + if ($success) + drupal_set_message ("Deleted $counter group(s)"); + else + drupal_set_error ("Could not delete all selected groups, only $counter were removed"); + plc_redirect (l_nodegroups()); + break; + } //////////////////////////////////////// diff --git a/planetlab/css/my_slice.css b/planetlab/css/my_slice.css index b41ee06..fa07f33 100644 --- a/planetlab/css/my_slice.css +++ b/planetlab/css/my_slice.css @@ -9,10 +9,19 @@ div.my-slice-renewal { /* internal toggles */ div#toggle-container-my-slice-persons-current, +div#toggle-container-my-slice-nodes-current { + background: #f0f0f0; +} + div#toggle-container-my-slice-persons-add, -div#toggle-container-my-slice-nodes-current, div#toggle-container-my-slice-nodes-add { -/* background:#fcf7ff; */ - background: #ccffc7; + background: #f0e0e0; } +/* qualify enough so that this wins over the even/odd row patterns in tables */ +tbody>tr>td.node-ok { + background: #a0f0e6; +} +tbody>tr>td.node-ko { + background: #ffa7a8; +} diff --git a/planetlab/includes/plc_functions.php b/planetlab/includes/plc_functions.php index 4f10e8c..53600ae 100644 --- a/planetlab/includes/plc_functions.php +++ b/planetlab/includes/plc_functions.php @@ -105,6 +105,7 @@ function l_site_obj($site) { return href (l_site($site['site_id']),$site['name' function l_slices () { return "/db/slices/index.php"; } function l_slices_peer ($peer_id) { return "/db/slices/index.php?peerscope=$peer_id"; } function l_slice ($slice_id) { return "/db/slices/index.php?id=$slice_id"; } +function l_slice_nodes ($slice_id) { return "/db/slices/index.php?id=$slice_id&show_details=0&show_nodes=1&show_nodes_current=1&show_nodes_add=1"; } function l_slice_t ($slice_id,$text) { return href (l_slice($slice_id),$text); } function l_slice_add () { return "/db/slices/slice_add.php"; } function l_slices_site($site_id) { return "/db/slices/index.php?site_id=$site_id"; } @@ -134,6 +135,8 @@ function l_nodegroups () { return "/db/tags/nodegroups.php"; } function l_nodegroup ($nodegroup_id) { return "/db/tags/nodegroup.php?id=$nodegroup_id"; } function l_nodegroup_t ($nodegroup_id,$text) { return href(l_nodegroup($nodegroup_id),$text); } +function l_nodegroup_obj ($nodegroup) { + return href(l_nodegroup($nodegroup['nodegroup_id']),$nodegroup['groupname']); } function l_events () { return "/db/events/index.php"; } function l_event ($type,$param,$id) { return "/db/events/index.php?type=$type&$param=$id"; } @@ -360,12 +363,15 @@ function truncate ($text,$numb,$etc = "...") { } return $text; } -function html_div ($text,$class="") { - $html=" (text) +function html_atom ($atom,$text,$class="") { + $html="<$atom"; if ($class) $html .= " class='$class'"; - $html .= ">$text"; + $html .= ">$text"; return $html; } +function html_div ($text,$class="") { return html_atom ('div',$text,$class); } +function html_span ($text,$class="") { return html_atom ('span',$text,$class); } // should use the same channel as the php errors.. function plc_error_html ($text) { return html_div ($text,'plc-error'); } @@ -391,10 +397,10 @@ function errors_display ($errors) { } } -function plc_warning_html ($text) { return "" . $text . "";} +function plc_warning_html ($text) { return html_span($text,'plc-warning'); } function plc_warning ($text) { print plc_warning_html("Warning " . $text); } -function bold_html ($text) { return "$text"; } +function bold_html ($text) { return html_span($text,'bold'); } // shows a php variable verbatim with a heading message function plc_debug ($message,$object) { diff --git a/planetlab/slices/slice.php b/planetlab/slices/slice.php index 45afc94..9649136 100644 --- a/planetlab/slices/slice.php +++ b/planetlab/slices/slice.php @@ -96,12 +96,14 @@ function renew_area ($slice,$site,$visible) { global $DAY, $WEEK, $MAX_WEEKS, $GRACE_DAYS, $NOW; $current_exp=$slice['expires']; + $current_text = gmstrftime("%A %b-%d-%y %T %Z", $current_exp); $max_exp= $NOW + ($MAX_WEEKS * $WEEK); // seconds since epoch + $max_text = gmstrftime("%A %b-%d-%y %T %Z", $max_exp); // xxx some extra code needed to enable this area only if the slice description is OK: // description and url must be non void $toggle= - new PlekitToggle('renew',"Renew this slice", + new PlekitToggle('renew',"Expires $current_text - Renew this slice", array("bubble"=> "Enter this zone if you wish to renew your slice", 'visible'=>$visible)); @@ -142,8 +144,9 @@ EOF; if ( empty( $selectors ) ) { print <<< EOF -
-Slice cannot be renewed any further into the future, try again closer to expiration date. +
+Slices annot be renewed more than $MAX_WEEKS weeks from now, i.e. not beyond $max_text. +For this reason, the current slice cannot be renewed any further into the future, try again closer to expiration date.
EOF; } else { @@ -373,9 +376,47 @@ if ($privileges) { } $toggle->end(); -//////////////////// nodes +//////////////////////////////////////////////////////////// Nodes +// the nodes details to display here +// (1) we search for the tag types for which 'category' matches 'node*/ui*' +// all these tags will then be tentatively displayed in this area +// (2) further information can also be optionally specified in the category: +// (.) we split the category with '/' and search for assignments of the form var=value +// (.) header can be set to supersede the column header (default is tagname) +// (.) rank can be used for ordering the columns (default is tagname) +// (.) type is passed to the javascript table, for sorting (default is 'string') + // minimal list as a start -$node_columns = array('hostname','node_id','arch','peer_id','slice_ids_whitelist'); +$node_fixed_columns = array('hostname','node_id','peer_id','slice_ids_whitelist','run_level','boot_state'); +// scan tag types to find relevant additional columns +$nodeui_tag_types = $api->GetTagTypes(array('category'=>'node*/ui*')); +// extract tagname +$node_tag_columns = array_map(create_function('$tt','return $tt["tagname"];'),$nodeui_tag_types); +// build an ordered list of chunks {'tagname','header','rank','description'} +$more_tags = array(); +foreach ($nodeui_tag_types as $tag_type) { + $tagname=$tag_type['tagname']; + $chunk=array(); + $chunk['tagname']=$tagname; + $chunk['header']=$tagname; + $chunk['rank']=$tagname; + $chunk['type']='string'; + $chunk['description']=$tag_type['description']; + $category_tokens=split('/',$tag_type['category']); + foreach ($category_tokens as $token) { + $assign=split('=',$token); + if (count($assign)==2) + $chunk[$assign[0]]=$assign[1]; + } + $more_tags []= $chunk; +} + +function sort_chunks ($ch1, $ch2) { return strcmp($ch1['rank'],$ch2['rank']); } +usort ($more_tags, sort_chunks); + +//plc_debug('ordered additional tags',$more_tags); + +$node_columns=array_merge($node_fixed_columns,$node_tag_columns); $nodes=$api->GetNodes(array('node_id'=>$slice['node_ids']),$node_columns); $potential_nodes=$api->GetNodes(array('~node_id'=>$slice['node_ids']),$node_columns); $count=count($nodes); @@ -394,15 +435,22 @@ $toggle_nodes=new PlekitToggle('my-slice-nodes-current', $toggle_nodes->start(); $headers=array(); +$notes=array(); $headers['peer']='string'; $headers['hostname']='string'; -$headers['arch']='string'; +$headers['S']='string'; +$notes[]='S = last known status'; +foreach ($more_tags as $chunk) { + $header=$chunk['header']; + $headers[$header]=$chunk['type']; + if ($header != $chunk['tagname']) $notes []= $header . ' = ' . $chunk['description']; +} if ($privileges) $headers[plc_delete_icon()]="none"; -$table_options = array('notes_area'=>false, +$table_options = array('notes'=>$notes, 'search_width'=>15, 'pagesize'=>20); -$table=new PlekitTable('nodes',$headers,'0',$table_options); +$table=new PlekitTable('nodes',$headers,'1',$table_options); $form=new PlekitForm(l_actions(),array('slice_id'=>$slice['slice_id'])); $form->start(); @@ -411,7 +459,12 @@ if ($nodes) foreach ($nodes as $node) { $table->row_start(); $peers->cell($table,$node['peer_id']); $table->cell(l_node_obj($node)); - $table->cell($node['arch']); + $run_level=$node['run_level']; + if ( empty($run_level)) $run_level=$node['boot_state']; + $class=($run_level == 'boot') ? 'node-ok' : 'node-ko'; + $table->cell($run_level,array('class'=>$class)); + foreach ($more_tags as $chunk) $table->cell($node[$chunk['tagname']]); + if ($privileges) $table->cell ($form->checkbox_html('node_ids[]',$node['node_id'])); $table->row_end(); } @@ -443,7 +496,7 @@ if ($privileges) { $count=count($potential_nodes); $toggle_nodes=new PlekitToggle('my-slice-nodes-add', "$count more nodes available", - array('visible'=>get_arg('show_persons_add',false))); + array('visible'=>get_arg('show_nodes_add',false))); $toggle_nodes->start(); if ( ! $potential_nodes ) { @@ -451,9 +504,16 @@ if ($privileges) { echo "

No node to add

"; } else { $headers=array(); + $notes=array(); $headers['peer']='string'; $headers['hostname']='string'; - $headers['arch']='string'; + $headers['S']='string'; + $notes[]='S = last known status'; + foreach ($more_tags as $chunk) { + $header=$chunk['header']; + $headers[$header]=$chunk['type']; + if ($header != $chunk['tagname']) $notes []= $header . ' = ' . $chunk['description']; + } $headers['+']="none"; $table=new PlekitTable('add_nodes',$headers,'1', $table_options); @@ -465,7 +525,11 @@ if ($privileges) { $table->row_start(); $peers->cell($table,$node['peer_id']); $table->cell(l_node_obj($node)); - $table->cell($node['arch']); + $run_level=$node['run_level']; + if ( empty($run_level)) $run_level=$node['boot_state']; + $class=($run_level == 'boot') ? 'node-ok' : 'node-ko'; + $table->cell($run_level,array('class'=>$class)); + foreach ($more_tags as $chunk) $table->cell($node[$chunk['tagname']]); $table->cell ($form->checkbox_html('node_ids[]',$node['node_id'])); $table->row_end(); } diff --git a/planetlab/slices/slices.php b/planetlab/slices/slices.php index bc5ecbb..63245e9 100644 --- a/planetlab/slices/slices.php +++ b/planetlab/slices/slices.php @@ -141,7 +141,7 @@ foreach ($slices as $slice) { $table->row_start(); if (plc_is_admin()) $table->cell (l_slice_t($slice_id,$slice_id)); $peers->cell($table,$peer_id); - $table->cell (l_slice_obj($slice)); + $table->cell (href(l_slice_nodes($slice_id),$slice['name'])); $table->cell ($users); $table->cell(href(l_persons_slice($slice_id),count($slice['person_ids']))); $table->cell (href(l_nodes_slice($slice_id),count($slice['node_ids']))); diff --git a/planetlab/tags/nodegroup.php b/planetlab/tags/nodegroup.php index cb97270..b29545a 100644 --- a/planetlab/tags/nodegroup.php +++ b/planetlab/tags/nodegroup.php @@ -52,14 +52,22 @@ $tabs []= tab_nodes_local(); drupal_set_title("Details for node group " . $nodegroup['groupname']); plekit_linetabs($tabs); -$details=new PlekitDetails(false); +$toggle=new PlekitToggle('details','Details'); +$toggle->start(); +$details=new PlekitDetails(plc_is_admin()); $details->start(); -$details->th_td ("Node group name",$nodegroup['groupname']); +$details->form_start(l_actions(),array("action"=>"update-nodegroup", "nodegroup_id"=>$nodegroup_id)); +$details->th_td ("Node group name",$nodegroup['groupname'],'groupname'); +// can't change the target tag $details->th_td ("Based on tag",href(l_tag($nodegroup['tag_type_id']),$tagname)); -$details->th_td("Matching value",$nodegroup['value']); +$details->th_td("Matching value",$nodegroup['value'],'value'); $details->th_td("# nodes",count($nodegroup['node_ids'])); +$details->tr_submit("submit","Update Nodegroup"); +$details->form_end(); $details->end(); +$toggle->end(); + // xxx : add & delete buttons would make sense here too $toggle=new PlekitToggle('nodes',"Nodes"); $toggle->start(); diff --git a/planetlab/tags/nodegroups.php b/planetlab/tags/nodegroups.php index 6917d6a..82bac8c 100644 --- a/planetlab/tags/nodegroups.php +++ b/planetlab/tags/nodegroups.php @@ -17,6 +17,7 @@ include 'plc_header.php'; require_once 'plc_functions.php'; require_once 'linetabs.php'; require_once 'table.php'; +require_once 'form.php'; // -------------------- // recognized URL arguments @@ -55,27 +56,62 @@ if ( ! $nodegroups ) { return; } +$headers=array(); +$notes=array(); -$headers = array ( "Name"=>"string", - "Tag"=>"string", - "Value"=>"string", - "Nodes"=>"int"); +$headers['group name']='string'; +$headers['tag name']='string'; +$headers['tag value']='string'; +$headers['# N']='int'; +$notes []= '# N = number of nodes in the group'; +$headers["Id"]="int"; +if (plc_is_admin()) $headers[plc_delete_icon()]="none"; + +$form=new PlekitForm(l_actions(),NULL); +$form->start(); # initial sort on groupname -$table=new PlekitTable("nodegroups",$headers,0); +$table=new PlekitTable("nodegroups",$headers,0,array('notes'=>$notes)); $table->start(); foreach ($nodegroups as $nodegroup) { $table->row_start(); - $table->cell (href(l_nodegroup($nodegroup['nodegroup_id']),$nodegroup['groupname'])); + $nodegroup_id=$nodegroup['nodegroup_id']; + $table->cell (href(l_nodegroup($nodegroup_id),$nodegroup['groupname'])); // yes, a nodegroup is not a tag, but knows enough for this to work $table->cell (l_tag_obj($nodegroup)); $table->cell ($nodegroup['value']); $table->cell (count($nodegroup['node_ids'])); + $table->cell ($nodegroup_id); + $table->cell ($form->checkbox_html('nodegroup_ids[]',$nodegroup_id)); $table->row_end(); } +$table->tfoot_start(); + +$table->row_start(); +$table->cell($form->submit_html ("delete-nodegroups","Remove groups"), + array('hfill'=>true,'align'=>'right')); +$table->row_end(); + +// an inline area to add a tag type +$table->row_start(); + +// build the tagname selector +$relevant_tags = $api->GetTagTypes( array("category"=>'*node*')); +function selector_argument ($tt) { return array('display'=>$tt['tagname'],"value"=>$tt['tag_type_id']); } +$selectors=array_map("selector_argument",$relevant_tags); +$tagname_input=$form->select_html("tag_type_id",$selectors,array('label'=>"Tag Name")); + + +$table->cell($form->text_html('groupname','')); +$table->cell($tagname_input); +$table->cell($form->text_html('value','')); +$table->cell($form->submit_html("add-nodegroup","Add"),3); +$table->row_end(); + $table->end(); +$form->end(); //plekit_linetabs ($tabs,"bottom"); diff --git a/planetlab/tags/tag.php b/planetlab/tags/tag.php index 675594d..010150c 100644 --- a/planetlab/tags/tag.php +++ b/planetlab/tags/tag.php @@ -47,13 +47,41 @@ $category=$tag_type['category']; $filter=array('tag_type_id'=>$tag_type_id); $node_tags=$api->GetNodeTags($filter); $interface_tags=$api->GetInterfaceTags($filter); -$slice_tags=$api->GetSliceTags(array_merge($filter,array("node_id"=>array()))); -$sliver_tags=$api->GetSliceTags(array_merge($filter,array("~node_id"=>array()))); +// split slice tags into 3 families, whether this applies to the whole slice, or a nodegroup, or a node +// using filters for this purpose does not work out very well, maybe a bug in the filter stuff +// anyway this is more efficient, and we compute the related node(groups) in the same pass +$slice_tags=$api->GetSliceTags(array_merge($filter)); +$count_slice=0; +$count_nodegroup=0; +$nodegroup_ids=array(); +$count_node=0; +$node_ids=array(); +foreach ($slice_tags as $slice_tag) { + if ($slice_tag['node_id']) { + $node_ids []= $slice_tag['node_id']; + $count_node += 1; + } else if ($slice_tag['nodegroup_id']) { + $nodegroup_ids []= $slice_tag['nodegroup_id']; + $count_nodegroup += 1; + } else { + $count_slice += 1; + } +} + +$nodes=$api->GetNodes($node_ids,array('hostname','node_id')); +$node_hash=array(); +foreach ($nodes as $node) $node_hash[$node['node_id']]=$node; +$nodegroups=$api->GetNodeGroups($nodegroup_ids,array('groupname','nodegroup_id')); +$nodegroup_hash=array(); +foreach ($nodegroups as $nodegroup) $nodegroup_hash[$nodegroup['nodegroup_id']]=$nodegroup; + drupal_set_title("Details for tag type $tagname"); plekit_linetabs($tabs); // ---------- +$toggle = new PlekitToggle ('details','Details'); +$toggle->start(); $can_update=plc_is_admin(); $details=new PlekitDetails ($can_update); @@ -61,8 +89,8 @@ $details->form_start(l_actions(),array("action"=>"update-tag-type", "tag_type_id"=>$tag_type_id)); $details->start(); $details->th_td("Name",$tagname,"tagname"); -$details->th_td("Category",$category,"category"); -$details->th_td("Description",$description,"description"); +$details->th_td("Category",$category,"category",array('width'=>30)); +$details->th_td("Description",$description,"description",array('width'=>40)); if ($can_update) { // select the option corresponding with min_role_id @@ -79,11 +107,13 @@ if ($can_update) $details->space(); $details->th_td("Used in nodes",count($node_tags)); $details->th_td("Used in interfaces",count($interface_tags)); -$details->th_td("Used in slices",count($slice_tags)); -$details->th_td("Used in slivers",count($sliver_tags)); +$details->th_td("Used in slices/node",$count_node); +$details->th_td("Used in slices/nodegroup",$count_nodegroup); +$details->th_td("Used in slices",$count_slice); $details->end(); $details->form_end(); +$toggle->end(); // common options for tables below $table_options=array('notes_area'=>false, 'pagesize_area'=>false, 'search_width'=>10); @@ -119,23 +149,37 @@ if (count ($interface_tags)) { $toggle->end(); } -// grouping both kinds of slice tags -// xxx don't show hostnames yet -$slice_tags = array_merge ($slice_tags,$sliver_tags); if (count ($slice_tags)) { - $toggle=new PlekitToggle('tag_slices',"Slice and sliver tags"); + $toggle=new PlekitToggle('tag_slices',"Slice tags"); $toggle->start(); - $table=new PlekitTable ("tag_slices",array("Slice"=>"string","value"=>"string","Node id"=>"int"),0,$table_options); + $headers=array(); + $headers["slice"]='string'; + $headers["value"]='string'; + $headers["node"]='string'; + $headers["nodegroup"]='string'; + $table=new PlekitTable ("tag_slices",$headers,0,$table_options); $table->start(); foreach ($slice_tags as $slice_tag) { $table->row_start(); $table->cell(href(l_slice($slice_tag['slice_id']),$slice_tag['name'])); $table->cell($slice_tag['value']); + $node_text="all"; - // sliver tag - if ($slice_tag['node_id']) - $node_text=l_node($slice_tag['node_id'],$slice_tag['node_id']); + if ($slice_tag['node_id']) { + $node_id=$slice_tag['node_id']; + $node=$node_hash[$node_id]; + $node_text=l_node_obj($node); + } $table->cell($node_text); + + $nodegroup_text="all"; + if ($slice_tag['nodegroup_id']) { + $nodegroup_id=$slice_tag['nodegroup_id']; + $nodegroup=$nodegroup_hash[$nodegroup_id]; + $nodegroup_text=l_nodegroup_obj($nodegroup); + } + $table->cell($nodegroup_text); + $table->row_end(); } $table->end(); diff --git a/planetlab/tags/tags.php b/planetlab/tags/tags.php index a8b218a..0f57723 100644 --- a/planetlab/tags/tags.php +++ b/planetlab/tags/tags.php @@ -44,20 +44,24 @@ if ($pattern) $tag_types= $api->GetTagTypes($tag_type_filter, $tag_type_columns); $headers=array(); +$notes=array(); // delete button $headers['Name']="string"; $headers['Description']="string"; $headers['Category']="string"; -$headers['Min role']="string"; -// xxx ref count would be helpful -//if (plc_is_admin()) $headers['#']='int'; +$headers['MR']="string"; +$notes []= "MR: Min Role, needed to manage this tag"; + +// xxx ref count would be helpful but seem too expensive to compute at this stage +// the individual tag page show those ref counts per type + $headers["Id"]="int"; if (plc_is_admin()) $headers[plc_delete_icon()]="none"; $form=new PlekitForm(l_actions(),NULL); $form->start(); -$table = new PlekitTable("tags",$headers,0); +$table = new PlekitTable("tags",$headers,0,array('notes'=>$notes)); $table->start(); $roles_hash=plc_role_global_hash($api); @@ -102,7 +106,7 @@ if (plc_is_admin()) { $table->cell($form->textarea_html('description','',$description_width,2)); $table->cell($form->text_html('category','')); $table->cell($role_input); - $table->cell($form->submit_html("add-tag-type","Add Type"),2); + $table->cell($form->submit_html("add-tag-type","Add"),2); $table->row_end(); } -- 2.43.0