001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.juneau.petstore.console.dev; 018 019import java.util.*; 020 021import org.apache.juneau.http.*; 022import org.apache.juneau.http.response.*; 023import org.apache.juneau.petstore.console.*; 024import org.apache.juneau.petstore.console.pages.*; 025import org.apache.juneau.rest.server.*; 026import org.apache.juneau.console.*; 027import org.apache.juneau.rest.server.view.*; 028import org.apache.juneau.rest.server.view.freemarker.*; 029 030/** 031 * Themes: the stock console themes and one custom token theme, switchable with {@code ?theme=}. 032 * 033 * <p> 034 * The chosen name reaches {@code base.ftlh} as the {@code petstoreTheme} view attribute, which feeds 035 * {@code <@console theme=...>}. {@code ?theme=custom} also sets {@code petstoreCustomTheme}, which turns on a 036 * nameless {@code <@theme>} block (it inherits the page theme, {@code light-brown} here) with {@code <@token>} 037 * overrides: a leaf and an alias. 038 * 039 * <h5 class='section'>Example:</h5> 040 * <p class='bftl'> 041 * <@console brand="My app" theme="light-brown"> 042 * <@theme> 043 * <@token name="--jc-pill-red-bg" value="#fdeceb"/> 044 * <@token name="--jc-tab-bar-bg" alias="var(--jc-card-bg)"/> 045 * </@theme> 046 * ... 047 * </@console> 048 * </p> 049 * <p class='bcode'> 050 * GET /console/dev/themes?theme=gray 051 * </p> 052 */ 053@Rest(path="/themes", title="Themes") 054@SuppressWarnings({ 055 "java:S110", // Inheritance depth comes from the BasicRestServlet hierarchy, not this page. 056 "java:S2386" // CHOICES is an immutable List.copyOf(); public so templates and tests can read it. 057}) 058public class ThemesRest extends PetstoreConsolePage { 059 060 private static final long serialVersionUID = 1L; 061 062 /** The name {@code ?theme=} takes for the custom token theme. */ 063 public static final String CUSTOM = "custom"; 064 065 /** The custom theme's stock seed. */ 066 public static final String CUSTOM_SEED = "light-brown"; 067 068 /** Every name {@code ?theme=} accepts, stock themes first. */ 069 public static final List<String> CHOICES = choices(); 070 071 private static List<String> choices() { 072 var l = new ArrayList<>(ConsoleChromeMixin.BUILTIN_THEME_NAMES); 073 l.add(CUSTOM); 074 return List.copyOf(l); 075 } 076 077 /** 078 * Renders the Themes page. 079 * 080 * @param req The request; {@code ?builder} renders the builder twin. 081 * @param theme The theme to render in, or <jk>null</jk> for the default. 082 * @return The page. 083 * @throws BadRequest If the name is not one of {@link #CHOICES}. 084 */ 085 @RestGet(path="/") 086 public View page(RestRequest req, @Query("theme") String theme) { 087 var name = theme == null || theme.isEmpty() ? ConsoleChromeMixin.BUILTIN_THEME_NAMES.get(0) : theme; 088 if (! CHOICES.contains(name)) 089 throw new BadRequest("Unknown theme '%s'; choose one of: '%s'", name, String.join(", ", CHOICES)); 090 var custom = CUSTOM.equals(name); 091 if (builder(req)) 092 return twin(req, DevPageBuilders.themes(custom ? CUSTOM_SEED : name, custom, CHOICES)); 093 return FreemarkerView.of("themes.ftlh") 094 .attr("petstoreTheme", custom ? CUSTOM_SEED : name) 095 .attr("petstoreCustomTheme", custom) 096 .attr("themeChoices", CHOICES); 097 } 098}