mirror of
https://github.com/OneUptime/oneuptime.git
synced 2026-04-06 08:42:13 +02:00
Compare commits
10 Commits
error-trac
...
group-by
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6f9e61b64c | ||
|
|
5271cd2a83 | ||
|
|
709fb8567f | ||
|
|
53115d1e5b | ||
|
|
62aedf90f0 | ||
|
|
66785d33b2 | ||
|
|
ead8d62190 | ||
|
|
8d66d4f0c2 | ||
|
|
bef4163278 | ||
|
|
1d49815fd3 |
@@ -26,6 +26,7 @@ import {
|
||||
import PartialEntity from 'Common/Types/Database/PartialEntity';
|
||||
import { UserPermission } from 'Common/Types/Permission';
|
||||
import CommonAPI from './CommonAPI';
|
||||
import GroupBy from '../Types/Database/GroupBy';
|
||||
|
||||
export default class BaseAPI<
|
||||
TBaseModel extends BaseModel,
|
||||
@@ -237,6 +238,7 @@ export default class BaseAPI<
|
||||
let query: Query<BaseModel> = {};
|
||||
let select: Select<BaseModel> = {};
|
||||
let sort: Sort<BaseModel> = {};
|
||||
let groupBy: GroupBy<BaseModel> | undefined;
|
||||
|
||||
if (req.body) {
|
||||
query = JSONFunctions.deserialize(
|
||||
@@ -250,6 +252,10 @@ export default class BaseAPI<
|
||||
sort = JSONFunctions.deserialize(
|
||||
req.body['sort']
|
||||
) as Sort<BaseModel>;
|
||||
|
||||
groupBy = JSONFunctions.deserialize(
|
||||
req.body['groupBy']
|
||||
) as GroupBy<BaseModel>;
|
||||
}
|
||||
|
||||
const databaseProps: DatabaseCommonInteractionProps =
|
||||
@@ -260,6 +266,7 @@ export default class BaseAPI<
|
||||
select,
|
||||
skip: skip,
|
||||
limit: limit,
|
||||
groupBy: groupBy,
|
||||
sort: sort,
|
||||
props: databaseProps,
|
||||
});
|
||||
|
||||
@@ -25,6 +25,7 @@ import { UserPermission } from 'Common/Types/Permission';
|
||||
import AnalyticsDataModel from 'Common/AnalyticsModels/BaseModel';
|
||||
import AnalyticsDatabaseService from '../Services/AnalyticsDatabaseService';
|
||||
import CommonAPI from './CommonAPI';
|
||||
import GroupBy from '../Types/AnalyticsDatabase/GroupBy';
|
||||
|
||||
export default class BaseAnalyticsAPI<
|
||||
TAnalyticsDataModel extends AnalyticsDataModel,
|
||||
@@ -235,6 +236,7 @@ export default class BaseAnalyticsAPI<
|
||||
let query: Query<AnalyticsDataModel> = {};
|
||||
let select: Select<AnalyticsDataModel> = {};
|
||||
let sort: Sort<AnalyticsDataModel> = {};
|
||||
let groupBy: GroupBy<AnalyticsDataModel> = {};
|
||||
|
||||
if (req.body) {
|
||||
query = JSONFunctions.deserialize(
|
||||
@@ -248,6 +250,10 @@ export default class BaseAnalyticsAPI<
|
||||
sort = JSONFunctions.deserialize(
|
||||
req.body['sort']
|
||||
) as Sort<AnalyticsDataModel>;
|
||||
|
||||
groupBy = JSONFunctions.deserialize(
|
||||
req.body['groupBy']
|
||||
) as GroupBy<AnalyticsDataModel>;
|
||||
}
|
||||
|
||||
const databaseProps: DatabaseCommonInteractionProps =
|
||||
@@ -259,11 +265,13 @@ export default class BaseAnalyticsAPI<
|
||||
skip: skip,
|
||||
limit: limit,
|
||||
sort: sort,
|
||||
groupBy: groupBy,
|
||||
props: databaseProps,
|
||||
});
|
||||
|
||||
const count: PositiveNumber = await this.service.countBy({
|
||||
query,
|
||||
groupBy: groupBy,
|
||||
props: databaseProps,
|
||||
});
|
||||
|
||||
|
||||
@@ -1018,9 +1018,8 @@ export default class StatusPageAPI extends BaseAPI<
|
||||
},
|
||||
select: scheduledEventsSelect,
|
||||
sort: {
|
||||
createdAt: SortOrder.Ascending,
|
||||
startsAt: SortOrder.Ascending,
|
||||
},
|
||||
|
||||
skip: 0,
|
||||
limit: LIMIT_PER_PROJECT,
|
||||
props: {
|
||||
@@ -1039,9 +1038,8 @@ export default class StatusPageAPI extends BaseAPI<
|
||||
},
|
||||
select: scheduledEventsSelect,
|
||||
sort: {
|
||||
createdAt: SortOrder.Ascending,
|
||||
startsAt: SortOrder.Ascending,
|
||||
},
|
||||
|
||||
skip: 0,
|
||||
limit: LIMIT_PER_PROJECT,
|
||||
props: {
|
||||
|
||||
@@ -320,6 +320,7 @@ export default class AnalyticsDatabaseService<
|
||||
|
||||
const databaseName: string =
|
||||
this.database.getDatasourceOptions().database!;
|
||||
|
||||
const whereStatement: Statement =
|
||||
this.statementGenerator.toWhereStatement(countBy.query);
|
||||
|
||||
@@ -331,6 +332,15 @@ export default class AnalyticsDatabaseService<
|
||||
WHERE TRUE `.append(whereStatement);
|
||||
/* eslint-enable prettier/prettier */
|
||||
|
||||
if (countBy.groupBy && Object.keys(countBy.groupBy).length > 0) {
|
||||
statement.append(
|
||||
SQL`
|
||||
GROUP BY `.append(
|
||||
this.statementGenerator.toGroupByStatement(countBy.groupBy)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (countBy.limit) {
|
||||
statement.append(SQL`
|
||||
LIMIT ${{
|
||||
@@ -364,29 +374,72 @@ export default class AnalyticsDatabaseService<
|
||||
|
||||
const databaseName: string =
|
||||
this.database.getDatasourceOptions().database!;
|
||||
let groupByStatement: Statement | null = null;
|
||||
|
||||
if (findBy.groupBy && Object.keys(findBy.groupBy).length > 0) {
|
||||
// overwrite select object
|
||||
findBy.select = {
|
||||
...findBy.groupBy,
|
||||
};
|
||||
|
||||
groupByStatement = this.statementGenerator.toGroupByStatement(
|
||||
findBy.groupBy
|
||||
);
|
||||
}
|
||||
|
||||
const select: { statement: Statement; columns: Array<string> } =
|
||||
this.statementGenerator.toSelectStatement(findBy.select!);
|
||||
|
||||
const whereStatement: Statement =
|
||||
this.statementGenerator.toWhereStatement(findBy.query);
|
||||
|
||||
const sortStatement: Statement =
|
||||
this.statementGenerator.toSortStatement(findBy.sort!);
|
||||
|
||||
/* eslint-disable prettier/prettier */
|
||||
const statement: Statement = SQL`
|
||||
SELECT `.append(select.statement).append(SQL`
|
||||
FROM ${databaseName}.${this.model.tableName}
|
||||
WHERE TRUE `).append(whereStatement).append(SQL`
|
||||
ORDER BY `).append(sortStatement).append(SQL`
|
||||
const statement: Statement = SQL``;
|
||||
|
||||
statement.append(
|
||||
SQL`
|
||||
SELECT `.append(select.statement)
|
||||
);
|
||||
statement.append(SQL`
|
||||
FROM ${databaseName}.${this.model.tableName}`);
|
||||
statement
|
||||
.append(
|
||||
SQL`
|
||||
WHERE TRUE `
|
||||
)
|
||||
.append(whereStatement);
|
||||
|
||||
if (groupByStatement) {
|
||||
statement
|
||||
.append(
|
||||
SQL`
|
||||
GROUP BY `
|
||||
)
|
||||
.append(groupByStatement);
|
||||
}
|
||||
|
||||
statement
|
||||
.append(
|
||||
SQL`
|
||||
ORDER BY `
|
||||
)
|
||||
.append(sortStatement);
|
||||
|
||||
statement.append(SQL`
|
||||
LIMIT ${{
|
||||
value: Number(findBy.limit),
|
||||
type: TableColumnType.Number,
|
||||
}}
|
||||
}}`);
|
||||
|
||||
statement.append(SQL`
|
||||
OFFSET ${{
|
||||
value: Number(findBy.skip),
|
||||
type: TableColumnType.Number,
|
||||
}}
|
||||
`);
|
||||
|
||||
/* eslint-enable prettier/prettier */
|
||||
|
||||
logger.info(`${this.model.tableName} Find Statement`);
|
||||
|
||||
@@ -809,9 +809,16 @@ class DatabaseService<TBaseModel extends BaseModel> extends BaseService {
|
||||
skip,
|
||||
limit,
|
||||
props,
|
||||
groupBy,
|
||||
distinctOn,
|
||||
}: CountBy<TBaseModel>): Promise<PositiveNumber> {
|
||||
try {
|
||||
if (groupBy && Object.keys(groupBy).length > 0) {
|
||||
throw new BadDataException(
|
||||
'Group By is not supported for countBy'
|
||||
);
|
||||
}
|
||||
|
||||
if (!skip) {
|
||||
skip = new PositiveNumber(0);
|
||||
}
|
||||
@@ -1130,6 +1137,15 @@ class DatabaseService<TBaseModel extends BaseModel> extends BaseService {
|
||||
onBeforeFind.limit = new PositiveNumber(onBeforeFind.limit);
|
||||
}
|
||||
|
||||
if (
|
||||
onBeforeFind.groupBy &&
|
||||
Object.keys(onBeforeFind.groupBy).length > 0
|
||||
) {
|
||||
throw new BadDataException(
|
||||
'GroupBy is currently not supported'
|
||||
);
|
||||
}
|
||||
|
||||
const items: Array<TBaseModel> = await this.getRepository().find({
|
||||
skip: onBeforeFind.skip.toNumber(),
|
||||
take: onBeforeFind.limit.toNumber(),
|
||||
|
||||
@@ -196,13 +196,14 @@ describe('StatementGenerator', () => {
|
||||
test('should SELECT multiple columns', () => {
|
||||
const { statement, columns } = generator.toSelectStatement({
|
||||
_id: true,
|
||||
createdAt: false,
|
||||
createdAt: true,
|
||||
updatedAt: true,
|
||||
});
|
||||
expect(statement.query).toBe('{p0:Identifier}, {p1:Identifier}');
|
||||
expect(statement.query_params).toStrictEqual({
|
||||
p0: '_id',
|
||||
p1: 'updatedAt',
|
||||
p1: 'createdAt',
|
||||
p2: 'updatedAt',
|
||||
});
|
||||
expect(columns).toStrictEqual(['_id', 'updatedAt']);
|
||||
});
|
||||
|
||||
@@ -2,10 +2,12 @@ import AnalyticsBaseModel from 'Common/AnalyticsModels/BaseModel';
|
||||
import PositiveNumber from 'Common/Types/PositiveNumber';
|
||||
import DatabaseCommonInteractionProps from 'Common/Types/BaseDatabase/DatabaseCommonInteractionProps';
|
||||
import Query from './Query';
|
||||
import GroupBy from './GroupBy';
|
||||
|
||||
export default interface CountBy<TBaseModel extends AnalyticsBaseModel> {
|
||||
query: Query<TBaseModel>;
|
||||
skip?: PositiveNumber | number;
|
||||
limit?: PositiveNumber | number;
|
||||
groupBy?: GroupBy<TBaseModel> | undefined;
|
||||
props: DatabaseCommonInteractionProps;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import GroupBy from './GroupBy';
|
||||
import Query from './Query';
|
||||
import Select from './Select';
|
||||
import Sort from './Sort';
|
||||
@@ -8,5 +9,6 @@ export default interface FindOneBy<TBaseModel extends BaseModel> {
|
||||
query: Query<TBaseModel>;
|
||||
select?: Select<TBaseModel> | undefined;
|
||||
sort?: Sort<TBaseModel> | undefined;
|
||||
groupBy?: GroupBy<TBaseModel> | undefined;
|
||||
props: DatabaseCommonInteractionProps;
|
||||
}
|
||||
|
||||
8
CommonServer/Types/AnalyticsDatabase/GroupBy.ts
Normal file
8
CommonServer/Types/AnalyticsDatabase/GroupBy.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
/**
|
||||
* GroupBy find options.
|
||||
*/
|
||||
declare type GroupBy<Entity> = {
|
||||
[P in keyof Entity]?: true;
|
||||
};
|
||||
|
||||
export default GroupBy;
|
||||
@@ -1,7 +1,7 @@
|
||||
import AnalyticsBaseModel from 'Common/AnalyticsModels/BaseModel';
|
||||
import Dictionary from 'Common/Types/Dictionary';
|
||||
|
||||
export type SelectPropertyOptions = boolean | Dictionary<boolean>;
|
||||
export type SelectPropertyOptions = true | Dictionary<true>;
|
||||
|
||||
/**
|
||||
* Select find options.
|
||||
|
||||
@@ -2,10 +2,12 @@ import BaseModel from 'Common/Models/BaseModel';
|
||||
import PositiveNumber from 'Common/Types/PositiveNumber';
|
||||
import DatabaseCommonInteractionProps from 'Common/Types/BaseDatabase/DatabaseCommonInteractionProps';
|
||||
import Query from './Query';
|
||||
import GroupBy from './GroupBy';
|
||||
|
||||
export default interface CountBy<TBaseModel extends BaseModel> {
|
||||
query: Query<TBaseModel>;
|
||||
skip?: PositiveNumber | number;
|
||||
groupBy?: GroupBy<TBaseModel> | undefined;
|
||||
limit?: PositiveNumber | number;
|
||||
props: DatabaseCommonInteractionProps;
|
||||
distinctOn?: string | undefined;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import GroupBy from './GroupBy';
|
||||
import Query from './Query';
|
||||
import Select from './Select';
|
||||
import Sort from './Sort';
|
||||
@@ -8,5 +9,6 @@ export default interface FindOneBy<TBaseModel extends BaseModel> {
|
||||
query: Query<TBaseModel>;
|
||||
select?: Select<TBaseModel> | undefined;
|
||||
sort?: Sort<TBaseModel> | undefined;
|
||||
groupBy?: GroupBy<TBaseModel> | undefined;
|
||||
props: DatabaseCommonInteractionProps;
|
||||
}
|
||||
|
||||
8
CommonServer/Types/Database/GroupBy.ts
Normal file
8
CommonServer/Types/Database/GroupBy.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
/**
|
||||
* GroupBy find options.
|
||||
*/
|
||||
declare type GroupBy<Entity> = {
|
||||
[P in keyof Entity]?: true;
|
||||
};
|
||||
|
||||
export default GroupBy;
|
||||
@@ -24,6 +24,7 @@ import GreaterThanOrEqual from 'Common/Types/BaseDatabase/GreaterThanOrEqual';
|
||||
import InBetween from 'Common/Types/BaseDatabase/InBetween';
|
||||
import IsNull from 'Common/Types/BaseDatabase/IsNull';
|
||||
import Includes from 'Common/Types/BaseDatabase/Includes';
|
||||
import GroupBy from '../../Types/AnalyticsDatabase/GroupBy';
|
||||
// import JSONFunctions from 'Common/Types/JSONFunctions';
|
||||
// import { JSONObject } from 'Common/Types/JSON';
|
||||
|
||||
@@ -471,6 +472,22 @@ export default class StatementGenerator<TBaseModel extends AnalyticsBaseModel> {
|
||||
return whereStatement;
|
||||
}
|
||||
|
||||
public toGroupByStatement(groupBy: GroupBy<TBaseModel>): Statement {
|
||||
const groupByStatement: Statement = new Statement();
|
||||
|
||||
let first: boolean = true;
|
||||
for (const key in groupBy) {
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
groupByStatement.append(SQL`, `);
|
||||
}
|
||||
groupByStatement.append(SQL`${key}`);
|
||||
}
|
||||
|
||||
return groupByStatement;
|
||||
}
|
||||
|
||||
public toSortStatement(sort: Sort<TBaseModel>): Statement {
|
||||
const sortStatement: Statement = new Statement();
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ import Sort from '../../Utils/BaseDatabase/Sort';
|
||||
import RequestOptions from '../../Utils/BaseDatabase/RequestOptions';
|
||||
import NotImplementedException from 'Common/Types/Exception/NotImplementedException';
|
||||
import { BaseModelType } from 'Common/Models/BaseModel';
|
||||
import GroupBy from '../../Utils/BaseDatabase/GroupBy';
|
||||
|
||||
export interface ComponentProps<TBaseModel extends AnalyticsBaseModel>
|
||||
extends BaseTableProps<TBaseModel> {
|
||||
@@ -71,6 +72,7 @@ const AnalyticsModelTable: <TBaseModel extends AnalyticsBaseModel>(
|
||||
getList: async (data: {
|
||||
modelType: BaseModelType | AnalyticsBaseModelType;
|
||||
query: Query<TBaseModel>;
|
||||
groupBy?: GroupBy<TBaseModel> | undefined;
|
||||
limit: number;
|
||||
skip: number;
|
||||
sort: Sort<TBaseModel>;
|
||||
@@ -80,6 +82,7 @@ const AnalyticsModelTable: <TBaseModel extends AnalyticsBaseModel>(
|
||||
return await modelAPI.getList<TBaseModel>({
|
||||
modelType: data.modelType as { new (): TBaseModel },
|
||||
query: data.query,
|
||||
groupBy: data.groupBy,
|
||||
limit: data.limit,
|
||||
skip: data.skip,
|
||||
sort: data.sort,
|
||||
|
||||
@@ -77,6 +77,7 @@ import SelectEntityField from '../../Types/SelectEntityField';
|
||||
import { FilterData } from '../Filters/Filter';
|
||||
import ClassicFilterType from '../Filters/Types/Filter';
|
||||
import { getRefreshButton } from '../Card/CardButtons/Refresh';
|
||||
import GroupBy from '../../Utils/BaseDatabase/GroupBy';
|
||||
|
||||
export enum ShowAs {
|
||||
Table,
|
||||
@@ -94,6 +95,7 @@ export interface BaseTableCallbacks<
|
||||
getList: (data: {
|
||||
modelType: BaseModelType | AnalyticsBaseModelType;
|
||||
query: Query<TBaseModel>;
|
||||
groupBy?: GroupBy<TBaseModel> | undefined;
|
||||
limit: number;
|
||||
skip: number;
|
||||
sort: Sort<TBaseModel>;
|
||||
@@ -148,6 +150,7 @@ export interface BaseTableProps<
|
||||
viewPageRoute?: undefined | Route;
|
||||
onViewPage?: (item: TBaseModel) => Promise<Route>;
|
||||
query?: Query<TBaseModel>;
|
||||
groupBy?: GroupBy<TBaseModel> | undefined;
|
||||
onBeforeFetch?: (() => Promise<TBaseModel>) | undefined;
|
||||
createInitialValues?: FormValues<TBaseModel> | undefined;
|
||||
onBeforeCreate?:
|
||||
@@ -611,6 +614,9 @@ const BaseModelTable: <TBaseModel extends BaseModel | AnalyticsBaseModel>(
|
||||
...query,
|
||||
...props.query,
|
||||
},
|
||||
groupBy: {
|
||||
...props.groupBy,
|
||||
},
|
||||
limit: itemsOnPage,
|
||||
skip: (currentPageNumber - 1) * itemsOnPage,
|
||||
select: {
|
||||
|
||||
@@ -11,6 +11,7 @@ import Sort from '../../Utils/BaseDatabase/Sort';
|
||||
import ModelFormModal from '../ModelFormModal/ModelFormModal';
|
||||
import { FormType } from '../Forms/ModelForm';
|
||||
import { AnalyticsBaseModelType } from 'Common/AnalyticsModels/BaseModel';
|
||||
import GroupBy from '../../Utils/BaseDatabase/GroupBy';
|
||||
|
||||
export interface ComponentProps<TBaseModel extends BaseModel>
|
||||
extends BaseTableProps<TBaseModel> {
|
||||
@@ -53,6 +54,7 @@ const ModelTable: <TBaseModel extends BaseModel>(
|
||||
getList: async (data: {
|
||||
modelType: BaseModelType | AnalyticsBaseModelType;
|
||||
query: Query<TBaseModel>;
|
||||
groupBy?: GroupBy<TBaseModel> | undefined;
|
||||
limit: number;
|
||||
skip: number;
|
||||
sort: Sort<TBaseModel>;
|
||||
@@ -63,6 +65,7 @@ const ModelTable: <TBaseModel extends BaseModel>(
|
||||
modelType: data.modelType as { new (): TBaseModel },
|
||||
query: data.query,
|
||||
limit: data.limit,
|
||||
groupBy: data.groupBy,
|
||||
skip: data.skip,
|
||||
sort: data.sort,
|
||||
select: data.select,
|
||||
|
||||
@@ -20,6 +20,7 @@ import Project from 'Model/Models/Project';
|
||||
import Navigation from '../Navigation';
|
||||
import BaseListResult from '../BaseDatabase/ListResult';
|
||||
import RequestOptions from '../BaseDatabase/RequestOptions';
|
||||
import GroupBy from '../BaseDatabase/GroupBy';
|
||||
|
||||
export interface ListResult<TAnalyticsBaseModel extends AnalyticsBaseModel>
|
||||
extends BaseListResult<TAnalyticsBaseModel> {}
|
||||
@@ -200,14 +201,23 @@ export default class ModelAPI {
|
||||
>(data: {
|
||||
modelType: { new (): TAnalyticsBaseModel };
|
||||
query: Query<TAnalyticsBaseModel>;
|
||||
groupBy?: GroupBy<TAnalyticsBaseModel> | undefined;
|
||||
limit: number;
|
||||
skip: number;
|
||||
select: Select<TAnalyticsBaseModel>;
|
||||
sort: Sort<TAnalyticsBaseModel>;
|
||||
requestOptions?: RequestOptions | undefined;
|
||||
}): Promise<ListResult<TAnalyticsBaseModel>> {
|
||||
const { modelType, query, limit, skip, select, sort, requestOptions } =
|
||||
data;
|
||||
const {
|
||||
modelType,
|
||||
query,
|
||||
limit,
|
||||
skip,
|
||||
select,
|
||||
sort,
|
||||
requestOptions,
|
||||
groupBy,
|
||||
} = data;
|
||||
|
||||
const model: TAnalyticsBaseModel = new modelType();
|
||||
const apiPath: Route | null = model.crudApiPath;
|
||||
@@ -242,6 +252,7 @@ export default class ModelAPI {
|
||||
query: JSONFunctions.serialize(query as JSONObject),
|
||||
select: JSONFunctions.serialize(select as JSONObject),
|
||||
sort: JSONFunctions.serialize(sort as JSONObject),
|
||||
groupBy: JSONFunctions.serialize(groupBy as JSONObject),
|
||||
},
|
||||
headers,
|
||||
{
|
||||
|
||||
9
CommonUI/src/Utils/BaseDatabase/GroupBy.ts
Normal file
9
CommonUI/src/Utils/BaseDatabase/GroupBy.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import AnalyticsDataModel from 'Common/AnalyticsModels/BaseModel';
|
||||
import BaseModel from 'Common/Models/BaseModel';
|
||||
import { JSONObject } from 'Common/Types/JSON';
|
||||
|
||||
type GroupBy<TBaseModel extends AnalyticsDataModel | BaseModel | JSONObject> = {
|
||||
[P in keyof TBaseModel]?: true;
|
||||
};
|
||||
|
||||
export default GroupBy;
|
||||
@@ -20,6 +20,7 @@ import Project from 'Model/Models/Project';
|
||||
import Navigation from '../Navigation';
|
||||
import BaseListResult from '../BaseDatabase/ListResult';
|
||||
import BaseRequestOptions from '../BaseDatabase/RequestOptions';
|
||||
import GroupBy from '../BaseDatabase/GroupBy';
|
||||
|
||||
export class ModelAPIHttpResponse<
|
||||
TBaseModel extends BaseModel
|
||||
@@ -184,6 +185,7 @@ export default class ModelAPI {
|
||||
public static async getList<TBaseModel extends BaseModel>(data: {
|
||||
modelType: { new (): TBaseModel };
|
||||
query: Query<TBaseModel>;
|
||||
groupBy?: GroupBy<TBaseModel> | undefined;
|
||||
limit: number;
|
||||
skip: number;
|
||||
select: Select<TBaseModel>;
|
||||
@@ -227,6 +229,9 @@ export default class ModelAPI {
|
||||
query: JSONFunctions.serialize(data.query as JSONObject),
|
||||
select: JSONFunctions.serialize(data.select as JSONObject),
|
||||
sort: JSONFunctions.serialize(data.sort as JSONObject),
|
||||
groupBy: JSONFunctions.serialize(
|
||||
data.groupBy as JSONObject
|
||||
),
|
||||
},
|
||||
headers,
|
||||
{
|
||||
|
||||
@@ -1,13 +1,71 @@
|
||||
import React, { Fragment, FunctionComponent, ReactElement } from 'react';
|
||||
import PageComponentProps from '../../../../PageComponentProps';
|
||||
import ComingSoon from 'CommonUI/src/Components/ComingSoon/ComingSoon';
|
||||
import AnalyticsModelTable from 'CommonUI/src/Components/ModelTable/AnalyticsModelTable';
|
||||
import Metric from 'Model/AnalyticsModels/Metric';
|
||||
import DashboardNavigation from '../../../../../Utils/Navigation';
|
||||
import Navigation from 'CommonUI/src/Utils/Navigation';
|
||||
import ObjectID from 'Common/Types/ObjectID';
|
||||
import FieldType from 'CommonUI/src/Components/Types/FieldType';
|
||||
import Route from 'Common/Types/API/Route';
|
||||
import SortOrder from 'Common/Types/BaseDatabase/SortOrder';
|
||||
|
||||
const ServiceDelete: FunctionComponent<PageComponentProps> = (
|
||||
_props: PageComponentProps
|
||||
): ReactElement => {
|
||||
const modelId: ObjectID = Navigation.getLastParamAsObjectID(1);
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<ComingSoon />
|
||||
<AnalyticsModelTable<Metric>
|
||||
modelType={Metric}
|
||||
id="metrics-table"
|
||||
isDeleteable={false}
|
||||
isEditable={false}
|
||||
isCreateable={false}
|
||||
singularName="Metric"
|
||||
pluralName="Metrics"
|
||||
name="Metrics"
|
||||
isViewable={true}
|
||||
sortBy="name"
|
||||
sortOrder={SortOrder.Ascending}
|
||||
cardProps={{
|
||||
title: 'Metrics',
|
||||
description:
|
||||
'Metrics are the individual data points that make up a service. They are the building blocks of a service and represent the work done by a single service.',
|
||||
}}
|
||||
groupBy={{
|
||||
name: true,
|
||||
}}
|
||||
onViewPage={async (_item: Metric) => {
|
||||
return Promise.resolve(new Route(''));
|
||||
}}
|
||||
query={{
|
||||
projectId: DashboardNavigation.getProjectId(),
|
||||
serviceId: modelId,
|
||||
}}
|
||||
showViewIdButton={false}
|
||||
noItemsMessage={'No metrics found for this service.'}
|
||||
showRefreshButton={true}
|
||||
viewPageRoute={Navigation.getCurrentRoute()}
|
||||
filters={[
|
||||
{
|
||||
field: {
|
||||
name: true,
|
||||
},
|
||||
title: 'Name',
|
||||
type: FieldType.Text,
|
||||
},
|
||||
]}
|
||||
columns={[
|
||||
{
|
||||
field: {
|
||||
name: true,
|
||||
},
|
||||
title: 'Name',
|
||||
type: FieldType.Text,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -15,6 +15,32 @@ export default class Metric extends AnalyticsBaseModel {
|
||||
singularName: 'Metric',
|
||||
pluralName: 'Metrics',
|
||||
crudApiPath: new Route('/metrics'),
|
||||
accessControl: {
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CanReadTelemetryServiceTraces,
|
||||
],
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CanCreateTelemetryServiceTraces,
|
||||
],
|
||||
update: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CanEditTelemetryServiceTraces,
|
||||
],
|
||||
delete: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CanDeleteTelemetryServiceTraces,
|
||||
],
|
||||
},
|
||||
tableColumns: [
|
||||
new AnalyticsTableColumn({
|
||||
key: 'projectId',
|
||||
|
||||
Reference in New Issue
Block a user