diff --git a/resume/resume.ts b/resume/resume.ts index e4756b5..701929e 100644 --- a/resume/resume.ts +++ b/resume/resume.ts @@ -137,6 +137,35 @@ function getPropertyMultiSelect( return null; } +function getPropertyRelation( + property: PageObjectResponse['properties'][number], + lookupRows: PageObjectResponse[] +) { + if (property.type === 'relation') { + return property.relation.map(option => { + const row = lookupRows.find(row => row.id === option.id); + if (row) { + const ob: Record = {}; + for (const key in row.properties) { + if (row.properties[key].type === 'title') { + ob[key] = getPropertyText(row.properties[key]); + } else if (row.properties[key].type === 'rich_text') { + ob[key] = getPropertyText(row.properties[key]); + } else if (row.properties[key].type === 'number') { + ob[key] = row.properties[key].number; + } else if (row.properties[key].type === 'select') { + ob[key] = row.properties[key].select?.name; + } else if (row.properties[key].type === 'multi_select') { + ob[key] = row.properties[key].multi_select.map(option => option.name); + } + } + return ob + } + }); + } + return null; +} + // Retrieves a value from the "About" section by key function getAboutValueWithKey(rows: PageObjectResponse[], key: string) { const row = rows.find(row => getPropertyText(row.properties.Name) === key); @@ -199,9 +228,16 @@ function getPropertyDate(property: PageObjectResponse['properties'][number]) { return { start: null, end: null, duration: null }; } +async function getSkillsList(databases: Record) { + return (await getRows( + databases['Skills'].id, + )) as PageObjectResponse[]; +} + // Builds the experience list async function buildExperienceList( data: Record, + skills: PageObjectResponse[] ) { spinner.text = 'Reading company data'; const companies = (await getRows( @@ -251,11 +287,13 @@ async function buildExperienceList( start: start?.toFormat('MMMM yyyy'), end: end?.toFormat('MMMM yyyy') ?? 'Present', duration: toHuman(duration, !end), + domain: getPropertyRelation(exp.properties.Domain, skills), bullets: bulletsForExperience.map(bullet => { return { text: getPropertyText(bullet.properties.Name), - skills: getPropertyMultiSelect( - bullet.properties.Skills, + skills: getPropertyRelation( + bullet.properties.Skill, + skills ), }; }), @@ -323,7 +361,8 @@ async function buildEducationList( {}, ); - const experiences = await buildExperienceList(databases); + const skills = await getSkillsList(databases); + const experiences = await buildExperienceList(databases, skills); const education = await buildEducationList(databases); const about = await buildAboutInfo(databases); @@ -341,10 +380,10 @@ async function buildEducationList( education, }; - const outputPath = path.join(rootDir, '/resume.json'); + const outputPath = path.join(rootDir, '/typst/resume.json'); fs.writeFileSync(outputPath, JSON.stringify(data, null, 2)); - const pathToTemplate = path.join(rootDir, 'main.typ'); + const pathToTemplate = path.join(rootDir, '/typst/main.typ'); const output = q() .add(`typst compile ${pathToTemplate} ${outputFile}`) .run() diff --git a/resume/avatar.jpg b/resume/typst/avatar.jpg similarity index 100% rename from resume/avatar.jpg rename to resume/typst/avatar.jpg diff --git a/resume/constants.typ b/resume/typst/constants.typ similarity index 100% rename from resume/constants.typ rename to resume/typst/constants.typ diff --git a/resume/helpers.typ b/resume/typst/helpers.typ similarity index 100% rename from resume/helpers.typ rename to resume/typst/helpers.typ diff --git a/resume/icons/email.svg b/resume/typst/icons/email.svg similarity index 100% rename from resume/icons/email.svg rename to resume/typst/icons/email.svg diff --git a/resume/icons/github.svg b/resume/typst/icons/github.svg similarity index 100% rename from resume/icons/github.svg rename to resume/typst/icons/github.svg diff --git a/resume/icons/linkedin.svg b/resume/typst/icons/linkedin.svg similarity index 100% rename from resume/icons/linkedin.svg rename to resume/typst/icons/linkedin.svg diff --git a/resume/icons/location.svg b/resume/typst/icons/location.svg similarity index 100% rename from resume/icons/location.svg rename to resume/typst/icons/location.svg diff --git a/resume/icons/phone.svg b/resume/typst/icons/phone.svg similarity index 100% rename from resume/icons/phone.svg rename to resume/typst/icons/phone.svg diff --git a/resume/icons/web.svg b/resume/typst/icons/web.svg similarity index 100% rename from resume/icons/web.svg rename to resume/typst/icons/web.svg diff --git a/resume/main.typ b/resume/typst/main.typ similarity index 88% rename from resume/main.typ rename to resume/typst/main.typ index 9d873e1..bd9f8f7 100644 --- a/resume/main.typ +++ b/resume/typst/main.typ @@ -1,6 +1,6 @@ #import "resume.typ": * -#let data = json("resume.json") +#let data = json("./resume.json") #show: resume.with( name: data.name, @@ -28,7 +28,7 @@ #company-heading(company.company, start: company.start, end: company.end)[ #for exp in company.experience [ #let bullets = exp.bullets.map(bullet => bullet.text) - #job-heading(exp.title, start: exp.duration, list(..bullets)) + #job-heading(exp.title, start: exp.duration, domain: exp.domain.at(0).Name, list(..bullets)) ] ] ] diff --git a/resume/resume.typ b/resume/typst/resume.typ similarity index 90% rename from resume/resume.typ rename to resume/typst/resume.typ index ae7aa1b..3e73e07 100644 --- a/resume/resume.typ +++ b/resume/typst/resume.typ @@ -145,10 +145,11 @@ context text( weight: COMPANY_NAME_WEIGHT, size: COMPANY_NAME_SIZE, - font: __get("heading-font"), + font: __get("heading-font"), name ), + // third column, dots if start != none { repeat(h(0.3em) + "." + h(0.3em)) @@ -178,7 +179,7 @@ // Alias to school heading #let school-heading = company-heading -#let job-heading(title, location: none, start: none, end: none, comment: none, body) = { +#let job-heading(title, location: none, start: none, end: none, domain: none, comment: none, body) = { block( above: JOB_BLOCK_ABOVE, below: JOB_BLOCK_BELOW, @@ -186,7 +187,7 @@ // heading grid( - columns: (auto, auto, auto, 1fr, auto), + columns: (auto, auto, auto, auto, 1fr, auto), gutter: 1em, align: (left + horizon, right + horizon), @@ -200,10 +201,28 @@ title ), - // second column, job comment ellipsisd + + // domain + if domain != none { + context box( + fill: black, + outset: 0.2em, + inset: 0.2em, + radius: 0.2em, + text( + weight: "light", + size: 0.7em, + fill: white, + font: __get("heading-font"), + domain + ) + ) + }, + + // job comment ellipsisd if comment != none { [ ... ] }, - // third column, job comment ellipsis + // job comment ellipsis if comment != none { [ #comment ] }, // fourth column, hfill @@ -225,7 +244,7 @@ } ), - grid.cell(colspan: 5, body) + grid.cell(colspan: 6, body) ) ) } diff --git a/resume/state.typ b/resume/typst/state.typ similarity index 100% rename from resume/state.typ rename to resume/typst/state.typ