Source code - Fluid Topics - Latest

Fluid Topics Designer Guide

Category
Reference Guides
Audience
public
Version
Latest

The following HTML content sets up a container for the table.

The following JavaScript content performs two primary functions:

  • Select all the documents where the document type is map.
  • Retrieve the ft:lastEdition metadata values for each document.

The following JavaScript example relies on:

To add the same Custom component:

  1. In the HTML panel, copy and paste the following:

    <div id="result">
    <table id="result_table">
        <thead>
        <tr>
          <th>Type</th>
          <th>Title</th>
          <th>Last edition</th>
        </tr>
      </thead>
      <tbody>
      </tbody>
      </table>
    </div>
    <div id="result_paging"></div>
    
  2. In the CSS panel, copy and paste the following:

    div#result {
      margin:0px;
      width:100%;
    }
    
    table#result_table {
      border: 1px solid black;
      border-collapse: collapse;
    }
    
    table#result_table td, #result_table th {
      border: 1px solid black;
      padding: 15px 5px;
    }
    
    table#result_table th {
      background-color:#E8ECEF;
    }
    
    div#result_paging {
      margin-top: 10px;
    }
    
    div#result_paging a, div#result_paging span {
      border: 1px solid #000;
      border-radius: 10px;
      padding: 5px;
    }
    
  3. In the JS panel, copy and paste the following:

    (async () => {
      const FTAPI = await new window.fluidtopics.FluidTopicsApi();
      FTAPI["FtCallingApp"] = "custom-component-XXX";  // Change XXX to a more descriptive name
    
      let allResults = []; // Store all the fetched results
      let currentPage = 1; // Initialize the current page of the table
      const resultsPerPage = 10; // Number of results to display per page of the table
    
      /********* Search Request **********/
    
      async function fetchResults() {
        let body = {
          "filters": [{ 'key': 'ft:editorialType', values: ['book'] }],
          "paging": {
            "perPage": 50
          }
        };
    
        try {
          let apiMaps = await FTAPI.post('/api/khub/clustered-search', body);
    
          allResults = apiMaps.results.map(result => {
            let entry = result.entries[0];
            return {
              'type': entry.type,
              'url': entry.map.readerUrl,
              'title': entry.map.title,
              'metadata': entry.map.metadata
            };
          });
    
          displayResults(currentPage);
        } catch (error) {
          console.error('Error fetching search results:', error);
        }
      }
    
      /********* Metadata **********/
    
      function get_metadata_value_by_key(metas, key) {
        let o = metas.find(e => e.key === key);
        return (o === undefined ? '' : o.values.join(', '));
      }
    
      /********* Results Display **********/
    
      function displayResults(page) {
        // Calculate start and end indices for slicing the results
        const start = (page - 1) * resultsPerPage;
        const end = start + resultsPerPage;
        const paginatedResults = allResults.slice(start, end);
    
        let tbody = document.querySelector("#result_table tbody");
        tbody.innerHTML = ""; // Clear previous results from tbody
    
        paginatedResults.forEach(r => {
          let row = tbody.insertRow();
          let cell = row.insertCell();
          cell.innerHTML = r.type;
          cell = row.insertCell();
          cell.innerHTML = `<a href="${r.url}">${r.title}</a>`;
          cell = row.insertCell();
          cell.innerHTML = get_metadata_value_by_key(r.metadata, 'ft:lastEdition');
        });
    
        // Pagination
        let div_paging = document.getElementById("result_paging");
        div_paging.innerHTML = ""; // Clear previous pagination
    
        if (currentPage > 1) {
          let prevButton = document.createElement('button');
          prevButton.innerText = 'Prev';
          prevButton.onclick = () => {
            if (currentPage > 1) {
              currentPage -= 1;
              displayResults(currentPage);
            }
          };
          div_paging.appendChild(prevButton);
        }
    
        let total_pages = Math.ceil(allResults.length / resultsPerPage);
        let pageInfo = document.createElement('span');
        pageInfo.innerText = `${currentPage}/${total_pages}`;
        div_paging.appendChild(pageInfo);
    
        if (currentPage < total_pages) {
          let nextButton = document.createElement('button');
          nextButton.innerText = 'Next';
          nextButton.onclick = () => {
            if (currentPage < total_pages) {
              currentPage += 1;
              displayResults(currentPage);
            }
          };
          div_paging.appendChild(nextButton);
        }
      }
    
      // Initial fetch
      fetchResults();
    })();
    
  4. Save the component.

  5. Save and publish the page.

Custom components that call the Fluid Topics API must include an ftCallingApp header. To exclude these API calls from billing, set the ftCallingApp value to a name starting with custom-component.