@@ -25,14 +25,13 @@ export async function seedCoarNotify(communityId?: CommunitiesId) {
2525 Published : "dddddddd-dddd-4ddd-dddd-dddddddddd14" as StagesId ,
2626 // Outbound review request stages (for our Submissions)
2727 Submissions : "dddddddd-dddd-4ddd-dddd-dddddddddd17" as StagesId ,
28- ReviewRequested : "dddddddd-dddd-4ddd-dddd-dddddddddd11" as StagesId ,
2928 AwaitingResponse : "dddddddd-dddd-4ddd-dddd-dddddddddd18" as StagesId ,
3029 }
3130
3231 const WEBHOOK_PATH = "coar-inbox"
3332
3433 // Default remote inbox URL - can be changed in UI for testing
35- const REMOTE_INBOX_URL = "http://localhost:4000 /api/inbox"
34+ const REMOTE_INBOX_URL = "http://localhost:4001 /api/inbox"
3635
3736 return seedCommunity (
3837 {
@@ -48,11 +47,13 @@ export async function seedCoarNotify(communityId?: CommunitiesId) {
4847 Payload : { schemaName : CoreSchemaType . String } ,
4948 SourceURL : { schemaName : CoreSchemaType . String } ,
5049 RelatedPub : { schemaName : CoreSchemaType . String , relation : true } ,
50+ Author : { schemaName : CoreSchemaType . MemberId } ,
5151 } ,
5252 pubTypes : {
5353 Submission : {
5454 Title : { isTitle : true } ,
5555 Content : { isTitle : false } ,
56+ Author : { isTitle : false } ,
5657 } ,
5758 Notification : {
5859 Title : { isTitle : true } ,
@@ -80,12 +81,23 @@ export async function seedCoarNotify(communityId?: CommunitiesId) {
8081 existing : true ,
8182 role : MemberRole . admin ,
8283 } ,
84+ joeAuthor : {
85+ id : "dddddddd-dddd-4ddd-dddd-dddddddddd02" as UsersId ,
86+ firstName : "Joe" ,
87+ lastName : "Author" ,
88+ email : "joe-author@pubpub.org" ,
89+ password : "pubpub-joe" ,
90+ role : MemberRole . contributor ,
91+ } ,
8392 } ,
8493 pubs : [
8594 {
8695 pubType : "Submission" ,
8796 stage : "Submissions" ,
88- values : { Title : "Sample Submission for Review" } ,
97+ values : {
98+ Title : "Sample Submission for Review" ,
99+ Author : "dddddddd-dddd-4ddd-dddd-dddddddddd02" ,
100+ } ,
89101 } ,
90102 ] ,
91103 stages : {
@@ -103,6 +115,17 @@ export async function seedCoarNotify(communityId?: CommunitiesId) {
103115 config : { path : WEBHOOK_PATH } ,
104116 } ,
105117 ] ,
118+ // Only process incoming Offer notifications (review requests from external services)
119+ condition : {
120+ type : AutomationConditionBlockType . AND ,
121+ items : [
122+ {
123+ kind : "condition" ,
124+ type : "jsonata" ,
125+ expression : "'Offer' in $.json.type" ,
126+ } ,
127+ ] ,
128+ } ,
106129 actions : [
107130 {
108131 action : Action . createPub ,
@@ -211,13 +234,44 @@ export async function seedCoarNotify(communityId?: CommunitiesId) {
211234 // Entry point for our own submissions that we want to request reviews for
212235 Submissions : {
213236 id : STAGE_IDS . Submissions ,
214- // No automations - this is just an entry/holding stage
237+ automations : {
238+ // Manual action to request a review from a remote repository
239+ "Request Review" : {
240+ icon : {
241+ name : "send" ,
242+ color : "#f59e0b" ,
243+ } ,
244+ triggers : [
245+ {
246+ event : AutomationEvent . manual ,
247+ config : { } ,
248+ } ,
249+ ] ,
250+ condition : {
251+ type : AutomationConditionBlockType . AND ,
252+ items : [
253+ {
254+ kind : "condition" ,
255+ type : "jsonata" ,
256+ expression : "$.pub.pubType.name = 'Submission'" ,
257+ } ,
258+ ] ,
259+ } ,
260+ actions : [
261+ {
262+ action : Action . move ,
263+ config : { stage : STAGE_IDS . AwaitingResponse } ,
264+ } ,
265+ ] ,
266+ } ,
267+ } ,
215268 } ,
216- // When we request a review from an external service
217- ReviewRequested : {
218- id : STAGE_IDS . ReviewRequested ,
269+ // Waiting for response from external service after requesting a review
270+ AwaitingResponse : {
271+ id : STAGE_IDS . AwaitingResponse ,
219272 automations : {
220- "Offer Review" : {
273+ // Send the Offer when a submission enters this stage
274+ "Send Review Offer" : {
221275 icon : {
222276 name : "send" ,
223277 color : "#f59e0b" ,
@@ -228,6 +282,16 @@ export async function seedCoarNotify(communityId?: CommunitiesId) {
228282 config : { } ,
229283 } ,
230284 ] ,
285+ condition : {
286+ type : AutomationConditionBlockType . AND ,
287+ items : [
288+ {
289+ kind : "condition" ,
290+ type : "jsonata" ,
291+ expression : "$.pub.pubType.name = 'Submission'" ,
292+ } ,
293+ ] ,
294+ } ,
231295 actions : [
232296 {
233297 action : Action . http ,
@@ -255,22 +319,54 @@ export async function seedCoarNotify(communityId?: CommunitiesId) {
255319 inbox : REMOTE_INBOX_URL ,
256320 type : "Service" ,
257321 } ,
322+ origin : {
323+ id : "{{ $.env.PUBPUB_URL }}/c/{{ $.community.slug }}" ,
324+ inbox : `{{ $.env.PUBPUB_URL }}/api/v0/c/{{ $.community.slug }}/site/webhook/${ WEBHOOK_PATH } ` ,
325+ type : "Service" ,
326+ } ,
258327 } ,
259328 } ,
260329 } ,
330+ ] ,
331+ } ,
332+ // Process incoming responses (Accept/Reject/Announce) from external services
333+ "Process Response" : {
334+ icon : {
335+ name : "mail" ,
336+ color : "#3b82f6" ,
337+ } ,
338+ triggers : [
261339 {
262- action : Action . move ,
263- config : { stage : STAGE_IDS . AwaitingResponse } ,
340+ event : AutomationEvent . webhook ,
341+ config : { path : WEBHOOK_PATH } ,
342+ } ,
343+ ] ,
344+ // Only process Accept, Reject, or Announce responses (not Offer)
345+ condition : {
346+ type : AutomationConditionBlockType . AND ,
347+ items : [
348+ {
349+ kind : "condition" ,
350+ type : "jsonata" ,
351+ expression :
352+ "'Accept' in $.json.type or 'Reject' in $.json.type or 'Announce' in $.json.type" ,
353+ } ,
354+ ] ,
355+ } ,
356+ // Resolver finds the Submission pub that matches the inReplyTo field
357+ // The inReplyTo will be like "urn:uuid:<pub-id>" from our sent Offer
358+ resolver : `{{ $replace($.json.inReplyTo, "http://localhost:3000/c/coar-notify/pub/", "") }} = $.pub.id` ,
359+ actions : [
360+ {
361+ action : Action . log ,
362+ config : {
363+ text : "Received response: {{ $.json.type }} for pub {{ $.pub.values.title }} ({{ $.pub.id }})" ,
364+ } ,
264365 } ,
265366 ] ,
266367 } ,
267368 } ,
268369 } ,
269- // Waiting for Accept/Reject response from external service
270- AwaitingResponse : {
271- id : STAGE_IDS . AwaitingResponse ,
272- // No automations - we wait for incoming Accept/Reject notifications
273- } ,
274370 Published : {
275371 id : STAGE_IDS . Published ,
276372 automations : {
@@ -299,7 +395,7 @@ export async function seedCoarNotify(communityId?: CommunitiesId) {
299395 "type": ["Announce", "coar-notify:ReviewAction"],
300396 "id": "urn:uuid:" & $.pub.id,
301397 "object": {
302- "id": $.env.PUBPUB_URL & "/c/ " & $.community.slug & "/pub /" & $.pub.id,
398+ "id": "http://localhost:8080 " & $.community.slug & "/reviews /" & $.pub.id,
303399 "type": ["Page", "sorg:Review"],
304400 "as:inReplyTo": $.pub.out.RelatedPub.values.SourceURL
305401 },
@@ -313,6 +409,119 @@ export async function seedCoarNotify(communityId?: CommunitiesId) {
313409 } ,
314410 ] ,
315411 } ,
412+ "Build Site" : {
413+ icon : {
414+ name : "globe" ,
415+ color : "#6366f1" ,
416+ } ,
417+ triggers : [
418+ {
419+ event : AutomationEvent . pubEnteredStage ,
420+ config : { } ,
421+ } ,
422+ {
423+ event : AutomationEvent . manual ,
424+ config : { } ,
425+ } ,
426+ ] ,
427+ condition : {
428+ type : AutomationConditionBlockType . AND ,
429+ items : [
430+ {
431+ kind : "condition" ,
432+ type : "jsonata" ,
433+ expression : "$.pub.pubType.name = 'Review'" ,
434+ } ,
435+ ] ,
436+ } ,
437+ actions : [
438+ {
439+ action : Action . buildSite ,
440+ config : {
441+ css : `:root {
442+ --color-bg: #ffffff;
443+ --color-text: #1a1a1a;
444+ --color-muted: #6b7280;
445+ --color-border: #e5e7eb;
446+ --color-accent: #3b82f6;
447+ --font-sans: system-ui, -apple-system, sans-serif;
448+ --font-mono: ui-monospace, monospace;
449+ }
450+
451+ * { box-sizing: border-box; margin: 0; padding: 0; }
452+
453+ body {
454+ font-family: var(--font-sans);
455+ line-height: 1.6;
456+ color: var(--color-text);
457+ background: var(--color-bg);
458+ max-width: 800px;
459+ margin: 0 auto;
460+ padding: 2rem 1rem;
461+ }
462+
463+ h1, h2, h3 { line-height: 1.3; margin-bottom: 0.5em; }
464+ h1 { font-size: 2rem; }
465+ h2 { font-size: 1.5rem; color: var(--color-muted); }
466+
467+ .pub-field { margin-bottom: 1.5rem; }
468+ .pub-field-label {
469+ font-size: 0.75rem;
470+ text-transform: uppercase;
471+ letter-spacing: 0.05em;
472+ color: var(--color-muted);
473+ margin-bottom: 0.25rem;
474+ }
475+ .pub-field-value { font-size: 1rem; }
476+ .pub-field-value:empty::after { content: "—"; color: var(--color-muted); }
477+
478+ a { color: var(--color-accent); }
479+ pre, code { font-family: var(--font-mono); font-size: 0.875rem; }
480+ pre { background: #f3f4f6; padding: 1rem; border-radius: 0.5rem; overflow-x: auto; }
481+
482+ .review-list { list-style: none; }
483+ .review-list li { margin-bottom: 1rem; padding-bottom: 1rem; border-bottom: 1px solid var(--color-border); }
484+ .review-list li:last-child { border-bottom: none; }` ,
485+ subpath : "reviews" ,
486+ pages : [
487+ {
488+ // Individual review page - one per Review pub
489+ slug : "$.pub.id" ,
490+ // Use all published pubs
491+ filter : '$.pub.pubType.name = "Review"' ,
492+ transform : `'<article>' &
493+ '<h1>' & $.pub.title & '</h1>' &
494+ $join(
495+ $map(
496+ $filter($keys($.pub.values), function($v){ $not($contains($v, ":")) }),
497+ function($v){
498+ '<div class="pub-field">' &
499+ '<div class="pub-field-label">' & $v & '</div>' &
500+ '<div class="pub-field-value">' &
501+ $string($lookup($.pub.values, $v)) & '</div>' &
502+ '</div>'
503+ }
504+ ),
505+ ''
506+ ) &
507+ '<p><a href="/">← Back to all reviews</a></p>' &
508+ '</article>'` ,
509+ } ,
510+ {
511+ // Index page - lists all published reviews
512+ slug : '"/"' ,
513+ filter : '$.pub.pubType.name = "Review"' ,
514+ transform : `'<h1>Published Reviews</h1>' &
515+ '<ul class="review-list">' &
516+ '<li><a href="/coar-notify/reviews/' & $.pub.id & '">' & $.pub.title & '</a></li>' &
517+ '</ul>'` ,
518+ } ,
519+ ] ,
520+ outputMap : [ ] ,
521+ } ,
522+ } ,
523+ ] ,
524+ } ,
316525 } ,
317526 } ,
318527 Accepted : {
@@ -492,9 +701,6 @@ export async function seedCoarNotify(communityId?: CommunitiesId) {
492701 } ,
493702 // Outbound request flow: our submissions requesting external reviews
494703 Submissions : {
495- to : [ "ReviewRequested" ] ,
496- } ,
497- ReviewRequested : {
498704 to : [ "AwaitingResponse" ] ,
499705 } ,
500706 } ,
0 commit comments