Ver código fonte

#22 - popup previews with edit button

Alex Trofimov 13 anos atrás
pai
commit
2b76e05d83

+ 6 - 1
inc/js/jquery.dolPopup.js

@@ -95,7 +95,7 @@
 
                     // attach event for outer click checking
                     if (o.closeOnOuterClick) {
-                        $(document).click(function(e) {
+                        var fCallback = function(e) {
                             if ($el.hasClass('bx-popup-applied') && $el.is(':visible')) {
                                 if ($(e.target).parents('#' + $el.attr('id')).length == 0) {
                                     $el.dolPopupHide();
@@ -103,6 +103,11 @@
                             }
 
                             return true;
+                        }
+
+                        $(document).on({
+                            click: fCallback,
+                            touchend: fCallback
                         });
                     }
                 }

+ 4 - 1
modules/boonex/persons/classes/BxPersonsConfig.php

@@ -18,13 +18,16 @@ class BxPersonsConfig extends BxDolModuleConfig {
     public static $FIELD_CHANGED = 'changed';
     public static $FIELD_NAME = 'fullname';
     public static $FIELD_PICTURE = 'picture';
+    public static $FIELD_PICTURE_PREVIEW = 'picture_preview';
     public static $FIELD_COVER = 'cover';
+    public static $FIELD_COVER_PREVIEW = 'cover_preview';
 
     public static $OBJECT_STORAGE = 'bx_persons_pictures';
-    public static $OBJECT_STORAGE_COVER = 'bx_persons_pictures_covers';
+    public static $OBJECT_STORAGE_COVER = 'bx_persons_pictures';
     public static $OBJECT_IMAGES_TRANSCODER_THUMB = 'bx_persons_thumb';
     public static $OBJECT_IMAGES_TRANSCODER_ICON = 'bx_persons_icon';
     public static $OBJECT_IMAGES_TRANSCODER_PREVIEW = 'bx_persons_preview';
+    public static $OBJECT_IMAGES_TRANSCODER_PICTURE = 'bx_persons_picture';
     public static $OBJECT_IMAGES_TRANSCODER_COVER = 'bx_persons_cover';
     public static $OBJECT_IMAGES_TRANSCODER_COVER_THUMB = 'bx_persons_cover_thumb';
 

+ 54 - 152
modules/boonex/persons/classes/BxPersonsFormPerson.php

@@ -10,6 +10,8 @@
  */
 
 bx_import('BxTemplFormView');
+bx_import('BxDolProfile');
+bx_import('BxDolStorage');
 
 /**
  * Create/Edit Person Form.
@@ -27,70 +29,59 @@ class BxPersonsFormPerson extends BxTemplFormView {
             BxPersonsConfig::$FIELD_PICTURE => array (
                 'storage_object' => BxPersonsConfig::$OBJECT_STORAGE,
                 'images_transcoder' => BxPersonsConfig::$OBJECT_IMAGES_TRANSCODER_THUMB,
-                'uploaders' => array('bx_persons_avatar'),
+                'field_preview' => BxPersonsConfig::$FIELD_PICTURE_PREVIEW,
             ),
             BxPersonsConfig::$FIELD_COVER => array (
                 'storage_object' => BxPersonsConfig::$OBJECT_STORAGE_COVER,
                 'images_transcoder' => BxPersonsConfig::$OBJECT_IMAGES_TRANSCODER_COVER_THUMB,
-                'uploaders' => array('bx_persons_cover'),
+                'field_preview' => BxPersonsConfig::$FIELD_COVER_PREVIEW,
             ),
         );
+        $this->_aImageFields[BxPersonsConfig::$FIELD_PICTURE_PREVIEW] = $this->_aImageFields[BxPersonsConfig::$FIELD_PICTURE];
+        $this->_aImageFields[BxPersonsConfig::$FIELD_COVER_PREVIEW] = $this->_aImageFields[BxPersonsConfig::$FIELD_COVER];
 
-        bx_import('BxDolProfile');
         $oAccountProfile = BxDolProfile::getInstanceAccountProfile();
         if ($oAccountProfile)
             $this->_iAccountProfileId = $oAccountProfile->id();
 
         $this->_oModule = BxDolModule::getInstance('bx_persons');
-
-
-        $aDefaultsFieldImage = array (
-            'storage_object' => BxPersonsConfig::$OBJECT_STORAGE,
-            'uploaders' => array('bx_persons_avatar'),
-            'images_transcoder' => BxPersonsConfig::$OBJECT_IMAGES_TRANSCODER_THUMB,
-            'multiple' => false,
-            'content_id' => 0,
-            'upload_buttons_titles' => _t('_bx_persons_form_person_input_picture_btn_upload'),
-            'ghost_template' => '',
-        );
-
-        foreach ($this->_aImageFields as $sField => $aVals) {
-            if (!isset($this->aInputs[$sField]))
-                continue;
-            foreach ($aDefaultsFieldImage as $k => $v )
-                $this->aInputs[$sField][$k] = isset($aVals[$k]) ? $aVals[$k] : $v;
-        }
-
     }
 
     function initChecker ($aValues = array (), $aSpecificValues = array())  {
 
+        parent::initChecker($aValues, $aSpecificValues);
+
         foreach ($this->_aImageFields as $sField => $aVals) {
-            if (!isset($this->aInputs[$sField]))
+            if (!isset($this->aInputs[$sField]) || !isset($aValues[$sField]))
                 continue;
 
             if ($aValues && !empty($aValues['id'])) 
                 $this->aInputs[$sField]['content_id'] = $aValues['id'];
 
-            bx_import('BxDolUploader');
-            $oUploader = BxDolUploader::getObjectInstance($this->aInputs[$sField]['uploaders'][0], $this->aInputs[$sField]['storage_object'], rand(0, PHP_INT_MAX));
-            
+            $sErrorString = '';
+            $this->aInputs[$sField]['file_id'] = $this->_processFile ($sField, $aValues[$sField], $sErrorString);
+            if ($sErrorString) {
+                $this->aInputs[$sField]['error'] = $sErrorString;
+                $this->setValid(false);
+            }
+
+            $oTranscoder = BxDolImageTranscoder::getObjectInstance($aVals['images_transcoder']);
+
             $aVars = array (
-                'name' => $this->aInputs[$sField]['name'],
-                'content_id' => $this->aInputs[$sField]['content_id'],
-                'current_picture_id' => (isset($aValues[$sField]) ? $aValues[$sField] : 0),
-                'uploader_js_instance_name' => $oUploader->getNameJsInstanceUploader(),
-                'bx_if:not_required' => array (
-                    'condition' => !$this->aInputs[$sField]['required'],
-                    'content' => array(
-                        'name' => $this->aInputs[$sField]['name'],
+                'bx_if:picture' => array (
+                    'condition' => $oTranscoder && $aValues[$sField] ? true : false,
+                    'content' => array (
+                        'picture_url' => $oTranscoder ? $oTranscoder->getImageUrl($aValues[$sField]) : '',
                     ),
                 ),
-            );            
-            $this->aInputs[$sField]['ghost_template'] = $this->_oModule->_oTemplate->parseHtmlByName('form_ghost_template.html', $aVars);
+                'bx_if:no_picture' => array (
+                    'condition' => !$oTranscoder || !$aValues[$sField] ? true : false,
+                    'content' => array (),
+                ),
+            );
+            $this->aInputs[$aVals['field_preview']]['content'] = $this->_oModule->_oTemplate->parseHtmlByName('picture_preview.html', $aVars);
         }
         
-        return parent::initChecker($aValues, $aSpecificValues);
     }
 
     public function insert ($aValsToAdd = array(), $isIgnore = false) {
@@ -98,146 +89,57 @@ class BxPersonsFormPerson extends BxTemplFormView {
             BxPersonsConfig::$FIELD_AUTHOR => $this->_iAccountProfileId,
             BxPersonsConfig::$FIELD_ADDED => time(),
             BxPersonsConfig::$FIELD_CHANGED => time(),
+            BxPersonsConfig::$FIELD_COVER => $this->aInputs[BxPersonsConfig::$FIELD_COVER]['file_id'],
+            BxPersonsConfig::$FIELD_PICTURE => $this->aInputs[BxPersonsConfig::$FIELD_PICTURE]['file_id'],
         ));
-        if ($iContentId = parent::insert ($aValsToAdd, $isIgnore)) {
-            foreach ($this->_aImageFields as $sField => $aVals)
-                $this->_processFiles ((int)$this->getCleanValue($sField), $iContentId, true, $sField);
-        }
-        return $iContentId;
+        return parent::insert ($aValsToAdd, $isIgnore);
     }
 
     function update ($iContentId, $aValsToAdd = array(), &$aTrackTextFieldsChanges = null) {        
         $aValsToAdd[BxPersonsConfig::$FIELD_CHANGED] = time();
-        if ($iRet = parent::update ($iContentId, $aValsToAdd, $aTrackTextFieldsChanges)) {
-            foreach ($this->_aImageFields as $sField => $aVals)
-                $this->_processFiles ((int)$this->getCleanValue($sField), $iContentId, false, $sField);
-        }
-        return $iRet;
-    }
-
-    function delete ($iContentId, $aContentInfo = array()) {
-
-        // TODO: clean db field after deletion
-        // TODO: delete proper file! cover or avatar - NOT BOTH!
-        // TODO: also old image is not deleted when new image is uploaded
-        if (!$this->_deleteFile($aContentInfo[BxPersonsConfig::$FIELD_PICTURE], BxPersonsConfig::$OBJECT_STORAGE) && !$this->_deleteFile($aContentInfo[BxPersonsConfig::$FIELD_COVER], BxPersonsConfig::$OBJECT_STORAGE_COVER))
-            return false;
-
-        return parent::delete($iContentId);
-    }
-
-    function deleteGhost ($iFileId, $iContentId, $isRestoreOriginal = true, $sFieldName = '') {
-
-        if (CHECK_ACTION_RESULT_ALLOWED !== ($sMsg = $this->_oModule->isAllowedAdd()))
-            return $sMsg;
+        if (isset($this->aInputs[BxPersonsConfig::$FIELD_COVER]))
+            $aValsToAdd[BxPersonsConfig::$FIELD_COVER] = $this->aInputs[BxPersonsConfig::$FIELD_COVER]['file_id'];
+        if (isset($this->aInputs[BxPersonsConfig::$FIELD_PICTURE]))
+            $aValsToAdd[BxPersonsConfig::$FIELD_PICTURE] = $this->aInputs[BxPersonsConfig::$FIELD_PICTURE]['file_id'];
 
-        foreach ($this->_aImageFields as $sField => $aVals) {
-
-            if ($sField != $sFieldName)
-                continue;
-
-            bx_import('BxDolStorage');
-            $oStorage = BxDolStorage::getObjectInstance($aVals['storage_object']);
-            if (!$oStorage)
-                return _t('_sys_txt_error_occured');
-
-            if (!$oStorage->deleteFile($iFileId, $this->_iAccountProfileId))
-                return _t('_sys_txt_error_occured');
-
-            $this->_oModule->_oDb->updateContentPictureById($iContentId, $this->_iAccountProfileId, 0, $sField);
-        }
-
-        return '';
+        return parent::update ($iContentId, $aValsToAdd, $aTrackTextFieldsChanges);
     }
 
-    function discardGhost ($iFileId, $iContentId, $isRestoreOriginal = true, $sFieldName = '') {
-
-        if (CHECK_ACTION_RESULT_ALLOWED !== ($sMsg = $this->_oModule->isAllowedAdd()))
-            return $sMsg;
-
+    function delete ($iContentId, $aContentInfo = array()) {
 
         foreach ($this->_aImageFields as $sField => $aVals) {
-
-            if ($sField != $sFieldName)
-                continue;
-
-            bx_import('BxDolStorage');
-            $oStorage = BxDolStorage::getObjectInstance($aVals['storage_object']);
-            if (!$oStorage)
-                return _t('_sys_txt_error_occured');
-        
-            
-            $aFiles = $oStorage->getGhosts($this->_iAccountProfileId, $iContentId);        
-            if (!$aFiles)
-                return _t('_sys_txt_error_occured');
-
-            $isFileDeleted = false;
-            foreach ($aFiles as $aFile) {
-                if ($aFile['id'] == $iFileId) {
-                    $isFileDeleted = $oStorage->deleteFile($aFile['id'], $this->_iAccountProfileId);
-                    break;
-                }
-            }
-     
-            if (!$isFileDeleted)
-                return _t('_sys_txt_error_occured');
-
-            if ($isRestoreOriginal && $iContentId) {
-                $aContentInfo = $this->_oModule->_oDb->getContentInfoById($iContentId);
-                if (!$aContentInfo)
-                    return _t('_sys_txt_error_occured');
-
-                
-                if ($aContentInfo[$sField])
-                    if (!$oStorage->insertGhost($aContentInfo[$sField], $this->_iAccountProfileId, $iContentId))
-                        return _t('_sys_txt_error_occured');
-                
-            }
-
+            if (isset($aContentInfo[$sField]) && $aContentInfo[$sField])
+                $htis->_deleteFile ($aContentInfo[$sField], $aVals['storage_object']);
         }
 
-        return '';
+        return parent::delete($iContentId);
     }
 
-    function _processFiles ($iFileId, $iContentId = 0, $isCheckForZero = false, $sField = '') {
-        if (!isset($this->_aImageFields[$sField]))
-            return false;
+    function _processFile ($sField, $iFileIdOld, &$sErrorString) {
+        if (empty($_FILES[$sField]['tmp_name']))
+            return $iFileIdOld;
 
-        bx_import('BxDolStorage');
         $oStorage = BxDolStorage::getObjectInstance($this->_aImageFields[$sField]['storage_object']);
         if (!$oStorage)
-            return false;
+            return $iFileIdOld;
 
-        $iErrors = 0;
-
-        $a = array($iContentId);
-        if ($isCheckForZero)
-            $a[] = 0;
-
-        foreach ($a as $iForceContentId) {
-            $aFiles = $oStorage->getGhosts($this->_iAccountProfileId, $iForceContentId);
-            foreach ($aFiles as $aFile) {
-                if ($iFileId == $aFile['id']) { 
-                    // save only one file
-                    if (0 == $iForceContentId && $isCheckForZero) // if we are adding content, then associate ghosts with just added content
-                        if (!$oStorage->updateGhostsContentId($iFileId, $this->_iAccountProfileId, $iContentId))
-                            ++$iErrors;
-                } else {
-                    // delete all other files
-                    if (!$oStorage->deleteFile($aFile['id'], $this->_iAccountProfileId)) 
-                        ++$iErrors;
-                }
-            }
+        // delete previous file
+        $this->_deleteFile($iFileIdOld, $this->_aImageFields[$sField]['storage_object']);
+
+        // process new file and return new file id
+        if (!($iFileId = $oStorage->storeFileFromForm($_FILES[$sField], false, $this->_iAccountProfileId))) {
+            $sErrorString = $oStorage->getErrorString();
+            return 0;
         }
-        return $iErrors ? false : true;
+
+        return $iFileId;
     }
 
     function _deleteFile ($iFileId, $sStorageObject) {
 
         if (!$iFileId)
-            return true;        
+            return true;
 
-        bx_import('BxDolStorage');
         if (!($oStorage = BxDolStorage::getObjectInstance($sStorageObject)))
             return false;
 

+ 0 - 26
modules/boonex/persons/classes/BxPersonsModule.php

@@ -235,32 +235,6 @@ class BxPersonsModule extends BxDolModule implements iBxDolProfileService {
         $oTemplate->getPageCode();
     }
 
-    function actionDiscardGhost ($iFileId, $iContentId = 0, $sFieldName = '') {
-        $this->_actionWithGhost('discardGhost', $iFileId, $iContentId, $sFieldName);
-    }
-
-    function actionDeleteGhost ($iFileId, $iContentId = 0, $sFieldName = '') {
-        $this->_actionWithGhost('deleteGhost', $iFileId, $iContentId, $sFieldName);
-    }
-
-    function _actionWithGhost ($sAction, $iFileId, $iContentId = 0, $sFieldName = '') {
-        $iFileId = (int)$iFileId;
-        $iContentId = (int)$iContentId;
-
-        if (!$iFileId) {
-            header('Content-type: text/html; charset=utf-8');
-            echo _t('_sys_txt_error_occured');        
-            exit;
-        }
-
-        bx_import('BxDolForm');
-        $oForm = BxDolForm::getObjectInstance('bx_person', 'bx_person_add'); 
-
-        header('Content-type: text/html; charset=utf-8');
-        echo $oForm->$sAction($iFileId, $iContentId, true, $sFieldName);
-        exit;
-    }
-
     // ====== PERMISSION METHODS
 
     function _checkModeratorAccess ($isPerformAction = false) {

+ 41 - 11
modules/boonex/persons/classes/BxPersonsTemplate.php

@@ -50,23 +50,41 @@ class BxPersonsTemplate extends BxDolModuleTemplate {
      */
     function cover ($aData, $sTemplateName = 'cover.html') {        
 
-        $oModuleMain = BxDolModule::getInstance('bx_persons');
-        $sUrlCover = $this->urlCover ($aData);
-        $sUrlCoverChange = BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink('page.php?i=edit-persons-cover&id=' . $aData['id']);
-
-        // get person's url
         bx_import('BxDolPermalinks');
+
+        $oModuleMain = BxDolModule::getInstance('bx_persons');
         $sUrl = BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink('page.php?i=view-persons-profile&id=' . $aData['id']);
 
+        $sUrlPicture = $this->urlPicture ($aData);
+        $sUrlPreview = $this->urlPreview ($aData);
+        $sUrlPictureChange = BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink('page.php?i=edit-persons-profile&id=' . $aData['id']);
+
+        $sUrlCover = $this->urlCover ($aData);
+        $sUrlCoverChange = BX_DOL_URL_ROOT . BxDolPermalinks::getInstance()->permalink('page.php?i=edit-persons-cover&id=' . $aData['id']);        
+
         $sCoverPopup = '';
         if ($aData[BxPersonsConfig::$FIELD_COVER]) {
             bx_import('BxTemplFunctions');
-            $sCoverPopup = BxTemplFunctions::getInstance()->transBox($this->parseHtmlByName('cover_popup.html', array (
-                'cover_url' => $sUrlCover,
+            $sCoverPopup = BxTemplFunctions::getInstance()->transBox($this->parseHtmlByName('image_popup.html', array (
+                'image_url' => $sUrlCover,
                 'bx_if:owner' => array (
                     'condition' => CHECK_ACTION_RESULT_ALLOWED === $oModuleMain->isAllowedChangeCover($aData),
                     'content' => array (
-                        'change_cover_url' => $sUrlCoverChange,
+                        'change_image_url' => $sUrlCoverChange,
+                    ),
+                ),
+            )), true);
+        }
+
+        $sPicturePopup = '';
+        if ($aData[BxPersonsConfig::$FIELD_PICTURE]) {
+            bx_import('BxTemplFunctions');
+            $sPicturePopup = BxTemplFunctions::getInstance()->transBox($this->parseHtmlByName('image_popup.html', array (
+                'image_url' => $sUrlPicture,
+                'bx_if:owner' => array (
+                    'condition' => CHECK_ACTION_RESULT_ALLOWED === $oModuleMain->isAllowedEdit($aData),
+                    'content' => array (
+                        'change_image_url' => $sUrlPictureChange,
                     ),
                 ),
             )), true);
@@ -75,11 +93,16 @@ class BxPersonsTemplate extends BxDolModuleTemplate {
         // generate html        
         $aVars = array (
             'id' => $aData['id'],
-            'cover_url' => $sUrlCover,
-            'preview_url' => $this->urlPreview ($aData),
             'content_url' => $sUrl,
             'title' => $aData[BxPersonsConfig::$FIELD_NAME],
+
+            'picture_preview_url' => $sUrlPreview,
+            'picture_url' => $sUrlPicture,
+            'picture_popup' => $sPicturePopup,
+            'picture_href' => !$aData[BxPersonsConfig::$FIELD_PICTURE] && CHECK_ACTION_RESULT_ALLOWED === $oModuleMain->isAllowedEdit($aData) ? $sUrlPictureChange : 'javascript:void(0);',
+
             'cover_popup' => $sCoverPopup,
+            'cover_url' => $sUrlCover,
             'cover_href' => !$aData[BxPersonsConfig::$FIELD_COVER] && CHECK_ACTION_RESULT_ALLOWED === $oModuleMain->isAllowedChangeCover($aData) ? $sUrlCoverChange : 'javascript:void(0);',
         );
 
@@ -102,12 +125,19 @@ class BxPersonsTemplate extends BxDolModuleTemplate {
     }
 
     /**
-     * Get profile picture icon url
+     * Get profile picture preview url
      */
     function urlPreview ($aData, $bSubstituteNoImage = true) {
         return $this->_image (BxPersonsConfig::$FIELD_PICTURE, BxPersonsConfig::$OBJECT_IMAGES_TRANSCODER_PREVIEW, 'no-picture-preview.png', $aData, $bSubstituteNoImage);
     }
 
+    /**
+     * Get profile picture url
+     */
+    function urlPicture ($aData, $bSubstituteNoImage = true) {
+        return $this->_image (BxPersonsConfig::$FIELD_PICTURE, BxPersonsConfig::$OBJECT_IMAGES_TRANSCODER_PICTURE, 'no-picture-preview.png', $aData, $bSubstituteNoImage);
+    }
+
     /**
      * Get profile cover image url
      */

+ 9 - 5
modules/boonex/persons/install/langs/en.xml

@@ -18,10 +18,14 @@
 	<string name="_bx_persons_form_person_input_sex"><![CDATA[Sex]]></string>
 	<string name="_bx_persons_form_person_input_sex_err"><![CDATA[Sex field is mandatory]]></string>
 	<string name="_bx_persons_form_person_input_sys_picture"><![CDATA[Profile Picture]]></string>
-	<string name="_bx_persons_form_person_input_picture"><![CDATA[Profile Picture]]></string>
+	<string name="_bx_persons_form_person_input_picture"><![CDATA[Upload New Profile Picture]]></string>
+	<string name="_bx_persons_form_person_input_sys_picture_preview"><![CDATA[Profile Picture Preview]]></string>
+	<string name="_bx_persons_form_person_input_picture_preview"><![CDATA[Current Profile Picture]]></string>
 	<string name="_bx_persons_form_person_input_picture_err"><![CDATA[Profile picture is mandatory.]]></string>
-	<string name="_bx_persons_form_person_input_sys_cover"><![CDATA[Cover Image]]></string>
-	<string name="_bx_persons_form_person_input_cover"><![CDATA[Cover Image]]></string>
+	<string name="_bx_persons_form_person_input_sys_cover"><![CDATA[Cover Picture]]></string>
+	<string name="_bx_persons_form_person_input_cover"><![CDATA[Upload New Cover Picture]]></string>
+	<string name="_bx_persons_form_person_input_sys_cover_preview"><![CDATA[Cover Picture Preview]]></string>
+	<string name="_bx_persons_form_person_input_cover_preview"><![CDATA[Current Cover Picture]]></string>
 	<string name="_bx_persons_form_person_input_sys_delete_confirm"><![CDATA[Delete confirmation]]></string>
 	<string name="_bx_persons_form_person_input_delete_confirm"><![CDATA[I am sure I want to delete this profile]]></string>
 	<string name="_bx_persons_form_person_input_delete_confirm_info"><![CDATA[This action can not be undone.]]></string>
@@ -86,6 +90,6 @@
     <string name="_bx_persons_txt_account_pending"><![CDATA[This profile is pending approval, please wait until it is activated.]]></string>
     <string name="_bx_persons_txt_account_suspended"><![CDATA[This profile is suspended.]]></string>
 
-    <string name="_bx_persons_txt_change_cover"><![CDATA[Change Cover Image]]></string>
-
+    <string name="_bx_persons_txt_change_image"><![CDATA[Change Picure]]></string>
+    <string name="_bx_persons_txt_no_picture_uploaded"><![CDATA[No picture uploaded]]></string>
 </resources>

+ 5 - 5
modules/boonex/persons/install/sql/disable.sql

@@ -9,12 +9,12 @@ DELETE FROM `sys_options_types` WHERE `id` = @iTypeId;
 
 -- STORAGES & TRANSCODERS
 
-DELETE FROM `sys_objects_storage` WHERE `object` IN('bx_persons_pictures', 'bx_persons_pictures_resized', 'bx_persons_pictures_covers');
-DELETE FROM `sys_storage_tokens` WHERE `object` IN('bx_persons_pictures', 'bx_persons_pictures_resized', 'bx_persons_pictures_covers');
+DELETE FROM `sys_objects_storage` WHERE `object` IN('bx_persons_pictures', 'bx_persons_pictures_resized');
+DELETE FROM `sys_storage_tokens` WHERE `object` IN('bx_persons_pictures', 'bx_persons_pictures_resized');
 
-DELETE FROM `sys_objects_transcoder_images` WHERE `object` IN('bx_persons_icon', 'bx_persons_thumb', 'bx_persons_preview', 'bx_persons_cover', 'bx_persons_cover_thumb');
-DELETE FROM `sys_transcoder_images_filters` WHERE `transcoder_object` IN('bx_persons_icon', 'bx_persons_thumb', 'bx_persons_preview', 'bx_persons_cover', 'bx_persons_cover_thumb');
-DELETE FROM `sys_transcoder_images_files` WHERE `transcoder_object` IN('bx_persons_icon', 'bx_persons_thumb', 'bx_persons_preview', 'bx_persons_cover', 'bx_persons_cover_thumb');
+DELETE FROM `sys_objects_transcoder_images` WHERE `object` IN('bx_persons_icon', 'bx_persons_thumb', 'bx_persons_preview', 'bx_persons_picture', 'bx_persons_cover', 'bx_persons_cover_thumb');
+DELETE FROM `sys_transcoder_images_filters` WHERE `transcoder_object` IN('bx_persons_icon', 'bx_persons_thumb', 'bx_persons_preview', 'bx_persons_picture', 'bx_persons_cover', 'bx_persons_cover_thumb');
+DELETE FROM `sys_transcoder_images_files` WHERE `transcoder_object` IN('bx_persons_icon', 'bx_persons_thumb', 'bx_persons_preview', 'bx_persons_picture', 'bx_persons_cover', 'bx_persons_cover_thumb');
 -- TODO: delete resized picture files as well
 TRUNCATE TABLE `bx_persons_pictures_resized`; 
 

+ 4 - 6
modules/boonex/persons/install/sql/enable.sql

@@ -19,28 +19,26 @@ INSERT INTO `sys_options` (`name`, `value`, `category_id`, `caption`, `type`, `c
 SET @iTotalPicturesSize = IFNULL((SELECT SUM(`size`) FROM `bx_persons_pictures`), 0);
 SET @iTotalPicturesNum = IFNULL((SELECT COUNT(*) FROM `bx_persons_pictures`), 0);
 
-SET @iTotalPicturesCoversSize = IFNULL((SELECT SUM(`size`) FROM `bx_persons_pictures_covers`), 0);
-SET @iTotalPicturesCoversNum = IFNULL((SELECT COUNT(*) FROM `bx_persons_pictures_covers`), 0);
-
 SET @iTotalPicturesResizedSize = IFNULL((SELECT SUM(`size`) FROM `bx_persons_pictures_resized`), 0);
 SET @iTotalPicturesResizedNum = IFNULL((SELECT COUNT(*) FROM `bx_persons_pictures_resized`), 0);
 
 INSERT INTO `sys_objects_storage` (`object`, `engine`, `params`, `token_life`, `cache_control`, `levels`, `table_files`, `ext_mode`, `ext_allow`, `ext_deny`, `quota_size`, `current_size`, `quota_number`, `current_number`, `max_file_size`, `ts`) VALUES
 ('bx_persons_pictures', 'Local', '', 360, 2592000, 3, 'bx_persons_pictures', 'allow-deny', 'jpg,jpeg,jpe,gif,png', '', 0, @iTotalPicturesSize, 0, @iTotalPicturesNum, 0, 0),
-('bx_persons_pictures_covers', 'Local', '', 360, 2592000, 3, 'bx_persons_pictures_covers', 'allow-deny', 'jpg,jpeg,jpe,gif,png', '', 0, @iTotalPicturesCoversSize, 0, @iTotalPicturesCoversNum, 0, 0),
 ('bx_persons_pictures_resized', 'Local', '', 360, 2592000, 3, 'bx_persons_pictures_resized', 'allow-deny', 'jpg,jpeg,jpe,gif,png', '', 0, @iTotalPicturesResizedSize, 0, @iTotalPicturesResizedNum, 0, 0);
 
 INSERT INTO `sys_objects_transcoder_images` (`object`, `storage_object`, `source_type`, `source_params`, `private`, `atime_tracking`, `atime_pruning`, `ts`) VALUES 
 ('bx_persons_icon', 'bx_persons_pictures_resized', 'Storage', 'a:1:{s:6:"object";s:19:"bx_persons_pictures";}', 'no', '1', '2592000', '0'),
 ('bx_persons_thumb', 'bx_persons_pictures_resized', 'Storage', 'a:1:{s:6:"object";s:19:"bx_persons_pictures";}', 'no', '1', '2592000', '0'),
 ('bx_persons_preview', 'bx_persons_pictures_resized', 'Storage', 'a:1:{s:6:"object";s:19:"bx_persons_pictures";}', 'no', '1', '2592000', '0'),
-('bx_persons_cover', 'bx_persons_pictures_resized', 'Storage', 'a:1:{s:6:"object";s:26:"bx_persons_pictures_covers";}', 'no', '1', '2592000', '0'),
-('bx_persons_cover_thumb', 'bx_persons_pictures_resized', 'Storage', 'a:1:{s:6:"object";s:26:"bx_persons_pictures_covers";}', 'no', '1', '2592000', '0');
+('bx_persons_picture', 'bx_persons_pictures_resized', 'Storage', 'a:1:{s:6:"object";s:19:"bx_persons_pictures";}', 'no', '1', '2592000', '0'),
+('bx_persons_cover', 'bx_persons_pictures_resized', 'Storage', 'a:1:{s:6:"object";s:19:"bx_persons_pictures";}', 'no', '1', '2592000', '0'),
+('bx_persons_cover_thumb', 'bx_persons_pictures_resized', 'Storage', 'a:1:{s:6:"object";s:19:"bx_persons_pictures";}', 'no', '1', '2592000', '0');
 
 INSERT INTO `sys_transcoder_images_filters` (`transcoder_object`, `filter`, `filter_params`, `order`) VALUES 
 ('bx_persons_icon', 'Resize', 'a:4:{s:1:"w";s:2:"32";s:1:"h";s:2:"32";s:13:"square_resize";s:1:"1";s:10:"force_type";s:3:"jpg";}', '0'),
 ('bx_persons_thumb', 'Resize', 'a:4:{s:1:"w";s:2:"64";s:1:"h";s:2:"64";s:13:"square_resize";s:1:"1";s:10:"force_type";s:3:"jpg";}', '0'),
 ('bx_persons_preview', 'Resize', 'a:4:{s:1:"w";s:3:"150";s:1:"h";s:3:"150";s:13:"square_resize";s:1:"1";s:10:"force_type";s:3:"jpg";}', '0'),
+('bx_persons_picture', 'Resize', 'a:4:{s:1:"w";s:4:"1024";s:1:"h";s:4:"1024";s:13:"square_resize";s:1:"0";s:10:"force_type";s:3:"jpg";}', '0'),
 ('bx_persons_cover', 'Resize', 'a:4:{s:1:"w";s:4:"1024";s:1:"h";s:4:"1024";s:13:"square_resize";s:1:"1";s:10:"force_type";s:3:"jpg";}', '0'),
 ('bx_persons_cover_thumb', 'Resize', 'a:4:{s:1:"w";s:2:"64";s:1:"h";s:2:"64";s:13:"square_resize";s:1:"1";s:10:"force_type";s:3:"jpg";}', '0');
 

+ 41 - 40
modules/boonex/persons/install/sql/install.sql

@@ -32,22 +32,6 @@ CREATE TABLE `bx_persons_pictures` (
   UNIQUE KEY `remote_id` (`remote_id`)
 );
 
-CREATE TABLE `bx_persons_pictures_covers` (
-  `id` int(11) NOT NULL AUTO_INCREMENT,
-  `profile_id` int(10) unsigned NOT NULL,
-  `remote_id` varchar(255) NOT NULL,
-  `path` varchar(255) NOT NULL,
-  `file_name` varchar(255) NOT NULL,
-  `mime_type` varchar(128) NOT NULL,
-  `ext` varchar(32) NOT NULL,
-  `size` int(11) NOT NULL,
-  `added` int(11) NOT NULL,
-  `modified` int(11) NOT NULL,
-  `private` int(11) NOT NULL,
-  PRIMARY KEY (`id`),
-  UNIQUE KEY `remote_id` (`remote_id`)
-);
-
 CREATE TABLE `bx_persons_pictures_resized` (
   `id` int(11) NOT NULL AUTO_INCREMENT,
   `profile_id` int(10) unsigned NOT NULL,
@@ -77,40 +61,57 @@ INSERT INTO `sys_form_displays`(`object`, `display_name`, `module`, `view_mode`,
 ('bx_person', 'bx_person_view', 'bx_persons', 1, '_bx_persons_form_person_display_view');
 
 INSERT INTO `sys_form_inputs`(`object`, `module`, `name`, `value`, `values`, `checked`, `type`, `caption_system`, `caption`, `info`, `required`, `collapsed`, `html`, `attrs`, `attrs_tr`, `attrs_wrapper`, `checker_func`, `checker_params`, `checker_error`, `db_pass`, `db_params`, `editable`, `deletable`) VALUES 
+('bx_person', 'bx_persons', 'cover', '', '', 0, 'file', '_bx_persons_form_person_input_sys_cover', '_bx_persons_form_person_input_cover', '', 0, 0, 0, '', '', '', '', '', '', 'Int', '', 1, 0),
+('bx_person', 'bx_persons', 'cover_preview', '', '', 0, 'custom', '_bx_persons_form_person_input_sys_cover_preview', '_bx_persons_form_person_input_cover_preview', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
 ('bx_person', 'bx_persons', 'delete_confirm', 1, '', 0, 'checkbox', '_bx_persons_form_person_input_sys_delete_confirm', '_bx_persons_form_person_input_delete_confirm', '_bx_persons_form_person_input_delete_confirm_info', 1, 0, 0, '', '', '', 'Avail', '', '_bx_persons_form_person_input_delete_confirm_error', '', '', 1, 0),
 ('bx_person', 'bx_persons', 'do_submit', '_sys_form_account_input_submit', '', 0, 'submit', '_bx_persons_form_person_input_sys_do_submit', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
 ('bx_person', 'bx_persons', 'fullname', '', '', 0, 'text', '_bx_persons_form_person_input_sys_fullname', '_bx_persons_form_person_input_fullname', '', 1, 0, 0, '', '', '', 'Avail', '', '_bx_persons_form_person_input_fullname_err', 'Xss', '', 1, 0),
-('bx_person', 'bx_persons', 'picture', '', '', 0, 'files', '_bx_persons_form_person_input_sys_picture', '_bx_persons_form_person_input_picture', '', 1, 0, 0, '', '', '', 'Avail', '', '_bx_persons_form_person_input_picture_err', 'Int', '', 1, 0),
-('bx_person', 'bx_persons', 'cover', '', '', 0, 'files', '_bx_persons_form_person_input_sys_cover', '_bx_persons_form_person_input_cover', '', 0, 0, 0, '', '', '', '', '', '', 'Int', '', 1, 0),
+('bx_person', 'bx_persons', 'picture', '', '', 0, 'file', '_bx_persons_form_person_input_sys_picture', '_bx_persons_form_person_input_picture', '', 1, 0, 0, '', '', '', 'Avail', '', '_bx_persons_form_person_input_picture_err', 'Int', '', 1, 0),
+('bx_person', 'bx_persons', 'picture_preview', '', '', 0, 'custom', '_bx_persons_form_person_input_sys_picture_preview', '_bx_persons_form_person_input_picture_preview', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
 ('bx_person', 'bx_persons', 'sex', 1, '#!Sex', 0, 'radio_set', '_bx_persons_form_person_input_sys_sex', '_bx_persons_form_person_input_sex', '', 1, 0, 0, '', '', '', 'Avail', '', '_bx_persons_form_person_input_sex_err', 'Xss', '', 1, 1);
 
 INSERT INTO `sys_form_display_inputs`(`display_name`, `input_name`, `visible_for_levels`, `active`, `order`) VALUES 
-('bx_person_add', 'delete_confirm', 2147483647, 0, 1),
-('bx_person_add', 'cover', 2147483647, 0, 2),
-('bx_person_add', 'picture', 2147483647, 1, 3),
-('bx_person_add', 'fullname', 2147483647, 1, 4),
-('bx_person_add', 'sex', 2147483647, 1, 5),
-('bx_person_add', 'do_submit', 2147483647, 1, 6),
-('bx_person_delete', 'picture', 2147483647, 0, 0),
-('bx_person_delete', 'cover', 2147483647, 0, 0),
+('bx_person_add', 'cover_preview', 2147483647, 0, 1),
+('bx_person_add', 'picture_preview', 2147483647, 0, 2),
+('bx_person_add', 'delete_confirm', 2147483647, 0, 3),
+('bx_person_add', 'cover', 2147483647, 0, 4),
+('bx_person_add', 'picture', 2147483647, 1, 5),
+('bx_person_add', 'fullname', 2147483647, 1, 6),
+('bx_person_add', 'sex', 2147483647, 1, 7),
+('bx_person_add', 'do_submit', 2147483647, 1, 8),
+('bx_person_delete', 'cover_preview', 2147483647, 0, 0),
+('bx_person_delete', 'picture_preview', 2147483647, 0, 0),
 ('bx_person_delete', 'delete_confirm', 2147483647, 1, 0),
+('bx_person_delete', 'cover', 2147483647, 0, 0),
+('bx_person_delete', 'picture', 2147483647, 0, 0),
 ('bx_person_delete', 'do_submit', 2147483647, 1, 1),
 ('bx_person_delete', 'fullname', 2147483647, 0, 2),
 ('bx_person_delete', 'sex', 2147483647, 0, 3),
-('bx_person_edit', 'delete_confirm', 2147483647, 0, 1),
-('bx_person_edit', 'cover', 2147483647, 0, 2),
-('bx_person_edit', 'picture', 2147483647, 1, 3),
-('bx_person_edit', 'fullname', 2147483647, 1, 4),
-('bx_person_edit', 'sex', 2147483647, 1, 5),
-('bx_person_edit', 'do_submit', 2147483647, 1, 6),
-('bx_person_edit_cover', 'cover', 2147483647, 1, 1),
-('bx_person_edit_cover', 'do_submit', 2147483647, 1, 2),
-('bx_person_view', 'delete_confirm', 2147483647, 0, 1),
-('bx_person_view', 'picture', 2147483647, 0, 2),
-('bx_person_view', 'cover', 2147483647, 0, 3),
-('bx_person_view', 'fullname', 2147483647, 1, 4),
-('bx_person_view', 'sex', 2147483647, 1, 5),
-('bx_person_view', 'do_submit', 2147483647, 0, 6);
+('bx_person_edit', 'cover_preview', 2147483647, 0, 1),
+('bx_person_edit', 'delete_confirm', 2147483647, 0, 2),
+('bx_person_edit', 'cover', 2147483647, 0, 3),
+('bx_person_edit', 'picture_preview', 2147483647, 1, 4),
+('bx_person_edit', 'picture', 2147483647, 1, 5),
+('bx_person_edit', 'fullname', 2147483647, 1, 6),
+('bx_person_edit', 'sex', 2147483647, 1, 7),
+('bx_person_edit', 'do_submit', 2147483647, 1, 8),
+('bx_person_edit_cover', 'delete_confirm', 2147483647, 0, 1),
+('bx_person_edit_cover', 'fullname', 2147483647, 0, 2),
+('bx_person_edit_cover', 'picture', 2147483647, 0, 3),
+('bx_person_edit_cover', 'picture_preview', 2147483647, 0, 4),
+('bx_person_edit_cover', 'sex', 2147483647, 0, 5),
+('bx_person_edit_cover', 'cover_preview', 2147483647, 1, 6),
+('bx_person_edit_cover', 'cover', 2147483647, 1, 7),
+('bx_person_edit_cover', 'do_submit', 2147483647, 1, 8),
+('bx_person_view', 'cover_preview', 2147483647, 0, 1),
+('bx_person_view', 'picture_preview', 2147483647, 0, 2),
+('bx_person_view', 'delete_confirm', 2147483647, 0, 3),
+('bx_person_view', 'picture', 2147483647, 0, 4),
+('bx_person_view', 'cover', 2147483647, 0, 5),
+('bx_person_view', 'do_submit', 2147483647, 0, 6),
+('bx_person_view', 'fullname', 2147483647, 1, 7),
+('bx_person_view', 'sex', 2147483647, 1, 8);
+
 
 -- STUDIO PAGE & WIDGET
 

+ 1 - 5
modules/boonex/persons/install/sql/uninstall.sql

@@ -8,7 +8,6 @@ DELETE FROM sys_profiles WHERE `type` = 'bx_persons';
 
 -- TODO: delete picture files as well
 DROP TABLE IF EXISTS `bx_persons_pictures`; 
-DROP TABLE IF EXISTS `bx_persons_pictures_covers`; 
 DROP TABLE IF EXISTS `bx_persons_pictures_resized`;
 
 -- FORMS
@@ -19,10 +18,7 @@ DELETE FROM `sys_form_displays` WHERE `module` = 'bx_persons';
 
 DELETE FROM `sys_form_inputs` WHERE `module` = 'bx_persons';
 
-DELETE FROM `sys_form_display_inputs` WHERE `display_name`='bx_person_add';
-DELETE FROM `sys_form_display_inputs` WHERE `display_name`='bx_person_delete';
-DELETE FROM `sys_form_display_inputs` WHERE `display_name`='bx_person_edit';
-DELETE FROM `sys_form_display_inputs` WHERE `display_name`='bx_person_view';
+DELETE FROM `sys_form_display_inputs` WHERE `display_name` IN('bx_person_add', 'bx_person_delete', 'bx_person_edit', 'bx_person_edit_cover', 'bx_person_view');
 
 -- STUDIO PAGE & WIDGET
 

+ 38 - 17
modules/boonex/persons/template/cover.html

@@ -1,8 +1,8 @@
 
 <div class="bx-persons-cover">
-    <a class="bx-persons-cover-image bx-def-round-corners" href="__cover_href__" onclick="bx_persons_popup_cover()" style="background-image:url(__cover_url__)">&nbsp;</a>
+    <a class="bx-persons-cover-image bx-def-round-corners" href="__cover_href__" onclick="bx_persons_popup('bx-persons-popup-cover', '__cover_url__')" style="background-image:url(__cover_url__)">&nbsp;</a>
     <div class="bx-persons-cover-info bx-def-padding">
-        <img class="bx-def-margin-right bx-def-round-corners" src="__preview_url__" />
+        <a href="__picture_href__" onclick="bx_persons_popup('bx-persons-popup-picture', '__picture_url__')"><img class="bx-def-margin-right bx-def-round-corners" src="__picture_preview_url__" /></a>
         <h1 class="bx-def-margin-sec-bottom bx-def-margin-sec-top">__title__</h1>
     </div>
 </div>
@@ -11,29 +11,50 @@
     __cover_popup__
 </div>
 
+<div id="bx-persons-popup-picture" style="display:none;">
+    __picture_popup__
+</div>
+
 <script>
-    function bx_persons_popup_cover () {
-        var w = $(window).width(),
+    function bx_persons_popup (sId, sUrl) {
+        var k = .95,
+            w = $(window).width(),
             h = $(window).height(),
             eImg = new Image();
 
-        if (!$('#bx-persons-popup-cover-image').size())
+        if (!$('#' + sId + ' .bx-persons-popup-image').size())
             return;
 
-        eImg.src = '__cover_url__';
+        eImg.src = sUrl;
 
-        if (eImg.width > eImg.height && eImg.width > w * .9) {
-            $('#bx-persons-popup-cover-image').css({
-                width: '' + parseInt(w * .9) + 'px',
-                height: 'auto'
-            });
-        } else if (eImg.height > eImg.width && eImg.height > h * .9) {
-            $('#bx-persons-popup-cover-image').css({
-                width: 'auto',
-                height: '' + parseInt(h * .9) + 'px'
+        $(eImg).on('load', function () {
+
+            // fit image into the browser window
+            if ((w * k - eImg.width) < (h * k - eImg.height)) {
+                $('#' + sId + ' .bx-persons-popup-image').css({
+                    width: '' + (eImg.width > w * k ? parseInt(w * k) : eImg.width) + 'px',
+                    height: 'auto'
+                });
+            } else {
+                $('#' + sId + ' .bx-persons-popup-image').css({
+                    width: 'auto',
+                    height: '' + (eImg.height > h * k ? parseInt(h * k) : eImg.height) + 'px',
+                });
+            }
+
+            // show popup
+            $('#' + sId).dolPopup();
+
+            // hide popup upon clicking/tapping on the image
+            var fCallback = function (e) {
+                e.stopPropagation();
+                $('#' + sId).dolPopupHide();
+            };
+            $('#' + sId + ' .bx-persons-popup-image').on({
+                click: fCallback,
+                touchend: fCallback
             });
-        }
 
-        $('#bx-persons-popup-cover').dolPopup();
+        });
     }
 </script>

+ 0 - 6
modules/boonex/persons/template/cover_popup.html

@@ -1,6 +0,0 @@
-<div id="bx-persons-popup-cover-wrapper">
-    <bx_if:owner>
-        <div id="bx-persons-popup-cover-btn" class="bx-def-padding"><a class="bx-btn" href="__change_cover_url__"><bx_text:_bx_persons_txt_change_cover /></a></div>
-    </bx_if:owner>
-    <img id="bx-persons-popup-cover-image" src="__cover_url__" />
-</div>

+ 2 - 2
modules/boonex/persons/template/css/main.css

@@ -87,11 +87,11 @@
     text-shadow: 0px 0px 2px #000;
 }
 
-#bx-persons-popup-cover-wrapper {
+.bx-persons-popup-wrapper {
     position:relative;
 }
 
-#bx-persons-popup-cover-btn {
+.bx-persons-popup-btn {
     position:absolute;
     top:0;
     right:0;

+ 6 - 0
modules/boonex/persons/template/image_popup.html

@@ -0,0 +1,6 @@
+<div class="bx-persons-popup-wrapper">
+    <bx_if:owner>
+        <div class="bx-persons-popup-btn bx-def-padding"><a class="bx-btn" href="__change_image_url__"><bx_text:_bx_persons_txt_change_image /></a></div>
+    </bx_if:owner>
+    <img class="bx-persons-popup-image" src="__image_url__" />
+</div>

+ 6 - 0
modules/boonex/persons/template/picture_preview.html

@@ -0,0 +1,6 @@
+<bx_if:picture>
+    <img class="bx-def-round-corners" src="__picture_url__" />
+</bx_if:picture>
+<bx_if:no_picture>
+    <i class="bx-def-font-small"><bx_text:_bx_persons_txt_no_picture_uploaded /></i>
+</bx_if:no_picture>