Feature (approved)

create person item table


Oct 10, 2006
Oct 10, 2006 / pixtur
Mar 10, 2011 / guest
burger, pixtur

Attached files

Stores relation ship of items to persons:

NOTE: This is a very rough draft. Please add commentss on any aspects!

possibile purposes:π

  • if item has been viewed of downloaded (or number of views)
  • if item has been editing by person?

From we could add:
  • remember_unchanged - duration until a notification is been sent that item has not been modified (in seconds)
  • is_bookmark
  • notify_on_change - Sent instant mail on changes and comments.

Implementation Details:π

This object should not be derived from DbProjectItem because it's not real data there is not right managment needed for it. The rows of this table can not be querried directly.


Type Name Comment
INTid primary key
INTnotify_if_unchangedduration until a notification is been sent that item has not been modified (in seconds)
BOOLnotify_on_changeSent instant mail on changes and comments (item is monitored)

also see:π

  • previous Discussion:
  • related features:



12 years ago (2. update 12 years ago)

Hi Tom,

is it okay if I join you to handle this task?

It is really important for us so that it would be great if I could start with this task.


12 years ago (4. update 12 years ago)

Thomas (binder) and me, we discussed this topic and we have some suggestions:
  • table 'myprojitems' with db fields:
    • id (int)
    • person (int)
    • item (int)
    • viewed (bool)
    • viewed_last (datetime)
    • remember_unchanged (int)
    • remember_unchanged_sent (bool)
    • is_bookmark (bool)
    • notify_on_change (bool)
  • stored items:
    • only items which are elements of project (project, task, version, effort, ...)
    • reason: it don't make sense to e.g. show companies as not viewed or the like
  • handling:
    • every person with account is related to every projitem (every person x every projitem)
    • reason: it takes more time and effort to check which person has which rights and which person is related to which project/task/... as to have a db table with some useless entries
  • handling of 'viewed':
    • if e.g. a new task is added then it will be related to every person in the myprojitems-table (viewed = false)
    • if a person read the task then the recordset related to this person and task will be set to viewed = true and viewed_last = current date/time
    • if a task is modified then for all recordsets related to this task the field is set to viewed = false to mark the change


12 years ago (2. update 12 years ago)

To mark e.g. at the tasklist which tasks are read or unread we would like to mark the unread as bold like unread emails because everyone is used to this behaviour.


12 years ago (3. update 12 years ago)

Dear Burger,

sorry for this late reply. I was very busy during the last days...

On your suggestions...π

I do not think that your suggested implementation is an optimal solution:
  • Never store useless data to the database
  • Inserting rows on the fly costs nothing. The new rows have only to be added, if current_user accesses some few pages (taskView, projView etc.)
  • Checking if an item has been viewed is fast, because it's just checking if there is one row matching (item== id and person == cur_user->id)
  • Rolling out the table will tremendously slow down creation of new items if there are many users.
  • I don't see why this table should be reduced to certain item types. I just would implement it for all items and later decide if to display this information. I might be useful to see, if a person has downloaded a file.
  • This table is not involved in any user rights checking. It should only be used by other functions to get additional information on an item that already has been approved to as being visible.
  • Due to the already existing DB-Tables I would call this table itemperson.
Although I love the idea of highlighting new items as bold I see some problems with the already existing display style in Clean Theme. Bold is already used at many other places, so this would lead to some inconsistency. I would rather introduce a "visited link color" which is also some how a standard ;-) Alternatively we could highlight new items. But this is only a matter of CSS...

Sorry for this erm... negative feedback. But I really would love you to implement this feature, though.

I will write some more details on a suggested implement in the task's description.


binder:some more information

12 years ago (2. update 12 years ago)

the problem we had, is to decide, whether users have the right to view specific items. and this can be changed though. The time needed to create the db-entries on creation should be not really extend the time needed at present. but to check on a change of item, who has the right to see this is more complicated and needs more time in my opinion...
and as you stated in some other comment "database space costs nothing" ;)

what we could do is to create the entry "on the fly", but this means, if you open an item, streber needs to check, whether an entry is alredy made with your person-id and update the settings, if not create one.... perhaps we need some more thinking! ;)

pixtur:I still don't get it...

12 years ago (2. update 12 years ago)

I would implemented like this:
  1. create a non project item table similar to itemchange
  2. Create new member functions to ItemChange:
 public function isViewedByUser($user=NULL) 
   global $auth;
   if(is_null($user)) {
     if($auth->cur_user) {
       $user= $auth->cur_user;
     else {
       return NULL;
   if($view= ItemPerson::getByPersonItem($user->id, $this->id)) {
      $view-> viewed ++;
   else {
     $new_view= new ItemPerson(array(
        'item'=> $this->id,
        'person'=> $user->id,
        'viewed' => 1,
        ### ... some more here ...

 public function wasViewedByUser($user= NULL) {
   ###... similar like above function

  1. In direct view pages (taskView, personView, commentView, effortView, companyView, projectView, fileView, fileDownload, fileDownloadAsImage) add line...
  1. In list rendering functions add line like:
  if($viewed= ItemPerson::getByItemPerson($obj->id, NULL)) {
     ### do some special stuff here like...
     if($viewed->last_time <= $obj->modified) {
        ### highlight...

     if($viewed->monitor && $viewed->last_time <= $obj->modified) {
        ### very important, because monitored item was changed ###
  else {
     ### highlight because not viewed yet

There is no need to check for visibility.


If performance will be too slow, we could query to itemperson-fields directly to the Item-Class similar like an Item is constructed from the Item-Part and the actual data part (like 'Task'). But this will be some incredibly complex code...

pixtur:View collapsed could be in person item table too...

12 years ago (2. update 12 years ago)

I am not sure, if this is useful, but actually the option, if an folders is collapsed or open might be user specific. The itemperson-table would be the right place to store this information.

binder:some more thoughts

12 years ago (2. update 12 years ago)

ok. imagine you're adding a new item. What has to be done:
  1. create lines to itemperson-table
  2. if rendering lists
    • check if item is read
    • check other features as suggested
    • ...
  1. don't create lines
  2. if rendering lists
    • check if item/person is in itemperson-table
    • add line to itemperson-table, if not
    • check if item is read
    • check other features as suggested
    • ...
am I missing something?

pixtur:why create itemperson if not viewed?

12 years ago (2. update 12 years ago)

I only would create the itemperson row, if the person actually did something with the item, e.g. really viewed it, edited it etc.

Otherwise your second approch is correct.

binder:all right then

12 years ago (2. update 12 years ago)

problem is, if you want to highlight unread items, you then have two states:
  1. no entry at all
  2. entry with "non-read" marking
that's why, I would make the entry before even opening the item, otherwise the code gets more complicated? what do you think?

guest:I believe it will not be too complicated...

12 years ago (2. update 12 years ago) -

We could add an additional wrapper function:

public function DbItem->hasBeenViewed()
  if( not itemperson) {
    return false;
  else if (itemperson -> viewed == false)
    return false;
  else {
    return true;

binder:ok. convinced!

12 years ago (2. update 12 years ago)


burger:Some questions ...

12 years ago (2. update 12 years ago)

Hello Tom,

Can you explain to me in which case you'll need the isViewedByUser function and in which case the wasViewedByUser function?

I don't understand the difference exactly and where to place it?!

And what is the difference between the isViewedByUser function and the ViewedByUser function (at view pages)? Aren't them the same?

pixtur:Labeling is not final...

12 years ago (2. update 12 years ago)

The function names are not meant to be final:
  • isViewedByUser() -> called in taskView etc. to say update item person
  • wasViewedByUser() -> reads to current state


12 years ago (3. update 12 years ago)

I started to implement the viewed-functionality.
In this context occurs a really strange behaviour.

In one part of the code I check if the "viewed_last" date is older than the "modified"-date.

from render/render_list.inc.php

if($view->viewed_last <= $obj->modified){
    echo "<tr id={$this->id}_{$obj->id} class='$style not_viewed'>";
    echo "<tr id={$this->id}_{$obj->id} class='$style'>";

And in the most cases this code-fragment works fine, but in some cases like:
  1. personView -> Block: "works in projects"
  2. companyView -> Block: "active projects", "closed projects" and "related persons"
the date of $obj->modified isn't the same date as in the item-table, it is the current date. The effect is that the $view->viewed_last date is always earlier than the $obj->modified date.

I really don't know where this behaviour comes from.

Can somebody help me and tell me why this happens?

burger:Another question

12 years ago (2. update 12 years ago)

I found out that in that blocks the default value of the "modified"-field is taken (= FINIT_NOW).

But I still do not unterstand why in the 'normal' lists the correct "modified"-date is taken but in these blocks (described previous) the default value is chosen?!

burger:I found a solution

12 years ago (3. update 12 years ago)

If the code is like this then the problem occurs:

from pages/company.inc.php

$projects= $company->getProjects($order_by);

$list= new ListBlock_projects();

$list->title=__("Active projects");
$list->groupings= NULL;
$list->block_functions = NULL;


if($auth->cur_user->user_rights & RIGHT_PROJECT_CREATE) {
    $list->no_items_html=$PH->getLink('projNew',__('Create new    project'),array('company'=>$company->id))." ".
    __(" Hint: for already existing projects please edit those and adjust company-setting.");
else {
    $list->no_items_html=__("no projects yet");
$list->render_list(&$projects); *Problem*

So I change it to:

from pages/company.inc.php

$list= new ListBlock_projects();

$list->title=__("Active projects");
$list->groupings= NULL;
$list->block_functions = NULL;

$list->query_options['status_min']= STATUS_UPCOMING;
$list->query_options['status_max']= STATUS_OPEN;
$list->query_options['company']= $company->id;
if($auth->cur_user->user_rights & RIGHT_PROJECT_CREATE) {
    $list->no_items_html=$PH->getLink('projNew',__('Create new project'),array('company'=>$company->id))." ".
    __(" Hint: for already existing projects please edit those and adjust company-setting.");
else {
    $list->no_items_html=__("no projects yet");


And now, everything is fine :-).

burger:Another solution

12 years ago

The last solution didn't work with every ListBlock.

Therefore you have to change some database code to e.g.

from class_company.inc.php

function getPersons(){
    foreach($tmp as $t) {
        if($person = Person::getVisibleById($t['id'])) {

burger:And ...

12 years ago

... I already committed the changes ;-).

pixtur:I will check them...

12 years ago

Thanks for you work!


12 years ago

Is it okay:
  1. to add a new entry ('as bookmark') in the drop-down-menu of the eg. task list to define a/some task(s) as bookmark(s)?
  2. to add a new box at the home view to show this bookmarks?
Or how should we handle this?

burger:Notify on change

12 years ago

And can I add a new entry ('notify on change') in the drop-down-list of e.g. the task list, too?

burger:Committed some changes

12 years ago

I committed some changes in relation to bookmarks.

It isn't 100% perfect (Sorry!!!), because:
  1. the 'Export as CSV' link isn't at the right position anymor
  2. if a e.g. is closed and it is shown in the bookmark list then it isn't strike through anymore
but I didn't find the reason.

Maybe somebody can check this?

P.S.: Sorry I forgot to make some comments at the svn. Normally I never forget this. So I'm really sorry!

madlyr:Bookmarks are great, nice work Burger! It is VERY usefull :-)

12 years ago

As I see it works good, although I founded some lacks ;-)
You can't bookmark milestone and comment.
You missed Milestone, but comment does not work.
Right button menu shows Mark as bookmark but doesn't submit action. Maybe it's part of bigger bug because edit menu doesn't work either.

madlyr:Submitted milestones as bookmarks and projectcolumn in My bookmarks

12 years ago

I submitted in rev. 211 some changes for bookmarks:
  • milestone could be bookmarked now
  • added column Project in My bookmarks list
  • Type column in My bookmarks shows task category name now

burger:Thanks for your help

12 years ago (2. update 12 years ago)

Sorry for my late reply, but I wasn't at work the last 1,5 weeks.
And also sorry that I forgot to implement the bookmarks for milestones and comments. But I see that you solved this problem :-).

Maybe we should add the status of the item (project, task, ...), too? What do you think?
Because at the moment there is no visual difference between closed and open task ect..


12 years ago

I think about what to do with items in the bookmark list which get deleted?!

I had the situation that I had an task marked as bookmark and then I deleted this task. But this task is still shown in the bookmark list.

So what do you think. Should this task vanish into thin air or should it be marked as deleted?

I think it's better to keep it in the bookmark list and mark is as deleted. I think it's confusing if a bookmark suddenly disappears. Or?


12 years ago (4. update 12 years ago)

My suggestion for deleted items in the bookmarklist see screenshot.

madlyr:I agree...

12 years ago

icon is ok, and task should be visible but not accessible if rights are not enough to view deleted item.


12 years ago

If you wouldn't have enough rights to see this item then you would never have the chance to mark it as bookmark. So it should be okay like this.

I changed your project-column code a little bit. Because if the item is a project then it's enough to have the name of the project once (name column) and not twice (project column). Is this okay for you?

madlyr:Reply to Comment - bookmarks are broken in rev 216

12 years ago

Rights: check if it's not a security hole, probably not :-).

After your changes in rev 216 (I work on rev 217 with merged my changes) bookmarks don't work propoerly.

I see only one last added bookmark and I see only columns Type and Status with data, other are empty.

burger:Uups ...

12 years ago

Sorry. I like take care about it immediately.


12 years ago

The only thing I changed is that I added the State-column and items which states are >= STATUS_COMPLTED are striked-trough.

So can you maybe check if one of those causes the error? That would be very kind.
It's not very easy for me to find out the error because everything works fine on my computer.

burger:Found the error

12 years ago

Sorry for your inconvenience. I forgot to submit the db_items.inc.php. Therefore a new function (function getItemState()) wasn't found and this causes the error.

So sorry again.

madlyr:Reply to Found the error

12 years ago (2. update 12 years ago)

NOP, sometimes it happens :-).
It works now perfectly.

I always use check for modifications menu of Tortoise and check modifications with svn repository to make sure I don't forget about any change.

madlyr:What should display column State?

12 years ago

I see new and empty column named State in bookmark list. What's this?

I suggest to change widths of columns - Name should be much wider.


12 years ago (2. update 12 years ago)

State displays the state of the bookmark (deleted or 'alive') --> see screenshot.
I only didn't know a good german translation for 'state'.

I tried to change the column width but nothing happened. So I decided to continue with the implementation and to care about the layout later.

pixtur:wow, lots of stuff going on here...

12 years ago (7. update 12 years ago)

Sorry for being absent for such a long time. I had (or still have) some personal problems and a lot of work. Anyways.

I saw your changes at bookmarks and viewed items. Very nice!

Some comments on your changes:
  • Please refactor ListBlock.render_trow() and make a custom version for bookmark list
  • I think there is too much orange in the pages. I suggest to only highlight new/updated items like it was done with the items changed since last logout. I don't think we need two highlight mechanisms, so the old check can be removed.
  • I think the labeling is a little bit awkward right now. Maybe we could replace "not viewed" with something like "changed/new/updated".
  • I added a new field to date_highlight_changes to Person. Together with the page function personAllItemsViewed this can be used to mark all items as viewed without flooding the item_person table. This should be initialized with "now" for new persons.
  • Why do you add the double id to the book-mark list? I just don't understand what this should be good for.
  • Why didn't you start a new file for the list_bookmarks?
  • I renamed isViewedByUser($auth->cur_user) into nowViewedByUser()
    • note that $auth->cur_user is the default value for the function, so I removed it from all calls.
  • Please do not use getCurTheme():
print "<td><img src='themes/".getCurTheme() ."/icons/delete.gif'></td>";

is better written as...

  echo '<td><img src="'. getThemeFile("icons/delete.gif") . '"></td>';

By this themes can be derived from Clean-Theme without having to copy all files. getCurTheme() is depreciated. Please do not use it anymore.

Since I wanted to update my own site I refactored some of your code a little bit. I hope this is ok for you. Have a close look at my changes in rev224.

Monitoring itemsπ

Since you already implemented so much, why not complete the group of feature by also finishing ? I wrote some description there, what is still missing.

burger:Questions & Answers & Comments

12 years ago (2. update 12 years ago)

  1. What was the old highlight mechanism? Bold?
  2. Which labeling do you mean? At the 'My bookmarks' list or in the code?
  3. What do you mean with double id at the bookmark list?
  1. I didn't have a special reason not to start a new file for the list_bookmarks. So if you want then we can change it.
I already started to implement the notification mechanism if something changed (like you suggested at ).
My ideas:
  1. Function drop-down-list: 'Add notification' and 'Remove notification'
  2. Mail-Icon behind the selected items (no new list at the home view, because of clarity)
  3. New mail every time the particular item changes


12 years ago (2. update 12 years ago)

Old highlight mechanismπ

  • In renderDateHtml() I compared all dates with $auth->cur_user->last_logout. If the item was modified after the last_logout, the date was rendered with the class isNew (bold orange). Since most list featured a modified date column, this was sufficient.
With your new changed I suggest to check each list row for "isChanged" and add the class like...

from render/render_list.inc.php

            if( $obj->isChangedForUser() ) {
				echo "<tr class='$style isChanged'>";
            else {
				echo "<tr class='$style'>";

Then we can easily add all possible highlights to the styles.css without modifing the code. E.g. to render changed items in bookmark list different, we could add...

from styles.css

    table#bookmarks tr.isChanged a {


Both. In the code and in the interface. I think we could write into the upcomming documentation, that "you can bookmark by monitoring items".

Double idπ

From your modified render_list code:

from render/render_list.inc.php

echo "<tr id={$this->id}_{$obj->id} class='$style not_viewed'>";

I removed the <tr> "id" because it wasn't necessary (or I didn't get its purpose).


Please start a new file. That will keep the code a little bit more readable.

I didn't understand this...

# Function drop-down-list: 'Add notification' and 'Remove notification'

I don't like the idea of using "toolicons" to display a state (e.g. deleted). This is very confusing, because, it suggests you can click on the Icon to delete it.

I did a quick Photoshop mock-up how I would love to have the bookmark list (see attachment).


burger:Short comment

12 years ago

Sorry I don't have very much time. So only a short comment:
  • I like your Photoshop mock-up and if it's okay I will realize it like this.
  • I already added the comment column.
  • I already implemented the edit form for bookmarks.
But the code is not perfected yet to get committed.
I hope it's okay if you get the code next week, because I will finish work now and I cannot continue before next thursday?!

pixtur:that's just fine for me...

12 years ago

burger:Committed some changes

12 years ago

Hi Tom,

I made some changes:
  1. new bookmark list (new, changed or removed columns)
  2. notification if item changed
  3. notification if item not changed
  4. edit form for bookmarks
I hope I haven't made an error in reasoning in the range of notification.

Notification on change:
  • Every time an monitored item changes an email is sent to the persons who are monitoring this item.
  • But no email is sent to the person who changes the item.
Notification on unchange:
  • Every time the user logs in there's a check if a notification mail on unchanged items should be send.
  • Every time the monitored item is changed the "base" date (notify_date) is modified.
Still to implement:
  • recognition of changes at Multiple ... / tasksComplete / tasksDelete ...
It would be great if you could check this.
I really hope that I didn't make any mistakes, because I'm on holiday till 07/01/04 or 07/01/05.
If there are bigger problems please try to contact me on Skype.

So, I wish you a merry christmas and a happy new year.
Try to relax a little bit ;).

pixtur:thanks for your work!

12 years ago (2. update 12 years ago)

I just had a short glimpse at your changes, but since it so much, I probably will come with some more suggestions later.

So far anything but the following detail looks perfect:
  • I don't thing that sending the notification on unchanged items after login in is a good idea. because:
    1. We could highlight those items in the bookmark list of the user
    2. Sending the notification stuff takes time, and just after login is the worst point to let the user wait
    3. There already is a good place for this kind of information: The notification mail itself. I just would it implement like suggested in :
  monitored by you [ignore all monitored]:
  - admin edited > adfjlkasdjf (to xyz)  [ignore]
  sleeping monitored items [ignore all sleeping]
  - task23423 (not touched since 34 days) [ignore]

The ignore-list would request a page like:
  • index.php?go=stopNotifyUnchanged&item=234
  • index.php?go=stopNotifyAllUnchanged
  • index.php?go=stopNotifyChange&item=234
  • index.php?go=stopNotifyAllChange
One Question:
  • what is public function outputNotifcationForPersonTXT($person) for?
Just tested the bookmarks a little bit:
Thanks again for this incredible work! I guess my wishes for happy x-mas, new year and vacation come a little bit too late...
I will try to relax with my parents, but since I will release a new demo at http://2006.tum-party.net/ I am a little bit under preasure... :)


12 years ago (3. update 12 years ago)

  1. I really don't know who implemented the public function outputNotifcationForPersonTXT($person) . I didn't.
  1. Can you please specify how this ignore list should look like and how it can be accessed?
  1. You suggest to highlight the unchanged items, but I have a own column for this. So what's better?
  1. I will include the notification on unchanged items in the already existing notification mail.

pixtur:(some) answeres

12 years ago

  • on 1.: ok, then remove the outputNotifcationForPersonTXT function.
  • on 2.: I don't think that there is something like an ignore list. It would simply..
    • remove the Bookmark or
    • disable reminder for a Bookmark
  • on 3. Sorry. I was wrong. The column list_bookmarks is just fine

Thanks for you work.

ps. Could you please move list_bookmarks into a separate file?


12 years ago

I made some changes and committed them.
But I didn't add your second point.
I will do this tomorrow.

pixtur:ok... I will check your changes.

12 years ago

pixtur:Very nice...

12 years ago

The code looks very good. I really like that you already use the DbProjectItem::getObjectById() .

Personal taste... I would write...

from mail.inc.php line 224

				# do nothing
				$changes_headline_html = "<h3>"


				$changes_headline_html = "<h3>"


we could already define

NOTIFY_1DAY etc. as... `define(PERIOD_1DAY, 246060)`. This would also make storing the notify-field as being stored in seconds more obvious...

Do not forget to remove class ListBlock_bookmarks extends ListBlock from list items. But probably this just not yet committed :)

Thank you! Seeing your help with streber really saves my day :)

burger:Problem with edit multiple

12 years ago

I would like to realise the edit multiple form for bookmarks but I really don't know how.
  1. Multiple forms? (--> but how can the submit work?)
  2. One form for all bookmarks? (--> like editTasksMultiple)
What do you think?

burger:Talked with Thomas (binder) ..

12 years ago

Thomas and me, we decided to solve it like at taskEditMultiple (to keep the functionality similar and not to confuse the user).

Therefore I will use the same functionality like the taskEditMultiple (with -- keep different -- etc.).
But I don't have the comment field, because I think it isn't possible with multiple items. or?

Is this solution okay for you?

burger:Committed some changes

12 years ago

I realised the itemMonitorEditMultiple like I described in the last comment.
Please check if everything is okay.

pixtur:Yes... This solution is quiet ok

12 years ago

I will check your code.

pixtur:considered to be done :)

12 years ago

guest:who delete a person??

11 years ago -

I can't delete a person, why?....