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

Add support for custom activity type (including variables) #23

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
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
25 changes: 22 additions & 3 deletions src/components/QueryEditor.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { PureComponent } from 'react';
import React, { ChangeEvent, PureComponent } from 'react';
import { SelectableValue, QueryEditorProps } from '@grafana/data';
import { InlineFormLabel, Select } from '@grafana/ui';
import { InlineFormLabel, Input, Select } from '@grafana/ui';
import {
StravaQuery,
StravaQueryType,
Expand Down Expand Up @@ -34,6 +34,7 @@ const stravaActivityTypeOptions: Array<SelectableValue<StravaActivityType>> = [
{ value: 'Run', label: 'Run' },
{ value: 'Ride', label: 'Ride' },
{ value: 'Other', label: 'Other' },
{ value: 'Custom', label: 'Custom' },
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't better to convert activity selector to support multi-value selection and add variables to the list?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How would you know which variable to put in the list?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Usually, it's just a list of created variables from templateSrv, but it might be bad from UX perspective.

];

const FORMAT_OPTIONS: Array<SelectableValue<StravaQueryFormat>> = [
Expand All @@ -56,6 +57,7 @@ export const DefaultTarget: State = {
athlete: {},
queryType: StravaQueryType.Activities,
activityType: null,
customActivityType: '',
activityStat: StravaActivityStat.Distance,
format: StravaQueryFormat.TimeSeries,
interval: StravaQueryInterval.Auto,
Expand All @@ -74,6 +76,7 @@ export class QueryEditor extends PureComponent<Props, State> {
format: StravaQueryFormat.TimeSeries,
queryType: StravaQueryType.Activities,
activityType: null,
customActivityType: '',
activityStat: StravaActivityStat.Distance,
};

Expand Down Expand Up @@ -123,6 +126,13 @@ export class QueryEditor extends PureComponent<Props, State> {
}
};

onCustomActivityTypeChanged = (event: ChangeEvent<HTMLInputElement>) => {
const { query } = this.props;
if (event.target.value) {
this.onChange({ ...query, customActivityType: event.target.value })
}
}

onFormatChange = (option: SelectableValue<StravaQueryFormat>) => {
const { query } = this.props;
if (option.value) {
Expand All @@ -145,6 +155,7 @@ export class QueryEditor extends PureComponent<Props, State> {

render() {
const { athlete } = this.state;
const { query } = this.props;

return (
<>
Expand All @@ -159,7 +170,7 @@ export class QueryEditor extends PureComponent<Props, State> {
onChange={this.onQueryTypeChanged}
className="gf-form-select"
/>
<InlineFormLabel width={7}>Activity</InlineFormLabel>
<InlineFormLabel width={7} tooltip="The Custom option allows you to type a comma-separated list of activity types or a variable name.">Activity</InlineFormLabel>
<Select
isSearchable={false}
width={10}
Expand All @@ -168,6 +179,14 @@ export class QueryEditor extends PureComponent<Props, State> {
onChange={this.onActivityTypeChanged}
className="gf-form-select"
/>
{
this.getSelectedActivityType()?.value == 'Custom' &&
(<Input
width={15}
value={query.customActivityType || ''}
onChange={this.onCustomActivityTypeChanged}
/>)
}
<InlineFormLabel width={5}>Stat</InlineFormLabel>
<Select
isSearchable={false}
Expand Down
22 changes: 15 additions & 7 deletions src/datasource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
TimeSeriesPoints,
TimeSeriesValue,
} from '@grafana/data';
import { getTemplateSrv } from '@grafana/runtime';
import StravaApi from './stravaApi';
import polyline from './polyline';
import {
Expand Down Expand Up @@ -55,7 +56,7 @@ export default class StravaDatasource extends DataSourceApi<StravaQuery, StravaJ
});

for (const target of options.targets) {
const filteredActivities = this.filterActivities(activities, target.activityType);
const filteredActivities = this.filterActivities(activities, target.activityType, target.customActivityType);
switch (target.format) {
case StravaQueryFormat.Table:
const tableData = this.transformActivitiesToTable(filteredActivities, target);
Expand Down Expand Up @@ -105,18 +106,25 @@ export default class StravaDatasource extends DataSourceApi<StravaQuery, StravaJ
return authCode;
}

filterActivities(activities: any[], activityType: StravaActivityType): any[] {
filterActivities(allActivities: any[], activityType: StravaActivityType, customActivityType: string): any[] {
let activities = [activityType]
if (!activityType) {
// No filter, return all
return activities;
return allActivities;
} else if (activityType === 'Custom' && customActivityType) {
// Handle template variables if any
if (customActivityType.indexOf('$') != -1) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't need to check value for variables, getTemplateSrv().replace() already do this, so this can be omitted.

customActivityType = getTemplateSrv().replace(customActivityType, undefined, 'csv')
}
activities = customActivityType.split(',').map(activity => activity.trim())
}

return activities.filter(activity => {
return allActivities.filter(activity => {
if (activityType === 'Other') {
return activity.type !== 'Run' && activity.type !== 'Ride';
} else {
}
return activity.type === activityType;
}

return activities.indexOf(activity.type) != -1
});
}

Expand Down
1 change: 1 addition & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export interface StravaQuery extends DataQuery {
queryType: StravaQueryType;
activityStat: StravaActivityStat;
activityType: StravaActivityType;
customActivityType: string;
format: StravaQueryFormat;
interval: StravaQueryInterval;
}
Expand Down