Commits

Jason Green committed 86a5910

More work on conversations and comments modules.

Comments (0)

Files changed (24)

app/protected/extensions/zurmoinc/framework/views/DetailsView.php

             return $content;
         }
 
-        /**
-         * Render a menu above the form layout. This includes buttons and/or
-         * links to go to different views or process actions such as save or delete
-         * @return A string containing the element's content.
-          */
-        protected function renderActionElementMenu()
-        {
-            $metadata  = $this::getMetadata();
-            $menuItems = array('label' => Yii::t('Default', 'Options'), 'items' => array());
-            if (isset($metadata['global']['toolbar']) && is_array($metadata['global']['toolbar']['elements']))
-            {
-                foreach ($metadata['global']['toolbar']['elements'] as $elementInformation)
-                {
-                    $elementclassname = $elementInformation['type'] . 'ActionElement';
-                    $params = array_slice($elementInformation, 1);
-                    array_walk($params, array($this, 'resolveEvaluateSubString'));
-                    $element  = new $elementclassname($this->controllerId, $this->moduleId, $this->modelId, $params);
-                    if (!$this->shouldRenderToolBarElement($element, $elementInformation))
-                    {
-                        continue;
-                    }
-                    if ($element->isFormRequiredToUse())
-                    {
-                        throw new NotSupportedException();
-                    }
-                    $menuItems['items'][] = $element->renderMenuItem();
-                }
-            }
-            if (count($menuItems['items']) > 0)
-            {
-                $cClipWidget = new CClipWidget();
-                $cClipWidget->beginClip("DetailsOptionMenu");
-                $cClipWidget->widget('ext.zurmoinc.framework.widgets.MbMenu', array(
-                    'htmlOptions' => array('id' => 'OptionsMenu'),
-                    'items'                   => array($menuItems),
-                    'navContainerClass'       => 'nav-single-container',
-                    'navBarClass'             => 'nav-single-bar',
-                ));
-                $cClipWidget->endClip();
-                return $cClipWidget->getController()->clips['DetailsOptionMenu'];
-            }
-        }
-
         protected function renderTitleContent()
         {
             if ($this->title != null)

app/protected/extensions/zurmoinc/framework/views/MetadataView.php

             assert('is_array($elementInformation)');
             return true;
         }
+
+        /**
+         * Render a menu above the form layout. This includes buttons and/or
+         * links to go to different views or process actions such as save or delete
+         * @return A string containing the element's content.
+          */
+        protected function renderActionElementMenu($title = null)
+        {
+            if($title == null)
+            {
+                $title = Yii::t('Default', 'Options');
+            }
+            $metadata  = $this::getMetadata();
+            $menuItems = array('label' => $title, 'items' => array());
+            if (isset($metadata['global']['toolbar']) && is_array($metadata['global']['toolbar']['elements']))
+            {
+                foreach ($metadata['global']['toolbar']['elements'] as $elementInformation)
+                {
+                    $elementclassname = $elementInformation['type'] . 'ActionElement';
+                    $params = array_slice($elementInformation, 1);
+                    array_walk($params, array($this, 'resolveEvaluateSubString'));
+                    $element  = new $elementclassname($this->controllerId, $this->moduleId, $this->modelId, $params);
+                    if (!$this->shouldRenderToolBarElement($element, $elementInformation))
+                    {
+                        continue;
+                    }
+                    if ($element->isFormRequiredToUse())
+                    {
+                        throw new NotSupportedException();
+                    }
+                    $menuItems['items'][] = $element->renderMenuItem();
+                }
+            }
+            if (count($menuItems['items']) > 0)
+            {
+                $cClipWidget = new CClipWidget();
+                $cClipWidget->beginClip("OptionMenu");
+                $cClipWidget->widget('ext.zurmoinc.framework.widgets.MbMenu', array(
+                    'htmlOptions' => array('id' => 'OptionsMenu'),
+                    'items'                   => array($menuItems),
+                    'navContainerClass'       => 'nav-single-container',
+                    'navBarClass'             => 'nav-single-bar',
+                ));
+                $cClipWidget->endClip();
+                return $cClipWidget->getController()->clips['OptionMenu'];
+            }
+        }
     }
 ?>

app/protected/modules/activities/utils/ActivitiesUtil.php

 
         protected static function renderOwnerStringContent($model)
         {
-            if ($model instanceof MashableActivity)
+            if ($model instanceof OwnedSecurableItem)
             {
                 return strval($model->owner);
             }

app/protected/modules/activities/views/LatestActivtiesForPortletView.php

 
         protected $viewData;
 
+        abstract protected function getLatestActivitiesViewClassName();
+
         /**
          * Some extra assertions are made to ensure this view is used in a way that it supports.
          */
 
         public function renderContent()
         {
-            return $this->renderLatestActivitiesContent();
+            $content  = $this->renderActionContent();
+            $content .= $this->renderLatestActivitiesContent();
+            return $content;
         }
 
         protected function renderLatestActivitiesContent()
             return 'ActivitiesModule';
         }
 
-        abstract protected function getLatestActivitiesViewClassName();
+        protected function renderActionContent()
+        {
+            $actionElementContent = $this->renderActionElementMenu(Yii::t('Default', 'Create'));
+            $content              = null;
+            if ($actionElementContent != null)
+            {
+                $content .= '<div class="view-toolbar-container toolbar-mbmenu clearfix"><div class="view-toolbar">';
+                $content .= $actionElementContent;
+                $content .= '</div></div>';
+            }
+            return $content;
+        }
+
+        /**
+         * Expects there to be a modelClassName parameter passed through the elementInformation that can be used
+         * to compare the Rights security on based on the actionType of the element.
+         * (non-PHPdoc)
+         * @see MetadataView::shouldRenderToolBarElement()
+         */
+        protected function shouldRenderToolBarElement($element, $elementInformation)
+        {
+            assert('$element instanceof ActionElement');
+            assert('is_array($elementInformation)');
+            if (!parent::shouldRenderToolBarElement($element, $elementInformation))
+            {
+                return false;
+            }
+            if(isset($elementInformation['modelClassName']))
+            {
+                $modelClassName = $elementInformation['modelClassName'];
+                //Todo: figure out how to not need to new up a new model.
+                return ActionSecurityUtil::canCurrentUserPerformAction( $element->getActionType(),
+                                                                        new $modelClassName(false));
+            }
+            return true;
+        }
     }
 ?>

app/protected/modules/activities/views/related/AccountLatestActivtiesForPortletView.php

      */
     class AccountLatestActivtiesForPortletView extends LatestActivtiesForPortletView
     {
+        public static function getDefaultMetadata()
+        {
+            $metadata = parent::getDefaultMetadata();
+            return array_merge($metadata, array(
+                'global' => array(
+                    'toolbar' => array(
+                        'elements' => array(
+                            array('type'                    => 'CreateConversationFromRelatedListLink',
+                                  'modelClassName'			=> 'Conversation',
+                                  'routeParameters'         =>
+                                    array('relationAttributeName'    => 'notUsed',
+                                            'relationModelClassName' => 'Account',
+                                            'relationModelId'        => 'eval:$this->params["relationModel"]->id',
+                                            'relationModuleId'       => 'accounts',
+                                            'redirectUrl'            => 'eval:Yii::app()->request->getRequestUri()')
+                        ),
+                    ),
+                ),
+            )));
+        }
+
         public function getLatestActivitiesViewClassName()
         {
             return 'LatestActivitiesForAccountListView';

app/protected/modules/activities/views/related/OpportunityLatestActivtiesForPortletView.php

      */
     class OpportunityLatestActivtiesForPortletView extends LatestActivtiesForPortletView
     {
+        public static function getDefaultMetadata()
+        {
+            $metadata = parent::getDefaultMetadata();
+            return array_merge($metadata, array(
+                'global' => array(
+                    'toolbar' => array(
+                        'elements' => array(
+                            array('type'                   => 'CreateConversationFromRelatedListLink',
+                                  'routeParameters'         =>
+                                    array('relationAttributeName'    => 'notUsed',
+                                            'relationModelClassName' => 'Opportunity',
+                                            'relationModelId'        => 'eval:$this->params["relationModel"]->id',
+                                            'relationModuleId'       => 'opportunities',
+                                            'redirectUrl'            => 'eval:Yii::app()->request->getRequestUri()')
+                        ),
+                    ),
+                ),
+            )));
+        }
+
         public function getLatestActivitiesViewClassName()
         {
             return 'LatestActivitiesForOpportunityListView';

app/protected/modules/comments/views/CommentsForRelatedModelView.php

 
         protected function renderContent()
         {
-            $content = null;
+            $content = '<div>';
+            $content .= '<div>' . $this->renderHiddenRefreshLinkContent() . '</div>';
             if(count($this->commentsData) > 0)
             {
-                $content .= '<div>';
-                $content .= '<div>' . $this->renderHiddenRefreshLinkContent() . '</div>';
                 if(count($this->commentsData) > $this->pageSize && $this->pageSize != null)
                 {
                     $content .= '<div>' . $this->renderShowAllLinkContent() . '</div>';
                 }
                 $content .= '<div>' . $this->renderCommentsContent() . '</div>';
-                $content .= '</div>';
             }
+            $content .= '</div>';
             return $content;
         }
 

app/protected/modules/conversations/adapters/columns/ConversationLatestDateTimeListViewColumnAdapter.php

+<?php
+    /*********************************************************************************
+     * Zurmo is a customer relationship management program developed by
+     * Zurmo, Inc. Copyright (C) 2012 Zurmo Inc.
+     *
+     * Zurmo is free software; you can redistribute it and/or modify it under
+     * the terms of the GNU General Public License version 3 as published by the
+     * Free Software Foundation with the addition of the following permission added
+     * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
+     * IN WHICH THE COPYRIGHT IS OWNED BY ZURMO, ZURMO DISCLAIMS THE WARRANTY
+     * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
+     *
+     * Zurmo is distributed in the hope that it will be useful, but WITHOUT
+     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+     * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+     * details.
+     *
+     * You should have received a copy of the GNU General Public License along with
+     * this program; if not, see http://www.gnu.org/licenses or write to the Free
+     * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+     * 02110-1301 USA.
+     *
+     * You can contact Zurmo, Inc. with a mailing address at 113 McHenry Road Suite 207,
+     * Buffalo Grove, IL 60089, USA. or at email address contact@zurmo.com.
+     ********************************************************************************/
+
+    class ConversationLatestDateTimeListViewColumnAdapter extends TextListViewColumnAdapter
+    {
+        public function renderGridViewData()
+        {
+            return array(
+                'name'   => $this->attribute,
+                'header' => false,
+                'value'  => 'DateTimeUtil::convertDbFormattedDateTimeToLocaleFormattedDisplay($data->' . $this->attribute . ')',
+                'type'   => 'raw',
+            );
+        }
+    }
+?>

app/protected/modules/conversations/adapters/columns/ConversationLatestListViewColumnAdapter.php

+<?php
+    /*********************************************************************************
+     * Zurmo is a customer relationship management program developed by
+     * Zurmo, Inc. Copyright (C) 2012 Zurmo Inc.
+     *
+     * Zurmo is free software; you can redistribute it and/or modify it under
+     * the terms of the GNU General Public License version 3 as published by the
+     * Free Software Foundation with the addition of the following permission added
+     * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
+     * IN WHICH THE COPYRIGHT IS OWNED BY ZURMO, ZURMO DISCLAIMS THE WARRANTY
+     * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
+     *
+     * Zurmo is distributed in the hope that it will be useful, but WITHOUT
+     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+     * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+     * details.
+     *
+     * You should have received a copy of the GNU General Public License along with
+     * this program; if not, see http://www.gnu.org/licenses or write to the Free
+     * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+     * 02110-1301 USA.
+     *
+     * You can contact Zurmo, Inc. with a mailing address at 113 McHenry Road Suite 207,
+     * Buffalo Grove, IL 60089, USA. or at email address contact@zurmo.com.
+     ********************************************************************************/
+
+    class ConversationLatestListViewColumnAdapter extends AddressListViewColumnAdapter
+    {
+        public function renderGridViewData()
+        {
+            return array(
+                'name'        => 'subject',
+                'header'	  => false,
+                'type'        => 'raw',
+                'value'       => 'ConversationsUtil::renderSubjectAndLatestForDisplayView($data)',
+                'htmlOptions' => array('style' => 'width:40%;'),
+            );
+        }
+    }
+?>

app/protected/modules/conversations/adapters/dataproviders/ConversationsSearchDataProviderMetadataAdapter.php

+<?php
+    /*********************************************************************************
+     * Zurmo is a customer relationship management program developed by
+     * Zurmo, Inc. Copyright (C) 2012 Zurmo Inc.
+     *
+     * Zurmo is free software; you can redistribute it and/or modify it under
+     * the terms of the GNU General Public License version 3 as published by the
+     * Free Software Foundation with the addition of the following permission added
+     * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
+     * IN WHICH THE COPYRIGHT IS OWNED BY ZURMO, ZURMO DISCLAIMS THE WARRANTY
+     * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
+     *
+     * Zurmo is distributed in the hope that it will be useful, but WITHOUT
+     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+     * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+     * details.
+     *
+     * You should have received a copy of the GNU General Public License along with
+     * this program; if not, see http://www.gnu.org/licenses or write to the Free
+     * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+     * 02110-1301 USA.
+     *
+     * You can contact Zurmo, Inc. with a mailing address at 113 McHenry Road Suite 207,
+     * Buffalo Grove, IL 60089, USA. or at email address contact@zurmo.com.
+     ********************************************************************************/
+
+    /**
+     * Adapter class to handle special metadata needs of conversation listviews.  This is because there is a
+     * relation where clause with ConversationParticipants person, which is difficult to do via the searchAttributes array
+     */
+    class ConversationsSearchDataProviderMetadataAdapter extends SearchDataProviderMetadataAdapter
+    {
+        /**
+         * Filter by conversations the current user created.
+         * @var integer
+         */
+        const LIST_TYPE_CREATED = 1;
+
+        /**
+         * Filter by conversations the current user is participating in
+         * @var integer
+         */
+        const LIST_TYPE_PARTICIPANT = 2;
+
+        protected $type;
+        /**
+         * Override to add passing in type
+         */
+        public function __construct($model, $userId, $metadata, $type)
+        {
+            assert('$type == self::LIST_TYPE_CREATED || $type == self::LIST_TYPE_PARTICIPANT');
+            parent::__construct($model, $userId, $metadata);
+            $this->type = $type;
+        }
+
+        /**
+         * Convert metadata which is just an array
+         * of posted searchAttributes into metadata that is
+         * readable by the RedBeanModelDataProvider
+         */
+        public function getAdaptedMetadata($appendStructureAsAnd = true)
+        {
+            $adaptedMetadata = parent::getAdaptedMetadata($appendStructureAsAnd);
+            $clauseCount = count($adaptedMetadata['clauses']);
+            $startingCount = $clauseCount + 1;
+            $structure = '';
+
+            if($this->type == self::LIST_TYPE_CREATED)
+            {
+                $adaptedMetadata['clauses'][$startingCount] = array(
+                    'attributeName' => 'owner',
+                    'operatorType'  => 'equals',
+                    'value'         => Yii::app()->user->userModel->id
+                );
+                $structure .= $startingCount;
+            }
+            else
+            {
+                $adaptedMetadata['clauses'][$startingCount] = array(
+                    'attributeName'        => 'conversationParticipants',
+                    'relatedAttributeName' => 'person',
+                    'operatorType'  => 'equals',
+                    'value'         => Yii::app()->user->userModel->getClassId('Item')
+                );
+                $structure .= $startingCount;
+            }
+            if (empty($metadata['structure']))
+            {
+                $adaptedMetadata['structure'] = '(' . $structure . ')';
+            }
+            else
+            {
+                $adaptedMetadata['structure'] = '(' . $adaptedMetadata['structure'] . ') and (' . $structure . ')';
+            }
+            return $adaptedMetadata;
+        }
+    }
+?>

app/protected/modules/conversations/controllers/DefaultController.php

             $type             = ArrayUtil::getArrayValue($getData, 'type');
             if ($type == null)
             {
-                $type = ConversationUtil::LIST_TYPE_CREATED;
+                $type = ConversationsSearchDataProviderMetadataAdapter::LIST_TYPE_CREATED;
             }
-            if ($type == ConversationUtil::LIST_TYPE_CREATED)
+            if ($type == ConversationsSearchDataProviderMetadataAdapter::LIST_TYPE_CREATED)
             {
                 $activeActionElementType = 'ConversationsCreatedLink';
             }
-            elseif ($type == ConversationUtil::LIST_TYPE_PARTICIPANT)
+            elseif ($type == ConversationsSearchDataProviderMetadataAdapter::LIST_TYPE_PARTICIPANT)
             {
                 $activeActionElementType = 'ConversationsParticipantLink';
             }
             {
                 throw new NotSupportedException();
             }
-
             $searchAttributes = array();
-            $searchAttributes = ConversationUtil::resolveSearchAttributesByType($type);
-            $metadataAdapter  = new SearchDataProviderMetadataAdapter(
+            $metadataAdapter  = new ConversationsSearchDataProviderMetadataAdapter(
                 $conversation,
                 Yii::app()->user->userModel->id,
-                $searchAttributes
+                $searchAttributes,
+                $type
             );
             $dataProvider = RedBeanModelDataProviderUtil::makeDataProvider(
                 $metadataAdapter,
             }
         }
 
+        /**
+         * (non-PHPdoc)
+         * @see ZurmoModuleController::actionCreateFromRelation()
+         */
         public function actionCreateFromRelation($relationAttributeName, $relationModelId, $relationModuleId, $redirectUrl)
         {
+            $getData              = GetUtil::getData();
+            if(null == ArrayUtil::getArrayValue($getData, 'relationModelClassName'))
+            {
+                throw new NotSupportedException();
+            }
             $conversation         = $this->resolveNewModelByRelationInformation( new Conversation(),
-                                                                                $relationAttributeName,
+                                                                                ArrayUtil::getArrayValue($getData, 'relationModelClassName'),
                                                                                 (int)$relationModelId,
                                                                                 $relationModuleId);
             $this->actionCreateByModel($conversation, $redirectUrl);
 
         protected function actionCreateByModel(Conversation $conversation, $redirectUrl)
         {
-            $titleBarAndEditView = $this->makeEditAndDetailsView(
-                                            $this->attemptToSaveModelFromPost($conversation, $redirectUrl), 'Edit');
-            $pageViewClassName = $this->getPageViewClassName();
-            $view = new $pageViewClassName(ZurmoDefaultViewUtil::
-                                             makeStandardViewForCurrentUser($this, $titleBarAndEditView));
+            $editView = new ConversationEditView($this->getId(), $this->getModule()->getId(),
+                                                 $this->attemptToSaveModelFromPost($conversation, $redirectUrl),
+                                                 Yii::t('Default', 'Create Conversation'));
+            $view     = new ConversationsPageView(ZurmoDefaultViewUtil::
+                                             makeStandardViewForCurrentUser($this, $editView));
             echo $view->render();
         }
 
                                                                     $relationModelId, $relationModuleId)
         {
             assert('$model instanceof Conversation');
-            assert('is_string($relationModelClassName)');
+            assert('is_string($relationModelClassName) || null');
             assert('is_int($relationModelId)');
             assert('is_string($relationModuleId)');
 

app/protected/modules/conversations/elements/actions/ConversationsCreatedLinkActionElement.php

         {
             return Yii::app()->createUrl(
                 $this->moduleId . '/' . $this->controllerId . '/list/',
-                array('type' => ConversationUtil::LIST_TYPE_CREATED));
+                array('type' => ConversationsSearchDataProviderMetadataAdapter::LIST_TYPE_CREATED));
         }
     }
 ?>

app/protected/modules/conversations/elements/actions/ConversationsParticipantLinkActionElement.php

         {
             return Yii::app()->createUrl(
                 $this->moduleId . '/' . $this->controllerId . '/list/',
-                array('type' => ConversationUtil::LIST_TYPE_PARTICIPANT));
+                array('type' => ConversationsSearchDataProviderMetadataAdapter::LIST_TYPE_PARTICIPANT));
         }
     }
 ?>

app/protected/modules/conversations/elements/actions/CreateConversationFromRelatedListLinkActionElement.php

+<?php
+    /*********************************************************************************
+     * Zurmo is a customer relationship management program developed by
+     * Zurmo, Inc. Copyright (C) 2012 Zurmo Inc.
+     *
+     * Zurmo is free software; you can redistribute it and/or modify it under
+     * the terms of the GNU General Public License version 3 as published by the
+     * Free Software Foundation with the addition of the following permission added
+     * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
+     * IN WHICH THE COPYRIGHT IS OWNED BY ZURMO, ZURMO DISCLAIMS THE WARRANTY
+     * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
+     *
+     * Zurmo is distributed in the hope that it will be useful, but WITHOUT
+     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+     * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+     * details.
+     *
+     * You should have received a copy of the GNU General Public License along with
+     * this program; if not, see http://www.gnu.org/licenses or write to the Free
+     * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+     * 02110-1301 USA.
+     *
+     * You can contact Zurmo, Inc. with a mailing address at 113 McHenry Road Suite 207,
+     * Buffalo Grove, IL 60089, USA. or at email address contact@zurmo.com.
+     ********************************************************************************/
+
+    class CreateConversationFromRelatedListLinkActionElement extends RelatedListLinkActionElement
+    {
+        protected function getDefaultLabel()
+        {
+            return Yii::t('Default', 'Conversation');
+        }
+
+        protected function getDefaultRoute()
+        {
+            return Yii::app()->createUrl('conversations/default/createFromRelation/', $this->getRouteParameters());
+        }
+
+        public function getActionType()
+        {
+            return 'Create';
+        }
+    }
+?>

app/protected/modules/conversations/elements/derived/ConversationLatestElement.php

+<?php
+    /*********************************************************************************
+     * Zurmo is a customer relationship management program developed by
+     * Zurmo, Inc. Copyright (C) 2012 Zurmo Inc.
+     *
+     * Zurmo is free software; you can redistribute it and/or modify it under
+     * the terms of the GNU General Public License version 3 as published by the
+     * Free Software Foundation with the addition of the following permission added
+     * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
+     * IN WHICH THE COPYRIGHT IS OWNED BY ZURMO, ZURMO DISCLAIMS THE WARRANTY
+     * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
+     *
+     * Zurmo is distributed in the hope that it will be useful, but WITHOUT
+     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+     * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+     * details.
+     *
+     * You should have received a copy of the GNU General Public License along with
+     * this program; if not, see http://www.gnu.org/licenses or write to the Free
+     * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+     * 02110-1301 USA.
+     *
+     * You can contact Zurmo, Inc. with a mailing address at 113 McHenry Road Suite 207,
+     * Buffalo Grove, IL 60089, USA. or at email address contact@zurmo.com.
+     ********************************************************************************/
+
+    /**
+     * Display the conversation latest information either the latest comment or the description of the conversation.
+     * Current support is for  the list view only.
+     */
+    class ConversationLatestElement extends Element implements DerivedElementInterface
+    {
+        protected function renderEditable()
+        {
+            throw NotSupportedException();
+        }
+
+        protected function renderControlEditable()
+        {
+            throw NotSupportedException();
+        }
+
+        /**
+         * Render the full name as a non-editable display
+         * @return The element's content.
+         */
+        protected function renderControlNonEditable()
+        {
+            throw NotSupportedException();
+        }
+
+        protected function renderLabel()
+        {
+            return Yii::t('Default', 'Conversation');
+        }
+
+        public static function getDisplayName()
+        {
+            return Yii::t('Default', 'Conversation Latest');
+        }
+
+        /**
+         * Get the attributeNames of attributes used in
+         * the derived element.
+         * @return array of model attributeNames used.
+         */
+        public static function getModelAttributeNames()
+        {
+            return array(
+                'subject',
+                'description',
+            );
+        }
+    }
+?>

app/protected/modules/conversations/elements/derived/OnChangeProcessMultiplePeopleForConversationElement.php

 
         protected function getParticipatingInListUrl()
         {
-            return Yii::app()->createUrl('conversations/default/list', array('type' => ConversationUtil::LIST_TYPE_PARTICIPANT));
+            return Yii::app()->createUrl('conversations/default/list', array('type' => ConversationsSearchDataProviderMetadataAdapter::LIST_TYPE_PARTICIPANT));
         }
     }
 ?>

app/protected/modules/conversations/tests/unit/walkthrough/ConversationsUserWalkthroughTest.php

             //Confirm Mary is invited.
             $this->assertEquals(1,     $conversations[0]->conversationParticipants->count());
             $this->assertEquals($mary, $conversations[0]->conversationParticipants->offsetGet(0)->person);
-            $this->assertNull($conversations[0]->conversationParticipants->offsetGet(0)->hasReadLatest);
+            $this->assertEquals(0,     $conversations[0]->conversationParticipants->offsetGet(0)->hasReadLatest);
 
             //Confirm Mary is the only one with explicit permissions on the conversation
             $explicitReadWriteModelPermissions = ExplicitReadWriteModelPermissionsUtil::
             $content = $this->runControllerWithNoExceptionsAndGetContent('conversations/default/list');
             $this->assertfalse(strpos($content, 'Conversations') === false);
             $this->setGetArray(array(
-                'type' => ConversationUtil::LIST_TYPE_CREATED));
+                'type' => ConversationsSearchDataProviderMetadataAdapter::LIST_TYPE_CREATED));
             $content = $this->runControllerWithNoExceptionsAndGetContent('conversations/default/list');
             $this->assertfalse(strpos($content, 'Conversations') === false);
             $this->setGetArray(array(
-                'type' => ConversationUtil::LIST_TYPE_PARTICIPANT));
+                'type' => ConversationsSearchDataProviderMetadataAdapter::LIST_TYPE_PARTICIPANT));
             $content = $this->runControllerWithNoExceptionsAndGetContent('conversations/default/list');
             $this->assertfalse(strpos($content, 'Conversations') === false);
         }
             $conversations  = Conversation::getAll();
             $this->assertEquals(0, count($conversations));
 
+            //First just go to the createFromRelation action. Make sure it comes up right
+            $this->setGetArray(array(   'relationAttributeName'  => 'notUsed',
+                                        'relationModelClassName' => 'Account',
+                                        'relationModelId'        => $superAccountId,
+                                        'relationModuleId'       => 'accounts',
+                                        'redirectUrl'            => 'someRedirection'));
+            $this->resetPostArray();
+            $this->runControllerWithNoExceptionsAndGetContent('conversations/default/createFromRelation');
+
             //add related note for account using createFromRelation action
             $conversationItemPostData = array('account' => array('id' => $accounts[0]->id));
-            $this->setGetArray(array(   'relationAttributeName'  => 'Account',
+            $this->setGetArray(array(   'relationAttributeName'  => 'notUsed',
+                                        'relationModelClassName' => 'Account',
                                         'relationModelId'        => $superAccountId,
                                         'relationModuleId'       => 'accounts',
                                         'redirectUrl'            => 'someRedirection'));

app/protected/modules/conversations/utils/ConversationParticipantsUtil.php

         protected static function makeConversationParticipantByPerson($personOrUserModel)
         {
             assert('$personOrUserModel instanceof User || $personOrUserModel instanceof Person');
-            $conversationParticipant         = new ConversationParticipant();
-            $conversationParticipant->person = $personOrUserModel;
+            $conversationParticipant                = new ConversationParticipant();
+            $conversationParticipant->hasReadLatest = false;
+            $conversationParticipant->person        = $personOrUserModel;
             return $conversationParticipant;
         }
 

app/protected/modules/conversations/utils/ConversationUtil.php

-<?php
-    /*********************************************************************************
-     * Zurmo is a customer relationship management program developed by
-     * Zurmo, Inc. Copyright (C) 2012 Zurmo Inc.
-     *
-     * Zurmo is free software; you can redistribute it and/or modify it under
-     * the terms of the GNU General Public License version 3 as published by the
-     * Free Software Foundation with the addition of the following permission added
-     * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
-     * IN WHICH THE COPYRIGHT IS OWNED BY ZURMO, ZURMO DISCLAIMS THE WARRANTY
-     * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
-     *
-     * Zurmo is distributed in the hope that it will be useful, but WITHOUT
-     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-     * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
-     * details.
-     *
-     * You should have received a copy of the GNU General Public License along with
-     * this program; if not, see http://www.gnu.org/licenses or write to the Free
-     * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-     * 02110-1301 USA.
-     *
-     * You can contact Zurmo, Inc. with a mailing address at 113 McHenry Road Suite 207,
-     * Buffalo Grove, IL 60089, USA. or at email address contact@zurmo.com.
-     ********************************************************************************/
-
-    /**
-     * Helper class for working with conversations
-     */
-    class ConversationUtil
-    {
-        /**
-         * Filter by conversations the current user created.
-         * @var integer
-         */
-        const LIST_TYPE_CREATED = 1;
-
-        /**
-         * Filter by conversations the current user is participating in
-         * @var integer
-         */
-        const LIST_TYPE_PARTICIPANT = 2;
-
-        /**
-         * Given a filter type, @return the searchAttributes. If there is no filter specified it will default to a
-         * list of conversations the logged in user has started
-         * @param string $type
-         */
-        public static function resolveSearchAttributesByType($type)
-        {
-            assert('$type == self::LIST_TYPE_CREATED || $type == self::LIST_TYPE_PARTICIPANT');
-            if($type == self::LIST_TYPE_CREATED)
-            {
-                $searchAttributes = array(
-                    'owner'    => array('id' => Yii::app()->user->userModel->id)
-                );
-            }
-            else
-            {
-                $searchAttributes = array(
-                    'conversationParticipants' => array('id' => Yii::app()->user->userModel->id),
-                );
-            }
-            return $searchAttributes;
-        }
-    }
-?>

app/protected/modules/conversations/utils/ConversationsUtil.php

+<?php
+    /*********************************************************************************
+     * Zurmo is a customer relationship management program developed by
+     * Zurmo, Inc. Copyright (C) 2012 Zurmo Inc.
+     *
+     * Zurmo is free software; you can redistribute it and/or modify it under
+     * the terms of the GNU General Public License version 3 as published by the
+     * Free Software Foundation with the addition of the following permission added
+     * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
+     * IN WHICH THE COPYRIGHT IS OWNED BY ZURMO, ZURMO DISCLAIMS THE WARRANTY
+     * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
+     *
+     * Zurmo is distributed in the hope that it will be useful, but WITHOUT
+     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+     * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+     * details.
+     *
+     * You should have received a copy of the GNU General Public License along with
+     * this program; if not, see http://www.gnu.org/licenses or write to the Free
+     * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+     * 02110-1301 USA.
+     *
+     * You can contact Zurmo, Inc. with a mailing address at 113 McHenry Road Suite 207,
+     * Buffalo Grove, IL 60089, USA. or at email address contact@zurmo.com.
+     ********************************************************************************/
+
+    /**
+     * Helper class for working with conversations
+     */
+    class ConversationsUtil
+    {
+        public static function renderSubjectAndLatestForDisplayView(Conversation $conversation)
+        {
+            $url     = Yii::app()->createUrl('/conversations/default/details', array('id' => $conversation->id));
+            $content = $conversation->subject;
+            if($conversation->comments->count() > 0)
+            {
+                $content .= '<BR/>';
+                $position = $conversation->comments->count() - 1;
+                if($conversation->comments->offsetGet($position)->createdByUser == Yii::app()->user->userModel)
+                {
+                    $content .= Yii::t('Default', 'Me') . ': ';
+                }
+                else
+                {
+                    $content .= strval($conversation->comments->offsetGet($position)->createdByUser) . ': ';
+                }
+                $content .= $conversation->comments->offsetGet($position);
+            }
+            elseif($conversation->description != null)
+            {
+                $content .= '<BR/>';
+                if($conversation->owner == Yii::app()->user->userModel)
+                {
+                    $content .= Yii::t('Default', 'Me') . ': ';
+                }
+                else
+                {
+                    $content .= strval($conversation->owner) . ': ';
+                }
+                $content .= $conversation->description;
+            }
+            return $content = ZurmoHtml::link($content, $url);
+        }
+    }
+?>

app/protected/modules/conversations/views/ConversationsActionBarForListView.php

                 'global' => array(
                     'toolbar' => array(
                         'elements' => array(
+                            array('type'          => 'CreateLink',
+                                'htmlOptions'     => array('class' => 'icon-create'),
+                            ),
                             array(
                                 'type'            => 'ConversationsCreatedLink',
                                 'htmlOptions'     => array( 'class' => 'icon-conversations-created' )

app/protected/modules/conversations/views/ConversationsListView.php

         {
             $metadata = array(
                 'global' => array(
+                    'derivedAttributeTypes' => array(
+                        'ConversationLatest',
+                    ),
                     'panels' => array(
                         array(
                             'rows' => array(
                                     array(
                                         array(
                                             'elements' => array(
-                                                array('attributeName' => 'subject', 'type' => 'Text', 'isLink' => true),
+                                                array('attributeName' => 'null', 'type' => 'ConversationLatest'),
                                             ),
                                         ),
                                     )
                                     array(
                                         array(
                                             'elements' => array(
-                                                array('attributeName' => 'latestDateTime', 'type' => 'DateTime'),
+                                                array('attributeName' => 'latestDateTime', 'type' => 'ConversationLatestDateTime'),
                                             ),
                                         ),
                                     )

app/protected/modules/zurmo/data/GroupsDefaultDataMaker.php

             $everyone->setRight('HomeModule',          HomeModule::RIGHT_CREATE_DASHBOARDS, Right::ALLOW);
             $everyone->setRight('HomeModule',          HomeModule::RIGHT_DELETE_DASHBOARDS, Right::ALLOW);
             $everyone->setRight('ExportModule',        ExportModule::RIGHT_ACCESS_EXPORT, Right::ALLOW);
+            $everyone->setRight('ConversationsModule', ConversationsModule::RIGHT_ACCESS_CONVERSATIONS, Right::ALLOW);
+            $everyone->setRight('ConversationsModule', ConversationsModule::RIGHT_CREATE_CONVERSATIONS, Right::ALLOW);
+            $everyone->setRight('ConversationsModule', ConversationsModule::RIGHT_DELETE_CONVERSATIONS, Right::ALLOW);
             $saved = $everyone->save();
             assert('$saved');
         }

app/protected/modules/zurmo/views/DetailsAndRelationsView.php

             else
             {
                 $leftTopView    = new $detailsViewClassName($this->params["controllerId"],
-                                                                            $this->params["relationModuleId"],
-                                                                            $this->params["relationModel"]);
+                                                            $this->params["relationModuleId"],
+                                                            $this->params["relationModel"]);
             }
             $leftBottomView = new ModelRelationsSecuredPortletFrameView($this->controllerId,
                                                                         $this->moduleId,