Skip to content

Commit 39080c2

Browse files
authored
feat: add dashboard feature flag (#6832)
1 parent d7943ac commit 39080c2

File tree

12 files changed

+338
-121
lines changed

12 files changed

+338
-121
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
com.vaadin.experimental.dashboardComponent=true

vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/Dashboard.java

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,13 @@
2121

2222
import org.slf4j.LoggerFactory;
2323

24+
import com.vaadin.experimental.FeatureFlags;
2425
import com.vaadin.flow.component.AttachEvent;
2526
import com.vaadin.flow.component.Component;
2627
import com.vaadin.flow.component.ComponentEventListener;
2728
import com.vaadin.flow.component.HasSize;
2829
import com.vaadin.flow.component.Tag;
30+
import com.vaadin.flow.component.UI;
2931
import com.vaadin.flow.component.dependency.JsModule;
3032
import com.vaadin.flow.component.dependency.NpmPackage;
3133
import com.vaadin.flow.dom.DomEvent;
@@ -69,6 +71,8 @@ public class Dashboard extends Component implements HasWidgets, HasSize {
6971

7072
private boolean pendingUpdate = false;
7173

74+
private boolean featureFlagEnabled;
75+
7276
/**
7377
* Creates an empty dashboard.
7478
*/
@@ -496,6 +500,7 @@ public boolean isVisible() {
496500
@Override
497501
protected void onAttach(AttachEvent attachEvent) {
498502
super.onAttach(attachEvent);
503+
checkFeatureFlag();
499504
getElement().executeJs(
500505
"Vaadin.FlowComponentHost.patchVirtualContainer(this);");
501506
customizeItemMovedEvent();
@@ -773,6 +778,41 @@ private static JsonArray getSectionItems(JsonArray items,
773778
return null;
774779
}
775780

781+
/**
782+
* Checks whether the Dashboard component feature flag is active. Succeeds
783+
* if the flag is enabled, and throws otherwise.
784+
*
785+
* @throws ExperimentalFeatureException
786+
* when the {@link FeatureFlags#DASHBOARD_COMPONENT} feature is
787+
* not enabled
788+
*/
789+
private void checkFeatureFlag() {
790+
boolean enabled = featureFlagEnabled || getFeatureFlags()
791+
.isEnabled(FeatureFlags.DASHBOARD_COMPONENT);
792+
if (!enabled) {
793+
throw new ExperimentalFeatureException();
794+
}
795+
}
796+
797+
/**
798+
* Gets the feature flags for the current UI.
799+
* <p>
800+
* Not private in order to support mocking
801+
*
802+
* @return the current set of feature flags
803+
*/
804+
FeatureFlags getFeatureFlags() {
805+
return FeatureFlags
806+
.get(UI.getCurrent().getSession().getService().getContext());
807+
}
808+
809+
/**
810+
* Only for test use.
811+
*/
812+
void setFeatureFlagEnabled(boolean featureFlagEnabled) {
813+
this.featureFlagEnabled = featureFlagEnabled;
814+
}
815+
776816
/**
777817
* The internationalization properties for {@link Dashboard}.
778818
*/

vaadin-dashboard-flow-parent/vaadin-dashboard-flow/src/main/java/com/vaadin/flow/component/dashboard/DashboardWidget.java

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,11 @@
88
*/
99
package com.vaadin.flow.component.dashboard;
1010

11+
import com.vaadin.experimental.FeatureFlags;
12+
import com.vaadin.flow.component.AttachEvent;
1113
import com.vaadin.flow.component.Component;
1214
import com.vaadin.flow.component.Tag;
15+
import com.vaadin.flow.component.UI;
1316
import com.vaadin.flow.component.dependency.JsModule;
1417
import com.vaadin.flow.component.dependency.NpmPackage;
1518
import com.vaadin.flow.component.shared.SlotUtils;
@@ -34,6 +37,8 @@ public class DashboardWidget extends Component {
3437

3538
private int rowspan = 1;
3639

40+
private boolean featureFlagEnabled;
41+
3742
/**
3843
* Returns the title of the widget.
3944
*
@@ -176,6 +181,12 @@ public boolean isVisible() {
176181
return true;
177182
}
178183

184+
@Override
185+
protected void onAttach(AttachEvent attachEvent) {
186+
super.onAttach(attachEvent);
187+
checkFeatureFlag();
188+
}
189+
179190
private void notifyParentDashboardOrSection() {
180191
getParent().ifPresent(parent -> {
181192
if (parent instanceof Dashboard dashboard) {
@@ -185,4 +196,39 @@ private void notifyParentDashboardOrSection() {
185196
}
186197
});
187198
}
199+
200+
/**
201+
* Checks whether the Dashboard component feature flag is active. Succeeds
202+
* if the flag is enabled, and throws otherwise.
203+
*
204+
* @throws ExperimentalFeatureException
205+
* when the {@link FeatureFlags#DASHBOARD_COMPONENT} feature is
206+
* not enabled
207+
*/
208+
private void checkFeatureFlag() {
209+
boolean enabled = featureFlagEnabled || getFeatureFlags()
210+
.isEnabled(FeatureFlags.DASHBOARD_COMPONENT);
211+
if (!enabled) {
212+
throw new ExperimentalFeatureException();
213+
}
214+
}
215+
216+
/**
217+
* Gets the feature flags for the current UI.
218+
* <p>
219+
* Not private in order to support mocking
220+
*
221+
* @return the current set of feature flags
222+
*/
223+
FeatureFlags getFeatureFlags() {
224+
return FeatureFlags
225+
.get(UI.getCurrent().getSession().getService().getContext());
226+
}
227+
228+
/**
229+
* Only for test use.
230+
*/
231+
void setFeatureFlagEnabled(boolean featureFlagEnabled) {
232+
this.featureFlagEnabled = featureFlagEnabled;
233+
}
188234
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/**
2+
* Copyright 2000-2024 Vaadin Ltd.
3+
*
4+
* This program is available under Vaadin Commercial License and Service Terms.
5+
*
6+
* See {@literal <https://vaadin.com/commercial-license-and-service-terms>} for the full
7+
* license.
8+
*/
9+
package com.vaadin.flow.component.dashboard;
10+
11+
/**
12+
* An exception which is thrown when somebody attempts to use {@link Dashboard}
13+
* or {@link DashboardWidget} components without activating the associated
14+
* feature flag first.
15+
*
16+
* @author Vaadin Ltd
17+
*/
18+
public class ExperimentalFeatureException extends RuntimeException {
19+
public ExperimentalFeatureException() {
20+
super("The Dashboard component is currently an experimental feature and needs to be "
21+
+ "explicitly enabled. The component can be enabled using Copilot, in the "
22+
+ "experimental features tab, or by adding a "
23+
+ "`src/main/resources/vaadin-featureflags.properties` file with the following content: "
24+
+ "`com.vaadin.experimental.dashboardComponent=true`");
25+
}
26+
}
Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* See {@literal <https://vaadin.com/commercial-license-and-service-terms>} for the full
77
* license.
88
*/
9-
package com.vaadin.flow.component.dashboard.tests;
9+
package com.vaadin.flow.component.dashboard;
1010

1111
import java.util.ArrayList;
1212
import java.util.List;
@@ -20,9 +20,6 @@
2020
import org.junit.Test;
2121

2222
import com.vaadin.flow.component.Component;
23-
import com.vaadin.flow.component.dashboard.Dashboard;
24-
import com.vaadin.flow.component.dashboard.DashboardSection;
25-
import com.vaadin.flow.component.dashboard.DashboardWidget;
2623

2724
import elemental.json.Json;
2825
import elemental.json.JsonArray;
@@ -37,11 +34,13 @@ public class DashboardItemMoveTest extends DashboardTestBase {
3734
@Override
3835
public void setup() {
3936
super.setup();
40-
dashboard = new Dashboard();
41-
dashboard.add(new DashboardWidget(), new DashboardWidget());
37+
dashboard = getNewDashboard();
38+
dashboard.setFeatureFlagEnabled(true);
39+
dashboard.add(getNewWidget(), getNewWidget());
4240
dashboard.setEditable(true);
4341
DashboardSection section = dashboard.addSection();
44-
section.add(new DashboardWidget(), new DashboardWidget());
42+
43+
section.add(getNewWidget(), getNewWidget());
4544
getUi().add(dashboard);
4645
fakeClientCommunication();
4746
itemsArray = getItemsArray(dashboard.getChildren().toList());
Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* See {@literal <https://vaadin.com/commercial-license-and-service-terms>} for the full
77
* license.
88
*/
9-
package com.vaadin.flow.component.dashboard.tests;
9+
package com.vaadin.flow.component.dashboard;
1010

1111
import java.util.List;
1212
import java.util.concurrent.atomic.AtomicInteger;
@@ -17,9 +17,6 @@
1717
import org.junit.Test;
1818

1919
import com.vaadin.flow.component.Component;
20-
import com.vaadin.flow.component.dashboard.Dashboard;
21-
import com.vaadin.flow.component.dashboard.DashboardSection;
22-
import com.vaadin.flow.component.dashboard.DashboardWidget;
2320

2421
public class DashboardItemResizeTest extends DashboardTestBase {
2522
private Dashboard dashboard;
@@ -28,11 +25,11 @@ public class DashboardItemResizeTest extends DashboardTestBase {
2825
@Override
2926
public void setup() {
3027
super.setup();
31-
dashboard = new Dashboard();
32-
dashboard.add(new DashboardWidget());
28+
dashboard = getNewDashboard();
29+
dashboard.add(getNewWidget());
3330
dashboard.setEditable(true);
3431
DashboardSection section = dashboard.addSection();
35-
section.add(new DashboardWidget());
32+
section.add(getNewWidget());
3633
getUi().add(dashboard);
3734
fakeClientCommunication();
3835
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* See {@literal <https://vaadin.com/commercial-license-and-service-terms>} for the full
77
* license.
88
*/
9-
package com.vaadin.flow.component.dashboard.tests;
9+
package com.vaadin.flow.component.dashboard;
1010

1111
import com.vaadin.flow.testutil.ClassesSerializableTest;
1212

0 commit comments

Comments
 (0)