Travel Dashboard

This describes the structure and content of the Travel Dashboard and includes all the needed queries.

Structure

Quick Actions

This contains buttons for the most relevant entities, letting the user add new ones quickly.

Trips

An overview of

Important

Remember that all inline DataviewJS queries need to be surrounded by single backticks ( `` ) and start with $= .

Disclaimer

All these queries were created, debugged, and documented with the help of the "Obsidian Oracle", a ChatGPT based custom GPT focused on Obsidian, Dataview, DataviewJS, and Templater scripts.
Not being a programmer, it really helped me, and might help you, too.

Planned

dv.list(dv.pages('')
  .filter(f => f.file.path.startsWith("Travel/"))
  .filter(f => f.tags && Array.isArray(f.tags) ? f.tags.some(tag => tag.includes("Trip")) : false)
  .filter(f => f["Travel Status"] && f["Travel Status"].includes("Planned"))
  .sort(f => f.Departure, "asc")
  .map(f => `${f.file.link}\n${f.Country}`))

Generates a list of planned trips, sorted by departure date in ascending order, and each entry in the list includes the page's link and associated country.

  1. dv.pages(''): This retrieves all pages from the DataView named dv.
  2. .filter(f => f.file.path.startsWith("Travel/")): This filters the pages to include only those with a file path starting with "Travel/".
  3. .filter(f => f.tags && Array.isArray(f.tags) ? f.tags.some(tag => tag.includes("Trip")) : false): This filters the pages further to include only those that have tags containing the word "Trip".
  4. .filter(f => f["Travel Status"] && f["Travel Status"].includes("Planned")): This filters the pages to include only those with a "Travel Status" property containing the word "Planned".
  5. .sort(f => f.Departure, "asc"): This sorts the filtered pages in ascending order based on the "Departure" property.
  6. .map(f => f.file.link\n{f.Country}): This maps each page to a string containing the page's link and the country associated with it, separated by a newline character.

Booked

dv.list(dv.pages('')
  .filter(f => f.file.path.startsWith("Travel/"))
  .filter(f => f.tags && Array.isArray(f.tags) ? f.tags.some(tag => tag.includes("Trip")) : false)
  .filter(f => f["Travel Status"] && f["Travel Status"].includes("Booked"))
  .sort(f => f.Departure, "asc")
  .map(f => `${f.file.link}\n${f.Country}`))

So, overall, this query creates a list of booked trips, sorted by departure date in ascending order, with each entry in the list including the page's link and associated country.

  1. dv.pages(''): Retrieves all pages from the DataView named dv.
  2. .filter(f => f.file.path.startsWith("Travel/")): Filters the pages to include only those with a file path starting with "Travel/".
  3. .filter(f => f.tags && Array.isArray(f.tags) ? f.tags.some(tag => tag.includes("Trip")) : false): Further filters the pages to include only those that have tags containing the word "Trip".
  4. .filter(f => f["Travel Status"] && f["Travel Status"].includes("Booked")): Filters the pages to include only those with a "Travel Status" property containing the word "Booked".
  5. .sort(f => f.Departure, "asc"): Sorts the filtered pages in ascending order based on the "Departure" property.
  6. .map(f => f.file.link\n{f.Country}): Maps each page to a string containing the page's link and the associated country, separated by a newline character.

Missing review

dv.list(dv.pages('')
  .filter(f => f.file.path.startsWith("Travel/"))
  .filter(f => f.tags && Array.isArray(f.tags) ? f.tags.some(tag => tag.includes("Trip")) : false)
  .filter(f => f["Travel Status"] && f["Travel Status"].includes("Over"))
  .filter(f => f["Review Status"] && f["Review Status"].includes("Missing"))
  .sort(f => f.Return, "desc")
  .map(f => `${f.file.link}\n${moment(f.Return).format("DD-MM-YYYY")}`))

This query returns a list of travel pages where the trip is marked as "Over" and the review is missing, sorted by the return date in descending order, and each entry in the list includes the page's link and the formatted return date.

  1. dv.pages(''): Retrieves all pages from the DataView named dv.
  2. .filter(f => f.file.path.startsWith("Travel/")): Filters the pages to include only those with a file path starting with "Travel/".
  3. .filter(f => f.tags && Array.isArray(f.tags) ? f.tags.some(tag => tag.includes("Trip")) : false): Further filters the pages to include only those that have tags containing the word "Trip".
  4. .filter(f => f["Travel Status"] && f["Travel Status"].includes("Over")): Filters the pages to include only those with a "Travel Status" property containing the word "Over".
  5. .filter(f => f["Review Status"] && f["Review Status"].includes("Missing")): Filters the pages to include only those with a "Review Status" property containing the word "Missing".
  6. .sort(f => f.Return, "desc"): Sorts the filtered pages in descending order based on the "Return" property.
  7. .map(f => f.file.link\n{moment(f.Return).format("DD-MM-YYYY")}): Maps each page to a string containing the page's link and the formatted return date (using the moment library to format the date as "DD-MM-YYYY").

Top 10

Lists the

Most recent trips

dv.list(dv.pages('')
  .filter(f => f.file.path.startsWith("Travel/"))
  .filter(f => f.tags && Array.isArray(f.tags) ? f.tags.some(tag => tag.includes("Trip")) : false)
  .filter(f => f["Travel Status"] && f["Travel Status"].includes("Over"))
  .sort(f => f.Return, "desc")
  .map(f => `${f.file.link}\n${f.Country}`)
  .slice(0, 10))

This query generates a list of the first 10 travel pages where the trip is marked as "Over", sorted by the return date in descending order, with each entry in the list including the page's link and the associated country.

  1. dv.pages(''): Retrieves all pages from the DataView named dv.
  2. .filter(f => f.file.path.startsWith("Travel/")): Filters the pages to include only those with a file path starting with "Travel/".
  3. .filter(f => f.tags && Array.isArray(f.tags) ? f.tags.some(tag => tag.includes("Trip")) : false): Further filters the pages to include only those that have tags containing the word "Trip".
  4. .filter(f => f["Travel Status"] && f["Travel Status"].includes("Over")): Filters the pages to include only those with a "Travel Status" property containing the word "Over".
  5. .sort(f => f.Return, "desc"): Sorts the filtered pages in descending order based on the "Return" property.
  6. .map(f => f.file.link\n{f.Country}): Maps each page to a string containing the page's link and the associated country, separated by a newline character.
  7. .slice(0, 10): Limits the results to the first 10 entries in the list.

Most recent landmarks

dv.list(dv.pages('')
  .filter(f => f.file.path.startsWith("Travel/"))
  .filter(f => Array.isArray(f.tags) ? f.tags.some(tag => tag.includes("Landmark")) : false)
  .filter(f => f.Visited === true)
  .sort(f => f["Last Visited"], "desc")
  .map(f => `${f.file.link} \n ${f.Rating}`)
  .slice(0, 10))

Lists the first 10 visited landmarks, sorted by the last visited date in descending order, with each entry in the list including the page's link and its rating.

  1. dv.pages(''): Retrieves all pages from the DataView named dv.
  2. .filter(f => f.file.path.startsWith("Travel/")): Filters the pages to include only those with a file path starting with "Travel/".
  3. .filter(f => Array.isArray(f.tags) ? f.tags.some(tag => tag.includes("Landmark")) : false): Further filters the pages to include only those that have tags containing the word "Landmark".
  4. .filter(f => f.Visited === true): Filters the pages to include only those with the "Visited" property set to true.
  5. .sort(f => f["Last Visited"], "desc"): Sorts the filtered pages in descending order based on the "Last Visited" property.
  6. .map(f => ${f.file.link} \n ${f.Rating}): Maps each page to a string containing the page's link and its rating, separated by a newline character.
  7. .slice(0, 10): Limits the results to the first 10 entries in the list.

Best rated trips

dv.list(dv.pages('')
  .filter(f => f.file.path.startsWith("Travel/"))
  .filter(f => f.tags && Array.isArray(f.tags) ? f.tags.some(tag => tag.includes("Trip")) : false)
  .filter(f => f["Travel Status"] && f["Travel Status"].includes("Over"))
  .filter(f => f.Rating !== undefined && f.Rating !== null && f.Rating !== "")
  .sort(f => f.Rating, "asc")
  .map(f => `${f.file.link}\n${f.Rating}`)
  .slice(0, 10))

Overall, this query returns the first 10 completed trips, sorted by their ratings in ascending order, with each entry in the list including the page's link and its rating.

  1. dv.pages(''): Retrieves all pages from the DataView named dv.
  2. .filter(f => f.file.path.startsWith("Travel/")): Filters the pages to include only those with a file path starting with "Travel/".
  3. .filter(f => f.tags && Array.isArray(f.tags) ? f.tags.some(tag => tag.includes("Trip")) : false): Further filters the pages to include only those that have tags containing the word "Trip".
  4. .filter(f => f["Travel Status"] && f["Travel Status"].includes("Over")): Filters the pages to include only those with a "Travel Status" property containing the word "Over", indicating that the trip is completed.
  5. .filter(f => f.Rating !== undefined && f.Rating !== null && f.Rating !== ""): Filters the pages to include only those with a defined, non-null, and non-empty "Rating" property.
  6. .sort(f => f.Rating, "asc"): Sorts the filtered pages in ascending order based on the "Rating" property.
  7. .map(f => f.file.link\n{f.Rating}): Maps each page to a string containing the page's link and its rating, separated by a newline character.
  8. .slice(0, 10): Limits the results to the first 10 entries in the list.

Completed Reviews

Lists trips with completed reviews grouped by

This year

const currentYear = new Date().getFullYear(); // Get the current year	
dv.list(dv.pages('')
	.filter(f => f.file.path.startsWith("Travel/"))
	.filter(f => Array.isArray(f.tags) ? f.tags.some(tag => tag.includes("Trip")) : false)
	.filter(f => f["Review Status"] && f["Review Status"].includes("Done"))
	.filter(f => {
		const departureDate = new Date(f.Departure); // Convert "Departure" field to a Date object
		return departureDate.getFullYear() === currentYear; // Check if the year matches the current year
	})
	.sort(f => f.file.link, "asc")
	.map(f => f.file.link))

Returns a list of travel pages for trips that have been reviewed and have a departure date within the current year, sorted by their link in ascending order.

  1. const currentYear = new Date().getFullYear();: Retrieves the current year.
  2. dv.pages(''): Retrieves all pages from the DataView named dv.
  3. .filter(f => f.file.path.startsWith("Travel/")): Filters the pages to include only those with a file path starting with "Travel/".
  4. .filter(f => Array.isArray(f.tags) ? f.tags.some(tag => tag.includes("Trip")) : false): Further filters the pages to include only those that have tags containing the word "Trip".
  5. .filter(f => f["Review Status"] && f["Review Status"].includes("Done")): Filters the pages to include only those with a "Review Status" property containing the word "Done", indicating that the review is completed.
  6. .filter(f => { const departureDate = new Date(f.Departure); return departureDate.getFullYear() === currentYear; }): Filters the pages to include only those with a departure date in the current year. It converts the "Departure" field to a Date object and checks if its year matches the current year.
  7. .sort(f => f.file.link, "asc"): Sorts the filtered pages in ascending order based on the page's link.
  8. .map(f => f.file.link): Maps each page to its link.

Last year

const currentYear = new Date().getFullYear(); // Get the current year
const previousYear = currentYear - 1; // Calculate the previous year	
dv.list(dv.pages('')
	.filter(f => f.file.path.startsWith("Travel/"))
	.filter(f => Array.isArray(f.tags) ? f.tags.some(tag => tag.includes("Trip")) : false)
	.filter(f => f["Review Status"] && f["Review Status"].includes("Done"))
	.filter(f => {
		const departureDate = new Date(f.Departure); // Convert "Departure" field to a Date object
		return departureDate.getFullYear() === previousYear; // Check if the year matches the previous year
	})
	.sort(f => f.file.link, "asc")
	.map(f => f.file.link))

This query generates a list of travel pages for trips that have been reviewed and have a departure date within the previous year, sorted by their link in ascending order.

  1. const currentYear = new Date().getFullYear();: Retrieves the current year.
  2. const previousYear = currentYear - 1;: Calculates the previous year.
  3. dv.pages(''): Retrieves all pages from the DataView named dv.
  4. .filter(f => f.file.path.startsWith("Travel/")): Filters the pages to include only those with a file path starting with "Travel/".
  5. .filter(f => Array.isArray(f.tags) ? f.tags.some(tag => tag.includes("Trip")) : false): Further filters the pages to include only those that have tags containing the word "Trip".
  6. .filter(f => f["Review Status"] && f["Review Status"].includes("Done")): Filters the pages to include only those with a "Review Status" property containing the word "Done", indicating that the review is completed.
  7. .filter(f => { const departureDate = new Date(f.Departure); return departureDate.getFullYear() === previousYear; }): Filters the pages to include only those with a departure date in the previous year. It converts the "Departure" field to a Date object and checks if its year matches the previous year.
  8. .sort(f => f.file.link, "asc"): Sorts the filtered pages in ascending order based on the page's link.
  9. .map(f => f.file.link): Maps each page to its link.

Older

const currentYear = new Date().getFullYear(); // Get the current year
const startOfPreviousYear = new Date(currentYear - 1, 0, 1); // Get the start of the previous year	
dv.list(dv.pages('')
	.filter(f => f.file.path.startsWith("Travel/"))
	.filter(f => Array.isArray(f.tags) ? f.tags.some(tag => tag.includes("Trip")) : false)
	.filter(f => f["Review Status"] && f["Review Status"].includes("Done"))
	.filter(f => {
		const departureDate = new Date(f.Departure); // Convert "Departure" field to a Date object
		return departureDate < startOfPreviousYear; // Check if the departure date is before the start of the previous year
	})
	.sort(f => f.file.link, "asc")
	.map(f => f.file.link)
	.slice(0, 10))

Generates a list of travel pages for trips that have been reviewed and had a departure date before the start of the previous year, sorted by their link in ascending order, and displaying only the first 10 results.

  1. const currentYear = new Date().getFullYear();: Retrieves the current year.
  2. const startOfPreviousYear = new Date(currentYear - 1, 0, 1);: Calculates the start of the previous year.
  3. dv.pages(''): Retrieves all pages from the DataView named dv.
  4. .filter(f => f.file.path.startsWith("Travel/")): Filters the pages to include only those with a file path starting with "Travel/".
  5. .filter(f => Array.isArray(f.tags) ? f.tags.some(tag => tag.includes("Trip")) : false): Further filters the pages to include only those that have tags containing the word "Trip".
  6. .filter(f => f["Review Status"] && f["Review Status"].includes("Done")): Filters the pages to include only those with a "Review Status" property containing the word "Done", indicating that the review is completed.
  7. .filter(f => { const departureDate = new Date(f.Departure); return departureDate < startOfPreviousYear; }): Filters the pages to include only those with a departure date before the start of the previous year. It converts the "Departure" field to a Date object and checks if it is before the start of the previous year.
  8. .sort(f => f.file.link, "asc"): Sorts the filtered pages in ascending order based on the page's link.
  9. .map(f => f.file.link): Maps each page to its link.
  10. .slice(0, 10): Limits the results to the first 10 entries in the list.