Compare commits

..

13 Commits

Author SHA1 Message Date
Jiaxin Peng
d7372c7c55 Improve preview function for customised database 2024-07-03 16:05:24 +01:00
Jiaxin Peng
f7bcf71020 create retrieve function to get all created properties for customised database 2024-07-03 14:26:02 +01:00
Jiaxin Peng
72146afe48 update settingModal.ts refactor the customise database and improve the creating logic 2024-07-03 13:39:56 +01:00
Jiaxin Peng
9bcdb42edb settingmodal save mapping for reference 2024-07-03 11:06:54 +01:00
Jiaxin Peng
16e0827991 update the basic function of edit modal 2024-07-03 08:47:33 +01:00
Jiaxin Peng
863a6fb0dc more clear logic customised database setting code 2024-07-02 23:56:35 +01:00
Jiaxin Peng
5799ffe79b Update custom function and adjust the custom interface ui 2024-07-02 23:48:37 +01:00
Jiaxin Peng
a8ebab7fcb change tags titleicon and summary to optional function in next database 2024-03-17 14:36:55 +00:00
Jiaxin Peng
e0ec27ad07 update readme 2024-03-12 22:04:34 +00:00
Jiaxin Peng
85220105b0 update README 2024-03-08 15:23:17 +00:00
Jiaxin Peng
9afdb24a82 typo 2024-02-26 11:57:28 +00:00
Jiaxin Peng
3c7ab13995 update readme 2024-02-26 11:53:02 +00:00
Jiaxin Peng
31b72f3bd3 Update version to 2.2.4 2024-02-19 23:08:47 +00:00
12 changed files with 402 additions and 323 deletions

View File

@@ -1,5 +1,5 @@
# Changelog v2.2.3
- Update NotionNext function that
- `tags`, `titleicon`, `slug` and `summary` are now optional. You can remove them from the frontmatter if you don't need them.
## Bug Fixes
- Fix a bug that 'text' property cannot be synchronized. 修复了一个无法同步'text'属性的bug。
- 更新 NotionNext 同步功能
- `tags`, `titleicon`, `slug``summary` 现在不是必选项了。你可以从你的模板中删除这些字段。

View File

@@ -3,7 +3,7 @@
[![Test](https://github.com/jxpeng98/obsidian-to-NotionNext/actions/workflows/test.yml/badge.svg)](https://github.com/jxpeng98/obsidian-to-NotionNext/actions/workflows/test.yml)
[![Release](https://github.com/jxpeng98/obsidian-to-NotionNext/actions/workflows/release.yml/badge.svg)](https://github.com/jxpeng98/obsidian-to-NotionNext/actions/workflows/release.yml)
[![Obsidian Downloads](https://img.shields.io/badge/dynamic/json?logo=obsidian&color=%23483699&label=downloads&query=%24%5B%22share-to-notionnext%22%5D.downloads&url=https%3A%2F%2Fraw.githubusercontent.com%2Fobsidianmd%2Fobsidian-releases%2Fmaster%2Fcommunity-plugin-stats.json)](https://GitHub.com/jxpeng98/obsidian-to-NotionNext/releases/)
[![GitHub release (with filter)](https://img.shields.io/github/v/release/jxpeng98/obsidian-to-NotionNext)](https://github.com/jxpeng98/obsidian-to-NotionNext/releases/)
[![GitHub release (with filter)](https://img.shields.io/github/package-json/v/jxpeng98/obsidian-to-NotionNext)](https://github.com/jxpeng98/obsidian-to-NotionNext/releases/)
[//]: # ([![Github all releases](https://img.shields.io/github/downloads/jxpeng98/obsidian-to-NotionNext/total.svg)](https://GitHub.com/jxpeng98/obsidian-to-NotionNext/releases/))
@@ -22,7 +22,69 @@
- [x] Support preview for database details in plugin settings. 支持预览数据库详情
- [x] Support edit for database details in plugin settings. 支持编辑数据库详情
## Update
## How to use
You need seven steps to use this plugin in your Obsidian.
1. Create a database in your Notion workspace.
Open Notion, clink the `+` button on the left side, and 'Add a page' -> select 'Table' -> 'New database'.
2. On the right-top corner, click the 'Share' -> 'Publish' -> 'Publish' -> copy the database id from the URL.
3. go to [Notion API](https://www.notion.com/my-integrations) to create a new integration, and copy the token.
4. Go back to your created Notion database, click the right-top '...' -> connections -> connect to -> find the integration you created and connect it.
5. Go to obsidian settings -> community plugins -> search 'NotionNext' -> install it.
6. Create a database in the plugin settings, and fill in the database details and all properties you want to sync (**Note: the name of the properties is case-sensitive.**).
- There are three type of database that you can use:
- NotionNext: the database for the NotionNext template.(**All the properties are in lowercase**)
- General: the database for the general Notion database (**Only have `title` and `tags` columns**)
- Custom: the database for the custom properties (You can customise the properties you want to sync)
7. Create a new note in Obsidian, and fill in the frontmatter with the properties you want to sync.
## 使用方法
如果你想使用这个插件,你需要完成下边的七个步骤。
1. 首先在你的Notion中创建一个数据库。
2. 点击右上角的'分享' -> '发布' -> '发布' -> 然后复制URL中的数据库ID。(版本不同可能id的形式也不同。只需要复制在之前的纯数字部分应该就可以了)
3. 去[Notion API](https://www.notion.com/my-integrations)创建一个新的API然后复制token。
4. 回到你创建的Notion数据库点击右上角的'...' -> 连接 -> 连接到 -> 把你刚才创建的API绑定到你的数据库
5. 回到Obsidian的设置 -> 社区插件 -> 搜索'NotionNext' -> 安装
6. 在插件设置中创建一个数据库,然后填写数据库的详情和你想要同步的属性 (**注意Notion会识别表头的大小写一定要和notion中的表头保持大小写一致**)。
- 你可以使用三种类型的数据库:
- NotionNext: 用于NotionNext模板的数据库。(**默认全部小写**)
- General: 用于普通的Notion数据库**只有`title``tags`两个属性**
- Custom: 用于自定义属性的数据库(你可以自定义你想要同步的属性)
7. 在Obsidian中创建一个新的笔记然后在frontmatter中写入你想要的属性。
## Example
```plain
---
# default value has been set.
# for any unwanted value, you can delete it or set it to empty.
# for example, if you donot want to set password, you can delete password: "1234" or set it to password: ""
# 我已经在插件中设置了默认值,如果有不需要的选项,可以直接删除。
# 例如你不需要密码选项你可以将password: "1234"删除,或者将它设置为空。
# !!!!!!!!!!!!
# 现在阶段一定不要修改表头的名字, please do not change the name of the header in YAML front matter
# !!!!!!!!!!!!
titleicon: 📎 # emoji icon, default is 📜, 默认是📜
date: 2023-07-23 # default is today 默认是今天。 Format is YYYY-MM-DD 格式是YYYY-MM-DD
coverurl: https://img.jxpeng.dev/2023/08/843e27a210847f05a0f7cfb121fec100.jpg # default is empty 默认是空
type: Post # Post or Page, default is Post 默认是Post
slug: test # slug for url, default is empty 默认是空
status: Draft # Draft, Invisible, Published, default is Draft 默认是Draft
category: test # default is 'Obsidian' 默认是'Obsidian'
summary: this is a summary for test post # default is empty 默认是空
icon: fa-solid fa-camera # you can ignore this, default is empty 默认是空,可直接删除
password: "1234" # if you donot want to set password, you can delete this line, default is empty 默认是空,可直接删除
# 现在必须开启tags选项否则会报错
tags:
- test # tags for post
- web # add more tags if you want
---
```
<details> <summary> Update </summary>
### 2.2.5
- Update NotionNext function that
- `tags`, `titleicon`, `slug` and `summary` are now optional. You can remove them from the frontmatter if you don't need them.
### 2.2.3
@@ -55,6 +117,8 @@
- [x] 'Phone'
- [x] 'File' (**Only support external embedded files**)
</details>
![](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)
@@ -69,7 +133,8 @@ Thus, based on the [original author's work](https://github.com/EasyChris/obsidia
---
## Archive Update
<details> <summary> Archive Update </summary>
### 2.1.0
- add confirmation interface for deleting a database 增加删除数据库的确认界面
@@ -206,7 +271,9 @@ If you turn off the button for the NotionNext database, you won't see the option
- [x] Removed the `convert tag` option. Now, you can directly add tags in the YAML front matter. If you don't want to add tags, you can delete the tags in the YAML front matter or leave the tags blank.
## How to Use
</details>
<details> <summary> Previous How to Use </summary>
### Precautions
@@ -298,9 +365,11 @@ Usage of the template is as follows:
**Plugin preview is shown below**
![](https://minioapi.pjx.ac.cn/img1/2023/09/d6199619b68fab218fca8ae0cebece78.gif)
</details>
---
**Original README.md**
<details> <summary> Original README.md </summary>
Many Thanks for the original author's work. I've only made some changes to the original author's work. If you find this plugin useful, please give the [original author](https://github.com/EasyChris/obsidian-to-notion) a star.
@@ -474,10 +543,6 @@ node update-version.js
./release.sh
```
```
# Thanks
[Development Process | Obsidian Plugin Development Documentation](https://luhaifeng666.github.io/obsidian-plugin-docs-zh/zh/getting-started/development-workflow.html)
@@ -494,3 +559,6 @@ node update-version.js
# License
GNU GPLv3
</details>

View File

@@ -1,7 +1,7 @@
{
"id": "share-to-notionnext",
"name": "Share to NotionNext",
"version": "2.2.3",
"version": "2.2.5",
"minAppVersion": "0.0.1",
"description": "Shares obsidian md file to notion with notion api for NotionNext web deploy, originally created by EasyChris/obsidian-to-notion.",
"author": "EasyChris, jxpeng98",

View File

@@ -12,7 +12,7 @@ date: 2023-07-23 # default is today 默认是今天。 Format is YYYY-MM-DD
coverurl: https://img.jxpeng.dev/2023/08/843e27a210847f05a0f7cfb121fec100.jpg # default is empty 默认是空
type: Post # Post or Page, default is Post 默认是Post
slug: test # slug for url, default is empty 默认是空
stats: Draft # Draft, Invisible, Published, default is Draft 默认是Draft
status: Draft # Draft, Invisible, Published, default is Draft 默认是Draft
category: test # default is 'Obsidian' 默认是'Obsidian'
summary: this is a summary for test post # default is empty 默认是空
icon: fa-solid fa-camera # you can ignore this, default is empty 默认是空,可直接删除

View File

@@ -1,6 +1,6 @@
{
"name": "share-to-notionnext",
"version": "2.2.3",
"version": "2.2.5",
"type": "module",
"description": "Shares obsidian md file to notion with notion api for NotionNext web deploy, originally created by EasyChris/obsidian-to-notion.",
"main": "main.js",

View File

@@ -1,162 +0,0 @@
import {App, Modal, Setting} from "obsidian";
import ObsidianSyncNotionPlugin from "../main";
import {ObsidianSettingTab} from "./settingTabs";
import {i18nConfig} from "../lang/I18n";
export class CustomModal extends Modal {
propertyLines: Setting[] = []; // Store all property line settings
properties: { customName: 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({customName: "", customType: ""}); // Initialize with empty values
const propertyLine = new Setting(containerEl)
if (propertyIndex === 0) {
propertyLine
.setName(i18nConfig.CustomPropertyFirstColumn)
.setDesc(i18nConfig.CustomPropertyFirstColumnDesc)
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(i18nConfig.CustomProperty + (propertyIndex))
propertyLine.addText((text) => {
text
.setPlaceholder(i18nConfig.CustomPropertyName)
.setValue("")
.onChange(async (value) => {
this.properties[propertyIndex].customName = value; // Update the customValue of the specific property
});
}
)
propertyLine.addDropdown((dropdown) => {
dropdown
// .addOption("none", '')
.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("")
.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(i18nConfig.AddCustomProperty);
let {contentEl} = this;
contentEl.empty();
const customDiv = contentEl.createDiv("custom-div");
new Setting(customDiv)
.setName(i18nConfig.AddNewProperty)
.setDesc(i18nConfig.AddNewPropertyDesc)
.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();
}
}

View File

@@ -3,9 +3,12 @@ import {SettingModal} from "./settingModal";
import ObsidianSyncNotionPlugin from "../main";
import {DatabaseDetails, ObsidianSettingTab} from "./settingTabs";
import {i18nConfig} from "../lang/I18n";
import {CustomModal} from "./CustomModal";
import {customProperty} from "./settingModal";
export class EditModal extends SettingModal {
propertyLines: Setting[] = []; // Store all property line settings
properties: { customName: string, customType: string , index: number}[] = []; // Array to store property values and types
[key: string]: any; // Index signature
dataTemp: Record<string, any> = {
databaseFormatTemp: '',
// databaseFormatTempInd: false,
@@ -244,22 +247,101 @@ export class EditModal extends SettingModal {
.setTooltip('Add new property')
.setIcon('plus')
.onClick(async () => {
let customModal = new CustomModal(this.app);
const customTabs = nextTabs.createDiv("custom-tabs");
this.createPropertyLine(customTabs);
customModal.onClose = () => {
this.renderCustomPreview(customModal.properties, nextTabs)
this.dataTemp.customPropertiesTemp = customModal.properties;
}
customModal.open();
});
}
);
const retrieveTabs = nextTabs.createDiv("retrieve-tabs");
this.retrievePropertyLine(retrieveTabs, this.dataTemp.customPropertiesTemp)
}
}
retrievePropertyLine(containerEl: HTMLElement, properties: customProperty[]): void {
const propertyIndex = properties.length;
console.log(propertyIndex, "have been created");
this.properties.forEach((property, index) => {
const propertyLine = new Setting(containerEl)
.setName(propertyIndex === 0 ? i18nConfig.CustomPropertyFirstColumn : `${i18nConfig.CustomProperty} ${propertyIndex}`)
.setDesc(propertyIndex === 0 ? i18nConfig.CustomPropertyFirstColumnDesc : "");
propertyLine.addText(text => {
text.setPlaceholder(i18nConfig.CustomPropertyName)
.setValue("")
.onChange(value => {
let actualIndex = properties.findIndex(p => p.index === propertyIndex);
if (actualIndex !== -1) {
properties[actualIndex].customName = value;
}
});
});
propertyLine.addDropdown((dropdown) => {
const options: Record<string, string> = {
'text': 'Text',
'number': 'Number',
'select': 'Select',
'multi_select': 'Multi-Select',
'date': 'Date',
'files': 'Files & Media',
'checkbox': 'Checkbox',
'url': 'URL',
'email': 'Email',
'phone_number': 'Phone Number',
// 'formula': 'Formula',
// 'relation': 'Relation',
// 'rollup': 'Rollup',
// 'created_time': 'Created time',
// 'created_by': 'Created by',
// 'last_edited_time': 'Last Edited Time',
// 'last_edited_by': 'Last Edited By',
};
// Use a reference to the current property object
const currentProperty = properties[propertyIndex];
if (propertyIndex === 0) {
dropdown.addOption("title", "Title");
} else {
Object.keys(options).forEach(key => {
dropdown.addOption(key, options[key]);
});
}
dropdown.setValue("")
.onChange(value => {
if (currentProperty) {
currentProperty.customType = value;
// Retrieve the index of currentProperty from the properties array
const updatedIndex = properties.findIndex(p => p === currentProperty);
console.log(`Updated value at index ${updatedIndex}: ${value}`);
} else {
console.log("Property not found, may have been deleted.");
}
});
});
if (propertyIndex > 0) {
propertyLine.addButton(button => {
return button
.setTooltip("Delete")
.setIcon("trash")
.onClick(() => {
this.deleteProperty(propertyIndex);
});
});
}
});
}
createStyleDiv(className: string, commandValue: boolean = false, parentEl: HTMLElement): HTMLDivElement {
return super.createStyleDiv(className, commandValue, parentEl);

View File

@@ -1,6 +1,8 @@
import {App, ExtraButtonComponent, Modal, Notice, Setting} from "obsidian";
import ObsidianSyncNotionPlugin from "../main";
import {DatabaseDetails, ObsidianSettingTab} from "./settingTabs";
import {customProperty} from "./settingModal";
import {i18nConfig} from "../lang/I18n";
export class PreviewModal extends Modal {
plugin: ObsidianSyncNotionPlugin;
@@ -120,12 +122,10 @@ export class PreviewModal extends Modal {
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));
const customPrv = previewEl.createDiv("custom-tabs");
this.previewPropertyLine(previewEl, this.dbDetails.customProperties);
}
}
@@ -136,4 +136,44 @@ export class PreviewModal extends Modal {
}
previewPropertyLine(containerEl: HTMLElement, properties: customProperty[]): void {
properties.forEach((property, index) => {
const propertyLine = new Setting(containerEl)
.setName(index === 0 ? i18nConfig.CustomPropertyFirstColumn : `${i18nConfig.CustomProperty} ${index}`)
.setDesc(index === 0 ? i18nConfig.CustomPropertyFirstColumnDesc : "");
propertyLine.addText(text => {
text.setPlaceholder(i18nConfig.CustomPropertyName)
.setValue(property.customName)
.setDisabled(true);
});
propertyLine.addDropdown((dropdown) => {
const options: Record<string, string> = {
'title': 'Title',
'text': 'Text',
'number': 'Number',
'select': 'Select',
'multi_select': 'Multi-Select',
'date': 'Date',
'files': 'Files & Media',
'checkbox': 'Checkbox',
'url': 'URL',
'email': 'Email',
'phone_number': 'Phone Number',
// Additional options can be added here
};
// Populate dropdown with options
Object.keys(options).forEach(key => {
dropdown.addOption(key, options[key]);
});
dropdown.setValue(property.customType)
.setDisabled(true); // Disable dropdown to prevent changes
});
});
}
}

View File

@@ -8,10 +8,12 @@ import {
import {i18nConfig} from "../lang/I18n";
import ObsidianSyncNotionPlugin from "../main";
import {DatabaseDetails, ObsidianSettingTab} from "./settingTabs";
import {CustomModal} from "./CustomModal";
// import {CustomModal} from "./CustomModal";
export class SettingModal extends Modal {
propertyLines: Setting[] = []; // Store all property line settings
properties: { customName: string, customType: string , index: number}[] = []; // Array to store property values and types
[key: string]: any; // Index signature
data: Record<string, any> = {
databaseFormat: 'none',
@@ -47,7 +49,6 @@ export class SettingModal extends Modal {
// this.data.customValues = dbDetails.customValues;
this.data.saved = dbDetails.saved;
}
}
display(): void {
@@ -62,48 +63,26 @@ export class SettingModal extends Modal {
const nextTabs = contentEl.createDiv('next-tabs');
if (this.data.saved) {
new Setting(settingDiv)
.setName(i18nConfig.databaseFormat)
.setDesc(i18nConfig.databaseFormatDesc)
.addDropdown((component) => {
component
.addOption('none', '')
.addOption('general', i18nConfig.databaseGeneral)
.addOption('next', i18nConfig.databaseNext)
.addOption('custom', i18nConfig.databaseCustom)
.setValue(this.data.databaseFormat)
.onChange(async (value) => {
this.data.databaseFormat = value;
nextTabs.empty();
this.updateContentBasedOnSelection(value, nextTabs);
});
new Setting(settingDiv)
.setName(i18nConfig.databaseFormat)
.setDesc(i18nConfig.databaseFormatDesc)
.addDropdown((component) => {
component
.addOption('none', '')
.addOption('general', i18nConfig.databaseGeneral)
.addOption('next', i18nConfig.databaseNext)
.addOption('custom', i18nConfig.databaseCustom)
.setValue(this.data.databaseFormat)
.onChange(async (value) => {
this.data.databaseFormat = value;
nextTabs.empty();
this.updateContentBasedOnSelection(value, nextTabs);
});
// Initialize content based on the current dropdown value
this.updateContentBasedOnSelection(this.data.databaseFormat, nextTabs);
});
// Initialize content based on the current dropdown value
(this.data.saved) ? this.updateContentBasedOnSelection(this.data.databaseFormat, nextTabs) : this.updateContentBasedOnSelection(this.data.databaseFormat, nextTabs);
} else {
new Setting(settingDiv)
.setName(i18nConfig.databaseFormat)
.setDesc(i18nConfig.databaseFormatDesc)
.addDropdown((component) => {
component
.addOption('none', '')
.addOption('general', i18nConfig.databaseGeneral)
.addOption('next', i18nConfig.databaseNext)
.addOption('custom', i18nConfig.databaseCustom)
.setValue(this.data.databaseFormat)
.onChange(async (value) => {
this.data.databaseFormat = value;
nextTabs.empty();
this.updateContentBasedOnSelection(value, nextTabs);
});
// Initialize content based on the current dropdown value
this.updateContentBasedOnSelection(this.plugin.settings.databaseFormat, nextTabs);
});
}
});
// add save button
@@ -115,6 +94,7 @@ export class SettingModal extends Modal {
.setIcon('checkmark')
.onClick(async () => {
this.data.saved = true;
this.data.customProperties = this.properties;
this.close();
});
}
@@ -125,6 +105,7 @@ export class SettingModal extends Modal {
.setIcon('cross')
.onClick(() => {
this.data.saved = false;
this.data.customProperties = this.properties;
this.close();
});
}
@@ -161,10 +142,6 @@ export class SettingModal extends Modal {
this.updateSettingEl(CustomNameEl, value)
// this.updateSettingEl(CustomValuesEl, value)
// await this.plugin.saveSettings();
// await this.plugin.commands.updateCommand();
})
);
@@ -223,15 +200,8 @@ export class SettingModal extends Modal {
.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();
const customTabs = nextTabs.createDiv("custom-tabs");
this.createPropertyLine(customTabs);
});
}
);
@@ -245,16 +215,113 @@ export class SettingModal extends Modal {
this.display()
}
renderCustomPreview(properties: any[], nextTabs: HTMLElement) {
const previewContainer = nextTabs.createDiv('preview-container');
createPropertyLine(containerEl: HTMLElement): void {
const propertyIndex = this.properties.length;
properties.forEach((property: { customName: any; customType: any; }) => {
const propertyEl = previewContainer.createEl('div', {cls: 'property-preview'});
propertyEl.createEl('span', {text: `Property: ${property.customName}, Type: ${property.customType}`});
this.properties.push({customName: "", customType: "", index: propertyIndex});
console.log(this.properties[propertyIndex].index);
const propertyLine = new Setting(containerEl)
.setName(propertyIndex === 0 ? i18nConfig.CustomPropertyFirstColumn : `${i18nConfig.CustomProperty} ${propertyIndex}`)
.setDesc(propertyIndex === 0 ? i18nConfig.CustomPropertyFirstColumnDesc : "");
propertyLine.addText(text => {
text.setPlaceholder(i18nConfig.CustomPropertyName)
.setValue("")
.onChange(value => {
let actualIndex = this.properties.findIndex(p => p.index === propertyIndex);
if (actualIndex !== -1) {
this.properties[actualIndex].customName = value;
}
});
});
propertyLine.addDropdown((dropdown) => {
const options: Record<string, string> = {
'text': 'Text',
'number': 'Number',
'select': 'Select',
'multi_select': 'Multi-Select',
'date': 'Date',
'files': 'Files & Media',
'checkbox': 'Checkbox',
'url': 'URL',
'email': 'Email',
'phone_number': 'Phone Number',
// 'formula': 'Formula',
// 'relation': 'Relation',
// 'rollup': 'Rollup',
// 'created_time': 'Created time',
// 'created_by': 'Created by',
// 'last_edited_time': 'Last Edited Time',
// 'last_edited_by': 'Last Edited By',
};
// Use a reference to the current property object
const currentProperty = this.properties[propertyIndex];
if (propertyIndex === 0) {
dropdown.addOption("title", "Title");
} else {
Object.keys(options).forEach(key => {
dropdown.addOption(key, options[key]);
});
}
dropdown.setValue("")
.onChange(value => {
if (currentProperty) {
currentProperty.customType = value;
// Retrieve the index of currentProperty from the properties array
const updatedIndex = this.properties.findIndex(p => p === currentProperty);
console.log(`Updated value at index ${updatedIndex}: ${value}`);
} else {
console.log("Property not found, may have been deleted.");
}
});
});
if (propertyIndex > 0) {
propertyLine.addButton(button => {
return button
.setTooltip("Delete")
.setIcon("trash")
.onClick(() => {
this.deleteProperty(propertyIndex);
});
});
}
this.propertyLines.push(propertyLine);
}
deleteProperty(propertyIndex: number) {
let actualIndex = this.properties.findIndex(p => p.index === propertyIndex);
if (actualIndex !== -1) {
this.properties.splice(actualIndex, 1);
this.propertyLines[actualIndex].settingEl.remove();
this.propertyLines.splice(actualIndex, 1);
// Update indices in the properties array
this.properties.forEach((prop, idx) => {
prop.index = idx;
});
this.updatePropertyLines();
console.log("Updated indices after deletion:");
this.properties.forEach((prop, idx) => {
console.log(`Index ${idx}: ${prop.index}`);
});
}
}
updatePropertyLines() {
this.propertyLines.forEach((line, idx) => {
line.setName(idx === 0 ? i18nConfig.CustomPropertyFirstColumn : `${i18nConfig.CustomProperty} ${idx}`);
});
}
// create a function to create a div with a style for pop over elements
public createStyleDiv(className: string, commandValue: boolean = false, parentEl: HTMLElement) {

View File

@@ -88,9 +88,6 @@ export class Upload2NotionNext extends UploadBaseNext {
parent: {
database_id: databaseID,
},
icon: {
emoji: emoji || '📜'
},
properties: {
title: {
title: [
@@ -101,25 +98,11 @@ export class Upload2NotionNext extends UploadBaseNext {
},
],
},
tags: {
multi_select: tags && true ? tags.map(tag => {
return { "name": tag }
}) : [],
},
type: {
select: {
name: type || 'Post'
}
},
slug: {
rich_text: [
{
text: {
content: slug || ''
}
}
]
},
status: {
select: {
name: stats || 'Draft'
@@ -130,15 +113,7 @@ export class Upload2NotionNext extends UploadBaseNext {
name: category || 'Obsidian'
}
},
summary: {
rich_text: [
{
text: {
content: summary || ''
}
}
]
},
password: {
rich_text: [
{
@@ -165,6 +140,52 @@ export class Upload2NotionNext extends UploadBaseNext {
},
children: childArr,
}
// add tags
if (tags) {
bodyString.properties.tags = {
multi_select: tags.map(tag => {
return { "name": tag }
})
}
}
// add title icon
if (emoji) {
bodyString.icon = {
emoji: emoji
}
}
// add slug
if (slug) {
bodyString.properties.slug = {
rich_text: [
{
text: {
content: slug
}
}
]
}
}
// check if summary is available
if (summary) {
bodyString.properties.summary = {
rich_text: [
{
text: {
content: summary
}
}
]
}
}
if (cover) {
bodyString.cover = {
type: "external",

View File

@@ -50,46 +50,4 @@ export class UploadBaseCustom {
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}`)
// // }
// }
}

View File

@@ -71,6 +71,8 @@ export class Upload2NotionCustom extends UploadBaseCustom {
};
}
console.log(bodyString)
try {
return await requestUrl({
url: `https://api.notion.com/v1/pages`,
@@ -218,11 +220,15 @@ export class Upload2NotionCustom extends UploadBaseCustom {
const properties: { [key: string]: any } = {};
// Only include custom properties that have values
customProperties.forEach(({customName, customType}) => {
if (customValues[customName] !== undefined) {
properties[customName] = this.buildPropertyObject(customName, customType, customValues);
}
}
);
console.log(properties)
return {
parent: {
@@ -233,5 +239,4 @@ export class Upload2NotionCustom extends UploadBaseCustom {
};
}
}