From a2c865d7f9de19d3aad973112d27201dea777d54 Mon Sep 17 00:00:00 2001 From: TatoniMatteo Date: Tue, 20 Oct 2026 14:44:44 +0200 Subject: [PATCH 1/3] Preserve unset Boolean values in console and enduser forms Add a three-state Boolean selector to distinguish true, false and unset values. --- .../html/form/AjaxTripleStateButtonPanel.java | 213 ++++++++++++++++++ .../ui/commons/panels/SyncopeFormPanel.java | 7 +- .../ui-commons/css/_triplestate.scss | 70 ++++++ .../resources/ui-commons/css/syncopeUI.scss | 1 + .../html/form/AjaxTripleStateButtonPanel.html | 53 +++++ .../AjaxTripleStateButtonPanel.properties | 19 ++ .../AjaxTripleStateButtonPanel_fr.properties | 19 ++ ...jaxTripleStateButtonPanel_fr_CA.properties | 19 ++ .../AjaxTripleStateButtonPanel_it.properties | 19 ++ .../AjaxTripleStateButtonPanel_ja.properties | 19 ++ .../AjaxTripleStateButtonPanel_pt.properties | 19 ++ ...jaxTripleStateButtonPanel_pt_BR.properties | 19 ++ .../AjaxTripleStateButtonPanel_ru.properties | 19 ++ .../client/console/panels/BeanPanel.java | 5 +- .../panels/ParametersWizardAttrStep.java | 35 +-- .../wizards/any/AbstractAttrsWizardStep.java | 38 +--- .../client/console/panels/TogglePanel.html | 5 +- .../html/bootstrap/dialog/BaseModal.html | 2 +- .../client/enduser/panels/any/PlainAttrs.java | 38 +--- 19 files changed, 519 insertions(+), 100 deletions(-) create mode 100644 client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/markup/html/form/AjaxTripleStateButtonPanel.java create mode 100644 client/idrepo/common-ui/src/main/resources/META-INF/resources/ui-commons/css/_triplestate.scss create mode 100644 client/idrepo/common-ui/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxTripleStateButtonPanel.html create mode 100644 client/idrepo/common-ui/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxTripleStateButtonPanel.properties create mode 100644 client/idrepo/common-ui/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxTripleStateButtonPanel_fr.properties create mode 100644 client/idrepo/common-ui/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxTripleStateButtonPanel_fr_CA.properties create mode 100644 client/idrepo/common-ui/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxTripleStateButtonPanel_it.properties create mode 100644 client/idrepo/common-ui/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxTripleStateButtonPanel_ja.properties create mode 100644 client/idrepo/common-ui/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxTripleStateButtonPanel_pt.properties create mode 100644 client/idrepo/common-ui/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxTripleStateButtonPanel_pt_BR.properties create mode 100644 client/idrepo/common-ui/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxTripleStateButtonPanel_ru.properties diff --git a/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/markup/html/form/AjaxTripleStateButtonPanel.java b/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/markup/html/form/AjaxTripleStateButtonPanel.java new file mode 100644 index 00000000000..0a3a61cccd9 --- /dev/null +++ b/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/markup/html/form/AjaxTripleStateButtonPanel.java @@ -0,0 +1,213 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.syncope.client.ui.commons.markup.html.form; + +import java.io.Serializable; +import java.util.List; +import java.util.Optional; +import org.apache.commons.lang3.BooleanUtils; +import org.apache.syncope.client.ui.commons.ajax.form.IndicatorAjaxFormChoiceComponentUpdatingBehavior; +import org.apache.syncope.common.lib.Attr; +import org.apache.syncope.common.lib.to.AttributableTO; +import org.apache.wicket.AttributeModifier; +import org.apache.wicket.ajax.AjaxRequestTarget; +import org.apache.wicket.markup.html.WebMarkupContainer; +import org.apache.wicket.markup.html.form.Radio; +import org.apache.wicket.markup.html.form.RadioGroup; +import org.apache.wicket.markup.html.list.ListItem; +import org.apache.wicket.model.IModel; +import org.apache.wicket.model.Model; +import org.apache.wicket.model.ResourceModel; + +public class AjaxTripleStateButtonPanel extends FieldPanel { + + private static final long serialVersionUID = 5433965057104106773L; + + protected final WebMarkupContainer unsetContainer; + + protected final Radio unsetOption; + + private final boolean convertValuesToString; + + public AjaxTripleStateButtonPanel(final String id, final String name, final IModel model) { + this(id, name, model, true); + } + + public AjaxTripleStateButtonPanel( + final String id, + final String name, + final IModel model, + final boolean enableOnChange) { + + this(id, name, model, enableOnChange, true); + } + + private AjaxTripleStateButtonPanel( + final String id, + final String name, + final IModel model, + final boolean enableOnChange, + final boolean convertValuesToString) { + + super(id, name, model); + + this.convertValuesToString = convertValuesToString; + + field = new RadioGroup<>("tripleStateField", model); + add(field.setLabel(new ResourceModel(name, name)).setOutputMarkupId(true)); + field.add(AttributeModifier.replace("aria-label", field.getLabel())); + field.add(AttributeModifier.replace("aria-required", (IModel) () -> Boolean.toString(isRequired()))); + + Radio trueOption = new Radio<>("trueOption", Model.of(Boolean.TRUE)); + Radio falseOption = new Radio<>("falseOption", Model.of(Boolean.FALSE)); + field.add(trueOption.setOutputMarkupId(true), falseOption.setOutputMarkupId(true)); + + WebMarkupContainer trueLabel = new WebMarkupContainer("trueLabel"); + trueLabel.add(AttributeModifier.replace("for", (IModel) trueOption::getMarkupId)); + trueLabel.add(AttributeModifier.replace("title", new ResourceModel("tristate.true"))); + field.add(trueLabel); + + WebMarkupContainer falseLabel = new WebMarkupContainer("falseLabel"); + falseLabel.add(AttributeModifier.replace("for", (IModel) falseOption::getMarkupId)); + falseLabel.add(AttributeModifier.replace("title", new ResourceModel("tristate.false"))); + field.add(falseLabel); + + unsetContainer = new WebMarkupContainer("unsetContainer"); + field.add(unsetContainer); + + unsetOption = new Radio<>("unsetOption", Model.of((Boolean) null)); + unsetContainer.add(unsetOption.setOutputMarkupId(true)); + + WebMarkupContainer unsetLabel = new WebMarkupContainer("unsetLabel"); + unsetLabel.add(AttributeModifier.replace("for", (IModel) unsetOption::getMarkupId)); + unsetLabel.add(AttributeModifier.replace("title", new ResourceModel("tristate.unset"))); + unsetContainer.add(unsetLabel); + + if (enableOnChange && !isReadOnly()) { + field.add(new IndicatorAjaxFormChoiceComponentUpdatingBehavior() { + + private static final long serialVersionUID = -8888833255711609077L; + + @Override + protected void onUpdate(final AjaxRequestTarget target) { + doUpdate(target); + } + }); + } + } + + protected void doUpdate(final AjaxRequestTarget target) { + // nothing to do + } + + @Override + public FieldPanel setRequired(final boolean required) { + unsetContainer.setVisible(!required); + unsetOption.setEnabled(!required); + return super.setRequired(required); + } + + @Override + public FieldPanel setNewModel(final List values) { + return setNewModel(new Model<>() { + + private static final long serialVersionUID = -4214654722524358000L; + + @Override + public Boolean getObject() { + return values == null || values.isEmpty() || values.getFirst() == null + ? null : BooleanUtils.toBooleanObject(values.getFirst().toString()); + } + + @Override + public void setObject(final Boolean object) { + values.clear(); + if (object != null) { + values.add(convertValuesToString ? object.toString() : object); + } + } + }); + } + + @Override + @SuppressWarnings({ "rawtypes", "unchecked" }) + public FieldPanel setNewModel(final ListItem item) { + return setNewModel(new Model<>() { + + private static final long serialVersionUID = 6799404673615637845L; + + @Override + public Boolean getObject() { + Object value = item.getModelObject(); + return value == null ? null : BooleanUtils.toBooleanObject(value.toString()); + } + + @Override + public void setObject(final Boolean object) { + item.setModelObject(Optional.ofNullable(object). + map(value -> convertValuesToString ? value.toString() : value).orElse(null)); + } + }); + } + + @Override + public FieldPanel setNewModel(final AttributableTO attributable, final String schema) { + return setNewModel(new Model<>() { + + private static final long serialVersionUID = -4214654722524358000L; + + @Override + public Boolean getObject() { + return attributable.getPlainAttr(schema).map(Attr::getValues).filter(values -> !values.isEmpty()). + map(values -> BooleanUtils.toBooleanObject(values.getFirst())).orElse(null); + } + + @Override + public void setObject(final Boolean object) { + attributable.getPlainAttr(schema).ifPresent(attr -> { + attr.getValues().clear(); + if (object != null) { + attr.getValues().add(object.toString()); + } + }); + } + }); + } + + public static class Builder { + + private boolean enableOnChange = false; + + private boolean convertValuesToString = true; + + public Builder enableOnChange() { + enableOnChange = true; + return this; + } + + public Builder convertValuesToString(final boolean convertValuesToString) { + this.convertValuesToString = convertValuesToString; + return this; + } + + public AjaxTripleStateButtonPanel build(final String id, final String name, final IModel model) { + return new AjaxTripleStateButtonPanel(id, name, model, enableOnChange, convertValuesToString); + } + } +} diff --git a/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/panels/SyncopeFormPanel.java b/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/panels/SyncopeFormPanel.java index d827d28aa6c..0b873aaadbf 100644 --- a/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/panels/SyncopeFormPanel.java +++ b/client/idrepo/common-ui/src/main/java/org/apache/syncope/client/ui/commons/panels/SyncopeFormPanel.java @@ -31,7 +31,6 @@ import org.apache.commons.lang3.time.FastDateFormat; import org.apache.syncope.client.ui.commons.MapChoiceRenderer; import org.apache.syncope.client.ui.commons.markup.html.form.AbstractFieldPanel; -import org.apache.syncope.client.ui.commons.markup.html.form.AjaxCheckBoxPanel; import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDateFieldPanel; import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDateTimeFieldPanel; import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel; @@ -39,6 +38,7 @@ import org.apache.syncope.client.ui.commons.markup.html.form.AjaxPalettePanel; import org.apache.syncope.client.ui.commons.markup.html.form.AjaxPasswordFieldPanel; import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel; +import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTripleStateButtonPanel; import org.apache.syncope.client.ui.commons.markup.html.form.BinaryFieldPanel; import org.apache.syncope.common.lib.form.FormProperty; import org.apache.syncope.common.lib.form.FormPropertyValue; @@ -79,13 +79,14 @@ protected void populateItem(final ListItem item) { AbstractFieldPanel field; switch (prop.getType()) { case Boolean: - field = new AjaxCheckBoxPanel("value", label, new PropertyModel(prop, "value") { + field = new AjaxTripleStateButtonPanel( + "value", label, new PropertyModel<>(prop, "value") { private static final long serialVersionUID = -3743432456095828573L; @Override public Boolean getObject() { - return BooleanUtils.toBoolean(prop.getValue()); + return BooleanUtils.toBooleanObject(prop.getValue()); } @Override diff --git a/client/idrepo/common-ui/src/main/resources/META-INF/resources/ui-commons/css/_triplestate.scss b/client/idrepo/common-ui/src/main/resources/META-INF/resources/ui-commons/css/_triplestate.scss new file mode 100644 index 00000000000..7fa98974696 --- /dev/null +++ b/client/idrepo/common-ui/src/main/resources/META-INF/resources/ui-commons/css/_triplestate.scss @@ -0,0 +1,70 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/* TriStateButton +============================================================================= */ + +.tristate-field { + display: flex; + flex-direction: column; + align-items: flex-start; +} + +.tristate-field-label-row { + display: flex; + flex-direction: row; + align-items: baseline; + gap: 0.25rem; +} + +.tristate-field .btn-group > .btn { + flex: 1 1 0; + white-space: nowrap; +} + +.tristate-icon-group > .btn { + min-width: 45px; + min-height: 35px; + display: flex; + align-items: center; + justify-content: center; + padding: 0.375rem 0.75rem; +} + +.tristate-icon-group .btn i { + font-size: 1rem; +} + +.tristate-icon-group .btn-check:checked + .tristate-true { + background-color: var(--bs-success); + border-color: var(--bs-success); + color: white; +} + +.tristate-icon-group .btn-check:checked + .tristate-false { + background-color: var(--bs-danger); + border-color: var(--bs-danger); + color: white; +} + +.tristate-icon-group .btn-check:checked + .tristate-unset { + background-color: var(--bs-secondary); + border-color: var(--bs-secondary); + color: white; +} diff --git a/client/idrepo/common-ui/src/main/resources/META-INF/resources/ui-commons/css/syncopeUI.scss b/client/idrepo/common-ui/src/main/resources/META-INF/resources/ui-commons/css/syncopeUI.scss index fdf5ddaac4d..c66ee97407c 100644 --- a/client/idrepo/common-ui/src/main/resources/META-INF/resources/ui-commons/css/syncopeUI.scss +++ b/client/idrepo/common-ui/src/main/resources/META-INF/resources/ui-commons/css/syncopeUI.scss @@ -19,6 +19,7 @@ @import 'theme'; @import 'utils'; +@import 'triplestate'; [data-bs-theme=dark] .sidebar-wrapper { background-color: rgba(var(--bs-secondary-bg-rgb), var(--bs-bg-opacity)) !important; diff --git a/client/idrepo/common-ui/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxTripleStateButtonPanel.html b/client/idrepo/common-ui/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxTripleStateButtonPanel.html new file mode 100644 index 00000000000..fdb0c192d46 --- /dev/null +++ b/client/idrepo/common-ui/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxTripleStateButtonPanel.html @@ -0,0 +1,53 @@ + + + +
+
+ + [LABEL] + +
+ +
+ + + + + + + + + + +
+ + +
+
+ diff --git a/client/idrepo/common-ui/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxTripleStateButtonPanel.properties b/client/idrepo/common-ui/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxTripleStateButtonPanel.properties new file mode 100644 index 00000000000..e5478a588e1 --- /dev/null +++ b/client/idrepo/common-ui/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxTripleStateButtonPanel.properties @@ -0,0 +1,19 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +tristate.unset=Not set +tristate.true=True +tristate.false=False diff --git a/client/idrepo/common-ui/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxTripleStateButtonPanel_fr.properties b/client/idrepo/common-ui/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxTripleStateButtonPanel_fr.properties new file mode 100644 index 00000000000..57f0deed485 --- /dev/null +++ b/client/idrepo/common-ui/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxTripleStateButtonPanel_fr.properties @@ -0,0 +1,19 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +tristate.unset=Non d\u00E9fini +tristate.true=Vrai +tristate.false=Faux diff --git a/client/idrepo/common-ui/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxTripleStateButtonPanel_fr_CA.properties b/client/idrepo/common-ui/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxTripleStateButtonPanel_fr_CA.properties new file mode 100644 index 00000000000..57f0deed485 --- /dev/null +++ b/client/idrepo/common-ui/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxTripleStateButtonPanel_fr_CA.properties @@ -0,0 +1,19 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +tristate.unset=Non d\u00E9fini +tristate.true=Vrai +tristate.false=Faux diff --git a/client/idrepo/common-ui/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxTripleStateButtonPanel_it.properties b/client/idrepo/common-ui/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxTripleStateButtonPanel_it.properties new file mode 100644 index 00000000000..8a8419fff50 --- /dev/null +++ b/client/idrepo/common-ui/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxTripleStateButtonPanel_it.properties @@ -0,0 +1,19 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +tristate.unset=Non impostato +tristate.true=Vero +tristate.false=Falso diff --git a/client/idrepo/common-ui/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxTripleStateButtonPanel_ja.properties b/client/idrepo/common-ui/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxTripleStateButtonPanel_ja.properties new file mode 100644 index 00000000000..aef9a0ae976 --- /dev/null +++ b/client/idrepo/common-ui/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxTripleStateButtonPanel_ja.properties @@ -0,0 +1,19 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +tristate.unset=\u672A\u8A2D\u5B9A +tristate.true=\u771F +tristate.false=\u507D diff --git a/client/idrepo/common-ui/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxTripleStateButtonPanel_pt.properties b/client/idrepo/common-ui/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxTripleStateButtonPanel_pt.properties new file mode 100644 index 00000000000..9f0a2cefc95 --- /dev/null +++ b/client/idrepo/common-ui/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxTripleStateButtonPanel_pt.properties @@ -0,0 +1,19 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +tristate.unset=N\u00E3o definido +tristate.true=Verdadeiro +tristate.false=Falso diff --git a/client/idrepo/common-ui/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxTripleStateButtonPanel_pt_BR.properties b/client/idrepo/common-ui/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxTripleStateButtonPanel_pt_BR.properties new file mode 100644 index 00000000000..9f0a2cefc95 --- /dev/null +++ b/client/idrepo/common-ui/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxTripleStateButtonPanel_pt_BR.properties @@ -0,0 +1,19 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +tristate.unset=N\u00E3o definido +tristate.true=Verdadeiro +tristate.false=Falso diff --git a/client/idrepo/common-ui/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxTripleStateButtonPanel_ru.properties b/client/idrepo/common-ui/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxTripleStateButtonPanel_ru.properties new file mode 100644 index 00000000000..82fd8ce71de --- /dev/null +++ b/client/idrepo/common-ui/src/main/resources/org/apache/syncope/client/ui/commons/markup/html/form/AjaxTripleStateButtonPanel_ru.properties @@ -0,0 +1,19 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +tristate.unset=\u041D\u0435 \u0437\u0430\u0434\u0430\u043D\u043E +tristate.true=\u0418\u0441\u0442\u0438\u043D\u0430 +tristate.false=\u041B\u043E\u0436\u044C diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/BeanPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/BeanPanel.java index 7da6cdee126..25b24eeb3c7 100644 --- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/BeanPanel.java +++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/BeanPanel.java @@ -55,6 +55,7 @@ import org.apache.syncope.client.ui.commons.markup.html.form.AjaxNumberFieldPanel; import org.apache.syncope.client.ui.commons.markup.html.form.AjaxPalettePanel; import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel; +import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTripleStateButtonPanel; import org.apache.syncope.client.ui.commons.markup.html.form.FieldPanel; import org.apache.syncope.client.ui.commons.markup.html.form.MultiFieldPanel; import org.apache.syncope.common.lib.report.SearchCondition; @@ -290,7 +291,9 @@ private SinglePanel buildSinglePanel( PropertyModel model = new PropertyModel<>(bean, fieldName); FieldPanel panel; - if (ClassUtils.isAssignable(Boolean.class, type)) { + if (Boolean.class.equals(type)) { + panel = new AjaxTripleStateButtonPanel(id, fieldName, model); + } else if (Boolean.TYPE.equals(type)) { panel = new AjaxCheckBoxPanel(id, fieldName, model); } else if (ClassUtils.isAssignable(Number.class, type)) { panel = new AjaxNumberFieldPanel.Builder<>().build( diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ParametersWizardAttrStep.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ParametersWizardAttrStep.java index 8bf69dee54d..63eaa748084 100644 --- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ParametersWizardAttrStep.java +++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ParametersWizardAttrStep.java @@ -19,12 +19,11 @@ package org.apache.syncope.client.console.panels; import java.util.List; -import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.time.DateFormatUtils; import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDateTimeFieldPanel; -import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel; import org.apache.syncope.client.ui.commons.markup.html.form.AjaxNumberFieldPanel; import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel; +import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTripleStateButtonPanel; import org.apache.syncope.client.ui.commons.markup.html.form.BinaryFieldPanel; import org.apache.syncope.client.ui.commons.markup.html.form.FieldPanel; import org.apache.syncope.client.ui.commons.markup.html.form.MultiFieldPanel; @@ -32,11 +31,9 @@ import org.apache.syncope.common.lib.to.PlainSchemaTO; import org.apache.wicket.extensions.wizard.WizardStep; import org.apache.wicket.markup.html.WebMarkupContainer; -import org.apache.wicket.markup.html.form.IChoiceRenderer; import org.apache.wicket.markup.html.list.ListItem; import org.apache.wicket.markup.html.list.ListView; import org.apache.wicket.markup.html.panel.Panel; -import org.apache.wicket.model.IModel; import org.apache.wicket.model.LoadableDetachableModel; import org.apache.wicket.model.Model; import org.apache.wicket.model.PropertyModel; @@ -98,33 +95,9 @@ private Panel getFieldPanel(final String id, final ConfParam param, final PlainS break; case Boolean: - panel = new AjaxDropDownChoicePanel(id, valueHeaderName, new Model<>(), false); - ((AjaxDropDownChoicePanel) panel).setChoices(List.of(true, false)); - - if (!param.getValues().isEmpty()) { - ((AjaxDropDownChoicePanel) panel).setChoiceRenderer(new IChoiceRenderer() { - - private static final long serialVersionUID = -8223314361351275865L; - - @Override - public Object getDisplayValue(final Boolean object) { - return BooleanUtils.toStringTrueFalse(object); - } - - @Override - public String getIdValue(final Boolean object, final int index) { - return BooleanUtils.toStringTrueFalse(object); - } - - @Override - public Boolean getObject( - final String id, final IModel> choices) { - - return BooleanUtils.toBoolean(id); - } - }); - } - ((AjaxDropDownChoicePanel) panel).setNullValid(false); + panel = new AjaxTripleStateButtonPanel.Builder(). + convertValuesToString(false). + build(id, valueHeaderName, new Model<>()); break; case Long: diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/AbstractAttrsWizardStep.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/AbstractAttrsWizardStep.java index 1f6bd71bbb8..bdca5069bba 100644 --- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/AbstractAttrsWizardStep.java +++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/wizards/any/AbstractAttrsWizardStep.java @@ -37,13 +37,13 @@ import org.apache.syncope.client.console.rest.SchemaRestClient; import org.apache.syncope.client.ui.commons.ajax.markup.html.LabelInfo; import org.apache.syncope.client.ui.commons.markup.html.form.AbstractFieldPanel; -import org.apache.syncope.client.ui.commons.markup.html.form.AjaxCheckBoxPanel; import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDateFieldPanel; import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDateTimeFieldPanel; import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel; import org.apache.syncope.client.ui.commons.markup.html.form.AjaxNumberFieldPanel; import org.apache.syncope.client.ui.commons.markup.html.form.AjaxPalettePanel; import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel; +import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTripleStateButtonPanel; import org.apache.syncope.client.ui.commons.markup.html.form.BinaryFieldPanel; import org.apache.syncope.client.ui.commons.markup.html.form.EncryptedFieldPanel; import org.apache.syncope.client.ui.commons.markup.html.form.FieldPanel; @@ -205,12 +205,12 @@ protected AbstractFieldPanel getFieldPanel(final PlainSchemaTO plainSchema, f AbstractFieldPanel panel; switch (type) { case Boolean: - panel = new AjaxCheckBoxPanel( + panel = new AjaxTripleStateButtonPanel( "panel", plainSchema.getLabel(SyncopeConsoleSession.get().getLocale()), new Model<>(), true); - panel.setRequired(required); + break; case Date: @@ -232,10 +232,6 @@ protected AbstractFieldPanel getFieldPanel(final PlainSchemaTO plainSchema, f FastDateFormat.getInstance(datePattern)); } - if (required) { - panel.addRequiredLabel(); - } - break; case Enum: @@ -268,9 +264,6 @@ public String getObject( }); } - if (required) { - panel.addRequiredLabel(); - } break; case Dropdown: @@ -291,9 +284,6 @@ public String getObject( ((AjaxDropDownChoicePanel) panel).setChoices(dropdownValues); } - if (required) { - panel.addRequiredLabel(); - } break; case Long: @@ -303,9 +293,6 @@ public String getObject( Long.class, new Model<>()); - if (required) { - panel.addRequiredLabel(); - } break; case Double: @@ -315,9 +302,6 @@ public String getObject( Double.class, new Model<>()); - if (required) { - panel.addRequiredLabel(); - } break; case Binary: @@ -336,9 +320,7 @@ protected PageReference getPageReference() { return pageRef; } }; - if (required) { - panel.addRequiredLabel(); - } + break; case Encrypted: @@ -348,9 +330,6 @@ protected PageReference getPageReference() { : new EncryptedFieldPanel("panel", plainSchema.getLabel(SyncopeConsoleSession.get().getLocale()), new Model<>(), true); - if (required) { - panel.addRequiredLabel(); - } break; default: @@ -360,12 +339,11 @@ protected PageReference getPageReference() { if (jexlHelp) { AjaxTextFieldPanel.class.cast(panel).enableJexlHelp(); } - - if (required) { - panel.addRequiredLabel(); - } } + if (required) { + panel.addRequiredLabel(); + } panel.setReadOnly(readOnly); return panel; @@ -380,7 +358,7 @@ protected FormComponent checkboxToggle( return null; } - private class AttrComparator implements Comparator, Serializable { + private final class AttrComparator implements Comparator, Serializable { private static final long serialVersionUID = -5105030477767941060L; diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/TogglePanel.html b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/TogglePanel.html index 045e483949c..c88d05fa738 100644 --- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/TogglePanel.html +++ b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/panels/TogglePanel.html @@ -120,9 +120,8 @@