mirror of https://github.com/grafana/grafana
Variables: Adds description field (#29332)
* Variables: Adds description field * Refactor: Adds new Form components * Refactor: Fixes aria labels * Refactor: removes skipped tests * Refactor: Breaks out smaller select components * Refactor: removes gf-form div * Refactor: Breaks up several more selects into smaller components * Chore: Fixes typingspull/29341/head^2
parent
b7dc6a1a22
commit
04d857dfe6
@ -1,710 +0,0 @@ |
||||
import { e2e } from '@grafana/e2e'; |
||||
|
||||
// skipped scenario helper because of some perf issue upgrading cypress to 4.5.0 and splitted the whole test into smaller
|
||||
// several it functions. Very important to keep the order of these it functions because they have dependency in the order
|
||||
// https://github.com/cypress-io/cypress/issues/5987
|
||||
// https://github.com/cypress-io/cypress/issues/6023#issuecomment-574031655
|
||||
describe.skip('Variables', () => { |
||||
let lastUid = ''; |
||||
let lastData = ''; |
||||
let variables: VariablesData[] = [ |
||||
{ name: 'query1', query: '*', label: 'query1-label', options: ['All', 'A', 'B', 'C'], selectedOption: 'A' }, |
||||
{ |
||||
name: 'query2', |
||||
query: '$query1.*', |
||||
label: 'query2-label', |
||||
options: ['All', 'AA', 'AB', 'AC'], |
||||
selectedOption: 'AA', |
||||
}, |
||||
{ |
||||
name: 'query3', |
||||
query: '$query1.$query2.*', |
||||
label: 'query3-label', |
||||
options: ['All', 'AAA', 'AAB', 'AAC'], |
||||
selectedOption: 'AAA', |
||||
}, |
||||
]; |
||||
|
||||
beforeEach(() => { |
||||
e2e.flows.login('admin', 'admin'); |
||||
if (!lastUid || !lastData) { |
||||
e2e.flows.addDataSource(); |
||||
e2e.flows.addDashboard(); |
||||
lastUid = 'test'; |
||||
lastData = 'test'; |
||||
} else { |
||||
e2e.flows.openDashboard(); |
||||
} |
||||
}); |
||||
|
||||
it(`asserts defaults`, () => { |
||||
e2e.pages.Dashboard.Toolbar.toolbarItems('Dashboard settings').click(); |
||||
e2e.pages.Dashboard.Settings.General.sectionItems('Variables').click(); |
||||
e2e.pages.Dashboard.Settings.Variables.List.addVariableCTA().click(); |
||||
|
||||
assertDefaultsForNewVariable(); |
||||
}); |
||||
|
||||
variables.forEach((variable, index) => { |
||||
it(`creates variable ${variable.name}`, () => { |
||||
e2e.pages.Dashboard.Toolbar.toolbarItems('Dashboard settings').click(); |
||||
e2e.pages.Dashboard.Settings.General.sectionItems('Variables').click(); |
||||
|
||||
if (index === 0) { |
||||
e2e.pages.Dashboard.Settings.Variables.List.addVariableCTA().click(); |
||||
} else { |
||||
e2e.pages.Dashboard.Settings.Variables.List.newButton().click(); |
||||
} |
||||
|
||||
const { name, label, query, options, selectedOption } = variable; |
||||
e2e.getScenarioContext().then(({ lastAddedDataSource }: any) => { |
||||
createQueryVariable({ |
||||
dataSourceName: lastAddedDataSource, |
||||
name, |
||||
label, |
||||
query, |
||||
options, |
||||
selectedOption, |
||||
}); |
||||
}); |
||||
|
||||
e2e.pages.Dashboard.Settings.General.saveDashBoard() |
||||
.should('be.visible') |
||||
.click(); |
||||
e2e.pages.SaveDashboardModal.save() |
||||
.should('be.visible') |
||||
.click(); |
||||
e2e.flows.assertSuccessNotification(); |
||||
|
||||
e2e.components.BackButton.backArrow() |
||||
.should('be.visible') |
||||
.click(); |
||||
}); |
||||
}); |
||||
|
||||
it(`asserts submenus`, () => { |
||||
assertVariableLabelsAndComponents(variables); |
||||
}); |
||||
|
||||
it(`asserts variable table`, () => { |
||||
e2e.pages.Dashboard.Toolbar.toolbarItems('Dashboard settings') |
||||
.should('be.visible') |
||||
.click(); |
||||
e2e.pages.Dashboard.Settings.General.sectionItems('Variables') |
||||
.should('be.visible') |
||||
.click(); |
||||
|
||||
assertVariableTable(variables); |
||||
}); |
||||
|
||||
it(`asserts variable selects`, () => { |
||||
assertSelects(variables); |
||||
}); |
||||
|
||||
it(`asserts duplicate variable`, () => { |
||||
// mutates variables
|
||||
variables = assertDuplicateItem(variables); |
||||
e2e.flows.saveDashboard(); |
||||
}); |
||||
|
||||
it(`asserts delete variable`, () => { |
||||
// mutates variables
|
||||
variables = assertDeleteItem(variables); |
||||
e2e.flows.saveDashboard(); |
||||
}); |
||||
|
||||
it(`asserts update variable`, () => { |
||||
// mutates variables
|
||||
variables = assertUpdateItem(variables); |
||||
e2e.components.BackButton.backArrow() |
||||
.should('be.visible') |
||||
.should('be.visible') |
||||
.click(); |
||||
e2e.flows.saveDashboard(); |
||||
}); |
||||
|
||||
it(`asserts move variable down`, () => { |
||||
e2e.pages.Dashboard.Toolbar.toolbarItems('Dashboard settings') |
||||
.should('be.visible') |
||||
.click(); |
||||
e2e.pages.Dashboard.Settings.General.sectionItems('Variables') |
||||
.should('be.visible') |
||||
.click(); |
||||
|
||||
// mutates variables
|
||||
variables = assertMoveDownItem(variables); |
||||
e2e.flows.saveDashboard(); |
||||
}); |
||||
|
||||
it(`asserts move variable up`, () => { |
||||
e2e.pages.Dashboard.Toolbar.toolbarItems('Dashboard settings') |
||||
.should('be.visible') |
||||
.click(); |
||||
e2e.pages.Dashboard.Settings.General.sectionItems('Variables') |
||||
.should('be.visible') |
||||
.click(); |
||||
|
||||
// mutates variables
|
||||
assertMoveUpItem(variables); |
||||
}); |
||||
}); |
||||
|
||||
interface VariablesData { |
||||
name: string; |
||||
query: string; |
||||
label: string; |
||||
options: string[]; |
||||
selectedOption: string; |
||||
} |
||||
|
||||
interface CreateQueryVariableArguments extends VariablesData { |
||||
dataSourceName: string; |
||||
} |
||||
|
||||
const assertDefaultsForNewVariable = () => { |
||||
e2e.pages.Dashboard.Settings.Variables.Edit.General.generalNameInput().within(input => { |
||||
expect(input.attr('placeholder')).equals('name'); |
||||
expect(input.val()).equals(''); |
||||
}); |
||||
e2e.pages.Dashboard.Settings.Variables.Edit.General.generalTypeSelect().within(select => { |
||||
e2e() |
||||
.get('option:selected') |
||||
.should('have.text', 'Query'); |
||||
}); |
||||
e2e.pages.Dashboard.Settings.Variables.Edit.General.generalLabelInput().within(input => { |
||||
expect(input.attr('placeholder')).equals('optional display name'); |
||||
expect(input.val()).equals(''); |
||||
}); |
||||
e2e.pages.Dashboard.Settings.Variables.Edit.General.generalHideSelect().within(select => { |
||||
e2e() |
||||
.get('option:selected') |
||||
.should('have.text', ''); |
||||
}); |
||||
|
||||
e2e.pages.Dashboard.Settings.Variables.Edit.QueryVariable.queryOptionsDataSourceSelect().within(select => { |
||||
e2e() |
||||
.get('option:selected') |
||||
.should('have.text', ''); |
||||
}); |
||||
|
||||
e2e.pages.Dashboard.Settings.Variables.Edit.QueryVariable.queryOptionsQueryInput().should('not.exist'); |
||||
e2e.pages.Dashboard.Settings.Variables.Edit.QueryVariable.queryOptionsRefreshSelect().within(select => { |
||||
e2e() |
||||
.get('option:selected') |
||||
.should('have.text', 'Never'); |
||||
}); |
||||
e2e.pages.Dashboard.Settings.Variables.Edit.QueryVariable.queryOptionsRegExInput().within(input => { |
||||
expect(input.attr('placeholder')).equals('/.*-(.*)-.*/'); |
||||
expect(input.val()).equals(''); |
||||
}); |
||||
e2e.pages.Dashboard.Settings.Variables.Edit.QueryVariable.queryOptionsSortSelect().within(select => { |
||||
e2e() |
||||
.get('option:selected') |
||||
.should('have.text', 'Disabled'); |
||||
}); |
||||
e2e.pages.Dashboard.Settings.Variables.Edit.General.selectionOptionsMultiSwitch().within(select => { |
||||
e2e() |
||||
.get('input') |
||||
.should('not.be.checked'); |
||||
}); |
||||
e2e.pages.Dashboard.Settings.Variables.Edit.General.selectionOptionsIncludeAllSwitch().within(select => { |
||||
e2e() |
||||
.get('input') |
||||
.should('not.be.checked'); |
||||
}); |
||||
e2e.pages.Dashboard.Settings.Variables.Edit.QueryVariable.valueGroupsTagsEnabledSwitch().within(select => { |
||||
e2e() |
||||
.get('input') |
||||
.should('not.be.checked'); |
||||
}); |
||||
e2e.pages.Dashboard.Settings.Variables.Edit.General.previewOfValuesOption().should('not.exist'); |
||||
e2e.pages.Dashboard.Settings.Variables.Edit.General.selectionOptionsCustomAllInput().should('not.exist'); |
||||
}; |
||||
|
||||
const createQueryVariable = ({ name, label, dataSourceName, query }: CreateQueryVariableArguments) => { |
||||
e2e.pages.Dashboard.Settings.Variables.Edit.General.generalNameInput().should('be.visible'); |
||||
e2e.pages.Dashboard.Settings.Variables.Edit.General.generalNameInput().type(name); |
||||
e2e.pages.Dashboard.Settings.Variables.Edit.General.generalLabelInput().type(label); |
||||
e2e.pages.Dashboard.Settings.Variables.Edit.QueryVariable.queryOptionsDataSourceSelect() |
||||
.select(`${dataSourceName}`) |
||||
.blur(); |
||||
e2e.pages.Dashboard.Settings.Variables.Edit.QueryVariable.queryOptionsQueryInput() |
||||
.type(query) |
||||
.blur(); |
||||
e2e.pages.Dashboard.Settings.Variables.Edit.General.previewOfValuesOption().should('exist'); |
||||
e2e.pages.Dashboard.Settings.Variables.Edit.General.selectionOptionsMultiSwitch() |
||||
.click() |
||||
.within(() => { |
||||
e2e() |
||||
.get('input') |
||||
.should('be.checked'); |
||||
}); |
||||
e2e.pages.Dashboard.Settings.Variables.Edit.General.selectionOptionsIncludeAllSwitch() |
||||
.click() |
||||
.within(() => { |
||||
e2e() |
||||
.get('input') |
||||
.should('be.checked'); |
||||
}); |
||||
e2e.pages.Dashboard.Settings.Variables.Edit.General.selectionOptionsCustomAllInput().within(input => { |
||||
expect(input.attr('placeholder')).equals('blank = auto'); |
||||
expect(input.val()).equals(''); |
||||
}); |
||||
e2e.pages.Dashboard.Settings.Variables.Edit.General.submitButton().click(); |
||||
}; |
||||
|
||||
const assertVariableLabelAndComponent = ({ label, options, selectedOption }: VariablesData) => { |
||||
e2e.pages.Dashboard.SubMenu.submenuItemLabels(label).should('be.visible'); |
||||
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts(selectedOption) |
||||
.should('be.visible') |
||||
.click(); |
||||
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownDropDown().should('be.visible'); |
||||
for (let optionIndex = 0; optionIndex < options.length; optionIndex++) { |
||||
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts(options[optionIndex]).should('be.visible'); |
||||
} |
||||
}; |
||||
|
||||
const assertVariableLabelsAndComponents = (args: VariablesData[]) => { |
||||
e2e.pages.Dashboard.SubMenu.submenuItem().should('have.length', args.length); |
||||
for (let index = 0; index < args.length; index++) { |
||||
e2e.pages.Dashboard.SubMenu.submenuItem() |
||||
.eq(index) |
||||
.within(() => { |
||||
e2e() |
||||
.get('label') |
||||
.contains(args[index].name); |
||||
}); |
||||
assertVariableLabelAndComponent(args[index]); |
||||
} |
||||
}; |
||||
|
||||
const assertVariableTableRow = ({ name, query }: VariablesData, index: number, length: number) => { |
||||
e2e.pages.Dashboard.Settings.Variables.List.tableRowNameFields(name) |
||||
.should('exist') |
||||
.contains(name); |
||||
e2e.pages.Dashboard.Settings.Variables.List.tableRowDefinitionFields(name) |
||||
.should('exist') |
||||
.contains(query); |
||||
if (index !== length - 1) { |
||||
e2e.pages.Dashboard.Settings.Variables.List.tableRowArrowDownButtons(name).should('exist'); |
||||
} |
||||
if (index !== 0) { |
||||
e2e.pages.Dashboard.Settings.Variables.List.tableRowArrowUpButtons(name).should('exist'); |
||||
} |
||||
e2e.pages.Dashboard.Settings.Variables.List.tableRowDuplicateButtons(name).should('exist'); |
||||
e2e.pages.Dashboard.Settings.Variables.List.tableRowRemoveButtons(name).should('exist'); |
||||
}; |
||||
|
||||
const assertVariableTable = (args: VariablesData[]) => { |
||||
e2e.pages.Dashboard.Settings.Variables.List.table() |
||||
.should('be.visible') |
||||
.within(() => { |
||||
e2e() |
||||
.get('tbody > tr') |
||||
.should('have.length', args.length); |
||||
}); |
||||
|
||||
for (let index = 0; index < args.length; index++) { |
||||
assertVariableTableRow(args[index], index, args.length); |
||||
} |
||||
}; |
||||
|
||||
const assertSelects = (variables: VariablesData[]) => { |
||||
// Values in submenus should be
|
||||
// query1: [A] query2: [AA] query3: [AAA]
|
||||
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts('A') |
||||
.should('be.visible') |
||||
.click(); |
||||
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('A') |
||||
.should('be.visible') |
||||
.click(); |
||||
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('B') |
||||
.should('be.visible') |
||||
.click(); |
||||
e2e.pages.Dashboard.Toolbar.navBar().click(); |
||||
// Values in submenus should be
|
||||
// query1: [B] query2: [All] query3: [All]
|
||||
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts('All') |
||||
.should('be.visible') |
||||
.should('have.length', 2); |
||||
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts('All') |
||||
.eq(0) |
||||
.should('be.visible') |
||||
.click(); |
||||
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('BA').should('be.visible'); |
||||
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('BB').should('be.visible'); |
||||
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('BC').should('be.visible'); |
||||
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('BB') |
||||
.should('be.visible') |
||||
.click(); |
||||
e2e.pages.Dashboard.Toolbar.navBar() |
||||
.should('be.visible') |
||||
.click(); |
||||
// Values in submenus should be
|
||||
// query1: [B] query2: [BB] query3: [All]
|
||||
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts('All') |
||||
.should('be.visible') |
||||
.should('have.length', 1); |
||||
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts('All') |
||||
.eq(0) |
||||
.should('be.visible') |
||||
.click(); |
||||
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('BBA').should('be.visible'); |
||||
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('BBB').should('be.visible'); |
||||
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('BBC').should('be.visible'); |
||||
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('BBB') |
||||
.should('be.visible') |
||||
.click(); |
||||
e2e.pages.Dashboard.Toolbar.navBar() |
||||
.should('be.visible') |
||||
.click(); |
||||
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts('All').should('have.length', 0); |
||||
// Values in submenus should be
|
||||
// query1: [B] query2: [BB] query3: [BBB]
|
||||
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts('BB') |
||||
.should('be.visible') |
||||
.click(); |
||||
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('BA').should('be.visible'); |
||||
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('BB').should('be.visible'); |
||||
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('BC').should('be.visible'); |
||||
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('BC') |
||||
.should('be.visible') |
||||
.click(); |
||||
e2e.pages.Dashboard.Toolbar.navBar() |
||||
.should('be.visible') |
||||
.click(); |
||||
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts('BB + BC') |
||||
.should('be.visible') |
||||
.should('have.length', 1); |
||||
// Values in submenus should be
|
||||
// query1: [B] query2: [BB + BC] query3: [BBB]
|
||||
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts('BBB') |
||||
.should('be.visible') |
||||
.click(); |
||||
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('BBA').should('be.visible'); |
||||
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('BBB').should('be.visible'); |
||||
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('BBC').should('be.visible'); |
||||
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('BCA').should('be.visible'); |
||||
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('BCB').should('be.visible'); |
||||
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('BCC').should('be.visible'); |
||||
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('BCC') |
||||
.should('be.visible') |
||||
.click(); |
||||
e2e.pages.Dashboard.Toolbar.navBar() |
||||
.should('be.visible') |
||||
.click(); |
||||
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts('BBB + BCC') |
||||
.should('be.visible') |
||||
.should('have.length', 1); |
||||
// Values in submenus should be
|
||||
// query1: [B] query2: [BB + BC] query3: [BBB + BCC]
|
||||
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts('BB + BC') |
||||
.should('be.visible') |
||||
.click(); |
||||
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('BA').should('be.visible'); |
||||
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('BB').should('be.visible'); |
||||
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('BC').should('be.visible'); |
||||
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('BA') |
||||
.should('be.visible') |
||||
.click(); |
||||
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('BB') |
||||
.should('be.visible') |
||||
.click(); |
||||
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('BC') |
||||
.should('be.visible') |
||||
.click(); |
||||
e2e.pages.Dashboard.Toolbar.navBar() |
||||
.should('be.visible') |
||||
.click(); |
||||
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts('BA') |
||||
.should('be.visible') |
||||
.should('have.length', 1); |
||||
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts('All') |
||||
.should('be.visible') |
||||
.should('have.length', 1); |
||||
// Values in submenus should be
|
||||
// query1: [B] query2: [BA] query3: [All]
|
||||
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts('B') |
||||
.should('be.visible') |
||||
.click(); |
||||
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('A') |
||||
.should('be.visible') |
||||
.should('be.visible'); |
||||
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('B') |
||||
.should('be.visible') |
||||
.should('be.visible'); |
||||
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('C') |
||||
.should('be.visible') |
||||
.should('be.visible'); |
||||
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('A') |
||||
.should('be.visible') |
||||
.click(); |
||||
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('B') |
||||
.should('be.visible') |
||||
.click(); |
||||
e2e.pages.Dashboard.Toolbar.navBar() |
||||
.should('be.visible') |
||||
.click(); |
||||
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts('A') |
||||
.should('be.visible') |
||||
.should('have.length', 1); |
||||
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts('All') |
||||
.should('be.visible') |
||||
.should('have.length', 2); |
||||
// Values in submenus should be
|
||||
// query1: [A] query2: [All] query3: [All]
|
||||
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts('All') |
||||
.eq(0) |
||||
.should('be.visible') |
||||
.click(); |
||||
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('AA') |
||||
.should('be.visible') |
||||
.click(); |
||||
e2e.pages.Dashboard.Toolbar.navBar() |
||||
.should('be.visible') |
||||
.click(); |
||||
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts('A') |
||||
.should('be.visible') |
||||
.should('have.length', 1); |
||||
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts('AA') |
||||
.should('be.visible') |
||||
.should('have.length', 1); |
||||
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts('All') |
||||
.should('be.visible') |
||||
.should('have.length', 1); |
||||
// Values in submenus should be
|
||||
// query1: [A] query2: [AA] query3: [All]
|
||||
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts('All') |
||||
.eq(0) |
||||
.should('be.visible') |
||||
.click(); |
||||
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('AAA') |
||||
.should('be.visible') |
||||
.click(); |
||||
e2e.pages.Dashboard.Toolbar.navBar() |
||||
.should('be.visible') |
||||
.click(); |
||||
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts('A') |
||||
.should('be.visible') |
||||
.should('have.length', 1); |
||||
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts('AA') |
||||
.should('be.visible') |
||||
.should('have.length', 1); |
||||
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts('AAA') |
||||
.should('be.visible') |
||||
.should('have.length', 1); |
||||
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts('All').should('have.length', 0); |
||||
}; |
||||
|
||||
const assertDuplicateItem = (variables: VariablesData[]) => { |
||||
const itemToDuplicate = variables[1]; |
||||
e2e.pages.Dashboard.Toolbar.toolbarItems('Dashboard settings').click(); |
||||
e2e.pages.Dashboard.Settings.General.sectionItems('Variables').click(); |
||||
e2e.pages.Dashboard.Settings.Variables.List.tableRowDuplicateButtons(itemToDuplicate.name) |
||||
.should('exist') |
||||
.click(); |
||||
e2e.pages.Dashboard.Settings.Variables.List.table() |
||||
.should('be.visible') |
||||
.within(() => { |
||||
e2e() |
||||
.get('tbody > tr') |
||||
.should('have.length', variables.length + 1); |
||||
}); |
||||
const newItem = { ...itemToDuplicate, name: `copy_of_${itemToDuplicate.name}` }; |
||||
assertVariableTableRow(newItem, variables.length - 1, variables.length); |
||||
e2e.pages.Dashboard.Settings.Variables.List.tableRowNameFields(newItem.name).click(); |
||||
|
||||
newItem.label = `copy_of_${itemToDuplicate.label}`; |
||||
e2e.pages.Dashboard.Settings.Variables.Edit.General.generalLabelInput() |
||||
.clear() |
||||
.type(newItem.label); |
||||
|
||||
e2e.pages.Dashboard.Settings.General.saveDashBoard().click(); |
||||
e2e.pages.SaveDashboardModal.save().click(); |
||||
e2e.flows.assertSuccessNotification(); |
||||
|
||||
e2e.components.BackButton.backArrow() |
||||
.should('be.visible') |
||||
.click(); |
||||
|
||||
e2e.pages.Dashboard.SubMenu.submenuItemLabels(newItem.label).should('be.visible'); |
||||
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts(newItem.selectedOption) |
||||
.should('be.visible') |
||||
.eq(1) |
||||
.click(); |
||||
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownDropDown().should('be.visible'); |
||||
for (let optionIndex = 0; optionIndex < newItem.options.length; optionIndex++) { |
||||
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts(newItem.options[optionIndex]).should('be.visible'); |
||||
} |
||||
|
||||
return [...variables, newItem]; |
||||
}; |
||||
|
||||
const assertDeleteItem = (variables: VariablesData[]) => { |
||||
const itemToDelete = variables[1]; |
||||
e2e.pages.Dashboard.Toolbar.toolbarItems('Dashboard settings').click(); |
||||
e2e.pages.Dashboard.Settings.General.sectionItems('Variables').click(); |
||||
|
||||
e2e.pages.Dashboard.Settings.Variables.List.tableRowRemoveButtons(itemToDelete.name).click(); |
||||
e2e.pages.Dashboard.Settings.Variables.List.table() |
||||
.should('be.visible') |
||||
.within(() => { |
||||
e2e() |
||||
.get('tbody > tr') |
||||
.should('have.length', variables.length - 1); |
||||
}); |
||||
|
||||
e2e.pages.Dashboard.Settings.General.saveDashBoard().click(); |
||||
e2e.pages.SaveDashboardModal.save().click(); |
||||
e2e.flows.assertSuccessNotification(); |
||||
|
||||
e2e.components.BackButton.backArrow() |
||||
.should('be.visible') |
||||
.click(); |
||||
|
||||
e2e.pages.Dashboard.SubMenu.submenuItemLabels(itemToDelete.label).should('not.exist'); |
||||
|
||||
return variables.filter(item => item.name !== itemToDelete.name); |
||||
}; |
||||
|
||||
const assertUpdateItem = (data: VariablesData[]) => { |
||||
const variables = [...data]; |
||||
// updates an item to a constant variable instead
|
||||
const itemToUpdate = variables[1]; |
||||
let updatedItem = { |
||||
...itemToUpdate, |
||||
name: `update_of_${itemToUpdate.name}`, |
||||
label: `update_of_${itemToUpdate.label}`, |
||||
query: 'A constant', |
||||
options: ['A constant'], |
||||
selectedOption: 'undefined', |
||||
}; |
||||
|
||||
variables[1] = updatedItem; |
||||
|
||||
e2e.pages.Dashboard.Toolbar.toolbarItems('Dashboard settings').click(); |
||||
e2e.pages.Dashboard.Settings.General.sectionItems('Variables').click(); |
||||
e2e.pages.Dashboard.Settings.Variables.List.tableRowNameFields(itemToUpdate.name).click(); |
||||
|
||||
e2e.pages.Dashboard.Settings.Variables.Edit.General.generalNameInput().should('be.visible'); |
||||
e2e.pages.Dashboard.Settings.Variables.Edit.General.generalNameInput() |
||||
.should('have.value', itemToUpdate.name) |
||||
.clear() |
||||
.type(updatedItem.name); |
||||
e2e.pages.Dashboard.Settings.Variables.Edit.General.generalLabelInput() |
||||
.should('have.value', itemToUpdate.label) |
||||
.clear() |
||||
.type(updatedItem.label); |
||||
e2e.pages.Dashboard.Settings.Variables.Edit.General.generalTypeSelect().select('Constant'); |
||||
e2e.pages.Dashboard.Settings.Variables.Edit.General.generalHideSelect().within(select => { |
||||
e2e() |
||||
.get('option:selected') |
||||
.should('have.text', 'Variable'); |
||||
}); |
||||
e2e.pages.Dashboard.Settings.Variables.Edit.General.generalHideSelect().select(''); |
||||
e2e.pages.Dashboard.Settings.Variables.Edit.ConstantVariable.constantOptionsQueryInput().type(updatedItem.query); |
||||
|
||||
e2e.components.BackButton.backArrow() |
||||
.should('be.visible') |
||||
.click(); |
||||
|
||||
variables[1].selectedOption = 'A constant'; |
||||
assertVariableLabelAndComponent(variables[1]); |
||||
|
||||
e2e.pages.Dashboard.Toolbar.toolbarItems('Dashboard settings').click(); |
||||
e2e.pages.Dashboard.Settings.General.sectionItems('Variables').click(); |
||||
|
||||
assertVariableTableRow(variables[1], 1, variables.length); |
||||
|
||||
variables[1].selectedOption = 'A constant'; |
||||
|
||||
return variables; |
||||
}; |
||||
|
||||
const assertMoveDownItem = (data: VariablesData[]) => { |
||||
const variables = [...data]; |
||||
e2e.pages.Dashboard.Settings.Variables.List.tableRowArrowDownButtons(variables[0].name).click(); |
||||
const temp = { ...variables[0] }; |
||||
variables[0] = { ...variables[1] }; |
||||
variables[1] = temp; |
||||
e2e.pages.Dashboard.Settings.Variables.List.table().within(() => { |
||||
e2e() |
||||
.get('tbody > tr') |
||||
.eq(0) |
||||
.within(() => { |
||||
e2e() |
||||
.get('td') |
||||
.eq(0) |
||||
.contains(variables[0].name); |
||||
e2e() |
||||
.get('td') |
||||
.eq(1) |
||||
.contains(variables[0].query); |
||||
}); |
||||
e2e() |
||||
.get('tbody > tr') |
||||
.eq(1) |
||||
.within(() => { |
||||
e2e() |
||||
.get('td') |
||||
.eq(0) |
||||
.contains(variables[1].name); |
||||
e2e() |
||||
.get('td') |
||||
.eq(1) |
||||
.contains(variables[1].query); |
||||
}); |
||||
}); |
||||
|
||||
e2e.components.BackButton.backArrow() |
||||
.should('be.visible') |
||||
.click(); |
||||
|
||||
assertVariableLabelsAndComponents(variables); |
||||
|
||||
return variables; |
||||
}; |
||||
|
||||
const assertMoveUpItem = (data: VariablesData[]) => { |
||||
const variables = [...data]; |
||||
e2e.pages.Dashboard.Settings.Variables.List.tableRowArrowUpButtons(variables[1].name).click(); |
||||
const temp = { ...variables[0] }; |
||||
variables[0] = { ...variables[1] }; |
||||
variables[1] = temp; |
||||
e2e.pages.Dashboard.Settings.Variables.List.table().within(() => { |
||||
e2e() |
||||
.get('tbody > tr') |
||||
.eq(0) |
||||
.within(() => { |
||||
e2e() |
||||
.get('td') |
||||
.eq(0) |
||||
.contains(variables[0].name); |
||||
e2e() |
||||
.get('td') |
||||
.eq(1) |
||||
.contains(variables[0].query); |
||||
}); |
||||
e2e() |
||||
.get('tbody > tr') |
||||
.eq(1) |
||||
.within(() => { |
||||
e2e() |
||||
.get('td') |
||||
.eq(0) |
||||
.contains(variables[1].name); |
||||
e2e() |
||||
.get('td') |
||||
.eq(1) |
||||
.contains(variables[1].query); |
||||
}); |
||||
}); |
||||
|
||||
e2e.components.BackButton.backArrow() |
||||
.should('be.visible') |
||||
.click(); |
||||
|
||||
assertVariableLabelsAndComponents(variables); |
||||
|
||||
return variables; |
||||
}; |
||||
@ -0,0 +1,31 @@ |
||||
import React, { PropsWithChildren, useMemo } from 'react'; |
||||
import { SelectableValue } from '@grafana/data'; |
||||
import { selectors } from '@grafana/e2e-selectors'; |
||||
|
||||
import { VariableSelectField } from '../editor/VariableSelectField'; |
||||
import { VariableHide } from '../types'; |
||||
|
||||
interface Props { |
||||
onChange: (option: SelectableValue<VariableHide>) => void; |
||||
hide: VariableHide; |
||||
} |
||||
|
||||
const HIDE_OPTIONS = [ |
||||
{ label: '', value: VariableHide.dontHide }, |
||||
{ label: 'Label', value: VariableHide.hideLabel }, |
||||
{ label: 'Variable', value: VariableHide.hideVariable }, |
||||
]; |
||||
|
||||
export function VariableHideSelect({ onChange, hide }: PropsWithChildren<Props>) { |
||||
const value = useMemo(() => HIDE_OPTIONS.find(o => o.value === hide) ?? HIDE_OPTIONS[0], [hide]); |
||||
|
||||
return ( |
||||
<VariableSelectField |
||||
name="Hide" |
||||
value={value} |
||||
options={HIDE_OPTIONS} |
||||
onChange={onChange} |
||||
ariaLabel={selectors.pages.Dashboard.Settings.Variables.Edit.General.generalHideSelect} |
||||
/> |
||||
); |
||||
} |
||||
@ -0,0 +1,24 @@ |
||||
import React, { PropsWithChildren, ReactElement } from 'react'; |
||||
import { useStyles } from '@grafana/ui'; |
||||
import { GrafanaTheme } from '@grafana/data'; |
||||
import { css } from 'emotion'; |
||||
|
||||
interface VariableSectionHeaderProps { |
||||
name: string; |
||||
} |
||||
|
||||
export function VariableSectionHeader({ name }: PropsWithChildren<VariableSectionHeaderProps>): ReactElement { |
||||
const styles = useStyles(getStyles); |
||||
|
||||
return <h5 className={styles.sectionHeading}>{name}</h5>; |
||||
} |
||||
|
||||
function getStyles(theme: GrafanaTheme) { |
||||
return { |
||||
sectionHeading: css` |
||||
label: sectionHeading; |
||||
font-size: ${theme.typography.size.md}; |
||||
margin-bottom: ${theme.spacing.sm}; |
||||
`,
|
||||
}; |
||||
} |
||||
@ -0,0 +1,53 @@ |
||||
import React, { PropsWithChildren, ReactElement } from 'react'; |
||||
import { InlineFormLabel, Select, useStyles } from '@grafana/ui'; |
||||
import { GrafanaTheme, SelectableValue } from '@grafana/data'; |
||||
import { css } from 'emotion'; |
||||
|
||||
interface VariableSelectFieldProps<T> { |
||||
name: string; |
||||
value: SelectableValue<T>; |
||||
options: Array<SelectableValue<T>>; |
||||
onChange: (option: SelectableValue<T>) => void; |
||||
tooltip?: string; |
||||
ariaLabel?: string; |
||||
width?: number; |
||||
labelWidth?: number; |
||||
} |
||||
|
||||
export function VariableSelectField({ |
||||
name, |
||||
value, |
||||
options, |
||||
tooltip, |
||||
onChange, |
||||
ariaLabel, |
||||
width, |
||||
labelWidth, |
||||
}: PropsWithChildren<VariableSelectFieldProps<any>>): ReactElement { |
||||
const styles = useStyles(getStyles); |
||||
|
||||
return ( |
||||
<> |
||||
<InlineFormLabel width={labelWidth ?? 6} tooltip={tooltip}> |
||||
{name} |
||||
</InlineFormLabel> |
||||
<div aria-label={ariaLabel}> |
||||
<Select |
||||
onChange={onChange} |
||||
value={value} |
||||
width={width ?? 25} |
||||
options={options} |
||||
className={styles.selectContainer} |
||||
/> |
||||
</div> |
||||
</> |
||||
); |
||||
} |
||||
|
||||
function getStyles(theme: GrafanaTheme) { |
||||
return { |
||||
selectContainer: css` |
||||
margin-right: ${theme.spacing.xs}; |
||||
`,
|
||||
}; |
||||
} |
||||
@ -0,0 +1,39 @@ |
||||
import React, { ChangeEvent, PropsWithChildren, ReactElement } from 'react'; |
||||
import { InlineField, Switch, useStyles } from '@grafana/ui'; |
||||
import { GrafanaTheme } from '@grafana/data'; |
||||
import { css } from 'emotion'; |
||||
|
||||
interface VariableSwitchFieldProps { |
||||
value: boolean; |
||||
name: string; |
||||
onChange: (event: ChangeEvent<HTMLInputElement>) => void; |
||||
tooltip?: string; |
||||
ariaLabel?: string; |
||||
} |
||||
|
||||
export function VariableSwitchField({ |
||||
value, |
||||
name, |
||||
tooltip, |
||||
onChange, |
||||
ariaLabel, |
||||
}: PropsWithChildren<VariableSwitchFieldProps>): ReactElement { |
||||
const styles = useStyles(getStyles); |
||||
|
||||
return ( |
||||
<InlineField label={name} labelWidth={20} tooltip={tooltip}> |
||||
<div aria-label={ariaLabel} className={styles.switchContainer}> |
||||
<Switch label={name} value={value} onChange={onChange} /> |
||||
</div> |
||||
</InlineField> |
||||
); |
||||
} |
||||
|
||||
function getStyles(theme: GrafanaTheme) { |
||||
return { |
||||
switchContainer: css` |
||||
margin-left: ${theme.spacing.sm}; |
||||
margin-right: ${theme.spacing.sm}; |
||||
`,
|
||||
}; |
||||
} |
||||
@ -0,0 +1,79 @@ |
||||
import React, { FormEvent, PropsWithChildren, ReactElement, useCallback } from 'react'; |
||||
import { HorizontalGroup, InlineField, TextArea, useStyles } from '@grafana/ui'; |
||||
import { GrafanaTheme } from '@grafana/data'; |
||||
import { css } from 'emotion'; |
||||
|
||||
interface VariableTextAreaFieldProps<T> { |
||||
name: string; |
||||
value: string; |
||||
placeholder: string; |
||||
onChange: (event: FormEvent<HTMLTextAreaElement>) => void; |
||||
width: number; |
||||
tooltip?: string; |
||||
ariaLabel?: string; |
||||
required?: boolean; |
||||
labelWidth?: number; |
||||
onBlur?: (event: FormEvent<HTMLTextAreaElement>) => void; |
||||
} |
||||
|
||||
export function VariableTextAreaField({ |
||||
name, |
||||
value, |
||||
placeholder, |
||||
tooltip, |
||||
onChange, |
||||
onBlur, |
||||
ariaLabel, |
||||
required, |
||||
width, |
||||
labelWidth, |
||||
}: PropsWithChildren<VariableTextAreaFieldProps<any>>): ReactElement { |
||||
const styles = useStyles(getStyles); |
||||
const getLineCount = useCallback((value: any) => { |
||||
if (value && typeof value === 'string') { |
||||
return value.split('\n').length; |
||||
} |
||||
|
||||
return 1; |
||||
}, []); |
||||
|
||||
return ( |
||||
<HorizontalGroup spacing="none"> |
||||
<InlineField |
||||
label={name} |
||||
labelWidth={labelWidth ?? 12} |
||||
grow={false} |
||||
tooltip={tooltip} |
||||
className={styles.inlineFieldOverride} |
||||
> |
||||
<span hidden /> |
||||
</InlineField> |
||||
<TextArea |
||||
rows={getLineCount(value)} |
||||
value={value} |
||||
onChange={onChange} |
||||
onBlur={onBlur} |
||||
placeholder={placeholder} |
||||
required={required} |
||||
aria-label={ariaLabel} |
||||
cols={width} |
||||
className={styles.textarea} |
||||
/> |
||||
</HorizontalGroup> |
||||
); |
||||
} |
||||
|
||||
function getStyles(theme: GrafanaTheme) { |
||||
return { |
||||
inlineFieldOverride: css` |
||||
margin: 0; |
||||
`,
|
||||
textarea: css` |
||||
white-space: pre-wrap; |
||||
min-height: 32px; |
||||
height: auto; |
||||
overflow: auto; |
||||
padding: 6px 8px; |
||||
`,
|
||||
}; |
||||
} |
||||
@ -0,0 +1,47 @@ |
||||
import React, { FormEvent, PropsWithChildren, ReactElement } from 'react'; |
||||
import { InlineField, Input, PopoverContent } from '@grafana/ui'; |
||||
|
||||
interface VariableTextFieldProps { |
||||
value: string; |
||||
name: string; |
||||
placeholder: string; |
||||
onChange: (event: FormEvent<HTMLInputElement>) => void; |
||||
ariaLabel?: string; |
||||
tooltip?: PopoverContent; |
||||
required?: boolean; |
||||
width?: number; |
||||
labelWidth?: number; |
||||
grow?: boolean; |
||||
onBlur?: (event: FormEvent<HTMLInputElement>) => void; |
||||
} |
||||
|
||||
export function VariableTextField({ |
||||
value, |
||||
name, |
||||
placeholder, |
||||
onChange, |
||||
ariaLabel, |
||||
width, |
||||
labelWidth, |
||||
required, |
||||
onBlur, |
||||
tooltip, |
||||
grow, |
||||
}: PropsWithChildren<VariableTextFieldProps>): ReactElement { |
||||
return ( |
||||
<InlineField label={name} labelWidth={labelWidth ?? 12} tooltip={tooltip} grow={grow}> |
||||
<Input |
||||
type="text" |
||||
id={name} |
||||
name={name} |
||||
placeholder={placeholder} |
||||
value={value} |
||||
onChange={onChange} |
||||
onBlur={onBlur} |
||||
width={grow ? undefined : width ?? 25} |
||||
aria-label={ariaLabel} |
||||
required={required} |
||||
/> |
||||
</InlineField> |
||||
); |
||||
} |
||||
@ -0,0 +1,28 @@ |
||||
import React, { PropsWithChildren, useMemo } from 'react'; |
||||
import { SelectableValue, VariableType } from '@grafana/data'; |
||||
import { selectors } from '@grafana/e2e-selectors'; |
||||
|
||||
import { VariableSelectField } from '../editor/VariableSelectField'; |
||||
import { getVariableTypes } from '../utils'; |
||||
import { variableAdapters } from '../adapters'; |
||||
|
||||
interface Props { |
||||
onChange: (option: SelectableValue<VariableType>) => void; |
||||
type: VariableType; |
||||
} |
||||
|
||||
export function VariableTypeSelect({ onChange, type }: PropsWithChildren<Props>) { |
||||
const options = useMemo(() => getVariableTypes(), [getVariableTypes]); |
||||
const value = useMemo(() => options.find(o => o.value === type) ?? options[0], [options, type]); |
||||
|
||||
return ( |
||||
<VariableSelectField |
||||
name="Type" |
||||
value={value} |
||||
options={options} |
||||
onChange={onChange} |
||||
tooltip={variableAdapters.get(type).description} |
||||
ariaLabel={selectors.pages.Dashboard.Settings.Variables.Edit.General.generalTypeSelect} |
||||
/> |
||||
); |
||||
} |
||||
@ -1,54 +1,67 @@ |
||||
import React, { useCallback, useEffect, useState } from 'react'; |
||||
import { VariableModel, VariableOption, VariableWithOptions } from '../types'; |
||||
import React, { MouseEvent, useCallback, useEffect, useState } from 'react'; |
||||
import { VariableOption, VariableWithOptions } from '../types'; |
||||
import { selectors } from '@grafana/e2e-selectors'; |
||||
import { Button, InlineFieldRow, InlineLabel, useStyles, VerticalGroup } from '@grafana/ui'; |
||||
import { GrafanaTheme } from '@grafana/data'; |
||||
import { css } from 'emotion'; |
||||
|
||||
export interface VariableValuesPreviewProps { |
||||
variable: VariableModel; |
||||
variable: VariableWithOptions; |
||||
} |
||||
|
||||
export const VariableValuesPreview: React.FunctionComponent<VariableValuesPreviewProps> = ({ variable }) => { |
||||
export const VariableValuesPreview: React.FunctionComponent<VariableValuesPreviewProps> = ({ |
||||
variable: { options }, |
||||
}) => { |
||||
const [previewLimit, setPreviewLimit] = useState(20); |
||||
const [previewOptions, setPreviewOptions] = useState<VariableOption[]>([]); |
||||
const showMoreOptions = useCallback(() => setPreviewLimit(previewLimit + 20), [previewLimit, setPreviewLimit]); |
||||
useEffect(() => { |
||||
if (!variable || !variable.hasOwnProperty('options')) { |
||||
return; |
||||
} |
||||
const variableWithOptions = variable as VariableWithOptions; |
||||
setPreviewOptions(variableWithOptions.options.slice(0, previewLimit)); |
||||
}, [previewLimit, variable]); |
||||
const showMoreOptions = useCallback( |
||||
(event: MouseEvent) => { |
||||
event.preventDefault(); |
||||
setPreviewLimit(previewLimit + 20); |
||||
}, |
||||
[previewLimit, setPreviewLimit] |
||||
); |
||||
const styles = useStyles(getStyles); |
||||
useEffect(() => setPreviewOptions(options.slice(0, previewLimit)), [previewLimit, options]); |
||||
|
||||
if (!previewOptions.length) { |
||||
return null; |
||||
} |
||||
|
||||
return ( |
||||
<div className="gf-form-group"> |
||||
<VerticalGroup spacing="none"> |
||||
<h5>Preview of values</h5> |
||||
<div className="gf-form-inline"> |
||||
<InlineFieldRow> |
||||
{previewOptions.map((o, index) => ( |
||||
<div className="gf-form" key={`${o.value}-${index}`}> |
||||
<span |
||||
className="gf-form-label" |
||||
aria-label={selectors.pages.Dashboard.Settings.Variables.Edit.General.previewOfValuesOption} |
||||
> |
||||
<InlineFieldRow key={`${o.value}-${index}`} className={styles.optionContainer}> |
||||
<InlineLabel aria-label={selectors.pages.Dashboard.Settings.Variables.Edit.General.previewOfValuesOption}> |
||||
{o.text} |
||||
</span> |
||||
</div> |
||||
</InlineLabel> |
||||
</InlineFieldRow> |
||||
))} |
||||
{previewOptions.length > previewLimit && ( |
||||
<div className="gf-form" ng-if="current.options.length > optionsLimit"> |
||||
<a |
||||
className="gf-form-label btn-secondary" |
||||
onClick={showMoreOptions} |
||||
aria-label="Variable editor Preview of Values Show More link" |
||||
> |
||||
Show more |
||||
</a> |
||||
</div> |
||||
)} |
||||
</div> |
||||
</div> |
||||
</InlineFieldRow> |
||||
{options.length > previewLimit && ( |
||||
<InlineFieldRow className={styles.optionContainer}> |
||||
<Button |
||||
onClick={showMoreOptions} |
||||
variant="secondary" |
||||
size="sm" |
||||
aria-label="Variable editor Preview of Values Show More link" |
||||
> |
||||
Show more |
||||
</Button> |
||||
</InlineFieldRow> |
||||
)} |
||||
</VerticalGroup> |
||||
); |
||||
}; |
||||
VariableValuesPreview.displayName = 'VariableValuesPreview'; |
||||
|
||||
function getStyles(theme: GrafanaTheme) { |
||||
return { |
||||
optionContainer: css` |
||||
margin-left: ${theme.spacing.xs}; |
||||
margin-bottom: ${theme.spacing.xs}; |
||||
`,
|
||||
}; |
||||
} |
||||
|
||||
@ -0,0 +1,28 @@ |
||||
import React, { PropsWithChildren, useMemo } from 'react'; |
||||
import { DataSourceSelectItem, SelectableValue } from '@grafana/data'; |
||||
import { selectors } from '@grafana/e2e-selectors'; |
||||
import { VariableSelectField } from '../editor/VariableSelectField'; |
||||
|
||||
interface Props { |
||||
onChange: (option: SelectableValue<string>) => void; |
||||
datasource: string | null; |
||||
dataSources?: DataSourceSelectItem[]; |
||||
} |
||||
|
||||
export function QueryVariableDatasourceSelect({ onChange, datasource, dataSources }: PropsWithChildren<Props>) { |
||||
const options = useMemo(() => { |
||||
return dataSources ? dataSources.map(ds => ({ label: ds.name, value: ds.value ?? '' })) : []; |
||||
}, [dataSources]); |
||||
const value = useMemo(() => options.find(o => o.value === datasource) ?? options[0], [options, datasource]); |
||||
|
||||
return ( |
||||
<VariableSelectField |
||||
name="Data source" |
||||
value={value} |
||||
options={options} |
||||
onChange={onChange} |
||||
labelWidth={10} |
||||
ariaLabel={selectors.pages.Dashboard.Settings.Variables.Edit.QueryVariable.queryOptionsDataSourceSelect} |
||||
/> |
||||
); |
||||
} |
||||
@ -0,0 +1,32 @@ |
||||
import React, { PropsWithChildren, useMemo } from 'react'; |
||||
import { SelectableValue } from '@grafana/data'; |
||||
import { selectors } from '@grafana/e2e-selectors'; |
||||
import { VariableSelectField } from '../editor/VariableSelectField'; |
||||
import { VariableRefresh } from '../types'; |
||||
|
||||
interface Props { |
||||
onChange: (option: SelectableValue<VariableRefresh>) => void; |
||||
refresh: VariableRefresh; |
||||
} |
||||
|
||||
const REFRESH_OPTIONS = [ |
||||
{ label: 'Never', value: VariableRefresh.never }, |
||||
{ label: 'On Dashboard Load', value: VariableRefresh.onDashboardLoad }, |
||||
{ label: 'On Time Range Change', value: VariableRefresh.onTimeRangeChanged }, |
||||
]; |
||||
|
||||
export function QueryVariableRefreshSelect({ onChange, refresh }: PropsWithChildren<Props>) { |
||||
const value = useMemo(() => REFRESH_OPTIONS.find(o => o.value === refresh) ?? REFRESH_OPTIONS[0], [refresh]); |
||||
|
||||
return ( |
||||
<VariableSelectField |
||||
name="Refresh" |
||||
value={value} |
||||
options={REFRESH_OPTIONS} |
||||
onChange={onChange} |
||||
labelWidth={10} |
||||
ariaLabel={selectors.pages.Dashboard.Settings.Variables.Edit.QueryVariable.queryOptionsRefreshSelect} |
||||
tooltip="When to update the values of this variable." |
||||
/> |
||||
); |
||||
} |
||||
@ -0,0 +1,36 @@ |
||||
import React, { PropsWithChildren, useMemo } from 'react'; |
||||
import { SelectableValue } from '@grafana/data'; |
||||
import { selectors } from '@grafana/e2e-selectors'; |
||||
import { VariableSelectField } from '../editor/VariableSelectField'; |
||||
import { VariableSort } from '../types'; |
||||
|
||||
interface Props { |
||||
onChange: (option: SelectableValue<VariableSort>) => void; |
||||
sort: VariableSort; |
||||
} |
||||
|
||||
const SORT_OPTIONS = [ |
||||
{ label: 'Disabled', value: VariableSort.disabled }, |
||||
{ label: 'Alphabetical (asc)', value: VariableSort.alphabeticalAsc }, |
||||
{ label: 'Alphabetical (desc)', value: VariableSort.alphabeticalDesc }, |
||||
{ label: 'Numerical (asc)', value: VariableSort.numericalAsc }, |
||||
{ label: 'Numerical (desc)', value: VariableSort.numericalDesc }, |
||||
{ label: 'Alphabetical (case-insensitive, asc)', value: VariableSort.alphabeticalCaseInsensitiveAsc }, |
||||
{ label: 'Alphabetical (case-insensitive, desc)', value: VariableSort.alphabeticalCaseInsensitiveDesc }, |
||||
]; |
||||
|
||||
export function QueryVariableSortSelect({ onChange, sort }: PropsWithChildren<Props>) { |
||||
const value = useMemo(() => SORT_OPTIONS.find(o => o.value === sort) ?? SORT_OPTIONS[0], [sort]); |
||||
|
||||
return ( |
||||
<VariableSelectField |
||||
name="Sort" |
||||
value={value} |
||||
options={SORT_OPTIONS} |
||||
onChange={onChange} |
||||
labelWidth={10} |
||||
ariaLabel={selectors.pages.Dashboard.Settings.Variables.Edit.QueryVariable.queryOptionsSortSelect} |
||||
tooltip="How to sort the values of this variable." |
||||
/> |
||||
); |
||||
} |
||||
Loading…
Reference in new issue