Plone: Froze state changing for an object (conditioned) - plone

Is it possible to froze state changing for an given object based on a condition?
What I have:
meetings (like events)
subscribers (participants in meetings)
the subscribers can be approved or not
What I need:
the subscribers of old meetings to have the state frozen (nobody to change an approved one to not approved etc).
Can you suggest a solution for this case?

The solution was to use a transition guard: https://docs.plone.org/4/en/old-reference-manuals/archgenxml/basic-features/workflows.html?highlight=guard#transition-guards
I used as an expression python:here.is_allowed_state_change() is True.
I defined is_allowed_state_change to return True if the meeting is not ended.

Related

WF4: Transition check order

In a state machine I have a state which has an entry activity and that activity has an out parameter which contains the information about the next state.
This info is then checked in the transition conditions.
One of the pitfalls is that you may overlook a transition. I wanted to create a default transition that runs into a logging activity and returns the state machine into a stable condition without getting stuck in that state because no transition condition evaluates to true.
However I can't just have a conditionless transition because there appears to be no way to order the checks like one would do in a code switch statement.
Any advice would be appreciated.
Could you set your Out parameter to a default state e.g. "NoTransition", at the start of your activity. Then if the Out parameter is not set to a valid transition during the activity the "NoTransition" state is output and acts as the default and can be picked up by the transition conditions

Which pattern to store the selected item of a list in Redux

Let's imagine I want to be able to select a task in the Todo with React-Redux.
Where should I store this state ?
First solution: Add a isActive: true attribut to the task
Second solution: Create a new reducer just to handle the id of the selected item.
I dislike both solutions: the first one feels like I'm storing something unrelated to the task in it, the second one feels overkilled to create a whole reducer only to store an id.
Is there any other option ? What's best ?
Thanks
I'd say it depends on your use case.
For a big app that has tons of UI state to persist, it makes a lot of sense to have a special reducer to mutate a slice of the store related to the UI.
It is valid to have a isActive: boolean property per task if you can have multiple tasks active at the same time. Even though it's not related to the task from the task data perspective, it actually is from an application perspective of the task. Your redux store main goal is to be your application source of truth rather than just mirroring your API data models.
You can also have a single isActive: id if you can only have a single task active/selected at the time.
You can also just use the component state. The limitation of this is that it won't persist and it won't be shared. For instance, if you want to have a save button, that button will have to be within the component that has the selected state.
There's nothing really wrong with either of the two options you've listed. But, if you're looking for other options, you can
1) Include the selected item in the todos reducer state, so your state object would look like this:
{
selected: id,
list: [{id, text, completed}, ...]
}
2) If you don't need the selected item anywhere else in your app, you can simply store it in your local state. There's nothing wrong with mixing both Redux for application state and local state for data contained solely within your component.

Recognize/raise an alert when a specific service has not been called within a time period by "Developer App"

Say I have a resource defined such that the service https://api.mydomainname.com/v1/stores/ABC/order where "ABC" has a direct relation to a Developer App entry. I also have a Custom Attribute for the maximum number of seconds that can elapse between calls; if the time between calls exceeds that threshold, I'd like to take an action (make an call, raise a Nagios alert, etc).
Example:
ABC (api key: 54c34ce0f7691840093bfba55a10c782) has a 300s elapsed time threshold
XYZ (api key: af9843af2d190f72481183a8645659ac) has a 600s elapsed time threshold
Do we have any ideas on how to do this on for all related message processors in an Organization?
I do not want to have to have a call to check if the threshold has been exceeded.
I'm thinking I have to push this further down to the actual service, but if there is an Apigee based potential solution, I'd be interested.
One option is to use the <LookupCache> and <PopulateCache> policies. Caching is distributed (across MPs) by default.
You could store the threshold value (300s/600s/etc) as a custom attribute on the develop app. After <VerifyAPIKey> policy, this attribute value should be automatically populated and you can use that reference in the <PopulateCache> policy. Example flow steps:
VerifyAPIKey (will get the threshold value for populate.
LookupCache
If cache hit, continue. Else, raise custom fault or execute custom logic.
PopulateCache to create/update entry, reading expiry from variable reference of attribute populated by #1). If the entry already exists, it will re-populate the entry with fresh expiration, essentially reseting the last request time.

How to determine next activity assignee in workflow in tridion

I am writing eventhandler for determining the workflow activities. I am able to get the currrent activity assignee.
I need to get the next activity assignee(i.e to which group the activity is assigned to).
Inside the TridionActivityDefinitinData for NextActivityDefinitions i find only Title and Idref of the activities.
Please let me know how to find the next possible activities' assignee.
Have a look at this question How to get the Next Activity Details from the FinishActivityEvent Hanlder?, where user978511 answered it there better than I can.
From what I see there, you'll need something like this:
FinishActivityEventArgs.ActivityFinish.NextAssignee
If that is indeed the case, I marked your question as a duplicate from that one.
Hope this helps someone...
Read the Process Definition for the full list of activities:
ProcessDefinitionData pdd = CoreServiceClient.Read(ProcessInstance.ProcessDefinition.IdRef, null) as ProcessDefinitionData;
then you can use your current posostion (not zero based) to index out from the Activitiy Definitions (zero based):
pdd.ActivityDefinitions[(int)ActivityInstance.Position].Assignee.Title
The above will get you the next activity information. If you want previous activities start by subtracting two from the current position and indexing from the Process Instance Activities:
ProcessInstance.Activities[(int)ActivityInstance.Position - 2].FinishMessage
Enjoy

Statefinalization/initialization activity only runs on leaf states

I am trying to get my Windows State Machine workflow to communicate with end users. The general pattern I am trying to implement within a StateActivity is:
StateInitializationActivity: Send a message to user requesting an answer to a question (e.g. "Do you approve this document?"), together with the context for...
...EventDrivenActivity: Deal with answer sent by user
StateFinalizationActivity: Cancel message (e.g. document is withdrawn and no longer needs approval)
This all works fine if the StateActivity is a "Leaf State" (i.e. has no child states). However, it does not work if I want to use recursive composition of states. For non-leaf states, StateInitialization and StateFinalization do not run (I confirmed this behaviour by using Reflector to inspect the StateActivity source code). The EventDrivenActivity is still listening, but the end user doesn't know what's going on.
For StateInitialization, I thought that one way to work around this would be to replace it with an EventDrivenActivity and a zero-delay timer. I'm stuck with what to do about StateFinalization.
So - does anyone have any ideas about how to get a State Finalization Activity to always run, even for non-leaf states?
Its unfortunate that the structure of "nested states" is one of a "parent" containing "children", the designer UI re-enforces this concept. Hence its quite natural and intuative to think the way you are thinking. Its unfortunate because its wrong.
The true relationship is one of "General" -> "Specific". Its in effect a hierachical class structure. Consider a much more familar such relationship:-
public class MySuperClass
{
public MySuperClass(object parameter) { }
protected void DoSomething() { }
}
public class MySubClass : MySuperClass
{
protected void DoSomethingElse() { }
}
Here MySubClass inherits DoSomething from SuperClass. The above though is broken because the SuperClass doesn't have a default constructor. Also parameterised constructor of SuperClass is not inherited by SubClass. In fact logically a sub-class never inherits the constructors (or destructors) of the super-class. (Yes there is some magic wiring up default constructors but thats more sugar than substance).
Similarly the relationship between StateAcivities contained with another StateActivity is actually that the contained activity is a specialisation of the container. Each contained activity inherits the set of event driven activities of the container. However, each contained StateActivity is a first class discrete state in the workflow same as any other state.
The containing activity actual becomes an abstract, it can not be transitioned to and importantly there is no real concept of transition to a state "inside" another state. By extension then there is no concept of leaving such an outer state either. As a result there is no initialization or finalization of the containing StateActivity.
A quirk of the designer allows you to add a StateInitialization and StateFinalization then add StateActivities to a state. If you try it the other way round the designer won't let you because it knows the Initialization and Finalization will never be run.
I realise this doesn't actually answer your question and I'm loath to say in this case "It can't be done" but if it can it will be a little hacky.
OK, so here’s what I decided to do in the end. I created a custom tracking service which looks for activity events corresponding to entering or leaving the states which are involved in communication with end users. This service enters decisions for the user into a database when the state is entered and removes them when the state is left. The user can query the database to see what decisions the workflow is waiting on. The workflow listens for user responses using a ReceiveActivity in an EventDrivenActivity. This also works for decisions in parent ‘superstates’. This might not be exactly what a "Tracking Service" is meant to be for, but it seems to work
I've thought of another way of solving the problem. Originally, I had in mind that for communications I would use the WCF-integrated SendActivity and ReceiveActivity provided in WF 3.5.
However, in the end I came to the conclusion that it's easier to ignore these activities and implement your own IEventActivity with a local service. IEventActivity.Subscribe can be used to indicate to users that there is a question for them to answer and IEventActivity.Unsubscribe can be used to cancel the question. This means that separate activities in the State's inialization and finalization blocks are not required. The message routing is done manually using workflow queues and the user's response is added to the queue with appropriate name. I used Guid's for the queue names, and these are passed to the user during the IEventActivity.Subscribe call.
I used the 'File System Watcher' example in MSDN to work out how to do this.
I also found this article very insructive: http://www.infoq.com/articles/lublinksy-workqueue-mgr

Resources