All checks were successful
		
		
	
	ci/woodpecker/push/woodpecker Pipeline was successful
				
			
		
			
				
	
	
		
			169 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			169 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
var sortState = {
 | 
						|
  sortBy: "sortArtist",
 | 
						|
  sortOrder: "asc",
 | 
						|
};
 | 
						|
 | 
						|
function init() {
 | 
						|
  fetch("/api/records")
 | 
						|
    .then((response) => response.json())
 | 
						|
    .then((records) => {
 | 
						|
      // prepare response
 | 
						|
      records.forEach(apiResponseParsing);
 | 
						|
      document.getElementById("search").addEventListener("input", (e) => {
 | 
						|
        renderTable(search(records, e.target.value));
 | 
						|
      });
 | 
						|
      renderTable(records);
 | 
						|
    });
 | 
						|
}
 | 
						|
 | 
						|
function renderTable(records, sortField) {
 | 
						|
  if (sortField) {
 | 
						|
    if (sortState.sortBy === sortField && sortState.sortOrder === "asc") {
 | 
						|
      sortState.sortOrder = "desc";
 | 
						|
    } else {
 | 
						|
      sortState.sortOrder = "asc";
 | 
						|
    }
 | 
						|
    sortState.sortBy = sortField;
 | 
						|
  }
 | 
						|
  records.sort((one, two) =>
 | 
						|
    (one[sortState.sortBy] + one["sortName"]).localeCompare(
 | 
						|
      two[sortState.sortBy] + two["sortName"]
 | 
						|
    )
 | 
						|
  );
 | 
						|
  if (sortState.sortOrder === "desc") {
 | 
						|
    records.reverse();
 | 
						|
  }
 | 
						|
  records.forEach((e, i) => (e.rowNumber = i)); // re-key
 | 
						|
 | 
						|
  // rendering
 | 
						|
  var recordElement = document.getElementById("records");
 | 
						|
  recordElement.innerHTML = TableTemplate(records);
 | 
						|
 | 
						|
  var recordCount = document.getElementById("recordCount");
 | 
						|
  recordCount.innerHTML = `${records.length} records`;
 | 
						|
 | 
						|
  // add listeners for selecting record to view
 | 
						|
  Array.from(recordElement.querySelectorAll("tbody tr"))
 | 
						|
    .slice(1) // remove header from Array
 | 
						|
    .forEach((row) => {
 | 
						|
      row.addEventListener("click", (e) => {
 | 
						|
        // add listener to swap current record
 | 
						|
        document.getElementById("current").innerHTML = RecordTemplate(
 | 
						|
          records[e.currentTarget.id]
 | 
						|
        );
 | 
						|
      });
 | 
						|
    });
 | 
						|
  // add sorting callbacks
 | 
						|
  Array.from(
 | 
						|
    recordElement.querySelectorAll("tbody tr th[data-sort-by]")
 | 
						|
  ).forEach((row) => {
 | 
						|
    row.addEventListener("click", function (e) {
 | 
						|
      renderTable(records, e.target.dataset.sortBy); // only add callback when there's a sortBy attribute
 | 
						|
    });
 | 
						|
  });
 | 
						|
  // mark currently active column
 | 
						|
  recordElement
 | 
						|
    .querySelector("tbody tr th[data-sort-by=" + sortState.sortBy + "]")
 | 
						|
    .classList.add(sortState.sortOrder);
 | 
						|
}
 | 
						|
 | 
						|
function apiResponseParsing(record) {
 | 
						|
  record.sortName = titleCleaner(record.name);
 | 
						|
  record.artists = record.artists.map((artist) => {
 | 
						|
    return artist.replace(/ \([0-9]+\)$/, "");
 | 
						|
  });
 | 
						|
  record.label = record.label.replace(/ \([0-9]+\)$/, "");
 | 
						|
  record.sortArtist = record.artists.reduce((acc, curr) => {
 | 
						|
    return (
 | 
						|
      acc +
 | 
						|
      curr
 | 
						|
        .replace(/^(An?|The)\s/i, "")
 | 
						|
        .toLowerCase()
 | 
						|
        .replaceAll('"', "")
 | 
						|
        .replaceAll(":", "")
 | 
						|
        .replaceAll("'", "")
 | 
						|
        .replaceAll(" ", "")
 | 
						|
    );
 | 
						|
  }, "");
 | 
						|
  return record;
 | 
						|
}
 | 
						|
 | 
						|
function search(records, searchBy) {
 | 
						|
  searchBy = searchCleaner(searchBy);
 | 
						|
  if (searchBy !== "") {
 | 
						|
    records = records.filter(({ name, artists, genre, label, year }) => {
 | 
						|
      return Object.values({
 | 
						|
        name,
 | 
						|
        artists: artists.join(" "),
 | 
						|
        genre,
 | 
						|
        label,
 | 
						|
        year,
 | 
						|
      }).find((field) => searchCleaner(field).indexOf(searchBy) !== -1);
 | 
						|
    });
 | 
						|
  }
 | 
						|
  return records;
 | 
						|
}
 | 
						|
 | 
						|
function titleCleaner(title) {
 | 
						|
  return title
 | 
						|
    .replace('"', "")
 | 
						|
    .replace(":", "")
 | 
						|
    .replace(/^(An?|The)\s/i, "");
 | 
						|
}
 | 
						|
 | 
						|
function searchCleaner(str) {
 | 
						|
  return str
 | 
						|
    .toLowerCase()
 | 
						|
    .replaceAll('"', "")
 | 
						|
    .replaceAll(":", "")
 | 
						|
    .replaceAll("'", "")
 | 
						|
    .replaceAll(" ", "");
 | 
						|
}
 | 
						|
 | 
						|
function RecordTemplate({
 | 
						|
  name,
 | 
						|
  artists,
 | 
						|
  coverURL,
 | 
						|
  format,
 | 
						|
  genre,
 | 
						|
  identifier,
 | 
						|
  label,
 | 
						|
  year,
 | 
						|
  discogsURL,
 | 
						|
}) {
 | 
						|
  return `${coverURL ? `<img src="${coverURL}" loading="lazy"/>` : ""}
 | 
						|
  <h1>${name}</h1>
 | 
						|
  <h2>${artists.join(", ")}</h2>
 | 
						|
  <span>${identifier}</span><br/>
 | 
						|
  <span>${genre}, ${label}, ${year}</span><br/>
 | 
						|
  <span>${format}</span><br/>
 | 
						|
  <span>
 | 
						|
    <a 
 | 
						|
      target="_blank"
 | 
						|
      href="${discogsURL}"
 | 
						|
    >
 | 
						|
      Data provided by Discogs.
 | 
						|
    </a>
 | 
						|
  </span>`;
 | 
						|
}
 | 
						|
 | 
						|
function TableRowTemplate({ name, coverURL, discogsURL }) {
 | 
						|
  return `<div class="record">
 | 
						|
    <img class="cover" src="${coverURL}" loading="lazy"/>
 | 
						|
    <span class="name">${name}</span>
 | 
						|
    <a 
 | 
						|
      target="_blank"
 | 
						|
      href="${discogsURL}"
 | 
						|
      class="discogsLink"
 | 
						|
    >
 | 
						|
      Data provided by Discogs.
 | 
						|
    </a>
 | 
						|
  </div>`;
 | 
						|
}
 | 
						|
 | 
						|
function TableTemplate(records) {
 | 
						|
  return `<div class="flow">${records.reduce((acc, record) => {
 | 
						|
    return acc.concat(TableRowTemplate(record));
 | 
						|
  }, "")} </div>`;
 | 
						|
}
 |