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.pages;
018
019import java.util.*;
020
021import org.apache.juneau.commons.beanquery.*;
022import org.apache.juneau.terminal.region.*;
023import org.apache.juneau.console.freemarker.*;
024import org.apache.juneau.console.views.*;
025import org.apache.juneau.console.views.RowAction.*;
026import org.apache.juneau.console.views.TableSpec.*;
027
028/**
029 * Builder twins of the Operations pages: P6 Jobs ({@code jobs.ftlh}) and P7 Audit ({@code audit.ftlh}).
030 *
031 * <h5 class='section'>Example:</h5>
032 * <p class='bjava'>
033 *    <jk>return</jk> <jsm>twin</jsm>(<jv>req</jv>, OpsPageBuilders.<jsm>audit</jsm>());
034 * </p>
035 */
036@SuppressWarnings({
037   "java:S1192" // Page-definition ids and labels repeat as inline literals by design.
038})
039public final class OpsPageBuilders {
040
041   private OpsPageBuilders() {}
042
043   /**
044    * P6 Jobs.
045    *
046    * @param groomOutput The latest groom run's terminal.
047    * @param groomFile The latest groom run's transcript file.
048    * @return The page spec.
049    */
050   public static PageSpec jobs(TerminalDef groomOutput, TerminalDef groomFile) {
051      return PageSpec.create().tab("ops/jobs").toolkit("views")
052         .html("restock-help", "Restocking", """
053            <div class="jc-prose"><p>Restock adds new available pets to the store as a background job; progress shows here until it finishes.
054            Submitting twice from the same dialog runs one job.  Give the card below a wait to see a cancel before anything changes, or a longer hold to see one after.</p></div>""")
055         .card(CardSpec.of("job-log", "restock").title("Restock inventory")
056            .body("submit", Map.of("endpoint", "/console/ops/jobs/restock", "submitLabel", "Restock", "fields", List.of(
057               Map.of("name", "DOG", "label", "Dogs (0-50)", "type", "number", "default", 1),
058               Map.of("name", "slowMs", "label", "Wait before restocking (ms, 0-10000)", "type", "number", "default", 0),
059               Map.of("name", "holdMs", "label", "Hold after restocking (ms, 0-10000)", "type", "number", "default", 1000))))
060            .body("urlParam", "job"))
061         .table(TableSpec.create("jobs").dataMode(DataMode.CLIENT).dataUrl("/console/ops/jobs/rows")
062            .pollIntervalMs(2000)
063            .columns(
064               Column.create("jobId").label("Job"),
065               Column.create("submitted").label("Submitted").render("timestamp"),
066               Column.create("state").label("State").render("pill"),
067               Column.create("result.message").label("Result"))
068            .ribbon(
069               RibbonItem.dialog("restock").title("Restock").endpoint("/console/ops/jobs/restock").method(Method.POST).form("/console/ops/jobs/restock-form"),
070               RibbonItem.refresh().id("refresh")))
071         .table(TableSpec.create("species").dataMode(DataMode.CLIENT).dataUrl("/console/ops/jobs/species")
072            .pollIntervalMs(2000)
073            .columns(
074               Column.create("species").label("Species"),
075               Column.create("available").label("Available"))
076            .detail(RowDetail.create("/console/ops/jobs/species/{id}").region(JobLogRegion.create("restock-species")
077               .submit(JobLogRegion.Submit.create("/console/ops/jobs/species/{id}/restock", "restock-species", "/console/ops/jobs/species/{id}/key")
078                  .submitLabel("Restock")
079                  .field(JobLogRegion.Field.of("count").label("How many (1-50)").type("number").defaultValue(1).required(true))
080                  .field(JobLogRegion.Field.of("species").type("hidden").source("row.species")))
081               .detail(JobLogRegion.Detail.of("fieldGrid", RegionDef.Field.of("available").label("Available")))
082               .output(JobLogRegion.Output.field("available").from("row.available"))
083               .toRegion())))
084         .card(CardSpec.of("terminal", "groom-output").title("Groom run").body("terminal", groomOutput.toMap()))
085         .card(CardSpec.of("terminal", "groom-file").title("Groom transcript (file)").body("terminal", groomFile.toMap()))
086         .table(TableSpec.create("groom-runs").dataMode(DataMode.CLIENT).dataUrl("/console/ops/jobs/groom-rows")
087            .columns(
088               Column.create("pet").label("Pet"),
089               Column.create("submitted").label("Submitted").render("timestamp"),
090               Column.create("state").label("State").render("pill"),
091               Column.create("lines").label("Lines"))
092            .detail(RowDetail.create("/console/ops/jobs/groom-runs/{id}")
093               .region(RegionDef.create("regroom").type(RegionDef.TYPE_ROW_DETAIL).populate("petstore-regroom").allowPopulators("petstore-regroom")))
094            .ribbon(
095               RibbonItem.dialog("groom").title("Groom").endpoint("/console/ops/jobs/groom").method(Method.POST).form("/console/ops/jobs/groom-form"),
096               RibbonItem.refresh().id("groom-refresh")));
097   }
098
099   /**
100    * P7 Audit.
101    *
102    * @return The page spec.
103    */
104   public static PageSpec audit() {
105      return PageSpec.create().tab("ops/audit").toolkit("views")
106         .table(TableSpec.create("audit").dataMode(DataMode.SERVER).dataUrl("/console/ops/audit/query")
107            .operators(SearchOperatorSet.standard())
108            .defaultOrder("at", Sort.DESC)
109            .columns(
110               Column.create("at").label("When").render("timestamp").searchType(SearchType.TIMESTAMP),
111               Column.create("actor").label("Actor").searchType(SearchType.TEXT),
112               Column.create("action").label("Action").searchType(SearchType.TEXT),
113               Column.create("entity").label("Entity").searchType(SearchType.TEXT),
114               Column.create("entityId").label("Id").searchType(SearchType.TEXT),
115               Column.create("detail").label("Detail").searchType(SearchType.TEXT))
116            .ribbon(RibbonItem.export("copy", "csv"), RibbonItem.refresh().id("refresh")));
117   }
118}