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.console.freemarker;
018
019import static org.apache.juneau.commons.utils.CollectionUtils.*;
020
021import java.util.*;
022
023/**
024 * The rail of a dashboard: a column of {@link Section}s beside the panel grid, with a splitter.
025 *
026 * <p>
027 * The width is a default; the user's dragged width is saved per page.  Below 900 px the rail moves above the grid
028 * as a collapsible "Filters" disclosure.
029 * </p>
030 *
031 * <h5 class='section'>Example:</h5>
032 * <p class='bjava'>
033 *    Rail.<jsm>left</jsm>().width(280).sections(SearchSection.<jsm>create</jsm>().publishes(Topics.<jsm>filter</jsm>(<js>"search"</js>)));
034 * </p>
035 *
036 * @since 10.0.0
037 */
038public final class Rail {
039
040   private final String side;
041   private int width = 280;
042   private final List<Section> sections = new ArrayList<>();
043
044   private Rail(String side) {
045      this.side = side;
046   }
047
048   /** @return A rail on the left of the grid. */
049   public static Rail left() {
050      return new Rail("left");
051   }
052
053   /** @return A rail on the right of the grid. */
054   public static Rail right() {
055      return new Rail("right");
056   }
057
058   /**
059    * Sets the default width.
060    *
061    * @param value The width in pixels, 200 to 480.  Defaults to 280.
062    * @return This object.
063    */
064   public Rail width(int value) {
065      width = value;
066      return this;
067   }
068
069   /**
070    * Appends sections, top to bottom.
071    *
072    * @param values The sections.
073    * @return This object.
074    */
075   public Rail sections(Section...values) {
076      for (var v : values)
077         sections.add(Objects.requireNonNull(v, "rail section must not be null"));
078      return this;
079   }
080
081   /** @return The sections, in order. */
082   List<Section> sections() {
083      return sections;
084   }
085
086   /**
087    * Checks the rail and every section, reporting E-77 under {@code dash}.
088    *
089    * @param dash The dashboard id.
090    */
091   void check(String dash) {
092      if (width < 200 || width > 480)
093         throw Section.e77(dash, "rail width " + width + " is outside 200-480");
094      for (var s : sections)
095         s.check(dash);
096   }
097
098   /** @return The rail JSON. */
099   Map<String,Object> toMap() {
100      var list = sections.stream().map(Section::toMap).toList();
101      return map("side", side, "width", width, "sections", list);
102   }
103}