mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-09-07 16:37:02 +03:00
Extend plugin config with a grouping class
This commit is contained in:
parent
05f1d62041
commit
e0ebc999d5
10 changed files with 162 additions and 129 deletions
|
|
@ -21,11 +21,11 @@ class PluginPopupView extends AbstractViewPopup {
|
||||||
readme: ''
|
readme: ''
|
||||||
});
|
});
|
||||||
|
|
||||||
this.configures = ko.observableArray();
|
this.config = ko.observableArray();
|
||||||
|
|
||||||
this.addComputables({
|
this.addComputables({
|
||||||
hasReadme: () => !!this.readme(),
|
hasReadme: () => !!this.readme(),
|
||||||
hasConfiguration: () => 0 < this.configures().length
|
hasConfiguration: () => 0 < this.config().length
|
||||||
});
|
});
|
||||||
|
|
||||||
this.bDisabeCloseOnEsc = true;
|
this.bDisabeCloseOnEsc = true;
|
||||||
|
|
@ -44,7 +44,7 @@ class PluginPopupView extends AbstractViewPopup {
|
||||||
Settings: {}
|
Settings: {}
|
||||||
};
|
};
|
||||||
|
|
||||||
this.configures.forEach(oItem => {
|
this.config.forEach(oItem => {
|
||||||
let value = oItem.value();
|
let value = oItem.value();
|
||||||
if (false === value || true === value) {
|
if (false === value || true === value) {
|
||||||
value = value ? 1 : 0;
|
value = value ? 1 : 0;
|
||||||
|
|
@ -64,7 +64,7 @@ class PluginPopupView extends AbstractViewPopup {
|
||||||
this.id('');
|
this.id('');
|
||||||
this.name('');
|
this.name('');
|
||||||
this.readme('');
|
this.readme('');
|
||||||
this.configures([]);
|
this.config([]);
|
||||||
|
|
||||||
if (oPlugin) {
|
if (oPlugin) {
|
||||||
this.id(oPlugin.Id);
|
this.id(oPlugin.Id);
|
||||||
|
|
@ -73,16 +73,11 @@ class PluginPopupView extends AbstractViewPopup {
|
||||||
|
|
||||||
const config = oPlugin.Config;
|
const config = oPlugin.Config;
|
||||||
if (arrayLength(config)) {
|
if (arrayLength(config)) {
|
||||||
this.configures(
|
this.config(
|
||||||
config.map(item => ({
|
config.map(item => {
|
||||||
value: ko.observable(item[0]),
|
item.value = ko.observable(item.value);
|
||||||
placeholder: ko.observable(item[6]),
|
return item;
|
||||||
Name: item[1],
|
})
|
||||||
Type: item[2],
|
|
||||||
Label: item[3],
|
|
||||||
Default: item[4],
|
|
||||||
Desc: item[5]
|
|
||||||
}))
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,9 @@ class ChangePasswordPlugin extends \RainLoop\Plugins\AbstractPlugin
|
||||||
{
|
{
|
||||||
const
|
const
|
||||||
NAME = 'Change Password',
|
NAME = 'Change Password',
|
||||||
VERSION = '2.9',
|
VERSION = '2.12',
|
||||||
RELEASE = '2021-07-20',
|
RELEASE = '2022-02-10',
|
||||||
REQUIRED = '2.9.1',
|
REQUIRED = '2.12.0',
|
||||||
CATEGORY = 'Security',
|
CATEGORY = 'Security',
|
||||||
DESCRIPTION = 'Extension to allow users to change their passwords';
|
DESCRIPTION = 'Extension to allow users to change their passwords';
|
||||||
|
|
||||||
|
|
@ -96,17 +96,21 @@ class ChangePasswordPlugin extends \RainLoop\Plugins\AbstractPlugin
|
||||||
->SetDefaultValue(70),
|
->SetDefaultValue(70),
|
||||||
];
|
];
|
||||||
foreach ($this->getSupportedDrivers(true) as $name => $class) {
|
foreach ($this->getSupportedDrivers(true) as $name => $class) {
|
||||||
$result[] = \RainLoop\Plugins\Property::NewInstance("driver_{$name}_enabled")
|
$group = new \RainLoop\Plugins\PropertyCollection($name);
|
||||||
->SetLabel('Enable ' . $class::NAME)
|
$props = [
|
||||||
->SetType(\RainLoop\Enumerations\PluginPropertyType::BOOL)
|
\RainLoop\Plugins\Property::NewInstance("driver_{$name}_enabled")
|
||||||
->SetDescription($class::DESCRIPTION)
|
->SetLabel('Enable ' . $class::NAME)
|
||||||
->SetDefaultValue(false);
|
->SetType(\RainLoop\Enumerations\PluginPropertyType::BOOL)
|
||||||
$result[] = \RainLoop\Plugins\Property::NewInstance("driver_{$name}_allowed_emails")
|
->SetDescription($class::DESCRIPTION)
|
||||||
->SetLabel('Allowed emails')
|
->SetDefaultValue(false),
|
||||||
->SetType(\RainLoop\Enumerations\PluginPropertyType::STRING_TEXT)
|
\RainLoop\Plugins\Property::NewInstance("driver_{$name}_allowed_emails")
|
||||||
->SetDescription('Allowed emails, space as delimiter, wildcard supported. Example: user1@example.net user2@example1.net *@example2.net')
|
->SetLabel('Allowed emails')
|
||||||
->SetDefaultValue('*');
|
->SetType(\RainLoop\Enumerations\PluginPropertyType::STRING_TEXT)
|
||||||
$result = \array_merge($result, \call_user_func("{$class}::configMapping"));
|
->SetDescription('Allowed emails, space as delimiter, wildcard supported. Example: user1@example.net user2@example1.net *@example2.net')
|
||||||
|
->SetDefaultValue('*')
|
||||||
|
];
|
||||||
|
$group->exchangeArray(\array_merge($props, \call_user_func("{$class}::configMapping")));
|
||||||
|
$result[] = $group;
|
||||||
}
|
}
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -791,34 +791,41 @@ trait Admin
|
||||||
$mResult = false;
|
$mResult = false;
|
||||||
$sId = (string) $this->GetActionParam('Id', '');
|
$sId = (string) $this->GetActionParam('Id', '');
|
||||||
|
|
||||||
if (!empty($sId))
|
if (!empty($sId)) {
|
||||||
{
|
|
||||||
$oPlugin = $this->Plugins()->CreatePluginByName($sId);
|
$oPlugin = $this->Plugins()->CreatePluginByName($sId);
|
||||||
if ($oPlugin)
|
if ($oPlugin) {
|
||||||
{
|
|
||||||
$mResult = array(
|
$mResult = array(
|
||||||
'Id' => $sId,
|
'@Object' => 'Object/Plugin',
|
||||||
'Name' => $oPlugin->Name(),
|
'Id' => $sId,
|
||||||
'Readme' => $oPlugin->Description(),
|
'Name' => $oPlugin->Name(),
|
||||||
'Config' => array()
|
'Readme' => $oPlugin->Description(),
|
||||||
|
'Config' => array()
|
||||||
);
|
);
|
||||||
|
|
||||||
$aMap = $oPlugin->ConfigMap();
|
$aMap = $oPlugin->ConfigMap();
|
||||||
$oConfig = $oPlugin->Config();
|
if (\is_array($aMap)) {
|
||||||
if (is_array($aMap))
|
$oConfig = $oPlugin->Config();
|
||||||
{
|
foreach ($aMap as $oItem) {
|
||||||
foreach ($aMap as $oItem)
|
if ($oItem) {
|
||||||
{
|
if ($oItem instanceof \RainLoop\Plugins\Property) {
|
||||||
if ($oItem && ($oItem instanceof \RainLoop\Plugins\Property))
|
if (PluginPropertyType::PASSWORD === $oItem->Type()) {
|
||||||
{
|
$oItem->SetValue(APP_DUMMY);
|
||||||
$aItem = $oItem->ToArray();
|
} else {
|
||||||
$aItem[0] = $oConfig->Get('plugin', $oItem->Name(), '');
|
$oItem->SetValue($oConfig->Get('plugin', $oItem->Name(), ''));
|
||||||
if (PluginPropertyType::PASSWORD === $oItem->Type())
|
}
|
||||||
{
|
$mResult['Config'][] = $oItem;
|
||||||
$aItem[0] = APP_DUMMY;
|
} else if ($oItem instanceof \RainLoop\Plugins\PropertyCollection) {
|
||||||
|
foreach ($oItem as $oSubItem) {
|
||||||
|
if ($oSubItem && $oSubItem instanceof \RainLoop\Plugins\Property) {
|
||||||
|
if (PluginPropertyType::PASSWORD === $oSubItem->Type()) {
|
||||||
|
$oSubItem->SetValue(APP_DUMMY);
|
||||||
|
} else {
|
||||||
|
$oSubItem->SetValue($oConfig->Get('plugin', $oSubItem->Name(), ''));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$mResult['Config'][] = $oItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
$mResult['Config'][] = $aItem;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -841,7 +848,7 @@ trait Admin
|
||||||
if ($oPlugin)
|
if ($oPlugin)
|
||||||
{
|
{
|
||||||
$oConfig = $oPlugin->Config();
|
$oConfig = $oPlugin->Config();
|
||||||
$aMap = $oPlugin->ConfigMap();
|
$aMap = $oPlugin->ConfigMap(true);
|
||||||
if (is_array($aMap))
|
if (is_array($aMap))
|
||||||
{
|
{
|
||||||
$aSettings = (array) $this->GetActionParam('Settings', []);
|
$aSettings = (array) $this->GetActionParam('Settings', []);
|
||||||
|
|
|
||||||
|
|
@ -7,39 +7,28 @@ class Plugin extends \RainLoop\Config\AbstractConfig
|
||||||
/**
|
/**
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
private $aMap;
|
private $aMap = array();
|
||||||
|
|
||||||
public function __construct(string $sPluginName, array $aMap = array())
|
public function __construct(string $sPluginName, array $aMap = array())
|
||||||
{
|
{
|
||||||
$this->aMap = is_array($aMap) ? $this->convertConfigMap($aMap) : array();
|
if (\count($aMap)) {
|
||||||
|
|
||||||
parent::__construct('plugin-'.$sPluginName.'.ini', '; SnappyMail plugin ('.$sPluginName.')');
|
|
||||||
}
|
|
||||||
|
|
||||||
private function convertConfigMap(array $aMap) : array
|
|
||||||
{
|
|
||||||
if (\count($aMap))
|
|
||||||
{
|
|
||||||
$aResultMap = array();
|
$aResultMap = array();
|
||||||
foreach ($aMap as /* @var $oProperty \RainLoop\Plugins\Property */ $oProperty)
|
foreach ($aMap as /* @var $oProperty \RainLoop\Plugins\Property */ $oProperty) {
|
||||||
{
|
if ($oProperty) {
|
||||||
if ($oProperty)
|
|
||||||
{
|
|
||||||
$mValue = $oProperty->DefaultValue();
|
$mValue = $oProperty->DefaultValue();
|
||||||
$sValue = \is_array($mValue) && isset($mValue[0]) ? $mValue[0] : $mValue;
|
$sValue = \is_array($mValue) && isset($mValue[0]) ? $mValue[0] : $mValue;
|
||||||
$aResultMap[$oProperty->Name()] = array($sValue, '');
|
$aResultMap[$oProperty->Name()] = array($sValue, '');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (\count($aResultMap))
|
if (\count($aResultMap)) {
|
||||||
{
|
$this->aMap = array(
|
||||||
return array(
|
|
||||||
'plugin' => $aResultMap
|
'plugin' => $aResultMap
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return array();
|
parent::__construct('plugin-'.$sPluginName.'.ini', '; SnappyMail plugin ('.$sPluginName.')');
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function defaultValues() : array
|
protected function defaultValues() : array
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ namespace RainLoop\Enumerations;
|
||||||
class PluginPropertyType
|
class PluginPropertyType
|
||||||
{
|
{
|
||||||
const
|
const
|
||||||
|
GROUP = 7,
|
||||||
STRING = 0,
|
STRING = 0,
|
||||||
INT = 1,
|
INT = 1,
|
||||||
STRING_TEXT = 2,
|
STRING_TEXT = 2,
|
||||||
|
|
|
||||||
|
|
@ -111,13 +111,31 @@ abstract class AbstractPlugin
|
||||||
return $this->sPath;
|
return $this->sPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
final public function ConfigMap() : array
|
final public function ConfigMap(bool $flatten = false) : array
|
||||||
{
|
{
|
||||||
if (null === $this->aConfigMap)
|
if (null === $this->aConfigMap)
|
||||||
{
|
{
|
||||||
$this->aConfigMap = $this->configMapping();
|
$this->aConfigMap = $this->configMapping();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($flatten) {
|
||||||
|
$result = [];
|
||||||
|
foreach ($this->aConfigMap as $oItem) {
|
||||||
|
if ($oItem) {
|
||||||
|
if ($oItem instanceof \RainLoop\Plugins\Property) {
|
||||||
|
$result[] = $oItem;
|
||||||
|
} else if ($oItem instanceof \RainLoop\Plugins\PropertyCollection) {
|
||||||
|
foreach ($oItem as $oSubItem) {
|
||||||
|
if ($oSubItem && $oSubItem instanceof \RainLoop\Plugins\Property) {
|
||||||
|
$result[] = $oSubItem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
return $this->aConfigMap;
|
return $this->aConfigMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,7 @@ class Manager
|
||||||
->SetName($sName)
|
->SetName($sName)
|
||||||
->SetPath(static::getPluginPath($sName))
|
->SetPath(static::getPluginPath($sName))
|
||||||
->SetPluginManager($this)
|
->SetPluginManager($this)
|
||||||
->SetPluginConfig(new \RainLoop\Config\Plugin($sName, $oPlugin->ConfigMap()))
|
->SetPluginConfig(new \RainLoop\Config\Plugin($sName, $oPlugin->ConfigMap(true)))
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -223,7 +223,7 @@ class Manager
|
||||||
if ($oPlugin)
|
if ($oPlugin)
|
||||||
{
|
{
|
||||||
$aConfig = array();
|
$aConfig = array();
|
||||||
$aMap = $oPlugin->ConfigMap();
|
$aMap = $oPlugin->ConfigMap(true);
|
||||||
if (\is_array($aMap))
|
if (\is_array($aMap))
|
||||||
{
|
{
|
||||||
foreach ($aMap as /* @var $oPluginProperty \RainLoop\Plugins\Property */ $oPluginProperty)
|
foreach ($aMap as /* @var $oPluginProperty \RainLoop\Plugins\Property */ $oPluginProperty)
|
||||||
|
|
@ -468,16 +468,15 @@ class Manager
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function ReadLang(string $sLang, array &$aLang) : self
|
public function ReadLang(string $sLang, array &$aLang) : void
|
||||||
{
|
{
|
||||||
if ($this->bIsEnabled)
|
if ($this->bIsEnabled) {
|
||||||
{
|
foreach ($this->aPlugins as $oPlugin) {
|
||||||
foreach ($this->aPlugins as $oPlugin)
|
if ($oPlugin->UseLangs()) {
|
||||||
{
|
|
||||||
if ($oPlugin->UseLangs())
|
|
||||||
{
|
|
||||||
$sPath = $oPlugin->Path().'/langs/';
|
$sPath = $oPlugin->Path().'/langs/';
|
||||||
$aPLang = [];
|
$aPLang = [];
|
||||||
|
|
||||||
|
// First get english
|
||||||
if (\is_file("{$sPath}en.ini")) {
|
if (\is_file("{$sPath}en.ini")) {
|
||||||
$aPLang = \parse_ini_file("{$sPath}en.ini", true);
|
$aPLang = \parse_ini_file("{$sPath}en.ini", true);
|
||||||
} else if (\is_file("{$sPath}en.json")) {
|
} else if (\is_file("{$sPath}en.json")) {
|
||||||
|
|
@ -487,8 +486,8 @@ class Manager
|
||||||
$aLang = \array_replace_recursive($aLang, $aPLang);
|
$aLang = \array_replace_recursive($aLang, $aPLang);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ('en' !== $sLang)
|
// Now get native
|
||||||
{
|
if ('en' !== $sLang) {
|
||||||
$aPLang = [];
|
$aPLang = [];
|
||||||
if (\is_file("{$sPath}{$sLang}.ini")) {
|
if (\is_file("{$sPath}{$sLang}.ini")) {
|
||||||
$aPLang = \parse_ini_file("{$sPath}{$sLang}.ini", true);
|
$aPLang = \parse_ini_file("{$sPath}{$sLang}.ini", true);
|
||||||
|
|
@ -504,8 +503,6 @@ class Manager
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function IsEnabled() : bool
|
public function IsEnabled() : bool
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,18 @@
|
||||||
|
|
||||||
namespace RainLoop\Plugins;
|
namespace RainLoop\Plugins;
|
||||||
|
|
||||||
class Property
|
class Property implements \JsonSerializable
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
private $sName;
|
private $sName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var mixed
|
||||||
|
*/
|
||||||
|
private $mValue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
|
|
@ -62,6 +67,14 @@ class Property
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param mixed $mValue
|
||||||
|
*/
|
||||||
|
public function SetValue($mValue) : void
|
||||||
|
{
|
||||||
|
$this->mValue = $mValue;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param mixed $mDefaultValue
|
* @param mixed $mDefaultValue
|
||||||
*/
|
*/
|
||||||
|
|
@ -138,16 +151,17 @@ class Property
|
||||||
return $this->sPlaceholder;
|
return $this->sPlaceholder;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function ToArray() : array
|
public function jsonSerialize()
|
||||||
{
|
{
|
||||||
return array(
|
return array(
|
||||||
'',
|
'@Object' => 'Object/PluginProperty',
|
||||||
$this->sName,
|
'value' => $this->mValue,
|
||||||
$this->iType,
|
'placeholder' => $this->sPlaceholder,
|
||||||
$this->sLabel,
|
'Name' => $this->sName,
|
||||||
$this->mDefaultValue,
|
'Type' => $this->iType,
|
||||||
$this->sDesc,
|
'Label' => $this->sLabel,
|
||||||
$this->sPlaceholder
|
'Default' => $this->mDefaultValue,
|
||||||
|
'Desc' => $this->sDesc
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,37 +1,35 @@
|
||||||
<label data-bind="text: Label, visible: 5 !== Type"></label>
|
<label data-bind="text: Label, visible: 5 !== Type"></label>
|
||||||
<div>
|
<!-- ko if: 0 === Type -->
|
||||||
<!-- ko if: 0 === Type -->
|
<input type="text" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"
|
||||||
<input type="text" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"
|
data-bind="value: value, attr: {placeholder: placeholder}" />
|
||||||
data-bind="value: value, attr: {placeholder: placeholder}" />
|
<!-- /ko -->
|
||||||
<!-- /ko -->
|
<!-- ko if: 1 === Type -->
|
||||||
<!-- ko if: 1 === Type -->
|
<input type="number" step="1"
|
||||||
<input type="number" step="1"
|
data-bind="value: value, attr: {placeholder: placeholder}" />
|
||||||
data-bind="value: value, attr: {placeholder: placeholder}" />
|
<!-- /ko -->
|
||||||
<!-- /ko -->
|
<!-- ko if: 3 === Type -->
|
||||||
<!-- ko if: 3 === Type -->
|
<input type="password" autocomplete="current-password" autocorrect="off" autocapitalize="off" spellcheck="false"
|
||||||
<input type="password" autocomplete="current-password" autocorrect="off" autocapitalize="off" spellcheck="false"
|
data-bind="value: value, attr: {placeholder: placeholder}" />
|
||||||
data-bind="value: value, attr: {placeholder: placeholder}" />
|
<!-- /ko -->
|
||||||
<!-- /ko -->
|
<!-- ko if: 2 === Type -->
|
||||||
<!-- ko if: 2 === Type -->
|
<div data-bind="component: {
|
||||||
<div data-bind="component: {
|
name: 'TextArea',
|
||||||
name: 'TextArea',
|
params: { value: value, placeholder: placeholder }
|
||||||
params: { value: value, placeholder: placeholder }
|
}"></div>
|
||||||
}"></div>
|
<!-- /ko -->
|
||||||
<!-- /ko -->
|
<!-- ko if: 4 === Type -->
|
||||||
<!-- ko if: 4 === Type -->
|
<select data-bind="options: Default, value: value"></select>
|
||||||
<select data-bind="options: Default, value: value"></select>
|
<!-- /ko -->
|
||||||
<!-- /ko -->
|
<!-- ko if: 5 === Type -->
|
||||||
<!-- ko if: 5 === Type -->
|
<div data-bind="component: {
|
||||||
<div data-bind="component: {
|
name: 'Checkbox',
|
||||||
name: 'Checkbox',
|
params: { value: value, label: Label }
|
||||||
params: { value: value, label: Label }
|
}"></div>
|
||||||
}"></div>
|
<!-- /ko -->
|
||||||
<!-- /ko -->
|
<!-- ko if: 6 === Type -->
|
||||||
<!-- ko if: 6 === Type -->
|
<input type="url"
|
||||||
<input type="url"
|
data-bind="value: value, attr: {placeholder: placeholder}" />
|
||||||
data-bind="value: value, attr: {placeholder: placeholder}" />
|
<!-- /ko -->
|
||||||
<!-- /ko -->
|
<!-- ko if: '' !== Desc -->
|
||||||
<!-- ko if: '' !== Desc -->
|
<span tabindex="0" class="help-block"><span data-bind="text: Desc"></span></span>
|
||||||
<span tabindex="0" class="help-block"><span data-bind="text: Desc"></span></span>
|
<!-- /ko -->
|
||||||
<!-- /ko -->
|
|
||||||
</div>
|
|
||||||
|
|
|
||||||
|
|
@ -14,8 +14,18 @@
|
||||||
<a href="#" class="close" data-bind="click: function () { saveError('') }">×</a>
|
<a href="#" class="close" data-bind="click: function () { saveError('') }">×</a>
|
||||||
<span data-bind="text: saveError"></span>
|
<span data-bind="text: saveError"></span>
|
||||||
</div>
|
</div>
|
||||||
<div data-bind="foreach: configures, visible: hasConfiguration">
|
<div data-bind="foreach: config, visible: hasConfiguration">
|
||||||
|
<!-- ko if: 7 == Type -->
|
||||||
|
<details open="">
|
||||||
|
<summary class="legend" data-bind="text: Label"></summary>
|
||||||
|
<div data-bind="foreach: config">
|
||||||
|
<div class="control-group" data-bind="template: { name: 'AdminSettingsPluginProperty' }"></div>
|
||||||
|
</div>
|
||||||
|
</details>
|
||||||
|
<!-- /ko -->
|
||||||
|
<!-- ko if: 7 != Type -->
|
||||||
<div class="control-group" data-bind="template: { name: 'AdminSettingsPluginProperty' }"></div>
|
<div class="control-group" data-bind="template: { name: 'AdminSettingsPluginProperty' }"></div>
|
||||||
|
<!-- /ko -->
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue