mirror of
https://github.com/OneUptime/oneuptime.git
synced 2026-04-06 00:32:12 +02:00
Add usage history page to settings menu
This commit is contained in:
@@ -12,6 +12,7 @@ export class Service extends DatabaseService<Model> {
|
||||
|
||||
public constructor(postgresDatabase?: PostgresDatabase) {
|
||||
super(Model, postgresDatabase);
|
||||
this.hardDeleteItemsOlderThanInDays('createdAt', 120);
|
||||
}
|
||||
|
||||
public async getUnreportedUsageBilling(data: { projectId: ObjectID; productType: ProductType; }): Promise<Model[]> {
|
||||
|
||||
@@ -295,6 +295,17 @@ const DashboardSideMenu: () => JSX.Element = (): ReactElement => {
|
||||
}}
|
||||
icon={IconProp.Billing}
|
||||
/>
|
||||
<SideMenuItem
|
||||
link={{
|
||||
title: 'Usage History',
|
||||
to: RouteUtil.populateRouteParams(
|
||||
RouteMap[
|
||||
PageMap.SETTINGS_USAGE_HISTORY
|
||||
] as Route
|
||||
),
|
||||
}}
|
||||
icon={IconProp.ChartBar}
|
||||
/>
|
||||
<SideMenuItem
|
||||
link={{
|
||||
title: 'Invoices',
|
||||
|
||||
115
Dashboard/src/Pages/Settings/UsageHistory.tsx
Normal file
115
Dashboard/src/Pages/Settings/UsageHistory.tsx
Normal file
@@ -0,0 +1,115 @@
|
||||
import Route from 'Common/Types/API/Route';
|
||||
import { JSONObject } from 'Common/Types/JSON';
|
||||
import ModelTable from 'CommonUI/src/Components/ModelTable/ModelTable';
|
||||
import Page from 'CommonUI/src/Components/Page/Page';
|
||||
import React, { FunctionComponent, ReactElement } from 'react';
|
||||
import PageMap from '../../Utils/PageMap';
|
||||
import RouteMap, { RouteUtil } from '../../Utils/RouteMap';
|
||||
import PageComponentProps from '../PageComponentProps';
|
||||
import DashboardSideMenu from './SideMenu';
|
||||
import UsageBilling from 'Model/Models/UsageBilling';
|
||||
import FieldType from 'CommonUI/src/Components/Types/FieldType';
|
||||
import DashboardNavigation from '../../Utils/Navigation';
|
||||
|
||||
export interface ComponentProps extends PageComponentProps { }
|
||||
|
||||
const Settings: FunctionComponent<ComponentProps> = (
|
||||
_props: ComponentProps
|
||||
): ReactElement => {
|
||||
|
||||
return (
|
||||
<Page
|
||||
title={'Project Settings'}
|
||||
breadcrumbLinks={[
|
||||
{
|
||||
title: 'Project',
|
||||
to: RouteUtil.populateRouteParams(
|
||||
RouteMap[PageMap.HOME] as Route
|
||||
),
|
||||
},
|
||||
{
|
||||
title: 'Settings',
|
||||
to: RouteUtil.populateRouteParams(
|
||||
RouteMap[PageMap.SETTINGS] as Route
|
||||
),
|
||||
},
|
||||
{
|
||||
title: 'Usage History',
|
||||
to: RouteUtil.populateRouteParams(
|
||||
RouteMap[PageMap.SETTINGS_USAGE_HISTORY] as Route
|
||||
),
|
||||
},
|
||||
]}
|
||||
sideMenu={<DashboardSideMenu />}
|
||||
>
|
||||
|
||||
|
||||
|
||||
<ModelTable<UsageBilling>
|
||||
modelType={UsageBilling}
|
||||
id="usage-history-table"
|
||||
isDeleteable={false}
|
||||
name="Settings > Billing > Usage History"
|
||||
isEditable={false}
|
||||
isCreateable={false}
|
||||
isViewable={false}
|
||||
cardProps={{
|
||||
title: 'Usage History',
|
||||
description:
|
||||
'Here is the usage history for this project.',
|
||||
}}
|
||||
noItemsMessage={'No usage history found. Maybe you have not used Telemetry features yet?'}
|
||||
query={{
|
||||
projectId:
|
||||
DashboardNavigation.getProjectId()?.toString(),
|
||||
}}
|
||||
showRefreshButton={true}
|
||||
showFilterButton={false}
|
||||
selectMoreFields={{
|
||||
usageUnitName: true,
|
||||
}}
|
||||
columns={[
|
||||
{
|
||||
field: {
|
||||
productType: true,
|
||||
},
|
||||
title: 'Product',
|
||||
type: FieldType.Text,
|
||||
isFilterable: true,
|
||||
},
|
||||
{
|
||||
field: {
|
||||
createdAt: true,
|
||||
},
|
||||
title: 'Day',
|
||||
type: FieldType.Date,
|
||||
isFilterable: true,
|
||||
},
|
||||
{
|
||||
field: {
|
||||
usageCount: true,
|
||||
},
|
||||
title: 'Usage',
|
||||
type: FieldType.Text,
|
||||
getElement: (item: JSONObject) => {
|
||||
return <div>{`${item['usageCount'] as string} ${item['usageUnitName'] as string}`}</div>;
|
||||
},
|
||||
},
|
||||
{
|
||||
field: {
|
||||
totalCostInUSD: true,
|
||||
},
|
||||
title: 'Total Cost',
|
||||
type: FieldType.Text,
|
||||
getElement: (item: JSONObject) => {
|
||||
return <div>{`${item['totalCostInUSD'] as string} USD`}</div>;
|
||||
},
|
||||
},
|
||||
]}
|
||||
/>
|
||||
|
||||
</Page>
|
||||
);
|
||||
};
|
||||
|
||||
export default Settings;
|
||||
@@ -160,6 +160,13 @@ const ScheduledMaintenanceNoteTemplateView: LazyExoticComponent<
|
||||
return import('../Pages/Settings/ScheduledMaintenanceNoteTemplateView');
|
||||
});
|
||||
|
||||
const SettingsUsageHistory: LazyExoticComponent<
|
||||
FunctionComponent<ComponentProps>
|
||||
> = lazy(() => {
|
||||
return import('../Pages/Settings/UsageHistory');
|
||||
});
|
||||
|
||||
|
||||
const SettingsRoutes: FunctionComponent<ComponentProps> = (
|
||||
props: ComponentProps
|
||||
): ReactElement => {
|
||||
@@ -201,7 +208,7 @@ const SettingsRoutes: FunctionComponent<ComponentProps> = (
|
||||
{...props}
|
||||
pageRoute={
|
||||
RouteMap[
|
||||
PageMap.SETTINGS_INCIDENT_TEMPLATES
|
||||
PageMap.SETTINGS_INCIDENT_TEMPLATES
|
||||
] as Route
|
||||
}
|
||||
/>
|
||||
@@ -212,7 +219,7 @@ const SettingsRoutes: FunctionComponent<ComponentProps> = (
|
||||
<PageRoute
|
||||
path={
|
||||
SettingsRoutePath[
|
||||
PageMap.SETTINGS_INCIDENT_TEMPLATES_VIEW
|
||||
PageMap.SETTINGS_INCIDENT_TEMPLATES_VIEW
|
||||
] || ''
|
||||
}
|
||||
element={
|
||||
@@ -221,7 +228,28 @@ const SettingsRoutes: FunctionComponent<ComponentProps> = (
|
||||
{...props}
|
||||
pageRoute={
|
||||
RouteMap[
|
||||
PageMap.SETTINGS_INCIDENT_TEMPLATES_VIEW
|
||||
PageMap.SETTINGS_INCIDENT_TEMPLATES_VIEW
|
||||
] as Route
|
||||
}
|
||||
/>
|
||||
</Suspense>
|
||||
}
|
||||
/>
|
||||
|
||||
|
||||
<PageRoute
|
||||
path={
|
||||
SettingsRoutePath[
|
||||
PageMap.SETTINGS_USAGE_HISTORY
|
||||
] || ''
|
||||
}
|
||||
element={
|
||||
<Suspense fallback={Loader}>
|
||||
<SettingsUsageHistory
|
||||
{...props}
|
||||
pageRoute={
|
||||
RouteMap[
|
||||
PageMap.SETTINGS_USAGE_HISTORY
|
||||
] as Route
|
||||
}
|
||||
/>
|
||||
@@ -237,7 +265,7 @@ const SettingsRoutes: FunctionComponent<ComponentProps> = (
|
||||
{...props}
|
||||
pageRoute={
|
||||
RouteMap[
|
||||
PageMap.SETTINGS_FEATURE_FLAGS
|
||||
PageMap.SETTINGS_FEATURE_FLAGS
|
||||
] as Route
|
||||
}
|
||||
/>
|
||||
@@ -248,7 +276,7 @@ const SettingsRoutes: FunctionComponent<ComponentProps> = (
|
||||
<PageRoute
|
||||
path={
|
||||
SettingsRoutePath[
|
||||
PageMap.SETTINGS_INCIDENT_NOTE_TEMPLATES
|
||||
PageMap.SETTINGS_INCIDENT_NOTE_TEMPLATES
|
||||
] || ''
|
||||
}
|
||||
element={
|
||||
@@ -257,7 +285,7 @@ const SettingsRoutes: FunctionComponent<ComponentProps> = (
|
||||
{...props}
|
||||
pageRoute={
|
||||
RouteMap[
|
||||
PageMap.SETTINGS_INCIDENT_NOTE_TEMPLATES
|
||||
PageMap.SETTINGS_INCIDENT_NOTE_TEMPLATES
|
||||
] as Route
|
||||
}
|
||||
/>
|
||||
@@ -268,7 +296,7 @@ const SettingsRoutes: FunctionComponent<ComponentProps> = (
|
||||
<PageRoute
|
||||
path={
|
||||
SettingsRoutePath[
|
||||
PageMap.SETTINGS_INCIDENT_NOTE_TEMPLATES_VIEW
|
||||
PageMap.SETTINGS_INCIDENT_NOTE_TEMPLATES_VIEW
|
||||
] || ''
|
||||
}
|
||||
element={
|
||||
@@ -277,8 +305,8 @@ const SettingsRoutes: FunctionComponent<ComponentProps> = (
|
||||
{...props}
|
||||
pageRoute={
|
||||
RouteMap[
|
||||
PageMap
|
||||
.SETTINGS_INCIDENT_NOTE_TEMPLATES_VIEW
|
||||
PageMap
|
||||
.SETTINGS_INCIDENT_NOTE_TEMPLATES_VIEW
|
||||
] as Route
|
||||
}
|
||||
/>
|
||||
@@ -289,7 +317,7 @@ const SettingsRoutes: FunctionComponent<ComponentProps> = (
|
||||
<PageRoute
|
||||
path={
|
||||
SettingsRoutePath[
|
||||
PageMap.SETTINGS_SCHEDULED_MAINTENANCE_NOTE_TEMPLATES
|
||||
PageMap.SETTINGS_SCHEDULED_MAINTENANCE_NOTE_TEMPLATES
|
||||
] || ''
|
||||
}
|
||||
element={
|
||||
@@ -298,8 +326,8 @@ const SettingsRoutes: FunctionComponent<ComponentProps> = (
|
||||
{...props}
|
||||
pageRoute={
|
||||
RouteMap[
|
||||
PageMap
|
||||
.SETTINGS_SCHEDULED_MAINTENANCE_NOTE_TEMPLATES
|
||||
PageMap
|
||||
.SETTINGS_SCHEDULED_MAINTENANCE_NOTE_TEMPLATES
|
||||
] as Route
|
||||
}
|
||||
/>
|
||||
@@ -310,8 +338,8 @@ const SettingsRoutes: FunctionComponent<ComponentProps> = (
|
||||
<PageRoute
|
||||
path={
|
||||
SettingsRoutePath[
|
||||
PageMap
|
||||
.SETTINGS_SCHEDULED_MAINTENANCE_NOTE_TEMPLATES_VIEW
|
||||
PageMap
|
||||
.SETTINGS_SCHEDULED_MAINTENANCE_NOTE_TEMPLATES_VIEW
|
||||
] || ''
|
||||
}
|
||||
element={
|
||||
@@ -320,8 +348,8 @@ const SettingsRoutes: FunctionComponent<ComponentProps> = (
|
||||
{...props}
|
||||
pageRoute={
|
||||
RouteMap[
|
||||
PageMap
|
||||
.SETTINGS_SCHEDULED_MAINTENANCE_NOTE_TEMPLATES_VIEW
|
||||
PageMap
|
||||
.SETTINGS_SCHEDULED_MAINTENANCE_NOTE_TEMPLATES_VIEW
|
||||
] as Route
|
||||
}
|
||||
/>
|
||||
@@ -379,7 +407,7 @@ const SettingsRoutes: FunctionComponent<ComponentProps> = (
|
||||
{...props}
|
||||
pageRoute={
|
||||
RouteMap[
|
||||
PageMap.SETTINGS_MONITORS_STATUS
|
||||
PageMap.SETTINGS_MONITORS_STATUS
|
||||
] as Route
|
||||
}
|
||||
/>
|
||||
@@ -395,7 +423,7 @@ const SettingsRoutes: FunctionComponent<ComponentProps> = (
|
||||
{...props}
|
||||
pageRoute={
|
||||
RouteMap[
|
||||
PageMap.SETTINGS_INCIDENTS_STATE
|
||||
PageMap.SETTINGS_INCIDENTS_STATE
|
||||
] as Route
|
||||
}
|
||||
/>
|
||||
@@ -406,7 +434,7 @@ const SettingsRoutes: FunctionComponent<ComponentProps> = (
|
||||
<PageRoute
|
||||
path={
|
||||
SettingsRoutePath[
|
||||
PageMap.SETTINGS_SCHEDULED_MAINTENANCE_STATE
|
||||
PageMap.SETTINGS_SCHEDULED_MAINTENANCE_STATE
|
||||
] || ''
|
||||
}
|
||||
element={
|
||||
@@ -415,7 +443,7 @@ const SettingsRoutes: FunctionComponent<ComponentProps> = (
|
||||
{...props}
|
||||
pageRoute={
|
||||
RouteMap[
|
||||
PageMap.SETTINGS_SCHEDULED_MAINTENANCE_STATE
|
||||
PageMap.SETTINGS_SCHEDULED_MAINTENANCE_STATE
|
||||
] as Route
|
||||
}
|
||||
/>
|
||||
@@ -445,7 +473,7 @@ const SettingsRoutes: FunctionComponent<ComponentProps> = (
|
||||
{...props}
|
||||
pageRoute={
|
||||
RouteMap[
|
||||
PageMap.SETTINGS_INCIDENTS_SEVERITY
|
||||
PageMap.SETTINGS_INCIDENTS_SEVERITY
|
||||
] as Route
|
||||
}
|
||||
/>
|
||||
@@ -520,7 +548,7 @@ const SettingsRoutes: FunctionComponent<ComponentProps> = (
|
||||
{...props}
|
||||
pageRoute={
|
||||
RouteMap[
|
||||
PageMap.SETTINGS_MONITOR_CUSTOM_FIELDS
|
||||
PageMap.SETTINGS_MONITOR_CUSTOM_FIELDS
|
||||
] as Route
|
||||
}
|
||||
/>
|
||||
@@ -531,7 +559,7 @@ const SettingsRoutes: FunctionComponent<ComponentProps> = (
|
||||
<PageRoute
|
||||
path={
|
||||
SettingsRoutePath[
|
||||
PageMap.SETTINGS_STATUS_PAGE_CUSTOM_FIELDS
|
||||
PageMap.SETTINGS_STATUS_PAGE_CUSTOM_FIELDS
|
||||
] || ''
|
||||
}
|
||||
element={
|
||||
@@ -540,7 +568,7 @@ const SettingsRoutes: FunctionComponent<ComponentProps> = (
|
||||
{...props}
|
||||
pageRoute={
|
||||
RouteMap[
|
||||
PageMap.SETTINGS_STATUS_PAGE_CUSTOM_FIELDS
|
||||
PageMap.SETTINGS_STATUS_PAGE_CUSTOM_FIELDS
|
||||
] as Route
|
||||
}
|
||||
/>
|
||||
@@ -551,7 +579,7 @@ const SettingsRoutes: FunctionComponent<ComponentProps> = (
|
||||
<PageRoute
|
||||
path={
|
||||
SettingsRoutePath[
|
||||
PageMap.SETTINGS_SCHEDULED_MAINTENANCE_CUSTOM_FIELDS
|
||||
PageMap.SETTINGS_SCHEDULED_MAINTENANCE_CUSTOM_FIELDS
|
||||
] || ''
|
||||
}
|
||||
element={
|
||||
@@ -560,8 +588,8 @@ const SettingsRoutes: FunctionComponent<ComponentProps> = (
|
||||
{...props}
|
||||
pageRoute={
|
||||
RouteMap[
|
||||
PageMap
|
||||
.SETTINGS_SCHEDULED_MAINTENANCE_CUSTOM_FIELDS
|
||||
PageMap
|
||||
.SETTINGS_SCHEDULED_MAINTENANCE_CUSTOM_FIELDS
|
||||
] as Route
|
||||
}
|
||||
/>
|
||||
@@ -572,7 +600,7 @@ const SettingsRoutes: FunctionComponent<ComponentProps> = (
|
||||
<PageRoute
|
||||
path={
|
||||
SettingsRoutePath[
|
||||
PageMap.SETTINGS_INCIDENT_CUSTOM_FIELDS
|
||||
PageMap.SETTINGS_INCIDENT_CUSTOM_FIELDS
|
||||
] || ''
|
||||
}
|
||||
element={
|
||||
@@ -581,7 +609,7 @@ const SettingsRoutes: FunctionComponent<ComponentProps> = (
|
||||
{...props}
|
||||
pageRoute={
|
||||
RouteMap[
|
||||
PageMap.SETTINGS_INCIDENT_CUSTOM_FIELDS
|
||||
PageMap.SETTINGS_INCIDENT_CUSTOM_FIELDS
|
||||
] as Route
|
||||
}
|
||||
/>
|
||||
@@ -592,7 +620,7 @@ const SettingsRoutes: FunctionComponent<ComponentProps> = (
|
||||
<PageRoute
|
||||
path={
|
||||
SettingsRoutePath[
|
||||
PageMap.SETTINGS_ON_CALL_DUTY_POLICY_CUSTOM_FIELDS
|
||||
PageMap.SETTINGS_ON_CALL_DUTY_POLICY_CUSTOM_FIELDS
|
||||
] || ''
|
||||
}
|
||||
element={
|
||||
@@ -601,8 +629,8 @@ const SettingsRoutes: FunctionComponent<ComponentProps> = (
|
||||
{...props}
|
||||
pageRoute={
|
||||
RouteMap[
|
||||
PageMap
|
||||
.SETTINGS_ON_CALL_DUTY_POLICY_CUSTOM_FIELDS
|
||||
PageMap
|
||||
.SETTINGS_ON_CALL_DUTY_POLICY_CUSTOM_FIELDS
|
||||
] as Route
|
||||
}
|
||||
/>
|
||||
@@ -634,7 +662,7 @@ const SettingsRoutes: FunctionComponent<ComponentProps> = (
|
||||
{...props}
|
||||
pageRoute={
|
||||
RouteMap[
|
||||
PageMap.SETTINGS_BILLING_INVOICES
|
||||
PageMap.SETTINGS_BILLING_INVOICES
|
||||
] as Route
|
||||
}
|
||||
/>
|
||||
|
||||
@@ -197,6 +197,7 @@ enum PageMap {
|
||||
|
||||
SETTINGS_BILLING = 'SETTINGS_BILLING',
|
||||
SETTINGS_BILLING_INVOICES = 'SETTINGS_BILLING_INVOICES',
|
||||
SETTINGS_USAGE_HISTORY = 'SETTINGS_USAGE_HISTORY',
|
||||
|
||||
// Featur Flags
|
||||
SETTINGS_FEATURE_FLAGS = 'SETTINGS_FEATURE_FLAGS',
|
||||
|
||||
@@ -123,6 +123,7 @@ export const SettingsRoutePath: Dictionary<string> = {
|
||||
[PageMap.SETTINGS_SCHEDULED_MAINTENANCE_NOTE_TEMPLATES_VIEW]: `scheduled-maintenance-note-templates/${RouteParams.ModelID}`,
|
||||
[PageMap.SETTINGS_BILLING]: 'billing',
|
||||
[PageMap.SETTINGS_BILLING_INVOICES]: 'invoices',
|
||||
[PageMap.SETTINGS_USAGE_HISTORY]: 'usage-history',
|
||||
[PageMap.SETTINGS_TEAM_VIEW]: `teams/${RouteParams.ModelID}`,
|
||||
[PageMap.SETTINGS_LABELS]: 'labels',
|
||||
[PageMap.SETTINGS_PROBES]: 'probes',
|
||||
@@ -175,6 +176,7 @@ const RouteMap: Dictionary<Route> = {
|
||||
[PageMap.HOME_NOT_OPERATIONAL_MONITORS]: new Route(
|
||||
`/dashboard/${RouteParams.ProjectID}/home/monitors-inoperational`
|
||||
),
|
||||
|
||||
[PageMap.HOME_ONGOING_SCHEDULED_MAINTENANCE_EVENTS]: new Route(
|
||||
`/dashboard/${RouteParams.ProjectID}/home/scheduled-maintenance-ongoing`
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user