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

Allow to optionally show "Total" in most dashboard entry types #89

Merged
merged 6 commits into from
Nov 3, 2024
Merged
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
1 change: 1 addition & 0 deletions dashboard/convert/entry.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ func ToExternalEntry(entry model.DashboardEntry) (*gqlmodel.DashboardEntry, erro
return &gqlmodel.DashboardEntry{
ID: entry.ID,
Title: entry.Title,
Total: entry.Total,
Pos: &pos,
StatsSelection: stats,
EntryType: ExternalEntryType(entry.Type),
Expand Down
2 changes: 1 addition & 1 deletion dashboard/dbrange/ranges_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ func TestRanges(t *testing.T) {
})
require.EqualError(t, err, "dashboard range does not exist")

entry, err := resolver.AddDashboardEntry(user1, 1, gqlmodel.EntryTypeBarChart, "other", gqlmodel.InputStatsSelection{
entry, err := resolver.AddDashboardEntry(user1, 1, gqlmodel.EntryTypeBarChart, "other", true, gqlmodel.InputStatsSelection{
Interval: gqlmodel.StatsIntervalDaily,
Tags: []string{"abc"},
RangeID: &xrange.ID,
Expand Down
3 changes: 2 additions & 1 deletion dashboard/entry/add.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import (
)

// AddDashboardEntry adds a dashboard entry.
func (r *ResolverForEntry) AddDashboardEntry(ctx context.Context, dashboardID int, entryType gqlmodel.EntryType, title string, stats gqlmodel.InputStatsSelection, pos *gqlmodel.InputResponsiveDashboardEntryPos) (*gqlmodel.DashboardEntry, error) {
func (r *ResolverForEntry) AddDashboardEntry(ctx context.Context, dashboardID int, entryType gqlmodel.EntryType, title string, total bool, stats gqlmodel.InputStatsSelection, pos *gqlmodel.InputResponsiveDashboardEntryPos) (*gqlmodel.DashboardEntry, error) {
userID := auth.GetUser(ctx).ID

if _, err := util.FindDashboard(r.DB, userID, dashboardID); err != nil {
Expand All @@ -28,6 +28,7 @@ func (r *ResolverForEntry) AddDashboardEntry(ctx context.Context, dashboardID in
Keys: strings.Join(stats.Tags, ","),
Type: convert.InternalEntryType(entryType),
Title: title,
Total: total,
DashboardID: dashboardID,
Interval: convert.InternalInterval(stats.Interval),
MobilePosition: convert.EmptyPos(),
Expand Down
39 changes: 24 additions & 15 deletions dashboard/entry/entries_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
func TestEntries(t *testing.T) {
db := test.InMemoryDB(t)
defer db.Close()
var bVal bool

resolver := dashboard.NewResolverForDashboard(db.DB)

Expand All @@ -35,7 +36,7 @@ func TestEntries(t *testing.T) {
}
require.Equal(t, expectAdded, dashboard)

_, err = resolver.AddDashboardEntry(user1, 5, gqlmodel.EntryTypeBarChart, "test", gqlmodel.InputStatsSelection{
_, err = resolver.AddDashboardEntry(user1, 5, gqlmodel.EntryTypeBarChart, "test", false, gqlmodel.InputStatsSelection{
Interval: "",
Tags: []string{"hhol"},
ExcludeTags: nil,
Expand All @@ -47,7 +48,7 @@ func TestEntries(t *testing.T) {
},
}, nil)
require.EqualError(t, err, "dashboard does not exist")
_, err = resolver.AddDashboardEntry(user1, 1, gqlmodel.EntryTypeBarChart, "test", gqlmodel.InputStatsSelection{
_, err = resolver.AddDashboardEntry(user1, 1, gqlmodel.EntryTypeBarChart, "test", false, gqlmodel.InputStatsSelection{
Interval: gqlmodel.StatsIntervalHourly,
Tags: []string{"hhol"},
ExcludeTags: nil,
Expand All @@ -59,7 +60,7 @@ func TestEntries(t *testing.T) {
},
}, nil)
require.EqualError(t, err, "dashboard range does not exist")
_, err = resolver.AddDashboardEntry(user2, 1, gqlmodel.EntryTypeBarChart, "test", gqlmodel.InputStatsSelection{
_, err = resolver.AddDashboardEntry(user2, 1, gqlmodel.EntryTypeBarChart, "test", false, gqlmodel.InputStatsSelection{
Interval: "doubly",
Tags: []string{"hhol"},
ExcludeTags: nil,
Expand All @@ -71,7 +72,7 @@ func TestEntries(t *testing.T) {
},
}, nil)
require.EqualError(t, err, "dashboard does not exist")
_, err = resolver.AddDashboardEntry(user1, 1, gqlmodel.EntryTypeBarChart, "test", gqlmodel.InputStatsSelection{
_, err = resolver.AddDashboardEntry(user1, 1, gqlmodel.EntryTypeBarChart, "test", false, gqlmodel.InputStatsSelection{
Interval: gqlmodel.StatsIntervalDaily,
Tags: []string{"hhol"},
ExcludeTags: nil,
Expand All @@ -83,7 +84,7 @@ func TestEntries(t *testing.T) {
},
}, nil)
require.EqualError(t, err, "range to (now-2) invalid: expected unit at the end but got nothing")
_, err = resolver.AddDashboardEntry(user1, 1, gqlmodel.EntryTypeBarChart, "test", gqlmodel.InputStatsSelection{
_, err = resolver.AddDashboardEntry(user1, 1, gqlmodel.EntryTypeBarChart, "test", false, gqlmodel.InputStatsSelection{
Interval: gqlmodel.StatsIntervalDaily,
Tags: []string{"hhol"},
ExcludeTags: nil,
Expand All @@ -95,7 +96,7 @@ func TestEntries(t *testing.T) {
},
}, nil)
require.EqualError(t, err, "range from (now-2) invalid: expected unit at the end but got nothing")
_, err = resolver.AddDashboardEntry(user1, 1, gqlmodel.EntryTypeBarChart, "test", gqlmodel.InputStatsSelection{
_, err = resolver.AddDashboardEntry(user1, 1, gqlmodel.EntryTypeBarChart, "test", false, gqlmodel.InputStatsSelection{
Interval: gqlmodel.StatsIntervalDaily,
Tags: []string{},
ExcludeTags: nil,
Expand All @@ -108,7 +109,7 @@ func TestEntries(t *testing.T) {
}, nil)
require.EqualError(t, err, "at least one tag is required")

entry, err := resolver.AddDashboardEntry(user1, 1, gqlmodel.EntryTypeBarChart, "test", gqlmodel.InputStatsSelection{
entry, err := resolver.AddDashboardEntry(user1, 1, gqlmodel.EntryTypeBarChart, "test", false, gqlmodel.InputStatsSelection{
Interval: gqlmodel.StatsIntervalDaily,
Tags: []string{"abc"},
ExcludeTags: nil,
Expand All @@ -128,6 +129,7 @@ func TestEntries(t *testing.T) {
expectedEntry := &gqlmodel.DashboardEntry{
ID: 1,
Title: "test",
Total: false,
StatsSelection: &gqlmodel.StatsSelection{
Interval: gqlmodel.StatsIntervalDaily,
Tags: []string{"abc"},
Expand Down Expand Up @@ -173,7 +175,7 @@ func TestEntries(t *testing.T) {
},
})
require.NoError(t, err)
_, err = resolver.AddDashboardEntry(user1, 1, gqlmodel.EntryTypeBarChart, "other", gqlmodel.InputStatsSelection{
_, err = resolver.AddDashboardEntry(user1, 1, gqlmodel.EntryTypeBarChart, "other", false, gqlmodel.InputStatsSelection{
Interval: gqlmodel.StatsIntervalDaily,
Tags: []string{"abc"},
RangeID: p(xrange.ID),
Expand All @@ -188,11 +190,11 @@ func TestEntries(t *testing.T) {
require.EqualError(t, err, "range is used in entries: other")

chart := gqlmodel.EntryTypePieChart
_, err = resolver.UpdateDashboardEntry(user2, 1, &chart, nil, nil, nil)
_, err = resolver.UpdateDashboardEntry(user2, 1, &chart, nil, nil, nil, nil)
require.EqualError(t, err, "dashboard does not exist")
_, err = resolver.UpdateDashboardEntry(user1, 3, &chart, nil, nil, nil)
_, err = resolver.UpdateDashboardEntry(user1, 3, &chart, nil, nil, nil, nil)
require.EqualError(t, err, "entry does not exist")
_, err = resolver.UpdateDashboardEntry(user1, 1, &chart, s("cool title"), &gqlmodel.InputStatsSelection{
_, err = resolver.UpdateDashboardEntry(user1, 1, &chart, s("cool title"), &bVal, &gqlmodel.InputStatsSelection{
Interval: gqlmodel.StatsIntervalDaily,
Tags: []string{"kek"},
ExcludeTags: nil,
Expand All @@ -204,7 +206,7 @@ func TestEntries(t *testing.T) {
},
}, nil)
require.EqualError(t, err, "range from (now-2) invalid: expected unit at the end but got nothing")
_, err = resolver.UpdateDashboardEntry(user1, 1, &chart, s("cool title"), &gqlmodel.InputStatsSelection{
_, err = resolver.UpdateDashboardEntry(user1, 1, &chart, s("cool title"), &bVal, &gqlmodel.InputStatsSelection{
Interval: gqlmodel.StatsIntervalDaily,
Tags: []string{"kek"},
ExcludeTags: nil,
Expand All @@ -222,6 +224,7 @@ func TestEntries(t *testing.T) {
{
ID: 1,
Title: "test",
Total: false,
StatsSelection: &gqlmodel.StatsSelection{
Interval: gqlmodel.StatsIntervalDaily,
Tags: []string{"abc"},
Expand Down Expand Up @@ -256,6 +259,7 @@ func TestEntries(t *testing.T) {
{
ID: 2,
Title: "other",
Total: false,
StatsSelection: &gqlmodel.StatsSelection{
Interval: gqlmodel.StatsIntervalDaily,
Tags: []string{"abc"},
Expand Down Expand Up @@ -284,7 +288,7 @@ func TestEntries(t *testing.T) {
EntryType: gqlmodel.EntryTypeBarChart,
},
}, dashboards[0].Items)
_, err = resolver.UpdateDashboardEntry(user1, 1, &chart, s("cool title"), &gqlmodel.InputStatsSelection{
_, err = resolver.UpdateDashboardEntry(user1, 1, &chart, s("cool title"), &bVal, &gqlmodel.InputStatsSelection{
Interval: gqlmodel.StatsIntervalDaily,
Tags: []string{"kek"},
ExcludeTags: nil,
Expand All @@ -308,6 +312,7 @@ func TestEntries(t *testing.T) {
{
ID: 1,
Title: "cool title",
Total: false,
StatsSelection: &gqlmodel.StatsSelection{
Interval: gqlmodel.StatsIntervalDaily,
Tags: []string{"kek"},
Expand Down Expand Up @@ -342,6 +347,7 @@ func TestEntries(t *testing.T) {
{
ID: 2,
Title: "other",
Total: false,
StatsSelection: &gqlmodel.StatsSelection{
Interval: gqlmodel.StatsIntervalDaily,
Tags: []string{"abc"},
Expand Down Expand Up @@ -371,7 +377,7 @@ func TestEntries(t *testing.T) {
},
}, dashboards[0].Items)

_, err = resolver.UpdateDashboardEntry(user1, 1, &chart, s("cool title"), &gqlmodel.InputStatsSelection{
_, err = resolver.UpdateDashboardEntry(user1, 1, &chart, s("cool title"), &bVal, &gqlmodel.InputStatsSelection{
Interval: gqlmodel.StatsIntervalDaily,
Tags: []string{"kek"},
ExcludeTags: nil,
Expand All @@ -385,7 +391,7 @@ func TestEntries(t *testing.T) {
}})
require.EqualError(t, err, "dashboard range does not exist")

_, err = resolver.UpdateDashboardEntry(user1, 1, &chart, s("cool title"), &gqlmodel.InputStatsSelection{
_, err = resolver.UpdateDashboardEntry(user1, 1, &chart, s("cool title"), &bVal, &gqlmodel.InputStatsSelection{
Interval: gqlmodel.StatsIntervalDaily,
Tags: []string{"kek"},
ExcludeTags: nil,
Expand All @@ -405,6 +411,7 @@ func TestEntries(t *testing.T) {
{
ID: 1,
Title: "cool title",
Total: false,
StatsSelection: &gqlmodel.StatsSelection{
Interval: gqlmodel.StatsIntervalDaily,
Tags: []string{"kek"},
Expand Down Expand Up @@ -435,6 +442,7 @@ func TestEntries(t *testing.T) {
{
ID: 2,
Title: "other",
Total: false,
StatsSelection: &gqlmodel.StatsSelection{
Interval: gqlmodel.StatsIntervalDaily,
Tags: []string{"abc"},
Expand Down Expand Up @@ -479,6 +487,7 @@ func TestEntries(t *testing.T) {
{
ID: 2,
Title: "other",
Total: false,
StatsSelection: &gqlmodel.StatsSelection{
Interval: gqlmodel.StatsIntervalDaily,
Tags: []string{"abc"},
Expand Down
7 changes: 6 additions & 1 deletion dashboard/entry/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import (
)

// UpdateDashboardEntry updates a dashboard entry.
func (r *ResolverForEntry) UpdateDashboardEntry(ctx context.Context, id int, entryType *gqlmodel.EntryType, title *string, stats *gqlmodel.InputStatsSelection, pos *gqlmodel.InputResponsiveDashboardEntryPos) (*gqlmodel.DashboardEntry, error) {
func (r *ResolverForEntry) UpdateDashboardEntry(ctx context.Context, id int, entryType *gqlmodel.EntryType, title *string, total *bool, stats *gqlmodel.InputStatsSelection, pos *gqlmodel.InputResponsiveDashboardEntryPos) (*gqlmodel.DashboardEntry, error) {
userID := auth.GetUser(ctx).ID

entry, err := util.FindDashboardEntry(r.DB, id)
Expand All @@ -31,6 +31,11 @@ func (r *ResolverForEntry) UpdateDashboardEntry(ctx context.Context, id int, ent
if title != nil {
entry.Title = *title
}

if total != nil {
entry.Total = *total
}

if stats != nil {
if stats.RangeID != nil {
if _, err := util.FindDashboardRange(r.DB, *stats.RangeID); err != nil {
Expand Down
1 change: 1 addition & 0 deletions model/dashboard.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ type DashboardEntry struct {
ID int `gorm:"primary_key;unique_index;AUTO_INCREMENT"`
DashboardID int `gorm:"type:int REFERENCES dashboards(id) ON DELETE CASCADE"`
Title string
Total bool `gorm:"default:false"`
Type DashboardType
Keys string
Interval Interval
Expand Down
5 changes: 3 additions & 2 deletions schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ type RootMutation {
updateDashboardRange(rangeId: Int!, range: InputNamedDateRange!): NamedDateRange
removeDashboardRange(rangeId: Int!): NamedDateRange

addDashboardEntry(dashboardId: Int!, entryType: EntryType!, title: String!, stats: InputStatsSelection!, pos: InputResponsiveDashboardEntryPos): DashboardEntry @hasRole(role: USER)
updateDashboardEntry(entryId: Int!, entryType: EntryType, title: String, stats: InputStatsSelection, pos: InputResponsiveDashboardEntryPos): DashboardEntry @hasRole(role: USER)
addDashboardEntry(dashboardId: Int!, entryType: EntryType!, title: String!, total: Boolean!, stats: InputStatsSelection!, pos: InputResponsiveDashboardEntryPos): DashboardEntry @hasRole(role: USER)
updateDashboardEntry(entryId: Int!, entryType: EntryType, title: String, total: Boolean, stats: InputStatsSelection, pos: InputResponsiveDashboardEntryPos): DashboardEntry @hasRole(role: USER)
removeDashboardEntry(id: Int!): DashboardEntry! @hasRole(role: USER)

setUserSettings(settings: InputUserSettings!): UserSettings! @hasRole(role: USER)
Expand Down Expand Up @@ -251,6 +251,7 @@ input InputRelativeOrStaticRange {
type DashboardEntry {
id: Int!
title: String!
total: Boolean!
statsSelection: StatsSelection!
pos: ResponsiveDashboardEntryPos!
entryType: EntryType!
Expand Down
1 change: 1 addition & 0 deletions ui/src/dashboard/DashboardPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ const newEntry = (): Dashboards_dashboards_items => {
__typename: 'DashboardEntryPos',
},
},
total: false,
};
};

Expand Down
1 change: 1 addition & 0 deletions ui/src/dashboard/Entry/AddPopup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ export const AddPopup: React.FC<EditPopupProps> = ({
dashboardId,
entryType: entry.entryType,
title: entry.title,
total: entry.total,
stats: {
tags: entry.statsSelection.tags,
interval: entry.statsSelection.interval,
Expand Down
5 changes: 3 additions & 2 deletions ui/src/dashboard/Entry/DashboardBarChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ interface DashboardPieChartProps {
entries: Stats_stats[];
interval: StatsInterval;
type: 'stacked' | 'normal';
total: boolean;
}

interface Indexed {
Expand All @@ -20,7 +21,7 @@ interface Indexed {
data: Record<string, number>;
}

export const DashboardBarChart: React.FC<DashboardPieChartProps> = ({entries, interval, type}) => {
export const DashboardBarChart: React.FC<DashboardPieChartProps> = ({entries, interval, type, total}) => {
const indexedEntries: Indexed[] = entries
.map((entry) => {
return {
Expand All @@ -46,7 +47,7 @@ export const DashboardBarChart: React.FC<DashboardPieChartProps> = ({entries, in
<BarChart data={indexedEntries}>
<CartesianGrid strokeDasharray="3 3" />
<YAxis type="number" unit={unit.short} />
<Tooltip content={<TagTooltip dateFormat={dateFormat} />} />
<Tooltip content={<TagTooltip dateFormat={dateFormat} total={total} />} />
<Legend />
<XAxis dataKey={(entry) => dateFormat(moment(entry.start))} interval={'preserveStartEnd'} />

Expand Down
10 changes: 5 additions & 5 deletions ui/src/dashboard/Entry/DashboardEntry.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ const SpecificDashboardEntry: React.FC<{entry: Dashboards_dashboards_items; rang
</Center>
);
}
return <DashboardBarChart entries={entries} interval={interval} type="normal" />;
return <DashboardBarChart entries={entries} interval={interval} type="normal" total={entry.total} />;
case EntryType.StackedBarChart:
if (entries.length === 0) {
return (
Expand All @@ -97,7 +97,7 @@ const SpecificDashboardEntry: React.FC<{entry: Dashboards_dashboards_items; rang
</Center>
);
}
return <DashboardBarChart entries={entries} interval={interval} type="stacked" />;
return <DashboardBarChart entries={entries} interval={interval} type="stacked" total={entry.total} />;
case EntryType.LineChart:
if (entries.length === 0) {
return (
Expand All @@ -106,7 +106,7 @@ const SpecificDashboardEntry: React.FC<{entry: Dashboards_dashboards_items; rang
</Center>
);
}
return <DashboardLineChart entries={entries} interval={interval} />;
return <DashboardLineChart entries={entries} interval={interval} total={entry.total} />;
case EntryType.VerticalTable:
if (entries.length === 0) {
return (
Expand All @@ -115,7 +115,7 @@ const SpecificDashboardEntry: React.FC<{entry: Dashboards_dashboards_items; rang
</Center>
);
}
return <DashboardTable mode="vertical" entries={entries} interval={interval} />;
return <DashboardTable mode="vertical" entries={entries} interval={interval} total={entry.total} />;
case EntryType.HorizontalTable:
if (entries.length === 0) {
return (
Expand All @@ -124,7 +124,7 @@ const SpecificDashboardEntry: React.FC<{entry: Dashboards_dashboards_items; rang
</Center>
);
}
return <DashboardTable mode="horizontal" entries={entries} interval={interval} />;
return <DashboardTable mode="horizontal" entries={entries} interval={interval} total={entry.total} />;
default:
return expectNever(entry.entryType);
}
Expand Down
Loading
Loading