diff --git a/src/__tests__/core/ContactNoteWriter.test.ts b/src/__tests__/core/ContactNoteWriter.test.ts index 8620f70..509a81e 100644 --- a/src/__tests__/core/ContactNoteWriter.test.ts +++ b/src/__tests__/core/ContactNoteWriter.test.ts @@ -122,6 +122,7 @@ describe('ContactNoteWriter', () => { folderPath: 'path/to/folder', noteBody: mockNoteBody, organizationAsLink: false, + relationsAsLink: false, trackSyncTime: true, renameFiles: false, namingStrategy: NamingStrategy.Default, @@ -172,6 +173,7 @@ describe('ContactNoteWriter', () => { folderPath: 'path/to/folder', noteBody: mockNoteBody, organizationAsLink: false, + relationsAsLink: false, trackSyncTime: true, renameFiles: false, namingStrategy: NamingStrategy.Default, @@ -221,6 +223,7 @@ describe('ContactNoteWriter', () => { folderPath: 'path/to/folder', noteBody: mockNoteBody, organizationAsLink: false, + relationsAsLink: false, trackSyncTime: true, renameFiles: false, namingStrategy: NamingStrategy.Default, @@ -264,6 +267,7 @@ describe('ContactNoteWriter', () => { folderPath: 'path/to/folder', noteBody: mockNoteBody, organizationAsLink: false, + relationsAsLink: false, trackSyncTime: true, renameFiles: false, namingStrategy: NamingStrategy.Default, @@ -305,6 +309,7 @@ describe('ContactNoteWriter', () => { folderPath: 'path/to/folder', noteBody: mockNoteBody, organizationAsLink: false, + relationsAsLink: false, trackSyncTime: true, renameFiles: false, namingStrategy: NamingStrategy.Default, diff --git a/src/__tests__/core/ContactNoteWriterProcess.test.ts b/src/__tests__/core/ContactNoteWriterProcess.test.ts index 083627e..c06c0e1 100644 --- a/src/__tests__/core/ContactNoteWriterProcess.test.ts +++ b/src/__tests__/core/ContactNoteWriterProcess.test.ts @@ -112,6 +112,7 @@ describe('ContactNoteWriterUpdate', () => { syncLabel: '', noteBody: mockNoteBody, organizationAsLink: false, + relationsAsLink: false, trackSyncTime: true, renameFiles: false, namingStrategy: NamingStrategy.Default, @@ -158,6 +159,7 @@ describe('ContactNoteWriterUpdate', () => { syncLabel: '', noteBody: mockNoteBody, organizationAsLink: false, + relationsAsLink: false, trackSyncTime: true, renameFiles: false, namingStrategy: NamingStrategy.Default, diff --git a/src/config/index.ts b/src/config/index.ts index ba47c42..d9e5d1e 100644 --- a/src/config/index.ts +++ b/src/config/index.ts @@ -5,7 +5,7 @@ export const URL_OAUTH_TOKEN = 'https://oauth2.googleapis.com/token'; /** Google People API endpoints */ const URL_PEOPLE_BASE = 'https://people.googleapis.com/v1'; export const URL_PEOPLE_CONNECTIONS = `${URL_PEOPLE_BASE}/people/me/connections`; -export const PERSONAL_FIELDS = `names,emailAddresses,phoneNumbers,birthdays,memberships,metadata,addresses,biographies,organizations`; +export const PERSONAL_FIELDS = `names,emailAddresses,phoneNumbers,birthdays,memberships,metadata,addresses,biographies,organizations,relations`; export const OTHER_CONTACTS_FIELDS = `names,emailAddresses,phoneNumbers`; export const URL_CONTACT_GROUPS = `${URL_PEOPLE_BASE}/contactGroups?pageSize=1000`; @@ -38,6 +38,7 @@ export const DEFAULT_SETTINGS: ContactSyncSettings = { syncOnStartup: false, trackSyncTime: false, organizationAsLink: false, + relationsAsLink: true, renameFiles: false, namingStrategy: NamingStrategy.Default, lastFirst: false, diff --git a/src/core/Formatter.ts b/src/core/Formatter.ts index e43a758..bfecccd 100644 --- a/src/core/Formatter.ts +++ b/src/core/Formatter.ts @@ -12,6 +12,7 @@ import { JobTitleAdapter } from './adapters/JobTitleAdapter'; import { DepartmentAdapter } from './adapters/DepartmentAdapter'; import { BirthdayAdapter } from './adapters/BirthdayAdapter'; import { LabelAdapter } from './adapters/LabelAdapter'; +import { RelationsAdapter } from './adapters/RelationsAdapter'; /** * Formatter class responsible for coordinating field extraction and key generation. @@ -99,6 +100,7 @@ export function createDefaultFormatter( jobtitle: new JobTitleAdapter(), department: new DepartmentAdapter(), labels: new LabelAdapter(), + relations: new RelationsAdapter(), }; if (strategyType === NamingStrategy.VCF) { diff --git a/src/core/adapters/RelationsAdapter.ts b/src/core/adapters/RelationsAdapter.ts new file mode 100644 index 0000000..04ddc2d --- /dev/null +++ b/src/core/adapters/RelationsAdapter.ts @@ -0,0 +1,19 @@ +import { FieldAdapter, ExtractionResult } from '../interfaces'; +import { GoogleContact } from '../../types/Contact'; +import { NamingStrategy } from 'src/types/Settings'; + +export class RelationsAdapter implements FieldAdapter { + extract( + contact: GoogleContact, + context?: Record + ): ExtractionResult[] { + const relationsAsLink = context?.relationsAsLink as boolean; + const isVcfStrategy = context?.namingStrategy === NamingStrategy.VCF; + return (contact.relations ?? []) + .filter((relation) => !!relation.person) + .map((relation) => ({ + // For VCF strategy, don't use wiki links even if organizationsAsLink is true + value: relationsAsLink && !isVcfStrategy ? `[[${relation.person}|${relation.person} (${relation.type})]]` : `${relation.person} (${relation.type})`, + })); + } +} \ No newline at end of file diff --git a/src/core/strategies/VcfNamingStrategy.ts b/src/core/strategies/VcfNamingStrategy.ts index 8d54642..984c9ee 100644 --- a/src/core/strategies/VcfNamingStrategy.ts +++ b/src/core/strategies/VcfNamingStrategy.ts @@ -6,6 +6,7 @@ export class VcfNamingStrategy implements KeyNamingStrategy { phone: 'TEL', address: 'ADR', organization: 'ORG', + relations: 'X-RELATION', jobtitle: 'TITLE', bio: 'NOTE', birthday: 'BDAY', diff --git a/src/main.ts b/src/main.ts index a5b2459..edbe1c3 100644 --- a/src/main.ts +++ b/src/main.ts @@ -209,6 +209,7 @@ export default class GoogleContactsSyncPlugin extends Plugin { syncLabel: this.settings.syncLabel, noteBody: this.settings.noteTemplate || '# Notes\n', organizationAsLink: this.settings.organizationAsLink, + relationsAsLink: this.settings.relationsAsLink, trackSyncTime: this.settings.trackSyncTime, renameFiles: this.settings.renameFiles, namingStrategy: this.settings.namingStrategy, diff --git a/src/plugin/settings.ts b/src/plugin/settings.ts index a87ffd3..411c3e9 100644 --- a/src/plugin/settings.ts +++ b/src/plugin/settings.ts @@ -147,6 +147,22 @@ export class ContactSyncSettingTab extends PluginSettingTab { }) ); + new Setting(containerEl) + .setName(t('Relations as links')) + .setDesc( + t( + 'Related people names will be stored as a obsidian link [[...]] instead of plain text' + ) + ) + .addToggle((toggle) => + toggle + .setValue(this.plugin.settings.relationsAsLink) + .onChange(async (value) => { + this.plugin.settings.relationsAsLink = value; + await this.plugin.saveSettings(); + }) + ); + new Setting(containerEl) .setName(t('Label to sync')) .setDesc( diff --git a/src/services/ContactNoteWriter.ts b/src/services/ContactNoteWriter.ts index 15ae806..6a24b0f 100644 --- a/src/services/ContactNoteWriter.ts +++ b/src/services/ContactNoteWriter.ts @@ -146,6 +146,7 @@ export class ContactNoteWriter { invertedLabelMap, config.namingStrategy, config.organizationAsLink, + config.relationsAsLink, config.trackSyncTime ) ) @@ -266,6 +267,7 @@ export class ContactNoteWriter { invertedLabelMap: Record, namingStrategy: NamingStrategy, organizationAsLink = false, + relationsAsLink = false, trackSyncTime = false ): Record { const formatter = createDefaultFormatter(namingStrategy); @@ -275,6 +277,7 @@ export class ContactNoteWriter { { labelMap: invertedLabelMap, organizationAsLink: organizationAsLink, + relationsAsLink: relationsAsLink, namingStrategy: namingStrategy, } ); diff --git a/src/types/Contact.ts b/src/types/Contact.ts index 687e9be..fd1c7a4 100644 --- a/src/types/Contact.ts +++ b/src/types/Contact.ts @@ -56,6 +56,12 @@ export interface GoogleContact { title: string; department: string; }[]; + + relations?: { + person: string; + type: string; + metadata: string; + }[]; } /** diff --git a/src/types/ContactNoteConfig.ts b/src/types/ContactNoteConfig.ts index c7fe059..05d2465 100644 --- a/src/types/ContactNoteConfig.ts +++ b/src/types/ContactNoteConfig.ts @@ -7,6 +7,7 @@ export interface ContactNoteConfig { syncLabel: string; noteBody: string; organizationAsLink: boolean; + relationsAsLink: boolean; trackSyncTime: boolean; renameFiles: boolean; namingStrategy: NamingStrategy; diff --git a/src/types/Settings.ts b/src/types/Settings.ts index 7beced2..ba7a685 100644 --- a/src/types/Settings.ts +++ b/src/types/Settings.ts @@ -47,6 +47,9 @@ export interface ContactSyncSettings { /** Save organization as obsidian link */ organizationAsLink: boolean; + /** Save relationships as links */ + relationsAsLink: boolean; + /** Whether to rename existing contact files in case if name has been changed based on current naming settings */ renameFiles: boolean; diff --git a/tsconfig.json b/tsconfig.json index 9047dee..05cb462 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,8 +1,8 @@ { "compilerOptions": { - "target": "es2017", + "target": "es2021", "lib": [ - "es2017", + "es2021", "dom" ], "module": "esnext",