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 *    &lt;@console brand="My app" theme="light-brown"&gt;
042 *    &lt;@theme&gt;
043 *    &lt;@token name="--jc-pill-red-bg" value="#fdeceb"/&gt;
044 *    &lt;@token name="--jc-tab-bar-bg" alias="var(--jc-card-bg)"/&gt;
045 *    &lt;/@theme&gt;
046 *    ...
047 *    &lt;/@console&gt;
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}