Orchard Core 使用工作流處理審批和創建內容項

譯自:http://www.ideliverable.com/blog/orchard-core-workflows-walkthrough-content-approval

轉載請註明出處, 原文地址:https://www.cnblogs.com/Qbit/p/orchardcore-Workflow.html 

 

 

爲了更好地瞭解新的Workflows模塊,我們將創建一個工作流程來嘗試一些新的活動。讓我們創建一個內容審批工作流程,爲以下流程建模:

 

  • 作爲作者,我可以向某個HTTP端點提交新文章。
  • 網站管理員會收到一封電子郵件,表明已提交新文章以供審覈。
  • 當審覈人員批准該文章時,將創建併發布實際的文章內容項。作者會收到一封電子郵件通知,其中包含指向已發佈內容項的鏈接。
  • 當審覈人員 拒絕 時,主持人會收到一封電子郵件通知,其中包含要向其提交工作更新版本的新URL。
    • 作者必須在超時到期之前提交她的工作的修訂版本。
    • 當作者提交修訂版本時,主持人再次可以選擇批准或拒絕該文章,允許工作流程無限期地重複

    

讓我們一步一步地構建這個工作流程,看看它的實際效果。

完整的工作流程如下所示:

Step 1:啓用工作流程和電子郵件功能

轉到配置 - > 模塊並啓用以下3個功能:

  • HTTP Workflow Activities
  • Timer Workflow Activities
  • Email

Step 2: 創建一個新的工作流定義

管理菜單將出現一個新的項,其中顯示“Workflows”。 單擊此項並單擊“Create Workflow Type”按鈕。爲工作流命名爲“Content Approval Workflow”,並確保勾選Enabled複選框。另外兩個複選框可以保持未選中狀態,但可以隨意嘗試。

第3步:添加傳入HTTP請求事件

我們需要一個允許作者將內容發佈到我們的應用程序的工作流程,因此我們將通過公開一個可以啓動的HTTP端點來啓動我們的工作流程。單擊“ Add Event” 按鈕以啓動活動選擇器。

從活動選擇器中,查找HTTP Request,然後單擊“ Add”  按鈕。

 

在活動編輯器中,選擇POST作爲HTTP方法,然後單擊Generate按鈕。單擊此按鈕將生成工作流URL和SAS令牌。

在向生成的URL發出HTTP請求時必須提供此令牌,否則將不會執行工作流。此令牌的目的是防止未授權方觸發您的工作流程。

因此,重要的是不要將此URL分發給任何人; 僅將工作流URL提供給您信任的各方,因爲擁有此URL的任何人都可以調用您的工作流。

單擊“ 保存”按鈕。

Step 4: 設置開始活動

返回工作流編輯器畫布,單擊添加的HTTP Request活動。

當你這樣做時,你會發現活動下方會出現一個小工具欄。

單擊最左側的按鈕,使用“打開/關閉電源”圖標將此活動標記爲啓動活動。

只有標記爲啓動活動的活動才能導致工作流程執行。標記位啓動活動後該活動的背景色將變爲綠色如下圖:

Step 5: 添加Set Property Activity

 當作者發出HTTP POST請求時,我們希望她發送JSON格式的內容。爲了處理這些數據,我們將其存儲爲工作流屬性。

單擊“ Add Task ”按鈕,查找“ Set Property Activity”活動,然後單擊“ Add”。在“ 名稱”字段中輸入“Article”,在“ 值”字段中輸入以下JavaScript表達式:

JSON.parse(readBody())

上述readBody函數讀取從請求作爲字符串的HTTP內容,並且JSON.parse功能解析這個字符串轉換成一個實際的對象。

Set Property活動將此對象存儲爲名爲“Article”的屬性。這允許我們通過簡單地詢問此屬性來在整個工作流程的其餘部分中訪問此對象。

我們將在下一步看到它是如何工作的。供您參考,我打算將JSON字符串看起來像這樣:

 

{
 "author": {
 "name": "Max Whitaker",
 "email": "[email protected]"
 },
 "article":{
 "title": "A short story",
 "body": "The article content goes here"
 }
}

在進行下一步之前,請確保將HTTP Request活動與Set Property活動相關聯。您的工作流現在應該如下所示:

 

Step 6: 添加發送電子郵件活動

當我們收到作者提交的文章時,我們會通知網站的主持人。我們通過發送電子郵件來做到這一點。使用以下值添加“發送電子郵件”活動:

Sender: [email protected]

Recipients: [email protected]

Subject: New article submission received: {{Article.article.title}}

Body:

<p>Hi! A new article was just submitted by <strong>{{Article.author.name}}</strong>.</p>
<p><em>{{Article.article.body}}</em></p>
<p>you have the following available actions:</p>
<p>
<a href="{{"Approve" | signal_url | absolute_url}}">Approve</a> | <a href="{{"NeedsWork" | signal_url | absolute_url}}">Needs Work</a>
</p>

請注意,我們可以在Subject和Body字段中使用Liquid語法。Orchard Core Workflow的一個非常巧妙的功能是它將爲Liquid模板上下文提供所有工作流屬性。由於我們在上一步中添加了“Article”屬性,因此我們現在可以在編寫Liquid語句時直接訪問該屬性。由於我們將JSON內容解析爲實際對象,因此我們可以簡單地使用點表示法來訪問其任何字段。

作爲電子郵件的一部分,我們希望爲主持人提供兩個操作:批准和  需要工作我們將通過使用signal_url Liquid過濾器生成工作流URL來實現此目的此過濾器的工作方式是它將獲取其輸入(前面的字符串,例如“Approve”或“NeedsWork”)並將其用作信號名稱。然後將該信號名稱編碼爲SAS令牌,並作爲查詢字符串參數附加到URL。調用此完整URL將觸發Signal事件。然後將執行以配置有相應信號名稱的Signal事件開始的任何工作流程。並且將恢復由具有相應信號名稱的Signal事件阻止的任何工作流程。這正是我們工作流程所需要的。

確保將“Set Article Property ”活動與“發送電子郵件”活動相關聯。

 

Step 7:添加Fork活動

Fork活動將工作流分成多個並行執行路徑。

我們在這裏想要這樣做的原因是我們將使用兩個Signal事件並等待它們中的任何一個被觸發。Signal事件將導致工作流程執行暫停,直到觸發爲止。

我們可以採用不同的方法並簡單地添加另一個HTTP請求事件,例如,期望具有查詢字符串參數的請求包含審批人批准或拒絕該文章,並簡單地測試該值。

雖然這樣可以很好地工作,但Signal事件和HTTP Request事件之間的主要區別在於Signal事件允許您將信號名稱包含在SAS令牌中,這有效地防止了任何人篡改信號名稱。

添加Fork活動時,請輸入以下兩個結果:“Await Approval,Await Needs Work”,然後單擊“保存”。在工作流編輯器畫布上,確保將發送電子郵件”活動“完成”結果連接到新添加的Fork活動。

 

請注意Fork 活動上面的兩個綠色小點,一個小點代表一個分支,這個分支的數量與我們定義的結果數量相匹配,多個結果之間使用逗號分割

 

Step 8:添加兩個信號活動

打開事件活動選擇器並添加Signal事件。使用“Approve”作爲信號名稱配置此項。添加另一個Signal事件,這次是針對“NeedsWork”信號。添加兩個活動後,將Fork活動中的相應結果連接到Signal活動。

 

Step 9:添加加入活動

此時,兩個信號事件可以繼續工作流程。如果觸發“批准”信號,則執行將從該點開始繼續,如果觸發“NeedsWork”信號,則從該點開始執行。但是,我們不想要的是,如果其中一個信號被觸發,另一個信號仍然可以在以後觸發。相反,當觸發一個信號時,我們希望將兩個分支“連接”到一個執行路徑中。爲此,請添加Join活動並將其Mode設置WaitAny

 

 

 

第10步:添加If / Else活動

雖然執行已合併,但我們確實需要知道觸發了哪個信號,以便我們採取適當的措施。如果觸發了“Approve”信號,我們希望繼續創建內容項。但如果“NeedsWork”信號被觸發,我們想採取不同的路徑。雖然我們可以在工作流上設置屬性以響應Signal事件,但有一種更簡單的方法:每當觸發信號事件時,信號名稱將作爲工作流輸入提供。讓我們繼續添加If / Else活動並將其條件設置爲:

input("Signal") === "NeedsWork"

 

如果接收到的信號爲“NeedsWork”,則JavaScript表達式的計算結果爲true;如果是任何其他信號,則表達式爲false。由於我們在工作流程中此時僅支持兩個信號,因此該邏輯工作正常。如果您有一個等待兩個以上信號的工作流程,您應該使用  腳本活動,它可以讓您定義多個結果。

有兩種可能的結果:無論是真還是假。我們將首先進行虛假結果(這意味着信號不是“NeedsWork” 就是 “Approve”),然後回到工作流程中的這一點並繼續使用True路徑(“文章需要工作”)。

第11步:創建文章內容類型

在我們真正讓工作流創建文章內容項之前,我們首先需要定義文章內容類型。爲此,請轉到“ 內容定義” - >“ 內容類型”,然後單擊“ 創建新類型”按鈕。爲“顯示名稱”和“技術名稱”字段輸入“Article”。

 

接下來,添加以下部分:

  • Autoroute
  • Body
  • Title

 

還要添加一個文本字段,併爲其指定顯示名稱“作者”和技術名稱“AuthorName"。您的內容定義應如下所示:

 

 

 

 

現在我們已經有了Article內容類型,我們可以返回到工作流編輯器並繼續下一步。

第12步:添加“創建內容活動”

如果提交的文章(JSON有效負載)得到主持人的批准,我們需要工作流實際創建文章內容項並複製提供的內容。爲此,我們將利用新的“創建內容”活動。繼續並從活動選擇器添加它,並提供以下值:

 

內容類型:文章

發佈:是的

內容屬性:

{
	"TitlePart": {
		"Title": "{{ Article.article.title }}",
	},
	"BodyPart": {
		"Body": "{{ Article.article.body }}"
	},
	"Article": {  
		"AuthorName": {
			"Text": {{Article.author.name | json | raw}}
			}  
	}
}

  

注意此處提交的內容如果包含中文您應當使用json | raw 過濾器 ,因爲頁面提交過來的所有內容將會被轉換爲HTML編碼格式 ,
它將自動生成 外圍的雙引號,所以不需要再添加雙引號包裹 ,其它位置的Liquid 類似,當然您也可以去掉 json filter 它將不會生成雙引號,但Orchard Core的作者建議您 結合 json 過濾器一起使用,因爲後續版本可能會修復這個編碼顯示的問題
"Text": {{ Article.author.name | json | raw }}

“內容屬性”字段的值需要包含一個JSON結構,該結構與用於ContentItem對象的Content屬性的結構完全相同。有許多方法可以確定內容項的結構。

比如:

  • 一種方法是通過管理員創建一條內容項,然後進入數據庫 Document 表並查看其JSON結構。
  • 另一種方法是使用Visual Studio調試器並在Display操作方法的Contents模塊的AdminController中設置斷點,然後使用立即窗口寫出contentItem的Content屬性。我使用後一種方法,因爲我碰巧在調試器中。

請注意,我正在使用Liquid語法從Article工作流屬性中插入字段。

    

 

Step 13: 添加發送郵件活動

當主持人批准提交的文章時,讓作者知道這一點會很好。我們通過電子郵件來做到這一點。添加另一個發送電子郵件活動並提供以下值:

Sender: [email protected] 

Recipients: {{ Article.author.email }}

Subject: Your article has been approved and published!

Body:

<p>Dear {{ Article.author.name }},</p>
<p>Your article &quot;<strong>{{ Article.article.title }}</strong>&quot; has been published!</p>
<p>You can check it out online via the following link:</p>
<p><a href="{{ LastResult | display_url | absolute_url}}">{{LastResult | display_text }}</a></p>

這是“批准”分支所需的最後一項活動。執行此活動後,工作流程即完成。

Step 14:添加另一個發送電子郵件活動

返回If / Else活動,我們將“已批准”流程分支。當主持人觸發“NeedsWork”信號時,此活動的條件將評估爲真,這意味着我們需要讓作者知道他的工作不夠好。爲此,請使用以下字段添加另一個“發送電子郵件”活動:

Sender: [email protected]

Recipients: {{Article.author.email}}

Subject: Your article needs work

Body:

<p>Dear {{Article.author.name}},</p>
<p>We received your submission, thank you!</p>
<p>However, your article needs a little bit of work.</p>
<p>When you're ready, please submit (HTTP PUT) an updated draft to the following URL:</p>
<p><strong>{{ "/Workflows/Invoke?token=CfDJ8J14khzBx5ZDmlhyDVsxlZ4hZHnM7Qfw4IqnSFuIMmcp1uwL90Gcf9uokBJSe_F5fgmCODds-YblHBCH1dnJ8UnwkL8TaYR3BZsDUXH6bBRD0_ek_Vgcj9aHIcd9YhRI6UkV15g6hu-ui8_TDQGPjlhGwziTzerc0Yee3CFAs_6YOktpZH4dR1K4GjFs5XTzXprY22L1V2ddNOvRhkePmHXPMunZ2XE_3Ioi1w0FU_00" | absolute_url }}</strong></p>
<p></p>
<p><strong>NOTE:</strong> Please re-submit your work within the next hour, or else your submission will expire!</p>

  (重要提示:使用在下面的步驟17中爲HTTP請求事件生成的URL替換上面代碼段中的URL!)。

Step 15:添加Fork活動

我們現在想等待作者的修改工作,所以我們應該添加另一個HTTP Request事件。但是,如果作者未在特定時間內向我們發送更新,我們還希望添加某種“超時”,以使工作流程到期。爲了實現這個邏輯,我們將等待兩個事件之一:HTTP Request事件和Timer事件。由於我們想要同時等待這兩個事件,我們應該再次分配我們的工作流,所以繼續添加一個新的Fork活動並指定以下兩個結果:“Await Revision,Begin Timer”

 

Step 16:添加定時器活動

要實現超時,請將Timer事件添加到工作流。Timer actvity使用CRON選項卡表達式來控制它何時應該觸發。讓我們做5分鐘,轉換爲以下CRON選項卡表達式:  */5 * * * *

 

Step17:添加HTTP請求活動

我們希望作者通過發送HTTP PUT請求來提交修改後的文章,所以讓我們添加另一個HTTP Request事件。確保將HTTP方法設置爲Put只要作者發出的HTTP請求與配置的任何方法匹配,您使用哪種HTTP方法並不重要。確保爲此活動生成URL,並在步驟14中描述的電子郵件正文中使用它。

 記得回到第14步更新URL

Step 18:添加加入活動

出於與步驟9中描述的相同的原因,我們需要添加Join活動以將分叉流連接回單個執行路徑,因爲我們只想在定時器觸發或收到HTTP請求時繼續執行,但是從來沒有。

如果沒有Join活動,即使我們在此之前收到HTTP請求,計時器仍會在5分鐘後觸發。所以讓我們繼續使用WaitAny模式添加Join活動和往常一樣,確保連接點。

Step19:添加If / Else活動

雖然我們將兩個流連接成一個流,但我們需要知道觸發了哪個事件:HTTP請求或計時器。幸運的是,這很容易做到,因爲當觸發Timer事件時,它會將工作流的LastResult  屬性設置爲字符串文字“TimerEvent”。所以我們需要做的就是添加一個If / Else活動並輸入一個JavaScript表達式來檢查這個astResult屬性。表達式如下: 

lastResult() === "TimerEvent"

如果該條件的計算結果爲true,則表示計時器已被觸發且作者的時間已到。發生這種情況時,我們應該給他發一封電子郵件。另一方面,如果作者提交了更新的文章,我們應該重複工作流程並向主持人發送電子郵件,以便關閉循環。 

Step 20:添加發送電子郵件活動

 

首先,使用以下值添加另一個“發送電子郵件”活動:

Sender: [email protected]

Recipients: {{Article.author.email}}

Subject: Sorry, you're revision took too long and we cancelled your submission

Body: 

<p>親愛的{{Article.author.name}},</ p> 
<p>不幸的是,您的修訂時間窗口已過期,我們不得不取消您的提交。</ p>
<p>請不要氣餒。您可以隨時通過提交新文章重新開始提交過程。</ p>
<p>很快見到您!</ p>

 

Step 21: 關閉循環

最後一步是關閉循環:當作者提交更新的文章時,我們需要重複整個工作流程。我們需要做的就是將步驟19中的If / Else活動的假結果連接到步驟5中創建的Set Article Property活動。

注意:當我嘗試將If / Else活動與Set Property活動一直連接到頂部時,我對編輯器不會自動向上滾動這一事實感到困惑。要解決此問題,我縮小了瀏覽器窗口。或者,您可以暫時將源活動拖動到足夠接近目標活動,連接兩者,然後將源活動拖回到您希望的活動。

 

經過上面一番操作,此時你的工作流畫布大概長這樣:

 

 

 

 

 

 下面的內容就直接機翻了,因爲我打算在下一篇文章中使用頁面提交,而不是用 Postman,當然原理差不多。

演示:試一試!

是時候嘗試工作流程了!

要觸發我們的工作流,我們需要發出一個HTTP POST請求,其中包含JSON格式的文章信息。一個簡單的方法是使用像Postman這樣的工具,這是我用於此演示的工具。因此,使用以下值在Postman中創建新請求:

網址: URL: https://localhost:44300/Workflows/Invoke?token=CfDJ8J14khzBx5ZDmlhyDVsxlZ6JIYCB0pHweMHXe7qHC5jazD-8WdrqnV5SzxXcN3MZSazeglEAu6zJZ_VahyBRkHTU6IJQSuwFXapu7y1Zg5g_Zkm8e62ywJ4hneNAAlhC1siSVNP6Ypsjsyz6d_Aoz55ZrcBQXwiiWXSDNcdEGBZpVbMs9ufB6iP4gFEQWnoRPO6c7X9rHWsJyjhDF8TBeNb0jQaZQrKIylYBzLTC5WpW 

(請務必使用您的啓動活動所產生的實際URL)

方法: POST

身體: 

{ 
“author”:{
“name”:“Max Whitaker”,
“email”:“[email protected]
},
“article”:{
“title”:“短篇小說”,
我討厭你,我想要一個wifi代碼。安迪回過頭來,更加自信,仍然指着那些微不足道的報紙。“佐伊,我沒有錢,”他回答道。他們帶着閃閃發光的感覺看着對方,就像兩個苦澀,強壯的獾在一個非常冷酷的晚宴上跳過,這個晚宴上有獨立的音樂,還有兩個高貴的叔叔在節拍中蹦蹦跳跳。安迪認爲佐伊英俊的腳和骨瘦如柴的睫毛。'我有同樣的感覺!' 安迪高興地露出了笑容。佐伊看起來很擔心,她的情緒像一個刺耳的,破爛的岩石一樣臉紅。然後佐伊進來一個漂亮的港口。結束” 他們帶着閃閃發光的感覺看着對方,就像兩個苦澀,強壯的獾在一個非常冷酷的晚宴上跳過,這個晚宴上有獨立的音樂,還有兩個高貴的叔叔在節拍中蹦蹦跳跳。安迪認爲佐伊英俊的腳和骨瘦如柴的睫毛。'我有同樣的感覺!' 安迪高興地露出了笑容。佐伊看起來很擔心,她的情緒像一個刺耳的,破爛的岩石一樣臉紅。然後佐伊進來一個漂亮的港口。結束” 他們帶着閃閃發光的感覺看着對方,就像兩個苦澀,強壯的獾在一個非常冷酷的晚宴上跳過,這個晚宴上有獨立的音樂,還有兩個高貴的叔叔在節拍中蹦蹦跳跳。安迪認爲佐伊英俊的腳和骨瘦如柴的睫毛。'我有同樣的感覺!' 安迪高興地露出了笑容。佐伊看起來很擔心,她的情緒像一個刺耳的,破爛的岩石一樣臉紅。然後佐伊進來一個漂亮的港口。結束” rabblesnatching rock。然後佐伊進來一個漂亮的港口。結束” rabblesnatching rock。然後佐伊進來一個漂亮的港口。結束”
}
}

內容類型: application / json

我們還需要配置SMTP服務器,以便我們可以讓工作流實際發送電子郵件。但我沒有使用真正的SMTP服務器,而是使用Smtp4Dev,這是一個實際上不發送電子郵件的SMTP服務器; 相反,它顯示在列表中發送的電子郵件,以便我們可以檢查發送的消息。這樣我們就可以發送電子郵件到假地址,並仍然檢查發送的消息。我將使用Smtp4Dev進行此演示。

如果您還沒有這樣做,請確保轉到配置 - >設置 - > Smtp並提供SMTP詳細信息。在我的情況下,我配置Smtp4Dev來偵聽端口2525,所以我的設置如下所示:

 

提交HTTP請求時,您應該收到HTTP 200 Accepted狀態代碼。我們還應該看到工作流的工作流實例:

 

單擊工作流實例ID以轉到工作流實例詳細信息視圖,該視圖應如下所示:

請注意以下事項:

  1. 工作流處於暫停狀態(1)。
  2. 兩個Signal活動阻止了工作流程(2)(3)

當我們在這個頁面上時,讓我們看一下工作流實例的State視圖:

如您所見,提交的JSON存儲在名爲“Article”的自定義屬性中。

現在讓我們打開Smtp4Dev Web界面來檢查發送的電子郵件:

所以這很有效。現在讓我們點擊電子郵件中的“需要工作”鏈接。當您這樣做時,您應該會立即看到一封新電子郵件:

輝煌!我們還來看看工作流程的當前狀態:

如您所見,工作流現在在HTTP Request事件(1)和Timer事件(2)上暫停。如果我們等待足夠長的時間(大約5分鐘),我們將收到一封電子郵件,告知我們的時間已到。(等待5分鐘......)果然:

在我們發送更新的文章之前觸發了計時器,並導致工作流程結束。

要再次啓動工作流,我們需要發送一個新的HTTP POST請求,然後批准或請求修訂等。您明白了。試試看!

結論

我希望我已經很好地瞭解了新的工作流程模塊的功能以及它的工作原理。雖然該模塊已經在其當前形狀中實現了強大的工作流程,但還有更多功能,例如:

  • 更多活動,例如用戶,角色,內容部署,表單,工作流活動和許多其他活動
  • 工作流跟蹤
  • 編輯和活動用戶體驗改進
  • 版本

您可以在此處關注GitHub上的Workflows項目:https:  //github.com/OrchardCMS/OrchardCore/projects/4

如果您對新功能有任何建議,請告訴我們!您可以 使用 @sfmskywalker 在Gitter找到我,給我發電子郵件或者只是  在GitHub上創建一個問題

 

 

Orchard Core 工作流相關介紹:https://orchardcore.readthedocs.io/en/dev/OrchardCore.Modules/OrchardCore.Workflows/

 

 

下一篇文章中,我將介紹如何使用Page 配合本次演練的工作流進行內容提交。

 Orchard Core QQ 羣:877196442 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章