notes-to-strapi-export-article-ai 1.0.119 → 3.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc +30 -22
- package/README.md +98 -143
- package/images/img.png +0 -0
- package/images/img_1.png +0 -0
- package/images/img_10.png +0 -0
- package/images/img_11.png +0 -0
- package/images/img_12.png +0 -0
- package/images/img_13.png +0 -0
- package/images/img_2.png +0 -0
- package/images/img_3.png +0 -0
- package/images/img_4.png +0 -0
- package/images/img_5.png +0 -0
- package/images/img_6.png +0 -0
- package/images/img_7.png +0 -0
- package/images/img_8.png +0 -0
- package/images/img_9.png +0 -0
- package/manifest.json +2 -2
- package/package.json +29 -26
- package/src/components/APIKeys.ts +219 -0
- package/src/components/Configuration.ts +663 -0
- package/src/components/Dashboard.ts +184 -0
- package/src/components/ImageSelectionModal.ts +58 -0
- package/src/components/Routes.ts +279 -0
- package/src/constants.ts +22 -61
- package/src/main.ts +177 -34
- package/src/services/configuration-generator.ts +172 -0
- package/src/services/field-analyzer.ts +84 -0
- package/src/services/frontmatter.ts +329 -0
- package/src/services/strapi-export.ts +436 -0
- package/src/settings/UnifiedSettingsTab.ts +206 -0
- package/src/types/image.ts +27 -16
- package/src/types/index.ts +3 -0
- package/src/types/route.ts +51 -0
- package/src/types/settings.ts +22 -23
- package/src/utils/analyse-file.ts +94 -0
- package/src/utils/debounce.ts +34 -0
- package/src/utils/image-processor.ts +124 -400
- package/src/utils/preview-modal.ts +265 -0
- package/src/utils/process-file.ts +122 -0
- package/src/utils/strapi-uploader.ts +120 -119
- package/src/settings.ts +0 -404
- package/src/types/article.ts +0 -8
- package/src/utils/openai-generator.ts +0 -139
- package/src/utils/validators.ts +0 -8
- package/version-bump.mjs +0 -14
- package/versions.json +0 -119
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { Setting, Notice } from 'obsidian'
|
|
2
|
+
import StrapiExporterPlugin from '../main'
|
|
3
|
+
|
|
4
|
+
interface ConfigStatus {
|
|
5
|
+
key: string
|
|
6
|
+
status: boolean
|
|
7
|
+
description: string
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
interface QuickLink {
|
|
11
|
+
name: string
|
|
12
|
+
description: string
|
|
13
|
+
targetTab: string
|
|
14
|
+
icon?: string
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export class Dashboard {
|
|
18
|
+
private plugin: StrapiExporterPlugin
|
|
19
|
+
private containerEl: HTMLElement
|
|
20
|
+
|
|
21
|
+
constructor(plugin: StrapiExporterPlugin, containerEl: HTMLElement) {
|
|
22
|
+
this.plugin = plugin
|
|
23
|
+
this.containerEl = containerEl
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
display(): void {
|
|
27
|
+
try {
|
|
28
|
+
const { containerEl } = this
|
|
29
|
+
containerEl.empty()
|
|
30
|
+
|
|
31
|
+
this.createHeader()
|
|
32
|
+
this.addSummary()
|
|
33
|
+
this.addQuickLinks()
|
|
34
|
+
} catch (error) {
|
|
35
|
+
new Notice('Error displaying dashboard' + error.message)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
private createHeader(): void {
|
|
40
|
+
const headerEl = this.containerEl.createEl('div', {
|
|
41
|
+
cls: 'dashboard-header',
|
|
42
|
+
})
|
|
43
|
+
headerEl.createEl('h2', {
|
|
44
|
+
text: 'Strapi Exporter Dashboard',
|
|
45
|
+
cls: 'dashboard-title',
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
headerEl.createEl('p', {
|
|
49
|
+
text: 'Overview of your Strapi export configuration and quick access to settings.',
|
|
50
|
+
cls: 'dashboard-description',
|
|
51
|
+
})
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
private addSummary(): void {
|
|
55
|
+
const summaryEl = this.containerEl.createEl('div', {
|
|
56
|
+
cls: 'dashboard-summary',
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
const configStatus = this.getConfigurationStatus()
|
|
60
|
+
summaryEl.createEl('h3', {
|
|
61
|
+
text: 'Configuration Status',
|
|
62
|
+
cls: 'dashboard-section-title',
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
this.createStatusList(summaryEl, configStatus)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
private createStatusList(
|
|
69
|
+
container: HTMLElement,
|
|
70
|
+
statuses: ConfigStatus[]
|
|
71
|
+
): void {
|
|
72
|
+
const statusList = container.createEl('ul', { cls: 'status-list' })
|
|
73
|
+
|
|
74
|
+
statuses.forEach(({ key, status, description }) => {
|
|
75
|
+
const listItem = statusList.createEl('li', { cls: 'status-item' })
|
|
76
|
+
|
|
77
|
+
// Status icon
|
|
78
|
+
listItem.createSpan({
|
|
79
|
+
text: status ? '✅ ' : '❌ ',
|
|
80
|
+
cls: `status-icon ${status ? 'status-ok' : 'status-error'}`,
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
// Status text
|
|
84
|
+
const textContainer = listItem.createSpan({ cls: 'status-text' })
|
|
85
|
+
textContainer.createSpan({ text: key, cls: 'status-key' })
|
|
86
|
+
textContainer.createSpan({ text: description, cls: 'status-description' })
|
|
87
|
+
})
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
private addQuickLinks(): void {
|
|
91
|
+
const quickLinksEl = this.containerEl.createEl('div', {
|
|
92
|
+
cls: 'dashboard-quick-links',
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
quickLinksEl.createEl('h3', {
|
|
96
|
+
text: 'Quick Links',
|
|
97
|
+
cls: 'dashboard-section-title',
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
this.quickLinks.forEach(link => {
|
|
101
|
+
this.createQuickLink(quickLinksEl, link)
|
|
102
|
+
})
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
private createQuickLink(container: HTMLElement, link: QuickLink): void {
|
|
106
|
+
new Setting(container)
|
|
107
|
+
.setName(link.name)
|
|
108
|
+
.setDesc(link.description)
|
|
109
|
+
.addButton(button => {
|
|
110
|
+
button
|
|
111
|
+
.setButtonText(`Go to ${link.name}`)
|
|
112
|
+
.setCta()
|
|
113
|
+
.onClick(() => {
|
|
114
|
+
this.navigateToTab(link.targetTab)
|
|
115
|
+
})
|
|
116
|
+
})
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
private navigateToTab(tab: string): void {
|
|
120
|
+
try {
|
|
121
|
+
this.plugin.settings.currentTab = tab
|
|
122
|
+
this.plugin.settingsTab.display()
|
|
123
|
+
} catch (error) {
|
|
124
|
+
new Notice(`Failed to navigate to ${tab}` + error.message)
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
private getConfigurationStatus(): ConfigStatus[] {
|
|
129
|
+
const { settings } = this.plugin
|
|
130
|
+
return [
|
|
131
|
+
{
|
|
132
|
+
key: 'Strapi URL',
|
|
133
|
+
status: !!settings.strapiUrl,
|
|
134
|
+
description: 'Connection to your Strapi instance',
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
key: 'Strapi API Token',
|
|
138
|
+
status: !!settings.strapiApiToken,
|
|
139
|
+
description: 'Authentication token for Strapi API',
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
key: 'ForVoyez API Key',
|
|
143
|
+
status: !!settings.forvoyezApiKey,
|
|
144
|
+
description: 'API key for ForVoyez integration',
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
key: 'OpenAI API Key',
|
|
148
|
+
status: !!settings.openaiApiKey,
|
|
149
|
+
description: 'API key for AI-powered features',
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
key: 'Schema Configured',
|
|
153
|
+
status: settings.routes.some(route => !!route.schema),
|
|
154
|
+
description: 'Strapi schema configuration',
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
key: 'Routes Configured',
|
|
158
|
+
status: settings.routes.length > 0,
|
|
159
|
+
description: 'Export route configuration',
|
|
160
|
+
},
|
|
161
|
+
]
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
private readonly quickLinks: QuickLink[] = [
|
|
165
|
+
{
|
|
166
|
+
name: 'Configuration',
|
|
167
|
+
description: 'Set up your Strapi schema and field mappings',
|
|
168
|
+
targetTab: 'configuration',
|
|
169
|
+
icon: 'settings',
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
name: 'API Keys',
|
|
173
|
+
description: 'Configure your API keys',
|
|
174
|
+
targetTab: 'apiKeys',
|
|
175
|
+
icon: 'key',
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
name: 'Routes',
|
|
179
|
+
description: 'Manage your export routes',
|
|
180
|
+
targetTab: 'routes',
|
|
181
|
+
icon: 'git-branch',
|
|
182
|
+
},
|
|
183
|
+
]
|
|
184
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { App, Modal, Setting } from 'obsidian'
|
|
2
|
+
|
|
3
|
+
export class ImageSelectionModal extends Modal {
|
|
4
|
+
private selectedImages: string[] = []
|
|
5
|
+
private onConfirm: (images: string[]) => void
|
|
6
|
+
private isMultiple: boolean
|
|
7
|
+
|
|
8
|
+
constructor(
|
|
9
|
+
app: App,
|
|
10
|
+
isMultiple: boolean,
|
|
11
|
+
onConfirm: (images: string[]) => void
|
|
12
|
+
) {
|
|
13
|
+
super(app)
|
|
14
|
+
this.isMultiple = isMultiple
|
|
15
|
+
this.onConfirm = onConfirm
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
onOpen() {
|
|
19
|
+
const { contentEl } = this
|
|
20
|
+
contentEl.empty()
|
|
21
|
+
|
|
22
|
+
contentEl.createEl('h2', {
|
|
23
|
+
text: this.isMultiple ? 'Select Images' : 'Select an Image',
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
new Setting(contentEl)
|
|
27
|
+
.setName('Image Selection')
|
|
28
|
+
.setDesc(
|
|
29
|
+
this.isMultiple ? 'Choose one or more images' : 'Choose an image'
|
|
30
|
+
)
|
|
31
|
+
.addButton(button =>
|
|
32
|
+
button
|
|
33
|
+
.setButtonText('Select Image(s)')
|
|
34
|
+
.onClick(() => this.openFilePicker())
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
new Setting(contentEl).addButton(button =>
|
|
38
|
+
button
|
|
39
|
+
.setButtonText('Confirm')
|
|
40
|
+
.setCta()
|
|
41
|
+
.onClick(() => {
|
|
42
|
+
this.close()
|
|
43
|
+
this.onConfirm(this.selectedImages)
|
|
44
|
+
})
|
|
45
|
+
)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
private async openFilePicker() {
|
|
49
|
+
// Implement file picking logic here
|
|
50
|
+
// This could use Obsidian's file suggestion API or a custom file browser
|
|
51
|
+
// Update this.selectedImages with the chosen file path(s)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
onClose() {
|
|
55
|
+
const { contentEl } = this
|
|
56
|
+
contentEl.empty()
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
import { Notice, Setting, TextComponent } from 'obsidian'
|
|
2
|
+
import StrapiExporterPlugin from '../main'
|
|
3
|
+
import { RouteConfig } from '../types'
|
|
4
|
+
|
|
5
|
+
interface RouteField {
|
|
6
|
+
name: string
|
|
7
|
+
description: string
|
|
8
|
+
type: 'text' | 'toggle'
|
|
9
|
+
key: keyof RouteConfig
|
|
10
|
+
placeholder?: string
|
|
11
|
+
icon?: string
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export class Routes {
|
|
15
|
+
private plugin: StrapiExporterPlugin
|
|
16
|
+
private containerEl: HTMLElement
|
|
17
|
+
|
|
18
|
+
private routeFields: RouteField[] = [
|
|
19
|
+
{
|
|
20
|
+
name: 'Name',
|
|
21
|
+
description: 'Enter a name for this route',
|
|
22
|
+
type: 'text',
|
|
23
|
+
key: 'name',
|
|
24
|
+
placeholder: 'My Export Route',
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
name: 'Icon',
|
|
28
|
+
description: 'Enter an icon name (e.g., "upload", "link", "star")',
|
|
29
|
+
type: 'text',
|
|
30
|
+
key: 'icon',
|
|
31
|
+
placeholder: 'upload',
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
name: 'URL',
|
|
35
|
+
description: 'Enter the Strapi API endpoint URL for this route',
|
|
36
|
+
type: 'text',
|
|
37
|
+
key: 'url',
|
|
38
|
+
placeholder: '/api/articles',
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
name: 'Subtitle',
|
|
42
|
+
description: 'Enter a brief subtitle for this route',
|
|
43
|
+
type: 'text',
|
|
44
|
+
key: 'subtitle',
|
|
45
|
+
placeholder: 'Export to articles collection',
|
|
46
|
+
},
|
|
47
|
+
]
|
|
48
|
+
|
|
49
|
+
constructor(plugin: StrapiExporterPlugin, containerEl: HTMLElement) {
|
|
50
|
+
this.plugin = plugin
|
|
51
|
+
this.containerEl = containerEl
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
display(): void {
|
|
55
|
+
const { containerEl } = this
|
|
56
|
+
containerEl.empty()
|
|
57
|
+
|
|
58
|
+
try {
|
|
59
|
+
this.createHeader()
|
|
60
|
+
this.createRoutesList()
|
|
61
|
+
this.addNewRouteButton()
|
|
62
|
+
} catch (error) {
|
|
63
|
+
this.showError('Failed to display routes configuration' + error.message)
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
private createHeader(): void {
|
|
68
|
+
const headerEl = this.containerEl.createEl('div', { cls: 'routes-header' })
|
|
69
|
+
|
|
70
|
+
headerEl.createEl('h2', {
|
|
71
|
+
text: 'Routes Configuration',
|
|
72
|
+
cls: 'routes-title',
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
headerEl.createEl('p', {
|
|
76
|
+
text: 'Configure export routes for different content types.',
|
|
77
|
+
cls: 'routes-description',
|
|
78
|
+
})
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
private createRoutesList(): void {
|
|
82
|
+
const routesContainer = this.containerEl.createDiv('routes-list')
|
|
83
|
+
|
|
84
|
+
this.plugin.settings.routes.forEach((route, index) => {
|
|
85
|
+
this.createRouteConfigSettings(route, index, routesContainer)
|
|
86
|
+
})
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
private createTextComponent(
|
|
90
|
+
text: TextComponent,
|
|
91
|
+
route: RouteConfig,
|
|
92
|
+
field: keyof RouteConfig
|
|
93
|
+
): TextComponent {
|
|
94
|
+
return text.setValue(route[field] as string).onChange(async value => {
|
|
95
|
+
try {
|
|
96
|
+
await this.updateRouteField(route, field, value)
|
|
97
|
+
} catch (error) {
|
|
98
|
+
this.showError(`Failed to update ${String(field)}` + error.message)
|
|
99
|
+
}
|
|
100
|
+
})
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
private createRouteConfigSettings(
|
|
104
|
+
route: RouteConfig,
|
|
105
|
+
index: number,
|
|
106
|
+
container: HTMLElement
|
|
107
|
+
): void {
|
|
108
|
+
try {
|
|
109
|
+
const routeEl = container.createEl('div', {
|
|
110
|
+
cls: 'route-config',
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
// Route header with toggle
|
|
114
|
+
this.createRouteHeader(routeEl, route, index)
|
|
115
|
+
|
|
116
|
+
// Route fields
|
|
117
|
+
this.routeFields.forEach(field => {
|
|
118
|
+
this.createRouteField(routeEl, route, field)
|
|
119
|
+
})
|
|
120
|
+
|
|
121
|
+
// Delete button
|
|
122
|
+
this.addDeleteButton(routeEl, index)
|
|
123
|
+
} catch (error) {
|
|
124
|
+
this.showError(
|
|
125
|
+
`Failed to create settings for route ${index + 1}` + error.message
|
|
126
|
+
)
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
private createRouteHeader(
|
|
131
|
+
routeEl: HTMLElement,
|
|
132
|
+
route: RouteConfig,
|
|
133
|
+
index: number
|
|
134
|
+
): void {
|
|
135
|
+
new Setting(routeEl)
|
|
136
|
+
.setName(`Route ${index + 1}: ${route.name}`)
|
|
137
|
+
.setDesc('Configure route settings')
|
|
138
|
+
.addToggle(toggle =>
|
|
139
|
+
toggle.setValue(route.enabled).onChange(async value => {
|
|
140
|
+
try {
|
|
141
|
+
await this.updateRouteEnabled(route, value)
|
|
142
|
+
} catch (error) {
|
|
143
|
+
this.showError('Failed to update route state' + error.message)
|
|
144
|
+
}
|
|
145
|
+
})
|
|
146
|
+
)
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
private createRouteField(
|
|
150
|
+
routeEl: HTMLElement,
|
|
151
|
+
route: RouteConfig,
|
|
152
|
+
field: RouteField
|
|
153
|
+
): void {
|
|
154
|
+
new Setting(routeEl)
|
|
155
|
+
.setName(field.name)
|
|
156
|
+
.setDesc(field.description)
|
|
157
|
+
.addText(text => {
|
|
158
|
+
text.setPlaceholder(field.placeholder || '')
|
|
159
|
+
return this.createTextComponent(text, route, field.key)
|
|
160
|
+
})
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
private addDeleteButton(routeEl: HTMLElement, index: number): void {
|
|
164
|
+
new Setting(routeEl).addButton(button =>
|
|
165
|
+
button
|
|
166
|
+
.setButtonText('Delete Route')
|
|
167
|
+
.setWarning()
|
|
168
|
+
.onClick(async () => {
|
|
169
|
+
try {
|
|
170
|
+
await this.deleteRoute(index)
|
|
171
|
+
} catch (error) {
|
|
172
|
+
this.showError('Failed to delete route' + error.message)
|
|
173
|
+
}
|
|
174
|
+
})
|
|
175
|
+
)
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
private async updateRouteField(
|
|
179
|
+
route: RouteConfig,
|
|
180
|
+
field: keyof RouteConfig,
|
|
181
|
+
value: string | boolean
|
|
182
|
+
): Promise<void> {
|
|
183
|
+
if (field === 'enabled') {
|
|
184
|
+
route[field] = value as boolean
|
|
185
|
+
} else {
|
|
186
|
+
const stringFields: (keyof RouteConfig)[] = [
|
|
187
|
+
'id',
|
|
188
|
+
'name',
|
|
189
|
+
'icon',
|
|
190
|
+
'url',
|
|
191
|
+
'contentType',
|
|
192
|
+
'contentField',
|
|
193
|
+
'additionalInstructions',
|
|
194
|
+
'description',
|
|
195
|
+
'subtitle',
|
|
196
|
+
'schema',
|
|
197
|
+
'schemaDescription',
|
|
198
|
+
'language',
|
|
199
|
+
]
|
|
200
|
+
|
|
201
|
+
if (stringFields.includes(field)) {
|
|
202
|
+
;(route[field] as string) = value as string
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
await this.plugin.saveSettings()
|
|
207
|
+
|
|
208
|
+
if (field === 'icon' || field === 'enabled') {
|
|
209
|
+
await this.plugin.debouncedUpdateRibbonIcons()
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
private async updateRouteEnabled(
|
|
214
|
+
route: RouteConfig,
|
|
215
|
+
value: boolean
|
|
216
|
+
): Promise<void> {
|
|
217
|
+
route.enabled = value
|
|
218
|
+
await this.plugin.saveSettings()
|
|
219
|
+
this.plugin.updateRibbonIcons()
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
private async deleteRoute(index: number): Promise<void> {
|
|
223
|
+
if (this.plugin.settings.routes.length <= 1) {
|
|
224
|
+
new Notice('Cannot delete the only route')
|
|
225
|
+
return
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
this.plugin.settings.routes.splice(index, 1)
|
|
229
|
+
await this.plugin.saveSettings()
|
|
230
|
+
this.plugin.updateRibbonIcons()
|
|
231
|
+
this.display()
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
private addNewRouteButton(): void {
|
|
235
|
+
new Setting(this.containerEl)
|
|
236
|
+
.setName('Add New Route')
|
|
237
|
+
.setDesc('Create a new route configuration')
|
|
238
|
+
.addButton(button =>
|
|
239
|
+
button
|
|
240
|
+
.setButtonText('Add Route')
|
|
241
|
+
.setCta()
|
|
242
|
+
.onClick(async () => {
|
|
243
|
+
try {
|
|
244
|
+
await this.createNewRoute()
|
|
245
|
+
} catch (error) {
|
|
246
|
+
this.showError('Failed to create new route' + error.message)
|
|
247
|
+
}
|
|
248
|
+
})
|
|
249
|
+
)
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
private async createNewRoute(): Promise<void> {
|
|
253
|
+
const newRoute: RouteConfig = {
|
|
254
|
+
generatedConfig: '',
|
|
255
|
+
id: `route-${Date.now()}`,
|
|
256
|
+
name: 'New Route',
|
|
257
|
+
icon: 'star',
|
|
258
|
+
url: '',
|
|
259
|
+
contentType: '',
|
|
260
|
+
contentField: '',
|
|
261
|
+
additionalInstructions: '',
|
|
262
|
+
enabled: true,
|
|
263
|
+
description: '',
|
|
264
|
+
subtitle: '',
|
|
265
|
+
schema: '',
|
|
266
|
+
schemaDescription: '',
|
|
267
|
+
language: '',
|
|
268
|
+
fieldMappings: {},
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
this.plugin.settings.routes.push(newRoute)
|
|
272
|
+
await this.plugin.saveSettings()
|
|
273
|
+
this.display()
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
private showError(message: string): void {
|
|
277
|
+
new Notice(message)
|
|
278
|
+
}
|
|
279
|
+
}
|
package/src/constants.ts
CHANGED
|
@@ -1,67 +1,28 @@
|
|
|
1
|
-
import { StrapiExporterSettings } from './types
|
|
1
|
+
import { StrapiExporterSettings } from './types'
|
|
2
2
|
|
|
3
|
-
/**
|
|
4
|
-
* The default settings for the plugin
|
|
5
|
-
*/
|
|
6
3
|
export const DEFAULT_STRAPI_EXPORTER_SETTINGS: StrapiExporterSettings = {
|
|
7
4
|
strapiUrl: '',
|
|
8
5
|
strapiApiToken: '',
|
|
6
|
+
forvoyezApiKey: '',
|
|
9
7
|
openaiApiKey: '',
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
"name": "string"
|
|
31
|
-
}
|
|
32
|
-
],
|
|
33
|
-
"locale": "string"
|
|
34
|
-
}
|
|
35
|
-
}`,
|
|
36
|
-
jsonTemplateDescription: `{
|
|
37
|
-
"data": {
|
|
38
|
-
"title": "Title of the item, as a short string",
|
|
39
|
-
"seo_title": "SEO optimized title, as a short string",
|
|
40
|
-
"seo_description": "SEO optimized description, as a short string",
|
|
41
|
-
"slug": "URL-friendly string derived from the title",
|
|
42
|
-
"excerpt": "A short preview or snippet from the content",
|
|
43
|
-
"links": "Array of related links with ID, label, and URL",
|
|
44
|
-
"subtitle": "Subtitle or secondary title, as a short string",
|
|
45
|
-
"type": "Category or type of the item, as a short string",
|
|
46
|
-
"rank": "Numerical ranking or order priority, as a number",
|
|
47
|
-
"tags": "Array of associated tags with ID and name",
|
|
48
|
-
"locale": "Locale or language code, as a short string"
|
|
49
|
-
}
|
|
50
|
-
}`,
|
|
51
|
-
strapiArticleCreateUrl: '',
|
|
52
|
-
strapiContentAttributeName: '',
|
|
53
|
-
additionalPrompt: '',
|
|
54
|
-
enableAdditionalApiCall: false,
|
|
55
|
-
additionalJsonTemplate: '',
|
|
56
|
-
additionalJsonTemplateDescription: '',
|
|
57
|
-
additionalUrl: '',
|
|
58
|
-
additionalContentAttributeName: '',
|
|
59
|
-
mainButtonImageEnabled: false,
|
|
60
|
-
mainButtonGalleryEnabled: false,
|
|
61
|
-
additionalButtonImageEnabled: false,
|
|
62
|
-
additionalButtonGalleryEnabled: false,
|
|
63
|
-
mainImageFullPathProperty: '',
|
|
64
|
-
mainGalleryFullPathProperty: '',
|
|
65
|
-
additionalImageFullPathProperty: '',
|
|
66
|
-
additionalGalleryFullPathProperty: '',
|
|
8
|
+
currentTab: 'dashboard',
|
|
9
|
+
routes: [
|
|
10
|
+
{
|
|
11
|
+
id: 'default-route',
|
|
12
|
+
name: 'Default Route',
|
|
13
|
+
icon: 'upload',
|
|
14
|
+
url: '',
|
|
15
|
+
contentType: 'articles',
|
|
16
|
+
enabled: true,
|
|
17
|
+
fieldMappings: {},
|
|
18
|
+
description: '',
|
|
19
|
+
subtitle: '',
|
|
20
|
+
schema: '',
|
|
21
|
+
schemaDescription: '',
|
|
22
|
+
language: '',
|
|
23
|
+
contentField: '',
|
|
24
|
+
additionalInstructions: '',
|
|
25
|
+
generatedConfig: '',
|
|
26
|
+
},
|
|
27
|
+
],
|
|
67
28
|
}
|