AntonLV 10 лет назад
Родитель
Сommit
c6bdc5f309

+ 1 - 0
install/sql/system.sql

@@ -423,6 +423,7 @@ CREATE TABLE `sys_options_mixes` (
   `name` varchar(64) NOT NULL default '',
   `title` varchar(64) NOT NULL default '',
   `active` tinyint(1) NOT NULL default '0',
+  `editable` tinyint(1) NOT NULL default '1',
   PRIMARY KEY (`id`),
   UNIQUE KEY `name`(`name`)
 ) ENGINE=MyISAM  DEFAULT CHARSET=utf8;

+ 7 - 0
modules/boonex/english/data/langs/system/en.xml

@@ -56,6 +56,7 @@
 	<string name="_Name"><![CDATA[Name]]></string>
 	<string name="_Name is required"><![CDATA[Name is required]]></string>
 	<string name="_No"><![CDATA[No]]></string>
+	<string name="_None"><![CDATA[None]]></string>
 	<string name="_No actions allowed for this membership"><![CDATA[No actions allowed for this membership]]></string>
 	<string name="_No such comment"><![CDATA[No such comment]]></string>
 	<string name="_Period"><![CDATA[Period]]></string>
@@ -545,8 +546,11 @@
 	<string name="_adm_btn_installed_submit"><![CDATA[Installed]]></string>
 	<string name="_adm_btn_login_submit"><![CDATA[Enter]]></string>
 	<string name="_adm_btn_queued_submit"><![CDATA[Queued]]></string>
+	<string name="_adm_btn_settings_import"><![CDATA[Import]]></string>
 	<string name="_adm_btn_settings_save"><![CDATA[Save]]></string>
 	<string name="_adm_btn_settings_mix_create"><![CDATA[Add New Mix]]></string>
+	<string name="_adm_btn_settings_mix_import"><![CDATA[Import Mix]]></string>
+	<string name="_adm_btn_settings_mix_export"><![CDATA[Export Mix]]></string>
 	<string name="_adm_btn_settings_mix_delete"><![CDATA[Delete Mix]]></string>
 	<string name="_adm_dbd_btn_update"><![CDATA[Update]]></string>
 	<string name="_adm_dbd_txt_version_n_available"><![CDATA[Trident {0} is available!]]></string>
@@ -1225,7 +1229,10 @@
 	<string name="_adm_stg_err_save_error_message"><![CDATA[Error in '{0}': {1}]]></string>
 	<string name="_adm_stg_err_cannot_perform"><![CDATA[Cannot perform the action.]]></string>
 	<string name="_adm_stg_txt_create_mix_popup"><![CDATA[Add New Mix]]></string>
+	<string name="_adm_stg_txt_import_mix_popup"><![CDATA[Import Mix]]></string>
+	<string name="_adm_stg_txt_mix_duplicate"><![CDATA[Duplicate from]]></string>
 	<string name="_adm_stg_txt_mix_title"><![CDATA[Mix Title]]></string>
+	<string name="_adm_stg_txt_mix_title_err"><![CDATA[Title is essential. Please, fill in this field.]]></string>
 	<string name="_adm_stg_txt_mix_system"><![CDATA[System]]></string>
 	<string name="_adm_stg_err_remove_old_image"><![CDATA[Cannot remove current image.]]></string>
 	<string name="_adm_str_cpt_files_file"><![CDATA[File]]></string>

+ 5 - 0
modules/boonex/russian/data/langs/system/ru.xml

@@ -56,6 +56,7 @@
 	<string name="_Name"><![CDATA[Имя]]></string>
 	<string name="_Name is required"><![CDATA[Необходимо указать имя]]></string>
 	<string name="_No"><![CDATA[Нет]]></string>
+	<string name="_None"><![CDATA[Никакой]]></string>
 	<string name="_No actions allowed for this membership"><![CDATA[Нет разрешённых действий для данного членства]]></string>
 	<string name="_No such comment"><![CDATA[Нет такого комментария]]></string>
 	<string name="_Period"><![CDATA[Период]]></string>
@@ -545,6 +546,7 @@
 	<string name="_adm_btn_installed_submit"><![CDATA[Установленные]]></string>
 	<string name="_adm_btn_login_submit"><![CDATA[Вход в Студию]]></string>
 	<string name="_adm_btn_queued_submit"><![CDATA[В очереди]]></string>
+	<string name="_adm_btn_settings_import"><![CDATA[Импортировать]]></string>
 	<string name="_adm_btn_settings_save"><![CDATA[Сохранить]]></string>
 	<string name="_adm_btn_settings_mix_create"><![CDATA[Создать набор]]></string>
 	<string name="_adm_btn_settings_mix_delete"><![CDATA[Удалить набор]]></string>
@@ -1225,7 +1227,10 @@
 	<string name="_adm_stg_err_save_error_message"><![CDATA[Ошибка в '{0}': {1}]]></string>
 	<string name="_adm_stg_err_cannot_perform"><![CDATA[Не могу выполнить действие.]]></string>
 	<string name="_adm_stg_txt_create_mix_popup"><![CDATA[Добавить новый набор]]></string>
+	<string name="_adm_stg_txt_import_mix_popup"><![CDATA[Импортировать набор]]></string>
+	<string name="_adm_stg_txt_mix_duplicate"><![CDATA[Продублировать]]></string>
 	<string name="_adm_stg_txt_mix_title"><![CDATA[Название набора]]></string>
+	<string name="_adm_stg_txt_mix_title_err"><![CDATA[Нужно указать название. Пожалуйста, заполните это поле.]]></string>
 	<string name="_adm_stg_txt_mix_system"><![CDATA[Системный]]></string>
 	<string name="_adm_stg_err_remove_old_image"><![CDATA[Невозможно удалить текущее изображение.]]></string>
 	<string name="_adm_str_cpt_files_file"><![CDATA[Файл]]></string>

+ 58 - 0
studio/classes/BxDolStudioSettings.php

@@ -87,6 +87,18 @@ class BxDolStudioSettings extends BxTemplStudioPage
                 		$aResult = array_merge($aResult, $this->getPopupCodeCreateMix());
 						break;
 
+					case 'import-mix':
+                		$aResult = array_merge($aResult, $this->getPopupCodeImportMix());
+						break;
+
+					case 'export-mix':
+                		$aResult = array_merge($aResult, $this->exportMix((int)$sValue));
+						break;
+
+					case 'download-mix':
+                		$aResult = array_merge($aResult, $this->downloadMix((int)$sValue));
+						break;
+
                 	case 'delete-mix':
                 		$aResult = array_merge($aResult, $this->deleteMix((int)$sValue));
 						break;
@@ -125,6 +137,52 @@ class BxDolStudioSettings extends BxTemplStudioPage
     	return $aResult;
     }
 
+    public function exportMix($iId)
+    {
+    	$aMix = array();
+    	$this->oDb->getMixes(array('type' => 'by_id', 'value' => $iId), $aMix, false);
+    	if(empty($aMix) || !is_array($aMix))
+    		return array('message' => _t('_adm_stg_err_cannot_perform'));
+
+		return array(
+			'url' => bx_append_url_params(BX_DOL_URL_STUDIO . 'settings.php', array(
+				'stg_action' => 'download-mix',
+    			'stg_value' => $iId,
+			)),
+			'eval' => $this->getPageJsObject() . '.onMixExport(oData);'
+		);
+    }
+
+    public function downloadMix($iId)
+    {
+    	$aMix = array();
+    	$this->oDb->getMixes(array('type' => 'by_id', 'value' => $iId), $aMix, false);
+    	if(empty($aMix) || !is_array($aMix))
+    		BxDolStudioTemplate::getInstance()->displayPageNotFound();
+
+		$aOptions = array();
+		$this->oDb->getMixesOptions(array('type' => 'by_mix_id_pair_option_value', 'value' => $iId, 'for_export' => 1), $aOptions, false);
+
+    	$aContent = array(
+    		'mix' => array(
+    			'type' => $aMix['type'],
+    			'category' => $aMix['category'],
+    			'name' => $aMix['name'],
+    			'title' => $aMix['title']
+    		),
+    		'options' => $aOptions
+    	);
+    	$sContent = json_encode($aContent);
+
+    	header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
+        header("Content-type: application/json");
+        header("Content-Length: " . strlen($sContent));
+        header("Content-Disposition: attachment; filename=\"". strtolower($aMix['name']) . ".json\"");
+
+        echo $sContent;
+        exit;
+    }
+    
     public function deleteMix($iId)
     {
     	$aResult = array();

+ 27 - 2
studio/classes/BxDolStudioSettingsQuery.php

@@ -231,7 +231,8 @@ class BxDolStudioSettingsQuery extends BxDolStudioPageQuery
                 `tm`.`category` AS `category`,
                 `tm`.`name` AS `name`,
                 `tm`.`title` AS `title`,
-                `tm`.`active` AS `active` " . $sSelectClause . "
+                `tm`.`active` AS `active`,
+                `tm`.`editable` AS `editable` " . $sSelectClause . "
             FROM `sys_options_mixes` AS `tm` " . $sJoinClause . "
             WHERE 1 " . $sWhereClause . " " . $sOrderClause . " " . $sLimitClause;
         $aItems = call_user_func_array(array($this, $aMethod['name']), $aMethod['params']);
@@ -274,7 +275,12 @@ class BxDolStudioSettingsQuery extends BxDolStudioPageQuery
                 	'mix_id' => $aParams['value']
                 );
 
-                $sWhereClause .= "AND `tmo`.`mix_id`=:mix_id";
+                $sWhereClause .= "AND `tmo`.`mix_id`=:mix_id ";
+
+                if(!empty($aParams['for_export'])) {
+                	$sJoinClause .= "LEFT JOIN `sys_options` AS `to` ON `tmo`.`option`=`to`.`name` ";
+                	$sWhereClause .= "AND `to`.`type` NOT IN ('file', 'image')";
+                }
                 break;
         }
 
@@ -292,6 +298,14 @@ class BxDolStudioSettingsQuery extends BxDolStudioPageQuery
         return (int)$this->getOne("SELECT FOUND_ROWS()");
     }
 
+	public function insertMixesOptions($aParamsSet)
+    {
+        if(empty($aParamsSet))
+            return false;
+
+        return (int)$this->query("INSERT INTO `sys_options_mixes2options` SET " . $this->arrayToSQL($aParamsSet)) > 0;
+    }
+
 	function deleteMixesOptions($aParamsWhere)
     {
         if(empty($aParamsWhere))
@@ -301,6 +315,17 @@ class BxDolStudioSettingsQuery extends BxDolStudioPageQuery
         return $this->query($sSql) !== false;
     }
 
+    function duplicateMixesOptions($iIdFrom, $iIdTo)
+    {
+    	$aBindings = array(
+    		'mix_id_from' => $iIdFrom,
+    		'mix_id_to' => $iIdTo
+    	);
+
+    	$sSql = "INSERT INTO `sys_options_mixes2options`(`option`, `mix_id`, `value`) SELECT `option`, :mix_id_to, `value` FROM `sys_options_mixes2options` WHERE `mix_id`=:mix_id_from";
+    	return $this->query($sSql, $aBindings) !== false;
+    }
+
     function getOptions($aParams, &$aItems, $bReturnCount = true)
     {
         $aMethod = array('name' => 'getAll', 'params' => array(0 => 'query'));

+ 47 - 0
studio/js/settings.js

@@ -66,6 +66,53 @@ BxDolStudioSettings.prototype.onMixCreate = function(oData) {
 	document.location.href = document.location.href;
 };
 
+BxDolStudioSettings.prototype.mixImport = function(oButton) {
+	var $this = this;
+	var oDate = new Date();
+
+	$.post(
+    	sUrlStudio + 'settings.php',
+    	{
+    		page: this.sType,
+    		category: this.sCategory,
+    		stg_action: 'import-mix',
+    		_t:oDate.getTime()
+    	},
+    	function (oData) {
+    		$this.processResult(oData);
+    	},
+    	'json'
+    );
+};
+
+BxDolStudioSettings.prototype.onMixImport = function(oData) {
+	document.location.href = document.location.href;
+};
+
+
+BxDolStudioSettings.prototype.mixExport = function(oButton, iId) {
+	var $this = this;
+	var oDate = new Date();
+
+	$.post(
+    	sUrlStudio + 'settings.php',
+    	{
+    		page: this.sType,
+    		category: this.sCategory,
+    		stg_action: 'export-mix',
+    		stg_value: iId,
+    		_t:oDate.getTime()
+    	},
+    	function (oData) {
+    		$this.processResult(oData);
+    	},
+    	'json'
+    );
+};
+
+BxDolStudioSettings.prototype.onMixExport = function(oData) {
+	document.location.href = oData.url;
+};
 BxDolStudioSettings.prototype.mixDelete = function(oButton, iId) {
 	var $this = this;
 	var oDate = new Date();

+ 180 - 18
studio/template/scripts/BxBaseStudioSettings.php

@@ -193,10 +193,10 @@ class BxBaseStudioSettings extends BxDolStudioSettings
 			$bTmplVarsMixes = !empty($aTmplVarsMixes);
         }
 
-        $bTmplVarsDeleteMix = !empty($this->sMix) && !empty($this->aMix);
-        $aTmplVarsDeleteMix = array();
-        if($bTmplVarsDeleteMix)
-        	$aTmplVarsDeleteMix = array(
+        $bMixSelected = !empty($this->sMix) && !empty($this->aMix);
+        $aTmplVarsButton = array();
+        if($bMixSelected)
+        	$aTmplVarsButton = array(
         		'js_object' => $sJsObject,
 				'id' => $this->aMix['id']
         	);
@@ -217,9 +217,13 @@ class BxBaseStudioSettings extends BxDolStudioSettings
         					'bx_repeat:mixes' => $aTmplVarsMixes,
         				) 
         			),
+        			'bx_if:show_export_mix' => array(
+        				'condition' => $bMixSelected,
+        				'content' => $aTmplVarsButton
+        			),
         			'bx_if:show_delete_mix' => array(
-        				'condition' => !empty($this->sMix) && !empty($this->aMix),
-        				'content' => $aTmplVarsDeleteMix
+        				'condition' => $bMixSelected,
+        				'content' => $aTmplVarsButton
         			),
         		)
         	), 
@@ -266,9 +270,24 @@ class BxBaseStudioSettings extends BxDolStudioSettings
                     'name' => 'title',
                     'caption' => _t('_adm_stg_txt_mix_title'),
                     'value' => '',
+					'required' => true,
+					'checker' => array(
+						'func' => 'avail',
+						'params' => array(),
+						'error' => _t('_adm_stg_txt_mix_title_err')
+					),
                     'db' => array (
                         'pass' => 'Xss',
             		)
+				),
+				'duplicate' => array(
+					'type' => 'select',
+                    'name' => 'duplicate',
+                    'caption' => _t('_adm_stg_txt_mix_duplicate'),
+					'values' => array(
+						array('key' => '', 'value' => _t('_None'))
+					),
+                    'value' => '',
 				),
 				'controls' => array(
 					'type' => 'input_set',
@@ -290,6 +309,11 @@ class BxBaseStudioSettings extends BxDolStudioSettings
             )
         );
 
+        $aMixes = array();
+        $this->oDb->getMixes(array('type' => 'by_type_category', 'type' => $this->sType, 'category' => $this->sCategory), $aMixes, false);
+        foreach($aMixes as $aMix)
+        	$aForm['inputs']['duplicate']['values'][] = array('key' => $aMix['name'], 'value' => $aMix['title']);
+
         $oForm = new BxTemplStudioFormView($aForm);
         $oForm->initChecker();
 
@@ -300,18 +324,24 @@ class BxBaseStudioSettings extends BxDolStudioSettings
         		'name' => $oForm->generateUri()
         	));
 
-        	if($iId !== false) {
-        		$this->oDb->updateMixes(array('active' => 0), array(
-        			'type' => $this->sType,
-        			'category' => is_string($this->sCategory) ? $this->sCategory : '',
-        			'active' => 1
-        		));
-        		$this->oDb->updateMixes(array('active' => 1), array('id' => $iId));
-
-        		return array(
-        			'eval' => $sJsObject . '.onMixCreate(oData);'
-        		);
-        	}
+        	if($iId === false)
+	        	return array('code' => '1', 'message' => _t('_adm_stg_err_cannot_perform'));
+
+			$this->oDb->updateMixes(array('active' => 0), array(
+				'type' => $this->sType,
+				'category' => is_string($this->sCategory) ? $this->sCategory : '',
+				'active' => 1
+			));
+			$this->oDb->updateMixes(array('active' => 1), array('id' => $iId));
+
+			$aDuplicate = array();
+			$this->oDb->getMixes(array('type' => 'by_name', 'value' => $oForm->getCleanValue('duplicate')), $aDuplicate, false);
+			if(!empty($aDuplicate) && is_array($aDuplicate)) 
+				$this->oDb->duplicateMixesOptions($aDuplicate['id'], $iId);
+
+			return array(
+				'eval' => $sJsObject . '.onMixCreate(oData);'
+			);
         }
 
 		return array(
@@ -323,6 +353,125 @@ class BxBaseStudioSettings extends BxDolStudioSettings
 		);
     }
 
+	public function getPopupCodeImportMix()
+    {
+    	$oTemplate = BxDolStudioTemplate::getInstance();
+    	$sJsObject = $this->getPageJsObject();
+
+    	$sForm = 'adm-settings-import-mix-form';
+    	$aForm = array(
+            'form_attrs' => array(
+                'id' => $sForm,
+                'name' => $sForm,
+                'action' => bx_append_url_params(BX_DOL_URL_STUDIO . 'settings.php', array('stg_action' => 'import-mix')),
+                'method' => 'post',
+                'enctype' => 'multipart/form-data'
+            ),
+            'params' => array(
+                'db' => array(
+                    'table' => 'sys_options_mixes',
+                    'key' => 'id',
+                    'uri' => 'name',
+                    'uri_title' => 'title',
+                    'submit_name' => 'save'
+                ),
+            ),
+            'inputs' => array(
+            	'page' => array(
+            		'type' => 'hidden',
+                    'name' => 'page',
+                    'value' => $this->sType
+				),
+				'category' => array(
+            		'type' => 'hidden',
+                    'name' => 'category',
+                    'value' => is_array($this->sCategory) ? json_encode($this->sCategory) : $this->sCategory,
+				),
+            	'file' => array(
+            		'type' => 'file',
+                    'name' => 'file',
+                    'caption' => '',
+                    'value' => '',
+				),
+				'controls' => array(
+					'type' => 'input_set',
+	            	array(
+	                    'type' => 'submit',
+	                    'name' => 'save',
+	                    'value' => _t('_adm_btn_settings_import'),
+	                ),
+	                array(
+	                    'type' => 'button',
+	                    'name' => 'cancel',
+	                    'value' => _t('_adm_txt_confirm_cancel'),
+	                	'attrs' => array(
+	                		'class' => 'bx-def-margin-sec-left-auto',
+	                		'onclick' => '$(".bx-popup-applied:visible").dolPopupHide()'
+	                	)
+	                )
+				)
+            )
+        );
+
+        $oForm = new BxTemplStudioFormView($aForm);
+        $oForm->initChecker();
+
+        if($oForm->isSubmittedAndValid()) {
+        	$sError = _t('_adm_stg_err_cannot_perform');
+
+        	$aFile = $_FILES['file'];
+        	if(empty($aFile['tmp_name']))
+        		return array('code' => '1', 'message' => $sError);
+
+			$sFile = $aFile['tmp_name'];
+        	$rHandle = @fopen($sFile, "r");
+        	if(!$rHandle)
+        		return array('code' => '2', 'message' => $sError);
+        	
+			$sContents = fread($rHandle, filesize($sFile));
+			fclose($rHandle);
+
+			$aContent = json_decode($sContents, true);
+			if(!is_array($aContent) || empty($aContent['mix']) || empty($aContent['options']))
+				return array('code' => '3', 'message' => $sError);
+
+        	$iId = $oForm->insert(array(
+        		'type' => $aContent['mix']['type'],
+        		'category' => $aContent['mix']['category'],
+        		'name' => $aContent['mix']['name'],
+        		'title' => $aContent['mix']['title']
+        	));
+        	if($iId === false)
+	        	return array('code' => '4', 'message' => $sError); 
+
+			foreach($aContent['options'] as $sKey => $sValue)
+				$this->oDb->insertMixesOptions(array(
+					'option' => $sKey,
+					'mix_id' => $iId,
+					'value' => $sValue
+				));
+
+			$this->oDb->updateMixes(array('active' => 0), array(
+				'type' => $this->sType,
+				'category' => is_string($this->sCategory) ? $this->sCategory : '',
+				'active' => 1
+			));
+			$this->oDb->updateMixes(array('active' => 1), array('id' => $iId));
+
+			return array(
+				'eval' => $sJsObject . '.onMixImport(oData);'
+			);
+        }
+
+		return array(
+			'popup' => BxTemplStudioFunctions::getInstance()->popupBox('adm-stg-import-mix-popup', _t('_adm_stg_txt_import_mix_popup'), $oTemplate->parseHtmlByName('stg_import_mix.html', array(
+				'js_object' => $sJsObject,
+				'form_id' => $sForm,
+				'form' => $oForm->getCode(true),
+			)))
+		);
+    }
+
     protected function header($aCategory, $aFields)
     {
         return array_merge(
@@ -343,6 +492,11 @@ class BxBaseStudioSettings extends BxDolStudioSettings
     	$oTemplate = BxDolStudioTemplate::getInstance();
 
     	$mixedValue = isset($aItems2Mixes[$aItem['name']]) ? $aItems2Mixes[$aItem['name']] : $aItem['value'];
+    	$aAttributes = array();
+    	if(!empty($this->aMix) && (int)$this->aMix['editable'] == 0)
+    	$aAttributes = array_merge($aAttributes, array(
+    		'disabled' => 'disabled'
+    	)); 	
 
         $aField = array();
         switch($aItem['type']) {
@@ -352,6 +506,7 @@ class BxBaseStudioSettings extends BxDolStudioSettings
                     'name' => $aItem['name'],
                     'caption' => _t($aItem['caption']),
                     'value' => $mixedValue,
+                	'attrs' => $aAttributes,
                     'db' => array (
                         'pass' => 'Xss',
                     ),
@@ -363,6 +518,7 @@ class BxBaseStudioSettings extends BxDolStudioSettings
                     'name' => $aItem['name'],
                     'caption' => _t($aItem['caption']),
                     'value' => $mixedValue,
+                	'attrs' => $aAttributes,
                     'db' => array (
                         'pass' => 'XssHtml',
                     ),
@@ -375,6 +531,7 @@ class BxBaseStudioSettings extends BxDolStudioSettings
                     'caption' => _t($aItem['caption']),
                     'value' => 'on',
                     'checked' => $mixedValue == 'on',
+                	'attrs' => $aAttributes,
                     'db' => array (
                         'pass' => 'Xss',
                     ),
@@ -388,6 +545,7 @@ class BxBaseStudioSettings extends BxDolStudioSettings
                     'caption' => _t($aItem['caption']),
                     'value' => !empty($mixedValue) ? explode(',', $mixedValue) : array(),
                 	'reverse' => $aItem['type'] == 'rlist',
+                	'attrs' => $aAttributes,
                     'db' => array (
                         'pass' => 'Xss',
                     ),
@@ -406,6 +564,7 @@ class BxBaseStudioSettings extends BxDolStudioSettings
                     'caption' => _t($aItem['caption']),
                     'value' => $mixedValue,
                     'values' => array(),
+                	'attrs' => $aAttributes,
                     'db' => array (
                         'pass' => 'Xss',
                     ),
@@ -423,6 +582,7 @@ class BxBaseStudioSettings extends BxDolStudioSettings
                     'name' => $aItem['name'],
                     'caption' => _t($aItem['caption']),
                     'value' => $mixedValue,
+                	'attrs' => $aAttributes,
                     'db' => array (
                         'pass' => 'Xss'
                     )
@@ -446,6 +606,7 @@ class BxBaseStudioSettings extends BxDolStudioSettings
 					),
                     'caption' => _t($aItem['caption']),
                     'value' => $mixedValue,
+					'attrs' => $aAttributes,
                     'db' => array (
                         'pass' => 'Xss'
                     )
@@ -458,6 +619,7 @@ class BxBaseStudioSettings extends BxDolStudioSettings
                     'name' => $aItem['name'],
                     'caption' => _t($aItem['caption']),
                     'value' => $mixedValue,
+                	'attrs' => $aAttributes,
                     'db' => array (
                         'pass' => 'Xss',
                     ),

+ 8 - 0
studio/template/settings.html

@@ -23,6 +23,14 @@
 			<a class="bx-btn" href="javascript:void(0)" onclick="javascript: __js_object__.mixCreate(this)">
 				<bx_text:_adm_btn_settings_mix_create />
 			</a>
+			<a class="bx-btn" href="javascript:void(0)" onclick="javascript: __js_object__.mixImport(this)">
+				<bx_text:_adm_btn_settings_mix_import />
+			</a>
+			<bx_if:show_export_mix>
+				<a class="bx-btn" href="javascript:void(0)" onclick="javascript: __js_object__.mixExport(this, __id__)">
+					<bx_text:_adm_btn_settings_mix_export />
+				</a>
+			</bx_if:show_export_mix>
 			<bx_if:show_delete_mix>
 				<a class="bx-btn" href="javascript:void(0)" onclick="javascript: __js_object__.mixDelete(this, __id__)">
 					<bx_text:_adm_btn_settings_mix_delete />

+ 19 - 0
studio/template/stg_import_mix.html

@@ -0,0 +1,19 @@
+<div class="bx-stg-import-mix bx-def-color-bg-block">
+    <div class="bx-stg-import-mix-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 (oData) {
+                        $(".bx-popup-applied:visible").dolPopupHide();
+                        __js_object__.processResult(oData);
+                    }
+                });
+            });
+        </script>
+    </div>
+</div>