Making some data read only
- Single Page
Posted 27 December 2011 - 20:03 PM
Excellent library ! Easy to use ... and the underlying classes are well written, so its easy to modify. Thanks for publishing this as open source - good things will come of that, I am sure.
In my application, I have a need to expand the functionality just a little bit to allow some data to be read-only.
In all cases, the author of each record is stamped on the record, and only the author may edit or delete the record. All other records in the tables are viewable by the rest of the users.
To make this work, I have added a 'View only' form alongside the 'Edit Form' and 'Add Form'.
On the main list, there are now 3 buttons - View, Edit, Delete.
I have added a callback to the CRUD class :
$crud->callback_can_edit ();
which is a user space function that takes the primary key of the row as a parameter, and returns true (yes, you can edit and delete this one), or false (you can only view this record). If the callback says that you cannot edit the record, then the edit and delete icons do not appear on the list form. So the editing and deleting functions are now granular on a per-row basis.
In the view form, the edit fields are displayed as straight HTML content rather than HTML input fields - this is useful for displaying the full details of each record (which may be more than is seen on the list screen), and is particularly useful for large text fields that contain embedded HTML content.
Anyway .. this was all pretty simple to hack the library and add those functions, which bodes well for adding more things in future.
If you want to see how this works, drop me a PM and I will setup an account for anyone that is interested to login to my application and have a play. Its all online after all.
Question :
- Given that my modifications are spread over a number of different files, and are quite extensive, how should I go about submitting the modifications for inclusion in the main branch of the code ? (assuming that you even want them :-) )
- If you are happy with my modifications, would you be interested in getting more of the same, if I tackle some of your TODO list items on the upcoming features ?
- If this proves to be productive (having multiple developers working on the base code, with you in command), could we look at setting up a git or svn repository to handle more developers on the project ?
Cheers
Steve
Posted 28 December 2011 - 00:59 AM
Your idea is great and I think that is HAS to be in grocery CRUD ( is Create Retreive/Read Update Delete/Destroy ) and so I think the "Retreive/Read" is... missing . So that's a good point of view to have something in the CRUD in general. I will do it in a little different way from that. So now I have the unset_edit, unset_add, unset_delete. So in the future ( and I will add it now to the future plans! ) is to have as you said a "view" action and an unset_view method. So with this a user can be much more flexible. So for example a user can view, edit only two fields and not delete. So his code will be for example:
...
if($user->role == 'editor')
{
$crud->unset_delete();
$crud->edit_fields('description','full_text');
}
elseif($user->role == 'admin')
{
$crud->edit_fields('title','description','full_text','status','public');
}
else
{
$crud->unset_view();
$crud->unset_edit();
$crud->unset_delete();
}
...
As for your questions in general now there are two ways to contribute and share your code.
The first is to just post to the extra coding/plugins area as a patch or just post your code.
The second one is to fork the grocery crud project at git hub and after this have a pull request and see how it goes.
For now I have to organize the contribution-development stuff and I have many things that they need to be, such as issues, features for the next version, milestones e.t.c. e.t.c.. So the best way to do it for now is the first in my opinion.
For me is very important to have a code that everyone can change easily and extended to their own CRUD. I am glad that you find it easy to change it.
You are always welcome to share your code as goFrendiAsgard did that works with grocery CRUD in the NEO-CMS project.
Kind Regards
Johnny
Posted 28 December 2011 - 04:22 AM
Yes, your idea there is a good one - thats a flexible approach to allow fine grained security on a field basis. Works well.
Didnt realise that you have github setup already, so that is perfect. Git is a great tool for this sort of work, and gets around the 'trusted developer' issue very nicely.
I will get onto polishing up what I have here, and posting it as a set of patches then. Silly me - I didnt put this into a my local svn before making changes, so working out the patch is not so simple now Well - its not a 1-liner anymore anyway.
I have a few more changes to add to the view_form yet ... namely
1) Make sure that external relations are calculated when the view form is rendered. Should be easy to do.
2) Get rid of the extra icon for viewing the record on the list, and make the first column in the list a link to the view form.
3) Only works with flexigrid at the moment, Ill set it up for datatables as well.
Talk soon/
Steve
Posted 04 January 2012 - 04:59 AM
/topic/70-large-changes-to-allow-for-read-mode-in-gc/
Posted 12 January 2012 - 09:02 AM
Posted 12 January 2012 - 18:29 PM
The patch posted above is pretty straightforward - you can either add the changes manually in an editor (not too difficult for this patch), or use git to merge the changes in. Git makes life easy, but you need to get through the learning curve of git first. That can take a little time, depending on where you are at.
There are also quite a few more additions going in as we speak, including some of the following tricks :[list]
[*]Chaining multiple CRUD forms together to edit sub-records of the main record.
[*]Extra field types to include images / youtube videos /google maps / links / embedded sections of other websites into forms.
[*]Additional navigation tokens added to the forms, to jump between levels of forms, and to toggle between edit and view modes.
[*]Adding images into list forms.
[*]Setting columns in list forms to be clickable links to other forms
[*]Security modifications to set edit / delete / view rights on a per-row basis.
[/list]
Whilst its working very nicely for me at the moment, its still not complete, and it does introduce some new bugs that are in the process of being ironed out.
I also have a github repository of my as yet unfinished application that is based on GC and codeigniter ... you could attempt to grab files out of that and integrate them, but that is just as messy. Not the best way of handling the problem.
If you can just hang in there for a couple more days, I will put up a a new Git repository for just my extensions to grocery_CRUD, which will include a simple ZIP file that you can download can just unzip into your application area. This will install the latest working version of my modifications that you can test and play with.
To get rid of my changes and revert back to the standard grocery_CRUD, you can always unzip the official version back over the top of my stuff. Simple .. and safe !
I actually have a pretty insane number of additions that I am working on at the moment. All sorts of cool new things. However - I do need to put together a simple installer for these extensions so that other developers can grab stable snapshots of what I am working on and safely integrate them into their work if they want to test the ideas. That will take a little more work yet.
Git solves the problem well - it allows for multiple branches to be easily managed, so as a developer you can pull code from the standard repository .. or you can merge in my branch to get my additions. Git has a bit of a learning curve, but its well worth the effort.
I will post a message on these forums when the extension package is ready to roll ... wont be too much longer now
Posted 12 January 2012 - 22:05 PM
I have merged in the latest fixes from the main tree and cleaned up my code a little as well. There is 1 large patch here as a starting point if you are using git :
https://github.com/steveoc64/grocery-crud/commit/1bf2204f93602e7a7f08aad59d798aba4b767ff4
If you are not using git, then you can simply grab the ZIP file of the latest release of my extensions, and install these on top of your base grocery_CRUD installation.
Latest updated ZIP file is always here :
https://github.com/steveoc64/grocery-crud/zipball/master
To roll back my extensions, grab the latest ZIP file from the main project, and install this again into your working directory. A ZIP file of the lLatest official grocery_CRUD code can always be found here :
https://github.com/scoumbourdis/grocery-crud/zipball/master
Hope that helps !
Posted 21 January 2012 - 14:48 PM
Posted 21 January 2012 - 15:20 PM
- update sub list works but redirects to textarea with json data
- insert works and redirects to the same textarea with json data, but have to make sure user enter the right parent ID
Is that what supposed to happen right now?
Posted 21 January 2012 - 16:24 PM
I got your hack/mod steveoc. And one thing I noticed right away was the FB-style field for relation_n_n when priority is not set. That is cool. Looking at your list, you've done a lot more. But I am not much of a code-hacker. Going through the codes but it puzzles me. I am interested [i][b]"Chaining multiple CRUD forms together to edit sub-records of the main record."[/b][/i] -- is that included in your latest patch? If so, can you show me an example how I can get that done?
[/quote]
@kidino the facebook style and the new drop down list it is on the new release of grocery CRUD v 1.1.8. So you will not need any hack to have it in your project. As for the multiple forms I will try to have steve's library as an extension so to be more easy to add it to your project.
Posted 21 January 2012 - 17:05 PM
[b]@steveoc[/b] - I think I found out why the form is not working well. It's because of the conflict in the form ID with the parent form. By default the ID is crudForm. I see that you use $depth to track how many levels the form goes. I edited the edit.php from "flexgrid/view/edit.php" to check for $depth, and added $depth at the end of crudForm. So it will be crudnForm1, crudForm2, etc... And then, as for the jquery binding, again checking for depth I added another $(function(){ ... }); for #crudForm1 right at the end of the file ... that seems to work. I believe I need to do this for add.php as well. But I am still thinking about how to make the foreign key in child form to autoset with the parent's ID, especially in add form. In edit, I believe I can just hide the field.
Here's how my edit.php looks like
<?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 crud-form" style='width: 100%;'>
<div class="mDiv">
<div class="ftitle">
<div class='ftitle-left'>
<?php echo $this->l('form_edit'); ?> <?php echo $subject?>
</div>
<div class='ftitle-right'>
<a href='<?php echo "$list_url$depth_url";?>' onclick='javascript: return goToList()'><?php echo "« ".$this->l('form_back_to_list'); ?></a>
<a href='<?php echo "$view_url/$primary_key$depth_url";?>' onclick='javascript: return goToView()'><?php //echo $this->l('list_view');?><span class='view-icon'></span></a>
</div>
<div class='clear'></div>
</div>
<div title="Minimize/Maximize Table" class="ptogtitle">
<span></span>
</div>
</div>
<div id='main-table-box'>
<form action='<?php echo $update_url?>' method='post' id='crudForm<?php echo $depth?>' autocomplete='off' enctype="multipart/form-data">
<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<?php echo $depth?>' class='report-div error'></div>
<div id='report-success<?php echo $depth?>' class='report-div success'></div>
</div>
<div class="pDiv">
<div class='form-button-box'>
<input type='submit' value='<?php echo $this->l('form_update_changes'); ?>' />
</div>
<div class='form-button-box'>
<input type='button' value='<?php echo $this->l('form_cancel'); ?>' onclick='javascript: return goToList()' />
</div>
<div class='form-button-box'>
<div class='small-loading' id='FormLoading<?php echo $depth?>'><?php echo $this->l('form_update_loading'); ?></div>
</div>
<div class='clear'></div>
</div>
</form>
</div>
</div>
<script>
var validation_url = '<?php echo $validation_url?>';
var list_url = '<?php echo "$list_url$depth_url";?>';
var view_url = '<?php echo "$view_url/$primary_key$depth_url";?>';
var message_alert_edit_form = "<?php echo $this->l('alert_edit_form')?>";
var message_update_error = "<?php echo $this->l('update_error')?>";
<?php if ($depth != '') { ?>
// ---- crudForm1 ------
$(function(){
$("#FormLoading<?php echo $depth?>").ajaxStart(function(){
$(this).show();
});
$("#FormLoading<?php echo $depth?>").ajaxStop(function(){
$(this).fadeOut('slow');
});
$('#crudForm<?php echo $depth?>').submit(function(){
$(this).ajaxSubmit({
url: validation_url,
dataType: 'json',
cache: 'false',
success: function(data){
if(data.success)
{
$('#crudForm<?php echo $depth?>').ajaxSubmit({
dataType: 'text',
cache: 'false',
success: function(result){
data = $.parseJSON( result );
if(data.success)
{
$('#report-error<?php echo $depth?>').hide().html('');
$('.field_error').each(function(){
$(this).removeClass('field_error');
});
$('#report-success<?php echo $depth?>').html(data.success_message);
$('#report-success<?php echo $depth?>').slideDown('slow');
}
else
{
alert( message_update_error );
}
},
error: function(){
alert( message_update_error );
}
});
}
else
{
$('.field_error').each(function(){
$(this).removeClass('field_error');
});
$('#report-error<?php echo $depth?>').slideUp('fast');
$('#report-error<?php echo $depth?>').html(data.error_message);
$.each(data.error_fields, function(index,value){
$('input[name='+index+']').addClass('field_error');
});
$('#report-error<?php echo $depth?>').slideDown('normal');
$('#report-success<?php echo $depth?>').slideUp('fast').html('');
}
}
});
return false;
});
});
<?php } ?>
</script>
Posted 23 January 2012 - 03:16 AM
Posted 24 January 2012 - 10:55 AM
Sorry about the late reply - been away from the computer for a few days, but I will be back into it from tomorrow. Lots more cool things coming up !
Posted 26 January 2012 - 07:04 AM
Posted 26 January 2012 - 22:56 PM
Thanks heaps Iszuddin - that would have taken me forever to find that one. I will have a look at your patch and merge that up with my code. Thanks again.
Sorry about the late reply - been away from the computer for a few days, but I will be back into it from tomorrow. Lots more cool things coming up !
[/quote]
Glad that you are back. Anyway, do you have any idea how to implement the parent's ID into the child's form autoset? Otherwise the user would have to know what's the parent's ID is when adding new child data, and that wouldn't be ideal. I am also looking into modifying the jQuery binding so that it works better which child forms.
By the way Johnny released 1.1.8 while you were away.
Posted 27 January 2012 - 00:32 AM
@Iszuddin :
The primary_key passed down from the parent form - maybe I should just add that automatically as a hidden field ? That would solve the issue quite elegantly, without needing any user callbacks to be used.
1.1.8 has been integrated in ... still integrating your hacks at the moment. Looks easy enough.
@CodeRider - I have taken a note of that bug, thanks for highlighting that one. I will post a patch as soon as I fix it. I assume you are using flexigrid ? Still may be some issues with datatables as far as I know.
Just holding off writing some documentation and examples at the moment, because I am thinking of adding a couple of little changes that will be tricky to implement.
1) Is to allow multiple child forms to be chained to a parent form. Bit hard to explain, but obvious once you see it working. ie - imagine a parent form with 2 or more sub-lists from different child tables underneath, each a fully fledged CRUD list. I have a need for this in my application.
2) Keep the default behaviour where child CRUD forms are placed directly below the parent form. However, add a new option, to allow a specific layout of parent and child forms that is different to this. example :
Default behaviour is :
-----------------------------
parent form
...
-----------------------------
child form underneath
...
-----------------------------
optional layout :
---------------------------------------------
parent form on | 1st child on the right
the left | ...
|---------------------------
| 2nd child form on
| the right
--------------------------------------------------
3rd child form underneath
...
--------------------------------------------------
Hope that makes sense ... It means that a collection of parent-child forms is modelled as a tree structure rather than a straight line relationship. Internally, each grocery_crud object would have a pointer to the parent form, and an array of pointers to child forms (rather than a single pointer to a child form)
Having that working would completely finish off the whole concept of automatic parent-child forms I think. That should cover 99% of common form layouts. Enough for me to finish off my application the way that I want it to look anyway.
The API for this is simple enough in the above example :
$form_parent = new grocery_CRUD(parent form);
$form_child1 = new grocery_CRUD(1st child form);
$form_child2 = new grocery_CRUD(2nd child form);
$form_child3 = new grocery_CRUD(3rd child form);
$form_child1->chain_to($form_parent, 'key field', LAYOUT_RIGHT);
$form_child2->chain_to($form_parent, 'key field', LAYOUT_RIGHT);
$form_child3->chain_to($form_parent, 'key field'); // default layout - directly under the parent form
Whilst the API is simple, adding multiple child forms is pretty tricky to pull off. Worth doing though ... I just need to get myself back into the right headspace, and I should be able to knock this off real quick.
Cheers.