Usage
Note: The following instructions assume that the user's preferred process views are set to “Valid Version”. Furthermore, it is assumed that email notifications are enabled in PkitConfig.xml and Stages knows about the user's email address. Finally, the user needs process application permissions.
Freeze a Phase
- Navigate to the phase to freeze.
- Select Actions –> Freeze for the phase to freeze.
- Provide a name for the new process baseline. Optionally, you can provide a description for the baseline.
- Click OK.
- Stages will inform you about the completion of the operation via email.
Update the Process
- Update the working revision process e.g. by updating to a new core process version.
- Navigate to the process start page.
- Select Actions –> Edit –> Merge working revision & valid version.
- Provide a name for the process baseline.
- Click OK.
- Stages will inform you about the completion of the operation via email.
Unfreeze a Phase
- Navigate to the start page of the process.
- Select the menu item Actions –> Edit –> Process Versions
- A table shows important information relating to the existing process versions
- Delete the baseline named “Base of frozen phase <phase to unfreeze>”.
- Follow the steps Update the Process above.
Connecting Dependent Processes
Usually a process is not a standalone entity, but is integrated into a system of dependent processes. E.g. there might be a system level process for 'System A' with dependent processes for each subsystem like 'Mechanics', 'Hardware' and 'Software'. The phases of the subsystems probably correlate in some way with the phases on system level and it might be desirable to keep track of the freeze subsystem phases on system level. This can be accomplished as shown in the following example by additional modeling and programming of a custom process start page.
<processtype ident="..."> [...] <element ident="phase" subtypes="phase milestone" freezableSubtypes="phase" freezeScript="local/freeze/moduleSpec.js"> <model> <associations> <association target="phase"> <association-type ident="correlate" sourceRole="system" targetRole="subsystem"/> </association> [...] </associations> [...] </model> <view> [...] <!--Extend the view to be able to model the correlate association--> </view> </element> [...] </processtype>
An additional association is needed to define the correlation of the system phase to the subsystem phase. Please note that the association ident can be defined freely as it is only used in the custom process start page as shown below.
Provide a custom start page at [installDir]/tomcat/webapps/pkit/local/process/pkit/[metamodelIdent]/view/screen/PkitProcess.ftl
<#ftl strip_whitespace=true> <#import "../../../view/common/object/object.ftl" as object/> <#import "../../../view/common/core/page/page.ftl" as page/> <@page.page> <@page.mainHeading> <@page.mainHeadingName> ${self.getText("process.main.title")} <@object.writeProtection /> </@page.mainHeadingName> <@page.mainHeadingInfo> ${self.processType}, ${self.getText("process.process.version", [self.version!""])} </@page.mainHeadingInfo> </@page.mainHeading> <#macro renderPhaseOverview> <#local script> function PhaseAdapter(phase) { this.phase = phase; this.dependentPhases = new Packages.org.eclipse.emf.common.util.BasicEList(); this.duration = 1; } function SubsystemAdapter(subsystem) { this.subsystem = subsystem; this.phases = new Array(); this.duration = 0; this.addPhase = function(phase, i) { this.phases.push(phase); if (this.duration <i + 1) { phase.duration = i + 1 - this.duration; } this.duration = i + 1; } } function PhaseMatrix(process) { this.system = new SubsystemAdapter(process.subsystem); this.subsystems = new Packages.java.util.LinkedHashMap(); this.init = function () { var phases = this.filter(process.phaseIndex_.list); for (var i = 0; i <phases.size(); i++) { var phase = phases.get(i); var phaseAdapter = new PhaseAdapter(phase); this.add(phaseAdapter, i); var associations = phase.getModelAssociation("correlate", "Phase", "system", null).references; for (var iterator = associations.iterator(); iterator.hasNext();) { var dependentPhase = iterator.next().target; this.add(new PhaseAdapter(dependentPhase), i); phaseAdapter.dependentPhases.add(dependentPhase); } } } this.add = function(phaseAdapter, i) { var subsystem = phaseAdapter.phase.process.subsystem; if (this.system.subsystem.equals(subsystem)) { this.system.addPhase(phaseAdapter, i); } else { var subsystemAdapter = this.subsystems.get(subsystem.id); if (subsystemAdapter == null) { subsystemAdapter = new SubsystemAdapter(subsystem); this.subsystems.put(subsystem.id, subsystemAdapter); } subsystemAdapter.addPhase(phaseAdapter, i); } } this.filter = function (phases) { var filteredPhases = new Packages.java.util.ArrayList(); for (var i = 0; i <phases.size(); i++) { var phase = phases.get(i); if (phase.findSubtype() == "phase") { filteredPhases.add(phase); } } return filteredPhases; } this.init(); } new PhaseMatrix(self); </#local> <#local phaseOverview = javascript(self, script) /> <table class="phaseOverview"> <tr> <td></td> <#local nmbrOfSubsystems=phaseOverview.subsystems?size/> <#local hasDependentPhases=nmbrOfSubsystems> 0> <@renderPhases phases = phaseOverview.system.phases hasDependents = hasDependentPhases/> </tr> <#list phaseOverview.subsystems?values as subsystem> <tr> <td>${subsystem.subsystem.name}</td> <@renderPhases phases = subsystem.phases hasDependents = false/> <#if phaseOverview.system.phases?size> subsystem.duration> <#list 0..phaseOverview.system.phases?size - 1 - subsystem.duration as i> <td></td> </#list> </#if> </tr> </#list> </table> </#macro> <#macro renderPhases phases hasDependents> <#if phases?size != 0> <#local phaseNr = -1 /> <#list 0..phases?size-1 as i> <#local phase = phases[i] /> <#local phaseNr = phaseNr + phase.duration /> <#local frozen><#if phase.phase.isFrozen()>frozen</#if></#local> <#local freezeLinkName><#if hasDependents>[Freeze all]<#else>[Freeze]</#if></#local> <@renderPhase phase=phase class="phase phase${phaseNr} ${frozen}" linkName=freezeLinkName/> </#list> </#if> </#macro> <#macro renderPhase phase linkName class="phase"> <#assign freezeLink = phase.phase.getFreezeLink(phase.dependentPhases)/> <td colspan="${phase.duration}"> <div class="wrapper"> <div class="${class}"><div class="name"> ${phase.phase.getViewLink().getHtml(phase.phase.name)}</div><div class="freezeLink">${freezeLink.getHtml(linkName)}</div></div> </div> </td> </#macro> <@renderPhaseOverview /> ${self.description!""} </@page.page>
Provide css styling for the custom start page at [installDir]/tomcat/webapps/pkit/local/process/pkit/[metamodelIdent]/view/screen/style.css.
.phaseOverview + .stages_description { margin-top: 3em; } .phaseOverview { border-spacing: 0; border-collapse: collapse; -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; } .phaseOverview tr:nth-child(2n) { background-color: #f9f9f9; border-top: 1px solid #ebebed; border-bottom: 1px solid #ebebed; } .phaseOverview td { text-align: left; padding-top: 5px; padding-bottom: 5px; padding-left: 10px; vertical-align: middle; } .phaseOverview td:first-child { text-align: right; min-width: 120px; } .phaseOverview .wrapper { display: table; width: 100%; min-width: 120px; } .phaseOverview .phase { vertical-align: middle; height: 32px; display: table-cell; padding-left: 5px; padding-right: 5px; padding-top: 2px; padding-bottom: 2px; } .phaseOverview .phase .name { white-space: nowrap; } .phaseOverview .phase .freezeLink { white-space: nowrap; text-align: right; } .phaseOverview .phase.frozen { background-image: url(../../../../../img/frozen.png); background-repeat: no-repeat; background-position: right; padding-right: 40px; } .phaseOverview .phase *, .phaseOverview .phase a:link, .phaseOverview .phase a:visited { color: #ffffff; } .phaseOverview .phase a:focus, .phaseOverview .phase a:hover { color: #000000; text-decoration: none; } .phaseOverview .phase a:active { color: #ffffff; } .phaseOverview .phase { transition: all 0.2s; -webkit-transition: all 0.2s; -moz-transition: all 0.2s; -o-transition: all 0.2s; } .phaseOverview .phase0 { background-color: #3366cc;} .phaseOverview .phase0:hover { background-color: #7094db; } .phaseOverview .phase1 { background-color: #ff9900; } .phaseOverview .phase1:hover { background-color: #ffb84d; } .phaseOverview .phase2 { background-color: #990099; } .phaseOverview .phase2:hover { background-color: #b84db8; } .phaseOverview .phase3 { background-color: #dc3912; } .phaseOverview .phase3:hover { background-color: #e77459; } .phaseOverview .phase4 { background-color: #66aa00; } .phaseOverview .phase4:hover { background-color: #94c44d; } .phaseOverview .phase5 { background-color: #316395; } .phaseOverview .phase5:hover { background-color: #6f92b5; } .phaseOverview .phase6 { background-color: #b82e2e; } .phaseOverview .phase6:hover { background-color: #cb6b6b; } .phaseOverview .phase7 { background-color: #6633cc; } .phaseOverview .phase7:hover { background-color: #9470db; } .phaseOverview .phase8 { background-color: #aaaa11; } .phaseOverview .phase8:hover { background-color: #c4c458; }