Skip to content

Commit

Permalink
Improve chart query for time by matching stories
Browse files Browse the repository at this point in the history
  • Loading branch information
matthiasn committed Jul 18, 2022
1 parent 9d65a65 commit d0c4382
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 104 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]
### Changed:
- Improved query for substring matched stories

## [0.8.111] - 2022-07-17
### Changed:
- Time format hh:mm:ss in time charts for aggregate of selected day
- Time format hh:mm:ss in workout charts for aggregate of selected day

Expand Down
8 changes: 3 additions & 5 deletions lib/database/database.dart
Original file line number Diff line number Diff line change
Expand Up @@ -307,16 +307,14 @@ class JournalDb extends _$JournalDb {
}

Stream<List<JournalEntity>> watchJournalByTagIds({
required List<String> tagIds,
required String match,
required DateTime rangeStart,
required DateTime rangeEnd,
int limit = 10000,
}) {
return filteredByTaggedWithIds(
tagIds,
return filteredByTagMatch(
'%$match%',
rangeStart,
rangeEnd,
limit,
).watch().where(makeDuplicateFilter()).map(entityStreamMapper);
}

Expand Down
14 changes: 14 additions & 0 deletions lib/database/database.drift
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,20 @@ SELECT * FROM journal
ORDER BY date_from DESC
LIMIT :limit;

filteredByTagMatch:
SELECT * FROM journal
WHERE deleted = false
AND id IN
(SELECT journal_id FROM tagged WHERE tag_entity_id IN
(SELECT id FROM tag_entities WHERE tag LIKE :match
AND private IN (0,
(SELECT status FROM config_flags WHERE name = 'private'))
AND deleted = false))
AND private IN (0, (SELECT status FROM config_flags WHERE name = 'private'))
AND date_from >= :rangeStart
AND date_to <= :rangeEnd
ORDER BY date_from DESC;

filteredTasks:
SELECT * FROM journal
WHERE type IN :types
Expand Down
189 changes: 91 additions & 98 deletions lib/widgets/charts/stories/wildcard_story_chart.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:lotti/blocs/charts/story_chart_info_cubit.dart';
import 'package:lotti/classes/entity_definitions.dart';
import 'package:lotti/classes/journal_entities.dart';
import 'package:lotti/classes/tag_type_definitions.dart';
import 'package:lotti/database/database.dart';
import 'package:lotti/get_it.dart';
import 'package:lotti/services/tags_service.dart';
Expand Down Expand Up @@ -46,106 +45,100 @@ class _WildcardStoryChartState extends State<WildcardStoryChart> {
final subString = widget.chartConfig.storySubstring;
final title = subString;

return StreamBuilder<List<TagEntity>>(
stream: _db.watchMatchingTags(subString),
builder: (context, tagsSnapshot) {
final tags = tagsSnapshot.data ?? [];
return BlocProvider<StoryChartInfoCubit>(
create: (BuildContext context) => StoryChartInfoCubit(),
child: StreamBuilder<List<JournalEntity?>>(
stream: _db.watchJournalByTagIds(
rangeStart: widget.rangeStart,
rangeEnd: widget.rangeEnd,
tagIds: tags.map((tag) => tag.id).toList(),
),
builder: (
BuildContext context,
AsyncSnapshot<List<JournalEntity?>> snapshot,
) {
final items = snapshot.data ?? [];

final data = aggregateStoryDailyTimeSum(
items,
rangeStart: widget.rangeStart,
rangeEnd: widget.rangeEnd,
);

final seriesList = [
charts.Series<MeasuredObservation, DateTime>(
id: widget.chartConfig.storySubstring,
domainFn: (MeasuredObservation val, _) => val.dateTime,
measureFn: (MeasuredObservation val, _) => val.value,
data: data,
)
];

void _infoSelectionModelUpdated(
charts.SelectionModel<DateTime> model,
) {
if (model.hasDatumSelection) {
final newSelection =
model.selectedDatum.first.datum as MeasuredObservation;
context.read<StoryChartInfoCubit>().setSelected(newSelection);
_chartState.selectionModels[charts.SelectionModelType.info] =
charts.UserManagedSelectionModel(model: model);
} else {
context.read<StoryChartInfoCubit>().clearSelected();
_chartState.selectionModels[charts.SelectionModelType.info] =
charts.UserManagedSelectionModel();
}
}

return Padding(
padding: const EdgeInsets.only(bottom: 8),
child: ClipRRect(
borderRadius: BorderRadius.circular(16),
child: Container(
key: Key('${widget.chartConfig.hashCode}'),
color: Colors.white,
height: 120,
padding: const EdgeInsets.symmetric(horizontal: 4),
child: Stack(
children: [
charts.TimeSeriesChart(
seriesList,
animate: false,
defaultRenderer: defaultRenderer,
selectionModels: [
charts.SelectionModelConfig(
updatedListener: _infoSelectionModelUpdated,
)
],
behaviors: [
chartRangeAnnotation(
widget.rangeStart,
widget.rangeEnd,
)
],
domainAxis: timeSeriesAxis,
primaryMeasureAxis: const charts.NumericAxisSpec(
tickFormatterSpec:
charts.BasicNumericTickFormatterSpec(
minutesToHhMm,
),
tickProviderSpec:
charts.BasicNumericTickProviderSpec(
zeroBound: true,
dataIsInWholeNumbers: false,
desiredMinTickCount: 4,
desiredMaxTickCount: 5,
),
),
),
InfoWidget(title),
return BlocProvider<StoryChartInfoCubit>(
create: (BuildContext context) => StoryChartInfoCubit(),
child: StreamBuilder<List<JournalEntity?>>(
stream: _db.watchJournalByTagIds(
match: subString,
rangeStart: widget.rangeStart,
rangeEnd: widget.rangeEnd,
// tagIds: tagIds,
),
builder: (
BuildContext context,
AsyncSnapshot<List<JournalEntity?>> snapshot,
) {
final items = snapshot.data ?? [];
//debugPrint('$items');

final data = aggregateStoryDailyTimeSum(
items,
rangeStart: widget.rangeStart,
rangeEnd: widget.rangeEnd,
);

final seriesList = [
charts.Series<MeasuredObservation, DateTime>(
id: widget.chartConfig.storySubstring,
domainFn: (MeasuredObservation val, _) => val.dateTime,
measureFn: (MeasuredObservation val, _) => val.value,
data: data,
)
];

void _infoSelectionModelUpdated(
charts.SelectionModel<DateTime> model,
) {
if (model.hasDatumSelection) {
final newSelection =
model.selectedDatum.first.datum as MeasuredObservation;
context.read<StoryChartInfoCubit>().setSelected(newSelection);
_chartState.selectionModels[charts.SelectionModelType.info] =
charts.UserManagedSelectionModel(model: model);
} else {
context.read<StoryChartInfoCubit>().clearSelected();
_chartState.selectionModels[charts.SelectionModelType.info] =
charts.UserManagedSelectionModel();
}
}

return Padding(
padding: const EdgeInsets.only(bottom: 8),
child: ClipRRect(
borderRadius: BorderRadius.circular(16),
child: Container(
key: Key('${widget.chartConfig.hashCode}'),
color: Colors.white,
height: 120,
padding: const EdgeInsets.symmetric(horizontal: 4),
child: Stack(
children: [
charts.TimeSeriesChart(
seriesList,
animate: false,
defaultRenderer: defaultRenderer,
selectionModels: [
charts.SelectionModelConfig(
updatedListener: _infoSelectionModelUpdated,
)
],
behaviors: [
chartRangeAnnotation(
widget.rangeStart,
widget.rangeEnd,
)
],
domainAxis: timeSeriesAxis,
primaryMeasureAxis: const charts.NumericAxisSpec(
tickFormatterSpec: charts.BasicNumericTickFormatterSpec(
minutesToHhMm,
),
tickProviderSpec: charts.BasicNumericTickProviderSpec(
zeroBound: true,
dataIsInWholeNumbers: false,
desiredMinTickCount: 4,
desiredMaxTickCount: 5,
),
),
),
),
InfoWidget(title),
],
),
);
},
),
);
},
),
),
);
},
),
);
}
}
Expand Down
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: lotti
description: A Smart Journal.
publish_to: 'none'
version: 0.8.111+1163
version: 0.8.112+1164

msix_config:
display_name: Lotti
Expand Down

0 comments on commit d0c4382

Please sign in to comment.