Skip to content

Commit c3a71b5

Browse files
Merge pull request #6853 from deutschebank/db-contrib/waltz-6834-flow-detail-rework
Db contrib/waltz 6834 flow detail rework
2 parents 76b7c04 + dcdbc6a commit c3a71b5

17 files changed

Lines changed: 1488 additions & 44 deletions

waltz-ng/client/common/svelte/DataTypeTreeSelector.svelte

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<script>
22
import {dataTypeStore} from "../../svelte-stores/data-type-store";
3-
import {buildHierarchies, doSearch, prepareSearchNodes} from "../hierarchy-utils";
3+
import {buildHierarchies, doSearch, prepareSearchNodes, reduceToSelectedNodesOnly} from "../hierarchy-utils";
44
import DataTypeTreeNode from "./DataTypeTreeNode.svelte";
55
import SearchInput from "./SearchInput.svelte";
66
import _ from "lodash";
@@ -9,6 +9,7 @@
99
export let nonConcreteSelectable = true;
1010
export let selectionFilter = () => true;
1111
export let expanded = true;
12+
export let dataTypeIds = [];
1213
1314
const root = {name: "Root", isExpanded: true};
1415
@@ -31,7 +32,10 @@
3132
let dataTypes = [];
3233
3334
$: dataTypes = $dataTypesCall.data;
34-
$: searchNodes = prepareSearchNodes(dataTypes);
35+
$: requiredNodes = _.isEmpty(dataTypeIds)
36+
? dataTypes
37+
: reduceToSelectedNodesOnly(dataTypes, dataTypeIds);
38+
$: searchNodes = prepareSearchNodes(requiredNodes);
3539
$: displayedHierarchy = calcDisplayHierarchy(searchNodes, qry);
3640
3741
</script>

waltz-ng/client/data-flow/components/data-flow-section/data-flow-section.html

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -281,8 +281,9 @@ <h4>Bulk Insert Logical Data Flows</h4>
281281

282282
<div class="wt-tab wt-active"
283283
ng-if="$ctrl.activeTab.id === 'FLOW_DETAIL'">
284-
<waltz-logical-flow-view-grid parent-entity-ref="$ctrl.parentEntityRef">
285-
</waltz-logical-flow-view-grid>
284+
<waltz-svelte-component parent-entity-ref="$ctrl.parentEntityRef"
285+
component="$ctrl.FlowDetailPanel">
286+
</waltz-svelte-component>
286287
</div>
287288

288289
<div class="wt-tab wt-active"

waltz-ng/client/data-flow/components/data-flow-section/data-flow-section.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import FlowClassificationLegend
2828
from "../../../flow-classification-rule/components/svelte/FlowClassificationLegend.svelte";
2929
import LogicalFlowScrollPanel from "../svelte/FlowDecoratorExplorerPanel.svelte"
3030
import {lastViewedFlowTabKey} from "../../../user";
31+
import FlowDetailPanel from "../svelte/flow-detail-tab/FlowDetailPanel.svelte"
3132

3233
const bindings = {
3334
parentEntityRef: "<",
@@ -48,6 +49,7 @@ const modes = {
4849
}
4950

5051
const initialState = {
52+
FlowDetailPanel,
5153
FlowClassificationLegend,
5254
LogicalFlowScrollPanel,
5355
activeTab: null,
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
<script>
2+
3+
4+
import {mkAssessmentFilter, mkDefinitionFilterId} from "./flow-detail-utils";
5+
import _ from "lodash";
6+
import {filters, updateFilters} from "./flow-details-store";
7+
import RatingIndicatorCell from "../../../../ratings/components/rating-indicator-cell/RatingIndicatorCell.svelte";
8+
import NoData from "../../../../common/svelte/NoData.svelte";
9+
10+
11+
export let assessmentFilters = [];
12+
13+
function selectRating(definitionId, ratingId) {
14+
15+
const filterId = mkDefinitionFilterId(definitionId);
16+
17+
const existingFilter = _.find($filters, f => f.id === filterId);
18+
19+
const ratingInfo = {
20+
definitionId,
21+
ratingId
22+
};
23+
24+
const existingRatings = _.get(existingFilter, "ratings", []);
25+
26+
const newRatings = _.some(existingRatings, r => _.isEqual(r, ratingInfo))
27+
? _.filter(existingRatings, d => !_.isEqual(d, ratingInfo))
28+
: _.concat(existingRatings, [ratingInfo]);
29+
30+
const newFilter = mkAssessmentFilter(filterId, newRatings)
31+
32+
updateFilters(filterId, newFilter);
33+
34+
}
35+
36+
function clearFiltersForDefinition(defnId) {
37+
const filterId = mkDefinitionFilterId(defnId);
38+
$filters = _.reject($filters, d => d.id === filterId);
39+
}
40+
41+
function isSelected(filters, defnId, ratingId){
42+
const ratingInfo = { definitionId: defnId, ratingId: ratingId};
43+
const filter = _.find(filters, d => d.id === mkDefinitionFilterId(defnId));
44+
const filteredRatings = _.get(filter, "ratings", []);
45+
return _.some(filteredRatings, r => _.isEqual(r, ratingInfo))
46+
}
47+
48+
</script>
49+
50+
<div class="help-block"
51+
style="padding-top: 1em">
52+
Use the assessment ratings to filter the logical flows. Only ratings aligned to a flow can be filtered upon.
53+
</div>
54+
<div style="display: flex; gap: 1em">
55+
{#each assessmentFilters as assessment}
56+
<div style="flex: 1 1 30%">
57+
<table class="table table-condensed table">
58+
<thead>
59+
<tr>
60+
<th>{assessment?.definition?.name}
61+
<span>
62+
<button class="btn btn-skinny"
63+
on:click={() => clearFiltersForDefinition(assessment?.definition.id)}>
64+
Clear
65+
</button>
66+
</span>
67+
</th>
68+
</tr>
69+
</thead>
70+
<tbody>
71+
{#each assessment?.ratings as rating}
72+
<tr class="clickable"
73+
class:selected={isSelected($filters, assessment?.definition.id, rating.id)}
74+
on:click={() => selectRating(assessment.definition.id, rating.id)}>
75+
<td>
76+
<RatingIndicatorCell {...rating}/>
77+
</td>
78+
</tr>
79+
{/each}
80+
</tbody>
81+
</table>
82+
</div>
83+
{:else}
84+
<NoData type="info">No flows have been given a rating for a primary assessment</NoData>
85+
{/each}
86+
</div>
87+
88+
<style>
89+
90+
.selected {
91+
background-color: #eee;
92+
}
93+
94+
</style>
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
<script>
2+
3+
4+
import {mkDataTypeFilter, mkDataTypeFilterId} from "./flow-detail-utils";
5+
import _ from "lodash";
6+
import {filters, updateFilters} from "./flow-details-store";
7+
import DataTypeTreeSelector from "../../../../common/svelte/DataTypeTreeSelector.svelte";
8+
import {flattenChildren} from "../../../../common/hierarchy-utils";
9+
10+
export let dataTypes = [];
11+
12+
$: dataTypeIds = _.map(dataTypes, d => d.id);
13+
14+
function selectDataType(evt) {
15+
16+
const filterId = mkDataTypeFilterId();
17+
const dataType = evt.detail;
18+
19+
const children = flattenChildren(dataType, [dataType]);
20+
const dataTypesToToggle = _.map(children, d => d.id);
21+
22+
const existingFilter = _.find($filters, f => f.id === filterId);
23+
24+
const existingDataTypes = _.get(existingFilter, "dataTypes", []);
25+
26+
const dataTypeId = dataType.id;
27+
28+
const newDataTypes = _.includes(existingDataTypes, dataTypeId)
29+
? _.without(existingDataTypes, ...dataTypesToToggle)
30+
: _.uniq(_.concat(existingDataTypes, dataTypesToToggle));
31+
32+
const newFilter = mkDataTypeFilter(filterId, newDataTypes);
33+
34+
return updateFilters(filterId, newFilter)
35+
}
36+
37+
function clearFilters() {
38+
const filterId = mkDataTypeFilterId();
39+
$filters = _.reject($filters, d => d.id === filterId);
40+
}
41+
42+
function filterAllDataTypes() {
43+
const filterId = mkDataTypeFilterId();
44+
const newFilter = mkDataTypeFilter(filterId, dataTypeIds);
45+
const withoutFilter = _.reject($filters, d => d.id === filterId);
46+
$filters = _.concat(withoutFilter, newFilter);
47+
}
48+
49+
$: dtFilter = _.find($filters, d => d.id === mkDataTypeFilterId());
50+
$: filteredDataTypes = _.get(dtFilter, ["dataTypes"], []);
51+
52+
$: selectionFilter = (x) => {
53+
return _.includes(filteredDataTypes, x.id);
54+
}
55+
56+
57+
</script>
58+
59+
<div class="help-block"
60+
style="padding-top: 1em">
61+
Use the data types to filter the logical flows. Selecting a datatype will add or remove it from the filter, along with all of its children.
62+
</div>
63+
<DataTypeTreeSelector multiSelect={true}
64+
expanded={true}
65+
dataTypeIds={dataTypeIds}
66+
nonConcreteSelectable={true}
67+
selectionFilter={selectionFilter}
68+
on:select={selectDataType}/>
69+
70+
<div style="padding-top: 1em">
71+
<button class="btn btn-skinny"
72+
on:click={filterAllDataTypes}>
73+
Deselect All
74+
</button>
75+
|
76+
<button class="btn btn-skinny"
77+
on:click={clearFilters}>
78+
Select All
79+
</button>
80+
</div>
81+
82+
<style>
83+
84+
85+
</style>
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<script>
2+
3+
import EntityLink from "../../../../common/svelte/EntityLink.svelte";
4+
import {flowClassificationStore} from "../../../../svelte-stores/flow-classification-store";
5+
import _ from "lodash";
6+
7+
export let decorators = [];
8+
9+
let flowClassificationCall = flowClassificationStore.findAll();
10+
11+
$: flowClassifications = $flowClassificationCall?.data;
12+
$: flowClassificationsByCode = _.keyBy(flowClassifications, d => d.code);
13+
14+
</script>
15+
16+
<h4>Data Types</h4>
17+
<ul class="list-unstyled">
18+
{#each _.orderBy(decorators, d => d.decoratorEntity.name) as type}
19+
<li style="padding-bottom: 2px">
20+
<div class="rating-icon"
21+
style={`background-color: ${flowClassificationsByCode[type.rating]?.color}`}>
22+
</div>
23+
<EntityLink ref={type.decoratorEntity}
24+
showIcon={false}>
25+
</EntityLink>
26+
</li>
27+
{/each}
28+
</ul>
29+
30+
<style>
31+
32+
.rating-icon {
33+
display: inline-block;
34+
height: 1em;
35+
width: 1em;
36+
border:1px solid #ccc;
37+
border-radius: 2px;
38+
}
39+
40+
</style>

0 commit comments

Comments
 (0)