Skip to content

Commit dcdbc6a

Browse files
jessica-woodland-scottdb-waltz
authored andcommitted
Pull request #326: CTCTOWALTZ-2931 data flow ui 6834
Merge in WALTZ/waltz from WALTZ/waltz-jws:CTCTOWALTZ-2931-data-flow-ui-6834 to db-feature/waltz-6834-flow-detail-rework * commit '6351068bcd8961bf6f6492aa13fba6814ee48db1': Add register new physical for logical Add register new physical for logical Data Type hover and additional phys flow fields Data Type hover and additional phys flow fields Filter counts Filter counts Direction Filters Data Type Filters Filters for assessments and breakdown into smaller components WIP, context panel Data Types Section Data Types Section
2 parents 126fb44 + 6351068 commit dcdbc6a

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)