feat: journal UX overhaul — picker, export dialog, events, readability
- Sidebar i18n: added missing nav.journal to backend ru.json - Export: SaveWorklogReport binding with native SaveFileDialog + os.WriteFile - Filter: better IncludeChildren label with disabled tooltip - Filter: renamed billable→К оплате, approximate→Тип времени with hints - worklog_entry_events table (migration 013) linking entries to activity events - Suggestion: EventIDs + Events details, expandable cards with timestamps - Journal rows: expandable with details, source, linked events - Contrast: improved readability for dates, timestamps, hover states - i18n: added worklog.*, journal.*, suggest.* keys to ru.js/en.js
This commit is contained in:
@@ -7,16 +7,29 @@ const (
|
||||
ConfidenceHigh = "high"
|
||||
)
|
||||
|
||||
// SuggestionDetail is a lightweight event summary for suggestion display.
|
||||
type SuggestionDetail struct {
|
||||
ID string `json:"id"`
|
||||
EventType string `json:"eventType"`
|
||||
TargetType string `json:"targetType"`
|
||||
TargetID string `json:"targetId"`
|
||||
Title string `json:"title"`
|
||||
CreatedAt string `json:"createdAt"`
|
||||
NodeID string `json:"nodeId"`
|
||||
}
|
||||
|
||||
// Suggestion represents a suggested worklog entry derived from today's activity.
|
||||
type Suggestion struct {
|
||||
NodeID string `json:"nodeId"`
|
||||
NodeTitle string `json:"nodeTitle"`
|
||||
Summary string `json:"summary"`
|
||||
SuggestedMin int `json:"suggestedMin"`
|
||||
EventCount int `json:"eventCount"`
|
||||
NodeKind string `json:"nodeKind"`
|
||||
Confidence string `json:"confidence"`
|
||||
ConfidenceReason string `json:"confidenceReason"`
|
||||
Hidden bool `json:"hidden"`
|
||||
TimeSpreadMin int `json:"timeSpreadMin"` // minutes between first and last event
|
||||
NodeID string `json:"nodeId"`
|
||||
NodeTitle string `json:"nodeTitle"`
|
||||
Summary string `json:"summary"`
|
||||
SuggestedMin int `json:"suggestedMin"`
|
||||
EventCount int `json:"eventCount"`
|
||||
NodeKind string `json:"nodeKind"`
|
||||
Confidence string `json:"confidence"`
|
||||
ConfidenceReason string `json:"confidenceReason"`
|
||||
Hidden bool `json:"hidden"`
|
||||
TimeSpreadMin int `json:"timeSpreadMin"` // minutes between first and last event
|
||||
EventIDs []string `json:"eventIds"`
|
||||
Events []SuggestionDetail `json:"events,omitempty"`
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
package storage
|
||||
|
||||
// migration013 — worklog_entry_events table linking entries to activity events.
|
||||
const migration013 = `
|
||||
CREATE TABLE IF NOT EXISTS worklog_entry_events (
|
||||
entry_id TEXT NOT NULL REFERENCES worklog_entries(id) ON DELETE CASCADE,
|
||||
event_id TEXT NOT NULL,
|
||||
PRIMARY KEY (entry_id, event_id)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_wle_events ON worklog_entry_events(event_id);
|
||||
`
|
||||
@@ -69,6 +69,7 @@ var migrationFiles = map[int]string{
|
||||
10: migration010,
|
||||
11: migration011,
|
||||
12: migration012,
|
||||
13: migration013,
|
||||
}
|
||||
|
||||
func (db *DB) runInitialSchema() error {
|
||||
|
||||
@@ -7,6 +7,17 @@
|
||||
"nav.recipes": "Recipes",
|
||||
"nav.documents": "Documents",
|
||||
"nav.archive": "Archive",
|
||||
"nav.journal": "Work Log",
|
||||
"nav.sections": "Sections",
|
||||
"nav.cases": "Cases",
|
||||
"nav.noCases": "No cases",
|
||||
"nav.sync": "Sync",
|
||||
"nav.syncSettings": "Sync settings",
|
||||
"nav.syncNow": "Sync now",
|
||||
"nav.selectPrompt": "Select a section or case",
|
||||
"nav.brand": "Verstak",
|
||||
"nav.createNode": "Create node",
|
||||
"nav.moveToRoot": "Move to root",
|
||||
|
||||
"tab.overview": "Overview",
|
||||
"tab.notes": "Notes",
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
"nav.sections": "Разделы",
|
||||
"nav.cases": "Дела",
|
||||
"nav.noCases": "Нет дел",
|
||||
"nav.journal": "Журнал",
|
||||
"nav.sync": "Синхронизация",
|
||||
"nav.syncSettings": "Настройки синхронизации",
|
||||
"nav.syncNow": "Синхронизировать",
|
||||
@@ -391,6 +392,8 @@
|
||||
"nav.noNodes": "Нет узлов",
|
||||
"nav.openFolder": "Открыть папку",
|
||||
"nav.createInside": "Создать внутри",
|
||||
"nav.createNode": "Создать элемент",
|
||||
"nav.moveToRoot": "Переместить в корень",
|
||||
|
||||
"template.folder": "Папка",
|
||||
"template.project": "Проект",
|
||||
|
||||
Reference in New Issue
Block a user