private static LogItemViewModel header( IThreadSafeTimeEntry[] group, LogItemVisualizationIntent visualizationIntent, DurationFormat durationFormat) { var sample = group.First(); return(new LogItemViewModel( groupId: new GroupId(sample), representedTimeEntriesIds: group.Select(timeEntry => timeEntry.Id).ToArray(), visualizationIntent: visualizationIntent, isBillable: sample.Billable, isActive: sample.Project?.Active ?? true, description: sample.Description, duration: DurationAndFormatToString.Convert( TimeSpan.FromSeconds(group.Sum(timeEntry => timeEntry.Duration ?? 0)), durationFormat), projectName: sample.Project?.Name, projectColor: sample.Project?.Color, clientName: sample.Project?.Client?.Name, taskName: sample.Task?.Name, hasTags: sample.Tags.Any(), needsSync: group.Any(timeEntry => timeEntry.SyncStatus == SyncStatus.SyncNeeded), canSync: group.All(timeEntry => timeEntry.SyncStatus != SyncStatus.SyncFailed), isInaccessible: sample.IsInaccessible, indexInLog: 0, dayInLog: 0, daysInThePast: 0, projectIsPlaceholder: sample.Project?.IsPlaceholder() ?? false, taskIsPlaceholder: sample.Task?.IsPlaceholder() ?? false)); }
public static LogItemViewModel ToViewModel( this IThreadSafeTimeEntry timeEntry, GroupId groupId, LogItemVisualizationIntent visualizationIntent, DurationFormat durationFormat, int indexInLog, int dayInLog, int daysInThePast) => new LogItemViewModel( groupId, new[] { timeEntry.Id }, visualizationIntent, timeEntry.Billable, timeEntry.Description, timeEntry.Duration.HasValue ? DurationAndFormatToString.Convert( TimeSpan.FromSeconds(timeEntry.Duration.Value), durationFormat) : string.Empty, timeEntry.Project?.DisplayName(), timeEntry.Project?.DisplayColor(), timeEntry.Project?.Client?.Name, timeEntry.Task?.Name, timeEntry.TagIds.Any(), timeEntry.SyncStatus == SyncStatus.SyncNeeded, timeEntry.SyncStatus != SyncStatus.SyncFailed, timeEntry.IsInaccessible, indexInLog, dayInLog, daysInThePast);
public void ReturnsNonEmptyStringForValidFormats(DurationFormat format) { var convertedValue = converter.Convert(TimeSpan.Zero, typeof(string), format, CultureInfo.CurrentCulture); convertedValue.Should().BeOfType <string>(); ((string)convertedValue).Length.Should().BeGreaterThan(0); }
public IEnumerable <MainLogSection> Flatten(IEnumerable <LogGrouping> days, IThreadSafePreferences preferences) { durationFormat = preferences.DurationFormat; return(days.Select(preferences.CollapseTimeEntries ? flatten(bySimilarTimeEntries) : flatten(withJustSingleTimeEntries))); }
public void FailsForDurationFormatsWhichAreOutOfRange(DurationFormat format) { var successful = tryGetValue(TimeSpan.Zero, format, out var convertedValue); successful.Should().BeTrue(); convertedValue.Should().BeOfType <string>(); ((string)convertedValue).Length.Should().BeGreaterThan(0); }
private static LogItemViewModel groupItem(IThreadSafeTimeEntry timeEntry, DurationFormat durationFormat) => timeEntry.ToViewModel( new GroupId(timeEntry), LogItemVisualizationIntent.GroupItem, durationFormat, 0, 0, 0);
public static ChartSegment WithDurationFormat(this ChartSegment segment, DurationFormat durationFormat) => new ChartSegment( segment.ProjectName, segment.Percentage, (float)segment.TrackedTime.TotalSeconds, segment.BillableSeconds, segment.Color, durationFormat);
private void onPreferencesChanged(IThreadSafePreferences preferences) { if (durationFormat != preferences.DurationFormat) { durationFormat = preferences.DurationFormat; var _ = fetchSectionedTimeEntries(); } }
public static ReportsSummaryData Create( IReadOnlyList <ChartSegment> segments, bool showEmptyState, TimeSpan totalTime, bool totalTimeIsZero, float?billablePercentage, DurationFormat durationFormat) { return(new ReportsSummaryData(segments, showEmptyState, totalTime, totalTimeIsZero, billablePercentage ?? 0f, durationFormat)); }
public void StartsWithZero(DurationFormat format, string expectedOutput) { var observer = TestScheduler.CreateObserver <string>(); ViewModel.TimeTrackedToday.Subscribe(observer); durationFormatSubject.OnNext(format); TestScheduler.Start(); observer.Messages.First().Value.Value.Should().Be(expectedOutput); }
public ISpannable convertReportTimeSpanToDurationString(TimeSpan timeSpan, DurationFormat durationFormat) { var timeString = timeSpan.ToFormattedString(durationFormat); var emphasizedPartLength = durationFormat == DurationFormat.Improved ? timeString.Length - 3 : timeString.Length; var isDisabled = timeSpan.Ticks == 0; return(selectTimeSpanEnabledStateSpan(timeString, emphasizedPartLength, isDisabled)); }
public void EmitsCorrectlyFormattedTimeBasedOnUsersPreferences(DurationFormat format, string expectedOutput) { var observer = TestScheduler.CreateObserver <string>(); ViewModel.TimeTrackedToday.Subscribe(observer); durationFormatSubject.OnNext(format); trackedTimeSubject.OnNext(duration); TestScheduler.Start(); observer.Messages.Skip(1).First().Value.Value.Should().Be(expectedOutput); }
public Preferences(TimeFormat timeOfDayFormat, DateFormat dateFormat, DurationFormat durationFormat, bool collapseTimeEntries, SyncStatus syncStatus = default(SyncStatus), string lastSyncErrorMessage = "", bool isDeleted = false) { Ensure.Argument.IsADefinedEnumValue(syncStatus, nameof(syncStatus)); Ensure.Argument.IsNotNull(dateFormat.Localized, nameof(dateFormat)); Ensure.Argument.IsNotNull(timeOfDayFormat.Localized, nameof(timeOfDayFormat)); TimeOfDayFormat = timeOfDayFormat; DateFormat = dateFormat; DurationFormat = durationFormat; CollapseTimeEntries = collapseTimeEntries; SyncStatus = syncStatus; LastSyncErrorMessage = lastSyncErrorMessage; IsDeleted = isDeleted; }
private void onPreferencesChanged(IThreadSafePreferences preferences) { durationFormat = preferences.DurationFormat; foreach (var collection in TimeEntries) { collection.DurationFormat = durationFormat; foreach (var timeEntry in collection) { timeEntry.DurationFormat = durationFormat; } } }
/// <summary> /// Reads in the settings, and returns a string representation /// of the <see cref="TimeSpan"/> object based on the settings. /// </summary> public static string ToSettingsString(this TimeSpan timespan, DateTimeSettings settings) { ArgumentNullException.ThrowIfNull(settings, nameof(settings)); DurationFormat duration = settings.DurationFormat; DurationSeparator separator = settings.DurationSeparator; string formatString; if (duration == DurationFormat.HourMinuteSecond) { if (separator == DurationSeparator.LettersOnly) { formatString = @"'H 'mm'M 'ss'S'"; } else if (separator == DurationSeparator.ColonAndLetters) { formatString = @"'H'\:mm'M'\:ss'S'"; } else // ColonOnly is the default. { formatString = @"\:mm\:ss"; } } else // HourMinute (and any others) are the default. { if (separator == DurationSeparator.LettersOnly) { formatString = @"'H 'mm'M'"; } else if (separator == DurationSeparator.ColonAndLetters) { formatString = @"'H'\:mm'M'"; } else // ColonOnly is the default. { formatString = @"\:mm"; } } // For total hours, need to use the TotalHours property instead of using // a format string. Otherwise, if the time is more than a day, // it won't report the correct number of hours. // // Need to Math.Floor it as well, otherwise if we have more than half an hour // in the minutes section, it will round up. return (Math.Floor(timespan.TotalHours).ToString("00") + timespan.ToString(formatString)); }
public ChartSegment( string projectName, float percentage, float trackedSeconds, float billableSeconds, string color, DurationFormat durationFormat = DurationFormat.Improved) { ProjectName = projectName; Color = color; Percentage = percentage; TrackedTime = TimeSpan.FromSeconds(trackedSeconds); BillableSeconds = billableSeconds; DurationFormat = durationFormat; }
private ReportsSummaryData( IReadOnlyList <ChartSegment> segments, bool showEmptyState, TimeSpan totalTime, bool totalTimeIsZero, float billablePercentage, DurationFormat durationFormat) { Segments = segments; ShowEmptyState = showEmptyState; TotalTime = totalTime; TotalTimeIsZero = totalTimeIsZero; BillablePercentage = billablePercentage; DurationFormat = durationFormat; }
public static string ToFormattedString(this TimeSpan duration, DurationFormat format) { switch (format) { case DurationFormat.Classic: return convertToClassicFormat(duration); case DurationFormat.Improved: return convertToImprovedFormat(duration); case DurationFormat.Decimal: return convertToDecimalFormat(duration); default: throw new ArgumentOutOfRangeException( $"The duration converter parameter '{format}' is not of the supported formats."); } }
public static DurationFormat GetDistance(BgTaxi.Models.Models.Location location1, BgTaxi.Models.Models.Location location2) { WebRequest request = WebRequest.Create("https://maps.googleapis.com/maps/api/distancematrix/json?origins=" + location1.Latitude.ToString("0.0000000", System.Globalization.CultureInfo.InvariantCulture) + ", " + location1.Longitude.ToString("0.0000000", System.Globalization.CultureInfo.InvariantCulture) + "&destinations=" + location2.Latitude.ToString("0.0000000", System.Globalization.CultureInfo.InvariantCulture) + ", " + location2.Longitude.ToString("0.0000000", System.Globalization.CultureInfo.InvariantCulture) + "&key=AIzaSyCqFT1vjwghgVYc9Y_jbuD-ux10qQD9H0s&language=bg"); WebResponse response = request.GetResponse(); Stream dataStream = response.GetResponseStream(); // Open the stream using a StreamReader for easy access. StreamReader reader = new StreamReader(dataStream); // Read the content. string responseFromServer = reader.ReadToEnd(); // Display the content. DurationFormat flight = Newtonsoft.Json.JsonConvert.DeserializeObject <DurationFormat>(responseFromServer); return(flight); }
public async Task ChangesDurationFormat(DurationFormat format) { var(togglClient, user) = await SetupTestUser(); var oldPreferences = await togglClient.Preferences.Get(); var newPreferences = new Preferences(oldPreferences); newPreferences.DurationFormat = format; await togglClient.Preferences.Update(newPreferences); var updatedPreferences = await togglClient.Preferences.Get(); updatedPreferences.DurationFormat.Should().Be(newPreferences.DurationFormat); }
public TimeEntryViewModelCollection(DateTime date, IEnumerable <TimeEntryViewModel> items, DurationFormat durationFormat) { Ensure.Argument.IsNotNull(items, nameof(items)); if (date.Kind != DateTimeKind.Local) { throw new ArgumentException($"{nameof(date)} must have kind DateTimeKind.Local"); } this.AddRange(items); Date = new DateTimeOffset(date); TotalTime = calculateTotalTime(); DurationFormat = durationFormat; }
public IEnumerable <MainLogSection> Flatten(IEnumerable <LogGrouping> days, IThreadSafePreferences preferences) { durationFormat = preferences.DurationFormat; indexInLog = 0; return(days.Select((day, dayInLog) => { var today = timeService.CurrentDateTime.Date; var sample = day.First().Start.Date; var daysInThePast = (today - sample).Days; var strategy = preferences.CollapseTimeEntries ? (Func <IEnumerable <IThreadSafeTimeEntry>, IEnumerable <IThreadSafeTimeEntry[]> >)bySimilarTimeEntries : (Func <IEnumerable <IThreadSafeTimeEntry>, IEnumerable <IThreadSafeTimeEntry[]> >)withJustSingleTimeEntries; return flatten(strategy, dayInLog, daysInThePast)(day); })); }
public static string ToFormattedString(this DurationFormat durationFormat) { switch (durationFormat) { case DurationFormat.Classic: return(Resources.DurationFormatClassic); case DurationFormat.Improved: return(Resources.DurationFormatImproved); case DurationFormat.Decimal: return(Resources.DurationFormatDecimal); default: throw new ArgumentException( $"Duration format must be either: {nameof(DurationFormat.Classic)}, {nameof(DurationFormat.Improved)} or {nameof(DurationFormat.Decimal)}" ); } }
public TimeEntryViewModel(IThreadSafeTimeEntry timeEntry, DurationFormat durationFormat) { Ensure.Argument.IsNotNull(timeEntry, nameof(timeEntry)); if (timeEntry.IsRunning()) { throw new InvalidOperationException("It is not possible to show a running time entry in the log."); } DurationFormat = durationFormat; Id = timeEntry.Id; WorkspaceId = timeEntry.WorkspaceId; StartTime = timeEntry.Start; IsBillable = timeEntry.Billable; TagIds = timeEntry.TagIds.ToArray(); HasTags = TagIds.Count() > 0; Description = timeEntry.Description; HasProject = timeEntry.Project != null; Duration = TimeSpan.FromSeconds(timeEntry.Duration.Value); HasDescription = !string.IsNullOrEmpty(timeEntry.Description); CanSync = timeEntry.SyncStatus != SyncStatus.SyncFailed; NeedsSync = timeEntry.SyncStatus == SyncStatus.SyncNeeded; IsGhost = timeEntry.IsGhost; if (!HasProject) { return; } ProjectId = timeEntry.Project.Id; ProjectName = timeEntry.Project.DisplayName(); ProjectColor = timeEntry.Project.DisplayColor(); TaskId = timeEntry.TaskId; TaskName = timeEntry.Task?.Name ?? ""; ClientName = timeEntry.Project.Client?.Name ?? ""; }
public void TransformsTimeEntriesIntoACorrectTree( DurationFormat durationFormat, IEnumerable <IGrouping <DateTime, IThreadSafeTimeEntry> > log, HashSet <GroupId> expandedGroups, params AnimatableSectionModel <DaySummaryViewModel, LogItemViewModel, IMainLogKey>[] expectedTree) { var preferences = new MockPreferences { CollapseTimeEntries = true, DateFormat = DateFormat.FromLocalizedDateFormat("YYYY-MM-DD"), DurationFormat = durationFormat }; var collapsingStrategy = new TimeEntriesGroupsFlattening(timeService); expandedGroups.ForEach(collapsingStrategy.ToggleGroupExpansion); var actualTree = collapsingStrategy.Flatten(log, preferences); actualTree.Should().BeEquivalentTo(expectedTree); }
public static string ToLabelString( this DurationFormat format, DateTimeSettings currentSettings, TimeSpan sampleTime ) { string label; if (format == DurationFormat.HourMinuteSecond) { label = "Hour Minute Second"; } else // Hour Minute is the default. { label = "Hour Minute"; } DateTimeSettings settings = currentSettings with { DurationFormat = format }; return($"{label} ({sampleTime.ToSettingsString( settings )})"); }
private string toFormattedString(TimeSpan timeSpan, DurationFormat format) { return(timeSpan.ToFormattedString(format)); }
private static IEnumerable <LogItemViewModel> expanded(IThreadSafeTimeEntry[] group, DurationFormat durationFormat) { yield return(header(group, LogItemVisualizationIntent.ExpandedGroupHeader, durationFormat)); foreach (var timeEntry in group) { yield return(groupItem(timeEntry, durationFormat)); } }
private static IEnumerable <LogItemViewModel> collapsed(IThreadSafeTimeEntry[] group, DurationFormat durationFormat) { yield return(header(group, LogItemVisualizationIntent.CollapsedGroupHeader, durationFormat)); }
private static IEnumerable <LogItemViewModel> single(IThreadSafeTimeEntry timeEntry, DurationFormat durationFormat) { yield return(timeEntry.ToViewModel( new GroupId(timeEntry), LogItemVisualizationIntent.SingleItem, durationFormat, 0, 0, 0)); }