diff --git a/module/custom/ui/set.html.php b/module/custom/ui/set.html.php
new file mode 100644
index 0000000000..be32a1f3f6
--- /dev/null
+++ b/module/custom/ui/set.html.php
@@ -0,0 +1,408 @@
+
+ * @package custom
+ * @link https://www.zentao.net
+ */
+namespace zin;
+
+$menuItems = array();
+if(!in_array($module, array('block', 'baseline')) && !empty($lang->custom->{$module}->fields))
+{
+ foreach($lang->custom->{$module}->fields as $key => $value)
+ {
+ $currentModule = 'custom';
+ $method = $key;
+ $params = $key == 'required' ? "module=$module" : '';
+ $active = $app->rawMethod == strtolower($key) ? 'active' : '';
+ if(!in_array($key, $config->custom->notSetMethods))
+ {
+ $params = "module=$module&field=$key";
+ $method = 'set';
+ $active = (isset($field) and $field == $key) ? 'active' : $active;
+ }
+
+ if($module == 'approvalflow')
+ {
+ $currentModule = 'approvalflow';
+ if(in_array($key, array('project', 'workflow')))
+ {
+ $method = 'browse';
+ $params = "type=$key";
+ $active = (isset($type) and $type == $key) ? 'active' : $active;
+ }
+ }
+
+ if(common::hasPriv($currentModule, $method))
+ {
+ $menuItems[] = li
+ (
+ setClass('menu-item py-1 px-4'),
+ a
+ (
+ setClass($active),
+ set::href(inlink($method, $params)),
+ $value,
+ )
+ );
+ }
+ }
+}
+
+$formItems = array();
+$formActions = array('submit');
+if($module == 'project' && $field == 'unitList')
+{
+ $formItems[] = formGroup
+ (
+ set::label($lang->custom->project->currencySetting),
+ set::name('unitList'),
+ set::value($unitList),
+ set::control('checkListInline'),
+ set::items($lang->project->unitList),
+ );
+
+ $formItems[] = formGroup
+ (
+ set::label($lang->custom->project->defaultCurrency),
+ set::control('select'),
+ set::name('defaultCurrency'),
+ set::value($lang->project->unitList),
+ set::items($defaultCurrency)
+ );
+}
+elseif($module == 'story' && $field == 'reviewRules')
+{
+ $formItems[] = formGroup
+ (
+ set::label($lang->custom->reviewRule),
+ set::name('reviewRules'),
+ set::value($needReview),
+ set::control('radioListInline'),
+ set::items($lang->custom->reviewRules),
+ );
+
+ $formItems[] = formGroup
+ (
+ set::label($lang->custom->superReviewers),
+ set::name('superReviewers'),
+ set::value($superReviewers),
+ set::control(array('type' => 'select', 'multiple' => true)),
+ set::items($users),
+ );
+}
+elseif(($module == 'story' || $module == 'testcase') && $field == 'review')
+{
+ $formItems[] = formGroup
+ (
+ set::label($lang->custom->storyReview),
+ set::name('needReview'),
+ set::value($needReview),
+ set::control('radioListInline'),
+ set::items($lang->custom->reviewList),
+ );
+
+ if($module == 'story')
+ {
+ $formItems[] = formGroup
+ (
+ setClass($needReview ? 'hidden' : ''),
+ set::label(''),
+ set::name(''),
+ set::value(sprintf($lang->custom->notice->forceReview, $lang->$module->common) . $lang->custom->notice->storyReviewTip),
+ set::control('static'),
+ );
+
+ $formItems[] = formGroup
+ (
+ setClass($needReview ? '' : 'hidden'),
+ set::label(''),
+ set::name(''),
+ set::value(sprintf($lang->custom->notice->forceNotReview, $lang->$module->common) . $lang->custom->notice->storyReviewTip),
+ set::control('static'),
+ );
+
+ $space = ($app->getClientLang() != 'zh-cn' and $app->getClientLang() != 'zh-tw') ? ' ' : '';
+ if($needReview)
+ {
+ $formItems[] = formGroup
+ (
+ set::label($lang->custom->forceReview . $space . $lang->custom->account),
+ set::name('forceNotReview'),
+ set::value($forceNotReview),
+ set::items($users),
+ set::control(array('type' => 'select', 'multiple' => true)),
+ );
+
+ $formItems[] = formGroup
+ (
+ set::label($lang->custom->forceReview . $space . $lang->custom->role),
+ set::name('forceNotReviewRoles'),
+ set::value($forceNotReviewRoles),
+ set::items($lang->user->roleList),
+ set::control(array('type' => 'select', 'multiple' => true)),
+ );
+
+ $formItems[] = formGroup
+ (
+ set::label($lang->custom->forceReview . $space . $lang->custom->dept),
+ set::name('forceNotReviewDepts'),
+ set::value($forceNotReviewDepts),
+ set::items($depts),
+ set::control(array('type' => 'select', 'multiple' => true)),
+ );
+ }
+ else
+ {
+ $formItems[] = formGroup
+ (
+ set::label($lang->custom->forceReview . $space . $lang->custom->account),
+ set::name('forceReview'),
+ set::value($forceReview),
+ set::items($users),
+ set::control(array('type' => 'select', 'multiple' => true)),
+ );
+
+ $formItems[] = formGroup
+ (
+ set::label($lang->custom->forceReview . $space . $lang->custom->role),
+ set::name('forceReviewRoles'),
+ set::value($forceReviewRoles),
+ set::items($lang->user->roleList),
+ set::control(array('type' => 'select', 'multiple' => true)),
+ );
+
+ $formItems[] = formGroup
+ (
+ set::label($lang->custom->forceReview . $space . $lang->custom->dept),
+ set::name('forceReviewDepts'),
+ set::value($forceReviewDepts),
+ set::items($depts),
+ set::control(array('type' => 'select', 'multiple' => true)),
+ );
+ }
+ }
+ elseif($module == 'testcase')
+ {
+ if($needReview)
+ {
+ $formItems[] = formRow
+ (
+ formGroup
+ (
+ set::width('2/3'),
+ set::label($lang->custom->forceReview . $space . $lang->custom->forceNotReview),
+ set::name('forceNotReview'),
+ set::value($forceNotReview),
+ set::items($users),
+ set::control(array('type' => 'select', 'multiple' => true)),
+ ),
+ span(
+ setClass('pl-4'),
+ sprintf($lang->custom->notice->forceReview, $lang->$module->common)
+ )
+ );
+ }
+ else
+ {
+ $formItems[] = formRow
+ (
+ formGroup
+ (
+ set::width('2/3'),
+ set::label($lang->custom->forceReview . $space . $lang->custom->forceReview),
+ set::name('forceReview'),
+ set::value($forceReview),
+ set::items($users),
+ set::control(array('type' => 'select', 'multiple' => true)),
+ ),
+ span(
+ setClass('pl-4'),
+ sprintf($lang->custom->notice->forceReview, $lang->$module->common)
+ )
+ );
+ }
+ }
+}
+elseif($module == 'bug' && $field == 'longlife')
+{
+ $formItems[] = formGroup
+ (
+ set::label($lang->custom->bug->fields['longlife']),
+ set::name('longlife'),
+ set::value($longlife),
+ set::width('1/3'),
+ set::control(array(
+ 'type' => 'inputControl',
+ 'suffix' => $lang->day,
+ ))
+ );
+
+ $formItems[] = div
+ (
+ setClass('alert alert-info alert-block'),
+ $lang->custom->notice->longlife
+ );
+}
+elseif($module == 'block' && $field == 'closed')
+{
+ if(empty($blockPairs))
+ {
+ $formItems[] = formGroup
+ (
+ set::label($lang->custom->block->fields['closed']),
+ set::name('closed'),
+ set::value($lang->custom->notice->noClosedBlock),
+ set::control('static'),
+ );
+ $formActions = array();
+ }
+ else
+ {
+ $formItems[] = formGroup
+ (
+ set::label($lang->custom->block->fields['closed']),
+ set::name('closed'),
+ set::value($closedBlock),
+ set::control(array(
+ 'type' => 'select',
+ 'multiple' => true,
+ )),
+ set::items($blockPairs)
+ );
+ }
+}
+elseif($module == 'user' && $field == 'contactField')
+{
+ $this->app->loadConfig('user');
+ $this->app->loadLang('user');
+
+ $formItems[] = formGroup
+ (
+ set::label($lang->custom->user->fields['contactField']),
+ set::name('contactField'),
+ set::value($config->user->contactField),
+ set::control(array(
+ 'type' => 'select',
+ 'multiple' => true,
+ )),
+ set::items($lang->user->contactFieldList)
+ );
+
+ if(common::hasPriv('custom', 'restore'))
+ {
+ $formActions[] = array(
+ 'url' => inlink('restore', "module=user&field=contactField&confirm=yes"),
+ 'text' => $lang->custom->restore,
+ 'class' => 'btn-wide ajax-submit',
+ 'data-confirm' => $lang->custom->confirmRestorelang->custom->confirmRestore,
+ );
+ }
+}
+elseif($module == 'user' && $field == 'deleted')
+{
+ $formItems[] = formGroup
+ (
+ set::label($lang->custom->user->fields['deleted']),
+ set::name('showDeleted'),
+ set::value($showDeleted),
+ set::control('radioListInline'),
+ set::items($lang->custom->deletedList)
+ );
+}
+else
+{
+ if(!empty($fieldList) && is_array($fieldList))
+ {
+ $formItems[] = formGroup
+ (
+ set::label($lang->custom->key),
+ set::name(''),
+ set::value($lang->custom->value),
+ set::control('static')
+ );
+
+ foreach($fieldList as $key => $value)
+ {
+ $system = isset($dbFields[$key]) ? $dbFields[$key]->system : 1;
+
+ $formItems[] = formRow
+ (
+ formGroup
+ (
+ set::width('1/2'),
+ set::label($key === '' ? 'NULL' : $key),
+ set::name('values'),
+ set::value(isset($dbFields[$key]) ? $dbFields[$key]->value : $value),
+ set::readonly(empty($key))
+ ),
+ $canAdd ? span(
+ setClass('pl-4'),
+ icon
+ (
+ setClass('add-item'),
+ 'plus',
+ ),
+ icon
+ (
+ setClass('del-item ml-2'),
+ 'close',
+ ),
+ ) : null,
+ );
+ }
+
+ $appliedTo = array($currentLang => $lang->custom->currentLang, 'all' => $lang->custom->allLang);
+ $formItems[] = formGroup
+ (
+ set::label(''),
+ set::name('lang'),
+ set::items($appliedTo),
+ set::value($lang2Set),
+ set::control('radioListInline'),
+ );
+
+ if(common::hasPriv('custom', 'restore'))
+ {
+ $formActions[] = array(
+ 'url' => inlink('restore', "module={$module}&field={$field}&confirm=yes"),
+ 'text' => $lang->custom->restore,
+ 'class' => 'btn-wide ajax-submit',
+ 'data-confirm' => $lang->custom->confirmRestorelang->custom->confirmRestore,
+ );
+ }
+
+ if(!$canAdd)
+ {
+ $formItems[] = div
+ (
+ setClass('alert alert-info alert-block'),
+ $lang->custom->notice->canNotAdd
+ );
+ }
+ }
+}
+
+div
+(
+ setClass('flex'),
+ $menuItems ? menu
+ (
+ setClass('w-48'),
+ $menuItems
+ ) : null,
+ formPanel
+ (
+ setClass('flex-auto'),
+ setClass($menuItems ? 'ml-4' : null),
+ set::title($lang->custom->$module->fields[$field]),
+ set::actions($formActions),
+ $formItems,
+ )
+);
+
+render();
diff --git a/module/index/config.php b/module/index/config.php
index d2ef9a78e4..158d2ff2b3 100644
--- a/module/index/config.php
+++ b/module/index/config.php
@@ -56,7 +56,6 @@ $config->index->oldPages[] = 'admin-checkweak';
$config->index->oldPages[] = 'admin-resetpwdsetting';
$config->index->oldPages[] = 'admin-tableengine';
$config->index->oldPages[] = 'custom-timezone';
-$config->index->oldPages[] = 'custom-set';
$config->index->oldPages[] = 'webhook-browse';
$config->index->oldPages[] = 'webhook-create';
$config->index->oldPages[] = 'dev-api';