Skip to content

Commit

Permalink
When adding a new source to a metric, don't show the spinner until th…
Browse files Browse the repository at this point in the history
…e source has been configured sufficiently to start collecting data.

Fixes #9994.
  • Loading branch information
fniessink committed Feb 26, 2025
1 parent 8537157 commit dbc45ab
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 0 deletions.
25 changes: 25 additions & 0 deletions components/frontend/src/utils.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { PERMISSIONS } from "./context/Permissions"
import { defaultDesiredResponseTimes } from "./defaults"
import { STATUSES_NOT_REQUIRING_ACTION } from "./metric/status"
import {
dataModelPropType,
datePropType,
metricPropType,
metricsPropType,
Expand Down Expand Up @@ -110,6 +111,30 @@ isMeasurementOutdated.propTypes = {
metric: metricPropType,
}

export function canBeMeasured(dataModel, metric) {
// Return whether the metric can be measured, meaning that there is at least one source and all sources have
// all mandatory parameters configured
const sources = Object.values(metric.sources ?? {})
if (sources.length === 0) {
return false
}
return sources.every((source) => {
const parameters = dataModel.sources[source.type].parameters ?? {}
return Object.entries(parameters).every(([parameterKey, parameter]) => {
if (parameter.mandatory && parameter.metrics.includes(metric.type) && !parameter.default_value) {
// If the parameter is mandatory, has no default value, and is applicable to the metric,
// check if it is configured:
return Boolean(source?.parameters?.[parameterKey])
}
return true
})
})
}
canBeMeasured.propTypes = {
dataModel: dataModelPropType,
metric: metricPropType,
}

export function isMeasurementRequested(metric) {
if (metric.measurement_requested) {
if (metric.latest_measurement) {
Expand Down
30 changes: 30 additions & 0 deletions components/frontend/src/utils.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { EDIT_ENTITY_PERMISSION, EDIT_REPORT_PERMISSION } from "./context/Permis
import { defaultDesiredResponseTimes } from "./defaults"
import {
addCounts,
canBeMeasured,
capitalize,
DOCUMENTATION_URL,
getMetricResponseDeadline,
Expand Down Expand Up @@ -517,6 +518,35 @@ it("returns whether a metric's measurement is outdated", () => {
expect(isMeasurementOutdated({ latest_measurement: { outdated: true } })).toBe(true)
})

it("returns whether a metric can be measured", () => {
const dataModel = {
sources: { source_type: { parameters: { url: { mandatory: true, metrics: ["metric_type"] } } } },
}
const metric = { type: "metric_type", sources: {} }
// A metric without sources is not measurable:
expect(canBeMeasured(dataModel, metric)).toBe(false)
// A metric with a source without parameters is not measurable:
metric.sources = { source_uuid: { type: "source_type" } }
expect(canBeMeasured(dataModel, metric)).toBe(false)
// A metric with a source with empty parameters is measurable:
metric.sources["source_uuid"].parameters = {}
expect(canBeMeasured(dataModel, metric)).toBe(false)
// A metric with a source with mandatory parameters configured is measurable:
metric.sources["source_uuid"].parameters["url"] = "https://example.org"
expect(canBeMeasured(dataModel, metric)).toBe(true)
// Non-mandatory parameters that are not configured don't make the metric unmeasurable:
dataModel.sources["source_type"].parameters["username"] = { mandatory: false, metrics: ["metric_type"] }
expect(canBeMeasured(dataModel, metric)).toBe(true)
// Mandatory parameters for other metrics that are not configured don't make the metric unmeasurable:
metric.sources["source_uuid"].parameters["password"] = { mandatory: true, metrics: ["other_metric_type"] }
expect(canBeMeasured(dataModel, metric)).toBe(true)
// A metric with a source with mandatory parameters that has a default value for a mandatory parameter is
// measurable:
dataModel.sources["source_type"].parameters["url"]["default_value"] = "https://example.org"
metric.sources["source_uuid"].parameters = {}
expect(canBeMeasured(dataModel, metric)).toBe(true)
})

it("returns the reference documentation URL", () => {
const url = `${DOCUMENTATION_URL}/reference.html`
// Simple name
Expand Down
1 change: 1 addition & 0 deletions docs/src/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ If your currently installed *Quality-time* version is not the latest version, pl

### Fixed

- When adding a new source to a metric, don't show the spinner until the source has been configured sufficiently to start collecting data. Fixes [#9994](https://github.com/ICTU/quality-time/issues/9994).
- Increase contrast for disabled items in the menu bar. Fixes [#10840](https://github.com/ICTU/quality-time/issues/10840).
- Links to documentation on Read the Docs for subjects, metrics, or sources with hyphens in their name wouldn't scroll to the right location. Fixes [#10843](https://github.com/ICTU/quality-time/issues/10843).
- Metric details were not shown in exports to PDF. Fixes [#10845](https://github.com/ICTU/quality-time/issues/10845).
Expand Down

0 comments on commit dbc45ab

Please sign in to comment.