Przeglądaj źródła

#1904 Classes module: classes availability and some design

Alex Trofimov 6 lat temu
rodzic
commit
d7ea6ceb02

+ 24 - 0
modules/boonex/classes/classes/BxClssDb.php

@@ -24,6 +24,30 @@ class BxClssDb extends BxBaseModTextDb
         parent::__construct($oConfig);
     }
 
+    public function getPrevEntry ($iClassId)
+    {        
+        return $this->_getNextPrevEntry($iClassId, 'DESC');
+    }
+
+    public function getNextEntry ($iClassId)
+    {        
+        return $this->_getNextPrevEntry($iClassId, 'ASC');
+    }
+
+    protected function _getNextPrevEntry ($iClassId, $sSorting = 'DESC')
+    {        
+        $aClass = $this->getRow("SELECT `c`.`id`, `c`.`order`, `m`.`order` as `order_module` FROM `" . $this->_oConfig->CNF['TABLE_ENTRIES'] . "` AS `c` INNER JOIN `" . $this->_oConfig->CNF['TABLE_MODULES'] . "` AS `m` ON (`m`.`id` = `c`.`module_id`) WHERE `c`.`id` = :class", array('class' => $iClassId));
+        $sQuery = "SELECT `c`.`*`, `m`.`module_title` FROM `" . $this->_oConfig->CNF['TABLE_ENTRIES'] . "` AS `c` INNER JOIN `" . $this->_oConfig->CNF['TABLE_MODULES'] . "` AS `m` ON (`m`.`id` = `c`.`module_id`) WHERE `m`.`order` <= :order_module AND `c`.`order` <= :order AND `c`.`id` != :id ORDER BY `m`.`order` DESC, `c`.`order` DESC LIMIT 1";
+        
+        $a = $this->getRow($sQuery, array(
+            'order_module' => $aClass['order_module'], 
+            'order' => $aClass['order'],
+            'id' => $aClass['id'],
+        ));
+
+        return $a;
+    }
+
     public function getEntriesByModule ($iModuleId)
     {
         $sQuery = $this->prepare ("SELECT * FROM `" . $this->_oConfig->CNF['TABLE_ENTRIES'] . "` WHERE `module_id` = ? ORDER BY `order`", $iModuleId);

+ 129 - 10
modules/boonex/classes/classes/BxClssModule.php

@@ -9,6 +9,12 @@
  * @{
  */
 
+
+define('BX_CLASSES_AVAIL_ALWAYS', 1);
+define('BX_CLASSES_AVAIL_PREV_CLASS_COMPLETED', 2);
+define('BX_CLASSES_AVAIL_AFTER_START_DATE', 3);
+define('BX_CLASSES_AVAIL_AFTER_START_DATE_PREV_CLASS_COMPLETED', 4);
+
 /**
  * Classes module
  */
@@ -188,17 +194,28 @@ class BxClssModule extends BxBaseModTextModule
         return parent::serviceCheckAllowedCommentsView($iContentId, $sObjectComments);
     }
 
-    public function serviceClassesInContext ($iProfileId = 0)
+    public function serviceClassesInContext ($iContextProfileId = 0)
     {
-        if (!$iProfileId)
-            $iProfileId = (int)bx_get('id') ? bx_get('id') : bx_get('profile_id');
+        if (!$iContextProfileId)
+            $iContextProfileId = (int)bx_get('id') ? bx_get('id') : bx_get('profile_id');
+
+        if (!($oContextProfile = BxDolProfile::getInstance($iContextProfileId)))
+            return MsgBox(_t('_sys_txt_error_occured'));
+
+        $mixedViewAllowed = $oContextProfile->checkAllowedProfileView();
+        if (CHECK_ACTION_RESULT_ALLOWED !== $mixedViewAllowed)
+            return MsgBox($mixedViewAllowed);
 
         $aInputs = array();
-        $aModules = $this->_oDb->getEntriesModulesByContext($iProfileId);
+        $aModules = $this->_oDb->getEntriesModulesByContext($iContextProfileId);
         foreach ($aModules as $aModule) {
+            $iCounterCompleted = 0;
+            $iCounterAvail = 0;
+            $iCounterNa = 0;
+
             $aInputs['module' . $aModule['id']] = array(
                 'type' => 'block_header',
-                'caption' => $aModule['module_title'],
+                'caption' => '&nbsp;' . bx_process_output($aModule['module_title']),
                 'collapsed' => false,
                 'attrs' => array('id' => 'module_' . $aModule['id'], 'class' => ''),
             );
@@ -206,14 +223,59 @@ class BxClssModule extends BxBaseModTextModule
             $sContent = '';
             if ($aClasses) {
                 foreach ($aClasses as $aClass) {
+                    $sStatusClass = '';
+                    // check class availability
+                    $mixedAvailability = $this->checkAllowedViewForProfile($aClass, bx_get_logged_profile_id());
+                    $sTip = '';
+                    if ($mixedAvailability !== CHECK_ACTION_RESULT_ALLOWED) {
+                        ++$iCounterNa;
+                        $sStatusClass = 'bx-classes-class-status-na';
+                        $sTip = strip_tags($mixedAvailability);
+                    }
+                    // check if class is completed
+                    elseif ($this->serviceIsClassCompleted($aClass['id'])) {
+                        ++$iCounterCompleted;
+                        $sStatusClass = 'bx-classes-class-status-completed';
+                    }
+                    // class is available
+                    else {
+                        ++$iCounterAvail;
+                        $sStatusClass = 'bx-classes-class-status-avail';
+                    }
+                                
+
                     $sContent .= $this->_oTemplate->parseHtmlByName('classes_class_row.html', array(
-                        'id' => $aClass['id'],
-                        'title' => $aClass['title'] . '(' . ($this->serviceIsClassCompleted($aClass['id']) ? 'completed' : 'not completed') . ')',
-                        'url' => BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink('page.php?i=' . $this->_oConfig->CNF['URI_VIEW_ENTRY'] . '&id=' . $aClass['id']),
+                        'id' => $aClass['id'],                        
+                        'status' => $sStatusClass,
+                        'bx_if:completed' => array(
+                            'condition' => 'bx-classes-class-status-completed' == $sStatusClass,
+                            'content' => array (
+                                'title' => bx_process_output($aClass['title']),
+                                'url' => $this->serviceGetLink($aClass['id']),
+                            ),
+                        ),
+                        'bx_if:avail' => array(
+                            'condition' => 'bx-classes-class-status-avail' == $sStatusClass,
+                            'content' => array (
+                                'title' => bx_process_output($aClass['title']),
+                                'url' => $this->serviceGetLink($aClass['id']),
+                            ),
+                        ),
+                        'bx_if:na' => array(
+                            'condition' => 'bx-classes-class-status-na' == $sStatusClass,
+                            'content' => array (
+                                'title' => bx_process_output($aClass['title']),
+                                'tip' => bx_html_attribute($sTip),
+                            ),
+                        ),
                     ));
                 }
             }
 
+            if (0 == $iCounterAvail) {
+                $aInputs['module' . $aModule['id']]['collapsed'] = true;
+            }
+
             $aInputs['class_module' . $aModule['id']] = array(
                 'type' => 'custom',
                 'name' => 'class_module' . $aModule['id'],
@@ -236,9 +298,14 @@ class BxClssModule extends BxBaseModTextModule
         $this->_oTemplate->addJs('main.js');
 
         return $this->_oTemplate->parseHtmlByName('classes_in_context.html', array(
-            'profile_id' => $iProfileId,
-            'new_class_url' => BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink('page.php?i=create-class&profile_id=' . $iProfileId),
             'form' => $oForm->getCode(),
+            'bx_if:admin' => array(
+                'condition' => isAdmin() || bx_srv($oContextProfile->getModule(), 'is_admin', array($oContextProfile->id(), bx_get_logged_profile_id())),
+                'content' => array(
+                    'context_profile_id' => $iContextProfileId,
+                    'new_class_url' => BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink('page.php?i=create-class&profile_id=' . $oContextProfile->id()),
+                ),
+            ),
         ));
     }
 
@@ -249,6 +316,58 @@ class BxClssModule extends BxBaseModTextModule
 
         return $this->_oDb->isClassCompleted($iClassId, $iProfileId);
     }
+
+    public function serviceIsAdmin ($aDataEntry, $iProfileId = 0)
+    {
+        if (!$iProfileId)
+            $iProfileId = bx_get_logged_profile_id();
+
+        if (!($oProfileContext = BxDolProfile::getInstance(abs($aDataEntry['allow_view_to']))))
+            return false;
+        
+        return bx_srv($oProfileContext->getModule(), 'is_admin', array($oProfileContext->id(), $iProfileId));
+    }
+
+    public function serviceIsPrevClassCompleted ($aDataEntry, $iProfileId = 0)
+    {
+        if (!$iProfileId)
+            $iProfileId = bx_get_logged_profile_id();
+
+        if (!($aPrevClass = $this->_oDb->getPrevEntry ($aDataEntry['id'])))
+            return true; // if there is no prev class it's considered as completed
+        
+        return $this->serviceIsClassCompleted($aPrevClass['id'], $iProfileId);
+    }
+
+    public function serviceCheckAvailabilityForProfile ($aDataEntry, $iProfileId)
+    {
+        if (BX_CLASSES_AVAIL_ALWAYS == $aDataEntry['avail'] || isAdmin() || $this->serviceIsAdmin ($aDataEntry, $iProfileId))
+            return CHECK_ACTION_RESULT_ALLOWED;
+
+        // check start date
+        if ((BX_CLASSES_AVAIL_AFTER_START_DATE == $aDataEntry['avail'] || BX_CLASSES_AVAIL_AFTER_START_DATE_PREV_CLASS_COMPLETED == $aDataEntry['avail']) && $aDataEntry['start_date'] > time()) {
+            return _t('_bx_classes_txt_err_not_avail_before_start_date', bx_time_js($aDataEntry['start_date'], BX_FORMAT_DATE_TIME, true));
+        }
+
+        // check availability
+        if ((BX_CLASSES_AVAIL_PREV_CLASS_COMPLETED == $aDataEntry['avail'] || BX_CLASSES_AVAIL_AFTER_START_DATE_PREV_CLASS_COMPLETED == $aDataEntry['avail']) && !$this->serviceIsPrevClassCompleted($aDataEntry, $iProfileId)) {
+            if (!($aPrevClass = $this->_oDb->getPrevEntry ($aDataEntry['id'])))
+                return _t('_sys_txt_error_occured');
+            return _t('_bx_classes_txt_err_not_avail_before_prev_class_completed', $this->serviceGetLink($aPrevClass['id']), bx_process_output($aPrevClass['title']));
+        }
+        
+
+        return CHECK_ACTION_RESULT_ALLOWED;
+    }
+
+    protected function _serviceCheckAllowedViewForProfile ($aDataEntry, $isPerformAction, $iProfileId)
+    {
+        $mixed = parent::_serviceCheckAllowedViewForProfile ($aDataEntry, $isPerformAction, $iProfileId);
+        if (CHECK_ACTION_RESULT_ALLOWED === $mixed)
+            return $this->serviceCheckAvailabilityForProfile ($aDataEntry, $iProfileId);
+        else
+            return $mixed;
+    }
 }
 
 /** @} */

+ 2 - 0
modules/boonex/classes/install/langs/en.xml

@@ -232,6 +232,8 @@
 
     <string name="_bx_classes_txt_err_cannot_perform_action"><![CDATA[Cannot perform action. Please report.]]></string>
     <string name="_bx_classes_txt_err_cant_add_class_without_context"><![CDATA[Class can be added into context only]]></string>
+    <string name="_bx_classes_txt_err_not_avail_before_start_date"><![CDATA[Class will be available {0}]]></string>
+    <string name="_bx_classes_txt_err_not_avail_before_prev_class_completed"><![CDATA[Class will be available after completing previous class - <a href="{0}">{1}</a>]]></string>
 
     <string name="_bx_classes_txt_poll_view_answers"><![CDATA[poll]]></string>
     <string name="_bx_classes_txt_poll_view_results"><![CDATA[results]]></string>

+ 17 - 1
modules/boonex/classes/template/classes_class_row.html

@@ -1,3 +1,19 @@
 <div id="class___id__" class="bx-classes-class bx-def-margin-thd-topbottom">
-    <div class="bx-classes-class-title"><a href="__url__">__title__</a></div>
+    <div class="bx-classes-class-title bx-def-font-h3 __status__">
+        <bx_if:completed>
+            <i class="sys-icon check-circle col-green1-dark sys-colored"></i>
+            <a href="__url__">__title__</a>
+        </bx_if:completed>
+        <bx_if:avail>
+            <i class="sys-icon play-circle col-blue1 sys-colored"></i>
+            <a href="__url__">__title__</a>
+        </bx_if:avail>
+        <bx_if:na>
+            <i class="sys-icon ban col-red1 sys-colored"></i>
+            <b title="__tip__" class="bx-def-font-grayed">
+                __title__ 
+                <i class="sys-icon info-circle"></i>
+            </b>
+        </bx_if:na>
+    </div>
 </div>

+ 6 - 4
modules/boonex/classes/template/classes_in_context.html

@@ -1,14 +1,16 @@
+<bx_if:admin>
 <div class="bx-course-controls bx-def-margin-bottom bx-clearfix">
     <div class="bx-course-controls-1 bx-clearfix">
         <a class="bx-btn bx-def-margin-right" href="__new_class_url__">Add Class</a>
-        <a class="bx-btn" href="javascript:void(0);" onclick="bx_classes_show_module_add_form('__profile_id__')">Add Module</a>
+        <a class="bx-btn" href="javascript:void(0);" onclick="bx_classes_show_module_add_form('__context_profile_id__')">Add Module</a>
     </div>
     <div class="bx-course-controls-2 bx-clearfix">
-        <a class="bx-btn" href="javascript:void(0);" onclick="bx_classes_reorder_modules('__profile_id__', true)">Rearrange Moodules</a>
-        <a class="bx-btn bx-def-margin-left" href="javascript:void(0);" onclick="bx_classes_reorder_classes('__profile_id__', true)">Rearrange Classes</a>
-        <a class="bx-btn bx-def-margin-left bx-classes-btn-done" href="javascript:void(0);" onclick="bx_classes_reorder_classes('__profile_id__', false); bx_classes_reorder_modules('__profile_id__', false);">Done</a>
+        <a class="bx-btn" href="javascript:void(0);" onclick="bx_classes_reorder_modules('__context_profile_id__', true)">Rearrange Moodules</a>
+        <a class="bx-btn bx-def-margin-left" href="javascript:void(0);" onclick="bx_classes_reorder_classes('__context_profile_id__', true)">Rearrange Classes</a>
+        <a class="bx-btn bx-def-margin-left bx-classes-btn-done" href="javascript:void(0);" onclick="bx_classes_reorder_classes('__context_profile_id__', false); bx_classes_reorder_modules('__context_profile_id__', false);">Done</a>
     </div>
 </div>
+</bx_if:admin>
 <div class="bx-course-classes">
     __form__
 </div>

+ 9 - 1
modules/boonex/classes/template/css/main.css

@@ -9,7 +9,11 @@
 }
 
 .bx-course-classes .bx-form-input-wrapper-custom {
-    min-height: 1.2rem;
+    min-height:1rem;
+}
+
+html .bx-classes-class-title {
+    line-height:2rem;
 }
 
 .bx-classes-btn-done {
@@ -21,3 +25,7 @@
 .bx-course-reordering-mode .bx-btn:not(.bx-classes-btn-done) {
     display:none;
 }
+
+.bx-classes-class-status-completed a {
+    text-decoration: line-through;
+}