@centreon/ui 25.10.5 → 25.10.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/Graph/BarChart/BarChart.cypress.spec.tsx +55 -83
- package/src/Graph/BarChart/BarStack.tsx +26 -15
- package/src/Graph/BarChart/MemoizedGroup.tsx +8 -7
- package/src/Graph/Chart/BasicComponents/Lines/StackedLines/index.tsx +5 -4
- package/src/Graph/Chart/BasicComponents/Lines/index.tsx +94 -94
- package/src/Graph/Chart/Chart.tsx +4 -2
- package/src/Graph/common/timeSeries/index.ts +65 -40
- package/src/InputField/Select/Autocomplete/Connected/index.tsx +6 -6
- package/src/InputField/Select/Autocomplete/index.tsx +28 -17
- package/src/InputField/Select/Option.tsx +3 -3
- package/src/components/Form/AccessRights/ShareInput/ShareInput.tsx +4 -3
- package/src/components/Form/AccessRights/ShareInput/useShareInput.tsx +15 -10
- package/src/components/Menu/Button/MenuButton.tsx +1 -2
package/package.json
CHANGED
|
@@ -84,6 +84,61 @@ const checkWidth = (orientation): void => {
|
|
|
84
84
|
};
|
|
85
85
|
|
|
86
86
|
describe('Bar chart', () => {
|
|
87
|
+
it('displays a tooltip when a single bar is hovered', () => {
|
|
88
|
+
initialize({
|
|
89
|
+
orientation: 'horizontal'
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
checkWidth('horizontal');
|
|
93
|
+
cy.contains('0 ms').should('be.visible');
|
|
94
|
+
cy.contains('20').should('be.visible');
|
|
95
|
+
cy.contains(':40 AM').should('be.visible');
|
|
96
|
+
|
|
97
|
+
cy.findByTestId('stacked-bar-10-0-7650.368581547736').realHover();
|
|
98
|
+
|
|
99
|
+
cy.contains('06/19/2024').should('be.visible');
|
|
100
|
+
cy.contains('Centreon-Server: Round-Trip Maximum Time').should(
|
|
101
|
+
'be.visible'
|
|
102
|
+
);
|
|
103
|
+
cy.contains('7.47 KB').should('be.visible');
|
|
104
|
+
|
|
105
|
+
cy.makeSnapshot();
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it('displays a tooltip when a stacked bar is hovered', () => {
|
|
109
|
+
initialize({
|
|
110
|
+
data: dataPingServiceStacked,
|
|
111
|
+
orientation: 'horizontal',
|
|
112
|
+
tooltip: {
|
|
113
|
+
mode: 'all',
|
|
114
|
+
sortOrder: 'ascending'
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
checkWidth('horizontal');
|
|
119
|
+
cy.contains('0 ms').should('be.visible');
|
|
120
|
+
cy.contains('20').should('be.visible');
|
|
121
|
+
cy.contains(':40 AM').should('be.visible');
|
|
122
|
+
|
|
123
|
+
cy.findByTestId('stacked-bar-1-0-0.05296').realHover();
|
|
124
|
+
|
|
125
|
+
cy.contains('06/19/2024').should('be.visible');
|
|
126
|
+
cy.contains('Centreon-Server: Round-Trip Maximum Time').should(
|
|
127
|
+
'be.visible'
|
|
128
|
+
);
|
|
129
|
+
cy.contains('Centreon-Server: Round-Trip Average Time').should(
|
|
130
|
+
'be.visible'
|
|
131
|
+
);
|
|
132
|
+
cy.contains('Centreon-Server: Round-Trip Minimum Time').should(
|
|
133
|
+
'be.visible'
|
|
134
|
+
);
|
|
135
|
+
cy.contains('0.05 ms').should('be.visible');
|
|
136
|
+
cy.contains('0.02 ms').should('be.visible');
|
|
137
|
+
cy.contains('0.11 ms').should('be.visible');
|
|
138
|
+
|
|
139
|
+
cy.findByTestId('stacked-bar-3-0-0.16196').should('be.visible');
|
|
140
|
+
});
|
|
141
|
+
|
|
87
142
|
['horizontal', 'vertical'].forEach((orientation) => {
|
|
88
143
|
it(`displays the bar chart ${orientation}ly`, () => {
|
|
89
144
|
initialize({ orientation });
|
|
@@ -183,27 +238,6 @@ describe('Bar chart', () => {
|
|
|
183
238
|
});
|
|
184
239
|
});
|
|
185
240
|
|
|
186
|
-
it('displays a tooltip when a single bar is hovered', () => {
|
|
187
|
-
initialize({
|
|
188
|
-
orientation: 'horizontal'
|
|
189
|
-
});
|
|
190
|
-
|
|
191
|
-
checkWidth('horizontal');
|
|
192
|
-
cy.contains('0 ms').should('be.visible');
|
|
193
|
-
cy.contains('20').should('be.visible');
|
|
194
|
-
cy.contains(':40 AM').should('be.visible');
|
|
195
|
-
|
|
196
|
-
cy.findByTestId('stacked-bar-10-0-7650.368581547736').realHover();
|
|
197
|
-
|
|
198
|
-
cy.contains('06/19/2024').should('be.visible');
|
|
199
|
-
cy.contains('Centreon-Server: Round-Trip Maximum Time').should(
|
|
200
|
-
'be.visible'
|
|
201
|
-
);
|
|
202
|
-
cy.contains('7.47 KB').should('be.visible');
|
|
203
|
-
|
|
204
|
-
cy.makeSnapshot();
|
|
205
|
-
});
|
|
206
|
-
|
|
207
241
|
it('does not display a tooltip when a bar is hovered and a props is set', () => {
|
|
208
242
|
initialize({
|
|
209
243
|
data: dataPingServiceStacked,
|
|
@@ -228,68 +262,6 @@ describe('Bar chart', () => {
|
|
|
228
262
|
cy.makeSnapshot();
|
|
229
263
|
});
|
|
230
264
|
|
|
231
|
-
it('displays a tooltip when a stacked bar is hovered', () => {
|
|
232
|
-
initialize({
|
|
233
|
-
data: dataPingServiceStacked,
|
|
234
|
-
orientation: 'horizontal',
|
|
235
|
-
tooltip: {
|
|
236
|
-
mode: 'all',
|
|
237
|
-
sortOrder: 'ascending'
|
|
238
|
-
}
|
|
239
|
-
});
|
|
240
|
-
|
|
241
|
-
checkWidth('horizontal');
|
|
242
|
-
cy.contains('0 ms').should('be.visible');
|
|
243
|
-
cy.contains('20').should('be.visible');
|
|
244
|
-
cy.contains(':40 AM').should('be.visible');
|
|
245
|
-
|
|
246
|
-
cy.findByTestId('stacked-bar-1-0-0.05296').realHover();
|
|
247
|
-
|
|
248
|
-
cy.contains('06/19/2024').should('be.visible');
|
|
249
|
-
cy.contains('Centreon-Server: Round-Trip Maximum Time').should(
|
|
250
|
-
'be.visible'
|
|
251
|
-
);
|
|
252
|
-
cy.contains('Centreon-Server: Round-Trip Average Time').should(
|
|
253
|
-
'be.visible'
|
|
254
|
-
);
|
|
255
|
-
cy.contains('Centreon-Server: Round-Trip Minimum Time').should(
|
|
256
|
-
'be.visible'
|
|
257
|
-
);
|
|
258
|
-
cy.contains('0.05 ms').should('be.visible');
|
|
259
|
-
cy.contains('0.02 ms').should('be.visible');
|
|
260
|
-
cy.contains('0.11 ms').should('be.visible');
|
|
261
|
-
|
|
262
|
-
cy.findByTestId('stacked-bar-3-0-0.16196').should('be.visible');
|
|
263
|
-
});
|
|
264
|
-
|
|
265
|
-
it('displays a tooltip with a single metric when a stacked bar is hovered and a prop is set', () => {
|
|
266
|
-
initialize({
|
|
267
|
-
data: dataPingServiceStacked,
|
|
268
|
-
orientation: 'horizontal',
|
|
269
|
-
tooltip: {
|
|
270
|
-
mode: 'single',
|
|
271
|
-
sortOrder: 'descending'
|
|
272
|
-
}
|
|
273
|
-
});
|
|
274
|
-
|
|
275
|
-
checkWidth('horizontal');
|
|
276
|
-
cy.contains('0 ms').should('be.visible');
|
|
277
|
-
cy.contains('20').should('be.visible');
|
|
278
|
-
cy.contains(':40 AM').should('be.visible');
|
|
279
|
-
|
|
280
|
-
cy.findByTestId('stacked-bar-1-0-0.05296').realHover();
|
|
281
|
-
|
|
282
|
-
cy.contains('06/19/2024').should('be.visible');
|
|
283
|
-
cy.contains('Centreon-Server: Round-Trip Average Time').should(
|
|
284
|
-
'be.visible'
|
|
285
|
-
);
|
|
286
|
-
cy.contains('0.05 ms').should('be.visible');
|
|
287
|
-
|
|
288
|
-
cy.findByTestId('stacked-bar-3-0-0.16196').should('be.visible');
|
|
289
|
-
|
|
290
|
-
cy.makeSnapshot();
|
|
291
|
-
});
|
|
292
|
-
|
|
293
265
|
it('displays the bottom axis correctly when data starts from several days ago', () => {
|
|
294
266
|
initialize({
|
|
295
267
|
data: dataLastWeek,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { memo } from 'react';
|
|
1
|
+
import { memo, ReactElement } from 'react';
|
|
2
2
|
|
|
3
3
|
import { ScaleType, scaleBand } from '@visx/scale';
|
|
4
4
|
import { BarRounded } from '@visx/shape';
|
|
@@ -22,6 +22,7 @@ interface Props extends Omit<UseBarStackProps, 'xScale'> {
|
|
|
22
22
|
barWidth: number;
|
|
23
23
|
isTooltipHidden: boolean;
|
|
24
24
|
neutralValue: number;
|
|
25
|
+
isStacked?: boolean;
|
|
25
26
|
}
|
|
26
27
|
|
|
27
28
|
const getPadding = ({ padding, size, isNegativeValue }): number => {
|
|
@@ -83,8 +84,9 @@ const BarStack = ({
|
|
|
83
84
|
barIndex,
|
|
84
85
|
isTooltipHidden,
|
|
85
86
|
barStyle = { opacity: 1, radius: 0.2 },
|
|
86
|
-
neutralValue
|
|
87
|
-
|
|
87
|
+
neutralValue,
|
|
88
|
+
isStacked
|
|
89
|
+
}: Props): ReactElement => {
|
|
88
90
|
const {
|
|
89
91
|
BarStackComponent,
|
|
90
92
|
commonBarStackProps,
|
|
@@ -118,6 +120,15 @@ const BarStack = ({
|
|
|
118
120
|
metricId: Number(bar.key)
|
|
119
121
|
}) as BarStyle;
|
|
120
122
|
|
|
123
|
+
const barY =
|
|
124
|
+
isNegativeValue && isStacked && !shouldApplyRadiusOnBottom
|
|
125
|
+
? getPadding({
|
|
126
|
+
isNegativeValue,
|
|
127
|
+
padding: bar.y,
|
|
128
|
+
size: bar.height
|
|
129
|
+
})
|
|
130
|
+
: bar.y;
|
|
131
|
+
|
|
121
132
|
return (
|
|
122
133
|
<BarRounded
|
|
123
134
|
{...barRoundedProps}
|
|
@@ -128,10 +139,10 @@ const BarStack = ({
|
|
|
128
139
|
barWidth,
|
|
129
140
|
y: isHorizontal
|
|
130
141
|
? getPadding({
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
142
|
+
isNegativeValue,
|
|
143
|
+
padding: bar.y,
|
|
144
|
+
size: bar.height
|
|
145
|
+
})
|
|
135
146
|
: barPadding,
|
|
136
147
|
isFirstBar: shouldApplyRadiusOnBottom,
|
|
137
148
|
isHorizontal,
|
|
@@ -146,19 +157,19 @@ const BarStack = ({
|
|
|
146
157
|
isHorizontal
|
|
147
158
|
? barPadding
|
|
148
159
|
: getPadding({
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
160
|
+
isNegativeValue,
|
|
161
|
+
padding: bar.x,
|
|
162
|
+
size: bar.width
|
|
163
|
+
})
|
|
153
164
|
}
|
|
154
|
-
y={isHorizontal ?
|
|
165
|
+
y={isHorizontal ? barY : barPadding}
|
|
155
166
|
onMouseEnter={
|
|
156
167
|
isTooltipHidden
|
|
157
168
|
? undefined
|
|
158
169
|
: hoverBar({
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
170
|
+
barIndex,
|
|
171
|
+
highlightedMetric: Number(bar.key)
|
|
172
|
+
})
|
|
162
173
|
}
|
|
163
174
|
onMouseLeave={isTooltipHidden ? undefined : exitBar}
|
|
164
175
|
/>
|
|
@@ -61,18 +61,19 @@ const MemoizedGroup = ({
|
|
|
61
61
|
const linesBar = isStackedBar
|
|
62
62
|
? stackedLinesTimeSeriesPerUnit[bar.key.replace('stacked-', '')].lines
|
|
63
63
|
: (notStackedLines.find(({ metric_id }) =>
|
|
64
|
-
|
|
65
|
-
|
|
64
|
+
equals(metric_id, Number(bar.key))
|
|
65
|
+
) as Line);
|
|
66
66
|
const timeSeriesBar = isStackedBar
|
|
67
67
|
? stackedLinesTimeSeriesPerUnit[bar.key.replace('stacked-', '')]
|
|
68
68
|
.timeSeries
|
|
69
69
|
: notStackedTimeSeries.map((timeSerie) => ({
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
70
|
+
timeTick: timeSerie.timeTick,
|
|
71
|
+
[bar.key]: timeSerie[Number(bar.key)]
|
|
72
|
+
}));
|
|
73
73
|
|
|
74
74
|
return isStackedBar ? (
|
|
75
75
|
<BarStack
|
|
76
|
+
isStacked
|
|
76
77
|
key={`bar-${barGroup.index}-${bar.width}-${bar.y}-${bar.height}-${bar.x}`}
|
|
77
78
|
barIndex={barGroup.index}
|
|
78
79
|
barPadding={isHorizontal ? bar.x : bar.y}
|
|
@@ -82,7 +83,7 @@ const MemoizedGroup = ({
|
|
|
82
83
|
isTooltipHidden={isTooltipHidden}
|
|
83
84
|
lines={linesBar as Array<Line>}
|
|
84
85
|
timeSeries={timeSeriesBar}
|
|
85
|
-
yScale={yScalesPerUnit[bar.key.replace('stacked-', '')]}
|
|
86
|
+
yScale={yScalesPerUnit[bar.key.replace('stacked-', '')] ?? undefined}
|
|
86
87
|
neutralValue={neutralValue}
|
|
87
88
|
/>
|
|
88
89
|
) : (
|
|
@@ -96,7 +97,7 @@ const MemoizedGroup = ({
|
|
|
96
97
|
isTooltipHidden={isTooltipHidden}
|
|
97
98
|
lines={[linesBar as Line]}
|
|
98
99
|
timeSeries={timeSeriesBar}
|
|
99
|
-
yScale={yScalesPerUnit[(linesBar as Line).unit]}
|
|
100
|
+
yScale={yScalesPerUnit[(linesBar as Line).unit ?? undefined]}
|
|
100
101
|
neutralValue={neutralValue}
|
|
101
102
|
/>
|
|
102
103
|
);
|
|
@@ -27,6 +27,7 @@ import { StackValue } from '../../../InteractiveComponents/AnchorPoint/models';
|
|
|
27
27
|
import { getCurveFactory, getFillColor } from '../../../common';
|
|
28
28
|
import { LineStyle } from '../../../models';
|
|
29
29
|
import Point from '../Point';
|
|
30
|
+
import { ReactElement } from 'react';
|
|
30
31
|
|
|
31
32
|
interface Props {
|
|
32
33
|
areaTransparency?: number;
|
|
@@ -56,7 +57,7 @@ const StackLines = ({
|
|
|
56
57
|
lineStyle,
|
|
57
58
|
hasSecondUnit,
|
|
58
59
|
maxLeftAxisCharacters
|
|
59
|
-
}: Props):
|
|
60
|
+
}: Props): ReactElement => {
|
|
60
61
|
const curveType = getCurveFactory(
|
|
61
62
|
(equals(type(lineStyle), 'Array')
|
|
62
63
|
? lineStyle?.[0].curve
|
|
@@ -134,9 +135,9 @@ const StackLines = ({
|
|
|
134
135
|
equals(style?.showArea, false)
|
|
135
136
|
? 'transparent'
|
|
136
137
|
: getFillColor({
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
138
|
+
areaColor: areaColor || lineColor,
|
|
139
|
+
transparency: formattedTransparency
|
|
140
|
+
})
|
|
140
141
|
}
|
|
141
142
|
opacity={highlight === false ? 0.3 : 1}
|
|
142
143
|
stroke={lineColor}
|
|
@@ -107,7 +107,7 @@ const Lines = ({
|
|
|
107
107
|
key={`stacked-${unit}`}
|
|
108
108
|
lines={lines}
|
|
109
109
|
timeSeries={stackedTimeSeries}
|
|
110
|
-
yScale={yScalesPerUnit[unit]}
|
|
110
|
+
yScale={yScalesPerUnit[unit] ?? undefined}
|
|
111
111
|
{...commonStackedLinesProps}
|
|
112
112
|
/>
|
|
113
113
|
)
|
|
@@ -123,7 +123,7 @@ const Lines = ({
|
|
|
123
123
|
invert: '1',
|
|
124
124
|
scale,
|
|
125
125
|
scaleLogarithmicBase,
|
|
126
|
-
unit,
|
|
126
|
+
unit: unit ?? undefined,
|
|
127
127
|
yScalesPerUnit
|
|
128
128
|
})}
|
|
129
129
|
{...commonStackedLinesProps}
|
|
@@ -146,107 +146,107 @@ const Lines = ({
|
|
|
146
146
|
|
|
147
147
|
{displayAreaRegularLines
|
|
148
148
|
? regularLines.map(
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
149
|
+
({
|
|
150
|
+
areaColor,
|
|
151
|
+
transparency,
|
|
152
|
+
lineColor,
|
|
153
|
+
filled,
|
|
154
|
+
unit,
|
|
155
|
+
highlight,
|
|
156
|
+
invert,
|
|
157
|
+
metric_id,
|
|
158
|
+
...rest
|
|
159
|
+
}) => {
|
|
160
|
+
const yScale = getYScale({
|
|
161
|
+
invert,
|
|
162
|
+
scale,
|
|
163
|
+
scaleLogarithmicBase,
|
|
154
164
|
unit,
|
|
155
|
-
|
|
165
|
+
yScalesPerUnit
|
|
166
|
+
});
|
|
167
|
+
const relatedTimeSeries = getTimeSeriesForLines({
|
|
156
168
|
invert,
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
timeSeries
|
|
183
|
-
});
|
|
184
|
-
|
|
185
|
-
const style = getStyle({
|
|
186
|
-
style: lineStyle,
|
|
187
|
-
metricId: metric_id
|
|
188
|
-
}) as LineStyle;
|
|
189
|
-
|
|
190
|
-
return (
|
|
191
|
-
<g key={metric_id}>
|
|
192
|
-
{displayGuidingLines && (
|
|
193
|
-
<RegularAnchorPoint
|
|
194
|
-
areaColor={areaColor || lineColor}
|
|
195
|
-
lineColor={lineColor}
|
|
196
|
-
metric_id={metric_id}
|
|
197
|
-
timeSeries={relatedTimeSeries}
|
|
198
|
-
transparency={transparency}
|
|
199
|
-
xScale={xScale}
|
|
200
|
-
yScale={yScale}
|
|
201
|
-
maxLeftAxisCharacters={maxLeftAxisCharacters}
|
|
202
|
-
hasSecondUnit={hasSecondUnit}
|
|
203
|
-
/>
|
|
204
|
-
)}
|
|
205
|
-
{style?.showPoints &&
|
|
206
|
-
getDates(relatedTimeSeries).map((timeTick) => (
|
|
207
|
-
<Point
|
|
208
|
-
key={timeTick.toString()}
|
|
209
|
-
lineColor={lineColor}
|
|
210
|
-
metric_id={metric_id}
|
|
211
|
-
radius={getPointRadius(style?.lineWidth)}
|
|
212
|
-
timeSeries={relatedTimeSeries}
|
|
213
|
-
timeTick={timeTick}
|
|
214
|
-
xScale={xScale}
|
|
215
|
-
yPoint={getYAnchorPoint({
|
|
216
|
-
metric_id,
|
|
217
|
-
timeSeries: relatedTimeSeries,
|
|
218
|
-
timeTick,
|
|
219
|
-
yScale
|
|
220
|
-
})}
|
|
221
|
-
yScale={yScale}
|
|
222
|
-
/>
|
|
223
|
-
))}
|
|
224
|
-
<RegularLine
|
|
169
|
+
lines: [
|
|
170
|
+
{
|
|
171
|
+
areaColor,
|
|
172
|
+
filled,
|
|
173
|
+
highlight,
|
|
174
|
+
invert,
|
|
175
|
+
lineColor,
|
|
176
|
+
metric_id,
|
|
177
|
+
transparency,
|
|
178
|
+
unit,
|
|
179
|
+
...rest
|
|
180
|
+
}
|
|
181
|
+
],
|
|
182
|
+
timeSeries
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
const style = getStyle({
|
|
186
|
+
style: lineStyle,
|
|
187
|
+
metricId: metric_id
|
|
188
|
+
}) as LineStyle;
|
|
189
|
+
|
|
190
|
+
return (
|
|
191
|
+
<g key={metric_id}>
|
|
192
|
+
{displayGuidingLines && (
|
|
193
|
+
<RegularAnchorPoint
|
|
225
194
|
areaColor={areaColor || lineColor}
|
|
226
|
-
curve={style?.curve || 'linear'}
|
|
227
|
-
dashLength={style?.dashLength}
|
|
228
|
-
dashOffset={style?.dashOffset}
|
|
229
|
-
dotOffset={style?.dotOffset}
|
|
230
|
-
filled={isNil(style?.showArea) ? filled : style.showArea}
|
|
231
|
-
graphHeight={height}
|
|
232
|
-
highlight={highlight}
|
|
233
195
|
lineColor={lineColor}
|
|
234
|
-
lineWidth={style?.lineWidth || 2}
|
|
235
196
|
metric_id={metric_id}
|
|
236
197
|
timeSeries={relatedTimeSeries}
|
|
237
|
-
transparency={
|
|
238
|
-
isNil(style?.areaTransparency)
|
|
239
|
-
? transparency || 80
|
|
240
|
-
: style.areaTransparency
|
|
241
|
-
}
|
|
242
|
-
unit={unit}
|
|
198
|
+
transparency={transparency}
|
|
243
199
|
xScale={xScale}
|
|
244
200
|
yScale={yScale}
|
|
201
|
+
maxLeftAxisCharacters={maxLeftAxisCharacters}
|
|
202
|
+
hasSecondUnit={hasSecondUnit}
|
|
245
203
|
/>
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
204
|
+
)}
|
|
205
|
+
{style?.showPoints &&
|
|
206
|
+
getDates(relatedTimeSeries).map((timeTick) => (
|
|
207
|
+
<Point
|
|
208
|
+
key={timeTick.toString()}
|
|
209
|
+
lineColor={lineColor}
|
|
210
|
+
metric_id={metric_id}
|
|
211
|
+
radius={getPointRadius(style?.lineWidth)}
|
|
212
|
+
timeSeries={relatedTimeSeries}
|
|
213
|
+
timeTick={timeTick}
|
|
214
|
+
xScale={xScale}
|
|
215
|
+
yPoint={getYAnchorPoint({
|
|
216
|
+
metric_id,
|
|
217
|
+
timeSeries: relatedTimeSeries,
|
|
218
|
+
timeTick,
|
|
219
|
+
yScale
|
|
220
|
+
})}
|
|
221
|
+
yScale={yScale}
|
|
222
|
+
/>
|
|
223
|
+
))}
|
|
224
|
+
<RegularLine
|
|
225
|
+
areaColor={areaColor || lineColor}
|
|
226
|
+
curve={style?.curve || 'linear'}
|
|
227
|
+
dashLength={style?.dashLength}
|
|
228
|
+
dashOffset={style?.dashOffset}
|
|
229
|
+
dotOffset={style?.dotOffset}
|
|
230
|
+
filled={isNil(style?.showArea) ? filled : style.showArea}
|
|
231
|
+
graphHeight={height}
|
|
232
|
+
highlight={highlight}
|
|
233
|
+
lineColor={lineColor}
|
|
234
|
+
lineWidth={style?.lineWidth || 2}
|
|
235
|
+
metric_id={metric_id}
|
|
236
|
+
timeSeries={relatedTimeSeries}
|
|
237
|
+
transparency={
|
|
238
|
+
isNil(style?.areaTransparency)
|
|
239
|
+
? transparency || 80
|
|
240
|
+
: style.areaTransparency
|
|
241
|
+
}
|
|
242
|
+
unit={unit}
|
|
243
|
+
xScale={xScale}
|
|
244
|
+
yScale={yScale}
|
|
245
|
+
/>
|
|
246
|
+
</g>
|
|
247
|
+
);
|
|
248
|
+
}
|
|
249
|
+
)
|
|
250
250
|
: null}
|
|
251
251
|
</g>
|
|
252
252
|
);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
type MutableRefObject,
|
|
3
|
+
ReactElement,
|
|
3
4
|
useEffect,
|
|
4
5
|
useMemo,
|
|
5
6
|
useRef,
|
|
@@ -116,7 +117,7 @@ const Chart = ({
|
|
|
116
117
|
min,
|
|
117
118
|
max,
|
|
118
119
|
boundariesUnit
|
|
119
|
-
}: Props):
|
|
120
|
+
}: Props): ReactElement => {
|
|
120
121
|
const { classes } = useChartStyles();
|
|
121
122
|
|
|
122
123
|
const { title, timeSeries, baseAxis, lines } = graphData;
|
|
@@ -197,7 +198,8 @@ const Chart = ({
|
|
|
197
198
|
valueGraphHeight: graphHeight - margin.bottom,
|
|
198
199
|
min,
|
|
199
200
|
max,
|
|
200
|
-
boundariesUnit
|
|
201
|
+
boundariesUnit,
|
|
202
|
+
isFilled: lineStyle?.showArea
|
|
201
203
|
}),
|
|
202
204
|
[
|
|
203
205
|
linesGraph,
|
|
@@ -32,7 +32,8 @@ import {
|
|
|
32
32
|
reject,
|
|
33
33
|
sortBy,
|
|
34
34
|
split,
|
|
35
|
-
uniq
|
|
35
|
+
uniq,
|
|
36
|
+
isNotNil
|
|
36
37
|
} from 'ramda';
|
|
37
38
|
|
|
38
39
|
import { margin } from '../../Chart/common';
|
|
@@ -158,8 +159,8 @@ const getMetrics = (timeValue: TimeValue): Array<string> =>
|
|
|
158
159
|
|
|
159
160
|
const getValueForMetric =
|
|
160
161
|
(timeValue: TimeValue) =>
|
|
161
|
-
|
|
162
|
-
|
|
162
|
+
(metric_id: number): number =>
|
|
163
|
+
prop(metric_id, timeValue) as number;
|
|
163
164
|
|
|
164
165
|
const getUnits = (lines: Array<Line>): Array<string> =>
|
|
165
166
|
pipe(map(prop('unit')), uniq)(lines);
|
|
@@ -303,8 +304,8 @@ const getTimeSeriesForLines = ({
|
|
|
303
304
|
...acc,
|
|
304
305
|
[metric_id]:
|
|
305
306
|
invert &&
|
|
306
|
-
|
|
307
|
-
|
|
307
|
+
metricsValue[metric_id] &&
|
|
308
|
+
gt(metricsValue[metric_id], 0)
|
|
308
309
|
? negate(metricsValue[metric_id])
|
|
309
310
|
: metricsValue[metric_id]
|
|
310
311
|
};
|
|
@@ -337,10 +338,10 @@ const getYScale = ({
|
|
|
337
338
|
|
|
338
339
|
return invert
|
|
339
340
|
? getScaleType(scale)({
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
341
|
+
base: scaleLogarithmicBase,
|
|
342
|
+
domain: yScale.domain().reverse(),
|
|
343
|
+
range: yScale.range().reverse()
|
|
344
|
+
})
|
|
344
345
|
: yScale;
|
|
345
346
|
};
|
|
346
347
|
|
|
@@ -377,6 +378,7 @@ const getScale = ({
|
|
|
377
378
|
invert,
|
|
378
379
|
hasDisplayAsBar,
|
|
379
380
|
hasLineFilled,
|
|
381
|
+
hasStackedLines,
|
|
380
382
|
min,
|
|
381
383
|
max
|
|
382
384
|
}): ScaleLinear<number, number> => {
|
|
@@ -384,30 +386,42 @@ const getScale = ({
|
|
|
384
386
|
const sanitizedValuesForMinimum = min
|
|
385
387
|
? [min]
|
|
386
388
|
: getSanitizedValues([
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
const minValue = Math.min(...sanitizedValuesForMinimum);
|
|
396
|
-
const minValueWithMargin =
|
|
397
|
-
(hasDisplayAsBar || hasLineFilled) && minValue > 0 && !min
|
|
398
|
-
? 0
|
|
399
|
-
: minValue - Math.abs(minValue) * 0.05;
|
|
389
|
+
invert && graphValues.every(lt(0))
|
|
390
|
+
? negate(getMax(graphValues))
|
|
391
|
+
: getMin(graphValues),
|
|
392
|
+
!isEmpty(stackedValues) &&
|
|
393
|
+
!equals(stackedValues, [0]) &&
|
|
394
|
+
getMin(stackedValues),
|
|
395
|
+
Math.min(...thresholds)
|
|
396
|
+
]);
|
|
397
|
+
const minValue = Math.min(...sanitizedValuesForMinimum.filter(isNotNil));
|
|
400
398
|
|
|
401
399
|
const sanitizedValuesForMaximum = max
|
|
402
400
|
? [max]
|
|
403
401
|
: getSanitizedValues([
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
const maxValue = Math.max(...sanitizedValuesForMaximum);
|
|
410
|
-
|
|
402
|
+
getMax(graphValues),
|
|
403
|
+
getMax(stackedValues),
|
|
404
|
+
hasOnlyZeroesHasValue(graphValues) ? 1 : null,
|
|
405
|
+
Math.max(...thresholds)
|
|
406
|
+
]);
|
|
407
|
+
const maxValue = Math.max(...sanitizedValuesForMaximum.filter(isNotNil));
|
|
408
|
+
|
|
409
|
+
const minValueWithMargin =
|
|
410
|
+
(hasDisplayAsBar && minValue > 0) ||
|
|
411
|
+
(hasLineFilled &&
|
|
412
|
+
Math.max(maxValue, minValue) > minValue &&
|
|
413
|
+
minValue > 0) ||
|
|
414
|
+
(hasStackedLines && minValue > maxValue)
|
|
415
|
+
? 0
|
|
416
|
+
: minValue - Math.abs(minValue) * 0.05;
|
|
417
|
+
const maxValueWithMargin =
|
|
418
|
+
(hasDisplayAsBar && maxValue < 0) ||
|
|
419
|
+
(hasLineFilled &&
|
|
420
|
+
Math.min(maxValue, minValue) < maxValue &&
|
|
421
|
+
maxValue < 0) ||
|
|
422
|
+
(hasStackedLines && minValue > maxValue)
|
|
423
|
+
? 0
|
|
424
|
+
: maxValue + Math.abs(maxValue) * 0.05;
|
|
411
425
|
|
|
412
426
|
const scaleType = getScaleType(scale);
|
|
413
427
|
|
|
@@ -474,7 +488,8 @@ const getYScaleUnit = ({
|
|
|
474
488
|
min,
|
|
475
489
|
max,
|
|
476
490
|
isBarChart,
|
|
477
|
-
boundariesUnit
|
|
491
|
+
boundariesUnit,
|
|
492
|
+
isFilled
|
|
478
493
|
}: AxeScale & {
|
|
479
494
|
invert?: boolean | string | null;
|
|
480
495
|
unit: string;
|
|
@@ -482,6 +497,7 @@ const getYScaleUnit = ({
|
|
|
482
497
|
min?: number;
|
|
483
498
|
boundariesUnit?: string;
|
|
484
499
|
isBarChart?: boolean;
|
|
500
|
+
isFilled?: boolean;
|
|
485
501
|
}): ScaleLinear<number, number> => {
|
|
486
502
|
const [firstUnit] = getUnits(dataLines);
|
|
487
503
|
const shouldApplyThresholds =
|
|
@@ -500,12 +516,12 @@ const getYScaleUnit = ({
|
|
|
500
516
|
|
|
501
517
|
const stackedValues = hasStackedLines
|
|
502
518
|
? getStackedMetricValues({
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
: [
|
|
519
|
+
lines: getSortedStackedLines(dataLines).filter(
|
|
520
|
+
({ unit: stackedUnit }) => equals(unit, stackedUnit)
|
|
521
|
+
),
|
|
522
|
+
timeSeries: dataTimeSeries
|
|
523
|
+
})
|
|
524
|
+
: [];
|
|
509
525
|
|
|
510
526
|
return getScale({
|
|
511
527
|
graphValues,
|
|
@@ -515,8 +531,14 @@ const getYScaleUnit = ({
|
|
|
515
531
|
({ displayAs, unit: lineUnit }) =>
|
|
516
532
|
equals(unit, lineUnit) && equals(displayAs, 'bar')
|
|
517
533
|
),
|
|
518
|
-
hasLineFilled:
|
|
519
|
-
|
|
534
|
+
hasLineFilled: isNil(isFilled)
|
|
535
|
+
? dataLines.some(
|
|
536
|
+
({ unit: lineUnit, filled }) => equals(unit, lineUnit) && filled
|
|
537
|
+
)
|
|
538
|
+
: isFilled,
|
|
539
|
+
hasStackedLines: dataLines.some(
|
|
540
|
+
({ unit: lineUnit, stackKey, stackOrder }) =>
|
|
541
|
+
equals(unit, lineUnit) && (stackKey || stackOrder)
|
|
520
542
|
),
|
|
521
543
|
height: valueGraphHeight,
|
|
522
544
|
invert,
|
|
@@ -556,12 +578,14 @@ const getYScalePerUnit = ({
|
|
|
556
578
|
isBarChart,
|
|
557
579
|
min,
|
|
558
580
|
max,
|
|
559
|
-
boundariesUnit
|
|
581
|
+
boundariesUnit,
|
|
582
|
+
isFilled
|
|
560
583
|
}: AxeScale & {
|
|
561
584
|
min?: number;
|
|
562
585
|
max?: number;
|
|
563
586
|
isBarChart?: boolean;
|
|
564
587
|
boundariesUnit?: string;
|
|
588
|
+
isFilled?: boolean;
|
|
565
589
|
}): Record<string, ScaleLinear<number, number>> => {
|
|
566
590
|
const units = getUnits(dataLines);
|
|
567
591
|
|
|
@@ -585,7 +609,8 @@ const getYScalePerUnit = ({
|
|
|
585
609
|
min,
|
|
586
610
|
max,
|
|
587
611
|
isBarChart,
|
|
588
|
-
boundariesUnit
|
|
612
|
+
boundariesUnit,
|
|
613
|
+
isFilled
|
|
589
614
|
})
|
|
590
615
|
};
|
|
591
616
|
}, {});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useCallback, useEffect, useState } from 'react';
|
|
1
|
+
import { ReactElement, useCallback, useEffect, useState } from 'react';
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
4
|
equals,
|
|
@@ -44,7 +44,7 @@ export interface ConnectedAutoCompleteFieldProps<TData> {
|
|
|
44
44
|
field: string;
|
|
45
45
|
getEndpoint: ({ search, page }) => string;
|
|
46
46
|
decoder?;
|
|
47
|
-
getRenderedOptionText
|
|
47
|
+
getRenderedOptionText?: (option: TData) => ReactElement | string;
|
|
48
48
|
getRequestHeaders?: HeadersInit;
|
|
49
49
|
initialPage: number;
|
|
50
50
|
labelKey?: string;
|
|
@@ -53,9 +53,9 @@ export interface ConnectedAutoCompleteFieldProps<TData> {
|
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
const ConnectedAutocompleteField = (
|
|
56
|
-
AutocompleteField: (props) =>
|
|
56
|
+
AutocompleteField: (props) => ReactElement,
|
|
57
57
|
multiple: boolean
|
|
58
|
-
): ((props) =>
|
|
58
|
+
): ((props) => ReactElement) => {
|
|
59
59
|
const InnerConnectedAutocompleteField = <TData extends { name: string }>({
|
|
60
60
|
initialPage = 1,
|
|
61
61
|
getEndpoint,
|
|
@@ -74,7 +74,7 @@ const ConnectedAutocompleteField = (
|
|
|
74
74
|
changeIdValue,
|
|
75
75
|
...props
|
|
76
76
|
}: ConnectedAutoCompleteFieldProps<TData> &
|
|
77
|
-
Omit<AutocompleteFieldProps, 'options'>):
|
|
77
|
+
Omit<AutocompleteFieldProps, 'options'>): ReactElement => {
|
|
78
78
|
const [options, setOptions] = useState<Array<TData>>([]);
|
|
79
79
|
const [page, setPage] = useState(1);
|
|
80
80
|
const [maxPage, setMaxPage] = useState(initialPage);
|
|
@@ -221,7 +221,7 @@ const ConnectedAutocompleteField = (
|
|
|
221
221
|
debounce(event.target.value);
|
|
222
222
|
};
|
|
223
223
|
|
|
224
|
-
const renderOptions = (renderProps, option, { selected }):
|
|
224
|
+
const renderOptions = (renderProps, option, { selected }): ReactElement => {
|
|
225
225
|
const { value } = props;
|
|
226
226
|
|
|
227
227
|
const lastValue = Array.isArray(value) ? last(value) : value;
|
|
@@ -13,6 +13,7 @@ import { AutocompleteSlotsAndSlotProps } from '@mui/material/Autocomplete';
|
|
|
13
13
|
import { TextFieldSlotsAndSlotProps } from '@mui/material/TextField';
|
|
14
14
|
import { UseAutocompleteProps } from '@mui/material/useAutocomplete';
|
|
15
15
|
|
|
16
|
+
import type { AutocompleteRenderOptionState } from '@mui/material/Autocomplete';
|
|
16
17
|
import { ForwardedRef, HTMLAttributes, ReactElement, forwardRef } from 'react';
|
|
17
18
|
import { SelectEntry } from '..';
|
|
18
19
|
import { getNormalizedId } from '../../../utils';
|
|
@@ -33,6 +34,11 @@ export type Props = {
|
|
|
33
34
|
error?: string;
|
|
34
35
|
getOptionItemLabel?: (option) => string;
|
|
35
36
|
hideInput?: boolean;
|
|
37
|
+
renderOption?: (
|
|
38
|
+
renderProps: HTMLAttributes<HTMLLIElement>,
|
|
39
|
+
option: SelectEntry,
|
|
40
|
+
state: AutocompleteRenderOptionState
|
|
41
|
+
) => ReactElement;
|
|
36
42
|
label: string;
|
|
37
43
|
loading?: boolean;
|
|
38
44
|
onTextChange?;
|
|
@@ -52,7 +58,7 @@ export type Props = {
|
|
|
52
58
|
> &
|
|
53
59
|
UseAutocompleteProps<SelectEntry, Multiple, DisableClearable, FreeSolo>;
|
|
54
60
|
|
|
55
|
-
const LoadingIndicator = ():
|
|
61
|
+
const LoadingIndicator = (): ReactElement => {
|
|
56
62
|
const { classes } = useAutoCompleteStyles({});
|
|
57
63
|
|
|
58
64
|
return (
|
|
@@ -90,10 +96,11 @@ const AutocompleteField = forwardRef(
|
|
|
90
96
|
forceInputRenderValue = false,
|
|
91
97
|
textFieldSlotsAndSlotProps,
|
|
92
98
|
autocompleteSlotsAndSlotProps,
|
|
99
|
+
renderOption,
|
|
93
100
|
...autocompleteProps
|
|
94
101
|
}: Props,
|
|
95
102
|
ref?: ForwardedRef<HTMLDivElement>
|
|
96
|
-
):
|
|
103
|
+
): ReactElement => {
|
|
97
104
|
const { classes, cx } = useAutoCompleteStyles({ hideInput });
|
|
98
105
|
const { t } = useTranslation();
|
|
99
106
|
const theme = useTheme();
|
|
@@ -107,7 +114,24 @@ const AutocompleteField = forwardRef(
|
|
|
107
114
|
);
|
|
108
115
|
};
|
|
109
116
|
|
|
110
|
-
const
|
|
117
|
+
const renderOptions = renderOption
|
|
118
|
+
? renderOption
|
|
119
|
+
: (props, option): ReactElement => {
|
|
120
|
+
return (
|
|
121
|
+
<li
|
|
122
|
+
className={classes.options}
|
|
123
|
+
{...(props as HTMLAttributes<HTMLLIElement>)}
|
|
124
|
+
>
|
|
125
|
+
<Option
|
|
126
|
+
thumbnailUrl={displayOptionThumbnail ? option.url : undefined}
|
|
127
|
+
>
|
|
128
|
+
{getOptionItemLabel(option)}
|
|
129
|
+
</Option>
|
|
130
|
+
</li>
|
|
131
|
+
);
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
const renderInput = (params): ReactElement => {
|
|
111
135
|
return (
|
|
112
136
|
<TextField
|
|
113
137
|
{...params}
|
|
@@ -202,20 +226,7 @@ const AutocompleteField = forwardRef(
|
|
|
202
226
|
options={options}
|
|
203
227
|
ref={ref}
|
|
204
228
|
renderInput={renderInput}
|
|
205
|
-
renderOption={
|
|
206
|
-
return (
|
|
207
|
-
<li
|
|
208
|
-
className={classes.options}
|
|
209
|
-
{...(props as HTMLAttributes<HTMLLIElement>)}
|
|
210
|
-
>
|
|
211
|
-
<Option
|
|
212
|
-
thumbnailUrl={displayOptionThumbnail ? option.url : undefined}
|
|
213
|
-
>
|
|
214
|
-
{getOptionItemLabel(option)}
|
|
215
|
-
</Option>
|
|
216
|
-
</li>
|
|
217
|
-
);
|
|
218
|
-
}}
|
|
229
|
+
renderOption={renderOptions}
|
|
219
230
|
size="small"
|
|
220
231
|
slotProps={{
|
|
221
232
|
...autocompleteSlotsAndSlotProps?.slotProps,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { RefObject, forwardRef } from 'react';
|
|
1
|
+
import { ReactElement, RefObject, forwardRef } from 'react';
|
|
2
2
|
|
|
3
3
|
import { equals, isNil } from 'ramda';
|
|
4
4
|
import { makeStyles } from 'tss-react/mui';
|
|
@@ -28,12 +28,12 @@ const useStyles = makeStyles()((theme) => ({
|
|
|
28
28
|
|
|
29
29
|
interface Props {
|
|
30
30
|
checkboxSelected?: boolean;
|
|
31
|
-
children: string;
|
|
31
|
+
children: string | ReactElement;
|
|
32
32
|
thumbnailUrl?: string;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
const Option = forwardRef(
|
|
36
|
-
({ children, checkboxSelected, thumbnailUrl }: Props, ref):
|
|
36
|
+
({ children, checkboxSelected, thumbnailUrl }: Props, ref): ReactElement => {
|
|
37
37
|
const { classes } = useStyles();
|
|
38
38
|
|
|
39
39
|
return (
|
|
@@ -8,6 +8,7 @@ import { SelectEntry, SingleConnectedAutocompleteField } from '../../../..';
|
|
|
8
8
|
import RoleSelectField from '../common/RoleSelectField';
|
|
9
9
|
import { Endpoints, Labels } from '../models';
|
|
10
10
|
|
|
11
|
+
import { ReactElement } from 'react';
|
|
11
12
|
import ContactSwitch from './ContactSwitch';
|
|
12
13
|
import { useShareInputStyles } from './ShareInput.styles';
|
|
13
14
|
import useShareInput from './useShareInput';
|
|
@@ -18,18 +19,18 @@ interface Props {
|
|
|
18
19
|
roles: Array<SelectEntry>;
|
|
19
20
|
}
|
|
20
21
|
|
|
21
|
-
const ShareInput = ({ labels, endpoints, roles }: Props):
|
|
22
|
+
const ShareInput = ({ labels, endpoints, roles }: Props): ReactElement => {
|
|
22
23
|
const { t } = useTranslation();
|
|
23
24
|
const { classes } = useShareInputStyles();
|
|
24
25
|
|
|
25
26
|
const {
|
|
26
|
-
renderOption,
|
|
27
27
|
selectedContact,
|
|
28
28
|
getOptionDisabled,
|
|
29
29
|
getEndpoint,
|
|
30
30
|
selectContact,
|
|
31
31
|
isContactGroup,
|
|
32
32
|
selectedRole,
|
|
33
|
+
getRenderedOptionText,
|
|
33
34
|
setSelectedRole,
|
|
34
35
|
add,
|
|
35
36
|
changeIdValue
|
|
@@ -46,6 +47,7 @@ const ShareInput = ({ labels, endpoints, roles }: Props): JSX.Element => {
|
|
|
46
47
|
disableClearable={false}
|
|
47
48
|
field="name"
|
|
48
49
|
getEndpoint={getEndpoint}
|
|
50
|
+
getRenderedOptionText={getRenderedOptionText}
|
|
49
51
|
getOptionDisabled={getOptionDisabled}
|
|
50
52
|
label={t(
|
|
51
53
|
isContactGroup
|
|
@@ -53,7 +55,6 @@ const ShareInput = ({ labels, endpoints, roles }: Props): JSX.Element => {
|
|
|
53
55
|
: t(labels.autocompleteContact)
|
|
54
56
|
)}
|
|
55
57
|
queryKey={isContactGroup ? labels.contactGroup : labels.contact}
|
|
56
|
-
renderOption={renderOption}
|
|
57
58
|
value={selectedContact}
|
|
58
59
|
onChange={selectContact}
|
|
59
60
|
/>
|
|
@@ -1,10 +1,15 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
Dispatch,
|
|
3
|
+
ReactElement,
|
|
4
|
+
SetStateAction,
|
|
5
|
+
useEffect,
|
|
6
|
+
useState
|
|
7
|
+
} from 'react';
|
|
2
8
|
|
|
3
9
|
import { useAtomValue, useSetAtom } from 'jotai';
|
|
4
10
|
import { equals, includes, isNil } from 'ramda';
|
|
5
11
|
|
|
6
12
|
import CheckCircleIcon from '@mui/icons-material/CheckCircle';
|
|
7
|
-
import { ListItemText, MenuItem } from '@mui/material';
|
|
8
13
|
|
|
9
14
|
import { SelectEntry, buildListingEndpoint } from '../../../..';
|
|
10
15
|
import {
|
|
@@ -20,7 +25,7 @@ interface UseShareInputState {
|
|
|
20
25
|
getEndpoint: (parameters) => string;
|
|
21
26
|
getOptionDisabled: (option) => boolean;
|
|
22
27
|
isContactGroup: boolean;
|
|
23
|
-
|
|
28
|
+
getRenderedOptionText: (option: unknown) => ReactElement | string;
|
|
24
29
|
selectContact: (_, entry) => void;
|
|
25
30
|
selectedContact: AccessRightInitialValues | null;
|
|
26
31
|
selectedRole: string;
|
|
@@ -40,7 +45,7 @@ const useShareInput = (endpoints: Endpoints): UseShareInputState => {
|
|
|
40
45
|
|
|
41
46
|
const selectContact = (_, entry): void => {
|
|
42
47
|
setSelectedContact(entry);
|
|
43
|
-
if (equals('editor', entry
|
|
48
|
+
if (equals('editor', entry?.most_permissive_role)) {
|
|
44
49
|
return;
|
|
45
50
|
}
|
|
46
51
|
setSelectedRole('viewer');
|
|
@@ -71,14 +76,14 @@ const useShareInput = (endpoints: Endpoints): UseShareInputState => {
|
|
|
71
76
|
}
|
|
72
77
|
});
|
|
73
78
|
|
|
74
|
-
const
|
|
79
|
+
const getRenderedOptionText = (option): ReactElement => {
|
|
75
80
|
return (
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
{includes(option
|
|
81
|
+
<>
|
|
82
|
+
{option?.name}
|
|
83
|
+
{includes(option?.id, accessRightIds) && (
|
|
79
84
|
<CheckCircleIcon color="success" />
|
|
80
85
|
)}
|
|
81
|
-
|
|
86
|
+
</>
|
|
82
87
|
);
|
|
83
88
|
};
|
|
84
89
|
|
|
@@ -102,7 +107,7 @@ const useShareInput = (endpoints: Endpoints): UseShareInputState => {
|
|
|
102
107
|
getEndpoint,
|
|
103
108
|
getOptionDisabled,
|
|
104
109
|
isContactGroup,
|
|
105
|
-
|
|
110
|
+
getRenderedOptionText,
|
|
106
111
|
selectContact,
|
|
107
112
|
selectedContact,
|
|
108
113
|
selectedRole,
|
|
@@ -5,13 +5,12 @@ import {
|
|
|
5
5
|
Menu as MenuIcon
|
|
6
6
|
} from '@mui/icons-material';
|
|
7
7
|
|
|
8
|
+
import { useStyles } from './MenuButton.styles';
|
|
8
9
|
import { AriaLabelingAttributes } from '../../../@types/aria-attributes';
|
|
9
10
|
import { DataTestAttributes } from '../../../@types/data-attributes';
|
|
10
11
|
import { Button, ButtonProps } from '../../Button';
|
|
11
12
|
import { useMenu } from '../useMenu';
|
|
12
13
|
|
|
13
|
-
import { useStyles } from './MenuButton.styles';
|
|
14
|
-
|
|
15
14
|
type MenuButtonProps = {
|
|
16
15
|
ariaLabel?: string;
|
|
17
16
|
children?: ReactNode;
|