From 2a58dd3258dbdc3198ae26a84c853f982df7ca45 Mon Sep 17 00:00:00 2001 From: Jiaxin Peng Date: Sun, 28 Jan 2024 00:11:11 +0000 Subject: [PATCH 1/6] complete the custom ui design --- .github/workflows/release.yml | 14 +- README.md | 1 + src/ui/CustomModal.ts | 134 ++++++++++++++ src/ui/EditModal.ts | 90 ++++------ src/ui/PreviewModal.ts | 14 ++ src/ui/settingModal.ts | 164 ++++++++---------- src/ui/settingTabs.ts | 4 + src/upload/uploadCommand.ts | 4 +- .../upoload_custom/Upload2NotionCustom.ts | 9 +- .../upoload_custom/getMarkdownCustom.ts | 22 +-- 10 files changed, 289 insertions(+), 167 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ee27e04..551540f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -20,13 +20,13 @@ jobs: with: node-version: "18" -# - name: Generate changelog -# id: changelog -# uses: release-changelog/action@v1.0.0 -# with: -# repo-token: ${{ secrets.REPO_ACCESS_TOKEN }} -# version: ${{ github.ref }} -# file: CHANGELOG.md + - name: Generate changelog + id: changelog + uses: saadmk11/changelog-ci@v1.1.2 + with: + github_token: ${{ secrets.REPO_ACCESS_TOKEN }} + release_version: ${{ github.ref }} + changelog_filename: CHANGELOG.md - name: Build id: build diff --git a/README.md b/README.md index 6d51dc4..99a7195 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,7 @@ Thus, based on the [original author's work](https://github.com/EasyChris/obsidia ## TODO List - [ ] Support custom properties for Notion General database. 支持自定义属性 +- [ ] Support group upload with one click 支持一键多数据库上传 - [x] Support preview for database details in plugin settings. 支持预览数据库详情 - [x] Support edit for database details in plugin settings. 支持编辑数据库详情 diff --git a/src/ui/CustomModal.ts b/src/ui/CustomModal.ts index e69de29..844034b 100644 --- a/src/ui/CustomModal.ts +++ b/src/ui/CustomModal.ts @@ -0,0 +1,134 @@ +import {App, Modal, Setting} from "obsidian"; +import ObsidianSyncNotionPlugin from "../main"; +import {ObsidianSettingTab} from "./settingTabs"; + +export class CustomModal extends Modal { + propertyLines: Setting[] = []; // Store all property line settings + properties: { customValue: string, customType: string }[] = []; // Array to store property values and types + plugin: ObsidianSyncNotionPlugin; + settingTab: ObsidianSettingTab; + + constructor(app: App) { + super(app); + } + + createPropertyLine(containerEl: HTMLElement): void { + const propertyIndex = this.properties.length; + this.properties.push({customValue: "", customType: ""}); // Initialize with empty values + + const propertyLine = new Setting(containerEl) + + propertyLine + .setName("Property " + (propertyIndex + 1)) + + propertyLine.addText((text) => { + text + .setPlaceholder("Property name") + .setValue("") + .onChange(async (value) => { + this.properties[propertyIndex].customValue = value; // Update the customValue of the specific property + }); + } + ) + + propertyLine.addDropdown((dropdown) => { + dropdown + .addOption("text", "Text") + .addOption("number", "Number") + .addOption("select", "Select") + .addOption("multi_select", "Multi-Select") + .addOption("date", "Date") + .addOption("person", "Person") + .addOption("file", "Files & Media") + .addOption("checkbox", "Checkbox") + .addOption("url", "URL") + .addOption("email", "Email") + .addOption("phone_number", "Phone Number") + .addOption("formula", "Formula") + .addOption("relation", "Relation") + .addOption("rollup", "Rollup") + .addOption("created_time", "Created time") + .addOption("created_by", "Created by") + .addOption("last_edited_time", "Last Edited Time") + .addOption("last_edited_by", "Last Edited By") + .setValue("text") + .onChange(async (value) => { + this.properties[propertyIndex].customType = value; // Update the customType of the specific property + }); + } + ) + + propertyLine.addButton((button) => { + return button + .setTooltip("Delete") + .setIcon("trash") + .onClick(async () => { + // Handle the deletion of this property line + this.propertyLines = this.propertyLines.filter(line => line !== propertyLine); + this.properties.splice(propertyIndex, 1); // Remove the property from the array + propertyLine.settingEl.remove(); + }); + } + ); + + this.propertyLines.push(propertyLine); + } + + + display(): void { + + this.containerEl.addClass("custom-modal"); + this.titleEl.setText("Add Custom Property"); + + let {contentEl} = this; + contentEl.empty(); + + const customDiv = contentEl.createDiv("custom-div"); + + new Setting(customDiv) + .setName("Add new property") + .setDesc("Add new property match with your notion database") + .addButton((button) => { + return button + .setTooltip("Add") + .setIcon("plus") + .onClick(async () => { + const customTabs = customDiv.createDiv("custom-tabs"); + this.createPropertyLine(customTabs); + }); + }); + + + let footerEl = this.contentEl.createDiv("save-custom-value"); + let saveButton = new Setting(footerEl) + saveButton.addButton((button) => { + return button + .setTooltip("Save") + .setIcon("checkmark") + .onClick(async () => { + this.close(); + }); + } + ); + + saveButton.addExtraButton((button) => { + return button + .setTooltip("Cancel") + .setIcon("cross") + .onClick(async () => { + this.close(); + }); + } + ); + } + + onOpen(): void { + this.display(); + } + + onClose(): void { + const {contentEl} = this; + + contentEl.empty(); + } +} diff --git a/src/ui/EditModal.ts b/src/ui/EditModal.ts index 35c3f1f..030234d 100644 --- a/src/ui/EditModal.ts +++ b/src/ui/EditModal.ts @@ -3,6 +3,7 @@ import {SettingModal} from "./settingModal"; import ObsidianSyncNotionPlugin from "../main"; import {DatabaseDetails, ObsidianSettingTab} from "./settingTabs"; import {i18nConfig} from "../lang/I18n"; +import {CustomModal} from "./CustomModal"; export class EditModal extends SettingModal { dataTemp: Record = { @@ -21,6 +22,7 @@ export class EditModal extends SettingModal { customTitleButtonTemp: false, // customTitleButtonTempInd: false, customTitleNameTemp: '', + customPropertiesTemp: [], // customTitleNameTempInd: false, // customValues: '', savedTemp: false, @@ -42,6 +44,7 @@ export class EditModal extends SettingModal { customTitleButtonPrev: false, // customTitleButtonPrevInd: false, customTitleNamePrev: '', + customPropertiesPrev: [], // customTitleNamePrevInd: false, // customValues: '', savedPrev: false, @@ -67,6 +70,7 @@ export class EditModal extends SettingModal { this.dataTemp.tagButtonTemp = dbDetails.tagButton; this.dataTemp.customTitleButtonTemp = dbDetails.customTitleButton; this.dataTemp.customTitleNameTemp = dbDetails.customTitleName; + this.dataTemp.customPropertiesTemp = dbDetails.customProperties; // this.dataTemp.customValues = dbDetails.customValues; this.dataTemp.savedTemp = dbDetails.saved; @@ -79,6 +83,7 @@ export class EditModal extends SettingModal { this.dataPrev.tagButtonPrev = dbDetails.tagButton; this.dataPrev.customTitleButtonPrev = dbDetails.customTitleButton; this.dataPrev.customTitleNamePrev = dbDetails.customTitleName; + this.dataPrev.customPropertiesPrev = dbDetails.customProperties; // this.dataTemp.customValues = dbDetails.customValues; this.dataPrev.savedPrev = dbDetails.saved; } @@ -103,7 +108,7 @@ export class EditModal extends SettingModal { .addOption('none', '') .addOption('general', i18nConfig.databaseGeneral) .addOption('next', i18nConfig.databaseNext) - // .addOption('custom', i18nConfig.databaseCustom) + .addOption('custom', i18nConfig.databaseCustom) .setValue(this.dataTemp.databaseFormatTemp) .onChange(async (value) => { this.dataTemp.databaseFormatTemp = value; @@ -211,70 +216,49 @@ export class EditModal extends SettingModal { // add api key this.createSettingEl(nextTabs, i18nConfig.NotionAPI, i18nConfig.NotionAPIDesc, 'password', i18nConfig.NotionAPIText, this.dataTemp.notionAPITemp, 'dataTemp','notionAPITemp') - // add database id this.createSettingEl(nextTabs, i18nConfig.DatabaseID, i18nConfig.NotionAPIDesc, 'password', i18nConfig.DatabaseIDText, this.dataTemp.databaseIDTemp, 'dataTemp','databaseIDTemp') } else if (value === 'custom') { - nextTabs.createEl('h3', { text: i18nConfig.NotionCustomSettingHeader}); + + nextTabs.createEl('h3', {text: i18nConfig.NotionCustomSettingHeader}); // add full name - this.createSettingEl(nextTabs, i18nConfig.databaseFullName, i18nConfig.databaseFullNameDesc, 'text', i18nConfig.databaseFullNameText, this.dataTemp.databaseFullNameTemp,'dataTemp', 'databaseFullNameTemp') + this.createSettingEl(nextTabs, i18nConfig.databaseFullName, i18nConfig.databaseFullNameDesc, 'text', i18nConfig.databaseFullNameText, this.dataTemp.databaseFullNameTemp, 'dataTemp', 'databaseFullNameTemp') // add abbreviate name - this.createSettingEl(nextTabs, i18nConfig.databaseAbbreviateName, i18nConfig.databaseAbbreviateNameDesc, 'text', i18nConfig.databaseAbbreviateNameText, this.dataTemp.databaseAbbreviateNameTemp, 'dataTemp','databaseAbbreviateNameTemp') - - // tag button - this.createSettingEl(nextTabs, i18nConfig.NotionTagButton, i18nConfig.NotionTagButtonDesc, 'toggle', i18nConfig.NotionCustomTitleText, this.dataTemp.tagButtonTemp, 'dataTemp','tagButtonTemp') - - // add custom title button - - new Setting(nextTabs) - .setName(i18nConfig.NotionCustomTitle) - .setDesc(i18nConfig.NotionCustomTitleDesc) - .addToggle((toggle) => - toggle - .setValue(this.dataTemp.CustomTitleButtonTemp) - .onChange(async (value) => { - this.dataTemp.CustomTitleButtonTemp = value; - - this.updateSettingEl(CustomNameEl, value) - - // this.updateSettingEl(CustomValuesEl, value) - - // await this.plugin.saveSettings(); - // await this.plugin.commands.updateCommand(); - }) - ); - - - // add custom title name - const CustomNameEl = this.createStyleDiv('custom-name', (this.dataTemp.CustomTitleButtonTemp), nextTabs); - this.createSettingEl(CustomNameEl, i18nConfig.NotionCustomTitleName, i18nConfig.NotionCustomTitleNameDesc, 'text', i18nConfig.NotionCustomTitleText, this.dataTemp.CustomTitleNameTemp,'dataTemp', 'CustomTitleNameTemp') - - // // add custom values - // const CustomValuesEl = this.createStyleDiv('custom-values', (this.dataTemp.CustomTitleButton), nextTabs); - // new Setting(CustomValuesEl) - // .setName(i18nConfig.NotionCustomValues) - // .setDesc(i18nConfig.NotionCustomValuesDesc) - // .addTextArea((text) => { - // return text - // .setPlaceholder(i18nConfig.NotionCustomValuesText) - // .setValue(this.dataTemp.CustomValues) - // .onChange(async (value) => { - // this.dataTemp.CustomValues = value; - // await this.plugin.saveSettings(); - // }); - // }); - + this.createSettingEl(nextTabs, i18nConfig.databaseAbbreviateName, i18nConfig.databaseAbbreviateNameDesc, 'text', i18nConfig.databaseAbbreviateNameText, this.dataTemp.databaseAbbreviateNameTemp, 'dataTemp', 'databaseAbbreviateNameTemp') // add api key - const notionAPIGeneralEl = this.createStyleDiv('api-general', this.plugin.settings.GeneralButton, nextTabs); - this.createSettingEl(notionAPIGeneralEl, i18nConfig.NotionAPI, i18nConfig.NotionAPIDesc, 'password', i18nConfig.NotionAPIText, this.dataTemp.notionAPITemp, 'dataTemp','notionAPITemp') + this.createSettingEl(nextTabs, i18nConfig.NotionAPI, i18nConfig.NotionAPIDesc, 'password', i18nConfig.NotionAPIText, this.dataTemp.notionAPITemp, 'dataTemp', 'notionAPITemp') // add database id - const databaseIDGeneralEl = this.createStyleDiv('databaseID-general', this.plugin.settings.GeneralButton, nextTabs); - this.createSettingEl(databaseIDGeneralEl, i18nConfig.DatabaseID, i18nConfig.NotionAPIDesc, 'password', i18nConfig.DatabaseIDText, this.dataTemp.databaseIDTemp, 'dataTemp', 'databaseIDTemp') + this.createSettingEl(nextTabs, i18nConfig.DatabaseID, i18nConfig.NotionAPIDesc, 'password', i18nConfig.DatabaseIDText, this.dataTemp.databaseIDTemp, 'dataTemp', 'databaseIDTemp') + + // add custom title name + this.createSettingEl(nextTabs, i18nConfig.NotionCustomTitleName, i18nConfig.NotionCustomTitleNameDesc, 'text', i18nConfig.NotionCustomTitleText, this.dataTemp.CustomTitleNameTemp, 'dataTemp', 'CustomTitleNameTemp') + + // add new property button + new Setting(nextTabs) + .setName(i18nConfig.NotionCustomValues) + .setDesc(i18nConfig.NotionCustomValuesDesc) + .addButton((button: ButtonComponent) => { + return button + .setTooltip('Add new property') + .setIcon('plus') + .onClick(async () => { + let customModal = new CustomModal(this.app); + + customModal.onClose = () => { + + this.renderCustomPreview(customModal.properties, nextTabs) + this.dataTemp.customPropertiesTemp = customModal.properties; + } + + customModal.open(); + }); + } + ); } } diff --git a/src/ui/PreviewModal.ts b/src/ui/PreviewModal.ts index ae428a5..adec2bc 100644 --- a/src/ui/PreviewModal.ts +++ b/src/ui/PreviewModal.ts @@ -116,10 +116,24 @@ export class PreviewModal extends Modal { dbIdSetting.settingEl.style.display = 'none'; // Hide initially + // Preview the custom properties + + if (this.dbDetails.format === 'custom') { + + const customPropertiesEl = new Setting(previewEl) + customPropertiesEl + .setName('Custom Properties') + .addTextArea(text => text + .setValue(JSON.stringify(this.dbDetails.customProperties, null, 2)) + .setDisabled(true)); + } + } onOpen() { this.display() } + + } diff --git a/src/ui/settingModal.ts b/src/ui/settingModal.ts index a3889fd..462e669 100644 --- a/src/ui/settingModal.ts +++ b/src/ui/settingModal.ts @@ -5,9 +5,10 @@ import { ButtonComponent, App } from 'obsidian'; -import { i18nConfig } from "../lang/I18n"; +import {i18nConfig} from "../lang/I18n"; import ObsidianSyncNotionPlugin from "../main"; import {DatabaseDetails, ObsidianSettingTab} from "./settingTabs"; +import {CustomModal} from "./CustomModal"; export class SettingModal extends Modal { @@ -21,6 +22,7 @@ export class SettingModal extends Modal { tagButton: true, customTitleButton: false, customTitleName: '', + customProperties: [], // customValues: '', saved: false, }; @@ -31,6 +33,7 @@ export class SettingModal extends Modal { super(app); this.plugin = plugin; this.settingTab = settingTab; + this.properties = []; if (dbDetails) { this.data.databaseFormat = dbDetails.format; this.data.databaseFullName = dbDetails.fullName; @@ -40,6 +43,7 @@ export class SettingModal extends Modal { this.data.tagButton = dbDetails.tagButton; this.data.customTitleButton = dbDetails.customTitleButton; this.data.customTitleName = dbDetails.customTitleName; + this.data.customProperties = dbDetails.customProperties; // this.data.customValues = dbDetails.customValues; this.data.saved = dbDetails.saved; } @@ -51,14 +55,13 @@ export class SettingModal extends Modal { this.titleEl.setText('Add new database'); // create the dropdown button to select the database format - let { contentEl } = this; + let {contentEl} = this; contentEl.empty(); const settingDiv = contentEl.createDiv('setting-div'); const nextTabs = contentEl.createDiv('next-tabs'); - if (this.data.saved) { new Setting(settingDiv) .setName(i18nConfig.databaseFormat) @@ -68,7 +71,7 @@ export class SettingModal extends Modal { .addOption('none', '') .addOption('general', i18nConfig.databaseGeneral) .addOption('next', i18nConfig.databaseNext) - // .addOption('custom', i18nConfig.databaseCustom) + .addOption('custom', i18nConfig.databaseCustom) .setValue(this.data.databaseFormat) .onChange(async (value) => { this.data.databaseFormat = value; @@ -89,7 +92,7 @@ export class SettingModal extends Modal { .addOption('none', '') .addOption('general', i18nConfig.databaseGeneral) .addOption('next', i18nConfig.databaseNext) - // .addOption('custom', i18nConfig.databaseCustom) + .addOption('custom', i18nConfig.databaseCustom) .setValue(this.data.databaseFormat) .onChange(async (value) => { this.data.databaseFormat = value; @@ -103,29 +106,28 @@ export class SettingModal extends Modal { } - // add save button let footerEl = contentEl.createDiv('save-button'); let saveButton = new Setting(footerEl) saveButton.addButton((button: ButtonComponent) => { - return button - .setTooltip('Save') - .setIcon('checkmark') - .onClick(async () => { - this.data.saved = true; - this.close(); - }); - } + return button + .setTooltip('Save') + .setIcon('checkmark') + .onClick(async () => { + this.data.saved = true; + this.close(); + }); + } ); saveButton.addExtraButton((button) => { - return button - .setTooltip('Cancel') - .setIcon('cross') - .onClick(() => { - this.data.saved = false; - this.close(); - }); - } + return button + .setTooltip('Cancel') + .setIcon('cross') + .onClick(() => { + this.data.saved = false; + this.close(); + }); + } ); } @@ -135,16 +137,16 @@ export class SettingModal extends Modal { // Generate content based on the selected value if (value === 'general') { - nextTabs.createEl('h3', { text: i18nConfig.NotionGeneralSettingHeader }); + nextTabs.createEl('h3', {text: i18nConfig.NotionGeneralSettingHeader}); // add full name - this.createSettingEl(nextTabs, i18nConfig.databaseFullName, i18nConfig.databaseFullNameDesc, 'text', i18nConfig.databaseFullNameText, this.data.databaseFullName, 'data','databaseFullName') + this.createSettingEl(nextTabs, i18nConfig.databaseFullName, i18nConfig.databaseFullNameDesc, 'text', i18nConfig.databaseFullNameText, this.data.databaseFullName, 'data', 'databaseFullName') // add abbreviate name - this.createSettingEl(nextTabs, i18nConfig.databaseAbbreviateName, i18nConfig.databaseAbbreviateNameDesc, 'text', i18nConfig.databaseAbbreviateNameText, this.data.databaseAbbreviateName, 'data','databaseAbbreviateName') + this.createSettingEl(nextTabs, i18nConfig.databaseAbbreviateName, i18nConfig.databaseAbbreviateNameDesc, 'text', i18nConfig.databaseAbbreviateNameText, this.data.databaseAbbreviateName, 'data', 'databaseAbbreviateName') // tag button - this.createSettingEl(nextTabs, i18nConfig.NotionTagButton, i18nConfig.NotionTagButtonDesc, 'toggle', i18nConfig.NotionCustomTitleText, this.data.tagButton, 'data','tagButton') + this.createSettingEl(nextTabs, i18nConfig.NotionTagButton, i18nConfig.NotionTagButtonDesc, 'toggle', i18nConfig.NotionCustomTitleText, this.data.tagButton, 'data', 'tagButton') // add custom title button @@ -169,112 +171,100 @@ export class SettingModal extends Modal { // add custom title name const CustomNameEl = this.createStyleDiv('custom-name', (this.data.CustomTitleButton), nextTabs); - this.createSettingEl(CustomNameEl, i18nConfig.NotionCustomTitleName, i18nConfig.NotionCustomTitleNameDesc, 'text', i18nConfig.NotionCustomTitleText, this.data.CustomTitleName, 'data','CustomTitleName') + this.createSettingEl(CustomNameEl, i18nConfig.NotionCustomTitleName, i18nConfig.NotionCustomTitleNameDesc, 'text', i18nConfig.NotionCustomTitleText, this.data.CustomTitleName, 'data', 'CustomTitleName') // add api key - this.createSettingEl(nextTabs, i18nConfig.NotionAPI, i18nConfig.NotionAPIDesc, 'password', i18nConfig.NotionAPIText, this.data.notionAPI, 'data','notionAPI') + this.createSettingEl(nextTabs, i18nConfig.NotionAPI, i18nConfig.NotionAPIDesc, 'password', i18nConfig.NotionAPIText, this.data.notionAPI, 'data', 'notionAPI') // add database id - this.createSettingEl(nextTabs, i18nConfig.DatabaseID, i18nConfig.NotionAPIDesc, 'password', i18nConfig.DatabaseIDText, this.data.databaseID, 'data','databaseID') + this.createSettingEl(nextTabs, i18nConfig.DatabaseID, i18nConfig.NotionAPIDesc, 'password', i18nConfig.DatabaseIDText, this.data.databaseID, 'data', 'databaseID') } else if (value === 'next') { - nextTabs.createEl('h3', { text: i18nConfig.NotionNextSettingHeader }); + nextTabs.createEl('h3', {text: i18nConfig.NotionNextSettingHeader}); // add full name - this.createSettingEl(nextTabs, i18nConfig.databaseFullName, i18nConfig.databaseFullNameDesc, 'text', i18nConfig.databaseFullNameText, this.data.databaseFullName,'data','databaseFullName') + this.createSettingEl(nextTabs, i18nConfig.databaseFullName, i18nConfig.databaseFullNameDesc, 'text', i18nConfig.databaseFullNameText, this.data.databaseFullName, 'data', 'databaseFullName') // add abbreviate name - this.createSettingEl(nextTabs, i18nConfig.databaseAbbreviateName, i18nConfig.databaseAbbreviateNameDesc, 'text', i18nConfig.databaseAbbreviateNameText, this.data.databaseAbbreviateName, 'data','databaseAbbreviateName') + this.createSettingEl(nextTabs, i18nConfig.databaseAbbreviateName, i18nConfig.databaseAbbreviateNameDesc, 'text', i18nConfig.databaseAbbreviateNameText, this.data.databaseAbbreviateName, 'data', 'databaseAbbreviateName') // add api key - this.createSettingEl(nextTabs, i18nConfig.NotionAPI, i18nConfig.NotionAPIDesc, 'password', i18nConfig.NotionAPIText, this.data.notionAPI, 'data','notionAPI') + this.createSettingEl(nextTabs, i18nConfig.NotionAPI, i18nConfig.NotionAPIDesc, 'password', i18nConfig.NotionAPIText, this.data.notionAPI, 'data', 'notionAPI') // add database id - this.createSettingEl(nextTabs, i18nConfig.DatabaseID, i18nConfig.NotionAPIDesc, 'password', i18nConfig.DatabaseIDText, this.data.databaseID, 'data','databaseID') + this.createSettingEl(nextTabs, i18nConfig.DatabaseID, i18nConfig.NotionAPIDesc, 'password', i18nConfig.DatabaseIDText, this.data.databaseID, 'data', 'databaseID') } else if (value === 'custom') { - nextTabs.createEl('h3', { text: i18nConfig.NotionCustomSettingHeader}); + nextTabs.createEl('h3', {text: i18nConfig.NotionCustomSettingHeader}); // add full name - this.createSettingEl(nextTabs, i18nConfig.databaseFullName, i18nConfig.databaseFullNameDesc, 'text', i18nConfig.databaseFullNameText, this.data.databaseFullName, 'data','databaseFullName') + this.createSettingEl(nextTabs, i18nConfig.databaseFullName, i18nConfig.databaseFullNameDesc, 'text', i18nConfig.databaseFullNameText, this.data.databaseFullName, 'data', 'databaseFullName') // add abbreviate name - this.createSettingEl(nextTabs, i18nConfig.databaseAbbreviateName, i18nConfig.databaseAbbreviateNameDesc, 'text', i18nConfig.databaseAbbreviateNameText, this.data.databaseAbbreviateName, 'data','databaseAbbreviateName') - - // tag button - this.createSettingEl(nextTabs, i18nConfig.NotionTagButton, i18nConfig.NotionTagButtonDesc, 'toggle', i18nConfig.NotionCustomTitleText, this.data.tagButton,'data', 'tagButton') - - // add custom title button - - new Setting(nextTabs) - .setName(i18nConfig.NotionCustomTitle) - .setDesc(i18nConfig.NotionCustomTitleDesc) - .addToggle((toggle) => - toggle - .setValue(this.data.CustomTitleButton) - .onChange(async (value) => { - this.data.CustomTitleButton = value; - - this.updateSettingEl(CustomNameEl, value) - - // this.updateSettingEl(CustomValuesEl, value) - - // await this.plugin.saveSettings(); - // await this.plugin.commands.updateCommand(); - }) - ); - - - // add custom title name - const CustomNameEl = this.createStyleDiv('custom-name', (this.data.CustomTitleButton), nextTabs); - this.createSettingEl(CustomNameEl, i18nConfig.NotionCustomTitleName, i18nConfig.NotionCustomTitleNameDesc, 'text', i18nConfig.NotionCustomTitleText, this.data.CustomTitleName,'data', 'CustomTitleName') - - // // add custom values - // const CustomValuesEl = this.createStyleDiv('custom-values', (this.data.CustomTitleButton), nextTabs); - // new Setting(CustomValuesEl) - // .setName(i18nConfig.NotionCustomValues) - // .setDesc(i18nConfig.NotionCustomValuesDesc) - // .addTextArea((text) => { - // return text - // .setPlaceholder(i18nConfig.NotionCustomValuesText) - // .setValue(this.data.CustomValues) - // .onChange(async (value) => { - // this.data.CustomValues = value; - // await this.plugin.saveSettings(); - // }); - // }); - + this.createSettingEl(nextTabs, i18nConfig.databaseAbbreviateName, i18nConfig.databaseAbbreviateNameDesc, 'text', i18nConfig.databaseAbbreviateNameText, this.data.databaseAbbreviateName, 'data', 'databaseAbbreviateName') // add api key - const notionAPIGeneralEl = this.createStyleDiv('api-general', this.plugin.settings.GeneralButton, nextTabs); - this.createSettingEl(notionAPIGeneralEl, i18nConfig.NotionAPI, i18nConfig.NotionAPIDesc, 'password', i18nConfig.NotionAPIText, this.data.notionAPI,'data', 'notionAPI') + this.createSettingEl(nextTabs, i18nConfig.NotionAPI, i18nConfig.NotionAPIDesc, 'password', i18nConfig.NotionAPIText, this.data.notionAPI, 'data', 'notionAPI') // add database id - const databaseIDGeneralEl = this.createStyleDiv('databaseID-general', this.plugin.settings.GeneralButton, nextTabs); - this.createSettingEl(databaseIDGeneralEl, i18nConfig.DatabaseID, i18nConfig.NotionAPIDesc, 'password', i18nConfig.DatabaseIDText, this.data.databaseID, 'data', 'databaseID') + this.createSettingEl(nextTabs, i18nConfig.DatabaseID, i18nConfig.NotionAPIDesc, 'password', i18nConfig.DatabaseIDText, this.data.databaseID, 'data', 'databaseID') + + // add custom title name + this.createSettingEl(nextTabs, i18nConfig.NotionCustomTitleName, i18nConfig.NotionCustomTitleNameDesc, 'text', i18nConfig.NotionCustomTitleText, this.data.CustomTitleName, 'data', 'CustomTitleName') + + // add new property button + new Setting(nextTabs) + .setName(i18nConfig.NotionCustomValues) + .setDesc(i18nConfig.NotionCustomValuesDesc) + .addButton((button: ButtonComponent) => { + return button + .setTooltip('Add new property') + .setIcon('plus') + .onClick(async () => { + let customModal = new CustomModal(this.app); + + customModal.onClose = () => { + + this.renderCustomPreview(customModal.properties, nextTabs) + this.data.customProperties = customModal.properties; + } + + customModal.open(); + }); + } + ); } } - onOpen() { // add console log to check if the modal is opened this.display() } + renderCustomPreview(properties: any[], nextTabs: HTMLElement) { + const previewContainer = nextTabs.createDiv('preview-container'); + + properties.forEach((property: { customValue: any; customType: any; }) => { + const propertyEl = previewContainer.createEl('div', {cls: 'property-preview'}); + propertyEl.createEl('span', {text: `Property: ${property.customValue}, Type: ${property.customType}`}); + }); + + } // create a function to create a div with a style for pop over elements - public createStyleDiv(className: string, commandValue: boolean = false,parentEl: HTMLElement ) { + public createStyleDiv(className: string, commandValue: boolean = false, parentEl: HTMLElement) { return parentEl.createDiv(className, (div) => { this.updateSettingEl(div, commandValue); }); } + // update the setting display style in the setting tab public updateSettingEl(element: HTMLElement, commandValue: boolean) { element.style.borderTop = commandValue ? "1px solid var(--background-modifier-border)" : "none"; diff --git a/src/ui/settingTabs.ts b/src/ui/settingTabs.ts index 5c724b9..72b1049 100644 --- a/src/ui/settingTabs.ts +++ b/src/ui/settingTabs.ts @@ -37,6 +37,7 @@ export interface DatabaseDetails { tagButton: boolean; customTitleButton: boolean; customTitleName: string; + customProperties:{ customValue: string, customType: string }[]; // customValues: string; saved: boolean; } @@ -107,6 +108,7 @@ export class ObsidianSettingTab extends PluginSettingTab { tagButton: modal.data.tagButton, customTitleButton: modal.data.customTitleButton, customTitleName: modal.data.customTitleName, + customProperties: modal.data.customProperties, // customValues: modal.data.customValues, saved: modal.data.saved, } @@ -271,6 +273,7 @@ export class ObsidianSettingTab extends PluginSettingTab { tagButton: modal.dataTemp.tagButtonTemp, customTitleButton: modal.dataTemp.customTitleButtonTemp, customTitleName: modal.dataTemp.customTitleNameTemp, + customProperties: modal.dataTemp.customPropertiesTemp, // customValues: modal.data.customValues, saved: modal.dataTemp.savedTemp, } @@ -284,6 +287,7 @@ export class ObsidianSettingTab extends PluginSettingTab { tagButton: modal.dataPrev.tagButtonPrev, customTitleButton: modal.dataPrev.customTitleButtonPrev, customTitleName: modal.dataPrev.customTitleNamePrev, + customProperties: modal.dataPrev.customPropertiesPrev, // customValues: modal.data.customValues, saved: modal.dataPrev.savedPrev, } diff --git a/src/upload/uploadCommand.ts b/src/upload/uploadCommand.ts index 55c951e..fce960b 100644 --- a/src/upload/uploadCommand.ts +++ b/src/upload/uploadCommand.ts @@ -100,13 +100,13 @@ export async function uploadCommandCustom( return; } - const { markDownData, nowFile, cover, tags ,customValues} = await getNowFileMarkdownContentCustom(app, settings) + const { markDownData, nowFile, cover, customValues} = await getNowFileMarkdownContentCustom(app, dbDetails, settings) if (markDownData) { const { basename } = nowFile; const upload = new Upload2NotionCustom(plugin,dbDetails); - const res = await upload.syncMarkdownToNotionCustom(basename, cover, tags, customValues, markDownData, nowFile, this.app); + const res = await upload.syncMarkdownToNotionCustom(basename, cover, customValues, markDownData, nowFile, this.app); if (res.status === 200) { new Notice(`${i18nConfig["sync-success"]}${basename}`); diff --git a/src/upload/upoload_custom/Upload2NotionCustom.ts b/src/upload/upoload_custom/Upload2NotionCustom.ts index 2e2b141..33dadc3 100644 --- a/src/upload/upoload_custom/Upload2NotionCustom.ts +++ b/src/upload/upoload_custom/Upload2NotionCustom.ts @@ -23,7 +23,6 @@ export class Upload2NotionCustom extends UploadBaseCustom { notionID: string, title: string, cover: string, - tags: string[], customValues: Record, childArr: any, ) { @@ -39,13 +38,12 @@ export class Upload2NotionCustom extends UploadBaseCustom { cover = databaseCover; } - return await this.createPage(title, cover, tags, customValues, childArr); + return await this.createPage(title, cover, customValues, childArr); } async createPage( title: string, cover: string, - tags: string[], customValues: Record, childArr: any, ) { @@ -54,7 +52,6 @@ export class Upload2NotionCustom extends UploadBaseCustom { databaseID, customTitleButton, customTitleName, - tagButton, notionAPI } = this.dbDetails; @@ -129,7 +126,6 @@ export class Upload2NotionCustom extends UploadBaseCustom { async syncMarkdownToNotionCustom( title: string, cover: string, - tags: string[], customValues: Record, markdown: string, nowFile: TFile, @@ -153,12 +149,11 @@ export class Upload2NotionCustom extends UploadBaseCustom { notionID, title, cover, - tags, customValues, file2Block, ); } else { - res = await this.createPage(title, cover, tags, customValues, file2Block); + res = await this.createPage(title, cover, customValues, file2Block); } if (res.status === 200) { await updateYamlInfo(markdown, nowFile, res, app, this.plugin, this.dbDetails); diff --git a/src/upload/upoload_custom/getMarkdownCustom.ts b/src/upload/upoload_custom/getMarkdownCustom.ts index ad0b323..e39b748 100644 --- a/src/upload/upoload_custom/getMarkdownCustom.ts +++ b/src/upload/upoload_custom/getMarkdownCustom.ts @@ -1,28 +1,29 @@ import {App, Notice} from "obsidian"; import {i18nConfig} from "../../lang/I18n"; -import {PluginSettings} from "../../ui/settingTabs"; +import {DatabaseDetails, PluginSettings} from "../../ui/settingTabs"; export async function getNowFileMarkdownContentCustom( app: App, + dbDetails: DatabaseDetails, settings: PluginSettings, ) { const nowFile = app.workspace.getActiveFile(); let cover = ''; - let tags = []; - let customValues: Record = {}; + let customValues: Record = {}; // Change 'any' to a more specific type if possible const FileCache = app.metadataCache.getFileCache(nowFile); try { cover = FileCache.frontmatter.coverurl; - tags = FileCache.frontmatter.tags; - // split the CustomValues into an array - const customValuesNames = settings.CustomValues.split('\n').map(value => value.trim()); + // Get custom property names from dbDetails + const customPropertyNames = dbDetails.customProperties.map(property => property.customValue); - // get the custom values from the frontmatter - customValuesNames.forEach(valueName => { - customValues[valueName] = FileCache.frontmatter[valueName]; - }); + // Extract custom values from the frontmatter based on the names + customPropertyNames.forEach(propertyName => { + if (FileCache.frontmatter[propertyName] !== undefined) { + customValues[propertyName] = FileCache.frontmatter[propertyName]; + } + }); } catch (error) { new Notice(i18nConfig["set-tags-fail"]); } @@ -33,7 +34,6 @@ export async function getNowFileMarkdownContentCustom( markDownData, nowFile, cover, - tags, customValues, }; } else { From 569d8eb69914a4aca45a3693c14a63048d2a036b Mon Sep 17 00:00:00 2001 From: Jiaxin Peng Date: Sun, 28 Jan 2024 00:26:58 +0000 Subject: [PATCH 2/6] fix the error of the display of title custom button --- src/ui/EditModal.ts | 10 +++++----- src/ui/settingModal.ts | 11 ++++++----- src/ui/settingTabs.ts | 8 ++++---- 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/src/ui/EditModal.ts b/src/ui/EditModal.ts index 030234d..80088ba 100644 --- a/src/ui/EditModal.ts +++ b/src/ui/EditModal.ts @@ -177,9 +177,9 @@ export class EditModal extends SettingModal { .setDesc(i18nConfig.NotionCustomTitleDesc) .addToggle((toggle) => toggle - .setValue(this.dataTemp.CustomTitleButtonTemp) + .setValue(this.dataTemp.customTitleButtonTemp) .onChange(async (value) => { - this.dataTemp.CustomTitleButtonTemp = value; + this.dataTemp.customTitleButtonTemp = value; this.updateSettingEl(CustomNameEl, value) @@ -192,8 +192,8 @@ export class EditModal extends SettingModal { // add custom title name - const CustomNameEl = this.createStyleDiv('custom-name', (this.dataTemp.CustomTitleButtonTemp), nextTabs); - this.createSettingEl(CustomNameEl, i18nConfig.NotionCustomTitleName, i18nConfig.NotionCustomTitleNameDesc, 'text', i18nConfig.NotionCustomTitleText, this.dataTemp.CustomTitleNameTemp,'dataTemp', 'CustomTitleNameTemp') + const CustomNameEl = this.createStyleDiv('custom-name', (this.dataTemp.customTitleButtonTemp), nextTabs); + this.createSettingEl(CustomNameEl, i18nConfig.NotionCustomTitleName, i18nConfig.NotionCustomTitleNameDesc, 'text', i18nConfig.NotionCustomTitleText, this.dataTemp.customTitleNameTemp,'dataTemp', 'customTitleNameTemp') // add api key @@ -236,7 +236,7 @@ export class EditModal extends SettingModal { this.createSettingEl(nextTabs, i18nConfig.DatabaseID, i18nConfig.NotionAPIDesc, 'password', i18nConfig.DatabaseIDText, this.dataTemp.databaseIDTemp, 'dataTemp', 'databaseIDTemp') // add custom title name - this.createSettingEl(nextTabs, i18nConfig.NotionCustomTitleName, i18nConfig.NotionCustomTitleNameDesc, 'text', i18nConfig.NotionCustomTitleText, this.dataTemp.CustomTitleNameTemp, 'dataTemp', 'CustomTitleNameTemp') + this.createSettingEl(nextTabs, i18nConfig.NotionCustomTitleName, i18nConfig.NotionCustomTitleNameDesc, 'text', i18nConfig.NotionCustomTitleText, this.dataTemp.customTitleNameTemp, 'dataTemp', 'customTitleNameTemp') // add new property button new Setting(nextTabs) diff --git a/src/ui/settingModal.ts b/src/ui/settingModal.ts index 462e669..8fdbf77 100644 --- a/src/ui/settingModal.ts +++ b/src/ui/settingModal.ts @@ -155,9 +155,9 @@ export class SettingModal extends Modal { .setDesc(i18nConfig.NotionCustomTitleDesc) .addToggle((toggle) => toggle - .setValue(this.data.CustomTitleButton) + .setValue(this.data.customTitleButton) .onChange(async (value) => { - this.data.CustomTitleButton = value; + this.data.customTitleButton = value; this.updateSettingEl(CustomNameEl, value) @@ -170,8 +170,8 @@ export class SettingModal extends Modal { // add custom title name - const CustomNameEl = this.createStyleDiv('custom-name', (this.data.CustomTitleButton), nextTabs); - this.createSettingEl(CustomNameEl, i18nConfig.NotionCustomTitleName, i18nConfig.NotionCustomTitleNameDesc, 'text', i18nConfig.NotionCustomTitleText, this.data.CustomTitleName, 'data', 'CustomTitleName') + const CustomNameEl = this.createStyleDiv('custom-name', (this.data.customTitleButton), nextTabs); + this.createSettingEl(CustomNameEl, i18nConfig.NotionCustomTitleName, i18nConfig.NotionCustomTitleNameDesc, 'text', i18nConfig.NotionCustomTitleText, this.data.customTitleName, 'data', 'customTitleName') // add api key @@ -199,6 +199,7 @@ export class SettingModal extends Modal { this.createSettingEl(nextTabs, i18nConfig.DatabaseID, i18nConfig.NotionAPIDesc, 'password', i18nConfig.DatabaseIDText, this.data.databaseID, 'data', 'databaseID') } else if (value === 'custom') { + nextTabs.createEl('h3', {text: i18nConfig.NotionCustomSettingHeader}); // add full name @@ -214,7 +215,7 @@ export class SettingModal extends Modal { this.createSettingEl(nextTabs, i18nConfig.DatabaseID, i18nConfig.NotionAPIDesc, 'password', i18nConfig.DatabaseIDText, this.data.databaseID, 'data', 'databaseID') // add custom title name - this.createSettingEl(nextTabs, i18nConfig.NotionCustomTitleName, i18nConfig.NotionCustomTitleNameDesc, 'text', i18nConfig.NotionCustomTitleText, this.data.CustomTitleName, 'data', 'CustomTitleName') + this.createSettingEl(nextTabs, i18nConfig.NotionCustomTitleName, i18nConfig.NotionCustomTitleNameDesc, 'text', i18nConfig.NotionCustomTitleText, this.data.customTitleName, 'data', 'customTitleName') // add new property button new Setting(nextTabs) diff --git a/src/ui/settingTabs.ts b/src/ui/settingTabs.ts index 72b1049..0247cb0 100644 --- a/src/ui/settingTabs.ts +++ b/src/ui/settingTabs.ts @@ -16,8 +16,8 @@ export interface PluginSettings { proxy: string; GeneralButton: boolean; tagButton: boolean; - CustomTitleButton: boolean; - CustomTitleName: string; + customTitleButton: boolean; + customTitleName: string; notionAPIGeneral: string; databaseIDGeneral: string; CustomButton: boolean; @@ -51,8 +51,8 @@ export const DEFAULT_SETTINGS: PluginSettings = { proxy: "", GeneralButton: true, tagButton: true, - CustomTitleButton: false, - CustomTitleName: "", + customTitleButton: false, + customTitleName: "", notionAPIGeneral: "", databaseIDGeneral: "", CustomButton: false, From a179d3da52eeff9644277032a3920023879eb811 Mon Sep 17 00:00:00 2001 From: Jiaxin Peng Date: Mon, 29 Jan 2024 00:55:06 +0000 Subject: [PATCH 3/6] almost finish the structure --- src/commands/NotionCommands.ts | 12 +- src/ui/CustomModal.ts | 36 +++- src/ui/EditModal.ts | 3 - src/ui/settingModal.ts | 7 +- src/ui/settingTabs.ts | 2 +- src/upload/uploadCommand.ts | 167 ++++++++++-------- .../BaseUpload2NotionGeneral.ts | 153 ++++++++-------- .../upload_general/getMarkdownGeneral.ts | 48 ++--- .../upoload_custom/Upload2NotionCustom.ts | 120 ++++++++----- .../upoload_custom/getMarkdownCustom.ts | 17 +- 10 files changed, 319 insertions(+), 246 deletions(-) diff --git a/src/commands/NotionCommands.ts b/src/commands/NotionCommands.ts index 4e5979e..1b8a767 100644 --- a/src/commands/NotionCommands.ts +++ b/src/commands/NotionCommands.ts @@ -1,7 +1,7 @@ import { i18nConfig } from "src/lang/I18n"; import {Editor, MarkdownView, setTooltip} from "obsidian"; import { FuzzySuggester, DatabaseList } from "./FuzzySuggester"; -import { uploadCommandGeneral, uploadCommandNext } from "../upload/uploadCommand"; +import {uploadCommandCustom, uploadCommandGeneral, uploadCommandNext} from "../upload/uploadCommand"; import ObsidianSyncNotionPlugin from "src/main"; import {DatabaseDetails} from "../ui/settingTabs"; @@ -94,11 +94,11 @@ export default class RibbonCommands { await uploadCommandGeneral(this.plugin, this.plugin.settings, dbDetails, this.plugin.app); }; } - // else if (dbDetails.format === 'custom') { - // editorCallback = async (editor, view) => { - // await uploadCommandGeneral(this.plugin, dbDetails, this.plugin.app); - // }; - // } + else if (dbDetails.format === 'custom') { + editorCallback = async (editor, view) => { + await uploadCommandCustom(this.plugin, this.plugin.settings, dbDetails, this.plugin.app); + }; + } this.Ncommand.push({ id: commandId, name: commandName, editorCallback }); } diff --git a/src/ui/CustomModal.ts b/src/ui/CustomModal.ts index 844034b..e3428d4 100644 --- a/src/ui/CustomModal.ts +++ b/src/ui/CustomModal.ts @@ -4,7 +4,7 @@ import {ObsidianSettingTab} from "./settingTabs"; export class CustomModal extends Modal { propertyLines: Setting[] = []; // Store all property line settings - properties: { customValue: string, customType: string }[] = []; // Array to store property values and types + properties: { customName: string, customType: string }[] = []; // Array to store property values and types plugin: ObsidianSyncNotionPlugin; settingTab: ObsidianSettingTab; @@ -14,19 +14,45 @@ export class CustomModal extends Modal { createPropertyLine(containerEl: HTMLElement): void { const propertyIndex = this.properties.length; - this.properties.push({customValue: "", customType: ""}); // Initialize with empty values + this.properties.push({customName: "", customType: ""}); // Initialize with empty values const propertyLine = new Setting(containerEl) + if (propertyIndex === 0) { + propertyLine + .setName("Title") + .setDesc("The title of the page, must be the first property") + + propertyLine.addText((text) => { + text + .setPlaceholder("Property name") + .setValue("") + .onChange(async (value) => { + this.properties[propertyIndex].customName = value; // Update the customValue of the specific property + }); + + } + ) + + propertyLine.addDropdown((dropdown) => { + dropdown + .addOption("title", "Title") + .setValue("") + .onChange(async (value) => { + this.properties[propertyIndex].customType = value; // Update the customType of the specific property + }); + } + ) + } else { propertyLine - .setName("Property " + (propertyIndex + 1)) + .setName("Property " + (propertyIndex)) propertyLine.addText((text) => { text .setPlaceholder("Property name") .setValue("") .onChange(async (value) => { - this.properties[propertyIndex].customValue = value; // Update the customValue of the specific property + this.properties[propertyIndex].customName = value; // Update the customValue of the specific property }); } ) @@ -70,7 +96,7 @@ export class CustomModal extends Modal { }); } ); - + } this.propertyLines.push(propertyLine); } diff --git a/src/ui/EditModal.ts b/src/ui/EditModal.ts index 80088ba..2e0cc44 100644 --- a/src/ui/EditModal.ts +++ b/src/ui/EditModal.ts @@ -235,9 +235,6 @@ export class EditModal extends SettingModal { // add database id this.createSettingEl(nextTabs, i18nConfig.DatabaseID, i18nConfig.NotionAPIDesc, 'password', i18nConfig.DatabaseIDText, this.dataTemp.databaseIDTemp, 'dataTemp', 'databaseIDTemp') - // add custom title name - this.createSettingEl(nextTabs, i18nConfig.NotionCustomTitleName, i18nConfig.NotionCustomTitleNameDesc, 'text', i18nConfig.NotionCustomTitleText, this.dataTemp.customTitleNameTemp, 'dataTemp', 'customTitleNameTemp') - // add new property button new Setting(nextTabs) .setName(i18nConfig.NotionCustomValues) diff --git a/src/ui/settingModal.ts b/src/ui/settingModal.ts index 8fdbf77..c526324 100644 --- a/src/ui/settingModal.ts +++ b/src/ui/settingModal.ts @@ -214,9 +214,6 @@ export class SettingModal extends Modal { // add database id this.createSettingEl(nextTabs, i18nConfig.DatabaseID, i18nConfig.NotionAPIDesc, 'password', i18nConfig.DatabaseIDText, this.data.databaseID, 'data', 'databaseID') - // add custom title name - this.createSettingEl(nextTabs, i18nConfig.NotionCustomTitleName, i18nConfig.NotionCustomTitleNameDesc, 'text', i18nConfig.NotionCustomTitleText, this.data.customTitleName, 'data', 'customTitleName') - // add new property button new Setting(nextTabs) .setName(i18nConfig.NotionCustomValues) @@ -251,9 +248,9 @@ export class SettingModal extends Modal { renderCustomPreview(properties: any[], nextTabs: HTMLElement) { const previewContainer = nextTabs.createDiv('preview-container'); - properties.forEach((property: { customValue: any; customType: any; }) => { + properties.forEach((property: { customName: any; customType: any; }) => { const propertyEl = previewContainer.createEl('div', {cls: 'property-preview'}); - propertyEl.createEl('span', {text: `Property: ${property.customValue}, Type: ${property.customType}`}); + propertyEl.createEl('span', {text: `Property: ${property.customName}, Type: ${property.customType}`}); }); } diff --git a/src/ui/settingTabs.ts b/src/ui/settingTabs.ts index 0247cb0..28291d3 100644 --- a/src/ui/settingTabs.ts +++ b/src/ui/settingTabs.ts @@ -37,7 +37,7 @@ export interface DatabaseDetails { tagButton: boolean; customTitleButton: boolean; customTitleName: string; - customProperties:{ customValue: string, customType: string }[]; + customProperties:{ customName: string, customType: string }[]; // customValues: string; saved: boolean; } diff --git a/src/upload/uploadCommand.ts b/src/upload/uploadCommand.ts index fce960b..a9b8235 100644 --- a/src/upload/uploadCommand.ts +++ b/src/upload/uploadCommand.ts @@ -1,118 +1,131 @@ -import { i18nConfig } from "../lang/I18n"; -import { App, Notice } from "obsidian"; -import { Upload2NotionNext } from "./upload_next/Upload2NotionNext"; -import { Upload2NotionGeneral } from "./upload_general/Upload2NotionGeneral"; -import { Upload2NotionCustom } from "./upoload_custom/Upload2NotionCustom"; +import {i18nConfig} from "../lang/I18n"; +import {App, Notice} from "obsidian"; +import {Upload2NotionNext} from "./upload_next/Upload2NotionNext"; +import {Upload2NotionGeneral} from "./upload_general/Upload2NotionGeneral"; +import {Upload2NotionCustom} from "./upoload_custom/Upload2NotionCustom"; import {DatabaseDetails, PluginSettings} from "../ui/settingTabs"; import ObsidianSyncNotionPlugin from "../main"; -import { getNowFileMarkdownContentNext } from "./upload_next/getMarkdownNext"; -import { getNowFileMarkdownContentGeneral } from "./upload_general/getMarkdownGeneral"; +import {getNowFileMarkdownContentNext} from "./upload_next/getMarkdownNext"; +import {getNowFileMarkdownContentGeneral} from "./upload_general/getMarkdownGeneral"; import {getNowFileMarkdownContentCustom} from "./upoload_custom/getMarkdownCustom"; export async function uploadCommandNext( - plugin: ObsidianSyncNotionPlugin, - settings: PluginSettings, + plugin: ObsidianSyncNotionPlugin, + settings: PluginSettings, dbDetails: DatabaseDetails, - app: App, + app: App, ) { - const { notionAPI, databaseID } = dbDetails; + const {notionAPI, databaseID} = dbDetails; - // Check if NNon exists - // if (NNon === undefined) { - // const NNonmessage = i18nConfig.NNonMissing; - // new Notice(NNonmessage); - // return; - // } + // Check if NNon exists + // if (NNon === undefined) { + // const NNonmessage = i18nConfig.NNonMissing; + // new Notice(NNonmessage); + // return; + // } - // Check if the user has set up the Notion API and database ID - if (notionAPI === "" || databaseID === "") { - const setAPIMessage = i18nConfig["set-api-id"]; - new Notice(setAPIMessage); - return; - } + // Check if the user has set up the Notion API and database ID + if (notionAPI === "" || databaseID === "") { + const setAPIMessage = i18nConfig["set-api-id"]; + new Notice(setAPIMessage); + return; + } - const { markDownData, nowFile, emoji, cover, tags, type, slug, stats, category, summary, paword, favicon, datetime } = await getNowFileMarkdownContentNext(app, settings) + const { + markDownData, + nowFile, + emoji, + cover, + tags, + type, + slug, + stats, + category, + summary, + paword, + favicon, + datetime + } = await getNowFileMarkdownContentNext(app, settings) - if (markDownData) { - const { basename } = nowFile; - const upload = new Upload2NotionNext(plugin, dbDetails); - const res = await upload.syncMarkdownToNotionNext(basename, emoji, cover, tags, type, slug, stats, category, summary, paword, favicon, datetime, markDownData, nowFile, this.app); + if (markDownData) { + const {basename} = nowFile; + const upload = new Upload2NotionNext(plugin, dbDetails); + const res = await upload.syncMarkdownToNotionNext(basename, emoji, cover, tags, type, slug, stats, category, summary, paword, favicon, datetime, markDownData, nowFile, this.app); - if (res.status === 200) { - new Notice(`${i18nConfig["sync-success"]}${basename}`); - } else { - new Notice(`${i18nConfig["sync-fail"]}${basename}`, 5000); - } + if (res.status === 200) { + new Notice(`${i18nConfig["sync-success"]}${basename}`); + } else { + new Notice(`${i18nConfig["sync-fail"]}${basename}`, 5000); + } - } + } } - export async function uploadCommandGeneral( - plugin: ObsidianSyncNotionPlugin, - settings: PluginSettings, + plugin: ObsidianSyncNotionPlugin, + settings: PluginSettings, dbDetails: DatabaseDetails, - app: App, + app: App, ) { - const { notionAPI, databaseID } = dbDetails; + const {notionAPI, databaseID} = dbDetails; - // Check if the user has set up the Notion API and database ID - if (notionAPI === "" || databaseID === "") { - const setAPIMessage = i18nConfig["set-api-id"]; - new Notice(setAPIMessage); - return; - } + // Check if the user has set up the Notion API and database ID + if (notionAPI === "" || databaseID === "") { + const setAPIMessage = i18nConfig["set-api-id"]; + new Notice(setAPIMessage); + return; + } - const { markDownData, nowFile, cover, tags } = await getNowFileMarkdownContentGeneral(app, settings) + const {markDownData, nowFile, cover, tags} = await getNowFileMarkdownContentGeneral(app, settings) - if (markDownData) { - const { basename } = nowFile; + if (markDownData) { + const {basename} = nowFile; - const upload = new Upload2NotionGeneral(plugin, dbDetails); - const res = await upload.syncMarkdownToNotionGeneral(basename, cover, tags, markDownData, nowFile, this.app); + const upload = new Upload2NotionGeneral(plugin, dbDetails); + const res = await upload.syncMarkdownToNotionGeneral(basename, cover, tags, markDownData, nowFile, this.app); - if (res.status === 200) { - new Notice(`${i18nConfig["sync-success"]}${basename}`); - } else { - new Notice(`${i18nConfig["sync-fail"]}${basename}`, 5000); - } + if (res.status === 200) { + new Notice(`${i18nConfig["sync-success"]}${basename}`); + } else { + new Notice(`${i18nConfig["sync-fail"]}${basename}`, 5000); + } - } + } } export async function uploadCommandCustom( - plugin: ObsidianSyncNotionPlugin, - settings: PluginSettings, + plugin: ObsidianSyncNotionPlugin, + settings: PluginSettings, dbDetails: DatabaseDetails, - app: App, + app: App, ) { - const { notionAPI, databaseID } = settings; + const {notionAPI, databaseID} = settings; - // Check if the user has set up the Notion API and database ID - if (notionAPI === "" || databaseID === "") { - const setAPIMessage = i18nConfig["set-api-id"]; - new Notice(setAPIMessage); - return; - } + // Check if the user has set up the Notion API and database ID + if (notionAPI === "" || databaseID === "") { + const setAPIMessage = i18nConfig["set-api-id"]; + new Notice(setAPIMessage); + return; + } - const { markDownData, nowFile, cover, customValues} = await getNowFileMarkdownContentCustom(app, dbDetails, settings) + const {markDownData, nowFile, cover, customValues} = await getNowFileMarkdownContentCustom(app, dbDetails, settings) - if (markDownData) { - const { basename } = nowFile; + if (markDownData) { + const { basename} = nowFile; - const upload = new Upload2NotionCustom(plugin,dbDetails); - const res = await upload.syncMarkdownToNotionCustom(basename, cover, customValues, markDownData, nowFile, this.app); + const upload = new Upload2NotionCustom(plugin, dbDetails); + const res = await upload.syncMarkdownToNotionCustom(cover, customValues, markDownData, nowFile, this.app); - if (res.status === 200) { - new Notice(`${i18nConfig["sync-success"]}${basename}`); - } else { - new Notice(`${i18nConfig["sync-fail"]}${basename}`, 5000); - } + if (res.status === 200) { + new Notice(`${i18nConfig["sync-success"]}${basename}`); + } else { + new Notice(`${i18nConfig["sync-fail"]}${basename}`, 5000); + } - } + } } diff --git a/src/upload/upload_general/BaseUpload2NotionGeneral.ts b/src/upload/upload_general/BaseUpload2NotionGeneral.ts index a5d6795..7cca716 100644 --- a/src/upload/upload_general/BaseUpload2NotionGeneral.ts +++ b/src/upload/upload_general/BaseUpload2NotionGeneral.ts @@ -7,89 +7,90 @@ import MyPlugin from "src/main"; import {DatabaseDetails} from "../../ui/settingTabs"; export class UploadBaseGeneral { - plugin: MyPlugin; - notion: Client; - agent: any; + plugin: MyPlugin; + notion: Client; + agent: any; dbDetails: DatabaseDetails - constructor(plugin: MyPlugin, dbDetails: DatabaseDetails) { - this.plugin = plugin; + + constructor(plugin: MyPlugin, dbDetails: DatabaseDetails) { + this.plugin = plugin; this.dbDetails = dbDetails - } + } - async deletePage(notionID: string) { + async deletePage(notionID: string) { const {notionAPI} = this.dbDetails - return requestUrl({ - url: `https://api.notion.com/v1/blocks/${notionID}`, - method: 'DELETE', - headers: { - 'Content-Type': 'application/json', - 'Authorization': 'Bearer ' + notionAPI, - 'Notion-Version': '2022-06-28', - }, - body: '' - }); - } + return requestUrl({ + url: `https://api.notion.com/v1/blocks/${notionID}`, + method: 'DELETE', + headers: { + 'Content-Type': 'application/json', + 'Authorization': 'Bearer ' + notionAPI, + 'Notion-Version': '2022-06-28', + }, + body: '' + }); + } - async getDataBase(databaseID: string) { + async getDataBase(databaseID: string) { const {notionAPI} = this.dbDetails - const response = await requestUrl({ - url: `https://api.notion.com/v1/databases/${databaseID}`, - method: 'GET', - headers: { - 'Authorization': 'Bearer ' + notionAPI, - 'Notion-Version': '2022-06-28', - } - } - ) + const response = await requestUrl({ + url: `https://api.notion.com/v1/databases/${databaseID}`, + method: 'GET', + headers: { + 'Authorization': 'Bearer ' + notionAPI, + 'Notion-Version': '2022-06-28', + } + } + ) - // Check if cover is present in the JSON response and then get the URL - if (response.json.cover && response.json.cover.external) { - return response.json.cover.external.url; - } else { - return null; // or some other default value, if you prefer - } - } + // Check if cover is present in the JSON response and then get the URL + if (response.json.cover && response.json.cover.external) { + return response.json.cover.external.url; + } else { + return null; // or some other default value, if you prefer + } + } - // async updateYamlInfo(yamlContent: string, nowFile: TFile, res: any, app: App, settings: any) { - // let {url, id} = res.json - // // replace www to notionID - // const {notionUser} = this.plugin.settings; - // - // if (notionUser !== "") { - // // replace url str "www" to notionID - // url = url.replace("www.notion.so", `${notionUser}.notion.site`) - // } - // - // await app.fileManager.processFrontMatter(nowFile, yamlContent => { - // if (yamlContent['notionID']) { - // delete yamlContent['notionID'] - // } - // if (yamlContent['link']) { - // delete yamlContent['link'] - // } - // // add new notionID and link - // yamlContent.notionID = id; - // yamlContent.link = url; - // }); - // - // try { - // await navigator.clipboard.writeText(url) - // } catch (error) { - // new Notice(`复制链接失败,请手动复制${error}`) - // } - // // const __content = yamlContent.__content; - // // delete yamlContent.__content - // // const yamlhead = yaml.stringify(yamlContent) - // // // if yamlhead hava last \n remove it - // // const yamlhead_remove_n = yamlhead.replace(/\n$/, '') - // // // if __content have start \n remove it - // // const __content_remove_n = __content.replace(/^\n/, '') - // // const content = '---\n' +yamlhead_remove_n +'\n---\n' + __content_remove_n; - // // try { - // // await nowFile.vault.modify(nowFile, content) - // // } catch (error) { - // // new Notice(`write file error ${error}`) - // // } - // } + // async updateYamlInfo(yamlContent: string, nowFile: TFile, res: any, app: App, settings: any) { + // let {url, id} = res.json + // // replace www to notionID + // const {notionUser} = this.plugin.settings; + // + // if (notionUser !== "") { + // // replace url str "www" to notionID + // url = url.replace("www.notion.so", `${notionUser}.notion.site`) + // } + // + // await app.fileManager.processFrontMatter(nowFile, yamlContent => { + // if (yamlContent['notionID']) { + // delete yamlContent['notionID'] + // } + // if (yamlContent['link']) { + // delete yamlContent['link'] + // } + // // add new notionID and link + // yamlContent.notionID = id; + // yamlContent.link = url; + // }); + // + // try { + // await navigator.clipboard.writeText(url) + // } catch (error) { + // new Notice(`复制链接失败,请手动复制${error}`) + // } + // // const __content = yamlContent.__content; + // // delete yamlContent.__content + // // const yamlhead = yaml.stringify(yamlContent) + // // // if yamlhead hava last \n remove it + // // const yamlhead_remove_n = yamlhead.replace(/\n$/, '') + // // // if __content have start \n remove it + // // const __content_remove_n = __content.replace(/^\n/, '') + // // const content = '---\n' +yamlhead_remove_n +'\n---\n' + __content_remove_n; + // // try { + // // await nowFile.vault.modify(nowFile, content) + // // } catch (error) { + // // new Notice(`write file error ${error}`) + // // } + // } } diff --git a/src/upload/upload_general/getMarkdownGeneral.ts b/src/upload/upload_general/getMarkdownGeneral.ts index f035727..a1f7379 100644 --- a/src/upload/upload_general/getMarkdownGeneral.ts +++ b/src/upload/upload_general/getMarkdownGeneral.ts @@ -3,31 +3,31 @@ import {i18nConfig} from "../../lang/I18n"; import {PluginSettings} from "../../ui/settingTabs"; export async function getNowFileMarkdownContentGeneral( - app: App, - settings: PluginSettings, + app: App, + settings: PluginSettings, ) { - const nowFile = app.workspace.getActiveFile(); - let cover = ''; - let tags = []; + const nowFile = app.workspace.getActiveFile(); + let cover = ''; + let tags = []; - const FileCache = app.metadataCache.getFileCache(nowFile); - try { - cover = FileCache.frontmatter.coverurl; - tags = FileCache.frontmatter.tags; - } catch (error) { - new Notice(i18nConfig["set-tags-fail"]); - } + const FileCache = app.metadataCache.getFileCache(nowFile); + try { + cover = FileCache.frontmatter.coverurl; + tags = FileCache.frontmatter.tags; + } catch (error) { + new Notice(i18nConfig["set-tags-fail"]); + } - if (nowFile) { - const markDownData = await nowFile.vault.read(nowFile); - return { - markDownData, - nowFile, - cover, - tags, - }; - } else { - new Notice(i18nConfig["open-file"]); - return; - } + if (nowFile) { + const markDownData = await nowFile.vault.read(nowFile); + return { + markDownData, + nowFile, + cover, + tags, + }; + } else { + new Notice(i18nConfig["open-file"]); + return; + } } diff --git a/src/upload/upoload_custom/Upload2NotionCustom.ts b/src/upload/upoload_custom/Upload2NotionCustom.ts index 33dadc3..3f73bf6 100644 --- a/src/upload/upoload_custom/Upload2NotionCustom.ts +++ b/src/upload/upoload_custom/Upload2NotionCustom.ts @@ -1,11 +1,10 @@ -import { App, Notice, requestUrl, TFile } from "obsidian"; -import { Client } from "@notionhq/client"; -import { markdownToBlocks } from "@tryfabric/martian"; +import {App, Notice, requestUrl, TFile} from "obsidian"; +import {markdownToBlocks} from "@tryfabric/martian"; import * as yamlFrontMatter from "yaml-front-matter"; // import * as yaml from "yaml" import MyPlugin from "src/main"; import {DatabaseDetails, PluginSettings} from "../../ui/settingTabs"; -import { updateYamlInfo } from "../updateYaml"; +import {updateYamlInfo} from "../updateYaml"; import {UploadBaseCustom} from "./BaseUpload2NotionCustom"; export class Upload2NotionCustom extends UploadBaseCustom { @@ -21,14 +20,13 @@ export class Upload2NotionCustom extends UploadBaseCustom { // 暂时就直接删除,新建一个page async updatePage( notionID: string, - title: string, cover: string, customValues: Record, childArr: any, ) { await this.deletePage(notionID); - const { databaseID } = this.dbDetails; + const {databaseID} = this.dbDetails; const databaseCover = await this.getDataBase( databaseID @@ -38,11 +36,10 @@ export class Upload2NotionCustom extends UploadBaseCustom { cover = databaseCover; } - return await this.createPage(title, cover, customValues, childArr); + return await this.createPage(cover, customValues, childArr); } async createPage( - title: string, cover: string, customValues: Record, childArr: any, @@ -50,42 +47,11 @@ export class Upload2NotionCustom extends UploadBaseCustom { const { databaseID, - customTitleButton, - customTitleName, + customProperties, notionAPI } = this.dbDetails; - const bodyString: any = { - parent: { - database_id: databaseID, - }, - properties: { - [customTitleButton - ? customTitleName - : "title"]: { - title: [ - { - text: { - content: title, - }, - }, - ], - }, - ...(Object.keys(customValues).reduce((acc, key) => { - acc[key] = { - rich_text: [ - { - text: { - content: customValues[key] || '', - }, - }, - ], - }; - return acc; - }, {} as Record)), - }, - children: childArr, - }; + const bodyString: any = this.buildBodyString(customProperties, customValues, childArr); if (cover) { bodyString.cover = { @@ -124,7 +90,6 @@ export class Upload2NotionCustom extends UploadBaseCustom { } async syncMarkdownToNotionCustom( - title: string, cover: string, customValues: Record, markdown: string, @@ -147,13 +112,12 @@ export class Upload2NotionCustom extends UploadBaseCustom { if (notionID) { res = await this.updatePage( notionID, - title, cover, customValues, file2Block, ); } else { - res = await this.createPage(title, cover, customValues, file2Block); + res = await this.createPage(cover, customValues, file2Block); } if (res.status === 200) { await updateYamlInfo(markdown, nowFile, res, app, this.plugin, this.dbDetails); @@ -162,4 +126,72 @@ export class Upload2NotionCustom extends UploadBaseCustom { } return res; } + + private buildPropertyObject(customName: string, customType: string, customValues: Record) { + const value = customValues[customName] || ''; + + switch (customType) { + case "title": + return { + title: [ + { + text: { + content: value, + }, + }, + ], + }; + case "rich_text": + return { + rich_text: [ + { + text: { + content: value || '', + }, + }, + ], + }; + case "date": + return { + date: { + start: value || new Date().toISOString(), + }, + }; + case "select": + return { + select: { + name: value, + }, + }; + case "multi_select": + return { + multi_select: Array.isArray(value) ? value.map(item => ({name: item})) : [{name: value}], + }; + } + } + + private buildBodyString( + customProperties: { customName: string; customType: string }[], + customValues: Record, + childArr: any, + ) { + + const properties: { [key: string]: any } = {}; + + customProperties.forEach(({customName, customType}) => { + properties[customName] = this.buildPropertyObject(customName, customType, customValues); + } + ); + + + return { + parent: { + database_id: this.dbDetails.databaseID, + }, + properties, + children: childArr, + }; + } + + } diff --git a/src/upload/upoload_custom/getMarkdownCustom.ts b/src/upload/upoload_custom/getMarkdownCustom.ts index e39b748..0dacc09 100644 --- a/src/upload/upoload_custom/getMarkdownCustom.ts +++ b/src/upload/upoload_custom/getMarkdownCustom.ts @@ -1,4 +1,4 @@ -import {App, Notice} from "obsidian"; +import {App, Notice, TAbstractFile, TFile} from "obsidian"; import {i18nConfig} from "../../lang/I18n"; import {DatabaseDetails, PluginSettings} from "../../ui/settingTabs"; @@ -8,22 +8,29 @@ export async function getNowFileMarkdownContentCustom( settings: PluginSettings, ) { const nowFile = app.workspace.getActiveFile(); - let cover = ''; - let customValues: Record = {}; // Change 'any' to a more specific type if possible + if (!nowFile) { + new Notice(i18nConfig["open-file"]); + return; + } + let cover = ''; + let customValues: Record = {}; const FileCache = app.metadataCache.getFileCache(nowFile); try { cover = FileCache.frontmatter.coverurl; // Get custom property names from dbDetails - const customPropertyNames = dbDetails.customProperties.map(property => property.customValue); + const customPropertyValues = dbDetails.customProperties.map(property => property.customName); // Extract custom values from the frontmatter based on the names - customPropertyNames.forEach(propertyName => { + customPropertyValues.forEach( propertyName => { if (FileCache.frontmatter[propertyName] !== undefined) { customValues[propertyName] = FileCache.frontmatter[propertyName]; } }); + + customValues['title'] = nowFile.basename; // Use 'basename' for the file name without extension + } catch (error) { new Notice(i18nConfig["set-tags-fail"]); } From 8c6aea8250b6ce386400fcfb90e98cbf9ebb128d Mon Sep 17 00:00:00 2001 From: Jiaxin Peng Date: Mon, 29 Jan 2024 11:12:07 +0000 Subject: [PATCH 4/6] Complete the basic function of customisation --- README.md | 15 ++++- src/upload/updateYaml.ts | 2 +- .../upload_general/Upload2NotionGeneral.ts | 2 +- src/upload/upload_next/Upload2NotionNext.ts | 2 +- .../upoload_custom/Upload2NotionCustom.ts | 4 +- .../upoload_custom/getMarkdownCustom.ts | 65 ++++++++++--------- 6 files changed, 54 insertions(+), 36 deletions(-) diff --git a/README.md b/README.md index 99a7195..148d388 100644 --- a/README.md +++ b/README.md @@ -13,19 +13,28 @@ Thanks to the [original author](https://github.com/EasyChris/obsidian-to-notion) Thus, based on the [original author's work](https://github.com/EasyChris/obsidian-to-notion), I've added a feature to match the [NotionNext](https://github.com/tangly1024/NotionNext) template. This way, you can edit directly in Obsidian and publish with a single click after organizing. -**Now, support both NotionNext and General databases.** +**Now, support both NotionNext and General databases with customised properties.** -**现在支持NotionNext和普通Notion数据库。** +**现在支持NotionNext和普通Notion数据库,可自定义数据库列表。** ## TODO List -- [ ] Support custom properties for Notion General database. 支持自定义属性 +- [x] Support custom properties for Notion General database. 支持自定义属性 - [ ] Support group upload with one click 支持一键多数据库上传 - [x] Support preview for database details in plugin settings. 支持预览数据库详情 - [x] Support edit for database details in plugin settings. 支持编辑数据库详情 ## Update +### 2.2.0 + +- add the support for custom properties in the Notion General database. 支持自定义属性 + +![](https://minioapi.pjx.ac.cn/img1/2024/01/039760ee966c6c1e04410d3f69787f85.png) +- Once you create the properties, you can preview the database details in the plugin settings. + +Once you add the custom properties in the Notion General database, you can add the corresponding properties in the YAML frontmatter. **The name of the properties is case sensitive. You should use small letter.** + ### 2.1.0 - add confirmation interface for deleting a database 增加删除数据库的确认界面 diff --git a/src/upload/updateYaml.ts b/src/upload/updateYaml.ts index 2a91687..219254d 100644 --- a/src/upload/updateYaml.ts +++ b/src/upload/updateYaml.ts @@ -1,6 +1,6 @@ import { App, Notice, TFile } from "obsidian"; import ObsidianSyncNotionPlugin from "../main"; -import {DatabaseDetails, PluginSettings} from "../ui/settingTabs"; +import {DatabaseDetails} from "../ui/settingTabs"; export async function updateYamlInfo( yamlContent: string, diff --git a/src/upload/upload_general/Upload2NotionGeneral.ts b/src/upload/upload_general/Upload2NotionGeneral.ts index b0cb5af..266f666 100644 --- a/src/upload/upload_general/Upload2NotionGeneral.ts +++ b/src/upload/upload_general/Upload2NotionGeneral.ts @@ -139,7 +139,7 @@ export class Upload2NotionGeneral extends UploadBaseGeneral { const frontmasster = app.metadataCache.getFileCache(nowFile)?.frontmatter; const {abName} = this.dbDetails - const notionIDKey = `${abName}-NotionID`; + const notionIDKey = `NotionID-${abName}`; const notionID = frontmasster ? frontmasster[notionIDKey] : null; diff --git a/src/upload/upload_next/Upload2NotionNext.ts b/src/upload/upload_next/Upload2NotionNext.ts index 9408b70..bba434f 100644 --- a/src/upload/upload_next/Upload2NotionNext.ts +++ b/src/upload/upload_next/Upload2NotionNext.ts @@ -228,7 +228,7 @@ export class Upload2NotionNext extends UploadBaseNext { const file2Block = markdownToBlocks(__content, options); const frontmasster = app.metadataCache.getFileCache(nowFile)?.frontmatter const {abName} = this.dbDetails - const notionIDKey = `${abName}-NotionID`; + const notionIDKey = `NotionID-${abName}`; const notionID = frontmasster ? frontmasster[notionIDKey] : null; diff --git a/src/upload/upoload_custom/Upload2NotionCustom.ts b/src/upload/upoload_custom/Upload2NotionCustom.ts index 3f73bf6..5e6b6fc 100644 --- a/src/upload/upoload_custom/Upload2NotionCustom.ts +++ b/src/upload/upoload_custom/Upload2NotionCustom.ts @@ -107,7 +107,9 @@ export class Upload2NotionCustom extends UploadBaseCustom { const file2Block = markdownToBlocks(__content, options); const frontmasster = app.metadataCache.getFileCache(nowFile)?.frontmatter; - const notionID = frontmasster ? frontmasster.notionID : null; + const {abName} = this.dbDetails + const notionIDKey = `NotionID-${abName}`; + const notionID = frontmasster ? frontmasster[notionIDKey] : null; if (notionID) { res = await this.updatePage( diff --git a/src/upload/upoload_custom/getMarkdownCustom.ts b/src/upload/upoload_custom/getMarkdownCustom.ts index 0dacc09..ed33655 100644 --- a/src/upload/upoload_custom/getMarkdownCustom.ts +++ b/src/upload/upoload_custom/getMarkdownCustom.ts @@ -1,13 +1,12 @@ -import {App, Notice, TAbstractFile, TFile} from "obsidian"; +import {App, Notice} from "obsidian"; import {i18nConfig} from "../../lang/I18n"; -import {DatabaseDetails, PluginSettings} from "../../ui/settingTabs"; +import {DatabaseDetails} from "../../ui/settingTabs"; export async function getNowFileMarkdownContentCustom( - app: App, + app: App, dbDetails: DatabaseDetails, - settings: PluginSettings, ) { - const nowFile = app.workspace.getActiveFile(); + const nowFile = app.workspace.getActiveFile(); if (!nowFile) { new Notice(i18nConfig["open-file"]); return; @@ -15,36 +14,44 @@ export async function getNowFileMarkdownContentCustom( let cover = ''; let customValues: Record = {}; - const FileCache = app.metadataCache.getFileCache(nowFile); - try { - cover = FileCache.frontmatter.coverurl; + const FileCache = app.metadataCache.getFileCache(nowFile); + try { + cover = FileCache.frontmatter.coverurl; - // Get custom property names from dbDetails - const customPropertyValues = dbDetails.customProperties.map(property => property.customName); + // Get custom property names from dbDetails excluding the title type property + const customPropertyNames = dbDetails.customProperties + .filter(property => property.customType !== 'title') // Exclude 'title' type property + .map(property => property.customName); - // Extract custom values from the frontmatter based on the names - customPropertyValues.forEach( propertyName => { - if (FileCache.frontmatter[propertyName] !== undefined) { + // Extract custom values from the front matter based on the names + customPropertyNames.forEach(propertyName => { + if (FileCache.frontmatter && FileCache.frontmatter[propertyName] !== undefined) { customValues[propertyName] = FileCache.frontmatter[propertyName]; } }); - customValues['title'] = nowFile.basename; // Use 'basename' for the file name without extension + // Check if any of the customProperties has a customType of 'title' + const titleProperty = dbDetails.customProperties.find(property => property.customType === 'title'); - } catch (error) { - new Notice(i18nConfig["set-tags-fail"]); - } + // If a 'title' type property exists, use the file's basename as its value + if (titleProperty) { + customValues[titleProperty.customName] = nowFile.basename; // Use 'basename' for the file name without extension + } - if (nowFile) { - const markDownData = await nowFile.vault.read(nowFile); - return { - markDownData, - nowFile, - cover, - customValues, - }; - } else { - new Notice(i18nConfig["open-file"]); - return; - } + } catch (error) { + new Notice(i18nConfig["set-tags-fail"]); + } + + if (nowFile) { + const markDownData = await nowFile.vault.read(nowFile); + return { + markDownData, + nowFile, + cover, + customValues, + }; + } else { + new Notice(i18nConfig["open-file"]); + return; + } } From 01988980861e62dbec213eb1194e125ac499cc4e Mon Sep 17 00:00:00 2001 From: Jiaxin Peng Date: Mon, 29 Jan 2024 11:53:18 +0000 Subject: [PATCH 5/6] update the readme and changelog --- CHANGELOG.md | 29 +++++++------- README.md | 29 ++++++++++---- src/ui/CustomModal.ts | 18 ++++----- .../upoload_custom/Upload2NotionCustom.ts | 38 +++++++++++++++++++ 4 files changed, 84 insertions(+), 30 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e4a662..13232b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,18 +1,19 @@ -# Changelog v2.1.0 +# Changelog v2.2.0 ## Feature -- add confirmation interface for deleting a database -- 增加删除数据库的确认界面 +- add the support for the customised properties of general databases +- 增加对普通数据库自定义属性的支持 -## Fix - -- fix the typo in the edit database modal -- improve the logic for the database editing -- 修复编辑数据库界面的标题错误 -- 改进数据库编辑界面的逻辑 - -## TODO - -- [ ] add the support for the customised properties of general databases -- [ ] 增加对普通数据库自定义属性的支持 +- support + - [x] `title`, which is the first column of the database + - [x] 'Text' + - [x] 'Number' + - [x] 'Date' + - [x] 'Checkbox' + - [x] 'Select' + - [x] 'Multi-select' + - [x] 'URL' + - [x] 'Email' + - [x] 'Phone' + - [x] 'File' (**Only support external embedded files**) diff --git a/README.md b/README.md index 148d388..a31ce33 100644 --- a/README.md +++ b/README.md @@ -9,10 +9,6 @@ [中文文档](README-zh.md) -Thanks to the [original author](https://github.com/EasyChris/obsidian-to-notion) for developing such a useful plugin that can synchronize Obsidian to Notion. However, the original repository can only sync Name and Tag information. For those like me who use [NotionNext](https://github.com/tangly1024/NotionNext) to set up their website, this presents some limitations. Every time I import, I need to make a lot of modifications. - -Thus, based on the [original author's work](https://github.com/EasyChris/obsidian-to-notion), I've added a feature to match the [NotionNext](https://github.com/tangly1024/NotionNext) template. This way, you can edit directly in Obsidian and publish with a single click after organizing. - **Now, support both NotionNext and General databases with customised properties.** **现在支持NotionNext和普通Notion数据库,可自定义数据库列表。** @@ -26,15 +22,34 @@ Thus, based on the [original author's work](https://github.com/EasyChris/obsidia ## Update -### 2.2.0 +### 2.2.0 (Big Update) - add the support for custom properties in the Notion General database. 支持自定义属性 + - [x] `title`, which is the first column of the database + - [x] 'Text' + - [x] 'Number' + - [x] 'Date' + - [x] 'Checkbox' + - [x] 'Select' + - [x] 'Multi-select' + - [x] 'URL' + - [x] 'Email' + - [x] 'Phone' + - [x] 'File' (**Only support external embedded files**) -![](https://minioapi.pjx.ac.cn/img1/2024/01/039760ee966c6c1e04410d3f69787f85.png) +![](https://minioapi.pjx.ac.cn/img1/2024/01/0cd99007409feede77bf5a3291e88af3.png) - Once you create the properties, you can preview the database details in the plugin settings. +![](https://minioapi.pjx.ac.cn/img1/2024/01/665139962cc4cee2a0cb576b508b29f2.png) -Once you add the custom properties in the Notion General database, you can add the corresponding properties in the YAML frontmatter. **The name of the properties is case sensitive. You should use small letter.** +--- +Thanks to the [original author](https://github.com/EasyChris/obsidian-to-notion) for developing such a useful plugin that can synchronize Obsidian to Notion. However, the original repository can only sync Name and Tag information. For those like me who use [NotionNext](https://github.com/tangly1024/NotionNext) to set up their website, this presents some limitations. Every time I import, I need to make a lot of modifications. + +Thus, based on the [original author's work](https://github.com/EasyChris/obsidian-to-notion), I've added a feature to match the [NotionNext](https://github.com/tangly1024/NotionNext) template. This way, you can edit directly in Obsidian and publish with a single click after organizing. + +--- + +## Archive Update ### 2.1.0 - add confirmation interface for deleting a database 增加删除数据库的确认界面 diff --git a/src/ui/CustomModal.ts b/src/ui/CustomModal.ts index e3428d4..3d5593f 100644 --- a/src/ui/CustomModal.ts +++ b/src/ui/CustomModal.ts @@ -42,7 +42,7 @@ export class CustomModal extends Modal { this.properties[propertyIndex].customType = value; // Update the customType of the specific property }); } - ) + ) } else { propertyLine .setName("Property " + (propertyIndex)) @@ -64,19 +64,19 @@ export class CustomModal extends Modal { .addOption("select", "Select") .addOption("multi_select", "Multi-Select") .addOption("date", "Date") - .addOption("person", "Person") + // .addOption("person", "Person") .addOption("file", "Files & Media") .addOption("checkbox", "Checkbox") .addOption("url", "URL") .addOption("email", "Email") .addOption("phone_number", "Phone Number") - .addOption("formula", "Formula") - .addOption("relation", "Relation") - .addOption("rollup", "Rollup") - .addOption("created_time", "Created time") - .addOption("created_by", "Created by") - .addOption("last_edited_time", "Last Edited Time") - .addOption("last_edited_by", "Last Edited By") + // .addOption("formula", "Formula") + // .addOption("relation", "Relation") + // .addOption("rollup", "Rollup") + // .addOption("created_time", "Created time") + // .addOption("created_by", "Created by") + // .addOption("last_edited_time", "Last Edited Time") + // .addOption("last_edited_by", "Last Edited By") .setValue("text") .onChange(async (value) => { this.properties[propertyIndex].customType = value; // Update the customType of the specific property diff --git a/src/upload/upoload_custom/Upload2NotionCustom.ts b/src/upload/upoload_custom/Upload2NotionCustom.ts index 5e6b6fc..b1a68c3 100644 --- a/src/upload/upoload_custom/Upload2NotionCustom.ts +++ b/src/upload/upoload_custom/Upload2NotionCustom.ts @@ -159,6 +159,44 @@ export class Upload2NotionCustom extends UploadBaseCustom { start: value || new Date().toISOString(), }, }; + case "number": + return { + number: Number(value), + }; + case "phone_number": + return { + phone_number: value, + }; + case "email": + return { + email: value, + }; + case "url": + return { + url: value, + }; + case "files": + return { + files: Array.isArray(value) ? value.map(url => ({ + name: url, + type: "external", + external: { + url: url, + }, + })) : [ + { + name: value, + type: "external", + external: { + url: value, + }, + }, + ], + }; + case "checkbox": + return { + checkbox: Boolean(value) || false, + }; case "select": return { select: { From 8248640b5fd7c67a31c8616790737312bae10032 Mon Sep 17 00:00:00 2001 From: Jiaxin Peng Date: Mon, 29 Jan 2024 11:55:52 +0000 Subject: [PATCH 6/6] fix the extra argument in the uploadcommand --- src/upload/uploadCommand.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/upload/uploadCommand.ts b/src/upload/uploadCommand.ts index a9b8235..78c5be0 100644 --- a/src/upload/uploadCommand.ts +++ b/src/upload/uploadCommand.ts @@ -113,7 +113,7 @@ export async function uploadCommandCustom( return; } - const {markDownData, nowFile, cover, customValues} = await getNowFileMarkdownContentCustom(app, dbDetails, settings) + const {markDownData, nowFile, cover, customValues} = await getNowFileMarkdownContentCustom(app, dbDetails) if (markDownData) { const { basename} = nowFile;