Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(insights): add icons and dashboard. #4803

Merged
merged 1 commit into from
Jul 21, 2023
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
27 changes: 27 additions & 0 deletions packages/insights/src/components/icons/close.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { type QwikIntrinsicElements } from '@builder.io/qwik';
import { css, cx } from '~/styled-system/css';

export function CloseIcon(props: QwikIntrinsicElements['svg'], key: string) {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="1em"
height="1em"
viewBox="0 0 24 24"
{...props}
class={cx(
css({
display: 'inline-block',
margin: '4px 2px',
}),
String(props.class)
)}
key={key}
>
<path
fill="currentColor"
d="M19 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2m-3.4 14L12 13.4L8.4 17L7 15.6l3.6-3.6L7 8.4L8.4 7l3.6 3.6L15.6 7L17 8.4L13.4 12l3.6 3.6l-1.4 1.4Z"
></path>
</svg>
);
}
25 changes: 25 additions & 0 deletions packages/insights/src/components/icons/dashboard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { type QwikIntrinsicElements } from '@builder.io/qwik';

export function DashboardIcon(props: QwikIntrinsicElements['svg'], key: string) {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="1em"
height="1em"
viewBox="0 0 24 24"
{...props}
key={key}
>
<g
fill="none"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="1.5"
>
<path d="M12 4v4M4 8l2.5 2.5m11 0L20 8M3 17h3m6 0l1-6m5 6h3M8.5 20.001H4A9.956 9.956 0 0 1 2 14C2 8.477 6.477 4 12 4s10 4.477 10 10c0 2.252-.744 4.33-2 6.001L15.5 20"></path>
<path d="M12 23a3 3 0 1 0 0-6a3 3 0 0 0 0 6Z"></path>
</g>
</svg>
);
}
23 changes: 23 additions & 0 deletions packages/insights/src/components/icons/edge.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { type QwikIntrinsicElements } from '@builder.io/qwik';

export function EdgeIcon(props: QwikIntrinsicElements['svg'], key: string) {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="1em"
height="1em"
viewBox="0 0 24 24"
{...props}
key={key}
>
<path
fill="none"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M18 3a3 3 0 0 1 3 3v12a3 3 0 0 1-3 3M3 18V6a3 3 0 1 1 6 0v12a3 3 0 0 1-6 0zm6-6h8m-3 3l3-3l-3-3"
></path>
</svg>
);
}
8 changes: 8 additions & 0 deletions packages/insights/src/components/icons/error.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { type QwikIntrinsicElements } from '@builder.io/qwik';
import { css, cx } from '~/styled-system/css';

export const ErrorIcon = function MaterialSymbolsChatErrorSharp(
props: QwikIntrinsicElements['svg'],
Expand All @@ -11,6 +12,13 @@ export const ErrorIcon = function MaterialSymbolsChatErrorSharp(
height="1em"
viewBox="0 0 24 24"
{...props}
class={cx(
String(props.class),
css({
display: 'inline-block',
margin: '4px 2px',
})
)}
key={key}
>
<path
Expand Down
98 changes: 98 additions & 0 deletions packages/insights/src/components/popup-manager/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import {
type Component,
Slot,
component$,
useStore,
useSignal,
type NoSerialize,
} from '@builder.io/qwik';
import { css } from '~/styled-system/css';
import { CloseIcon } from '../icons/close';

export const PopupManager = component$(() => {
const popupTarget = useSignal<HTMLElement>();
const popup = useStore({
Component: null as null | NoSerialize<Component<any>>,
props: null as any,
currentTarget: null as null | HTMLElement,
popupTarget: null as null | HTMLElement,
x: 0,
y: 0,
});
return (
<div
document:onMouseEnter$={(e) => {
const target = e.target;
if (isHTMLElement(target)) {
if (popup.currentTarget?.contains(target) || popupTarget.value?.contains(target)) {
return;
}
target.dispatchEvent(
new CustomEvent('popup', {
bubbles: false,
detail: {
show<T extends {}>(component: Component<T>, props: T) {
// TODO: Remove cast once https://github.com/BuilderIO/qwik/issues/4794 is fixed
(popup as { Component: any }).Component = component;
popup.props = props;
popup.currentTarget = target;
},
} satisfies PopupEvent['detail'],
})
);
}
}}
document:onMouseLeave$={(e) => {
const target = e.target;
if (isHTMLElement(target)) {
if (
e.shiftKey ||
popup.currentTarget?.contains(target) ||
popupTarget.value?.contains(target) ||
popupTarget.value?.contains(e.relatedTarget as HTMLElement | null)
) {
return;
}
popup.currentTarget = null;
}
}}
document:onMouseMove$={(e) => {
if (!e.shiftKey) {
popup.x = e.clientX;
popup.y = e.clientY;
}
}}
>
<Slot />
{popup.currentTarget && popup.Component ? (
<div
ref={popupTarget}
class={css({
display: 'inline-block',
position: 'fixed',
border: '1px solid black',
backgroundColor: 'white',
})}
style={{
top: popup.y + 4 + 'px',
left: popup.x + 4 + 'px',
}}
>
<CloseIcon
onClick$={() => (popup.currentTarget = null)}
class={css({ position: 'absolute', right: '0px', margin: 0 })}
/>
<popup.Component {...popup.props} />
</div>
) : null}
</div>
);
});

function isHTMLElement(target: any): target is HTMLElement {
return target && target.nodeType === 1;
}

export type PopupEvent = CustomEvent<{
show<PROPS extends {}>(component: Component<PROPS>, props: PROPS): void;
}>;
129 changes: 32 additions & 97 deletions packages/insights/src/components/symbol/index.tsx
Original file line number Diff line number Diff line change
@@ -1,100 +1,50 @@
import {
$,
Resource,
Slot,
component$,
createContextId,
useContext,
useContextProvider,
useResource$,
useStore,
type ContextId,
type QwikMouseEvent,
} from '@builder.io/qwik';
import { Resource, component$, useResource$, useStore } from '@builder.io/qwik';
import { server$, useLocation } from '@builder.io/qwik-city';
import { and, eq } from 'drizzle-orm';
import { getDB, symbolDetailTable } from '~/db';
import { css } from '~/styled-system/css';
import { SymbolIcon } from '../icons/symbol';
import { type PopupEvent } from '../popup-manager';

const symbolHoverContext = createContextId<{
visible: boolean;
symbolHash: string;
x: number;
y: number;
}>('SymbolHoverContext');

export const SymbolProvider = component$(() => {
const symbolHover = useStore<typeof symbolHoverContext extends ContextId<infer T> ? T : unknown>({
visible: false,
symbolHash: '',
x: 0,
y: 0,
});
useContextProvider(symbolHoverContext, symbolHover);
export const SymbolPopup = component$<{ symbolHash: string }>(({ symbolHash }) => {
return (
<>
<Slot />
<div
style={{
display: symbolHover.visible ? 'block' : 'none',
top: symbolHover.y + 4 + 'px',
left: symbolHover.x + 4 + 'px',
}}
<div
class={css({
minWidth: '300px',
minHeight: '300px',
})}
>
<h1
class={css({
display: 'none',
position: 'fixed',
background: 'white',
border: '1px solid black',
borderRadius: '8px',
padding: '5px',
width: '50vw',
height: '50vh',
overflow: 'scroll',
fontWeight: 'bold',
fontSize: '14px',
})}
>
<button
class={css({
float: 'right',
padding: '2px 4px',
cursor: 'pointer',
})}
onClick$={() => (symbolHover.visible = false)}
>
</button>
<h1
Symbol:{' '}
<code
class={css({
fontFamily: 'monospace',
fontWeight: 'bold',
fontSize: '14px',
padding: '2px 4px',
backgroundColor: '#EEE',
border: '1px solid #CCC',
borderRadius: '5px',
})}
>
Symbol:{' '}
<code
class={css({
fontFamily: 'monospace',
fontWeight: 'bold',
fontSize: '14px',
padding: '2px 4px',
backgroundColor: '#EEE',
border: '1px solid #CCC',
borderRadius: '5px',
})}
>
{symbolHover.symbolHash}
</code>
</h1>
<div
class={css({
display: 'flex',
flexDirection: 'column',
justifyContent: 'flex-start',
})}
>
<SymbolSource symbolHash={symbolHover.symbolHash} />
</div>
{symbolHash}
</code>
</h1>
<div
class={css({
display: 'flex',
flexDirection: 'column',
justifyContent: 'flex-start',
})}
>
<SymbolSource symbolHash={symbolHash} />
</div>
</>
</div>
);
});

Expand Down Expand Up @@ -190,24 +140,8 @@ export const SymbolSource = component$<{ symbolHash: string }>(({ symbolHash })
});

export const SymbolCmp = component$<{ symbol: string }>(({ symbol }) => {
const symbolHover = useContext(symbolHoverContext);
const onMouseMove = $((event: QwikMouseEvent) => {
if (event.shiftKey) return;
symbolHover.x = event.clientX;
symbolHover.y = event.clientY;
});
return (
<code
onMouseEnter$={async (e, target) => {
symbolHover.visible = true;
symbolHover.symbolHash = target.textContent!;
await onMouseMove(e);
}}
onMouseLeave$={(event) => {
if (event.shiftKey) return;
symbolHover.visible = false;
}}
onMouseMove$={onMouseMove}
class={css({
fontFamily: 'monospace',
fontWeight: 'bold',
Expand All @@ -218,6 +152,7 @@ export const SymbolCmp = component$<{ symbol: string }>(({ symbol }) => {
borderRadius: '5px',
whiteSpace: 'nowrap',
})}
onPopup$={(e: PopupEvent) => e.detail.show(SymbolPopup, { symbolHash: symbol })}
>
<SymbolIcon
class={css({ display: 'inline-block', marginBottom: '1px', marginRight: '2px' })}
Expand Down
Loading