Skip to content

Commit a5f9d4a

Browse files
committed
Issue #34: add missing webcomponents
1 parent b597b8c commit a5f9d4a

File tree

1 file changed

+176
-0
lines changed

1 file changed

+176
-0
lines changed

src/configuration/DataLink.tsx

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
import { css } from '@emotion/css';
2+
import React, { Dispatch, SetStateAction, useEffect, useState } from 'react';
3+
import { usePrevious } from 'react-use';
4+
5+
import { DataSourceInstanceSettings, VariableSuggestion } from '@grafana/data';
6+
import {
7+
Button,
8+
DataLinkInput,
9+
InlineField,
10+
InlineSwitch,
11+
InlineFieldRow,
12+
InlineLabel,
13+
Input,
14+
useStyles2
15+
} from '@grafana/ui';
16+
17+
import { DataSourcePicker } from '@grafana/runtime'
18+
19+
import { DataLinkConfig } from '../types';
20+
21+
interface Props {
22+
value: DataLinkConfig;
23+
onChange: (value: DataLinkConfig) => void;
24+
onDelete: () => void;
25+
suggestions: VariableSuggestion[];
26+
className?: string;
27+
}
28+
29+
export const DataLink = (props: Props) => {
30+
const { value, onChange, onDelete, suggestions, className } = props;
31+
const styles = useStyles2(getStyles);
32+
const [showInternalLink, setShowInternalLink] = useInternalLink(value.datasourceUid);
33+
34+
const handleChange = (field: keyof typeof value) => (event: React.ChangeEvent<HTMLInputElement>) => {
35+
onChange({
36+
...value,
37+
[field]: event.currentTarget.value,
38+
});
39+
};
40+
41+
return (
42+
<div className={className}>
43+
<div className={styles.firstRow}>
44+
<InlineField
45+
label="Field"
46+
htmlFor="elasticsearch-datasource-config-field"
47+
labelWidth={12}
48+
tooltip={'Can be exact field name or a regex pattern that will match on the field name.'}
49+
>
50+
<Input
51+
type="text"
52+
id="elasticsearch-datasource-config-field"
53+
value={value.field}
54+
onChange={handleChange('field')}
55+
width={100}
56+
/>
57+
</InlineField>
58+
<Button
59+
variant={'destructive'}
60+
title="Remove field"
61+
icon="times"
62+
onClick={(event) => {
63+
event.preventDefault();
64+
onDelete();
65+
}}
66+
/>
67+
</div>
68+
69+
<InlineFieldRow>
70+
<div className={styles.urlField}>
71+
<InlineLabel htmlFor="elasticsearch-datasource-internal-link" width={12}>
72+
{showInternalLink ? 'Query' : 'URL'}
73+
</InlineLabel>
74+
<DataLinkInput
75+
placeholder={showInternalLink ? '${__value.raw}' : 'http://example.com/${__value.raw}'}
76+
value={value.url || ''}
77+
onChange={(newValue) =>
78+
onChange({
79+
...value,
80+
url: newValue,
81+
})
82+
}
83+
suggestions={suggestions}
84+
/>
85+
</div>
86+
87+
<div className={styles.urlDisplayLabelField}>
88+
<InlineField
89+
label="URL Label"
90+
htmlFor="elasticsearch-datasource-url-label"
91+
labelWidth={14}
92+
tooltip={'Use to override the button label.'}
93+
>
94+
<Input
95+
type="text"
96+
id="elasticsearch-datasource-url-label"
97+
value={value.urlDisplayLabel}
98+
onChange={handleChange('urlDisplayLabel')}
99+
/>
100+
</InlineField>
101+
</div>
102+
</InlineFieldRow>
103+
104+
<div className={styles.row}>
105+
<InlineField label="Internal link" labelWidth={12}>
106+
<InlineSwitch
107+
label="Internal link"
108+
value={showInternalLink || false}
109+
onChange={() => {
110+
if (showInternalLink) {
111+
onChange({
112+
...value,
113+
datasourceUid: undefined,
114+
});
115+
}
116+
setShowInternalLink(!showInternalLink);
117+
}}
118+
/>
119+
</InlineField>
120+
121+
{showInternalLink && (
122+
<DataSourcePicker
123+
tracing={true}
124+
onChange={(ds: DataSourceInstanceSettings) => {
125+
onChange({
126+
...value,
127+
datasourceUid: ds.uid,
128+
});
129+
}}
130+
current={value.datasourceUid}
131+
/>
132+
)}
133+
</div>
134+
</div>
135+
);
136+
};
137+
138+
function useInternalLink(datasourceUid?: string): [boolean, Dispatch<SetStateAction<boolean>>] {
139+
const [showInternalLink, setShowInternalLink] = useState<boolean>(!!datasourceUid);
140+
const previousUid = usePrevious(datasourceUid);
141+
142+
// Force internal link visibility change if uid changed outside of this component.
143+
useEffect(() => {
144+
if (!previousUid && datasourceUid && !showInternalLink) {
145+
setShowInternalLink(true);
146+
}
147+
if (previousUid && !datasourceUid && showInternalLink) {
148+
setShowInternalLink(false);
149+
}
150+
}, [previousUid, datasourceUid, showInternalLink]);
151+
152+
return [showInternalLink, setShowInternalLink];
153+
}
154+
155+
const getStyles = () => ({
156+
firstRow: css`
157+
display: flex;
158+
`,
159+
nameField: css`
160+
flex: 2;
161+
`,
162+
regexField: css`
163+
flex: 3;
164+
`,
165+
row: css`
166+
display: flex;
167+
align-items: baseline;
168+
`,
169+
urlField: css`
170+
display: flex;
171+
flex: 1;
172+
`,
173+
urlDisplayLabelField: css`
174+
flex: 1;
175+
`,
176+
});

0 commit comments

Comments
 (0)