mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
SearchV2: Fix Move and Delete not updating list in folder view (#49524)
Co-authored-by: Ryan McKinley <ryantxu@gmail.com>
This commit is contained in:
parent
1a324b3330
commit
b344f48e68
@ -190,9 +190,9 @@ const getStyles = (theme: GrafanaTheme2) => {
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
`,
|
`,
|
||||||
cellWrapper: css`
|
nameCellStyle: css`
|
||||||
border-right: none;
|
border-right: none;
|
||||||
padding: ${theme.spacing(1)};
|
padding: ${theme.spacing(1)} ${theme.spacing(1)} ${theme.spacing(1)} ${theme.spacing(2)};
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
user-select: text;
|
user-select: text;
|
||||||
@ -201,6 +201,9 @@ const getStyles = (theme: GrafanaTheme2) => {
|
|||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
|
headerNameStyle: css`
|
||||||
|
padding-left: ${theme.spacing(1)};
|
||||||
|
`,
|
||||||
headerCell: css`
|
headerCell: css`
|
||||||
padding: ${theme.spacing(1)};
|
padding: ${theme.spacing(1)};
|
||||||
`,
|
`,
|
||||||
@ -254,10 +257,11 @@ const getStyles = (theme: GrafanaTheme2) => {
|
|||||||
`,
|
`,
|
||||||
sortedHeader: css`
|
sortedHeader: css`
|
||||||
text-align: right;
|
text-align: right;
|
||||||
|
padding-right: ${theme.spacing(2)};
|
||||||
`,
|
`,
|
||||||
sortedItems: css`
|
sortedItems: css`
|
||||||
text-align: right;
|
text-align: right;
|
||||||
padding: ${theme.spacing(1)};
|
padding: ${theme.spacing(1)} ${theme.spacing(3)} ${theme.spacing(1)} ${theme.spacing(1)};
|
||||||
`,
|
`,
|
||||||
locationCellStyle: css`
|
locationCellStyle: css`
|
||||||
padding-top: ${theme.spacing(1)};
|
padding-top: ${theme.spacing(1)};
|
||||||
|
@ -50,6 +50,8 @@ export const SearchView = ({
|
|||||||
const layout = getValidQueryLayout(query);
|
const layout = getValidQueryLayout(query);
|
||||||
const isFolders = layout === SearchLayout.Folders;
|
const isFolders = layout === SearchLayout.Folders;
|
||||||
|
|
||||||
|
const [listKey, setListKey] = useState(Date.now());
|
||||||
|
|
||||||
const searchQuery = useMemo(() => {
|
const searchQuery = useMemo(() => {
|
||||||
const q: SearchQuery = {
|
const q: SearchQuery = {
|
||||||
query: queryText,
|
query: queryText,
|
||||||
@ -121,7 +123,8 @@ export const SearchView = ({
|
|||||||
// function to update items when dashboards or folders are moved or deleted
|
// function to update items when dashboards or folders are moved or deleted
|
||||||
const onChangeItemsList = async () => {
|
const onChangeItemsList = async () => {
|
||||||
// clean up search selection
|
// clean up search selection
|
||||||
setSearchSelection(newSearchSelection());
|
clearSelection();
|
||||||
|
setListKey(Date.now());
|
||||||
// trigger again the search to the backend
|
// trigger again the search to the backend
|
||||||
onQueryChange(query.query);
|
onQueryChange(query.query);
|
||||||
};
|
};
|
||||||
@ -169,11 +172,13 @@ export const SearchView = ({
|
|||||||
onTagSelected={onTagAdd}
|
onTagSelected={onTagAdd}
|
||||||
renderStandaloneBody={true}
|
renderStandaloneBody={true}
|
||||||
tags={query.tag}
|
tags={query.tag}
|
||||||
|
key={listKey}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<FolderView
|
<FolderView
|
||||||
|
key={listKey}
|
||||||
selection={selection}
|
selection={selection}
|
||||||
selectionToggle={toggleSelection}
|
selectionToggle={toggleSelection}
|
||||||
tags={query.tag}
|
tags={query.tag}
|
||||||
|
@ -77,7 +77,7 @@ export const generateColumns = (
|
|||||||
const selected = selection(kind, uid);
|
const selected = selection(kind, uid);
|
||||||
const hasUID = uid != null; // Panels don't have UID! Likely should not be shown on pages with manage options
|
const hasUID = uid != null; // Panels don't have UID! Likely should not be shown on pages with manage options
|
||||||
return (
|
return (
|
||||||
<div {...p.cellProps} className={p.cellStyle}>
|
<div {...p.cellProps}>
|
||||||
<div className={styles.checkbox}>
|
<div className={styles.checkbox}>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
disabled={!hasUID}
|
disabled={!hasUID}
|
||||||
@ -99,7 +99,7 @@ export const generateColumns = (
|
|||||||
width = Math.max(availableWidth * 0.2, 300);
|
width = Math.max(availableWidth * 0.2, 300);
|
||||||
columns.push({
|
columns.push({
|
||||||
Cell: (p) => {
|
Cell: (p) => {
|
||||||
let classNames = cx(p.cellStyle, styles.cellWrapper);
|
let classNames = cx(styles.nameCellStyle);
|
||||||
let name = access.name.values.get(p.row.index);
|
let name = access.name.values.get(p.row.index);
|
||||||
if (!name?.length) {
|
if (!name?.length) {
|
||||||
name = 'Missing title'; // normal for panels
|
name = 'Missing title'; // normal for panels
|
||||||
@ -113,7 +113,9 @@ export const generateColumns = (
|
|||||||
},
|
},
|
||||||
id: `column-name`,
|
id: `column-name`,
|
||||||
field: access.name!,
|
field: access.name!,
|
||||||
Header: 'Name',
|
Header: () => {
|
||||||
|
return <div className={styles.headerNameStyle}>Name</div>;
|
||||||
|
},
|
||||||
width,
|
width,
|
||||||
});
|
});
|
||||||
availableWidth -= width;
|
availableWidth -= width;
|
||||||
@ -122,6 +124,35 @@ export const generateColumns = (
|
|||||||
columns.push(makeTypeColumn(access.kind, access.panel_type, width, styles));
|
columns.push(makeTypeColumn(access.kind, access.panel_type, width, styles));
|
||||||
availableWidth -= width;
|
availableWidth -= width;
|
||||||
|
|
||||||
|
const meta = response.view.dataFrame.meta?.custom as SearchResultMeta;
|
||||||
|
if (meta?.locationInfo && availableWidth > 0) {
|
||||||
|
width = Math.max(availableWidth / 1.75, 300);
|
||||||
|
availableWidth -= width;
|
||||||
|
columns.push({
|
||||||
|
Cell: (p) => {
|
||||||
|
const parts = (access.location?.values.get(p.row.index) ?? '').split('/');
|
||||||
|
return (
|
||||||
|
<div {...p.cellProps} className={cx(styles.locationCellStyle)}>
|
||||||
|
{parts.map((p) => {
|
||||||
|
const info = meta.locationInfo[p];
|
||||||
|
return info ? (
|
||||||
|
<a key={p} href={info.url} className={styles.locationItem}>
|
||||||
|
<Icon name={getIconForKind(info.kind)} /> {info.name}
|
||||||
|
</a>
|
||||||
|
) : (
|
||||||
|
<span key={p}>{p}</span>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
id: `column-location`,
|
||||||
|
field: access.location ?? access.url,
|
||||||
|
Header: 'Location',
|
||||||
|
width,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Show datasources if we have any
|
// Show datasources if we have any
|
||||||
if (access.ds_uid && onDatasourceChange) {
|
if (access.ds_uid && onDatasourceChange) {
|
||||||
width = DATASOURCE_COLUMN_WIDTH;
|
width = DATASOURCE_COLUMN_WIDTH;
|
||||||
@ -138,35 +169,8 @@ export const generateColumns = (
|
|||||||
availableWidth -= width;
|
availableWidth -= width;
|
||||||
}
|
}
|
||||||
|
|
||||||
width = Math.max(availableWidth / 2.5, 200);
|
if (availableWidth > 0) {
|
||||||
columns.push(makeTagsColumn(access.tags, width, styles.tagList, onTagSelected));
|
columns.push(makeTagsColumn(access.tags, availableWidth, styles.tagList, onTagSelected));
|
||||||
availableWidth -= width;
|
|
||||||
|
|
||||||
const meta = response.view.dataFrame.meta?.custom as SearchResultMeta;
|
|
||||||
if (meta?.locationInfo && availableWidth > 0) {
|
|
||||||
columns.push({
|
|
||||||
Cell: (p) => {
|
|
||||||
const parts = (access.location?.values.get(p.row.index) ?? '').split('/');
|
|
||||||
return (
|
|
||||||
<div {...p.cellProps} className={cx(p.cellStyle, styles.locationCellStyle)}>
|
|
||||||
{parts.map((p) => {
|
|
||||||
const info = meta.locationInfo[p];
|
|
||||||
return info ? (
|
|
||||||
<a key={p} href={info.url} className={styles.locationItem}>
|
|
||||||
<Icon name={getIconForKind(info.kind)} /> {info.name}
|
|
||||||
</a>
|
|
||||||
) : (
|
|
||||||
<span key={p}>{p}</span>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
id: `column-location`,
|
|
||||||
field: access.location ?? access.url,
|
|
||||||
Header: 'Location',
|
|
||||||
width: availableWidth,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sortField) {
|
if (sortField) {
|
||||||
@ -223,7 +227,7 @@ function makeDataSourceColumn(
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<div {...p.cellProps} className={cx(p.cellStyle, datasourceItemClass)}>
|
<div {...p.cellProps} className={cx(datasourceItemClass)}>
|
||||||
{dslist.map((v, i) => {
|
{dslist.map((v, i) => {
|
||||||
const settings = srv.getInstanceSettings(v);
|
const settings = srv.getInstanceSettings(v);
|
||||||
const icon = settings?.meta?.info?.logos?.small;
|
const icon = settings?.meta?.info?.logos?.small;
|
||||||
@ -283,16 +287,12 @@ function makeTypeColumn(
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'panel':
|
case 'panel':
|
||||||
icon = 'public/img/icons/unicons/graph-bar.svg';
|
icon = 'public/img/icons/mono/library-panel.svg';
|
||||||
const type = typeField.values.get(i);
|
const type = typeField.values.get(i);
|
||||||
if (type) {
|
if (type) {
|
||||||
txt = type;
|
txt = type;
|
||||||
const info = config.panels[txt];
|
const info = config.panels[txt];
|
||||||
if (info?.name) {
|
if (info?.name) {
|
||||||
const v = info.info?.logos.small;
|
|
||||||
if (v && v.endsWith('.svg')) {
|
|
||||||
icon = v;
|
|
||||||
}
|
|
||||||
txt = info.name;
|
txt = info.name;
|
||||||
} else {
|
} else {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
@ -302,7 +302,6 @@ function makeTypeColumn(
|
|||||||
break;
|
break;
|
||||||
case 'singlestat': // auto-migration
|
case 'singlestat': // auto-migration
|
||||||
txt = 'Singlestat';
|
txt = 'Singlestat';
|
||||||
icon = `public/app/plugins/panel/stat/img/icn-singlestat-panel.svg`;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
icon = `public/img/icons/unicons/question.svg`; // plugin not found
|
icon = `public/img/icons/unicons/question.svg`; // plugin not found
|
||||||
@ -333,7 +332,7 @@ function makeTagsColumn(
|
|||||||
Cell: (p) => {
|
Cell: (p) => {
|
||||||
const tags = field.values.get(p.row.index);
|
const tags = field.values.get(p.row.index);
|
||||||
return tags ? (
|
return tags ? (
|
||||||
<div {...p.cellProps} className={p.cellStyle}>
|
<div {...p.cellProps}>
|
||||||
<TagList className={tagListClass} tags={tags} onClick={onTagSelected} />
|
<TagList className={tagListClass} tags={tags} onClick={onTagSelected} />
|
||||||
</div>
|
</div>
|
||||||
) : null;
|
) : null;
|
||||||
|
Loading…
Reference in New Issue
Block a user