From e2c9d25140e74e3aa26fa577d68e06fcc06d1687 Mon Sep 17 00:00:00 2001 From: Mathias Oterhals Myklebust <24361490+mathiazom@users.noreply.github.com> Date: Tue, 3 Sep 2024 12:41:47 +0200 Subject: [PATCH] v3 - per location compensations (#540) * feat(compensations): offices reference * feat(compensations): offices array preview * docs(compensations): improve array preview comment * feat(compensations): move offices string to preview subtitle and reformat * feat(compensations): helper description for offices field * feat(office): default descriptions for reusable office and offices fields * feat(compensations): rename office -> locations * docs(compensations): remove explainer for preview truncation cutoff * docs(compensations): document preview string function * docs(compensations): reword locations preview comment --- studio/schemas/documents/compensations.ts | 54 +++++++++++++++++++++++ studio/schemas/objects/locations.ts | 22 +++++++++ 2 files changed, 76 insertions(+) create mode 100644 studio/schemas/objects/locations.ts diff --git a/studio/schemas/documents/compensations.ts b/studio/schemas/documents/compensations.ts index 098b49db4..44d57f3c5 100644 --- a/studio/schemas/documents/compensations.ts +++ b/studio/schemas/documents/compensations.ts @@ -1,9 +1,13 @@ import { defineField, defineType } from "sanity"; import { titleSlug } from "../schemaTypes/slug"; import seo from "../objects/seo"; +import locations from "../objects/locations"; import { title } from "../fields/text"; import { benefitId } from "./benefit"; +// maximum number of locations to display in the preview without truncating +const LOCATIONS_PREVIEW_CUTOFF = 3; + export const compensationsId = "compensations"; const compensations = defineType({ @@ -11,6 +15,7 @@ const compensations = defineType({ type: "document", title: "Compensations", fields: [ + locations, title, titleSlug, seo, @@ -29,6 +34,55 @@ const compensations = defineType({ of: [{ type: benefitId }], }), ], + preview: { + select: { + title: "basicTitle", + /* + Access array object values using dot notation with the array index, e.g., "locations.0.basicTitle". + This approach allows selecting a subset of the array for preview purposes. + For more details, see: https://www.sanity.io/docs/previews-list-views#62febb15a63a + */ + ...[...Array(LOCATIONS_PREVIEW_CUTOFF + 1).keys()].reduce( + (o, i) => ({ ...o, [`location${i}`]: `locations.${i}.basicTitle` }), + {}, + ), + }, + prepare({ title, ...locationsMap }) { + return { + title, + subtitle: previewStringFromLocationsMap( + locationsMap, + LOCATIONS_PREVIEW_CUTOFF, + ), + }; + }, + }, }); +/** + * Generates a preview string based on the selected office locations. + * + * @param {Object} locationsMap - A map of office titles selected for preview, e.g., { office0: "Trondheim", office1: "Oslo", ... }. + * @param {number} cutoff - The maximum number of locations to display before shortening the preview string. + * @returns {string|undefined} - A formatted string summarizing the selected locations or `undefined` if no locations are selected. + */ +function previewStringFromLocationsMap( + locationsMap: { + [key: string]: string; + }, + cutoff: number, +): string | undefined { + const locations = Object.values(locationsMap).filter( + (o) => o !== undefined, + ); + if (locations.length === 0) { + return undefined; + } else if (locations.length === 1) { + return `Location: ${locations[0]}`; + } else if (locations.length > cutoff) { + return `Locations: ${locations.toSpliced(cutoff - 1).join(", ")}, and more`; + } + return `Locations: ${locations.toSpliced(-1).join(", ")} and ${locations.at(-1)}`; +} + export default compensations; diff --git a/studio/schemas/objects/locations.ts b/studio/schemas/objects/locations.ts new file mode 100644 index 000000000..36673297f --- /dev/null +++ b/studio/schemas/objects/locations.ts @@ -0,0 +1,22 @@ +import { defineField } from "sanity"; +import { locationId } from "../documents/location"; + +const locations = defineField({ + name: "locations", + type: "array", + title: "Relevant Locations", + description: + "You can tailor this content to specific office locations by selecting them here. If the content applies to all locations, just leave this field empty.", + of: [ + { + title: "Select a location", + type: "reference", + to: [{ type: locationId }], + options: { + disableNew: true, + }, + }, + ], +}); + +export default locations;