Browse Source

Ticket #2103 - Categories builder in Studio.

AntonLV 7 years ago
parent
commit
27d037f9ac

+ 19 - 8
modules/boonex/directory/classes/BxDirConfig.php

@@ -28,13 +28,14 @@ class BxDirConfig extends BxBaseModTextConfig
             // database tables
             'TABLE_ENTRIES' => $aModule['db_prefix'] . 'entries',
             'TABLE_ENTRIES_FULLTEXT' => 'title_text',
+            'TABLE_CATEGORIES' => $aModule['db_prefix'] . 'categories',
+            'TABLE_CATEGORIES_TYPES' => $aModule['db_prefix'] . 'categories_types',
 
             // database fields
             'FIELD_ID' => 'id',
             'FIELD_AUTHOR' => 'author',
             'FIELD_ADDED' => 'added',
             'FIELD_CHANGED' => 'changed',
-            'FIELD_PUBLISHED' => 'published',
             'FIELD_TITLE' => 'title',
             'FIELD_TEXT' => 'text',
             'FIELD_TEXT_ID' => 'ad-text',
@@ -55,7 +56,6 @@ class BxDirConfig extends BxBaseModTextConfig
             'FIELD_LABELS' => 'labels',
             'FIELD_ANONYMOUS' => 'anonymous',
             'FIELDS_WITH_KEYWORDS' => 'auto', // can be 'auto', array of fields or comma separated string of field names, works only when OBJECT_METATAGS is specified
-            'FIELD_DISABLE_COMMENTS' => 'disable_comments',
             
             // page URIs
             'URI_VIEW_ENTRY' => 'view-ad',
@@ -78,7 +78,7 @@ class BxDirConfig extends BxBaseModTextConfig
             'PARAM_SEARCHABLE_FIELDS' => 'bx_directory_searchable_fields',
             'PARAM_PER_PAGE_BROWSE_SHOWCASE' => 'bx_directory_per_page_browse_showcase',
             'PARAM_LABELS' => 'bx_directory_labels',
-            
+            'PARAM_CATEGORY_LEVEL_MAX' => 1,
 
             // objects
             'OBJECT_STORAGE' => 'bx_directory_covers',
@@ -110,10 +110,14 @@ class BxDirConfig extends BxBaseModTextConfig
             'OBJECT_COMMENTS' => 'bx_directory',
             'OBJECT_CATEGORY' => 'bx_directory_cats',
             'OBJECT_PRIVACY_VIEW' => 'bx_directory_allow_view_to',
+            'OBJECT_FORM_CATEGORY' => 'bx_directory_category',
+            'OBJECT_FORM_CATEGORY_DISPLAY_ADD' => 'bx_directory_category_add',
+            'OBJECT_FORM_CATEGORY_DISPLAY_EDIT' => 'bx_directory_category_edit',
+            'OBJECT_FORM_CATEGORY_DISPLAY_DELETE' => 'bx_directory_category_delete',
             'OBJECT_FORM_ENTRY' => 'bx_directory',
-            'OBJECT_FORM_ENTRY_DISPLAY_VIEW' => 'bx_directory_entry_view',
+            'OBJECT_FORM_ENTRY_DISPLAY_VIEW' => '',
             'OBJECT_FORM_ENTRY_DISPLAY_ADD' => 'bx_directory_entry_add',
-            'OBJECT_FORM_ENTRY_DISPLAY_EDIT' => 'bx_directory_entry_edit',
+            'OBJECT_FORM_ENTRY_DISPLAY_EDIT' => '',
             'OBJECT_FORM_ENTRY_DISPLAY_DELETE' => 'bx_directory_entry_delete',
             'OBJECT_FORM_POLL' => 'bx_directory_poll',
             'OBJECT_FORM_POLL_DISPLAY_ADD' => 'bx_directory_poll_add',
@@ -126,6 +130,7 @@ class BxDirConfig extends BxBaseModTextConfig
             'OBJECT_MENU_SUBMENU_VIEW_ENTRY_MAIN_SELECTION' => 'directory-home', // first item in view entry submenu from main module submenu
             'OBJECT_MENU_SNIPPET_META' => 'bx_directory_snippet_meta', // menu for snippet meta info
             'OBJECT_MENU_MANAGE_TOOLS' => 'bx_directory_menu_manage_tools', //manage menu in content administration tools
+            'OBJECT_GRID_CATEGORIES' => 'bx_directory_categories',
             'OBJECT_GRID_ADMINISTRATION' => 'bx_directory_administration',
             'OBJECT_GRID_COMMON' => 'bx_directory_common',
             'OBJECT_UPLOADERS' => array('bx_directory_simple', 'bx_directory_html5'),
@@ -159,19 +164,25 @@ class BxDirConfig extends BxBaseModTextConfig
                 'txt_err_cannot_perform_action' => '_bx_directory_txt_err_cannot_perform_action',
                 'txt_poll_answer_vote_do_by' => '_bx_directory_txt_poll_answer_vote_do_by',
                 'txt_poll_answer_vote_counter' => '_bx_directory_txt_poll_answer_vote_counter',
-                'txt_poll_answer_vote_percent' => '_bx_directory_txt_poll_answer_vote_percent'
+                'txt_poll_answer_vote_percent' => '_bx_directory_txt_poll_answer_vote_percent',
+                'txt_display_add' => '_bx_directory_txt_display_title_add',
+                'txt_display_edit' => '_bx_directory_txt_display_title_edit',
+                'txt_display_view' => '_bx_directory_txt_display_title_view',
             ),
         ));
         
         $this->_aJsClasses = array_merge($this->_aJsClasses, array(
-            'manage_tools' => 'BxDirManageTools'
+            'manage_tools' => 'BxDirManageTools',
+            'studio' => 'BxDirStudio'
         ));
 
         $this->_aJsObjects = array_merge($this->_aJsObjects, array(
-            'manage_tools' => 'oBxDirManageTools'
+            'manage_tools' => 'oBxDirManageTools',
+            'studio' => 'oBxDirStudio'
         ));
 
         $this->_aGridObjects = array(
+            'categories' => $this->CNF['OBJECT_GRID_CATEGORIES'],
             'common' => $this->CNF['OBJECT_GRID_COMMON'],
             'administration' => $this->CNF['OBJECT_GRID_ADMINISTRATION'],
         );

+ 129 - 10
modules/boonex/directory/classes/BxDirDb.php

@@ -19,21 +19,140 @@ class BxDirDb extends BxBaseModTextDb
         parent::__construct($oConfig);
     }
 
-    public function publish()
+    public function insertCategoryType($aParamsSet)
     {
-        $CNF = $this->_oConfig->CNF;
+        $CNF = &$this->_oConfig->CNF;
 
-        $aEntries = $this->getAll("SELECT `id`, `" . $CNF['FIELD_PUBLISHED'] . "`, from_unixtime(`" . $CNF['FIELD_PUBLISHED'] . "`)  FROM `" . $CNF['TABLE_ENTRIES'] . "` WHERE `" . $CNF['FIELD_STATUS'] . "` = 'awaiting'");
-        if(empty($aEntries) || !is_array($aEntries))
+        if(empty($aParamsSet))
+            return 0;
+
+        if((int)$this->query("INSERT INTO `" . $CNF['TABLE_CATEGORIES_TYPES'] . "` SET " . $this->arrayToSQL($aParamsSet)) <= 0)
+            return 0;
+
+        return (int)$this->lastId();
+    }
+
+    public function deleteCategoryType($aParamsWhere)
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        if(empty($aParamsWhere))
+            return false;
+
+        return (int)$this->query("DELETE FROM `" . $CNF['TABLE_CATEGORIES_TYPES'] . "` WHERE " . $this->arrayToSQL($aParamsWhere, ' AND ')) <= 0;
+    }
+
+    public function getCategoryTypes($aParams = array())
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $aMethod = array('name' => 'getAll', 'params' => array(0 => 'query'));
+
+        $sSelectClause = "`tct`.*";
+        $sWhereClause = $sOrderClause = "";
+        
+        switch($aParams['type']) {
+            case 'id':
+                $aMethod['name'] = 'getRow';
+                $aMethod['params'][1] = array(
+                    'id' => $aParams['id']
+                );
+
+                $sWhereClause = " AND `tct`.`id`=:id";
+                break;
+            
+            case 'all':
+                break;
+        }
+
+        if(!empty($sOrderClause))
+            $sOrderClause = "ORDER BY " . $sOrderClause;
+
+        $aMethod['params'][0] = "SELECT " . $sSelectClause . " 
+            FROM `" . $CNF['TABLE_CATEGORIES_TYPES'] . "` AS `tct`
+            WHERE 1" . $sWhereClause . " " . $sOrderClause;
+
+        return call_user_func_array(array($this, $aMethod['name']), $aMethod['params']);
+    }
+    
+    public function getCategories($aParams = array())
+    {
+        $CNF = &$this->_oConfig->CNF;
+
+        $aMethod = array('name' => 'getAll', 'params' => array(0 => 'query'));
+
+        $sSelectClause = "`tc`.*";
+        $sWhereClause = "";
+        $sOrderClause = "`tc`.`order` ASC";
+
+        switch($aParams['type']) {
+            case 'id':
+                $aMethod['name'] = 'getRow';
+                $aMethod['params'][1] = array(
+                    'id' => $aParams['id']
+                );
+
+                $sWhereClause = " AND `tc`.`id`=:id";
+                break;
+
+            case 'parent_id':
+                $aMethod['params'][1] = array(
+                    'parent_id' => $aParams['parent_id']
+                );
+
+            $sWhereClause = " AND `tc`.`parent_id`=:parent_id";
+            break;
+
+            case 'parent_id_count':
+                $aMethod['name'] = 'getOne';
+                $aMethod['params'][1] = array(
+                    'parent_id' => $aParams['parent_id']
+                );
+
+            $sSelectClause = "COUNT(`tc`.`id`)";
+            $sWhereClause = " AND `tc`.`parent_id`=:parent_id";
+            break;
+        
+            case 'parent_id_order':
+                $aMethod['name'] = 'getOne';
+                $aMethod['params'][1] = array(
+                    'parent_id' => $aParams['parent_id']
+                );
+
+            $sSelectClause = "MAX(`tc`.`order`)";
+            $sWhereClause = " AND `tc`.`parent_id`=:parent_id";
+            break;
+        }
+
+        if(!empty($sOrderClause))
+            $sOrderClause = "ORDER BY " . $sOrderClause;
+
+        $aMethod['params'][0] = "SELECT " . $sSelectClause . " 
+            FROM `" . $CNF['TABLE_CATEGORIES'] . "` AS `tc`
+            WHERE 1" . $sWhereClause . " " . $sOrderClause;
+
+        return call_user_func_array(array($this, $aMethod['name']), $aMethod['params']);
+    }
+
+    public function cloneDisplay($sDisplayName, $sNewDisplayName, $sNewDisplayTitle)
+    {
+        $aDisplay = $this->getRow("SELECT * FROM `sys_form_displays` WHERE `display_name`=:display_name", array('display_name' => $sDisplayName));
+        if(empty($aDisplay) || !is_array($aDisplay))
             return false;
+        
+        unset($aDisplay['id']);
+        $aDisplay['display_name'] = $sNewDisplayName;
+        $aDisplay['title'] = $sNewDisplayTitle;
 
-        $iNow = time();
-        $aResult = array();
-        foreach($aEntries as $aEntry)
-            if($aEntry[$CNF['FIELD_PUBLISHED']] <= $iNow) 
-                $aResult[] = $aEntry[$CNF['FIELD_ID']];
+        if((int)$this->query("INSERT INTO `sys_form_displays` SET " . $this->arrayToSQL($aDisplay)) <= 0)
+            return false;
+
+        $iNewDisplayId = (int)$this->lastId();
+
+        if((int)$this->query("INSERT INTO `sys_form_display_inputs` SELECT NULL, '" . $sNewDisplayName . "', `input_name`, `visible_for_levels`, `active`, `order` FROM `sys_form_display_inputs` WHERE `display_name`=:display_name AND `active`='1'", array('display_name' => $sDisplayName)) <= 0)
+            return false;
 
-        return count($aResult) == (int)$this->query("UPDATE `" . $CNF['TABLE_ENTRIES'] . "` SET `" . $CNF['FIELD_ADDED'] . "`=`" . $CNF['FIELD_PUBLISHED'] . "`, `" . $CNF['FIELD_CHANGED'] . "`=`" . $CNF['FIELD_PUBLISHED'] . "`, `" . $CNF['FIELD_STATUS'] . "` = 'active' WHERE `id` IN (" . $this->implode_escape($aResult) . ")") ? $aResult : false;
+        return true;
     }
 }
 

+ 43 - 0
modules/boonex/directory/classes/BxDirFormCategory.php

@@ -0,0 +1,43 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Directory Directory
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+/**
+ * Create/Edit category form
+ */
+class BxDirFormCategory extends BxTemplStudioFormView
+{
+    protected $_sModule;
+    protected $_oModule;
+
+    public function __construct($aInfo, $oTemplate = false)
+    {
+        $this->_sModule = 'bx_directory';
+        $this->_oModule = BxDolModule::getInstance($this->_sModule);
+
+        parent::__construct($aInfo, $oTemplate);
+
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        if(isset($this->aInputs['parent_id'])) {
+            $this->aInputs['parent_id']['values'] = array();            
+        }
+
+        if(isset($this->aInputs['type'])) {
+            $this->aInputs['type']['values'] = array();
+
+            $aTypes = $this->_oModule->_oDb->getCategoryTypes(array('type' => 'all'));
+            foreach($aTypes as $aType)
+                $this->aInputs['type']['values'][] = array('key' => $aType['id'], 'value' => _t($aType['title']));
+        }
+    }
+}
+
+/** @} */

+ 0 - 35
modules/boonex/directory/classes/BxDirFormEntry.php

@@ -100,30 +100,6 @@ class BxDirFormEntry extends BxBaseModTextFormEntry
     {
         $CNF = &$this->_oModule->_oConfig->CNF;
 
-        if(isset($CNF['FIELD_ADDED']) && empty($aValsToAdd[$CNF['FIELD_ADDED']])) {
-            $iAdded = 0;
-            if(isset($this->aInputs[$CNF['FIELD_ADDED']]))
-                $iAdded = $this->getCleanValue($CNF['FIELD_ADDED']);
-            
-            if(empty($iAdded))
-                 $iAdded = time();
-
-            $aValsToAdd[$CNF['FIELD_ADDED']] = $iAdded;
-        }
-
-        if(empty($aValsToAdd[$CNF['FIELD_PUBLISHED']])) {
-            $iPublished = 0;
-            if(isset($this->aInputs[$CNF['FIELD_PUBLISHED']]))
-                $iPublished = $this->getCleanValue($CNF['FIELD_PUBLISHED']);
-                
-             if(empty($iPublished))
-                 $iPublished = time();
-
-             $aValsToAdd[$CNF['FIELD_PUBLISHED']] = $iPublished;
-        }
-
-        $aValsToAdd[$CNF['FIELD_STATUS']] = $aValsToAdd[$CNF['FIELD_PUBLISHED']] > $aValsToAdd[$CNF['FIELD_ADDED']] ? 'awaiting' : 'active';
-
         $iContentId = parent::insert ($aValsToAdd, $isIgnore);
         if(!empty($iContentId))
             $this->processFiles($CNF['FIELD_COVER'], $iContentId, true);
@@ -135,17 +111,6 @@ class BxDirFormEntry extends BxBaseModTextFormEntry
     {
         $CNF = &$this->_oModule->_oConfig->CNF;
 
-        if(empty($aValsToAdd[$CNF['FIELD_PUBLISHED']]) && isset($this->aInputs[$CNF['FIELD_PUBLISHED']])) {
-            $iPublished = $this->getCleanValue($CNF['FIELD_PUBLISHED']);
-            if(empty($iPublished))
-                $iPublished = time();
-
-            $aValsToAdd[$CNF['FIELD_PUBLISHED']] = $iPublished;
-        }
-
-        if(isset($aValsToAdd[$CNF['FIELD_PUBLISHED']]))
-            $aValsToAdd[$CNF['FIELD_STATUS']] = $aValsToAdd[$CNF['FIELD_PUBLISHED']] > time() ? 'awaiting' : 'active';
-
         $iResult = parent::update ($iContentId, $aValsToAdd, $aTrackTextFieldsChanges);
 
         $this->processFiles($CNF['FIELD_COVER'], $iContentId, false);

+ 286 - 0
modules/boonex/directory/classes/BxDirGridCategories.php

@@ -0,0 +1,286 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Directory Directory
+ * @ingroup     UnaModules
+ * 
+ * @{
+ */
+
+class BxDirGridCategories extends BxTemplGrid
+{
+    protected $_sModule;
+    protected $_oModule;
+
+    protected $_sBaseUrl;
+
+    protected $_iParentId;
+    protected $_aParentInfo;
+    
+    public function __construct ($aOptions, $oTemplate = false)
+    {
+        parent::__construct ($aOptions, $oTemplate);
+        
+        $this->_sModule = 'bx_directory';
+        $this->_oModule = BxDolModule::getInstance($this->_sModule);
+
+        $this->_sBaseUrl = bx_append_url_params(BX_DOL_URL_STUDIO . 'module.php', array(
+            'name' => $this->_sModule, 
+            'page' => 'categories'
+        ));
+
+        $this->_iParentId = bx_get('parent_id') !== false ? (int)bx_get('parent_id') : 0;
+        $this->_aQueryAppend['parent_id'] = $this->_iParentId;
+
+        if(!empty($this->_iParentId)) 
+            $this->_aParentInfo = $this->_oModule->_oDb->getCategories(array('type' => 'id', 'id' => $this->_iParentId));
+    }
+
+    public function performActionAdd()
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        $sAction = 'add';
+
+        $oForm = $this->_getFormObject($sAction);
+        $oForm->initChecker();
+
+        if($oForm->isSubmittedAndValid()) {
+            $aValsToAdd = array('active' => 1);
+
+            $iParentId = (int)$oForm->getCleanValue('parent_id');
+            if($iParentId != 0) {
+                $aParentInfo = $this->_oModule->_oDb->getCategories(array('type' => 'id', 'id' => $iParentId));
+
+                $aValsToAdd['level'] = $aParentInfo['level'] + 1;
+                $aValsToAdd['order'] = $this->_oModule->_oDb->getCategories(array('type' => 'parent_id_order', 'parent_id' => $iParentId)) + 1;
+            }
+            else {
+                $aValsToAdd['level'] = 0;
+                $aValsToAdd['order'] = $this->_oModule->_oDb->getCategories(array('type' => 'parent_id_order', 'parent_id' => 0)) + 1;
+            }
+
+            $oLanguage = BxDolStudioLanguagesUtils::getInstance();
+            $aLanguages = $oLanguage->getLanguagesExt();
+            $sLanguageCurrent = $oLanguage->getCurrentLangName(false);
+
+            $sTitle = BxDolForm::getSubmittedValue('title-' . $sLanguageCurrent, $oForm->aFormAttrs['method']);
+            $sName = uriGenerate(strtolower($sTitle), $CNF['TABLE_CATEGORIES'], 'name', 'cat', '_');
+
+            $aValsToAdd['name'] = $sName;
+            BxDolForm::setSubmittedValue('title', '_bx_directory_cat_' . $sName, $oForm->aFormAttrs['method']);
+            BxDolForm::setSubmittedValue('text', '_bx_directory_cat_' . $sName, $oForm->aFormAttrs['method']);
+
+            if($oForm->getCleanValue('type_clone') == 'on') {
+                $sTypeNewTitle = BxDolForm::getSubmittedValue('type_title-' . $sLanguageCurrent, $oForm->aFormAttrs['method']);
+                if(empty($sTypeNewTitle))
+                    $sTypeNewTitle = $sTitle;
+
+                $sTypeNewName = uriGenerate(strtolower($sTypeNewTitle), $CNF['TABLE_CATEGORIES_TYPES'], 'name', 'cat_type', '_');
+
+                $iType = (int)$oForm->getCleanValue('type');
+                $aType = $this->_oModule->_oDb->getCategoryTypes(array('type' => 'id', 'id' => $iType));
+
+                $aTypeNew = array('name' => $sTypeNewName, 'title' => '_bx_directory_cat_type_' . $sTypeNewName);
+                foreach($aLanguages as $sLanguage => $aLanguage) {
+                    $sTypeNewTitleLang = bx_process_input(BxDolForm::getSubmittedValue('type_title-' . $sLanguage, $oForm->aFormAttrs['method']));
+                    if(!empty($sTypeNewTitleLang))
+                        $sTypeNewKeys[$aTypeNew['title']][$aLanguage['id']] = $sTypeNewTitleLang;
+                }
+
+                $bDisplayCloned = true;
+                $aDisplayTypes = array('add', 'edit', 'view');
+                foreach($aDisplayTypes as $sDisplayType) {
+                    $sDisplay = 'display_' . $sDisplayType;
+                    if(empty($aType[$sDisplay])) {
+                        $aTypeNew[$sDisplay] = '';
+                        continue;
+                    }
+
+                    $sDisplayNewName = 'bx_directory_entry_' . $sTypeNewName . '_' . $sDisplayType;
+                    $sDisplayNewTitle = '_bx_directory_form_display_' . $sTypeNewName . '_' . $sDisplayType;
+
+                    if(!$this->_oModule->_oDb->cloneDisplay($aType[$sDisplay], $sDisplayNewName, $sDisplayNewTitle)) {
+                        $bDisplayCloned = false;
+                        break;
+                    }
+
+                    $aTypeNew[$sDisplay] = $sDisplayNewName;
+                    $sTypeNewKeys[$sDisplayNewTitle] = _t($CNF['T']['txt_display_' . $sDisplayType], $sTypeNewTitle);
+                }
+
+                if($bDisplayCloned && ($iTypeNewId = $this->_oModule->_oDb->insertCategoryType($aTypeNew)) !== 0) {
+                    BxDolForm::setSubmittedValue('type', $iTypeNewId, $oForm->aFormAttrs['method']);
+
+                    foreach($sTypeNewKeys as $sKey => $mixedString)
+                        $oLanguage->addLanguageString($sKey, $mixedString, 0, 0, false);
+                    $oLanguage->compileLanguage();
+                }
+            }
+
+            unset($oForm->aInputs['type_clone'], $oForm->aInputs['type_title']);
+
+            $iId = (int)$oForm->insert($aValsToAdd);
+            if($iId != 0)
+                $aRes = array('grid' => $this->getCode(false), 'blink' => $iId);
+            else
+                $aRes = array('msg' => _t('_bx_directory_grid_action_err_add_category'));
+
+            echoJson($aRes);
+        }
+        else {
+            $sContent = BxTemplStudioFunctions::getInstance()->popupBox($this->_sModule . '-category-add-popup', _t('_bx_directory_grid_popup_title_add'), $this->_oModule->_oTemplate->parseHtmlByName('category_form.html', array(
+                'form_id' => $oForm->aFormAttrs['id'],
+                'form' => $oForm->getCode(true),
+                'object' => $this->_sObject,
+                'action' => $sAction
+            )));
+
+            echoJson(array('popup' => array('html' => $sContent, 'options' => array('closeOnOuterClick' => false))));
+        }
+    }
+    
+    public function performActionEdit()
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        $sAction = 'edit';
+
+        $aIds = bx_get('ids');
+        if(!$aIds || !is_array($aIds)) {
+            $iId = (int)bx_get('id');
+            if(!$iId)
+                return false;
+
+            $aIds = array($iId);
+        }
+
+        $iId = $aIds[0];
+
+        $aCategory = $this->_oModule->_oDb->getCategories(array('type' => 'id', 'id' => $iId));
+        if(empty($aCategory) || !is_array($aCategory))
+            return echoJson(array());
+
+        $oForm = $this->_getFormObject($sAction, $aCategory);
+        $oForm->initChecker($aCategory);
+
+        if($oForm->isSubmittedAndValid()) {
+            $aValsToAdd = array('active' => 1);
+
+            $iParentId = (int)$oForm->getCleanValue('parent_id');
+            if($iParentId != 0) {
+                $aParentInfo = $this->_oModule->_oDb->getCategories(array('type' => 'id', 'id' => $iParentId));
+
+                $aValsToAdd['level'] = $aParentInfo['level'] + 1;
+                $aValsToAdd['order'] = $this->_oModule->_oDb->getCategories(array('type' => 'parent_id_order', 'parent_id' => $iParentId)) + 1;
+            }
+            else {
+                $aValsToAdd['level'] = 0;
+                $aValsToAdd['order'] = $this->_oModule->_oDb->getCategories(array('type' => 'parent_id_order', 'parent_id' => 0)) + 1;
+            }
+                
+            $iId = (int)$oForm->update($iId, $aValsToAdd);
+            if($iId != 0)
+                $aRes = array('grid' => $this->getCode(false), 'blink' => $iId);
+            else
+                $aRes = array('msg' => _t('_bx_directory_grid_action_err_edit_category'));
+
+            echoJson($aRes);
+        }
+        else {
+            $sContent = BxTemplStudioFunctions::getInstance()->popupBox($this->_sModule . '-category-edit-popup', _t('_bx_directory_grid_popup_title_edit', _t($aCategory['title'])), $this->_oModule->_oTemplate->parseHtmlByName('category_form.html', array(
+                'form_id' => $oForm->aFormAttrs['id'],
+                'form' => $oForm->getCode(true),
+                'object' => $this->_sObject,
+                'action' => $sAction
+            )));
+
+            echoJson(array('popup' => array('html' => $sContent, 'options' => array('closeOnOuterClick' => false))));
+        }
+    }
+
+    protected function _getFormObject($sAction, $aCategory = array())
+    {
+        $CNF = &$this->_oModule->_oConfig->CNF;
+
+        $oForm = BxDolForm::getObjectInstance($CNF['OBJECT_FORM_CATEGORY'], $CNF['OBJECT_FORM_CATEGORY_DISPLAY_' . strtoupper($sAction)]);
+        $oForm->aFormAttrs['action'] = BX_DOL_URL_ROOT . 'grid.php?o=' . $this->_sObject . '&a=' . $sAction . '&parent_id=' . $this->_iParentId;
+        if(!empty($aCategory['id']))
+            $oForm->aFormAttrs['action'] .= '&id=' . $aCategory['id'];
+
+        if(isset($oForm->aInputs['parent_id'])) {
+            if(empty($this->_iParentId)) {
+                $oForm->aInputs['parent_id']['values'][] = array('key' => 0, 'value' => _t('_bx_directory_form_category_input_parent_id_empty'));
+
+                $aCategories = $this->_oModule->_oDb->getCategories(array('type' => 'parent_id', 'parent_id' => $this->_iParentId));
+                foreach($aCategories as $aCategory)
+                    $oForm->aInputs['parent_id']['values'][] = array(
+                        'key' => $aCategory['id'], 
+                        'value' => _t($aCategory['title'])
+                    );
+            }
+            else {
+                $oForm->aInputs['parent_id']['type'] = 'hidden';
+                $oForm->aInputs['parent_id']['value'] = $this->_iParentId;
+            }
+        }
+        
+        return $oForm;
+    }
+
+    protected function _getCellIcon ($mixedValue, $sKey, $aField, $aRow)
+    {
+        $mixedValue = $this->_oTemplate->getIcon($mixedValue, array('class' => 'bx-def-border'));
+
+        return parent::_getCellDefault($mixedValue, $sKey, $aField, $aRow);
+    }
+    
+    protected function _getCellSubcategories ($mixedValue, $sKey, $aField, $aRow)
+    {
+        $sContent = _t('_bx_directory_grid_column_value_subcategories', $this->_oModule->_oDb->getCategories(array('type' => 'parent_id_count', 'parent_id' => $aRow['id'])));
+
+        $mixedValue = $this->_oTemplate->parseLink(bx_append_url_params($this->_sBaseUrl, array('parent_id' => $aRow['id'])), $sContent, array(
+            'title' => _t('_bx_directory_grid_column_info_subcategories')
+        ));
+
+        return parent::_getCellDefault($mixedValue, $sKey, $aField, $aRow);
+    }
+
+    protected function _addJsCss()
+    {
+        parent::_addJsCss();
+        $this->_oModule->_oTemplate->addStudioJs(array('jquery.form.min.js', 'studio.js'));
+
+        $oForm = new BxTemplStudioFormView(array());
+        $oForm->addCssJs();
+    }
+
+    protected function _isVisibleGrid ($a)
+    {
+        return isAdmin();
+    }
+
+    protected function _delete ($mixedId)
+    {
+        $sTable = $this->_aOptions['table'];
+        $sFieldId = $this->_aOptions['field_id'];
+        $aCategory = $this->_oModule->_oDb->getRow("SELECT * FROM `" . $sTable . "` WHERE `" . $sFieldId . "`=:id", array('id' => $mixedId));
+        if(!empty($aCategory['title'])) {
+            $oLanguage = BxDolStudioLanguagesUtils::getInstance();
+            $oLanguage->deleteLanguageString($aCategory['title']);
+            $oLanguage->deleteLanguageString($aCategory['text']);
+        }
+
+        return parent::_delete($mixedId);
+    }
+
+    protected function _getDataSql($sFilter, $sOrderField, $sOrderDir, $iStart, $iPerPage)
+    {
+        $this->_aOptions['source'] .= $this->_oModule->_oDb->prepareAsString(" AND `parent_id`=?", $this->_iParentId);
+        return parent::_getDataSql($sFilter, $sOrderField, $sOrderDir, $iStart, $iPerPage);
+    }
+}
+
+/** @} */

+ 2 - 57
modules/boonex/directory/classes/BxDirModule.php

@@ -17,66 +17,11 @@ class BxDirModule extends BxBaseModTextModule
     function __construct(&$aModule)
     {
         parent::__construct($aModule);
-
-        $CNF = &$this->_oConfig->CNF;
-        $this->_aSearchableNamesExcept = array_merge($this->_aSearchableNamesExcept, array(
-             $CNF['FIELD_PUBLISHED']
-        ));
     }
 
-    /**
-     * Entry post for Timeline module
-     */
-    public function serviceGetTimelinePost($aEvent, $aBrowseParams = array())
+    public function serviceCategoriesList($aParams = array())
     {
-        $CNF = &$this->_oConfig->CNF;
-
-        $aResult = parent::serviceGetTimelinePost($aEvent, $aBrowseParams);
-        if(empty($aResult) || !is_array($aResult) || empty($aResult['date']))
-            return $aResult;
-
-        $aContentInfo = $this->_oDb->getContentInfoById($aEvent['object_id']);
-        if($aContentInfo[$CNF['FIELD_PUBLISHED']] > $aResult['date'])
-            $aResult['date'] = $aContentInfo[$CNF['FIELD_PUBLISHED']];
-
-        return $aResult;
-    }
-
-    public function onPublished($iContentId)
-    {
-		$CNF = &$this->_oConfig->CNF;
-
-		$aContentInfo = $this->_oDb->getContentInfoById($iContentId);
-        if(!$aContentInfo)
-            return MsgBox(_t('_sys_txt_error_occured'));
-
-		$aParams = array('object_author_id' => $aContentInfo[$CNF['FIELD_AUTHOR']]);
-		if(isset($aContentInfo[$CNF['FIELD_ALLOW_VIEW_TO']]))
-			$aParams['privacy_view'] = $aContentInfo[$CNF['FIELD_ALLOW_VIEW_TO']];
-
-        bx_alert($this->getName(), 'added', $iContentId, false, $aParams);
-
-        return '';
-    }
-    
-    public function serviceCheckAllowedCommentsPost($iContentId, $sObjectComments) 
-    {
-		$CNF = &$this->_oConfig->CNF;
-		$aContentInfo = $this->_oDb->getContentInfoById($iContentId);
-		if ($aContentInfo[$CNF['FIELD_DISABLE_COMMENTS']] == 1)
-			return false;
-
-        return parent::serviceCheckAllowedCommentsPost($iContentId, $sObjectComments);
-    }
-	
-	public function serviceCheckAllowedCommentsView($iContentId, $sObjectComments) 
-    {
-        $CNF = &$this->_oConfig->CNF;
-		$aContentInfo = $this->_oDb->getContentInfoById($iContentId);
-		if ($aContentInfo[$CNF['FIELD_DISABLE_COMMENTS']] == 1)
-			return false;
-
-        return parent::serviceCheckAllowedCommentsView($iContentId, $sObjectComments);
+        return 'Categories would be here!';
     }
 }
 

+ 40 - 0
modules/boonex/directory/classes/BxDirStudioPage.php

@@ -0,0 +1,40 @@
+<?php defined('BX_DOL') or die('hack attempt');
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Directory Directory
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+define('BX_DOL_STUDIO_MOD_TYPE_CATEGORIES', 'categories');
+
+class BxDirStudioPage extends BxTemplStudioModule
+{
+    protected $_sModule;
+    protected $_oModule;
+
+    function __construct($sModule = "", $sPage = "")
+    {
+    	$this->_sModule = 'bx_directory';
+    	$this->_oModule = BxDolModule::getInstance($this->_sModule);
+
+        parent::__construct($sModule, $sPage);
+
+        $this->aMenuItems[] = array('name' => BX_DOL_STUDIO_MOD_TYPE_CATEGORIES, 'icon' => 'bars', 'title' => '_bx_directory_menu_item_title_categories');
+    }
+
+    protected function getCategories()
+    {
+        $oGrid = BxDolGrid::getObjectInstance($this->_oModule->_oConfig->CNF['OBJECT_GRID_CATEGORIES'], BxDolStudioTemplate::getInstance());
+        if(!$oGrid)
+            return '';
+
+        $this->_oModule->_oTemplate->addJs('studio');
+        return $this->_oModule->_oTemplate->getJsCode('studio') . $oGrid->getCode();
+    }
+}
+
+/** @} */

+ 117 - 45
modules/boonex/directory/install/langs/en.xml

@@ -10,22 +10,62 @@
     <string name="_bx_directory_option_rss_num"><![CDATA[Number of items in RSS feed]]></string>
     <string name="_bx_directory_option_searchable_fields"><![CDATA[Searchable fields for keyword search]]></string>
 
+    <string name="_bx_directory_form_category"><![CDATA[Category]]></string>
+    <string name="_bx_directory_form_category_display_add"><![CDATA[Add Category]]></string>
+    <string name="_bx_directory_form_category_display_edit"><![CDATA[Edit Category]]></string>
+    <string name="_bx_directory_form_category_display_delete"><![CDATA[Delete Category]]></string>
+    <string name="_bx_directory_form_category_input_sys_do_submit"><![CDATA[Submit]]></string>
+    <string name="_bx_directory_form_category_input_do_submit"><![CDATA[Submit]]></string>
+    <string name="_bx_directory_form_category_input_sys_do_cancel"><![CDATA[Cancel]]></string>
+    <string name="_bx_directory_form_category_input_do_cancel"><![CDATA[Cancel]]></string>
+    <string name="_bx_directory_form_category_input_sys_parent_id"><![CDATA[Parent]]></string>
+    <string name="_bx_directory_form_category_input_parent_id"><![CDATA[Parent category]]></string>
+    <string name="_bx_directory_form_category_input_parent_id_empty"><![CDATA[No parent]]></string>
+    <string name="_bx_directory_form_category_input_sys_title"><![CDATA[Title]]></string>
+    <string name="_bx_directory_form_category_input_title"><![CDATA[Title]]></string>
+    <string name="_bx_directory_form_category_input_title_err"><![CDATA[Title is essential. Please, fill in this field.]]></string>
+    <string name="_bx_directory_form_category_input_sys_text"><![CDATA[Text]]></string>
+    <string name="_bx_directory_form_category_input_text"><![CDATA[Text]]></string>
+    <string name="_bx_directory_form_category_input_sys_type"><![CDATA[Type]]></string>
+    <string name="_bx_directory_form_category_input_type"><![CDATA[Type]]></string>
+    <string name="_bx_directory_form_category_input_type_err"><![CDATA[Type is essential. Please, select a value for this field.]]></string>
+    <string name="_bx_directory_form_category_input_type_info"><![CDATA[Type determines a set of fields for entries in this category.]]></string>
+    <string name="_bx_directory_form_category_input_sys_type_clone"><![CDATA[Clone type]]></string>
+    <string name="_bx_directory_form_category_input_type_clone"><![CDATA[Clone type]]></string>
+    <string name="_bx_directory_form_category_input_sys_type_title"><![CDATA[Type title]]></string>
+    <string name="_bx_directory_form_category_input_type_title"><![CDATA[Type title]]></string>
+    <string name="_bx_directory_form_category_input_sys_icon"><![CDATA[Icon]]></string>
+    <string name="_bx_directory_form_category_input_icon"><![CDATA[Icon]]></string>
+    <string name="_bx_directory_form_category_input_sys_delete_confirm"><![CDATA[Delete confirmation]]></string>
+    <string name="_bx_directory_form_category_input_delete_confirm"><![CDATA[I am sure I want to delete this category]]></string>
+    <string name="_bx_directory_form_category_input_delete_confirm_info"><![CDATA[This action can not be undone]]></string>
+    <string name="_bx_directory_form_category_input_delete_confirm_error"><![CDATA[Please check this checkbox if you really want to delete the category]]></string>
+
     <string name="_bx_directory_form_entry"><![CDATA[Ads]]></string>
     <string name="_bx_directory_form_entry_display_add"><![CDATA[Add Ad]]></string>
-    <string name="_bx_directory_form_entry_display_edit"><![CDATA[Edit Ad]]></string>
     <string name="_bx_directory_form_entry_display_delete"><![CDATA[Delete Ad]]></string>
-    <string name="_bx_directory_form_entry_display_view"><![CDATA[View Ad]]></string>
+
+    <string name="_bx_directory_form_entry_price_display_add"><![CDATA[With Price: Add]]></string>
+    <string name="_bx_directory_form_entry_price_display_edit"><![CDATA[With Price: Edit]]></string>
+    <string name="_bx_directory_form_entry_price_display_view"><![CDATA[With Price: View]]></string>
+
+    <string name="_bx_directory_form_entry_price_year_display_add"><![CDATA[With Price and Year: Add]]></string>
+    <string name="_bx_directory_form_entry_price_year_display_edit"><![CDATA[With Price and Year: Edit]]></string>
+    <string name="_bx_directory_form_entry_price_year_display_view"><![CDATA[With Price and Year: View]]></string>
+
     <string name="_bx_directory_form_entry_input_author"><![CDATA[Author]]></string>
     <string name="_bx_directory_form_entry_input_sys_do_submit"><![CDATA[Submit]]></string>
     <string name="_bx_directory_form_entry_input_do_submit"><![CDATA[Submit]]></string>
-    <string name="_bx_directory_form_entry_input_sys_do_publish"><![CDATA[Publish]]></string>
-    <string name="_bx_directory_form_entry_input_do_publish"><![CDATA[Publish]]></string>
     <string name="_bx_directory_form_entry_input_sys_title"><![CDATA[Title]]></string>
     <string name="_bx_directory_form_entry_input_title"><![CDATA[Title]]></string>
     <string name="_bx_directory_form_entry_input_title_err"><![CDATA[Title is essential. Please, fill in this field]]></string>
-    <string name="_bx_directory_form_entry_input_sys_cat"><![CDATA[Category]]></string>
-    <string name="_bx_directory_form_entry_input_cat"><![CDATA[Category]]></string>
-    <string name="_bx_directory_form_entry_input_cat_err"><![CDATA[Please select category]]></string>
+    <string name="_bx_directory_form_entry_input_sys_price"><![CDATA[Price]]></string>
+    <string name="_bx_directory_form_entry_input_price"><![CDATA[Price]]></string>
+    <string name="_bx_directory_form_entry_input_sys_year"><![CDATA[Year]]></string>
+    <string name="_bx_directory_form_entry_input_year"><![CDATA[Year]]></string>
+    <string name="_bx_directory_form_entry_input_sys_category"><![CDATA[Category]]></string>
+    <string name="_bx_directory_form_entry_input_category"><![CDATA[Category]]></string>
+    <string name="_bx_directory_form_entry_input_category_err"><![CDATA[Please select category]]></string>
     <string name="_bx_directory_form_entry_input_sys_text"><![CDATA[Text]]></string>
     <string name="_bx_directory_form_entry_input_text"><![CDATA[Text]]></string>
     <string name="_bx_directory_form_entry_input_text_err"><![CDATA[Text field can't be empty]]></string>
@@ -50,12 +90,7 @@
     <string name="_bx_directory_form_entry_input_date_added"><![CDATA[Created]]></string>
     <string name="_bx_directory_form_entry_input_sys_date_changed"><![CDATA[Updated]]></string>
     <string name="_bx_directory_form_entry_input_date_changed"><![CDATA[Updated]]></string>
-    <string name="_bx_directory_form_entry_input_sys_date_published"><![CDATA[Publish at]]></string>
-    <string name="_bx_directory_form_entry_input_date_published"><![CDATA[Publish at]]></string>
-    <string name="_bx_directory_form_entry_input_date_published_info"><![CDATA[Leave empty to publish immediately.]]></string>
     <string name="_bx_directory_form_entry_input_sys_attachments"><![CDATA[Attachments]]></string>
-    <string name="_bx_directory_form_entry_input_sys_disable_comments"><![CDATA[Disable comments]]></string>
-    <string name="_bx_directory_form_entry_input_disable_comments"><![CDATA[Disable comments]]></string>
 
     <string name="_bx_directory_form_poll"><![CDATA[Polls]]></string>
     <string name="_bx_directory_form_poll_display_add"><![CDATA[Add Poll]]></string>
@@ -217,6 +252,19 @@
     <string name="_bx_directory_menu_item_title_admt_posts"><![CDATA[Ads - {addon} hidden]]></string>
     <string name="_bx_directory_menu_item_title_manage_my"><![CDATA[My Ads]]></string>
     <string name="_bx_directory_menu_item_title_manage_all"><![CDATA[All Ads]]></string>
+    <string name="_bx_directory_menu_item_title_categories"><![CDATA[Categories]]></string>
+
+    <string name="_bx_directory_grid_column_title_icon"><![CDATA[Icon]]></string>
+    <string name="_bx_directory_grid_column_title_title"><![CDATA[Title]]></string>
+    <string name="_bx_directory_grid_column_title_subcategories"><![CDATA[Subcategories]]></string>
+    <string name="_bx_directory_grid_column_value_subcategories"><![CDATA[{0} subcategories]]></string>
+    <string name="_bx_directory_grid_column_info_subcategories"><![CDATA[View subcategories]]></string>
+    <string name="_bx_directory_grid_action_title_add"><![CDATA[Add New]]></string>
+    <string name="_bx_directory_grid_action_title_delete"><![CDATA[Delete]]></string>
+    <string name="_bx_directory_grid_popup_title_add"><![CDATA[Add New Category]]></string>
+    <string name="_bx_directory_grid_popup_title_edit"><![CDATA[Edit '{0}' Category]]></string>
+    <string name="_bx_directory_grid_action_err_add_category"><![CDATA[Cannot add a category.]]></string>
+    <string name="_bx_directory_grid_action_err_edit_category"><![CDATA[Cannot edit the category.]]></string>
 
     <string name="_bx_directory_grid_filter_item_title_adm_select_one_filter1"><![CDATA[All Statuses]]></string>
     <string name="_bx_directory_grid_filter_item_title_adm_active"><![CDATA[Active]]></string>
@@ -237,39 +285,60 @@
     <string name="_bx_directory_search_extended"><![CDATA[Directory Search]]></string>
     <string name="_bx_directory_search_extended_cmts"><![CDATA[Directory Comments Search]]></string>
 
-    <string name="_bx_directory_pre_lists_cats"><![CDATA[Ad categories]]></string>
-    <string name="_bx_directory_cat_Animals_Pets"><![CDATA[Animals & Pets]]></string>
-    <string name="_bx_directory_cat_Architecture"><![CDATA[Architecture]]></string>
-    <string name="_bx_directory_cat_Art"><![CDATA[Art]]></string>
-    <string name="_bx_directory_cat_Cars_Motorcycles"><![CDATA[Cars & Motorcycles]]></string>
-    <string name="_bx_directory_cat_Celebrities"><![CDATA[Celebrities]]></string>
-    <string name="_bx_directory_cat_Design"><![CDATA[Design]]></string>
-    <string name="_bx_directory_cat_DIY_Crafts"><![CDATA[DIY & Crafts]]></string>
-    <string name="_bx_directory_cat_Education"><![CDATA[Education]]></string>
-    <string name="_bx_directory_cat_Film_Music_Books"><![CDATA[Film, Music & Books]]></string>
-    <string name="_bx_directory_cat_Food_Drink"><![CDATA[Food & Drink]]></string>
-    <string name="_bx_directory_cat_Gardening"><![CDATA[Gardening]]></string>
-    <string name="_bx_directory_cat_Geek"><![CDATA[Geek]]></string>
-    <string name="_bx_directory_cat_Hair_Beauty"><![CDATA[Hair & Beauty]]></string>
-    <string name="_bx_directory_cat_Health_Fitness"><![CDATA[Health & Fitness]]></string>
-    <string name="_bx_directory_cat_History"><![CDATA[History]]></string>
-    <string name="_bx_directory_cat_Holidays_Events"><![CDATA[Holidays & Events]]></string>
-    <string name="_bx_directory_cat_Home_Decor"><![CDATA[Home Decor]]></string>
-    <string name="_bx_directory_cat_Humor"><![CDATA[Humor]]></string>
-    <string name="_bx_directory_cat_Illustrations_Posters"><![CDATA[Illustrations & Posters]]></string>
-    <string name="_bx_directory_cat_Kids_Parenting"><![CDATA[Kids & Parenting]]></string>
-    <string name="_bx_directory_cat_Mens_Fashion"><![CDATA[Men's Fashion]]></string>
-    <string name="_bx_directory_cat_Outdoors"><![CDATA[Outdoors]]></string>
-    <string name="_bx_directory_cat_Photography"><![CDATA[Photography]]></string>
-    <string name="_bx_directory_cat_Products"><![CDATA[Products]]></string>
-    <string name="_bx_directory_cat_Quotes"><![CDATA[Quotes]]></string>
-    <string name="_bx_directory_cat_Science_Nature"><![CDATA[Science & Nature]]></string>
-    <string name="_bx_directory_cat_Sports"><![CDATA[Sports]]></string>
-    <string name="_bx_directory_cat_Tattoos"><![CDATA[Tattoos]]></string>
-    <string name="_bx_directory_cat_Technology"><![CDATA[Technology]]></string>
-    <string name="_bx_directory_cat_Travel"><![CDATA[Travel]]></string>
-    <string name="_bx_directory_cat_Weddings"><![CDATA[Weddings]]></string>
-    <string name="_bx_directory_cat_Womens_Fashion"><![CDATA[Women's Fashion]]></string>
+    <!-- Ctegories -->
+    <string name="_bx_directory_cat_type_price"><![CDATA[With price]]></string>
+    <string name="_bx_directory_cat_type_price_year"><![CDATA[With price and year]]></string>
+
+    <string name="_bx_directory_cat_title_job"><![CDATA[Jobs]]></string>
+    <string name="_bx_directory_cat_title_accounting_finance"><![CDATA[accounting / finance]]></string>
+    <string name="_bx_directory_cat_title_education_nonprofit"><![CDATA[education / nonprofit]]></string>
+    <string name="_bx_directory_cat_title_government_legal"><![CDATA[government / legal]]></string>
+    <string name="_bx_directory_cat_title_programming_web_design"><![CDATA[programming / web design]]></string>
+    <string name="_bx_directory_cat_title_other_jobs"><![CDATA[other]]></string>
+
+    <string name="_bx_directory_cat_title_music"><![CDATA[Music Exchange]]></string>
+    <string name="_bx_directory_cat_title_instrument_sale"><![CDATA[instruments for sale]]></string>
+    <string name="_bx_directory_cat_title_instrument_wanted"><![CDATA[instruments wanted]]></string>
+    <string name="_bx_directory_cat_title_other"><![CDATA[other]]></string>
+
+    <string name="_bx_directory_cat_title_housing"><![CDATA[Housing & Rentals]]></string>
+    <string name="_bx_directory_cat_title_apartments_housing"><![CDATA[apartments / housing]]></string>
+    <string name="_bx_directory_cat_title_office_commercial"><![CDATA[office / commercial]]></string>
+    <string name="_bx_directory_cat_title_real_estate_sale"><![CDATA[real estate for sale]]></string>
+    <string name="_bx_directory_cat_title_roommate"><![CDATA[roommates]]></string>
+    <string name="_bx_directory_cat_title_temporary_rental"><![CDATA[temporary rental]]></string>
+    
+    <string name="_bx_directory_cat_title_service"><![CDATA[Services]]></string>
+    <string name="_bx_directory_cat_title_automotive"><![CDATA[automotive]]></string>
+    <string name="_bx_directory_cat_title_educational"><![CDATA[educational]]></string>
+    <string name="_bx_directory_cat_title_financial"><![CDATA[financial]]></string>
+    <string name="_bx_directory_cat_title_labor_move"><![CDATA[labor / move]]></string>
+    <string name="_bx_directory_cat_title_legal"><![CDATA[legal]]></string>
+
+    <string name="_bx_directory_cat_title_casting"><![CDATA[Casting Calls]]></string>
+    <string name="_bx_directory_cat_title_acting"><![CDATA[acting]]></string>
+    <string name="_bx_directory_cat_title_dance"><![CDATA[dance]]></string>
+    <string name="_bx_directory_cat_title_modeling"><![CDATA[modeling]]></string>
+    <string name="_bx_directory_cat_title_musician"><![CDATA[musicians]]></string>
+    <string name="_bx_directory_cat_title_reality_show"><![CDATA[reality shows]]></string>
+
+    <string name="_bx_directory_cat_title_personal"><![CDATA[Personals]]></string>
+    <string name="_bx_directory_cat_title_men_women"><![CDATA[men seeking women]]></string>
+    <string name="_bx_directory_cat_title_women_men"><![CDATA[women seeking men]]></string>
+    <string name="_bx_directory_cat_title_missed_connection"><![CDATA[missed connections]]></string>
+    <string name="_bx_directory_cat_title_personal_other"><![CDATA[other]]></string>
+
+    <string name="_bx_directory_cat_title_sale"><![CDATA[For Sale]]></string>
+    <string name="_bx_directory_cat_title_barter"><![CDATA[barter]]></string>
+    <string name="_bx_directory_cat_title_clothing"><![CDATA[clothing]]></string>
+    <string name="_bx_directory_cat_title_collectible"><![CDATA[collectibles]]></string>
+    <string name="_bx_directory_cat_title_miscellaneous"><![CDATA[miscellaneous]]></string>
+
+    <string name="_bx_directory_cat_title_sale_car"><![CDATA[Cars For Sale]]></string>
+    <string name="_bx_directory_cat_title_auto_part"><![CDATA[auto parts]]></string>
+    <string name="_bx_directory_cat_title_auto_truck"><![CDATA[autos / trucks]]></string>
+    <string name="_bx_directory_cat_title_motorcycle"><![CDATA[motorcycles]]></string>
+
 
     <string name="_bx_directory_txt_all_entries_in"><![CDATA[<a href="{0}">All Ads in {1} ({2})</a>]]></string>
     <string name="_bx_directory_txt_all_entries_by"><![CDATA[<a href="{0}">All Ads by {1} ({2})</a>]]></string>
@@ -277,6 +346,9 @@
     <string name="_bx_directory_txt_sample_single_with_article"><![CDATA[an ad]]></string>
     <string name="_bx_directory_txt_sample_comment_single"><![CDATA[comment to ad]]></string>
     <string name="_bx_directory_txt_sample_vote_single"><![CDATA[vote to ad]]></string>
+    <string name="_bx_directory_txt_display_title_add"><![CDATA[{0}: Add]]></string>
+    <string name="_bx_directory_txt_display_title_edit"><![CDATA[{0}: Edit]]></string>
+    <string name="_bx_directory_txt_display_title_view"><![CDATA[{0}: View]]></string>
 
     <string name="_bx_directory_txt_err_cannot_perform_action"><![CDATA[Cannot perform action. Please report.]]></string>
 

+ 3 - 6
modules/boonex/directory/install/sql/disable.sql

@@ -28,9 +28,6 @@ DELETE FROM `sys_objects_search` WHERE `ObjectName` IN ('bx_directory', 'bx_dire
 -- METATAGS
 DELETE FROM `sys_objects_metatags` WHERE `object` = 'bx_directory';
 
--- CATEGORY
-DELETE FROM `sys_objects_category` WHERE `object` = 'bx_directory_cats';
-
 -- STATS
 DELETE FROM `sys_statistics` WHERE `name` LIKE 'bx_directory%';
 
@@ -38,9 +35,9 @@ DELETE FROM `sys_statistics` WHERE `name` LIKE 'bx_directory%';
 DELETE FROM `sys_objects_chart` WHERE `object` LIKE 'bx_directory%';
 
 -- GRIDS
-DELETE FROM `sys_objects_grid` WHERE `object` IN ('bx_directory_administration', 'bx_directory_common');
-DELETE FROM `sys_grid_fields` WHERE `object` IN ('bx_directory_administration', 'bx_directory_common');
-DELETE FROM `sys_grid_actions` WHERE `object` IN ('bx_directory_administration', 'bx_directory_common');
+DELETE FROM `sys_objects_grid` WHERE `object` LIKE 'bx_directory%';
+DELETE FROM `sys_grid_fields` WHERE `object` LIKE 'bx_directory%';
+DELETE FROM `sys_grid_actions` WHERE `object` LIKE 'bx_directory%';
 
 -- UPLOADERS
 DELETE FROM `sys_objects_uploader` WHERE `object` LIKE 'bx_directory_%';

+ 21 - 7
modules/boonex/directory/install/sql/enable.sql

@@ -121,7 +121,7 @@ INSERT INTO `sys_pages_blocks`(`object`, `cell_id`, `module`, `title_system`, `t
 ('bx_directory_home', 1, 'bx_directory', '', '_bx_directory_page_block_title_featured_entries_view_extended', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:12:"bx_directory";s:6:"method";s:15:"browse_featured";s:6:"params";a:1:{i:0;s:8:"extended";}}', 0, 1, 1, 0),
 ('bx_directory_home', 1, 'bx_directory', '', '_bx_directory_page_block_title_recent_entries_view_extended', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:12:"bx_directory";s:6:"method";s:13:"browse_public";s:6:"params";a:1:{i:0;s:8:"extended";}}', 0, 1, 1, 1),
 ('bx_directory_home', 2, 'bx_directory', '', '_bx_directory_page_block_title_popular_keywords', 11, 2147483647, 'service', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:14:"keywords_cloud";s:6:"params";a:2:{i:0;s:12:"bx_directory";i:1;s:12:"bx_directory";}s:5:"class";s:20:"TemplServiceMetatags";}', 0, 1, 1, 0),
-('bx_directory_home', 2, 'bx_directory', '', '_bx_directory_page_block_title_cats', 11, 2147483647, 'service', 'a:4:{s:6:"module";s:6:"system";s:6:"method";s:15:"categories_list";s:6:"params";a:2:{i:0;s:17:"bx_directory_cats";i:1;a:1:{s:10:"show_empty";b:1;}}s:5:"class";s:20:"TemplServiceCategory";}', 0, 1, 1, 1);
+('bx_directory_home', 2, 'bx_directory', '', '_bx_directory_page_block_title_cats', 11, 2147483647, 'service', 'a:3:{s:6:"module";s:12:"bx_directory";s:6:"method";s:15:"categories_list";s:6:"params";a:1:{i:0;a:1:{s:10:"show_empty";b:1;}}}', 0, 1, 1, 1);
 
 
 -- PAGE: search for entries
@@ -411,10 +411,6 @@ INSERT INTO `sys_objects_search` (`ObjectName`, `Title`, `Order`, `ClassName`, `
 INSERT INTO `sys_objects_metatags` (`object`, `table_keywords`, `table_locations`, `table_mentions`, `override_class_name`, `override_class_file`) VALUES
 ('bx_directory', 'bx_directory_meta_keywords', 'bx_directory_meta_locations', 'bx_directory_meta_mentions', '', '');
 
--- CATEGORY
-INSERT INTO `sys_objects_category` (`object`, `search_object`, `form_object`, `list_name`, `table`, `field`, `join`, `where`, `override_class_name`, `override_class_file`) VALUES
-('bx_directory_cats', 'bx_directory', 'bx_directory', 'bx_directory_cats', 'bx_directory_entries', 'cat', 'INNER JOIN `sys_profiles` ON (`sys_profiles`.`id` = `bx_directory_entries`.`author` OR `sys_profiles`.`id` = -`bx_directory_entries`.`author`)', 'AND `sys_profiles`.`status` = ''active''', '', '');
-
 -- STATS
 SET @iMaxOrderStats = (SELECT IFNULL(MAX(`order`), 0) FROM `sys_statistics`);
 INSERT INTO `sys_statistics` (`module`, `name`, `title`, `link`, `icon`, `query`, `order`) VALUES 
@@ -431,7 +427,6 @@ INSERT INTO `sys_objects_grid` (`object`, `source_type`, `source`, `table`, `fie
 ('bx_directory_administration', 'Sql', 'SELECT * FROM `bx_directory_entries` WHERE 1 ', 'bx_directory_entries', 'id', 'added', 'status_admin', '', 20, NULL, 'start', '', 'title,text', '', 'like', 'reports', '', 192, 'BxDirGridAdministration', 'modules/boonex/directory/classes/BxDirGridAdministration.php'),
 ('bx_directory_common', 'Sql', 'SELECT * FROM `bx_directory_entries` WHERE 1 ', 'bx_directory_entries', 'id', 'added', 'status', '', 20, NULL, 'start', '', 'title,text', '', 'like', '', '', 2147483647, 'BxDirGridCommon', 'modules/boonex/directory/classes/BxDirGridCommon.php');
 
-
 INSERT INTO `sys_grid_fields` (`object`, `name`, `title`, `width`, `translatable`, `chars_limit`, `params`, `order`) VALUES
 ('bx_directory_administration', 'checkbox', '_sys_select', '2%', 0, '', '', 1),
 ('bx_directory_administration', 'switcher', '_bx_directory_grid_column_title_adm_active', '8%', 0, '', '', 2),
@@ -456,8 +451,27 @@ INSERT INTO `sys_grid_actions` (`object`, `type`, `name`, `title`, `icon`, `icon
 ('bx_directory_common', 'single', 'delete', '_bx_directory_grid_action_title_adm_delete', 'remove', 1, 1, 2),
 ('bx_directory_common', 'single', 'settings', '_bx_directory_grid_action_title_adm_more_actions', 'cog', 1, 0, 3);
 
--- UPLOADERS
+-- GRIDS: categories manager
+INSERT INTO `sys_objects_grid` (`object`, `source_type`, `source`, `table`, `field_id`, `field_order`, `field_active`, `paginate_url`, `paginate_per_page`, `paginate_simple`, `paginate_get_start`, `paginate_get_per_page`, `filter_fields`, `filter_mode`, `sorting_fields`, `visible_for_levels`, `override_class_name`, `override_class_file`) VALUES
+('bx_directory_categories', 'Sql', 'SELECT * FROM `bx_directory_categories` WHERE 1 ', 'bx_directory_categories', 'id', 'order', 'active', '', 20, NULL, 'start', '', 'title,text', 'auto', '', 128, 'BxDirGridCategories', 'modules/boonex/directory/classes/BxDirGridCategories.php');
+
+INSERT INTO `sys_grid_fields` (`object`, `name`, `title`, `width`, `translatable`, `chars_limit`, `params`, `order`) VALUES
+('bx_directory_categories', 'order', '', '1%', 0, '', '', 1),
+('bx_directory_categories', 'checkbox', '_sys_select', '1%', 0, '', '', 2),
+('bx_directory_categories', 'switcher', '', '8%', 0, '', '', 3),
+('bx_directory_categories', 'icon', '_bx_directory_grid_column_title_icon', '5%', 0, '', '', 4),
+('bx_directory_categories', 'title', '_bx_directory_grid_column_title_title', '50%', 1, '32', '', 5),
+('bx_directory_categories', 'subcategories', '_bx_directory_grid_column_title_subcategories', '15%', 0, '16', '', 6),
+('bx_directory_categories', 'actions', '', '20%', 0, '', '', 7);
+
+INSERT INTO `sys_grid_actions` (`object`, `type`, `name`, `title`, `icon`, `confirm`, `order`) VALUES
+('bx_directory_categories', 'bulk', 'delete', '_bx_directory_grid_action_title_delete', '', 1, 1),
+('bx_directory_categories', 'single', 'edit', '', 'pencil-alt', 0, 1),
+('bx_directory_categories', 'single', 'delete', '', 'remove', 1, 2),
+('bx_directory_categories', 'independent', 'add', '_bx_directory_grid_action_title_add', '', 0, 1);
 
+
+-- UPLOADERS
 INSERT INTO `sys_objects_uploader` (`object`, `active`, `override_class_name`, `override_class_file`) VALUES
 ('bx_directory_simple', 1, 'BxDirUploaderSimple', 'modules/boonex/directory/classes/BxDirUploaderSimple.php'),
 ('bx_directory_html5', 1, 'BxDirUploaderHTML5', 'modules/boonex/directory/classes/BxDirUploaderHTML5.php'),

+ 242 - 90
modules/boonex/directory/install/sql/install.sql

@@ -4,10 +4,9 @@ CREATE TABLE IF NOT EXISTS `bx_directory_entries` (
   `author` int(11) NOT NULL,
   `added` int(11) NOT NULL,
   `changed` int(11) NOT NULL,
-  `published` int(11) NOT NULL,
   `thumb` int(11) NOT NULL,
   `title` varchar(255) NOT NULL,
-  `cat` int(11) NOT NULL,
+  `category` int(11) NOT NULL,
   `text` mediumtext NOT NULL,
   `views` int(11) NOT NULL default '0',
   `rate` float NOT NULL default '0',
@@ -22,13 +21,127 @@ CREATE TABLE IF NOT EXISTS `bx_directory_entries` (
   `reports` int(11) NOT NULL default '0',
   `featured` int(11) NOT NULL default '0',
   `allow_view_to` int(11) NOT NULL DEFAULT '3',
-  `disable_comments` tinyint(4) NOT NULL DEFAULT '0',
   `status` enum('active','awaiting','hidden') NOT NULL DEFAULT 'active',
   `status_admin` enum('active','hidden') NOT NULL DEFAULT 'active',
   PRIMARY KEY (`id`),
   FULLTEXT KEY `title_text` (`title`,`text`)
 );
 
+-- TABLE: types of categories
+CREATE TABLE IF NOT EXISTS `bx_directory_categories_types` (
+  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
+  `name` varchar(64) NOT NULL DEFAULT '',
+  `title` varchar(255) NOT NULL DEFAULT '',
+  `display_add` varchar(255) NOT NULL DEFAULT '',
+  `display_edit` varchar(255) NOT NULL DEFAULT '',
+  `display_view` varchar(255) NOT NULL DEFAULT '',
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `name` (`name`)
+);
+
+INSERT INTO `bx_directory_categories_types` (`id`, `name`, `title`, `display_add`, `display_edit`, `display_view`) VALUES
+(1, 'price', '_bx_directory_cat_type_price', 'bx_directory_entry_price_add', 'bx_directory_entry_price_edit', 'bx_directory_entry_price_view'),
+(2, 'price_year', '_bx_directory_cat_type_price_year', 'bx_directory_entry_price_year_add', 'bx_directory_entry_price_year_edit', 'bx_directory_entry_price_year_view');
+
+-- TABLE: categories
+CREATE TABLE IF NOT EXISTS `bx_directory_categories` (
+  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
+  `parent_id` int(11) unsigned NOT NULL DEFAULT '0',
+  `level` tinyint(11) unsigned NOT NULL DEFAULT '0',
+  `type` int(11) NOT NULL DEFAULT '0',
+  `name` varchar(64) NOT NULL DEFAULT '',
+  `title` varchar(255) NOT NULL DEFAULT '',
+  `text` text NOT NULL,
+  `icon` varchar(255) NOT NULL DEFAULT '',
+  `active` tinyint(4) NOT NULL DEFAULT '1',
+  `order` int(11) NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `name` (`name`),
+  FULLTEXT KEY `title_text` (`title`,`text`)
+);
+
+INSERT INTO `bx_directory_categories` (`parent_id`, `level`, `type`, `name`, `title`, `text`, `icon`, `active`, `order`) VALUES 
+(0, 0, 1, 'job', '_bx_directory_cat_title_job', '', 'user-md', 1, 1);
+SET @iParentId = LAST_INSERT_ID();
+
+INSERT INTO `bx_directory_categories` (`parent_id`, `level`, `type`, `name`, `title`, `text`, `icon`, `active`, `order`) VALUES 
+(@iParentId, 1, 1, 'job_finance', '_bx_directory_cat_title_accounting_finance', '', '', 1, 1),
+(@iParentId, 1, 1, 'job_education', '_bx_directory_cat_title_education_nonprofit', '', '', 1, 2),
+(@iParentId, 1, 1, 'job_legal', '_bx_directory_cat_title_government_legal', '', '', 1, 3),
+(@iParentId, 1, 1, 'job_programming', '_bx_directory_cat_title_programming_web_design', '', '', 1, 4),
+(@iParentId, 1, 1, 'job_other', '_bx_directory_cat_title_other_jobs', '', '', 1, 5);
+
+INSERT INTO `bx_directory_categories` (`parent_id`, `level`, `type`, `name`, `title`, `text`, `icon`, `active`, `order`) VALUES 
+(0, 0, 2, 'music', '_bx_directory_cat_title_music', '', 'music', 1, 2);
+SET @iParentId = LAST_INSERT_ID();
+
+INSERT INTO `bx_directory_categories` (`parent_id`, `level`, `type`, `name`, `title`, `text`, `icon`, `active`, `order`) VALUES 
+(@iParentId, 1, 2, 'music_isale', '_bx_directory_cat_title_instrument_sale', '', '', 1, 1),
+(@iParentId, 1, 2, 'music_iwanted', '_bx_directory_cat_title_instrument_wanted', '', '', 1, 2),
+(@iParentId, 1, 2, 'music_other', '_bx_directory_cat_title_other', '', '', 1, 3);
+
+INSERT INTO `bx_directory_categories` (`parent_id`, `level`, `type`, `name`, `title`, `text`, `icon`, `active`, `order`) VALUES 
+(0, 0, 1, 'housing', '_bx_directory_cat_title_housing', '', 'home', 1, 3);
+SET @iParentId = LAST_INSERT_ID();
+
+INSERT INTO `bx_directory_categories` (`parent_id`, `level`, `type`, `name`, `title`, `text`, `icon`, `active`, `order`) VALUES 
+(@iParentId, 1, 1, 'housing_apartments', '_bx_directory_cat_title_apartments_housing', '', '', 1, 1),
+(@iParentId, 1, 1, 'housing_office', '_bx_directory_cat_title_office_commercial', '', '', 1, 2),
+(@iParentId, 1, 1, 'housing_re_sale', '_bx_directory_cat_title_real_estate_sale', '', '', 1, 3),
+(@iParentId, 1, 1, 'housing_roommate', '_bx_directory_cat_title_roommate', '', '', 1, 4),
+(@iParentId, 1, 1, 'housing_temp_rental', '_bx_directory_cat_title_temporary_rental', '', '', 1, 5);
+
+INSERT INTO `bx_directory_categories` (`parent_id`, `level`, `type`, `name`, `title`, `text`, `icon`, `active`, `order`) VALUES 
+(0, 0, 1, 'service', '_bx_directory_cat_title_service', '', 'wrench', 1, 4);
+SET @iParentId = LAST_INSERT_ID();
+
+INSERT INTO `bx_directory_categories` (`parent_id`, `level`, `type`, `name`, `title`, `text`, `icon`, `active`, `order`) VALUES 
+(@iParentId, 1, 1, 'service_automotive', '_bx_directory_cat_title_automotive', '', '', 1, 1),
+(@iParentId, 1, 1, 'service_educational', '_bx_directory_cat_title_educational', '', '', 1, 2),
+(@iParentId, 1, 1, 'service_financial', '_bx_directory_cat_title_financial', '', '', 1, 3),
+(@iParentId, 1, 1, 'service_labor', '_bx_directory_cat_title_labor_move', '', '', 1, 4),
+(@iParentId, 1, 1, 'service_legal', '_bx_directory_cat_title_legal', '', '', 1, 5);
+
+INSERT INTO `bx_directory_categories` (`parent_id`, `level`, `type`, `name`, `title`, `text`, `icon`, `active`, `order`) VALUES 
+(0, 0, 1, 'casting', '_bx_directory_cat_title_casting', '', 'eye', 1, 5);
+SET @iParentId = LAST_INSERT_ID();
+
+INSERT INTO `bx_directory_categories` (`parent_id`, `level`, `type`, `name`, `title`, `text`, `icon`, `active`, `order`) VALUES 
+(@iParentId, 1, 1, 'casting_acting', '_bx_directory_cat_title_acting', '', '', 1, 1),
+(@iParentId, 1, 1, 'casting_dance', '_bx_directory_cat_title_dance', '', '', 1, 2),
+(@iParentId, 1, 1, 'casting_modeling', '_bx_directory_cat_title_modeling', '', '', 1, 3),
+(@iParentId, 1, 1, 'casting_musician', '_bx_directory_cat_title_musician', '', '', 1, 4),
+(@iParentId, 1, 1, 'casting_rshow', '_bx_directory_cat_title_reality_show', '', '', 1, 5);
+
+INSERT INTO `bx_directory_categories` (`parent_id`, `level`, `type`, `name`, `title`, `text`, `icon`, `active`, `order`) VALUES 
+(0, 0, 2, 'personal', '_bx_directory_cat_title_personal', '', 'user', 1, 6);
+SET @iParentId = LAST_INSERT_ID();
+
+INSERT INTO `bx_directory_categories` (`parent_id`, `level`, `type`, `name`, `title`, `text`, `icon`, `active`, `order`) VALUES 
+(@iParentId, 1, 2, 'personal_mw', '_bx_directory_cat_title_men_women', '', '', 1, 1),
+(@iParentId, 1, 2, 'personal_wm', '_bx_directory_cat_title_women_men', '', '', 1, 2),
+(@iParentId, 1, 2, 'personal_missed', '_bx_directory_cat_title_missed_connection', '', '', 1, 3),
+(@iParentId, 1, 2, 'personal_other', '_bx_directory_cat_title_personal_other', '', '', 1, 4);
+
+INSERT INTO `bx_directory_categories` (`parent_id`, `level`, `type`, `name`, `title`, `text`, `icon`, `active`, `order`) VALUES 
+(0, 0, 2, 'sale', '_bx_directory_cat_title_sale', '', 'shopping-cart', 1, 7);
+SET @iParentId = LAST_INSERT_ID();
+
+INSERT INTO `bx_directory_categories` (`parent_id`, `level`, `type`, `name`, `title`, `text`, `icon`, `active`, `order`) VALUES 
+(@iParentId, 1, 2, 'sale_barter', '_bx_directory_cat_title_barter', '', '', 1, 1),
+(@iParentId, 1, 2, 'sale_clothing', '_bx_directory_cat_title_clothing', '', '', 1, 1),
+(@iParentId, 1, 2, 'sale_collectible', '_bx_directory_cat_title_collectible', '', '', 1, 1),
+(@iParentId, 1, 2, 'sale_misc', '_bx_directory_cat_title_miscellaneous', '', '', 1, 1);
+
+INSERT INTO `bx_directory_categories` (`parent_id`, `level`, `type`, `name`, `title`, `text`, `icon`, `active`, `order`) VALUES 
+(0, 0, 2, 'sale_car', '_bx_directory_cat_title_sale_car', '', 'truck', 1, 8);
+SET @iParentId = LAST_INSERT_ID();
+
+INSERT INTO `bx_directory_categories` (`parent_id`, `level`, `type`, `name`, `title`, `text`, `icon`, `active`, `order`) VALUES 
+(@iParentId, 1, 2, 'sale_car_part', '_bx_directory_cat_title_auto_part', '', '', 1, 1),
+(@iParentId, 1, 2, 'sale_car_auto', '_bx_directory_cat_title_auto_truck', '', '', 1, 2),
+(@iParentId, 1, 2, 'sale_car_motorcycle', '_bx_directory_cat_title_motorcycle', '', '', 1, 3);
+
 -- TABLE: storages & transcoders
 CREATE TABLE IF NOT EXISTS `bx_directory_covers` (
   `id` int(11) NOT NULL AUTO_INCREMENT,
@@ -355,20 +468,71 @@ INSERT INTO `sys_transcoder_filters` (`transcoder_object`, `filter`, `filter_par
 ('bx_directory_gallery_files', 'Resize', 'a:1:{s:1:"w";s:3:"500";}', '0');
 
 
--- FORMS: entry (post)
+-- FORMS: category
 INSERT INTO `sys_objects_form`(`object`, `module`, `title`, `action`, `form_attrs`, `table`, `key`, `uri`, `uri_title`, `submit_name`, `params`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
-('bx_directory', 'bx_directory', '_bx_directory_form_entry', '', 'a:1:{s:7:"enctype";s:19:"multipart/form-data";}', 'bx_directory_entries', 'id', '', '', 'a:2:{i:0;s:9:"do_submit";i:1;s:10:"do_publish";}', '', 0, 1, 'BxDirFormEntry', 'modules/boonex/directory/classes/BxDirFormEntry.php');
+('bx_directory_category', 'bx_directory', '_bx_directory_form_category', '', 'a:1:{s:7:"enctype";s:19:"multipart/form-data";}', 'bx_directory_categories', 'id', '', '', 'a:1:{i:0;s:9:"do_submit";}', '', 0, 1, 'BxDirFormCategory', 'modules/boonex/directory/classes/BxDirFormCategory.php');
+
+INSERT INTO `sys_form_displays`(`object`, `display_name`, `module`, `view_mode`, `title`) VALUES 
+('bx_directory_category', 'bx_directory_category_add', 'bx_directory', 0, '_bx_directory_form_category_display_add'),
+('bx_directory_category', 'bx_directory_category_delete', 'bx_directory', 0, '_bx_directory_form_category_display_delete'),
+('bx_directory_category', 'bx_directory_category_edit', 'bx_directory', 0, '_bx_directory_form_category_display_edit');
+
+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_directory_category', 'bx_directory', 'delete_confirm', 1, '', 0, 'checkbox', '_bx_directory_form_category_input_sys_delete_confirm', '_bx_directory_form_category_input_delete_confirm', '_bx_directory_form_category_input_delete_confirm_info', 1, 0, 0, '', '', '', 'Avail', '', '_bx_directory_form_category_input_delete_confirm_error', '', '', 1, 0),
+('bx_directory_category', 'bx_directory', 'parent_id', '', '', 0, 'select', '_bx_directory_form_category_input_sys_parent_id', '_bx_directory_form_category_input_parent_id', '', 0, 0, 0, '', '', '', '', '', '', 'Int', '', 1, 0),
+('bx_directory_category', 'bx_directory', 'title', '', '', 0, 'text_translatable', '_bx_directory_form_category_input_sys_title', '_bx_directory_form_category_input_title', '', 1, 0, 0, '', '', '', 'AvailTranslatable', 'a:1:{i:0;s:5:"title";}', '_bx_directory_form_category_input_title_err', 'Xss', '', 1, 0),
+('bx_directory_category', 'bx_directory', 'text', '', '', 0, 'textarea_translatable', '_bx_directory_form_category_input_sys_text', '_bx_directory_form_category_input_text', '', 0, 0, 2, '', '', '', '', '', '', 'XssHtml', '', 1, 0),
+('bx_directory_category', 'bx_directory', 'type', '', '', 0, 'select', '_bx_directory_form_category_input_sys_type', '_bx_directory_form_category_input_type', '_bx_directory_form_category_input_type_info', 1, 0, 0, '', '', '', 'Avail', '', '_bx_directory_form_category_input_type_err', 'Int', '', 0, 0),
+('bx_directory_category', 'bx_directory', 'type_clone', 'on', '', 0, 'switcher', '_bx_directory_form_category_input_sys_type_clone', '_bx_directory_form_category_input_type_clone', '', 0, 0, 0, 'a:1:{s:8:"onchange";s:33:"oBxDirStudio.onChangeClone(this);";}', '', '', '', '', '', '', '', 0, 0),
+('bx_directory_category', 'bx_directory', 'type_title', '', '', 0, 'text_translatable', '_bx_directory_form_category_input_sys_type_title', '_bx_directory_form_category_input_type_title', '', 0, 0, 0, 'a:1:{s:8:"disabled";s:8:"disabled";}', 'a:1:{s:5:"style";s:13:"display:none;";}', '', '', '', '', '', '', 0, 0),
+('bx_directory_category', 'bx_directory', 'icon', '', '', 0, 'text', '_bx_directory_form_category_input_sys_icon', '_bx_directory_form_category_input_icon', '', 0, 0, 0, '', '', '', '', '', '', 'Xss', '', 1, 0),
+('bx_directory_category', 'bx_directory', 'controls', '', 'do_submit,do_cancel', 0, 'input_set', '', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 0, 0),
+('bx_directory_category', 'bx_directory', 'do_submit', '_bx_directory_form_category_input_do_submit', '', 0, 'submit', '_bx_directory_form_category_input_sys_do_submit', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
+('bx_directory_category', 'bx_directory', 'do_cancel', '_bx_directory_form_category_input_do_cancel', '', 0, 'button', '_bx_directory_form_category_input_sys_do_cancel', '', '', 0, 0, 0, 'a:2:{s:7:"onclick";s:45:"$(''.bx-popup-applied:visible'').dolPopupHide()";s:5:"class";s:22:"bx-def-margin-sec-left";}', '', '', '', '', '', '', '', 1, 0);
+
+INSERT INTO `sys_form_display_inputs`(`display_name`, `input_name`, `visible_for_levels`, `active`, `order`) VALUES 
+('bx_directory_category_add', 'parent_id', 2147483647, 1, 1),
+('bx_directory_category_add', 'type', 2147483647, 1, 2),
+('bx_directory_category_add', 'type_clone', 2147483647, 1, 3),
+('bx_directory_category_add', 'type_title', 2147483647, 1, 4),
+('bx_directory_category_add', 'title', 2147483647, 1, 5),
+('bx_directory_category_add', 'text', 2147483647, 1, 6),
+('bx_directory_category_add', 'icon', 2147483647, 1, 7),
+('bx_directory_category_add', 'controls', 2147483647, 1, 8),
+('bx_directory_category_add', 'do_submit', 2147483647, 1, 9),
+('bx_directory_category_add', 'do_cancel', 2147483647, 1, 10),
+
+('bx_directory_category_delete', 'delete_confirm', 2147483647, 1, 1),
+('bx_directory_category_delete', 'do_submit', 2147483647, 1, 2),
+
+('bx_directory_category_edit', 'parent_id', 2147483647, 1, 1),
+('bx_directory_category_edit', 'title', 2147483647, 1, 2),
+('bx_directory_category_edit', 'text', 2147483647, 1, 3),
+('bx_directory_category_edit', 'icon', 2147483647, 1, 4),
+('bx_directory_category_edit', 'controls', 2147483647, 1, 5),
+('bx_directory_category_edit', 'do_submit', 2147483647, 1, 6),
+('bx_directory_category_edit', 'do_cancel', 2147483647, 1, 7);
+
+
+-- FORMS: entry (ad)
+INSERT INTO `sys_objects_form`(`object`, `module`, `title`, `action`, `form_attrs`, `table`, `key`, `uri`, `uri_title`, `submit_name`, `params`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES 
+('bx_directory', 'bx_directory', '_bx_directory_form_entry', '', 'a:1:{s:7:"enctype";s:19:"multipart/form-data";}', 'bx_directory_entries', 'id', '', '', 'a:1:{i:0;s:9:"do_submit";}', '', 0, 1, 'BxDirFormEntry', 'modules/boonex/directory/classes/BxDirFormEntry.php');
 
 INSERT INTO `sys_form_displays`(`object`, `display_name`, `module`, `view_mode`, `title`) VALUES 
 ('bx_directory', 'bx_directory_entry_add', 'bx_directory', 0, '_bx_directory_form_entry_display_add'),
 ('bx_directory', 'bx_directory_entry_delete', 'bx_directory', 0, '_bx_directory_form_entry_display_delete'),
-('bx_directory', 'bx_directory_entry_edit', 'bx_directory', 0, '_bx_directory_form_entry_display_edit'),
-('bx_directory', 'bx_directory_entry_view', 'bx_directory', 1, '_bx_directory_form_entry_display_view');
+
+('bx_directory', 'bx_directory_entry_price_add', 'bx_directory', 0, '_bx_directory_form_entry_price_display_add'),
+('bx_directory', 'bx_directory_entry_price_edit', 'bx_directory', 0, '_bx_directory_form_entry_price_display_edit'),
+('bx_directory', 'bx_directory_entry_price_view', 'bx_directory', 1, '_bx_directory_form_entry_price_display_view'),
+
+('bx_directory', 'bx_directory_entry_price_year_add', 'bx_directory', 0, '_bx_directory_form_entry_price_year_display_add'),
+('bx_directory', 'bx_directory_entry_price_year_edit', 'bx_directory', 0, '_bx_directory_form_entry_price_year_display_edit'),
+('bx_directory', 'bx_directory_entry_price_year_view', 'bx_directory', 1, '_bx_directory_form_entry_price_year_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_directory', 'bx_directory', 'allow_view_to', '', '', 0, 'custom', '_bx_directory_form_entry_input_sys_allow_view_to', '_bx_directory_form_entry_input_allow_view_to', '', 1, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
 ('bx_directory', 'bx_directory', 'delete_confirm', 1, '', 0, 'checkbox', '_bx_directory_form_entry_input_sys_delete_confirm', '_bx_directory_form_entry_input_delete_confirm', '_bx_directory_form_entry_input_delete_confirm_info', 1, 0, 0, '', '', '', 'Avail', '', '_bx_directory_form_entry_input_delete_confirm_error', '', '', 1, 0),
-('bx_directory', 'bx_directory', 'do_publish', '_bx_directory_form_entry_input_do_publish', '', 0, 'submit', '_bx_directory_form_entry_input_sys_do_publish', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
 ('bx_directory', 'bx_directory', 'do_submit', '_bx_directory_form_entry_input_do_submit', '', 0, 'submit', '_bx_directory_form_entry_input_sys_do_submit', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
 ('bx_directory', 'bx_directory', 'location', '', '', 0, 'location', '_sys_form_input_sys_location', '_sys_form_input_location', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
 ('bx_directory', 'bx_directory', 'covers', 'a:1:{i:0;s:18:"bx_directory_html5";}', 'a:2:{s:19:"bx_directory_simple";s:26:"_sys_uploader_simple_title";s:18:"bx_directory_html5";s:25:"_sys_uploader_html5_title";}', 0, 'files', '_bx_directory_form_entry_input_sys_covers', '_bx_directory_form_entry_input_covers', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
@@ -378,58 +542,85 @@ INSERT INTO `sys_form_inputs`(`object`, `module`, `name`, `value`, `values`, `ch
 ('bx_directory', 'bx_directory', 'polls', '', '', 0, 'custom', '_bx_directory_form_entry_input_sys_polls', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
 ('bx_directory', 'bx_directory', 'text', '', '', 0, 'textarea', '_bx_directory_form_entry_input_sys_text', '_bx_directory_form_entry_input_text', '', 1, 0, 2, '', '', '', 'Avail', '', '_bx_directory_form_entry_input_text_err', 'XssHtml', '', 1, 0),
 ('bx_directory', 'bx_directory', 'title', '', '', 0, 'text', '_bx_directory_form_entry_input_sys_title', '_bx_directory_form_entry_input_title', '', 1, 0, 0, '', '', '', 'Avail', '', '_bx_directory_form_entry_input_title_err', 'Xss', '', 1, 0),
-('bx_directory', 'bx_directory', 'cat', '', '#!bx_directory_cats', 0, 'select', '_bx_directory_form_entry_input_sys_cat', '_bx_directory_form_entry_input_cat', '', 1, 0, 0, '', '', '', 'avail', '', '_bx_directory_form_entry_input_cat_err', 'Xss', '', 1, 0),
+('bx_directory', 'bx_directory', 'price', '', '', 0, 'text', '_bx_directory_form_entry_input_sys_price', '_bx_directory_form_entry_input_price', '', 0, 0, 0, '', '', '', '', '', '', 'Xss', '', 1, 0),
+('bx_directory', 'bx_directory', 'year', '', '', 0, 'text', '_bx_directory_form_entry_input_sys_year', '_bx_directory_form_entry_input_year', '', 0, 0, 0, '', '', '', '', '', '', 'Xss', '', 1, 0),
+('bx_directory', 'bx_directory', 'category', '', '', 0, 'select', '_bx_directory_form_entry_input_sys_category', '_bx_directory_form_entry_input_category', '', 1, 0, 0, '', '', '', 'avail', '', '_bx_directory_form_entry_input_category_err', 'Xss', '', 1, 0),
 ('bx_directory', 'bx_directory', 'added', '', '', 0, 'datetime', '_bx_directory_form_entry_input_sys_date_added', '_bx_directory_form_entry_input_date_added', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
 ('bx_directory', 'bx_directory', 'changed', '', '', 0, 'datetime', '_bx_directory_form_entry_input_sys_date_changed', '_bx_directory_form_entry_input_date_changed', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
-('bx_directory', 'bx_directory', 'published', '', '', 0, 'datetime', '_bx_directory_form_entry_input_sys_date_published', '_bx_directory_form_entry_input_date_published', '_bx_directory_form_entry_input_date_published_info', 0, 0, 0, '', '', '', '', '', '', 'DateTimeUtc', '', 1, 0),
 ('bx_directory', 'bx_directory', 'attachments', '', '', 0, 'custom', '_bx_directory_form_entry_input_sys_attachments', '', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
-('bx_directory', 'bx_directory', 'labels', '', '', 0, 'custom', '_sys_form_input_sys_labels', '_sys_form_input_labels', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
-('bx_directory', 'bx_directory', 'anonymous', '', '', 0, 'switcher', '_sys_form_input_sys_anonymous', '_sys_form_input_anonymous', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0),
-('bx_directory', 'bx_directory', 'disable_comments', '1', '', 0, 'switcher', '_bx_directory_form_entry_input_sys_disable_comments', '_bx_directory_form_entry_input_disable_comments', '', 0, 0, 0, '', '', '', '', '', '', 'Int', '', 1, 0);
-
-
+('bx_directory', 'bx_directory', 'labels', '', '', 0, 'custom', '_sys_form_input_sys_labels', '_sys_form_input_labels', '', 0, 0, 0, '', '', '', '', '', '', '', '', 1, 0);
 
 INSERT INTO `sys_form_display_inputs`(`display_name`, `input_name`, `visible_for_levels`, `active`, `order`) VALUES 
-('bx_directory_entry_add', 'delete_confirm', 2147483647, 0, 1),
-('bx_directory_entry_add', 'title', 2147483647, 1, 2),
-('bx_directory_entry_add', 'cat', 2147483647, 1, 3),
-('bx_directory_entry_add', 'text', 2147483647, 1, 4),
-('bx_directory_entry_add', 'attachments', 2147483647, 1, 5),
-('bx_directory_entry_add', 'pictures', 2147483647, 1, 6),
-('bx_directory_entry_add', 'videos', 2147483647, 1, 7),
-('bx_directory_entry_add', 'files', 2147483647, 1, 8),
-('bx_directory_entry_add', 'polls', 2147483647, 1, 9),
-('bx_directory_entry_add', 'covers', 2147483647, 1, 10),
-('bx_directory_entry_add', 'allow_view_to', 2147483647, 1, 11),
-('bx_directory_entry_add', 'location', 2147483647, 1, 12),
-('bx_directory_entry_add', 'published', 192, 1, 13),
-('bx_directory_entry_add', 'disable_comments', 192, 1, 14),
-('bx_directory_entry_add', 'do_publish', 2147483647, 1, 15),
+('bx_directory_entry_add', 'category', 2147483647, 1, 1),
+('bx_directory_entry_add', 'do_submit', 2147483647, 1, 2),
 
 ('bx_directory_entry_delete', 'delete_confirm', 2147483647, 1, 1),
 ('bx_directory_entry_delete', 'do_submit', 2147483647, 1, 2),
 
-('bx_directory_entry_edit', 'do_publish', 2147483647, 0, 1),
-('bx_directory_entry_edit', 'delete_confirm', 2147483647, 0, 2),
-('bx_directory_entry_edit', 'title', 2147483647, 1, 3),
-('bx_directory_entry_edit', 'cat', 2147483647, 1, 4),
-('bx_directory_entry_edit', 'text', 2147483647, 1, 5),
-('bx_directory_entry_edit', 'attachments', 2147483647, 1, 6),
-('bx_directory_entry_edit', 'pictures', 2147483647, 1, 7),
-('bx_directory_entry_edit', 'videos', 2147483647, 1, 8),
-('bx_directory_entry_edit', 'files', 2147483647, 1, 9),
-('bx_directory_entry_edit', 'polls', 2147483647, 1, 10),
-('bx_directory_entry_edit', 'covers', 2147483647, 1, 11),
-('bx_directory_entry_edit', 'allow_view_to', 2147483647, 1, 12),
-('bx_directory_entry_edit', 'location', 2147483647, 1, 13),
-('bx_directory_entry_edit', 'disable_comments', 192, 1, 14),
-('bx_directory_entry_edit', 'published', 192, 1, 15),
-('bx_directory_entry_edit', 'do_submit', 2147483647, 1, 16),
-
-('bx_directory_entry_view', 'cat', 2147483647, 1, 1),
-('bx_directory_entry_view', 'added', 2147483647, 1, 2),
-('bx_directory_entry_view', 'changed', 2147483647, 1, 3),
-('bx_directory_entry_view', 'published', 192, 1, 4);
+('bx_directory_entry_price_add', 'title', 2147483647, 1, 1),
+('bx_directory_entry_price_add', 'price', 2147483647, 1, 2),
+('bx_directory_entry_price_add', 'text', 2147483647, 1, 3),
+('bx_directory_entry_price_add', 'attachments', 2147483647, 1, 4),
+('bx_directory_entry_price_add', 'pictures', 2147483647, 1, 5),
+('bx_directory_entry_price_add', 'videos', 2147483647, 1, 6),
+('bx_directory_entry_price_add', 'files', 2147483647, 1, 7),
+('bx_directory_entry_price_add', 'polls', 2147483647, 1, 8),
+('bx_directory_entry_price_add', 'covers', 2147483647, 1, 9),
+('bx_directory_entry_price_add', 'allow_view_to', 2147483647, 1, 10),
+('bx_directory_entry_price_add', 'location', 2147483647, 1, 11),
+('bx_directory_entry_price_add', 'do_submit', 2147483647, 1, 12),
+
+('bx_directory_entry_price_edit', 'title', 2147483647, 1, 1),
+('bx_directory_entry_price_edit', 'price', 2147483647, 1, 2),
+('bx_directory_entry_price_edit', 'text', 2147483647, 1, 3),
+('bx_directory_entry_price_edit', 'attachments', 2147483647, 1, 4),
+('bx_directory_entry_price_edit', 'pictures', 2147483647, 1, 5),
+('bx_directory_entry_price_edit', 'videos', 2147483647, 1, 6),
+('bx_directory_entry_price_edit', 'files', 2147483647, 1, 7),
+('bx_directory_entry_price_edit', 'polls', 2147483647, 1, 8),
+('bx_directory_entry_price_edit', 'covers', 2147483647, 1, 9),
+('bx_directory_entry_price_edit', 'allow_view_to', 2147483647, 1, 10),
+('bx_directory_entry_price_edit', 'location', 2147483647, 1, 11),
+('bx_directory_entry_price_edit', 'do_submit', 2147483647, 1, 12),
+
+('bx_directory_entry_price_view', 'category', 2147483647, 1, 1),
+('bx_directory_entry_price_view', 'price', 2147483647, 1, 2),
+('bx_directory_entry_price_view', 'added', 2147483647, 1, 2),
+('bx_directory_entry_price_view', 'changed', 2147483647, 1, 3),
+
+('bx_directory_entry_price_year_add', 'title', 2147483647, 1, 1),
+('bx_directory_entry_price_year_add', 'price', 2147483647, 1, 2),
+('bx_directory_entry_price_year_add', 'year', 2147483647, 1, 3),
+('bx_directory_entry_price_year_add', 'text', 2147483647, 1, 4),
+('bx_directory_entry_price_year_add', 'attachments', 2147483647, 1, 5),
+('bx_directory_entry_price_year_add', 'pictures', 2147483647, 1, 6),
+('bx_directory_entry_price_year_add', 'videos', 2147483647, 1, 7),
+('bx_directory_entry_price_year_add', 'files', 2147483647, 1, 8),
+('bx_directory_entry_price_year_add', 'polls', 2147483647, 1, 9),
+('bx_directory_entry_price_year_add', 'covers', 2147483647, 1, 10),
+('bx_directory_entry_price_year_add', 'allow_view_to', 2147483647, 1, 11),
+('bx_directory_entry_price_year_add', 'location', 2147483647, 1, 12),
+('bx_directory_entry_price_year_add', 'do_submit', 2147483647, 1, 13),
+
+('bx_directory_entry_price_year_edit', 'title', 2147483647, 1, 1),
+('bx_directory_entry_price_year_edit', 'price', 2147483647, 1, 2),
+('bx_directory_entry_price_year_edit', 'year', 2147483647, 1, 3),
+('bx_directory_entry_price_year_edit', 'text', 2147483647, 1, 4),
+('bx_directory_entry_price_year_edit', 'attachments', 2147483647, 1, 5),
+('bx_directory_entry_price_year_edit', 'pictures', 2147483647, 1, 6),
+('bx_directory_entry_price_year_edit', 'videos', 2147483647, 1, 7),
+('bx_directory_entry_price_year_edit', 'files', 2147483647, 1, 8),
+('bx_directory_entry_price_year_edit', 'polls', 2147483647, 1, 9),
+('bx_directory_entry_price_year_edit', 'covers', 2147483647, 1, 10),
+('bx_directory_entry_price_year_edit', 'allow_view_to', 2147483647, 1, 11),
+('bx_directory_entry_price_year_edit', 'location', 2147483647, 1, 12),
+('bx_directory_entry_price_year_edit', 'do_submit', 2147483647, 1, 13),
+
+('bx_directory_entry_price_year_view', 'category', 2147483647, 1, 1),
+('bx_directory_entry_price_year_view', 'price', 2147483647, 1, 2),
+('bx_directory_entry_price_year_view', 'year', 2147483647, 1, 3),
+('bx_directory_entry_price_year_view', 'added', 2147483647, 1, 4),
+('bx_directory_entry_price_year_view', 'changed', 2147483647, 1, 5);
 
 -- FORMS: poll
 INSERT INTO `sys_objects_form` (`object`, `module`, `title`, `action`, `form_attrs`, `submit_name`, `table`, `key`, `uri`, `uri_title`, `params`, `deletable`, `active`, `override_class_name`, `override_class_file`) VALUES
@@ -453,45 +644,6 @@ INSERT INTO `sys_form_display_inputs` (`display_name`, `input_name`, `visible_fo
 ('bx_directory_poll_add', 'do_cancel', 2147483647, 1, 5);
 
 
--- PRE-VALUES
-INSERT INTO `sys_form_pre_lists`(`key`, `title`, `module`, `use_for_sets`) VALUES
-('bx_directory_cats', '_bx_directory_pre_lists_cats', 'bx_directory', '0');
-
-INSERT INTO `sys_form_pre_values`(`Key`, `Value`, `Order`, `LKey`, `LKey2`) VALUES
-('bx_directory_cats', '', 0, '_sys_please_select', ''),
-('bx_directory_cats', '1', 1, '_bx_directory_cat_Animals_Pets', ''),
-('bx_directory_cats', '2', 2, '_bx_directory_cat_Architecture', ''),
-('bx_directory_cats', '3', 3, '_bx_directory_cat_Art', ''),
-('bx_directory_cats', '4', 4, '_bx_directory_cat_Cars_Motorcycles', ''),
-('bx_directory_cats', '5', 5, '_bx_directory_cat_Celebrities', ''),
-('bx_directory_cats', '6', 6, '_bx_directory_cat_Design', ''),
-('bx_directory_cats', '7', 7, '_bx_directory_cat_DIY_Crafts', ''),
-('bx_directory_cats', '8', 8, '_bx_directory_cat_Education', ''),
-('bx_directory_cats', '9', 9, '_bx_directory_cat_Film_Music_Books', ''),
-('bx_directory_cats', '10', 10, '_bx_directory_cat_Food_Drink', ''),
-('bx_directory_cats', '11', 11, '_bx_directory_cat_Gardening', ''),
-('bx_directory_cats', '12', 12, '_bx_directory_cat_Geek', ''),
-('bx_directory_cats', '13', 13, '_bx_directory_cat_Hair_Beauty', ''),
-('bx_directory_cats', '14', 14, '_bx_directory_cat_Health_Fitness', ''),
-('bx_directory_cats', '15', 15, '_bx_directory_cat_History', ''),
-('bx_directory_cats', '16', 16, '_bx_directory_cat_Holidays_Events', ''),
-('bx_directory_cats', '17', 17, '_bx_directory_cat_Home_Decor', ''),
-('bx_directory_cats', '18', 18, '_bx_directory_cat_Humor', ''),
-('bx_directory_cats', '19', 19, '_bx_directory_cat_Illustrations_Posters', ''),
-('bx_directory_cats', '20', 20, '_bx_directory_cat_Kids_Parenting', ''),
-('bx_directory_cats', '21', 21, '_bx_directory_cat_Mens_Fashion', ''),
-('bx_directory_cats', '22', 22, '_bx_directory_cat_Outdoors', ''),
-('bx_directory_cats', '23', 23, '_bx_directory_cat_Photography', ''),
-('bx_directory_cats', '24', 24, '_bx_directory_cat_Products', ''),
-('bx_directory_cats', '25', 25, '_bx_directory_cat_Quotes', ''),
-('bx_directory_cats', '26', 26, '_bx_directory_cat_Science_Nature', ''),
-('bx_directory_cats', '27', 27, '_bx_directory_cat_Sports', ''),
-('bx_directory_cats', '28', 28, '_bx_directory_cat_Tattoos', ''),
-('bx_directory_cats', '29', 29, '_bx_directory_cat_Technology', ''),
-('bx_directory_cats', '30', 30, '_bx_directory_cat_Travel', ''),
-('bx_directory_cats', '31', 31, '_bx_directory_cat_Weddings', ''),
-('bx_directory_cats', '32', 32, '_bx_directory_cat_Womens_Fashion', '');
-
 -- COMMENTS
 INSERT INTO `sys_objects_cmts` (`Name`, `Module`, `Table`, `CharsPostMin`, `CharsPostMax`, `CharsDisplayMax`, `Html`, `PerView`, `PerViewReplies`, `BrowseType`, `IsBrowseSwitch`, `PostFormPosition`, `NumberOfLevels`, `IsDisplaySwitch`, `IsRatable`, `ViewingThreshold`, `IsOn`, `RootStylePrefix`, `BaseUrl`, `ObjectVote`, `TriggerTable`, `TriggerFieldId`, `TriggerFieldAuthor`, `TriggerFieldTitle`, `TriggerFieldComments`, `ClassName`, `ClassFile`) VALUES
 ('bx_directory', 'bx_directory', 'bx_directory_cmts', 1, 5000, 1000, 3, 5, 3, 'tail', 1, 'bottom', 1, 1, 1, -3, 1, 'cmt', 'page.php?i=view-post&id={object_id}', '', 'bx_directory_entries', 'id', 'author', 'title', 'comments', '', '');

+ 1 - 1
modules/boonex/directory/install/sql/uninstall.sql

@@ -1,6 +1,6 @@
 
 -- TABLES
-DROP TABLE IF EXISTS `bx_directory_entries`, `bx_directory_covers`, `bx_directory_files`, `bx_directory_photos`, `bx_directory_photos_resized`, `bx_directory_videos`, `bx_directory_videos_resized`, `bx_directory_cmts`, `bx_directory_votes`, `bx_directory_votes_track`, `bx_directory_reactions`, `bx_directory_reactions_track`, `bx_directory_views_track`, `bx_directory_meta_keywords`, `bx_directory_meta_locations`, `bx_directory_meta_mentions`, `bx_directory_reports`, `bx_directory_reports_track`, `bx_directory_favorites_track`, `bx_directory_scores`, `bx_directory_scores_track`, `bx_directory_polls`, `bx_directory_polls_answers`, `bx_directory_polls_answers_votes`, `bx_directory_polls_answers_votes_track`;
+DROP TABLE IF EXISTS `bx_directory_entries`, `bx_directory_categories_types`, `bx_directory_categories`, `bx_directory_covers`, `bx_directory_files`, `bx_directory_photos`, `bx_directory_photos_resized`, `bx_directory_videos`, `bx_directory_videos_resized`, `bx_directory_cmts`, `bx_directory_votes`, `bx_directory_votes_track`, `bx_directory_reactions`, `bx_directory_reactions_track`, `bx_directory_views_track`, `bx_directory_meta_keywords`, `bx_directory_meta_locations`, `bx_directory_meta_mentions`, `bx_directory_reports`, `bx_directory_reports_track`, `bx_directory_favorites_track`, `bx_directory_scores`, `bx_directory_scores_track`, `bx_directory_polls`, `bx_directory_polls_answers`, `bx_directory_polls_answers_votes`, `bx_directory_polls_answers_votes_track`;
 
 -- STORAGES & TRANSCODERS
 DELETE FROM `sys_objects_storage` WHERE `object` LIKE 'bx_directory_%';

+ 52 - 0
modules/boonex/directory/js/studio.js

@@ -0,0 +1,52 @@
+/**
+ * Copyright (c) UNA, Inc - https://una.io
+ * MIT License - https://opensource.org/licenses/MIT
+ *
+ * @defgroup    Directory Directory
+ * @ingroup     UnaModules
+ *
+ * @{
+ */
+
+function BxDirStudio(oOptions) {
+    this._sActionsUri = oOptions.sActionUri;
+    this._sActionsUrl = oOptions.sActionUrl;
+    this._sObjName = oOptions.sObjName == undefined ? 'oBxDirStudio' : oOptions.sObjName;
+    this._sAnimationEffect = oOptions.sAnimationEffect == undefined ? 'slide' : oOptions.sAnimationEffect;
+    this._iAnimationSpeed = oOptions.iAnimationSpeed == undefined ? 'slow' : oOptions.iAnimationSpeed;
+    this._aHtmlIds = oOptions.aHtmlIds == undefined ? {} : oOptions.aHtmlIds;
+}
+
+BxDirStudio.prototype.onChangeClone = function(oElement) {
+    var sClass = 'bx-form-element-wrapper';
+    var oName = $(oElement).parents('form:first').find("#bx-form-element-type_title input");
+
+    if($(oElement).attr('checked') != undefined)
+        oName.removeAttr('disabled').parents('.' + sClass + ':first').show();
+    else
+        oName.attr('disabled', 'disabled').parents('.' + sClass + ':first').hide();
+};
+
+BxDirStudio.prototype.loadingInButton = function(e, bShow) {
+    if($(e).length)
+        bx_loading_btn($(e), bShow);
+    else
+        bx_loading($('body'), bShow);	
+};
+
+BxDirStudio.prototype.loadingInBox = function(e, bShow) {
+    var oParent = $(e).length ? $(e).parents('.bx-base-text-poll:first') : $('body'); 
+    bx_loading(oParent, bShow);
+};
+
+BxDirStudio.prototype.loadingInBlock = function(e, bShow) {
+    var oParent = $(e).length ? $(e).parents('.bx-db-container:first') : $('body'); 
+    bx_loading(oParent, bShow);
+};
+
+BxDirStudio.prototype._getDefaultData = function() {
+    var oDate = new Date();
+    return jQuery.extend({}, this._oRequestParams, {_t:oDate.getTime()});
+};
+
+/** @} */

+ 19 - 0
modules/boonex/directory/template/category_form.html

@@ -0,0 +1,19 @@
+<div class="bx-dir-category-form bx-def-color-bg-block">
+    <div class="bx-dir-category-form-cnt">
+        __form__
+        <script type="text/javascript">
+            $(document).ready(function () {
+                $("#__form_id__").ajaxForm({ 
+                    dataType: "json",
+                    beforeSubmit: function (formData, jqForm, options) {
+                        bx_loading($("#__form_id__"), true);
+                    },
+                    success: function (data) {
+                        $(".bx-popup-applied:visible").dolPopupHide();
+                        glGrids.__object__.processJson(data, '__action__');
+                    }
+                });
+            });
+        </script>
+    </div>
+</div>