Admin Specific

From Triangle Wiki

Jump to: navigation, search

Contents

Introduction

Data Grid To Dos

In order of priority please

  • Page (paging) resets to 1 after a row is updated
  • Ability to add multiple elements into the form, i.e. for the SMS Blacklist I want to enter hundreds of numbers at once - would be nice to incorporate something like this into the Data grid, as all it needs are the fields that are dynamic.
  • Each data grid should have the Check box to the right hand side (Optional via Flag) if true then user can select multiple rows - this will override edit as it used too. At bottom and top add in pull down menu with options to Delete (with caution alert) - Activate - Suspend - if all tables have the same Status fields then this should be easily achieved, or can be dynamic I think from the status field.
  • When clicking edit at the bottom of the page - need to scroll back to the top - can we make it so the page scrolls back up when any edit element is clicked so the user is presented the edit form.
  • What field does the calendar search on - creation date - need that as an option to change this if needed.
  • When Editing or adding when clicking the Submit the Submission should be done over AJAX via JSON which is faster - a progress icon will appear - the page will update the table to show the changes and the edit box will disappear, and a notice saying updated/edited as it does now.
  • At some stage would be nice to have boolean operations in the filter boxes - i.e. filter on ID for 1 & 4 brings up all elements that have a 1 and a 4 in the IDs i.e. 1 4 14 11 41....
  • the d and p variables are locked into the base_datagrid_new ?
  • Option to do PDF download.
  • Want to have the option to do the EXCEL download I think use excel writer in PEAR.
  • When show_form is false but convert rows is true then clicking on this brings an edit error - in this case the rows should be highlighted but not click able i.e. there is no edit. This should also override the edit icon.
  • The data grids are so interwoven with the admin that it is difficult to use them on anything else.

You don't have to use our datagrid, you can just stick with the parent class. The base class I wrote is designed to work with quickform and to output our admin, it's not designed for other uses. You'd need to write a different renderer if you want to use datagrids in another context

  • It is possible to load an existing quick form and remove elements from it, and even insert new elements between existing ones. The question is whether there is any significant overhead from using this method vs. writing a new specific form from scratch. If not, then we can prepare a generic form, for example for users data entry, and use it as a template without too much effort. So Speed testing is required. An example has been set up for Chinasavvy at http://www.chinasavvy.com/contact/general-enquiry.php
  • In the process of writing the PDF renderer. The following tasks are outstanding:
    1. Filtering and ordering: Whatever filtering and ordering is set on the html table should be the same in the outputted PDF file
    2. Cleaning records: A generic cleanRecords() does some basic string cleanup, but it should be improved to accept parameters

Bugs

  • When filtering the countries list to only 1 ID, although the query returns one row, the table shows "No data"
  • Users admin: When using a site-specific user_type for creating a user, if any extra fields are shown in the creation form, these are added no matter the user type selected. For example, a global admin doesn't need credits and expiration date, but because these are shown on the user creation page for the global site, they are also created as users_options.
  • Users_options page: the drop-down to other details is not showing.
  • Users_options page: When a global student is created with a subscription expiry date lower than 2000, no subscription expiry date gets recorded.
  • Users_options page: If a global student is given an expired subscription date (earlier than current date, s/he can still log on)

Multi-language support

The admin uses PEAR_Translation2 to provide multi-language strings based on user preferences. It automatically detects the preferred language when reaching the login page based on browser locale, but language can be changed at any time.

There is a translation management admin panel that parses the entire source code, searching for calls to the translation object's get() method. These are saved into a transition table called language_strings. It then compares these with the existing translations in the Database, and prints a form with the missing translations. A translator can enter the missing translations in the text areas.

To speed things up, a cache of the missing translations is saved in the session, and refreshed only when the user presses the update button, at which point the parsing restarts, and the session cache is updated. When a translation is entered using this widget, the corresponding translation in the session array is also removed, giving instant feedback.

The table for translation entry has 4 main columns:

[selected_language_string] [target_language] [page] [translations]

The first column is dynamic, based on which language is selected in the session. It provides the translated version of the string missing in the target language. If that translated version doesn't exist, it outputs the translation code instead, giving a less useful indication of the target translation.

The Page column refers to page-specific translations. Most translations can have this set to null, but if a different page is specified, the translation may differ from the top-level, null-page translation (so 'login' could be translated differently according to which page is loaded).

Form and Table

The admin framework generates a form for data entry and editing and a paginated table with in-built filters for each database table. To create this basic scaffold, all you need to do is create a new page in the modules section, under a specific module, and include this code: (example taken from the countries table)

$admin->authPage('admin');
$settings['show_actions_column'] = true;
$settings['show_calendar']       = false;
$settings['show_filters']        = true;
$settings['show_form']           = true;
$settings['convert_rows']        = true;
$settings['table']               = TBL_ADMIN_COUNTRIES;
$settings['table_id']            = 'country_id';
$settings['element']             = 'Countries';
$settings['icons']               = array('edit', 'delete');
$settings['datetime_format']     = 'UK';
$settings['records_per_page']    = 20;
$dg =& new Structures_DataGrid_Base_new($settings, null, 'Admin');
echo $admin->showMessage($msg . $dg->msg);
echo $dg->output(true);

A number of settings can be changed, including showing the form. If the form isn't shown, the application will consist only of a paginated, filtered table.

When the form is shown, it is hidden by default, and you bring it up by either

  1. clicking the Add button to create a new record
  2. clicking a row in the table to edit that record

Sometimes you will want to link directly to this page for data entry, in which case you may want the form to be shown by default. Simply append &show_form to the URL, and the form will be shown.

Navigation

The navigation system is now drawn from the users_options table. A single user may have many seperate inline sites within the admin, this is all controlled by adding the following lines into the Options table.

  • For the first site do the following - the value element takes the form Name of Site, menu filename and the option for it being the default site.
  • name - menu
  • value - Server Admin|server_admin|1
  • name - menu
  • value - Menu Name|not_default

Add as many menu elements as the user needs.

The files holding navigation set up now use a html-free method for creating links, incorporating translation features. A complex example that includes conditonal navigation elements is given here, for the Chinasavvy navigation:

$boxes = array(
  'entry_forms' => array(
    'enquiry' => 'admin.php?d=chinasavvy'
      . '&p=form_enquiry',
        'supplier_inbound' => 'admin.php?'
          . 'd=chinasavvy&p=form_inbound'
   )
);

// If the user is logged in as an Admin, 
// then show the extended navigation
if (isset($_SESSION['admin_is_admin']) && 
   $_SESSION['admin_is_admin'] == 1) {
   $boxes['entry_forms']['customer_outbound'] =
       'admin.php?d=chinasavvy&p=form_outbound';

     $boxes['reports'] = array(
         'enquiry_reports' => 'admin.php?
         . 'd=chinasavvy&p=report_enquiry',
         'supplier_reports' => 'admin.php?
         . 'd=chinasavvy&p=report_inbound',
         'customer_reports' => 'admin.php?
         . 'd=chinasavvy&p=report_outbound',
     );

     $boxes['admin'] = array(
         'staff_management' => 'admin.php?
         . 'd=users&p=admin_users',
         'client_management' => 'admin.php?
         . 'd=users&p=admin_users
         . '&option=is_admin&value=0'
     );

     $boxes['categories'] = array(
         'category_admin' => 'admin.php?
         . 'd=chinasavvy&p=admin_category',
         'subcategory_admin' => 'admin.php?
         . 'd=chinasavvy&p=admin_subcategory'
     );
 } elseif (isset($_SESSION['admin_is_admin']) &&
                 $_SESSION['admin_is_admin'] == 2) {

     $boxes['assignments'] = array(
         'assigned_enquiries' => 'admin.php?
         . 'd=chinasavvy&p=report_enquiry'
     );
 }

 echo $admin->showCompleteNav($boxes);

DataObject common class: Inter

This class extends the DB_DataObject class and adds a number of methods that can be used by all our DataObjects. It also overrides some of the parent class' methods such as insert() and update(), and adds a replace() method to make use of MySQL's replace statement. One of its most important features is the setupFields() method, which prepares the DO by assigning it an array of Field objects, which are mapped to the fields of the Database table. These Field objects contain additional information that is used to create CRUD forms and datagrid tables.

The setupField() method can be overridden by any DataObject that extends the Inter class, and is used to setup additional validation rules, display options and other specific settings. Following is a synopsis of the types of changes that can be made, using the DO_Country class as an example.

function setupFields()
{
  // Set default attributes here. Default size is 55
  $_SESSION['static_field']->attr['html_attributes']['size'] = 55;
 
  // Invoke parent's construct method, sets up all fields.
  // This MUST be invoked before any of the following code!
  parent::setupFields();
}

The overrideFields method takes three arguments, the first and third can be either strings or arrays. The first argument is one or more fields for which you want to override an attribute. The second is the attribute you wish to change. The third is either the value to assign to the attribute, and will be assigned to all the fields given in the first argument, or if an array is given, it must match the number of fields given in the first argument, and each of its values will be assigned respectively to each of the fields.

$this->overrideFields(array('country_iso', 'currency'),
  'required', true);

// Set Rule text
$this->overrideFields(
  array('country', 
    'country_iso', 
    'currency'),
    'required_msg', 
    array('Please enter a Country name',
      'Please enter a country ISO',
      'Please enter a currency'));
 
// Set whether they should display in the table
$this->overrideFields(
  array('currency_sub_unit', 
    'full_name', 
    'currency', 
    'capital',
    'adjective', 
    'continent', 
    'citizen', 
    'dial_code', 
    'idd', 
    'ndd'),
    'showInTable', 
    false);
 
// Default elements
$this->overrideFields('capital', 'default', 'Paris');
 
// Any variation in the type default is text
$this->overrideFields('citizen', 'type', 'textarea_counter');
$this->overrideFields('citizen', 'quickform_attributes',
  array('max_chars' => 160));
 

Additional fields can be setup also. The following comes from the DO_Users class

// Add additional site-specific fields if set up
if (isset($_SESSION['user_options'])) {
  foreach ($_SESSION['user_options'] as $option) {
    if (!is_array($option)) {
      continue;
    } else {
      $this->fields[] = new Structures_DataGrid_Field(
      $this->translateOptions($option));
    }
  }
}
 
// Add the details field (column)
$this->fields[] = new Structures_DataGrid_Field(
  array('name' => 'details',
    'info' => $tr->get('details'),
    'label' => $tr->get('details'),
    'showInForm' => false,
    'data_function' => 'DO_Users::getDetails()'
  )
);
 
// Add the user_type form field
$user_types = $this->getUserTypes();
 
if (!empty($user_types)) {
  $this->fields[] = new Structures_DataGrid_Field(
    array('name' => 'user_type',
      'info' => $tr->get('user_type'),
      'label' => $tr->get('user_type'),
      'showInTable' => false,
      'type' => 'select',
      'options' => $user_types,
      'default' => 'none'
    )
  );
}

return $this->fields;
}

The 'data_function' attribute of the Field object is used to populate a DataGrid column with different data than the default value from the row in the database. You can set up any method in any object, but it must meet the following criteria:

  1. It must be static: for PHP4, that means simply not containing any self-reference such as $this.
  2. It must have for only argument an array named $params
  3. This array will always receive a certain set of values from DataGrid, including a 'record' array which contains the values for this row, from the database.
  4. This method must always return a string or a value that can be displayed as a string (i.e. integer)

Following is an example from the DO_Users class:

/**
 * Callback function for getting the drop-down of details for this User.
 *
 * @param array $params
 * @return string The HTML code for the drop-down menu.
 */
 function getDetails($params)
 {
   global $admin, $tr;
   extract($params);
 
   $html = '
     <select onchange="window.location = \'admin.php?d=users&p=\'
     + this.value + \'&user_id=' . $record['user_id'] . '\';">
     <option selected="selected">' . $tr->get('select') . '</option>
     <option value="users_addresses">' . $tr->get('addresses') . '</option>
     <option value="users_contacts">' . $tr->get('contacts') . '</option>';
 
   if ($_SESSION['admin_is_admin'] == 1) {
     $html .= '<option value="users_options">' .
       $tr->get('options') . '</option>';
   }
 
   $html .= '</select>';
 
   return $html;
 }

External Links

Modules

Personal tools