From d0c4382846e638557486988e47e6e42dd5b54887 Mon Sep 17 00:00:00 2001 From: Matthias Nehlsen Date: Mon, 18 Jul 2022 02:40:22 +0200 Subject: [PATCH] Improve chart query for time by matching stories --- CHANGELOG.md | 4 + lib/database/database.dart | 8 +- lib/database/database.drift | 14 ++ .../charts/stories/wildcard_story_chart.dart | 189 +++++++++--------- pubspec.yaml | 2 +- 5 files changed, 113 insertions(+), 104 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index abe20ffec..efdc98db3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/lib/database/database.dart b/lib/database/database.dart index 8cbabcb60..295f37aa2 100644 --- a/lib/database/database.dart +++ b/lib/database/database.dart @@ -307,16 +307,14 @@ class JournalDb extends _$JournalDb { } Stream> watchJournalByTagIds({ - required List 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); } diff --git a/lib/database/database.drift b/lib/database/database.drift index 9744b2a6a..594bebfb3 100644 --- a/lib/database/database.drift +++ b/lib/database/database.drift @@ -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 diff --git a/lib/widgets/charts/stories/wildcard_story_chart.dart b/lib/widgets/charts/stories/wildcard_story_chart.dart index 938b551d8..c7032e7f1 100644 --- a/lib/widgets/charts/stories/wildcard_story_chart.dart +++ b/lib/widgets/charts/stories/wildcard_story_chart.dart @@ -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'; @@ -46,106 +45,100 @@ class _WildcardStoryChartState extends State { final subString = widget.chartConfig.storySubstring; final title = subString; - return StreamBuilder>( - stream: _db.watchMatchingTags(subString), - builder: (context, tagsSnapshot) { - final tags = tagsSnapshot.data ?? []; - return BlocProvider( - create: (BuildContext context) => StoryChartInfoCubit(), - child: StreamBuilder>( - stream: _db.watchJournalByTagIds( - rangeStart: widget.rangeStart, - rangeEnd: widget.rangeEnd, - tagIds: tags.map((tag) => tag.id).toList(), - ), - builder: ( - BuildContext context, - AsyncSnapshot> snapshot, - ) { - final items = snapshot.data ?? []; - - final data = aggregateStoryDailyTimeSum( - items, - rangeStart: widget.rangeStart, - rangeEnd: widget.rangeEnd, - ); - - final seriesList = [ - charts.Series( - id: widget.chartConfig.storySubstring, - domainFn: (MeasuredObservation val, _) => val.dateTime, - measureFn: (MeasuredObservation val, _) => val.value, - data: data, - ) - ]; - - void _infoSelectionModelUpdated( - charts.SelectionModel model, - ) { - if (model.hasDatumSelection) { - final newSelection = - model.selectedDatum.first.datum as MeasuredObservation; - context.read().setSelected(newSelection); - _chartState.selectionModels[charts.SelectionModelType.info] = - charts.UserManagedSelectionModel(model: model); - } else { - context.read().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( + create: (BuildContext context) => StoryChartInfoCubit(), + child: StreamBuilder>( + stream: _db.watchJournalByTagIds( + match: subString, + rangeStart: widget.rangeStart, + rangeEnd: widget.rangeEnd, +// tagIds: tagIds, + ), + builder: ( + BuildContext context, + AsyncSnapshot> snapshot, + ) { + final items = snapshot.data ?? []; + //debugPrint('$items'); + + final data = aggregateStoryDailyTimeSum( + items, + rangeStart: widget.rangeStart, + rangeEnd: widget.rangeEnd, + ); + + final seriesList = [ + charts.Series( + id: widget.chartConfig.storySubstring, + domainFn: (MeasuredObservation val, _) => val.dateTime, + measureFn: (MeasuredObservation val, _) => val.value, + data: data, + ) + ]; + + void _infoSelectionModelUpdated( + charts.SelectionModel model, + ) { + if (model.hasDatumSelection) { + final newSelection = + model.selectedDatum.first.datum as MeasuredObservation; + context.read().setSelected(newSelection); + _chartState.selectionModels[charts.SelectionModelType.info] = + charts.UserManagedSelectionModel(model: model); + } else { + context.read().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), + ], ), - ); - }, - ), - ); - }, + ), + ), + ); + }, + ), ); } } diff --git a/pubspec.yaml b/pubspec.yaml index 210f73f4b..47af56311 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -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