Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Get menu views api #19355

Merged
merged 10 commits into from
May 15, 2024
26 changes: 1 addition & 25 deletions flow-server/src/main/java/com/vaadin/flow/router/MenuData.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,31 +24,7 @@
* <p>
* Only for read as data is immutable.
*/
public class MenuData implements Serializable {

private final String title;
private final Double order;
private final boolean exclude;
private final String icon;

/**
* Creates a new instance of the menu data.
*
* @param title
* the title of the menu item
* @param order
* the order of the menu item
* @param exclude
* whether the menu item should be excluded
* @param icon
* the icon of the menu item
*/
public MenuData(String title, Double order, boolean exclude, String icon) {
this.title = title;
this.order = order;
this.exclude = exclude;
this.icon = icon;
}
public record MenuData(String title, Double order, boolean exclude, String icon) implements Serializable {

/**
* Gets the title of the menu item.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,24 @@
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Optional;

import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.UI;
import com.vaadin.flow.internal.CurrentInstance;
import com.vaadin.flow.router.internal.AbstractRouteRegistry;
import com.vaadin.flow.router.internal.BeforeEnterHandler;
import com.vaadin.flow.router.internal.HasUrlParameterFormat;
import com.vaadin.flow.router.internal.PathUtil;
import com.vaadin.flow.router.internal.RouteUtil;
import com.vaadin.flow.server.Command;
import com.vaadin.flow.server.InvalidRouteConfigurationException;
import com.vaadin.flow.server.RouteRegistry;
import com.vaadin.flow.server.SessionRouteRegistry;
import com.vaadin.flow.server.VaadinRequest;
import com.vaadin.flow.server.VaadinService;
import com.vaadin.flow.server.VaadinServlet;
import com.vaadin.flow.server.VaadinSession;
Expand Down Expand Up @@ -531,4 +535,41 @@ private final boolean isAnnotatedParameter(
return false;
}

/**
* Get the {@link RouteData} for all accessible registered navigation
* targets with a menu information. Access checking depends on the active
tltv marked this conversation as resolved.
Show resolved Hide resolved
* {@link VaadinService} and {@link VaadinRequest}.
* <p>
* Automatically adds access controls from UI if available.
*
* @return list of accessible menu routes available for handled registry
*/
public List<RouteData> getRegisteredAccessibleMenuRoutes() {
UI ui = UI.getCurrent();
if (ui != null) {
List<BeforeEnterListener> accessControls = ui.getInternals()
.getListeners(BeforeEnterHandler.class).stream()
.filter(BeforeEnterListener.class::isInstance)
.map(BeforeEnterListener.class::cast).toList();
return getRegisteredAccessibleMenuRoutes(accessControls);
}

return getRegisteredAccessibleMenuRoutes(Collections.emptyList());
}

/**
* Get the {@link RouteData} for all accessible registered navigation
* targets with a menu information. Access checking depends on the active
* {@link VaadinService} and {@link VaadinRequest} and the given collection
* of access controls.
*
* @param accessControls
* the access controls to use for checking access
* @return list of accessible menu routes available for handled registry
*/
public List<RouteData> getRegisteredAccessibleMenuRoutes(
Collection<BeforeEnterListener> accessControls) {
return getHandledRegistry().getRegisteredAccessibleMenuRoutes(
VaadinRequest.getCurrent(), accessControls);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/*
* 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.router.internal;

import java.io.Serializable;
import java.util.Optional;

/**
* Define a route url parameter details.
* <p>
* For internal use only. May be renamed or removed in a future release.
*/
public class ParameterInfo implements Serializable {

private final String name;

private final String template;

private final boolean optional;

private final boolean varargs;

private final String regex;

public ParameterInfo(String template) {
this.template = template;

if (!RouteFormat.isParameter(template)) {
throw new IllegalArgumentException(
"The given string is not a parameter template.");
}

optional = RouteFormat.isOptionalParameter(template);
if (optional) {
template = template.replaceFirst("\\?", "");
}
varargs = RouteFormat.isVarargsParameter(template);
if (varargs) {
template = template.replaceFirst("\\*", "");
}

// Remove :
template = template.substring(1);

// Extract the template defining the value of the parameter.
final int regexStartIndex = template.indexOf('(');
if (regexStartIndex != -1) {

name = template.substring(0, regexStartIndex);

regex = template.substring(regexStartIndex + 1,
template.length() - 1);
} else {
name = template;
regex = null;
}
}

public String getName() {
return name;
}

public String getTemplate() {
return template;
}

public boolean isOptional() {
return optional;
}

public boolean isVarargs() {
return varargs;
}

public Optional<String> getRegex() {
return Optional.ofNullable(regex);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -173,74 +173,4 @@ static Optional<String> formatSegmentRegex(RouteSegment segment,
}
}

/**
* Define a route url parameter details.
*/
static class ParameterInfo implements Serializable {

private final String name;

private final String template;

private final boolean optional;

private final boolean varargs;

private final String regex;

ParameterInfo(String template) {
this.template = template;

if (!isParameter(template)) {
throw new IllegalArgumentException(
"The given string is not a parameter template.");
}

optional = isOptionalParameter(template);
if (optional) {
template = template.replaceFirst("\\?", "");
}
varargs = isVarargsParameter(template);
if (varargs) {
template = template.replaceFirst("\\*", "");
}

// Remove :
template = template.substring(1);

// Extract the template defining the value of the parameter.
final int regexStartIndex = template.indexOf('(');
if (regexStartIndex != -1) {

name = template.substring(0, regexStartIndex);

regex = template.substring(regexStartIndex + 1,
template.length() - 1);
} else {
name = template;
regex = null;
}
}

public String getName() {
return name;
}

public String getTemplate() {
return template;
}

public boolean isOptional() {
return optional;
}

public boolean isVarargs() {
return varargs;
}

public Optional<String> getRegex() {
return Optional.ofNullable(regex);
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ final class RouteSegment implements Serializable {
/**
* Parameter details.
*/
private RouteFormat.ParameterInfo info;
private ParameterInfo info;

/**
* Parameter matching regex.
Expand Down Expand Up @@ -118,7 +118,7 @@ private RouteSegment(String segmentTemplate, boolean isRoot) {
this.isRoot = isRoot;

if (RouteFormat.isParameter(segmentTemplate)) {
info = new RouteFormat.ParameterInfo(segmentTemplate);
info = new ParameterInfo(segmentTemplate);

getRegex().ifPresent(s -> pattern = Pattern.compile(s));

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*
* 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.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import com.fasterxml.jackson.annotation.JsonProperty;

import com.vaadin.flow.router.MenuData;

/**
* Represents a view configuration for use with a menu.
*
* @param title
* @param rolesAllowed
* @param loginRequired
* @param route
* @param lazy
* @param register
* @param menu
* @param children
* @param routeParameters
*/
public record AvailableViewInfo(String title, String[] rolesAllowed,
boolean loginRequired, String route, boolean lazy,
boolean register, MenuData menu,
List<AvailableViewInfo> children, @JsonProperty(
"params") Map<String, RouteParamType> routeParameters) implements Serializable {

@Override
public boolean equals(final Object o) {
if (this == o) {
return true;
} else if (o == null || getClass() != o.getClass()) {
return false;
}
final AvailableViewInfo that = (AvailableViewInfo) o;
return Objects.equals(title, that.title)
&& Arrays.equals(rolesAllowed, that.rolesAllowed)
&& Objects.equals(loginRequired, that.loginRequired)
&& Objects.equals(route, that.route)
&& Objects.equals(lazy, that.lazy)
&& Objects.equals(register, that.register)
&& Objects.equals(menu, that.menu)
&& Objects.equals(routeParameters, that.routeParameters);
}

@Override
public int hashCode() {
int result = Objects.hash(title, loginRequired, route, lazy, register, menu, routeParameters);
result = 31 * result + Arrays.hashCode(rolesAllowed);
return result;
}

@Override
public String toString() {
return "AvailableViewInfo{" + "title='" + title
+ '\'' + ", rolesAllowed=" + Arrays.toString(rolesAllowed)
+ ", loginRequired=" + loginRequired
+ ", route='" + route + '\''
+ ", lazy=" + lazy
+ ", register=" + register
+ ", menu=" + menu
+ ", routeParameters=" + routeParameters + '}';
}

}
Loading
Loading