Skip to content

Commit

Permalink
feat: Dynamic query variable support.
Browse files Browse the repository at this point in the history
Signed-off-by: Bahattin Çiniç <[email protected]>
  • Loading branch information
bahattincinic committed Jun 5, 2024
1 parent 2bdad0b commit 3280e95
Show file tree
Hide file tree
Showing 4 changed files with 175 additions and 38 deletions.
37 changes: 0 additions & 37 deletions database/dashboard.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,40 +128,3 @@ func (d *Database) GetComponent(dashboardID, componentID uint) (*models.Componen

return &component, nil
}

func (d *Database) RunQuery(query string) ([]map[string]interface{}, error) {
rows, err := d.db.Raw(query).Rows()
if err != nil {
return nil, err
}
defer rows.Close()

cols, err := rows.Columns()
if err != nil {
return nil, err
}

var results []map[string]interface{}

for rows.Next() {
cm := make([]interface{}, len(cols))
cmp := make([]interface{}, len(cols))
for i := range cm {
cmp[i] = &cm[i]
}

if err := rows.Scan(cmp...); err != nil {
return nil, err
}

rm := make(map[string]interface{})
for i, colName := range cols {
val := cmp[i].(*interface{})
rm[colName] = *val
}

results = append(results, rm)
}

return results, nil
}
91 changes: 91 additions & 0 deletions database/query.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package database

import (
"strings"
"text/template"
"time"

pkgerrors "github.com/pkg/errors"
)

func (d *Database) compileQuery(query string) (string, error) {
tmpl, err := template.New("query").Parse(query)
if err != nil {
return "", pkgerrors.Wrap(err, "Parse")
}

now := time.Now()
format := "2006-01-02"

thisWeekStart := now.AddDate(0, 0, -int(now.Weekday())+1)
thisWeekEnd := thisWeekStart.AddDate(0, 0, 6)
lastWeekStart := thisWeekStart.AddDate(0, 0, -7)
lastWeekEnd := lastWeekStart.AddDate(0, 0, 6)

thisMonthStart := time.Date(now.Year(), now.Month(), 1, 0, 0, 0, 0, now.Location())
thisMonthEnd := thisMonthStart.AddDate(0, 1, -1)
lastMonthStart := thisMonthStart.AddDate(0, -1, 0)
lastMonthEnd := thisMonthStart.AddDate(0, 0, -1)

params := map[string]string{
"Today": now.Format(format),
"Yesterday": now.AddDate(0, 0, -1).Format(format),
"ThisWeekStart": thisWeekStart.Format(format),
"ThisWeekEnd": thisWeekEnd.Format(format),
"LastWeekStart": lastWeekStart.Format(format),
"LastWeekEnd": lastWeekEnd.Format(format),
"ThisMonthStart": thisMonthStart.Format(format),
"ThisMonthEnd": thisMonthEnd.Format(format),
"LastMonthStart": lastMonthStart.Format(format),
"LastMonthEnd": lastMonthEnd.Format(format),
}

var builder strings.Builder
if err := tmpl.Execute(&builder, params); err != nil {
return "", pkgerrors.Wrap(err, "tmpl.Execute")
}

return builder.String(), nil
}

func (d *Database) RunQuery(query string) ([]map[string]interface{}, error) {
compiledQuery, err := d.compileQuery(query)
if err != nil {
return nil, err
}

rows, err := d.db.Raw(compiledQuery).Rows()
if err != nil {
return nil, err
}
defer rows.Close()

cols, err := rows.Columns()
if err != nil {
return nil, err
}

var results []map[string]interface{}

for rows.Next() {
cm := make([]interface{}, len(cols))
cmp := make([]interface{}, len(cols))
for i := range cm {
cmp[i] = &cm[i]
}

if err := rows.Scan(cmp...); err != nil {
return nil, err
}

rm := make(map[string]interface{})
for i, colName := range cols {
val := cmp[i].(*interface{})
rm[colName] = *val
}

results = append(results, rm)
}

return results, nil
}
32 changes: 31 additions & 1 deletion ui/src/components/ComponentModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,23 @@
class="query-input"
/>
</div>

<div class="flex justify-content-end">
<span class="cursor-pointer pb-3" @click="toggleDynamicInput">
Click to see Dynamic Query Parameters.
</span>
</div>
<div
class="flex align-items-center gap-3 mb-3"
v-if="showDynamicInput"
>
<DataTable :value="dynamicQueryOptions">
<Column field="option" header="Option" />
<Column field="value" header="Value" />
<Column field="example" header="Example Usage" />
</DataTable>
</div>

<div class="flex pt-4 justify-content-between">
<Button
:disabled="loading"
Expand Down Expand Up @@ -177,7 +194,13 @@ import Button from 'primevue/button';
import Dropdown from 'primevue/dropdown';
import Stepper from 'primevue/stepper';
import StepperPanel from 'primevue/stepperpanel';
import { componentTypes, componentTypeEnum } from '@/services/components';
import DataTable from 'primevue/datatable';
import Column from 'primevue/column';
import {
componentTypes,
componentTypeEnum,
dynamicQueryOptions,
} from '@/services/components';
import TableComponent from '@/components/TableComponent';
import PieChartComponent from '@/components/PieChartComponent';
import BarChartComponent from '@/components/BarChartComponent';
Expand Down Expand Up @@ -216,12 +239,16 @@ export default {
Dropdown,
Stepper,
StepperPanel,
DataTable,
Column,
},
data() {
return {
componentTypes,
componentTypeEnum,
dynamicQueryOptions,
queryResult: null,
showDynamicInput: false,
form: this.getInitialForm(this.row),
};
},
Expand Down Expand Up @@ -336,6 +363,9 @@ export default {
nextCallback();
}
},
toggleDynamicInput() {
this.showDynamicInput = !this.showDynamicInput;
},
onError(err) {
this.$toast.add({
severity: 'error',
Expand Down
53 changes: 53 additions & 0 deletions ui/src/services/components.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,59 @@ export const componentTypes = [
{ name: 'Line Chart', code: componentTypeEnum.lineChart },
];

export const dynamicQueryOptions = [
{
option: 'Today',
value: '{{.Today}}',
example: "start_date = '{{.Today}}'",
},
{
option: 'Yesterday',
value: '{{.Yesterday}}',
example: "start_date = '{{.Yesterday}}'",
},
{
option: 'This Week Start',
value: '{{.ThisWeekStart}}',
example: "start_date >= '{{.ThisWeekStart}}'",
},
{
option: 'This Week End',
value: '{{.ThisWeekEnd}}',
example: "start_date <= '{{.ThisWeekEnd}}'",
},
{
option: 'Last Week Start',
value: '{{.LastWeekStart}}',
example: "start_date >= '{{.LastWeekStart}}'",
},
{
option: 'Last Week End',
value: '{{.LastWeekEnd}}',
example: "start_date <= '{{.LastWeekEnd}}'",
},
{
option: 'This Month Start',
value: '{{.ThisMonthStart}}',
example: "start_date >= '{{.ThisMonthStart}}'",
},
{
option: 'This Month End',
value: '{{.ThisMonthEnd}}',
example: "start_date <= '{{.ThisMonthEnd}}'",
},
{
option: 'Last Month Start',
value: '{{.LastMonthStart}}',
example: "start_date >= '{{.LastMonthStart}}'",
},
{
option: 'Last Month End',
value: '{{.LastMonthEnd}}',
example: "start_date <= '{{.LastMonthEnd}}'",
},
];

export async function fetchComponents(accessToken, dashId) {
return await makeRequest({
endpoint: `/dashboards/${dashId}/components`,
Expand Down

0 comments on commit 3280e95

Please sign in to comment.