feat(rsocials): thread editor link from campaign publish-thread nodes

- Add threadId config field to publish-thread nodes
- Add "Create Thread" / "Edit Thread" button in config panel
- Opens thread editor in new tab (new or edit by ID)
- Styled button matching indigo accent theme

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Jeff Emmett 2026-03-12 00:34:34 -07:00
parent c0de770e70
commit a658b20fb1
3 changed files with 39 additions and 0 deletions

View File

@ -274,6 +274,26 @@ folk-campaign-workflow {
outline: none;
}
.cw-config__thread-btn {
padding: 8px 12px;
border-radius: 6px;
border: 1px solid #6366f155;
background: #6366f122;
color: #818cf8;
font-size: 12px;
cursor: pointer;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
transition: background 0.15s, border-color 0.15s;
}
.cw-config__thread-btn:hover {
background: #6366f133;
border-color: #6366f1;
}
.cw-config__delete {
margin-top: 12px;
padding: 6px 12px;

View File

@ -506,6 +506,13 @@ class FolkCampaignWorkflow extends HTMLElement {
</div>
`).join('');
const threadBtnHtml = node.type === 'publish-thread'
? `<button class="cw-config__thread-btn" id="config-open-thread">
<span style="margin-right:4px">🧵</span>
${node.config.threadId ? 'Edit Thread' : 'Create Thread'}
</button>`
: '';
return `
<div class="cw-config__header">
<span>${def.icon} ${esc(node.label)}</span>
@ -517,6 +524,7 @@ class FolkCampaignWorkflow extends HTMLElement {
<input type="text" id="config-label" value="${esc(node.label)}">
</div>
${fieldsHtml}
${threadBtnHtml}
${logHtml ? `<div class="cw-exec-log"><div class="cw-exec-log__title">Execution Log</div>${logHtml}</div>` : ''}
<button class="cw-config__delete" id="config-delete-node">Delete Node</button>
</div>`;
@ -840,6 +848,16 @@ class FolkCampaignWorkflow extends HTMLElement {
if (this.selectedNodeId) this.deleteNode(this.selectedNodeId);
});
this.shadow.getElementById('config-open-thread')?.addEventListener('click', () => {
const node = this.nodes.find(n => n.id === this.selectedNodeId);
if (!node) return;
const threadId = node.config.threadId;
const url = threadId
? `${this.basePath}thread-editor/${threadId}/edit`
: `${this.basePath}thread-editor`;
window.open(url, '_blank');
});
const configPanel = this.shadow.getElementById('config-panel');
if (configPanel) {
configPanel.querySelectorAll('[data-config-key]').forEach(el => {

View File

@ -323,6 +323,7 @@ export const CAMPAIGN_NODE_CATALOG: CampaignWorkflowNodeDef[] = [
outputs: [{ name: 'done', type: 'trigger' }, { name: 'threadId', type: 'data' }],
configSchema: [
{ key: 'platform', label: 'Platform', type: 'select', options: ['X', 'Bluesky', 'Threads'] },
{ key: 'threadId', label: 'Thread ID (link existing)', type: 'text', placeholder: 'Leave empty to use inline content' },
{ key: 'threadContent', label: 'Thread (--- between tweets)', type: 'textarea', placeholder: 'Tweet 1\n---\nTweet 2\n---\nTweet 3' },
],
},