Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
159 changes: 109 additions & 50 deletions src/components/OnlyAdminsBadge.js
Original file line number Diff line number Diff line change
@@ -1,75 +1,134 @@
import { useState } from 'react'
import { useState, useId, useRef, useLayoutEffect } from 'react';
import { createPortal } from 'react-dom';

export function OnlyAdminsBadge() {
return OnlyBadge({ title: "Only Admins", tooltip: "This section describes functionality that's only available for users with a System Admin role." });
return Badge({
title: "Only Admins",
tooltip: "Only available for users with a System Admin role."
});
}

export function OnlyOperatorsBadge() {
return OnlyBadge({ title: "Requires Operator", tooltip: "This section describes functionality that requires at least Operator permissions on the flow" });
return Badge({
title: "Requires Operator",
tooltip: "Only available for users with at least Operator permissions on the flow."
});
}

export function OnlyFolderAdminsBadge() {
return OnlyBadge({ title: "Only Admins", tooltip: "This section describes functionality that's only available for users with a Folder or System Admin role."});
return Badge({
title: "Only Admins",
tooltip: "Only available for users with a Folder or System Admin role."
});
}

export function OnlyBadge({title, tooltip}) {
export function NewSinceBadge({ version }) {
return Badge({
title: `New since ${version}`,
tooltip: `Feature included since Invictus ${version}.`,
backgroundColor: '#008800',
color: 'white',
});
}

export function Badge({ title, tooltip, backgroundColor = '#b55d00', color = 'white' }) {
const [visible, setVisible] = useState(false);
return (
const [usePortal, setUsePortal] = useState(false);
const [tooltipPos, setTooltipPos] = useState({ top: 0, left: 0 });
const badgeRef = useRef(null);
const tooltipId = useId();

useLayoutEffect(() => {
if (visible && badgeRef.current) {
const rect = badgeRef.current.getBoundingClientRect();
const navHeight = 60; // adjust to your nav height
const spaceAbove = rect.top - navHeight;

// Decide if we need portal (tooltip is hidden under nav)
if (spaceAbove < 50) {
setUsePortal(true);
setTooltipPos({
top: rect.top - 40,
left: rect.left + rect.width / 2,
});
} else {
setUsePortal(false);
}
}
}, [visible]);

const tooltipElement = (
<span
style={{ position: 'relative', display: 'inline-block', marginLeft: '8px', textTransform: 'none', fontWeight: 'bold' }}
onMouseEnter={() => setVisible(true)}
onMouseLeave={() => setVisible(false)}
id={tooltipId}
role="tooltip"
style={{
position: usePortal ? 'fixed' : 'absolute',
bottom: usePortal ? 'auto' : '125%',
top: usePortal ? tooltipPos.top : 'auto',
left: usePortal ? tooltipPos.left : '50%',
transform: usePortal ? 'translateX(-50%)' : 'translateX(-50%)',
backgroundColor: '#333',
color: '#fff',
padding: '10px',
borderRadius: '6px',
whiteSpace: 'nowrap',
fontSize: '0.9rem',
fontFamily: 'Bitter',
fontWeight: 'normal',
zIndex: 1000,
pointerEvents: 'none',
boxShadow: '0px 0px 10px rgba(0, 0, 0, 0.3)',
}}
>
{tooltip}
<span
style={{
backgroundColor: '#FDECEA',
color: '#D93025 ',
padding: '2px 6px',
borderRadius: '4px',
fontSize: '0.75rem',
fontWeight: '600',
fontFamily: 'Bitter',
cursor: 'default',
userSelect: 'none',
position: 'absolute',
top: usePortal ? '100%' : '100%',
left: '50%',
marginLeft: '-5px',
width: 0,
height: 0,
borderLeft: '5px solid transparent',
borderRight: '5px solid transparent',
borderTop: '5px solid #333',
}}
/>
</span>
);

return (
<>
<span
ref={badgeRef}
style={{ position: 'relative', display: 'inline-block', marginLeft: '8px', textTransform: 'none', fontWeight: 'bold' }}
role="button"
aria-describedby={visible ? tooltipId : undefined}
onMouseEnter={() => setVisible(true)}
onMouseLeave={() => setVisible(false)}
onFocus={() => setVisible(true)}
onBlur={() => setVisible(false)}
>
{title}
</span>
{visible && (
<span
tabIndex={0}
style={{
position: 'absolute',
bottom: '125%',
left: '50%',
transform: 'translateX(-50%)',
backgroundColor: '#333',
color: '#fff',
padding: '6px',
borderRadius: '6px',
whiteSpace: 'nowrap',
fontSize: '0.75rem',
backgroundColor: backgroundColor,
color: color,
padding: '2px 6px',
borderRadius: '4px',
fontSize: '1rem',
fontWeight: '600',
fontFamily: 'Bitter',
fontWeight: 'normal',
zIndex: 10,
pointerEvents: 'none',
cursor: 'default',
userSelect: 'none',
}}
>
{tooltip}
<span
style={{
position: 'absolute',
top: '100%',
left: '50%',
marginLeft: '-5px',
width: 0,
height: 0,
borderLeft: '5px solid transparent',
borderRight: '5px solid transparent',
borderTop: '5px solid #333',
}}
/>
{title}
</span>
)}
</span>
{!usePortal && visible && tooltipElement}
</span>

{visible && usePortal && createPortal(tooltipElement, document.body)}
</>
);
}
149 changes: 90 additions & 59 deletions src/components/SharedNoteBadge.js
Original file line number Diff line number Diff line change
@@ -1,80 +1,111 @@
import { useState, useId } from 'react';
import { useState, useId, useRef, useLayoutEffect } from 'react';
import { createPortal } from 'react-dom';

export function SharedNote() {
const [visible, setVisible] = useState(false);
const [usePortal, setUsePortal] = useState(false);
const [tooltipPos, setTooltipPos] = useState({ top: 0, left: 0 });
const badgeRef = useRef(null);
const tooltipId = useId();

return (
useLayoutEffect(() => {
if (visible && badgeRef.current) {
const rect = badgeRef.current.getBoundingClientRect();
const navHeight = 60; // adjust to match your nav height
const spaceAbove = rect.top - navHeight;

if (spaceAbove < 50) {
// Tooltip would be hidden under nav → use portal
setUsePortal(true);
setTooltipPos({
top: rect.top - 40,
left: rect.left + rect.width / 2,
});
} else {
setUsePortal(false);
}
}
}, [visible]);

const tooltipElement = (
<span
id={tooltipId}
role="tooltip"
style={{
position: 'relative',
display: 'inline-block',
marginLeft: '8px',
textTransform: 'none',
fontWeight: 'bold',
position: usePortal ? 'fixed' : 'absolute',
bottom: usePortal ? 'auto' : '125%',
top: usePortal ? tooltipPos.top : 'auto',
left: usePortal ? tooltipPos.left : '50%',
transform: 'translateX(-50%)',
backgroundColor: '#333',
color: '#fff',
padding: '6px',
borderRadius: '6px',
whiteSpace: 'nowrap',
fontSize: '0.9rem',
fontFamily: 'Bitter',
fontWeight: 'normal',
zIndex: 1000,
pointerEvents: 'none',
boxShadow: '0px 0px 10px rgba(0, 0, 0, 0.3)',
}}
>
Same for both Dashboard and Framework. Can be skipped if done already.
<span
tabIndex={0}
role="button"
aria-describedby={visible ? tooltipId : undefined}
onMouseEnter={() => setVisible(true)}
onMouseLeave={() => setVisible(false)}
onFocus={() => setVisible(true)}
onBlur={() => setVisible(false)}
style={{
backgroundColor: '#e0f7f7',
color: '#0b6369',
padding: '2px 6px',
borderRadius: '4px',
fontSize: '0.75rem',
fontWeight: '600',
fontFamily: 'Bitter',
cursor: 'default',
userSelect: 'none',
outline: 'none',
position: 'absolute',
top: '100%',
left: '50%',
marginLeft: '-5px',
width: 0,
height: 0,
borderLeft: '5px solid transparent',
borderRight: '5px solid transparent',
borderTop: '5px solid #333',
}}
>
Shared
</span>
/>
</span>
);

{visible && (
return (
<>
<span
ref={badgeRef}
style={{
position: 'relative',
display: 'inline-block',
marginLeft: '8px',
textTransform: 'none',
fontWeight: 'bold',
}}
>
<span
id={tooltipId}
role="tooltip"
tabIndex={0}
role="button"
aria-describedby={visible ? tooltipId : undefined}
onMouseEnter={() => setVisible(true)}
onMouseLeave={() => setVisible(false)}
onFocus={() => setVisible(true)}
onBlur={() => setVisible(false)}
style={{
position: 'absolute',
bottom: '125%',
left: '50%',
transform: 'translateX(-50%)',
backgroundColor: '#333',
color: '#fff',
padding: '6px',
borderRadius: '6px',
whiteSpace: 'nowrap',
fontSize: '0.75rem',
backgroundColor: '#e0f7f7',
color: '#0b6369',
padding: '2px 6px',
borderRadius: '4px',
fontSize: '1rem',
fontWeight: '600',
fontFamily: 'Bitter',
fontWeight: 'normal',
zIndex: 10,
pointerEvents: 'none',
cursor: 'default',
userSelect: 'none',
outline: 'none',
}}
>
This section is the same for both Dashboard and Framework. Can be skipped if done already.
<span
style={{
position: 'absolute',
top: '100%',
left: '50%',
marginLeft: '-5px',
width: 0,
height: 0,
borderLeft: '5px solid transparent',
borderRight: '5px solid transparent',
borderTop: '5px solid #333',
}}
/>
Shared
</span>
)}
</span>
{!usePortal && visible && tooltipElement}
</span>

{visible && usePortal && createPortal(tooltipElement, document.body)}
</>
);
}
1 change: 0 additions & 1 deletion src/data/dashboard.v6.bicep.parameters.json
Original file line number Diff line number Diff line change
Expand Up @@ -759,7 +759,6 @@
{
"name": "flowActivityIntervalInMinutes",
"description": "The time period threshold (in minutes) to update the active flow traces watermark during finalizing pending flow traces in the merge job.",
"deprecatedSince": "v6.2, will be removed in v7, support for custom event tracking for flow activity stops.",
"default": "55",
"tags": [
"monitoring"
Expand Down
Binary file removed static/images/v2_alerting4.png
Binary file not shown.
Binary file removed static/images/v2_dsb-createflow.png
Binary file not shown.
Binary file removed static/images/v2_folderpermissions2.png
Binary file not shown.
Loading
Loading