Passed
Push — master ( e14e22...172c7d )
by
unknown
03:44
created

details-container.ts ➔ resetZoomPosition   A

Complexity

Conditions 2

Size

Total Lines 11
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 10
dl 0
loc 11
rs 9.9
c 0
b 0
f 0
cc 2
1
import {
2
    selectDetailsContainerDiv,
3
    selectDetailsExitButtonWrapper,
4
    selectDetailsRootNodeContainer,
5
    selectDetailsViewContainer,
6
    selectDetailsZoom,
7
} from '../utils/helpers/Selectors';
8
import { Colors, ElementIds, FAST_TRANSITION_DURATION } from '../utils/AppConsts';
9
import { symbol, symbolCross, zoom, zoomIdentity } from 'd3';
10
import { changeZoom, createZoom } from '../zoom/zoom';
11
import { TreeNode } from '../components/types';
12
import { createRootNode } from './root-node';
13
import { mapNodeToTreeStructure, TreeStructure } from './details-mappers';
14
import { createDiagram, createTree, getRootYPosition } from './details-diagram';
15
16
export function createDetailsViewContainer(width: number, height: number) {
17
    const containerWidth = width * 4;
18
    const containerHeight = height * 4;
19
20
    const container = selectDetailsContainerDiv()
21
        .style('display', 'none')
22
        .style('opacity', 0)
23
        .append('svg')
24
        .attr('id', ElementIds.DETAILS_VIEW_CONTAINER)
25
        .attr('x', 0)
26
        .attr('y', 0)
27
        .attr('width', containerWidth)
28
        .attr('height', containerHeight)
29
        .attr('viewBox', `0 0 ${width} ${height}`)
30
        .attr('preserveAspectRatio', 'xMidYMid meet');
31
    container
32
        .append('rect')
33
        .attr('width', width)
34
        .attr('height', height)
35
        .attr('fill', Colors.WHITE);
36
    createZoom(container, ElementIds.DETAILS_ZOOM);
37
    createDetailsExitButton();
38
}
39
40
function createDetailsExitButton() {
41
    selectDetailsViewContainer()
42
        .append('g')
43
        .attr('id', ElementIds.DETAILS_EXIT_BUTTON)
44
        .attr('cursor', 'pointer')
45
        .append('rect')
46
        .attr('transform', 'translate(5,5)')
47
        .attr('width', 10)
48
        .attr('height', 10)
49
        .attr('rx', 5)
50
        .attr('ry', 5)
51
        .attr('fill', Colors.WHITE);
52
    selectDetailsExitButtonWrapper()
53
        .append('path')
54
        .attr('transform', 'translate(10,10) rotate(45)')
55
        .attr(
56
            'd',
57
            symbol()
58
                .type(symbolCross)
59
                .size(20)
60
        );
61
}
62
63
function resetZoomPosition() {
64
    const detailsContainerDiv = selectDetailsContainerDiv().node();
65
    const { width, height } = detailsContainerDiv ? detailsContainerDiv.getBoundingClientRect() : { width: 0, height: 0 };
66
67
    const container = selectDetailsViewContainer();
68
69
    container.call(
70
        zoom<SVGSVGElement, unknown>().on('zoom', changeZoom(ElementIds.DETAILS_ZOOM)).transform,
71
        // rough center screen on diagram's root node
72
        zoomIdentity.translate(-width / 5.3, -height / 2.65)
73
    );
74
}
75
76
async function createDiagrams(
77
    container: ReturnType<typeof selectDetailsZoom>,
78
    consumersData: TreeStructure,
79
    providersData: TreeStructure,
80
    width: number,
81
    height: number
82
) {
83
    const rootNodeName = consumersData.name || providersData.name;
84
    consumersData.name = '';
85
    providersData.name = '';
86
    const consumersTree = createTree(consumersData);
87
    const providersTree = createTree(providersData);
88
89
    const consumersRootYPosition = getRootYPosition(consumersTree);
90
    const providersRootYPosition = getRootYPosition(providersTree);
91
92
    const rootNodeYOffset = Math.max(consumersRootYPosition, providersRootYPosition);
93
94
    const consumersDiagram = createDiagram(consumersTree, width, height, rootNodeYOffset, true);
95
    const providersDiagram = createDiagram(providersTree, width, height, rootNodeYOffset);
96
97
    await createRootNode(container, width, height, rootNodeName, Boolean(providersDiagram), Boolean(consumersDiagram));
98
99
    const detailsRootNodeContainer = selectDetailsRootNodeContainer();
100
    const detailsRootNodeBBox = detailsRootNodeContainer.node()?.getBBox() || { width: 0, x: 0 };
101
102
    const providersDiagramNode = providersDiagram?.node();
103
    const consumersDiagramNode = consumersDiagram?.node();
104
105
    const xOffsetFromRootNodeCenter = detailsRootNodeBBox.width / 7;
106
107
    if (providersDiagramNode) {
108
        providersDiagram?.attr('x', xOffsetFromRootNodeCenter);
109
        container.append<SVGSVGElement>(() => providersDiagramNode);
110
    }
111
112
    if (consumersDiagramNode) {
113
        consumersDiagram?.attr('x', -xOffsetFromRootNodeCenter);
114
        container.append<SVGSVGElement>(() => consumersDiagramNode);
115
    }
116
117
    detailsRootNodeContainer.raise();
118
}
119
120
export function initializeDetailsView(node: TreeNode) {
121
    const consumerNodes = mapNodeToTreeStructure(node, 'consumers');
122
    const providerNodes = mapNodeToTreeStructure(node, 'providers');
123
124
    const detailsViewContainer = selectDetailsViewContainer();
125
    const width = Number(detailsViewContainer.attr('width'));
126
    const height = Number(detailsViewContainer.attr('height'));
127
128
    const detailsZoom = selectDetailsZoom();
129
    createDiagrams(detailsZoom, consumerNodes, providerNodes, width, height);
130
    switchDetailsVisibility();
131
132
    resetZoomPosition();
133
}
134
135
export function shutdownDetailsView() {
136
    switchDetailsVisibility();
137
    deleteDiagrams();
138
}
139
140
function deleteDiagrams() {
141
    selectDetailsZoom()
142
        .transition()
143
        .selectAll('*')
144
        .remove();
145
}
146
147
export function switchDetailsVisibility() {
148
    const container = selectDetailsContainerDiv();
149
    const isVisible = container.style('display') === 'block';
150
    if (isVisible) {
151
        container
152
            .transition()
153
            .duration(FAST_TRANSITION_DURATION)
154
            .style('opacity', 0)
155
            .transition()
156
            .style('display', 'none');
157
    } else {
158
        container
159
            .style('display', 'block')
160
            .transition()
161
            .duration(FAST_TRANSITION_DURATION)
162
            .style('opacity', 1);
163
    }
164
}
165