Reference

Reference Templates

Templates

OtherEvergreenPublic

AEMTemplatesDashboard

import React, { useState, useEffect } from 'react';
import './AEMTemplatesDashboard.css';

const AEMTemplatesDashboard = (props) => {
  const { listDataProps = `{}` } = props; //props from aem/html
  console.log('Properties' + JSON.stringify(listDataProps));
  const { message, pattern, configurationPathPattern, liveusageQueryPath } =
    listDataProps; //props from redux/state

  const [loading, setLoading] = useState(false);
  const [aemTemplateList, setAemTemplateList] = useState([]);
  const [query, setQuery] = useState('');
  const [tabWindow, setTabWindow] = useState('templates');
  const [aemLiveUsageList, setAemLiveUsageList] = useState([]);
  const [aemLiveUsageListSize, setAemLiveUsageListSize] = useState(0);
  const [selectedTemplatePath, setSelectedTemplatePath] = useState(null);

  //const [scale, setScale] = useState(0);  //local state is not used, state kept in redux, allows to state sharing all components.
  useEffect(() => {
    getTemplates();
  }, [query]);

  async function getCsrfToken() {
    const response = await fetch('/libs/granite/csrf/token.json');
    const json = await response.json();
    return json.token;
  }

  async function getTemplates() {
    const details = {
      q: query,
      tp: pattern,
      tcp: configurationPathPattern,
    };

    let formBody = [];
    for (const property in details) {
      if (details[property]) {
        const encodedKey = encodeURIComponent(property);
        const encodedValue = encodeURIComponent(details[property]);
        formBody.push(encodedKey + '=' + encodedValue);
      }
    }
    formBody = formBody.join('&');

    fetch('/bin/aemcatalog.templates.json', {
      headers: {
        Accept: 'application/json',
        'Content-Type': 'application/x-www-form-urlencoded',
        'CSRF-Token': await getCsrfToken(),
      },
      method: 'POST',
      body: formBody,
    })
      .then((response) => response.json())
      .then((templates) => {
        if (templates && templates.aemTemplateList) {
          setAemTemplateList(templates.aemTemplateList);
        } else {
          setAemTemplateList([]);
          console.log('No template options loaded.');
        }
        setLoading(false);
      })
      .catch((err) => {
        console.log(err);
        setLoading(false);
        setAemTemplateList([]);
      });
  }

  function getWsParameter() {
    const search = window.location.search;
    const params = new URLSearchParams(search);
    const wsValue = params.get('ws');
    if (wsValue) {
      return wsValue;
    }
    return '';
  }

  async function getLiveUsage(templatePath, liveusageQueryPath) {
    setSelectedTemplatePath(templatePath);

    const details = {
      qpath: liveusageQueryPath,
      tpath: templatePath,
      ws: getWsParameter(),
    };

    let formBody = [];
    for (const property in details) {
      if (details[property]) {
        const encodedKey = encodeURIComponent(property);
        const encodedValue = encodeURIComponent(details[property]);
        formBody.push(encodedKey + '=' + encodedValue);
      }
    }
    formBody = formBody.join('&');

    fetch('/bin/aemcatalog.templateusage.json', {
      headers: {
        Accept: 'application/json',
        'Content-Type': 'application/x-www-form-urlencoded',
        'CSRF-Token': await getCsrfToken(),
      },
      method: 'POST',
      body: formBody,
    })
      .then((response) => response.json())
      .then((components) => {
        if (components && components.aemTemplateUsageList) {
          setAemLiveUsageList(components.aemTemplateUsageList);
          setAemLiveUsageListSize(components.count);
        } else {
          setAemLiveUsageList([]);
          setAemLiveUsageListSize(0);
          console.log('No component options loaded.');
        }
        //setLoading(false);
      })
      .catch((err) => {
        console.log(err);
        //setLoading(false);
        setAemLiveUsageList([]);
        setAemLiveUsageListSize(0);
      });
  }

  return (
    <div className="dashboard">
      {/* templates*/}
      <div
        className={
          ' ' + (tabWindow === 'templates' ? 'display-tab' : 'hide-tab')
        }
      >
        <div className="template-controls container">
          <div className="row">
            <div className="col-lg-3 col-xs-6 mb-3">
              <label htmlFor="filterListInput" className="form-label filter">
                Filter list by name
              </label>
              <input
                type="text"
                className="form-control"
                id="filterListInput"
                placeholder=""
                value={query}
                onChange={(e) => setQuery(e.target.value)}
              />
            </div>
          </div>
        </div>
        <div className="template-list container">
          {loading && <div>Loading...</div>}
          {aemTemplateList && (
            <div className="component-group">
              <div className="row">
                {aemTemplateList.map((template, index) => (
                  <div
                    key={index}
                    className="col-xl-3 col-lg-4 col-md-6 col-xs-12"
                  >
                    <a
                      className="card"
                      onClick={(e) => {
                        setTabWindow('liveusage');
                        getLiveUsage(template.path, liveusageQueryPath);
                      }}
                    >
                      <div className="card-body">
                        <h5 className="card-title">{template.title}</h5>
                        {template.thumbnailPath && (
                          <img
                            className="card-image"
                            src={template.thumbnailPath}
                          />
                        )}
                        {!template.thumbnailPath && (
                          <img
                            className="card-image"
                            src="/etc.clientlibs/aem-component-catalog/clientlibs/clientlib-react/resources/placeholder.svg"
                          />
                        )}
                        <h6 className="card-subtitle">{template.name}</h6>
                        <p className="card-text">{template.description}</p>
                        <p className="card-text">{template.path}</p>
                        <span className="card-link">
                          <span className="material-symbols-rounded">info</span>{' '}
                          View Usage Details
                        </span>
                      </div>
                    </a>
                  </div>
                ))}
              </div>
            </div>
          )}
        </div>
      </div>
      {/* End templates*/}

      {/*  liveusage*/}
      <div
        className={
          ' ' + (tabWindow === 'liveusage' ? 'display-tab' : 'hide-tab')
        }
      >
        <a
          className="nav-link"
          onClick={(e) => {
            setTabWindow('templates');
          }}
        >
          &larr; Back to Templates
        </a>

        <table className="liveusage-list table">
          <thead>
            <tr>
              <th scope="col">Count</th>
              <th scope="col">Template</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td>{aemLiveUsageListSize}</td>
              <td>{selectedTemplatePath}</td>
            </tr>
          </tbody>
        </table>
        <table className="liveusage-list table">
          <thead>
            <tr>
              <th scope="col">Title</th>
              <th scope="col">Page or Fragment Path</th>
            </tr>
          </thead>

          {aemLiveUsageList && (
            <tbody>
              {aemLiveUsageList.map((item, index) => (
                <tr key={index}>
                  <td>{item.title}</td>
                  <td>{item.path}</td>
                </tr>
              ))}
            </tbody>
          )}
        </table>
      </div>
      {/* End liveusage*/}
    </div>
  );
};

export { AEMTemplatesDashboard };
.template-list .card-image {
    max-width: 100%;
    margin-bottom: 20px;
}

.listaemtemplates-react .hide-tab {
    display: none;
}