- One way to do this is to grab the current query:
The --msg query string variable allows you to display a confirmation message. We put an exit after the header function to make sure nothing else in the script runs. - The above way works, but it leaves the primary id of the record you just added in the url. Probably not the best thing to do, another way to do it is just use the header function and manually enter the query parameters:
header('Location: '.DATAFACE_SITE_HREF.'?-table=tablename&-action=new
I used the DATAFACE_SITE_HREF constant variable here which provides the path your application. You NEVER want to hardcode your application path since portable. You can put this function like in your after_action_new() trigger so that after you add a record, it allow you to add another record right away.
Showing posts with label actions. Show all posts
Showing posts with label actions. Show all posts
Thursday, August 14, 2008
Redirecting to a page
Say after an action in Xataface (eg. finished adding a new record), by default it goes to the edit action for that record you just added. But say you want it to go to the new action to add another another. There are a few ways to do this:
Thursday, June 26, 2008
Displaying actions in a html select object
Here is an interesting example of how to use actions in an html select from object.
In our actions.ini file (delegate or conf.ini) we have a set of actions each with the category attribute set to bd_company_filters. Like this:
In our delegate class, we can access these actions like this:
The first line retrieves the Dataface_ActionTool object which we then use to return an array of actions underneath the category bd_company_filters. Each action in the array of actions will contain the attributes specified in the actions.ini and can be accessed by simply using the normal array key like this:
Here we are accessing the url attribute of each action under this category.
So putting it all together, we can do something like this (NOTE: this code is in the block__before_result_list() function):
Here we are creating a html select object and then we are placing the different actions as options for the select valuelist. The labels of the actions act as the labels in the select list, and the urls are used as the values of the options.
A little simple javascript is used to change the window.location to the value of the selected item in the list on change.
In our actions.ini file (delegate or conf.ini) we have a set of actions each with the category attribute set to bd_company_filters. Like this:
[show_only_approved_news]
;; Show only companies that have been approved by this broker dealer
url="{$this->url('approval_status=2')}"
condition="$query['-table'] == 'news' and isBrokerDealer()"
label="Approved News"
category=bd_news_filters
In our delegate class, we can access these actions like this:
$at =& Dataface_ActionTool::getInstance();
$actions = $at->getActions(array('category'=>'bd_company_filters'));
The first line retrieves the Dataface_ActionTool object which we then use to return an array of actions underneath the category bd_company_filters. Each action in the array of actions will contain the attributes specified in the actions.ini and can be accessed by simply using the normal array key like this:
foreach ($actions as $action){
echo action['url']
}
Here we are accessing the url attribute of each action under this category.
So putting it all together, we can do something like this (NOTE: this code is in the block__before_result_list() function):
$at =& Dataface_ActionTool::getInstance();
$actions = $at->getActions(array('category'=>'bd_company_filters'));
echo '<select onchange="window.location=this.options[this.selectedIndex].value" class="company_filters">';
echo '<option value="#">Filter Resources in this Category</option>';
foreach ($actions as $action){
echo '<option value="'.$action['url'].'">'.$action['label'].'</option>';
}
echo '</select>';
Here we are creating a html select object and then we are placing the different actions as options for the select valuelist. The labels of the actions act as the labels in the select list, and the urls are used as the values of the options.
A little simple javascript is used to change the window.location to the value of the selected item in the list on change.
Wednesday, April 9, 2008
Actions: Adding new actions at specific locations
One thing that seemed to escape me for the longest time was the fact that when I included an actions.ini, or like a permissions.ini file in my website's directory. I was actually overriding the actions and permissons.ini files in the main dataface directory.
My point of stating this was I wanted to figure out how to like add new actions to specific blocks/spaces in my website. Like for example, where the "list", "detail", "find" buttons are. In the actions.ini file, each action has an attribute called category and you can assign this a value. And then templates will uses these categories to figure out which actions to place where.
So my problem was trying to find out what categories were available. All this information is available in the dataface directory's actions.ini file.
My point of stating this was I wanted to figure out how to like add new actions to specific blocks/spaces in my website. Like for example, where the "list", "detail", "find" buttons are. In the actions.ini file, each action has an attribute called category and you can assign this a value. And then templates will uses these categories to figure out which actions to place where.
So my problem was trying to find out what categories were available. All this information is available in the dataface directory's actions.ini file.
Thursday, April 3, 2008
Creating approval levels for records through dynamic forms
This was done on the advisorpage website. I had so much trouble figuring how to do this, but I finally got it done. Before I show you how to do it, I want to give the situation this was applied. There a bunch of companies that needed to be approved. There were separate approval levels: approved, conditionally approved, and not approved. Rather than have the user have to go into the company detail page and select approve, disapprove, and stuff. The client wanted the ability to change the approval level in list view. The default list view of the companies was changed and the list of different approved options to change the approval level was displayed in the list view.
This was done through the actions.ini file and assigning actions to the category=record_actions. The list view displays any actions under this category in a specific location specified in the template. So there are several key things to note here:
This was done using actions. In the application's actions.ini file, there was three separate actions called bd_approve, bd_approve_record and bd_conditional_approve_record. Each of these actions corresponds to a separate thing that can be done to the company record. The content of one of these actions:
Here the url attribute is assigned to a javascript function called WLS_ApproveCompany(). This function is found in the script.js file in the folder js and it was included into the website in the ApplicationDelegate class by the function block__custom_javascripts():
If you to the script.js and find that function:
Here we are grabbing the html form companyApprovalForm (more on this later) assigning the elements --selected-ids and --level values to the function inputs.
The --selected-ids variable has to exactly named this way. This is because we use a Dataface function called df_get_records() which looks specify for the --selected-ids variable.
And this submitting the form using javascript. The form is located in the templates folder called companyApprovalForm.html:
Here we are just including all the values in the query string into this form so that when we submit it they are included in the post request and can be used again. Note the --level and --selected-id elements. We changed this in the javascript function. Notice how the action of the form is itself, but there is an additional element called -action and with a value called "bd_approve." This action is in the actions folder and called bd_approve.php. It is called when the page is get reloaded because the query string will have ?-action=bd_approve.php will tells it to run this.
The key thing to note is that if something isn't in the query string it won't be put into the form. You have to include the selected_ids and level in the $name not equal because it will continue to add these hidden fields to the form when you refresh it
So I was trying to extend this to include a separate form that handled trust values. The problem was I wasn't including the approval level in the query string and so when I tried to modify the database, I was just overriding the approval level (you will see why in a bit). We need to include this form on the page of our interest. So we can use the particular delegate class of our interest, and insert this code:
The bd_approve.php class
The important line is the one with the sql statement
And then we include the values. So we've now changed the approval level. It is important to notice that any columns in that record that don't have a value will be set to their default...meaning it will get overwritten. For example, say the dealer_companies had another column called trust_level. If I just included the replace statement without specifying the trust_level, it will always set that value to the default which could be like 0.
So you have to include the trust value even if you are only modifying the approval level. The way to make the changes are:
The next step is getting that to be reflected in the actions. Remember in our actions.ini file, for each action there was an attribute called condition which had this:
record->val('approval_level')
function init(&$table)
This is a function that is called each time the companies table is run. Note that the parameter $table refers to the dataface company table (like a table class that dataface represents). This allows us to create like an extended version of the companies table in the sense that we are adding new columns.
What is done here is:
We create a temporary table which grabs columns from other tables. We need to write the sql code to do this like this:
I am not going to show all the code, but the idea is to store the sql queries in an array of sql statements. And then:
This will execute the sql statements for use. And then the MyCompanyPermissions table will be available for use each time the companies table is executed.
__sql__ function
This function is the function that is called to override the usual sql statement which grabs rows from the companies table (or in delegate class). By default it will grab all rows using the statement "SELECT * FROM table_name". But we are overriding it here. We are still grabbing all rows, but now we are inner joining it with the MyCompanyPermission table that we just created:
It is important to understand that the __sql__ function must still grab all the rows of the original table. It can only add new columns.
Note the use of the left join here. We can't just normally do the SELECT column1, column2, FROM A, B WHERE (A.a = B.b). Because we need to grab all companies. Some companies might not actually have an approval level...so if we just did that they would not be returned. But if we did a left join, it will always return a row from the companies table (or which ever table was on the left of the join...hence the name LEFT JOIN) regardless of whether there was a row in the right table.
So our companies table is actually expanded by some additionally columns, and thus we have access to MyRole, approval_level, and trust_level columns. Note the trust level column was actually something I was adding on to the system.
This was done through the actions.ini file and assigning actions to the category=record_actions. The list view displays any actions under this category in a specific location specified in the template. So there are several key things to note here:
- All the companies information was stored in a companies table
- The details of approval were stored in a separate table called dealers_companies. The reason this was done was because there were different dealers for the website, and each dealer wanted the ability to either approval or not approve the company. The net result is that each approval level is specific to a certain dealer. So that there "customers" will only see what companies THEIR dealer approved of and not others.
This was done using actions. In the application's actions.ini file, there was three separate actions called bd_approve, bd_approve_record and bd_conditional_approve_record. Each of these actions corresponds to a separate thing that can be done to the company record. The content of one of these actions:
[bd_approve_record]
;; This action is available to Broker Dealers to change the approval level
;; of the current record to "Approved"
label="Approve"
category=record_actions
condition="$record and $record->_table->tablename == 'companies' and isBrokerDealer() and $record->val('approval_level') < url="">getId()}');"
url_condition="$record"
permission=bd_approve
icon="images/confirm_icon.gif"
description="Approve this company and all its news to be viewed by your agents."
- The label attribute was used to display the text of the action
- category was used to group this action under the record_actions category which is used by the template to show actions under this category at a location specified
- condition is when this action appears. Here we say that there must be a record, the tablename must be companies, the user logged in must a broker dealer and the approval level of the record must be less than 2.
Note that the companies doesn't include an approval level, this is actually found in a separate table called called "dealer_companies" This issue will be addressed later. - url_condition is like the condition the url has to satisfy in order for this action to be present. The reason why this is needed is because the condition attribute relies on like a record...so unless there is a record it won't be able to like apply the conditions. The url condition first checks to make sure that the url has a record...something along those lines.
- permission is taken from the permissions.ini file. Here the user who is currently logged on must have the bd_approve permission for this action to appear.
- icon is the image that appears beside the label
- description is the text that appears when the label is mouseovered..
Here the url attribute is assigned to a javascript function called WLS_ApproveCompany(). This function is found in the script.js file in the folder js and it was included into the website in the ApplicationDelegate class by the function block__custom_javascripts():
function block__custom_javascripts(){
echo '<script src="%27.DATAFACE_SITE_URL.%27/js/scripts.js" type="text/javascript" language="javascript"></script>';
echo '<script src="%27.DATAFACE_SITE_URL.%27/js/menu.js" type="text/javascript" language="javascript"></script>';
}
If you to the script.js and find that function:
function WLS_ApproveCompany(level, id){
var form = document.getElementById('companyApprovalForm');
form.elements['--selected-ids'].value = id;
form.elements['--level'].value = level;
form.submit();
}
Here we are grabbing the html form companyApprovalForm (more on this later) assigning the elements --selected-ids and --level values to the function inputs.
The --selected-ids variable has to exactly named this way. This is because we use a Dataface function called df_get_records() which looks specify for the --selected-ids variable.
And this submitting the form using javascript. The form is located in the templates folder called companyApprovalForm.html:
Here we are just including all the values in the query string into this form so that when we submit it they are included in the post request and can be used again. Note the --level and --selected-id elements. We changed this in the javascript function. Notice how the action of the form is itself, but there is an additional element called -action and with a value called "bd_approve." This action is in the actions folder and called bd_approve.php. It is called when the page is get reloaded because the query string will have ?-action=bd_approve.php will tells it to run this.
The key thing to note is that if something isn't in the query string it won't be put into the form. You have to include the selected_ids and level in the $name not equal because it will continue to add these hidden fields to the form when you refresh it
So I was trying to extend this to include a separate form that handled trust values. The problem was I wasn't including the approval level in the query string and so when I tried to modify the database, I was just overriding the approval level (you will see why in a bit). We need to include this form on the page of our interest. So we can use the particular delegate class of our interest, and insert this code:
function block__before_header(){
df_display(array(), 'abstract_approval_form.html');
The bd_approve.php class
class actions_bd_approve {
function handle(&$params){
$app =& Dataface_Application::getInstance();
$query =& $app->getQuery();
$records = df_get_selected_records($query);
//echo count($records).' records selected.';
$dealerid = getDealerID();
if ( !isset($dealerid) ){
return PEAR::raiseError("No dealer id set", DATAFACE_E_ERROR);
}
if ( !isBrokerDealer() ){
return PEAR::raiseError("Sorry, you must be a BD Administrator to approve companies for your BD.", DATAFACE_E_ERROR);
}
if ( !isset($_REQUEST['--level']) ){
$level = 0;
} else {
$level = $_REQUEST['--level'];
}
$sql = array();
$sql[] = "replace into dealer_companies (company_id,dealer_id,approval_level) values ";
$vals = array();
foreach ($records as $rec){
if ( $rec->_table->tablename != 'companies' ){
// we only approve companies
continue;
}
$vals[] = "('".$rec->val('company_id')."','$dealerid', '$level')";
}
if (count($vals) == 0 ) return PEAR::raiseError("No records were selected to be approved", DATAFACE_E_ERROR);
$sql[] = implode(',', $vals);
$sql = implode(' ',$sql);
$res = mysql_query($sql, df_db());
if ( !$res ) return PEAR::raiseError("A mysql error occurred while trying to approve companies: ".mysql_error(df_db()), DATAFACE_E_ERROR);
if ( isset($query['-from']) ){
$query['-action'] = $query['-from'];
} else {
$query['-action'] = 'list';
}
$url = $app->url($query).'&--msg='.urlencode('The selected companies have been succesfully approved for viewing by your representatives. '.count($vals).' companies approved.');
header("Location: $url");
exit;
}
}
The important line is the one with the sql statement
"$sql[] = "replace into dealer_companies (company_id,dealer_id,approval_level) values ";"
And then we include the values. So we've now changed the approval level. It is important to notice that any columns in that record that don't have a value will be set to their default...meaning it will get overwritten. For example, say the dealer_companies had another column called trust_level. If I just included the replace statement without specifying the trust_level, it will always set that value to the default which could be like 0.
So you have to include the trust value even if you are only modifying the approval level. The way to make the changes are:
$sql[] = "replace into dealer_companies (company_id,dealer_id, approval_level) values ";
BECOMES
$sql[] = "replace into dealer_companies (company_id,dealer_id, approval_level, trust_level) values ";
Have to add this in the foreach loop to grab the trust level of the corresponding record:
$trust_level = $rec->val('trust_level');
And finally:
$vals[] = "('$company_id','$dealerid', '$level')";
BECOMES
$vals[] = "('$company_id','$dealerid', '$level')";
The next step is getting that to be reflected in the actions. Remember in our actions.ini file, for each action there was an attribute called condition which had this:
record->val('approval_level')
function init(&$table)
This is a function that is called each time the companies table is run. Note that the parameter $table refers to the dataface company table (like a table class that dataface represents). This allows us to create like an extended version of the companies table in the sense that we are adding new columns.
What is done here is:
$app =& Dataface_Application::getInstance();
$sql = array();
$sql[] = "create temporary table MyCompanyPermissions (
company_id int(11) not null,
role varchar(32) not null,
approval_level int(5) default 0,
trust_level int(1) default 0,
Primary Key (company_id))";
We create a temporary table which grabs columns from other tables. We need to write the sql code to do this like this:
$sql[] = "replace into MyCompanyPermissions (company_id,role,approval_level)
select c.company_id, '$defaultRole' as role, ct.approval_level from companies c inner join company_types ct on c.resource_type=ct.id where ct.approval_level > '".APPROVAL_LEVEL_NOT_APPROVED."'";
I am not going to show all the code, but the idea is to store the sql queries in an array of sql statements. And then:
foreach ($sql as $query){
$res = mysql_query($query, df_db());
if ( !$res ){
trigger_error(mysql_error(df_db()).' while executing SQL query "'.$query.'"', E_USER_ERROR);
}
}
This will execute the sql statements for use. And then the MyCompanyPermissions table will be available for use each time the companies table is executed.
__sql__ function
This function is the function that is called to override the usual sql statement which grabs rows from the companies table (or in delegate class). By default it will grab all rows using the statement "SELECT * FROM table_name". But we are overriding it here. We are still grabbing all rows, but now we are inner joining it with the MyCompanyPermission table that we just created:
function __sql__(){
return "select c.*, mcp.role as MyRole, mcp.approval_level, mcp.trust_level from companies c left join MyCompanyPermissions mcp on c.company_id=mcp.company_id";
It is important to understand that the __sql__ function must still grab all the rows of the original table. It can only add new columns.
Note the use of the left join here. We can't just normally do the SELECT column1, column2, FROM A, B WHERE (A.a = B.b). Because we need to grab all companies. Some companies might not actually have an approval level...so if we just did that they would not be returned. But if we did a left join, it will always return a row from the companies table (or which ever table was on the left of the join...hence the name LEFT JOIN) regardless of whether there was a row in the right table.
So our companies table is actually expanded by some additionally columns, and thus we have access to MyRole, approval_level, and trust_level columns. Note the trust level column was actually something I was adding on to the system.
Subscribe to:
Posts (Atom)