http://www.grocerycr...data-read-only/
Just posting it here for convenience for the meantime to see if it is of any use to other developers, and to get some feedback / peer review on the concept.
A number of things mixed up in this patch :[list]
[*]This automatically adds a view icon to each record (next to the edit and delete icons).
[*]Click on the view icon brings up a read-only view of the data for display purposes.
[*]1-n relation fields on a view form display the related data from the related table (as it appears in the drop down list), rather than the key field.
[*]File upload fields are displayed as references to images (In my case, I assume that file uploads are images only ... not necessarily true for all upload fields though, so this needs work)
[*]Fields that contain HTML code allow you to 'attach' all sorts of neat things to database records - I am using it to embed youtube vids against database records for example. This is highly insecure, so may need modification if you intend using this on a public application.
[*]Added a layer of security, so that individual records in a table can be marked as not editable (or delete-able) ... which is determined via a new callback_can_edit() function that is called on each row of data in the list. The callback function receives the primary key value as the first parameter.
[*]Added a new 'view' to the flexigrid theme to layout display only records. Need to do the same with datatables. Laziness on my part !
[*]Added a new function $crud->is_link($fieldname) ... which tells the view form that the data in $fieldname should be displayed as a HTML link. This is a bit of a crude hack, just for my benefit ... I will remove this and do it properly in the next update, as it is not the best coding practice around.
[/list]
Here is the patch, across several files :
diff --git a/application/libraries/grocery_crud.php b/application/libraries/grocery_crud.php
index 56ef943..566c275 100644
--- a/application/libraries/grocery_crud.php
+++ b/application/libraries/grocery_crud.php
@@ -210,7 +210,42 @@ class grocery_Field_Types
return $field_info;
}
+
+ protected function get_field_display($field_info, $value = null)
+ {
+ $real_type = $field_info->crud_type;
+ switch ($real_type) {
+ case 'relation':
+ $field_info->input = $this->get_relation_display($field_info,$value);
+ break;
+
+ case 'upload_file':
+ $path = $field_info->extras->upload_path;
+ $field_info->input = "<a href=/$path/$value target=image><img src=/$path/$value width=400></a>";
+ break;
+
+ default:
+ if ($this->get_is_link($field_info)) {
+ $field_info->input = "<a href=\"$value\" target=\"links\">$value</a>";
+ } else {
+ $field_info->input = "$value";
+ }
+ break;
+ }
+
+ return $field_info;
+ }
+
+ protected function get_is_link($field_info)
+ {
+ if (isset($this->link_fields[$field_info->name])) {
+ return $this->link_fields[$field_info->name];
+ }
+ return false;
+
+ }
+
protected function change_list_value($field_info, $value = null)
{
$real_type = $field_info->crud_type;
@@ -1086,8 +1121,9 @@ class grocery_Layout extends grocery_Model_Driver
$data->add_url = $this->getAddUrl();
$data->edit_url = $this->getEditUrl();
$data->delete_url = $this->getDeleteUrl();
- $data->ajax_list_url = $this->getAjaxListUrl();
- $data->ajax_list_info_url = $this->getAjaxListInfoUrl();
+ $data->view_url = $this->getViewUrl();
+ $data->ajax_list_url = $this->getAjaxListUrl();
+ $data->ajax_list_info_url = $this->getAjaxListInfoUrl();
$data->actions = $this->actions;
$data->unique_hash = $this->get_method_hash();
@@ -1103,8 +1139,18 @@ class grocery_Layout extends grocery_Model_Driver
foreach($data->list as $num_row => $row)
{
- $data->list[$num_row]->edit_url = $data->edit_url.'/'.$row->{$data->primary_key};
- $data->list[$num_row]->delete_url = $data->delete_url.'/'.$row->{$data->primary_key};
+ $can_edit = true;
+ if (isset($this->callback_can_edit)) {
+ $can_edit = call_user_func($this->callback_can_edit,$row->{$data->primary_key});
+ }
+ if ($can_edit) {
+ $data->list[$num_row]->edit_url = $data->edit_url.'/'.$row->{$data->primary_key};
+ $data->list[$num_row]->delete_url = $data->delete_url.'/'.$row->{$data->primary_key};
+ } else {
+ $data->list[$num_row]->edit_url = null;
+ $data->list[$num_row]->delete_url = null;
+ }
+ $data->list[$num_row]->view_url = $data->view_url.'/'.$row->{$data->primary_key};
}
if(!$ajax)
@@ -1235,7 +1281,29 @@ class grocery_Layout extends grocery_Model_Driver
$this->_theme_view('edit.php',$data);
}
+
+ protected function showViewForm($state_info)
+ {
+ $this->set_js('assets/grocery_crud/themes/datatables/js/jquery-1.6.2.min.js');
+
+ $data = $this->get_common_data();
+ $data->types = $this->get_field_types();
+
+ $data->field_values = $this->get_edit_values($state_info->primary_key);
+
+ $data->add_url = $this->getAddUrl();
+
+ $data->list_url = $this->getListUrl();
+ $data->input_fields = $this->get_view_display_fields($data->field_values);
+
+ $data->fields = $this->get_edit_fields();
+
+ $data->validation_url = $this->getValidationUpdateUrl();
+
+ $this->_theme_view('view.php',$data);
+ }
+
protected function delete_layout($delete_result = true)
{
if($delete_result === false)
@@ -1491,6 +1559,22 @@ class grocery_Layout extends grocery_Model_Driver
$input .= "</select>";
return $input;
}
+
+ protected function get_relation_display($field_info,$value)
+ {
+ if (empty($value)) {
+ return '';
+ }
+ $options_array = $this->get_relation_array($field_info->extras);
+ foreach($options_array as $option_value => $option)
+ {
+ if ($value == $option_value) {
+ return $option;
+ }
+ }
+
+ return "Unknown - $value";
+ }
protected function get_relation_n_n_input($field_info_type, $selected_values)
{
@@ -1648,7 +1732,51 @@ class grocery_Layout extends grocery_Model_Driver
return $input_fields;
}
+
+ protected function get_view_display_fields($field_values = null)
+ {
+ $fields = $this->get_edit_fields();
+ $types = $this->get_field_types();
+
+ $input_fields = array();
+
+ foreach($fields as $field_num => $field)
+ {
+ $field_info = $types[$field->field_name];
+
+ $field_value = !empty($field_values) && isset($field_values->{$field->field_name}) ? $field_values->{$field->field_name} : null;
+ //if(!isset($this->callback_edit_field[$field->field_name]))
+ //{
+ $field_input = $this->get_field_display($field_info, $field_value);
+ //}
+ //else
+ //{
+ //$primary_key = $this->getStateInfo()->primary_key;
+ //$field_input = $field_info;
+ //$field_input->input = call_user_func($this->callback_edit_field[$field->field_name], $field_value, $primary_key);
+ //}
+
+ switch ($field_info->crud_type) {
+ case 'invisible':
+ unset($this->edit_fields[$field_num]);
+ unset($fields[$field_num]);
+ continue;
+ break;
+ case 'hidden':
+ $this->edit_hidden_fields[] = $field_input;
+ unset($this->edit_fields[$field_num]);
+ unset($fields[$field_num]);
+ continue;
+ break;
+ }
+
+ $input_fields[$field->field_name] = $field_input;
+ }
+
+ return $input_fields;
+ }
+
protected function setThemeBasics()
{
$this->theme_path = $this->default_theme_path;
@@ -1756,7 +1884,8 @@ class grocery_States extends grocery_Layout
9 => 'insert_validation',
10 => 'update_validation',
11 => 'upload_file',
- 12 => 'delete_file'
+ 12 => 'delete_file',
+ 13 => 'view'
);
protected function getStateCode()
@@ -1894,6 +2023,14 @@ class grocery_States extends grocery_Layout
else
return $this->state_url('delete/'.$state_info->primary_key);
}
+
+ protected function getViewUrl($state_info = null)
+ {
+ if(empty($state_info))
+ return $this->state_url('view');
+ else
+ return $this->state_url('view/'.$state_info->primary_key);
+ }
protected function getUploadUrl($field_name)
{
@@ -1922,6 +2059,7 @@ class grocery_States extends grocery_Layout
break;
case 3:
+ case 13:
if($first_parameter != null)
{
$state_info = (object)array('primary_key' => $first_parameter);
@@ -2086,6 +2224,7 @@ class grocery_CRUD extends grocery_States
protected $required_fields = array();
protected $unset_columns = null;
protected $validation_rules = array();
+ protected $link_fields = array();
protected $relation = array();
protected $relation_n_n = array();
protected $upload_fields = array();
@@ -2111,6 +2250,7 @@ class grocery_CRUD extends grocery_States
protected $callback_before_delete = null;
protected $callback_after_delete = null;
protected $callback_escape_delete = null;
+ protected $callback_can_edit = null;
protected $callback_column = array();
protected $callback_add_field = array();
protected $callback_edit_field = array();
@@ -2175,6 +2315,24 @@ class grocery_CRUD extends grocery_States
}
/**
+ * Set Is This Field a Link ?
+ *
+ * Important note: If the $field is an array then no automated crud fields will take apart
+ *
+ * @access public
+ * @param mixed
+ * @param string
+ * @return void
+ */
+
+ function is_link($field)
+ {
+ if (is_string($field)) {
+ $this->link_fields[$field] = true;
+ }
+ }
+
+ /**
*
* Changes the default field type
* @param string $field
@@ -2616,7 +2774,7 @@ class grocery_CRUD extends grocery_States
}
return $this->edit_fields;
}
-
+
public function order_by($order_by, $direction = '')
{
if($direction == '')
@@ -2706,6 +2864,26 @@ class grocery_CRUD extends grocery_States
$this->showAddForm();
break;
+
+ case 13://view
+ if($this->unset_edit)
+ {
+ throw new Exception('This user is not allowed to do this operation', 14);
+ die();
+ }
+
+ $this->set_basic_db_table($this->get_table());
+ if($this->theme === null)
+ $this->set_theme($this->default_theme);
+ $this->setThemeBasics();
+
+ $this->set_basic_Layout();
+
+ $state_info = $this->getStateInfo();
+
+ $this->showViewForm($state_info);
+
+ break;
case 3://edit
if($this->unset_edit)
@@ -2835,6 +3013,8 @@ class grocery_CRUD extends grocery_States
$this->delete_file_layout($delete_file_result);
break;
+
+
}
@@ -2859,6 +3039,16 @@ class grocery_CRUD extends grocery_States
{
$this->callback_before_insert = $callback;
}
+
+ /**
+ *
+ * Enter description here ...
+ */
+ public function callback_can_edit($callback = null)
+ {
+ $this->callback_can_edit = $callback;
+ }
+
/**
*
@@ -3157,9 +3347,9 @@ class grocery_CRUD extends grocery_States
* @param string $related_table
* @param string $related_title_field
*/
- public function set_relation($field_name , $related_table, $related_title_field)
+ public function set_relation($field_name , $related_table, $related_title_field, $link=null)
{
- $this->relation[$field_name] = array($field_name, $related_table,$related_title_field);
+ $this->relation[$field_name] = array($field_name, $related_table,$related_title_field,$link);
return $this;
}
@@ -4566,4 +4756,4 @@ class grocery_Form_validation {
}
}
-// END Form Validation Class
\ No newline at end of file
+// END Form Validation Class
diff --git a/assets/grocery_crud/themes/flexigrid/views/list.php b/assets/grocery_crud/themes/flexigrid/views/list.php
index 0935d86..6519fe1 100644
--- a/assets/grocery_crud/themes/flexigrid/views/list.php
+++ b/assets/grocery_crud/themes/flexigrid/views/list.php
@@ -38,14 +38,15 @@
<?php if(!$unset_delete || !$unset_edit || !empty($actions)){?>
<td align="left" width='20%'>
<div class='tools'>
- <?php if(!$unset_delete){?>
+ <?php if(!$unset_delete && $row->delete_url){?>
<a href='<?php echo $row->delete_url?>' title='<?php echo $this->l('list_delete')?> <?php echo $subject?>' class="delete-row" >
<span class='delete-icon'></span>
</a>
<?php }?>
- <?php if(!$unset_edit){?>
+ <?php if(!$unset_edit && $row->edit_url){?>
<a href='<?php echo $row->edit_url?>' title='<?php echo $this->l('list_edit')?> <?php echo $subject?>'><span class='edit-icon'></span></a>
<?php }?>
+ <a href='<?php echo $row->view_url?>' title='<?php echo $this->l('list_view')?> <?php echo $subject?>'><span class='view-icon'></span></a>
<?php
if(!empty($row->action_urls)){
foreach($row->action_urls as $action_unique_id => $action_url){
@@ -74,4 +75,4 @@
<?php echo $this->l('list_no_items'); ?>
<br/>
<br/>
-<?php }?>
\ No newline at end of file
+<?php }?>
diff --git a/assets/grocery_crud/themes/flexigrid/views/view.php b/assets/grocery_crud/themes/flexigrid/views/view.php
new file mode 100644
index 0000000..af7f51e
--- /dev/null
+++ b/assets/grocery_crud/themes/flexigrid/views/view.php
@@ -0,0 +1,73 @@
+<?php
+ if (!defined('BASEPATH')) exit('No direct script access allowed');
+
+ $this->set_css('assets/grocery_crud/themes/flexigrid/css/flexigrid.css');
+ $this->set_js('assets/grocery_crud/themes/flexigrid/js/jquery.form.js');
+ $this->set_js('assets/grocery_crud/themes/flexigrid/js/flexigrid-edit.js');
+?>
+<script type='text/javascript'>
+ var base_url = '<?php echo base_url();?>';
+
+ var upload_a_file_string = '<?php echo $this->l('form_upload_a_file');?>';
+</script>
+<div class="flexigrid" style='width: 100%;'>
+ <div class="mDiv">
+ <div class="ftitle">
+ <div class='ftitle-left'>
+ <?php echo $this->l('form_view'); ?> <?php echo $subject?>
+ </div>
+ <div class='ftitle-right'>
+ <a href='<?php echo $list_url?>' onclick='javascript: return goToList()'><?php echo $this->l('form_back_to_list'); ?></a>
+ </div>
+ <div class='clear'></div>
+ </div>
+ <div title="Minimize/Maximize Table" class="ptogtitle">
+ <span></span>
+ </div>
+ </div>
+<div id='main-table-box'>
+ <div class='form-div'>
+ <?php
+ $counter = 0;
+ foreach($fields as $field)
+ {
+ $even_odd = $counter % 2 == 0 ? 'odd' : 'even';
+ $counter++;
+ ?>
+ <div class='form-field-box <?php echo $even_odd?>'>
+ <div class='form-display-as-box'>
+ <?php echo $input_fields[$field->field_name]->display_as?><?php echo ($input_fields[$field->field_name]->required)? "* " : ""?> :
+ </div>
+ <div class='form-input-box'>
+ <?php echo $input_fields[$field->field_name]->input?>
+ </div>
+ <div class='clear'></div>
+ </div>
+ <?php }?>
+ <?php if(!empty($hidden_fields)){?>
+ <!-- Start of hidden inputs -->
+ <?php
+ foreach($hidden_fields as $hidden_field){
+ echo $hidden_field->input;
+ }
+ ?>
+ <!-- End of hidden inputs -->
+ <?php }?>
+ <div id='report-error' class='report-div error'></div>
+ <div id='report-success' class='report-div success'></div>
+ </div>
+ <div class="pDiv">
+ <div class='form-button-box'>
+ <div class='small-loading' id='FormLoading'><?php echo $this->l('form_update_loading'); ?></div>
+ </div>
+ <div class='clear'></div>
+ </div>
+ </form>
+</div>
+<script>
+ var validation_url = '<?php echo $validation_url?>';
+ var list_url = '<?php echo $list_url?>';
+
+ var message_alert_edit_form = "<?php echo $this->l('alert_edit_form')?>";
+ var message_update_error = "<?php echo $this->l('update_error')?>";
+</script>
[attachment=8:changes.txt]
Unfortunately, in my haste to get this developed, I have backed myself into a corner on github ! I have my whole project hosted on github (including grocery crud embedded into it), where I realise now that I should have pulled the official code down from its own git repository, and only hosted my own application specific code on my own repository.
Being new to git, I don't know if git can manage having an application where the sources for the application are pulled from multiple remote repositories (ie - Grocery CRUD, Custom Application, plus other bits, all in the same directory tree). Thats something I need to read up on offline from this forum, as its nothing to do with this library really. More reading for me !
Ah well - I will get around to fixing my git setup soon enough
Hope you find the above code patches useful.
Steve