Skip to content

Commit

Permalink
feat: add MenuConfiguration
Browse files Browse the repository at this point in the history
New public API for building application menu: adds `MenuConfiguration`, `MenuOptions` and `MenuOption` where `MenuConfiguration` is the main entry point to access menu data to build main menu.

Fixes: #20063
  • Loading branch information
tltv committed Oct 4, 2024
1 parent 430c40f commit 4ff26d4
Show file tree
Hide file tree
Showing 7 changed files with 463 additions and 31 deletions.
21 changes: 5 additions & 16 deletions flow-server/src/main/java/com/vaadin/flow/router/MenuData.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,14 @@
import java.io.Serializable;
import java.util.Objects;

import com.vaadin.flow.component.Component;

/**
* Data class for menu item information.
* <p>
* Only for read as data is immutable.
*/
public record MenuData(String title, Double order, boolean exclude, String icon) implements Serializable {
public record MenuData(String title, Double order, boolean exclude, String icon, Class<? extends Component> menuClass) implements Serializable {

/**
* Gets the title of the menu item.
Expand Down Expand Up @@ -65,20 +67,7 @@ public String getIcon() {
@Override
public String toString() {
return "MenuData{" + "title='" + title + '\'' + ", order=" + order
+ ", exclude=" + exclude + ", icon='" + icon + '\'' + '}';
}

@Override
public boolean equals(Object obj) {
return obj instanceof MenuData other
&& Objects.equals(title, other.title)
&& Objects.equals(order, other.order)
&& Objects.equals(exclude, other.exclude)
&& Objects.equals(icon, other.icon);
}

@Override
public int hashCode() {
return Objects.hash(title, order, exclude, icon);
+ ", exclude=" + exclude + ", icon='" + icon + "', menuClass='"
+ menuClass + "'" + '}';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ private void populateRegisteredRoutes(ConfiguredRoutes configuration,
(Objects.equals(menu.order(), Double.MIN_VALUE)) ? null
: menu.order(),
excludeFromMenu,
(menu.icon().isBlank() ? null : menu.icon())))
(menu.icon().isBlank() ? null : menu.icon()), target))
.orElse(null);

RouteData route = new RouteData(parentLayouts, template, parameters,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright 2000-2024 Vaadin Ltd.
*
* Licensed 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 com.vaadin.flow.server.menu;

import java.io.Serializable;

/**
* Menu configuration helper class to retrieve available menu options for
* application main menu.
*/
public class MenuConfiguration implements Serializable {

/**
* Get the {@link MenuOptions} instance containing all menu options for the
* application.
*
* @return the {@link MenuOptions} instance
*/
public static MenuOptions getMenuOptions() {
return MenuOptions.getInstance();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Copyright 2000-2024 Vaadin Ltd.
*
* Licensed 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 com.vaadin.flow.server.menu;

import java.io.Serializable;

import com.vaadin.flow.component.Component;

/**
* Menu option for the main menu.
*
* @param path
* the path to navigate to
* @param title
* the title to display
* @param order
* the order in the menu or null for default order
* @param exclude
* whether to exclude the menu option
* @param icon
* Icon to use in the menu or null for no icon. Value can go inside a
* {@code <vaadin-icon>} element's {@code icon} attribute which
* accepts icon group and name like 'vaadin:file'. Or it can go to a
* {@code <vaadin-icon>} element's {@code src} attribute which takes
* path to the icon. E.g. 'line-awesome/svg/lock-open-solid.svg'.
* @param menuClass
* the source class with {@link com.vaadin.flow.router.Menu}
* annotation or null if not available
*/
public record MenuOption(String path, String title, Double order,
boolean exclude, String icon, Class<? extends Component> menuClass) implements Serializable {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* Copyright 2000-2024 Vaadin Ltd.
*
* Licensed 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 com.vaadin.flow.server.menu;

import java.io.Serializable;
import java.util.List;
import java.util.stream.Stream;

/**
* {@link MenuOptions} holds a list of menu options.
*/
public class MenuOptions implements Serializable {

private final List<MenuOption> menuOptions;

private MenuOptions(List<MenuOption> menuOptions) {
this.menuOptions = menuOptions;
}

/**
* Construct a new instance containing all available menu options.
*/
public static MenuOptions getInstance() {
return new MenuOptions(
MenuRegistry.collectMenuItemsList().stream().map(viewInfo -> {
if (viewInfo.menu() == null) {
return new MenuOption(viewInfo.route(),
viewInfo.title(), null, false, null, null);
}
return new MenuOption(viewInfo.route(),
(viewInfo.menu().title() != null
&& !viewInfo.menu().title().isBlank()
? viewInfo.menu().title()
: viewInfo.title()),
viewInfo.menu().order(), viewInfo.menu().exclude(),
viewInfo.menu().icon(),
viewInfo.menu().menuClass());
}).toList());
}

/**
* Get a stream of the menu options.
*
* @return the menu options stream
*/
public Stream<MenuOption> stream() {
return menuOptions.stream();
}

/**
* Get the list of the menu options. Returned list is mutable and any
* changes to it will also change {@link MenuOptions} state.
*
* @return the menu options list
*/
public List<MenuOption> get() {
return menuOptions;
}
}
Loading

0 comments on commit 4ff26d4

Please sign in to comment.