Are Wizards & Transient Models the right way to implement complex interactive search across several tables (objects) and to visualize data aggregated from several objects?
“Complex interactive search” means a search panel with several input fields for entering search criteria, where input fields are dynamically filtered according to user access rules and data from other fields.
“Across several tables” means data stored in different objects (osv.Model) -- i.e. not only in different tables, but in different python 'objects' (osv.Model).
My current implementation using wizards & transients has the following drawbacks:
no way of filtering / grouping search results. Search results are handled as a one2many field, displayed as a Tree view in the Form view of the parent search wizard ==> hence no way of grouping results inside a form view of a wizard. Frankly, I’d be happy if there would be a way of making a complex search over multiple objects from a Tree view, as we do it with simple search on a single object.
2 reloads of a page happen when changing input parameters and making another search. First, the page is refreshed with the old results inside, and then after a second or two (w/o showing “Loading…”) the page is refreshed with the new results appearing. This doesn’t happen if I search with the same parameters several times in a row -- then only 1 refresh happens. This double refresh is very user-unfriendly, as it creates an impression that the search failed (the old results are displayed). Probably, this happens because on every search I create a new wizard instance (to keep a search history before it’s cleared with autovacuum) and return its id as a 'res_id'. However, I create a copy of previous wizard by passing an empty list as default search results ids, so I wouldn’t expect the old-results to show up. Also, I wouldn’t expect the second refresh to happen.
results from all previous searches are preserved on the client side and just made hidden on the page instead of being removed completely from the page ===> makes the page heavy after a lot of searches. E.g.:
<div class="oe_view_manager oe_view_manager_inline" style="display: none;">
<div class="oe_view_manager oe_view_manager_inline" style="display: none;">
<div class="oe_view_manager oe_view_manager_inline" style="display: none;">
<div class="oe_view_manager oe_view_manager_inline">
Here: 3 old result sets + the current active one (visible). Think I can get rid of those old results using JavaScript. Still, I wonder what is the purpose of such preserve&hide behavior?
Related
Sorry this isn't a specific coding question, it is more of a design concept.
What is the usage case for programmatically adding and removing fields to Notes Forms e.g. NotesDocument.RemoveItem(), ie why would you add and remove fields in the background?
For many years I have designed my forms with the fields layed out on the form which are required and then hide and show as required.
By adding dynamically you can't position them and frustratingly removing them or deleting they still appear the Database Fields in Domino Designer, getting rid of them is a bit a a black art, but that's another story.
I must be missing a trick or a basic design concept. Any thoughts on best practice would be appreciated.
Many thanks.
Yes, you are missing the difference between "Fields" and "Items". A field is a design element that you can place anywhere on your form. You define how it looks, what content it contains, what datatype it is, etc.
When creating a document with the form the value of the FIELD is stored in an ITEM in the resulting NotesDocument.
This item is totally decoupled from the field that created it. If you were to change the field in the form from text to number or move it around or make a names- field of it, the item in the existing documents would never change unless you open the documents and save them in frontend or use any LotusScript or Formula Code to recalculate the document in backend.
Very often items are added programmatically to documents to fulfill different purposes: Calculate values to be displayed in views, calculate values that are import for the workflow but not for the user, etc.
Complex applications often consist of a lot more items than there are fields in the several forms.
Back to your question: Removing an item from a document simply removes the value that was created by the field in the form. When reopening the document, the item will be repopulated, either by default value or whatever....
Usually you would use this to remove items that you no longer need (and probably already removed from the form).
As soon as you removed all references to a field / item everywhere in design and documents, you can finally get rid of it completely by compacting the database.
An item is distinct from a field in Notes. The form is purely a UI concept, the item is what the data is stored in.
Manipulating data in the backend can be used for a number of reasons. One such use case is the setting of a flag when a date on the form has expired.
Say you want a view showing all documents that have expired. Your rules dictate that documents are considered as "Expired" after 7 days. You could create a view with a formula that shows all document whose date is 7 days older than today:
SELECT Date < #Adjust(#Today; 0; 0; -7; 0; 0; 0);
This view will ALWAYS be out of date and will constantly be updated by the server as it re-evaluates #Today.
Now, a better way would be to create an agent that runs daily that sets an item on the document to indicate that it has expired e.g.
#SetField("Expired"; 1);
The view formula would then be
SELECT Expired = 1
The view would only need to update daily and you have a much faster view because of it.
RemoveItem is used to get rid of data no longer needed e.g. FaxNumber.
There are many use cases for RemoveItem. Here's one that comes up frequently.
You have a database and an agent that processes documents in that database. Every time it runs, the agent replaces the value of a bunch of items. There are a variety of error conditions that can cause it to abort processing a document early, but you're a smart programmer and you've accounted for that with on error traps. When you hit one, you log an error message, save your document, and then either abort your agent or go on to processing the next document.
But at this point, some of the items that the agent normally updates have values saved from this run, and some of them have values saved from a previous run. This might be bad. This might be confusing for someone who is looking at the item values and trying to figure out what's going on. This might even cause validation errors on the form.
So how do you avoid this? At the very beginning of your agent, you call a cleanup sub that finds and removes all the items that the agent is going to update. Now you have a clean slate, and if your agent hits that error condition, it can save whatever it can save without any concern about whether it is leaving things in an inconsistent state. Of course, in cases where you are doing this to avoid validation errors, your validation formulas will have to be smart enough to be checking #IsAvailable for dependent items, but that's a good practice anyhow.
I have, what I think is, a simple feature that I am trying to add to my Orchard (1.6) site, but I can't find any tutorials or instructions on how to do it. I have a custom type called "Office" and each office has a custom field called "State" indicating which state the office is in. I actually designed my Offices as a custom part in code with specific properties such as State on it, but I "think" it's the same as if I added the State through the Admin interface as a field on the Office content part.
Now, I can create a basic projection to show all the offices with a simple filter of "Content with type Office" to display all offices. However, what I want to do now is to have a drop down list at the top of the page that says "Filter by: [-SELECT STATE-]" with a list of all 50 states. When the user selects a state, the page should refresh and display just the offices in that state.
This is where I'm stuck. Should I do this through the code, or can I do this through the Admin UI? If through the code, should I model it after the Orchard.Search module (which I tried to do, but I am completely lost). If I can do it through the UI, do I use projections? If so, do I have to create 50 separate projections (one for each state)? That seems extremely time consuming to create and maintain.
Any help is GREATLY appreciated!
FYI, the site at http://ktowneric.com/listings/search (which uses Orchard) is very similar what I am looking for, and the developer stated he used projections, but I can't seem to figure out how he did it.
You can definitely use a projection. If you notice when you use the search function on the page you referenced, the inputs are formed into query string values. You can use tokens to grab the values from query strings to use in your projection filter. For example, if you're using fields as you stated, then you just add a filter for that field and in the value field use {Request.QueryString:State}. Or, replace "State" with whatever key you're using for the query string value.
That solves your projection issue. You will need to build a search form that would look something like this...
<form action="/search-results" method="Get">
<select name="State">
<option value="OH">Ohio</option>
...all the states...
</select>
<input type="submit" value="Search" />
</form>
"/search-results" could be a projection page or any content that has the projection widget present. You could build the form as a widget that you can place somewhere, or for testing purposes, you could just paste this html into an html widget to try it out.
If you add grouping to a list view does it inheretly improve performance when you navigate to the view in the sharepoint page? i.e. if you use grouping, does sharepoint retrieve data when you click the [+] icon (using an Ajax call)? or is the data already retrieved beforehand?
Many thanks.
when u use grouping by default all your group document are not loaded first time. when u expand group it load all document.
After that using JavaScript it change the property from display none to display block and display block to display none and so on.
so according to performance it load all document first time but it's quick.
This is same for list also
My experience is that using groupings loads all data at once. So if you have a list with 1000 items and you display a grouped view, you may experience very slow loading.
Many websites use <input type='text'> element to get simple text data from their customers. You can configure your browser to remember the values you enter into these fields, so that it can suggest you back a list of values, to speed up your data entry experience.
However, I'm seeing a strange behavior. On some fields of the same type, browser doesn't suggest anything, or suggests a different list from other fields. I've checked all fields and all of them are of the same <input type='text'> type.
Does anybody know how browser differentiates between different lists (or no list) for the same HTML form control?
There's an attribute on form elements that allows them to semantically specify their intended content (I believe its the V_Card attribute).
The following page gives a brief explanation and a table of acceptable values:
http://microformats.org/wiki/hcard-input-formats
What's a good way to paginate a list that is constantly growing?
For example, a user may open page 2 of some listing, keep looking at it for a while and then open page 3. Meanwhile, new records have been added to the beginning of the list (page 1) and caused page 3 to contain items that could have been on page 2 previously.
Should such a list be paginated from the other end? Then how to deal with the front page and the fact that it would, without special attention, contain TOTAL NUMBER OF ITEMS % PAGE SIZE items (ie. not constant)?
Assuming you have a fixed page size, some specified ordering, and the user is specifying the page they wish to view, I would simply fetch the data accordingly. Trying to do anything more complicated than that will just end up causing you unnecessary headache and confuse the user.
I think the element you're missing here is the ordering. If you specify an ordering then the user will intuitively understand. Also, that's how the majority of pagination is done, so you're not deviating from what you're user really expects.
I'd add a warning to advise the user that new items have come in and allow them to refresh the list. If they choose not to then maintain list in the state it was in when they clicked on the "Page 2" button. You can use a timestamp on the URL to determine which version of the list to serve to which user.
I do not think it's a good idea to page through a growing list. You'd better recalculate items that should be displayed on a page everytime user performs an action.