Compare commits

..

2 Commits

Author SHA1 Message Date
Simon Larsen
71a0edb7dd ```text
refactor: Update MonitorReport API endpoint route

This commit updates the API endpoint route for the MonitorReport model. The route is changed from "/status-page" to "/monitor-report" in the MonitorReport.ts file. This change ensures consistency and clarity in the API routes, aligning them with the model name.
2024-07-23 10:42:20 -06:00
Simon Larsen
a53b24ed05 refactor: Add Monitor Reports to SideMenu
This commit adds the "Monitor Reports" option to the SideMenu in the Monitor page. It includes the necessary code changes in the MonitorReports.tsx, MonitorReport/View/Index.tsx, MonitorReport/View/Delete.tsx, MonitorReport/View/Settings.tsx, and SideMenu.tsx files. The new option allows users to access and manage monitor reports directly from the SideMenu, improving the navigation and usability of the Monitor page.
2024-07-23 10:25:33 -06:00
3991 changed files with 191943 additions and 281552 deletions

View File

@@ -16,18 +16,14 @@ jobs:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v2
- name: Preinstall
run: npm run prerun
# build image for accounts service
- name: build docker image
uses: nick-fields/retry@v3
with:
timeout_minutes: 45
max_attempts: 3
command: sudo docker build -f ./Accounts/Dockerfile .
run: sudo docker build -f ./Accounts/Dockerfile .
docker-build-isolated-vm:
runs-on: ubuntu-latest
@@ -35,113 +31,14 @@ jobs:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v2
- name: Preinstall
run: npm run prerun
# build image for accounts service
- name: build docker image
uses: nick-fields/retry@v3
with:
timeout_minutes: 45
max_attempts: 3
command: sudo docker build -f ./IsolatedVM/Dockerfile .
docker-build-home:
runs-on: ubuntu-latest
env:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Preinstall
run: npm run prerun
# build image for accounts service
- name: build docker image
uses: nick-fields/retry@v3
with:
timeout_minutes: 45
max_attempts: 3
command: sudo docker build -f ./Home/Dockerfile .
docker-build-worker:
runs-on: ubuntu-latest
env:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Preinstall
run: npm run prerun
# build image for accounts service
- name: build docker image
uses: nick-fields/retry@v3
with:
timeout_minutes: 45
max_attempts: 3
command: sudo docker build -f ./Worker/Dockerfile .
docker-build-workflow:
runs-on: ubuntu-latest
env:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Preinstall
run: npm run prerun
# build image for accounts service
- name: build docker image
uses: nick-fields/retry@v3
with:
timeout_minutes: 45
max_attempts: 3
command: sudo docker build -f ./Workflow/Dockerfile .
docker-build-api-reference:
runs-on: ubuntu-latest
env:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Preinstall
run: npm run prerun
# build image for accounts service
- name: build docker image
uses: nick-fields/retry@v3
with:
timeout_minutes: 45
max_attempts: 3
command: sudo docker build -f ./APIReference/Dockerfile .
docker-build-docs:
runs-on: ubuntu-latest
env:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Preinstall
run: npm run prerun
# build image for accounts service
- name: build docker image
uses: nick-fields/retry@v3
with:
timeout_minutes: 45
max_attempts: 3
command: sudo docker build -f ./Docs/Dockerfile .
run: sudo docker build -f ./IsolatedVM/Dockerfile .
docker-build-otel-collector:
@@ -150,18 +47,14 @@ jobs:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v2
- name: Preinstall
run: npm run prerun
# build image for accounts service
- name: build docker image
uses: nick-fields/retry@v3
with:
timeout_minutes: 45
max_attempts: 3
command: sudo docker build -f ./OTelCollector/Dockerfile .
run: sudo docker build -f ./OTelCollector/Dockerfile .
docker-build-app:
runs-on: ubuntu-latest
@@ -169,7 +62,7 @@ jobs:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v2
- name: Preinstall
run: npm run prerun
@@ -177,11 +70,7 @@ jobs:
# build image for accounts service
- name: build docker image
uses: nick-fields/retry@v3
with:
timeout_minutes: 45
max_attempts: 3
command: sudo docker build -f ./App/Dockerfile .
run: sudo docker build -f ./App/Dockerfile .
docker-build-copilot:
@@ -190,18 +79,14 @@ jobs:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v2
- name: Preinstall
run: npm run prerun
# build image for accounts service
- name: build docker image
uses: nick-fields/retry@v3
with:
timeout_minutes: 45
max_attempts: 3
command: sudo docker build -f ./Copilot/Dockerfile .
run: sudo docker build -f ./Copilot/Dockerfile .
docker-build-e2e:
runs-on: ubuntu-latest
@@ -209,7 +94,7 @@ jobs:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v2
- name: Preinstall
run: npm run prerun
@@ -217,11 +102,7 @@ jobs:
# build image for accounts service
- name: build docker image
uses: nick-fields/retry@v3
with:
timeout_minutes: 45
max_attempts: 3
command: sudo docker build -f ./E2E/Dockerfile .
run: sudo docker build -f ./E2E/Dockerfile .
docker-build-admin-dashboard:
runs-on: ubuntu-latest
@@ -229,18 +110,14 @@ jobs:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v2
- name: Preinstall
run: npm run prerun
# build image for home
- name: build docker image
uses: nick-fields/retry@v3
with:
timeout_minutes: 45
max_attempts: 3
command: sudo docker build -f ./AdminDashboard/Dockerfile .
run: sudo docker build -f ./AdminDashboard/Dockerfile .
docker-build-dashboard:
runs-on: ubuntu-latest
@@ -248,18 +125,30 @@ jobs:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v2
- name: Preinstall
run: npm run prerun
# build image for home
- name: build docker image
uses: nick-fields/retry@v3
with:
timeout_minutes: 45
max_attempts: 3
command: sudo docker build -f ./Dashboard/Dockerfile .
run: sudo docker build -f ./Dashboard/Dockerfile .
docker-build-haraka:
runs-on: ubuntu-latest
env:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Preinstall
run: npm run prerun
# build images
- name: build docker image
run: sudo docker build -f ./Haraka/Dockerfile .
docker-build-probe:
runs-on: ubuntu-latest
@@ -267,113 +156,29 @@ jobs:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v2
- name: Preinstall
run: npm run prerun
# build image probe api
- name: build docker image
uses: nick-fields/retry@v3
with:
timeout_minutes: 45
max_attempts: 3
command: sudo docker build -f ./Probe/Dockerfile .
run: sudo docker build -f ./Probe/Dockerfile .
docker-build-probe-ingest:
docker-build-ingestor:
runs-on: ubuntu-latest
env:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v2
- name: Preinstall
run: npm run prerun
# build image probe api
- name: build docker image
uses: nick-fields/retry@v3
with:
timeout_minutes: 45
max_attempts: 3
command: sudo docker build -f ./ProbeIngest/Dockerfile .
docker-build-server-monitor-ingest:
runs-on: ubuntu-latest
env:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Preinstall
run: npm run prerun
# build image probe api
- name: build docker image
uses: nick-fields/retry@v3
with:
timeout_minutes: 45
max_attempts: 3
command: sudo docker build -f ./ServerMonitorIngest/Dockerfile .
docker-build-open-telemetry-ingest:
runs-on: ubuntu-latest
env:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Preinstall
run: npm run prerun
# build image probe api
- name: build docker image
uses: nick-fields/retry@v3
with:
timeout_minutes: 45
max_attempts: 3
command: sudo docker build -f ./OpenTelemetryIngest/Dockerfile .
docker-build-incoming-request-ingest:
runs-on: ubuntu-latest
env:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Preinstall
run: npm run prerun
# build image probe api
- name: build docker image
uses: nick-fields/retry@v3
with:
timeout_minutes: 45
max_attempts: 3
command: sudo docker build -f ./IncomingRequestIngest/Dockerfile .
docker-build-fluent-ingest:
runs-on: ubuntu-latest
env:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Preinstall
run: npm run prerun
# build image probe api
- name: build docker image
uses: nick-fields/retry@v3
with:
timeout_minutes: 45
max_attempts: 3
command: sudo docker build -f ./FluentIngest/Dockerfile .
run: sudo docker build -f ./Ingestor/Dockerfile .
docker-build-status-page:
runs-on: ubuntu-latest
@@ -381,18 +186,14 @@ jobs:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v2
- name: Preinstall
run: npm run prerun
# build image for home
- name: build docker image
uses: nick-fields/retry@v3
with:
timeout_minutes: 45
max_attempts: 3
command: sudo docker build -f ./StatusPage/Dockerfile .
run: sudo docker build -f ./StatusPage/Dockerfile .
docker-build-test-server:
runs-on: ubuntu-latest
@@ -400,15 +201,11 @@ jobs:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v2
- name: Preinstall
run: npm run prerun
# build image for mail service
- name: build docker image
uses: nick-fields/retry@v3
with:
timeout_minutes: 45
max_attempts: 3
command: sudo docker build -f ./TestServer/Dockerfile .
run: sudo docker build -f ./TestServer/Dockerfile .

View File

@@ -31,6 +31,8 @@ jobs:
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'javascript', 'typescript', 'go' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]

View File

@@ -14,7 +14,7 @@ jobs:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- name: Checkout repo
uses: actions/checkout@v4
uses: actions/checkout@v2
- name: Install Helm
run: |
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
@@ -28,7 +28,7 @@ jobs:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- name: Checkout repo
uses: actions/checkout@v4
uses: actions/checkout@v2
- run: sudo apt-get update
- run: sudo apt-get install -y curl gcc
- run: sudo apt-get install -y build-essential

View File

@@ -15,187 +15,110 @@ jobs:
env:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: latest
node-version: 18.3.0
- run: cd Common && npm install
- name: Compile Accounts
uses: nick-fields/retry@v3
with:
timeout_minutes: 30
max_attempts: 3
command: cd Accounts && npm install && npm run compile && npm run dep-check
- run: cd Model && npm install
- run: cd CommonServer && npm install
- run: cd CommonUI && npm install --force
- run: cd Accounts && npm install && npm run compile && npm run dep-check
compile-isolated-vm:
runs-on: ubuntu-latest
env:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: latest
node-version: 18.3.0
- run: cd Common && npm install
- name: Compile IsolatedVM
uses: nick-fields/retry@v3
- run: cd CommonServer && npm install
- run: cd IsolatedVM && npm install && npm run compile && npm run dep-check
compile-common-server:
runs-on: ubuntu-latest
env:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
timeout_minutes: 30
max_attempts: 3
command: cd IsolatedVM && npm install && npm run compile && npm run dep-check
node-version: 18.3.0
- run: cd Common && npm install
- run: cd Model && npm install
- run: cd CommonServer && npm install && npm run compile && npm run dep-check
compile-common-ui:
runs-on: ubuntu-latest
env:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: 18.3.0
- run: cd Common && npm install
- run: cd Model && npm install
- run: cd CommonUI && npm install --force && npm run compile && npm run dep-check
compile-common:
runs-on: ubuntu-latest
env:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: latest
- name: Compile Common
uses: nick-fields/retry@v3
with:
timeout_minutes: 30
max_attempts: 3
command: cd Common && npm install && npm run compile && npm run dep-check
node-version: 18.3.0
- run: cd Common && npm install
- run: cd Model && npm install && npm run compile && npm run dep-check
compile-app:
runs-on: ubuntu-latest
env:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: latest
node-version: 18.3.0
- run: cd Common && npm install
- name: Compile App
uses: nick-fields/retry@v3
with:
timeout_minutes: 30
max_attempts: 3
command: cd App && npm install && npm run compile && npm run dep-check
compile-home:
runs-on: ubuntu-latest
env:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: latest
- run: cd Common && npm install
- name: Compile Home
uses: nick-fields/retry@v3
with:
timeout_minutes: 30
max_attempts: 3
command: cd Home && npm install && npm run compile && npm run dep-check
compile-worker:
runs-on: ubuntu-latest
env:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: latest
- run: cd Common && npm install
- name: Compile Worker
uses: nick-fields/retry@v3
with:
timeout_minutes: 30
max_attempts: 3
command: cd Worker && npm install && npm run compile && npm run dep-check
compile-workflow:
runs-on: ubuntu-latest
env:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: latest
- run: cd Common && npm install
- name: Compile Workflow
uses: nick-fields/retry@v3
with:
timeout_minutes: 30
max_attempts: 3
command: cd Workflow && npm install && npm run compile && npm run dep-check
compile-api-reference:
runs-on: ubuntu-latest
env:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: latest
- run: cd Common && npm install
- name: Compile API Reference
uses: nick-fields/retry@v3
with:
timeout_minutes: 30
max_attempts: 3
command: cd APIReference && npm install && npm run compile && npm run dep-check
compile-docs-reference:
runs-on: ubuntu-latest
env:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: latest
- run: cd Common && npm install
- name: Compile Docs Reference
uses: nick-fields/retry@v3
with:
timeout_minutes: 30
max_attempts: 3
command: cd Docs && npm install && npm run compile && npm run dep-check
- run: cd Model && npm install
- run: cd CommonServer && npm install
- run: cd CommonUI && npm install --force
- run: cd App && npm install && npm run compile && npm run dep-check
compile-copilot:
runs-on: ubuntu-latest
env:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: latest
node-version: 18.3.0
- run: cd Common && npm install
- name: Compile Copilot
uses: nick-fields/retry@v3
with:
timeout_minutes: 30
max_attempts: 3
command: cd Copilot && npm install && npm run compile && npm run dep-check
- run: cd Model && npm install
- run: cd CommonServer && npm install
- run: cd Copilot && npm install && npm run compile && npm run dep-check
compile-nginx:
runs-on: ubuntu-latest
env:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: latest
node-version: 18.3.0
- run: cd Common && npm install
- name: Compile Nginx
uses: nick-fields/retry@v3
with:
timeout_minutes: 30
max_attempts: 3
command: cd Nginx && npm install && npm run compile && npm run dep-check
- run: cd Model && npm install
- run: cd CommonServer && npm install
- run: cd CommonUI && npm install --force
- run: cd Nginx && npm install && npm run compile && npm run dep-check
compile-infrastructure-agent:
runs-on: ubuntu-latest
@@ -205,12 +128,7 @@ jobs:
- uses: actions/checkout@v4
# Setup Go
- uses: actions/setup-go@v5
- name: Compile Infrastructure Agent
uses: nick-fields/retry@v3
with:
timeout_minutes: 30
max_attempts: 3
command: cd InfrastructureAgent && go build .
- run: cd InfrastructureAgent && go build .
compile-admin-dashboard:
@@ -218,158 +136,84 @@ jobs:
env:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: latest
node-version: 18.3.0
- run: cd Common && npm install
- name: Compile Admin Dashboard
uses: nick-fields/retry@v3
with:
timeout_minutes: 30
max_attempts: 3
command: cd AdminDashboard && npm install && npm run compile && npm run dep-check
- run: cd Model && npm install
- run: cd CommonServer && npm install
- run: cd CommonUI && npm install --force
- run: cd AdminDashboard && npm install && npm run compile && npm run dep-check
compile-dashboard:
runs-on: ubuntu-latest
env:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: latest
node-version: 18.3.0
- run: cd Common && npm install
- name: Compile Dashboard
uses: nick-fields/retry@v3
with:
timeout_minutes: 30
max_attempts: 3
command: cd Dashboard && npm install && npm run compile && npm run dep-check
- run: cd Model && npm install
- run: cd CommonServer && npm install
- run: cd CommonUI && npm install --force
- run: cd Dashboard && npm install && npm run compile && npm run dep-check
compile-model:
runs-on: ubuntu-latest
env:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: 18.3.0
- run: cd Common && npm install
- run: cd Model && npm install
- run: cd Model && npm install && npm run compile && npm run dep-check
compile-e2e:
runs-on: ubuntu-latest
env:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: latest
- run: sudo apt-get update
node-version: 18.3.0
- run: cd Common && npm install
- name: Compile E2E
uses: nick-fields/retry@v3
with:
timeout_minutes: 30
max_attempts: 3
command: cd E2E && npm install && npm run compile && npm run dep-check
- run: cd E2E && npm install && npm run compile && npm run dep-check
compile-probe:
runs-on: ubuntu-latest
env:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: latest
node-version: 18.3.0
- run: cd Common && npm install
- name: Compile Probe
uses: nick-fields/retry@v3
with:
timeout_minutes: 30
max_attempts: 3
command: cd Probe && npm install && npm run compile && npm run dep-check
- run: cd Model && npm install
- run: cd CommonServer && npm install
- run: cd Probe && npm install && npm run compile && npm run dep-check
compile-probe-ingest:
compile-ingestor:
runs-on: ubuntu-latest
env:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: latest
node-version: 18.3.0
- run: cd Common && npm install
- name: Compile Probe Ingest
uses: nick-fields/retry@v3
with:
timeout_minutes: 30
max_attempts: 3
command: cd ProbeIngest && npm install && npm run compile && npm run dep-check
compile-server-monitor-ingest:
runs-on: ubuntu-latest
env:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: latest
- run: cd Common && npm install
- name: Compile Server Monitor Ingest
uses: nick-fields/retry@v3
with:
timeout_minutes: 30
max_attempts: 3
command: cd ServerMonitorIngest && npm install && npm run compile && npm run dep-check
compile-open-telemetry-ingest:
runs-on: ubuntu-latest
env:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: latest
- run: cd Common && npm install
- name: Compile Open Telemetry Ingest
uses: nick-fields/retry@v3
with:
timeout_minutes: 30
max_attempts: 3
command: cd OpenTelemetryIngest && npm install && npm run compile && npm run dep-check
compile-incoming-request-ingest:
runs-on: ubuntu-latest
env:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: latest
- run: cd Common && npm install
- name: Compile Incoming Request Ingest
uses: nick-fields/retry@v3
with:
timeout_minutes: 30
max_attempts: 3
command: cd IncomingRequestIngest && npm install && npm run compile && npm run dep-check
compile-fluent-ingest:
runs-on: ubuntu-latest
env:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: latest
- run: cd Common && npm install
- name: Compile Fluent Ingest
uses: nick-fields/retry@v3
with:
timeout_minutes: 30
max_attempts: 3
command: cd FluentIngest && npm install && npm run compile && npm run dep-check
- run: cd Model && npm install
- run: cd CommonServer && npm install
- run: cd Ingestor && npm install && npm run compile && npm run dep-check
compile-status-page:
@@ -377,49 +221,26 @@ jobs:
env:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: latest
node-version: 18.3.0
- run: cd Common && npm install
- name: Compile Status Page
uses: nick-fields/retry@v3
with:
timeout_minutes: 30
max_attempts: 3
command: cd StatusPage && npm install && npm run compile && npm run dep-check
- run: cd Model && npm install
- run: cd CommonServer && npm install
- run: cd CommonUI && npm install --force
- run: cd StatusPage && npm install && npm run compile && npm run dep-check
compile-test-server:
runs-on: ubuntu-latest
env:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: latest
node-version: 18.3.0
- run: cd Common && npm install
- name: Compile Test Server
uses: nick-fields/retry@v3
with:
timeout_minutes: 30
max_attempts: 3
command: cd TestServer && npm install && npm run compile && npm run dep-check
compile-mcp:
runs-on: ubuntu-latest
env:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: latest
- run: cd Common && npm install
- name: Compile MCP
uses: nick-fields/retry@v3
with:
timeout_minutes: 30
max_attempts: 3
command: cd MCP && npm install && npm run compile && npm run dep-check
- run: cd Model && npm install
- run: cd CommonServer && npm install
- run: cd TestServer && npm install && npm run compile && npm run dep-check

View File

@@ -1,74 +0,0 @@
name: OpenAPI Spec Generation
on:
pull_request:
push:
branches-ignore:
- 'hotfix-*'
- 'release'
jobs:
generate-openapi-spec:
runs-on: ubuntu-latest
env:
CI_PIPELINE_ID: ${{ github.run_number }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: latest
cache: 'npm'
- name: Install Common dependencies
run: cd Common && npm install
- name: Install root dependencies
run: npm install
- name: Install Script dependencies
run: cd Scripts && npm install
- name: Generate OpenAPI specification
run: npm run generate-openapi-spec
- name: Check if OpenAPI spec was generated
run: |
if [ -f "./openapi.json" ]; then
echo "✅ OpenAPI spec file generated successfully"
echo "📄 File size: $(du -h ./openapi.json | cut -f1)"
echo "📊 Spec contains $(jq '.paths | length' ./openapi.json) API paths"
echo "🏷️ API version: $(jq -r '.info.version' ./openapi.json)"
echo "📝 API title: $(jq -r '.info.title' ./openapi.json)"
else
echo "❌ OpenAPI spec file was not generated"
exit 1
fi
- name: Validate OpenAPI spec format
run: |
# Check if the file is valid JSON
if jq empty ./openapi.json; then
echo "✅ OpenAPI spec is valid JSON"
else
echo "❌ OpenAPI spec is not valid JSON"
exit 1
fi
# Check if it has required OpenAPI fields
if jq -e '.openapi and .info and .paths' ./openapi.json > /dev/null; then
echo "✅ OpenAPI spec has required fields"
else
echo "❌ OpenAPI spec missing required fields (openapi, info, paths)"
exit 1
fi
- name: Upload OpenAPI spec as artifact
uses: actions/upload-artifact@v4
with:
name: openapi-spec
path: ./openapi.json
retention-days: 30

File diff suppressed because it is too large Load Diff

View File

@@ -20,7 +20,7 @@ jobs:
steps:
# Run Reliability Copilot in Docker Container
# Run Reliability Copilot in Doker Container
- name: Run Copilot
run: |
docker run --rm \

View File

@@ -1,101 +0,0 @@
name: Terraform Provider Generation
on:
pull_request:
push:
branches:
- main
- master
- develop
workflow_dispatch: # Allow manual trigger
jobs:
generate-terraform-provider:
runs-on: ubuntu-latest
env:
CI_PIPELINE_ID: ${{ github.run_number }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: latest
cache: 'npm'
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: '1.21'
cache: true
- name: Install Common dependencies
run: cd Common && npm install
- name: Install root dependencies
run: npm install
- name: Install Script dependencies
run: cd Scripts && npm install
- name: Generate Terraform provider
run: npm run generate-terraform-provider
- name: Verify provider generation
run: |
PROVIDER_DIR="./Terraform"
# Check if provider directory was created
if [ ! -d "$PROVIDER_DIR" ]; then
echo "❌ Terraform provider directory not created"
exit 1
fi
echo "✅ Provider directory created: $PROVIDER_DIR"
# Count generated files
GO_FILES=$(find "$PROVIDER_DIR" -name "*.go" | wc -l)
echo "📊 Generated Go files: $GO_FILES"
if [ "$GO_FILES" -eq 0 ]; then
echo "❌ No Go files were generated"
exit 1
fi
# Check for essential files
if [ -f "$PROVIDER_DIR/go.mod" ]; then
echo "✅ Go module file created"
fi
if [ -f "$PROVIDER_DIR/README.md" ]; then
echo "✅ Documentation created"
fi
# Show directory structure for debugging
echo "📁 Provider directory structure:"
ls -la "$PROVIDER_DIR" || true
- name: Test Go build
uses: nick-fields/retry@v3
with:
timeout_minutes: 30
max_attempts: 3
command: |
PROVIDER_DIR="./Terraform"
if [ -d "$PROVIDER_DIR" ] && [ -f "$PROVIDER_DIR/go.mod" ]; then
cd "$PROVIDER_DIR"
echo "🔨 Testing Go build..."
go mod tidy
go build -v ./...
echo "✅ Go build successful"
else
echo "⚠️ Cannot test build - missing go.mod or provider directory"
fi
- name: Upload Terraform provider as artifact
uses: actions/upload-artifact@v4
with:
name: Terraform
path: ./Terraform/
retention-days: 30

View File

@@ -1,4 +1,4 @@
name: Fluent Ingest Test
name: App Test
on:
pull_request:
@@ -13,8 +13,8 @@ jobs:
env:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: latest
- run: cd FluentIngest && npm install && npm run test
node-version: 18.3.0
- run: cd App && npm install && npm run test

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,24 @@
name: Common Server Test
on:
pull_request:
push:
branches-ignore:
- 'hotfix-*' # excludes hotfix branches
- 'release'
jobs:
test:
runs-on: ubuntu-latest
env:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: 18.3.0
- run: cd Common && npm install
- run: cd Model && npm install
- run: cd CommonServer && npm install
- run: cd CommonServer && bash test-setup.sh
- run: export $(grep -v '^#' config.env | xargs) && cd CommonServer && rm -rf build && npm run test

View File

@@ -12,12 +12,11 @@ jobs:
runs-on: ubuntu-latest
env:
CI_PIPELINE_ID: ${{github.run_number}}
BILLING_PRIVATE_KEY: ${{secrets.TEST_BILLING_PRIVATE_KEY}}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: latest
- run: cd Common && bash test-setup.sh
- run: cd Common && npm install && rm -rf build && npm run test
node-version: 18.3.0
- run: cd Model && npm install
- run: cd Common && npm install && npm run test

23
.github/workflows/test.commonui.yaml vendored Normal file
View File

@@ -0,0 +1,23 @@
name: CommonUI Test
on:
pull_request:
push:
branches-ignore:
- 'hotfix-*' # excludes hotfix branches
- 'release'
jobs:
test:
runs-on: ubuntu-latest
env:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: 18.3.0
- run: cd Common && npm install
- run: cd Model && npm install
- run: cd CommonUI && npm install --force && npm run test

58
.github/workflows/test.e2e.yaml vendored Normal file
View File

@@ -0,0 +1,58 @@
name: E2E Tests
on:
pull_request:
push:
branches-ignore:
- 'hotfix-*' # excludes hotfix branches
- 'release'
jobs:
test:
runs-on: ubuntu-latest
env:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
# Docker compose needs a lot of space to build images, so we need to free up some space first in the GitHub Actions runner
- name: Free Disk Space (Ubuntu)
uses: jlumbroso/free-disk-space@main
with:
# this might remove tools that are actually needed,
# if set to "true" but frees about 6 GB
tool-cache: false
android: true
dotnet: true
haskell: true
large-packages: true
docker-images: true
swap-storage: true
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: 18.3.0
- run: npm run prerun && bash ./Tests/Scripts/enable-billing-env-var.sh
- run: npm run dev
- name: Wait for server to start
run: bash ./Tests/Scripts/status-check.sh http://localhost
- name: Run E2E Tests. Run docker container e2e in docker compose file
run: export $(grep -v '^#' config.env | xargs) && docker compose -f docker-compose.dev.yml up --exit-code-from e2e --abort-on-container-exit e2e || (docker compose -f docker-compose.dev.yml logs e2e && exit 1)
- name: Upload test results
uses: actions/upload-artifact@v4
# Run this on failure
if: failure()
with:
# Name of the artifact to upload.
# Optional. Default is 'artifact'
name: test-results
# A file, directory or wildcard pattern that describes what to upload
# Required.
path: |
./E2E
# Duration after which artifact will expire in days. 0 means using default retention.
# Minimum 1 day.
# Maximum 90 days unless changed from the repository settings page.
# Optional. Defaults to repository settings.
retention-days: 7

View File

@@ -1,21 +0,0 @@
name: Incoming Request Ingest Test
on:
pull_request:
push:
branches-ignore:
- 'hotfix-*' # excludes hotfix branches
- 'release'
jobs:
test:
runs-on: ubuntu-latest
env:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: latest
- run: cd IncomingRequestIngest && npm install && npm run test

View File

@@ -1,4 +1,4 @@
name: ProbeIngest Test
name: Ingestor Test
on:
pull_request:
@@ -13,9 +13,9 @@ jobs:
env:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: latest
- run: cd ProbeIngest && npm install && npm run test
node-version: 18.3.0
- run: cd Ingestor && npm install && npm run test

View File

@@ -1,4 +1,4 @@
name: MCP Server Test
name: Model Test
on:
pull_request:
@@ -13,9 +13,11 @@ jobs:
env:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: latest
node-version: 18.3.0
- run: cd Common && npm install
- run: cd MCP && npm install && npm run test
- run: cd Model && npm install
- run: cd Model && npm install && npm run test

View File

@@ -1,21 +0,0 @@
name: OpenTelemetryIngest Test
on:
pull_request:
push:
branches-ignore:
- 'hotfix-*' # excludes hotfix branches
- 'release'
jobs:
test:
runs-on: ubuntu-latest
env:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: latest
- run: cd OpenTelemetryIngest && npm install && npm run test

View File

@@ -13,11 +13,12 @@ jobs:
env:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: latest
node-version: 18.3.0
- run: cd Common && npm install
- run: cd CommonServer && npm install
- run: cd Probe && npm install
- run: cd Probe && npm run test

View File

@@ -1,42 +0,0 @@
name: Tests
on:
pull_request:
push:
branches-ignore:
- 'hotfix-*' # excludes hotfix branches
- 'release'
jobs:
test-app:
runs-on: ubuntu-latest
env:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: latest
- run: cd App && npm install && npm run test
test-home:
runs-on: ubuntu-latest
env:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: latest
- run: cd Home && npm install && npm run test
test-worker:
runs-on: ubuntu-latest
env:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: latest
- run: cd Worker && npm install && npm run test

22
.gitignore vendored
View File

@@ -86,6 +86,9 @@ Backups/*.tar
.env
Haraka/dkim/keys/private_base64.txt
Haraka/dkim/keys/public_base64.txt
.eslintcache
HelmChart/Values/*.values.yaml
@@ -109,22 +112,3 @@ App/greenlock/greenlock.d/config.json
App/greenlock/greenlock.d/config.json.bak
Examples/otel-dotnet/bin/Debug/net6.0/Grpc.Core.Api.dll.txt
InfrastructureAgent/oneuptime-infrastructure-agent
# ESLint cache
.eslintcache*
# Terraform generated files
openapi.json
Terraform/**
TerraformTest/**
terraform-provider-example/**
# MCP Server
MCP/build/
MCP/.env
MCP/node_modules
Dashboard/public/sw.js
.claude/settings.local.json

View File

@@ -1 +1 @@
# Description: Copilot will run this script before we commit the changes to your repository.
# Description: Copilot will run this script before we commit the changes to your repository.

View File

@@ -51,3 +51,6 @@ licenses/*
certifications/*
ApiReference/public/assets/*
JavaScriptSDK/src/cli/server-monitor/out/scripts/prettify/*
CommonServer/Tests/TestingUtils/__mocks__/Stripe.mock.ts

150
.vscode/launch.json vendored
View File

@@ -63,76 +63,6 @@
"restart": true,
"autoAttachChildProcesses": true
},
{
"address": "127.0.0.1",
"localRoot": "${workspaceFolder}/Home",
"name": "Home: Debug with Docker",
"port": 9212,
"remoteRoot": "/usr/src/app",
"request": "attach",
"skipFiles": [
"<node_internals>/**"
],
"type": "node",
"restart": true,
"autoAttachChildProcesses": true
},
{
"address": "127.0.0.1",
"localRoot": "${workspaceFolder}/Worker",
"name": "Worker: Debug with Docker",
"port": 8734,
"remoteRoot": "/usr/src/app",
"request": "attach",
"skipFiles": [
"<node_internals>/**"
],
"type": "node",
"restart": true,
"autoAttachChildProcesses": true
},
{
"address": "127.0.0.1",
"localRoot": "${workspaceFolder}/Workflow",
"name": "Workflow: Debug with Docker",
"port": 8735,
"remoteRoot": "/usr/src/app",
"request": "attach",
"skipFiles": [
"<node_internals>/**"
],
"type": "node",
"restart": true,
"autoAttachChildProcesses": true
},
{
"address": "127.0.0.1",
"localRoot": "${workspaceFolder}/Docs",
"name": "Docs: Debug with Docker",
"port": 8738,
"remoteRoot": "/usr/src/app",
"request": "attach",
"skipFiles": [
"<node_internals>/**"
],
"type": "node",
"restart": true,
"autoAttachChildProcesses": true
},
{
"address": "127.0.0.1",
"localRoot": "${workspaceFolder}/APIReference",
"name": "API Reference: Debug with Docker",
"port": 8737,
"remoteRoot": "/usr/src/app",
"request": "attach",
"skipFiles": [
"<node_internals>/**"
],
"type": "node",
"restart": true,
"autoAttachChildProcesses": true
},
{
"address": "127.0.0.1",
"localRoot": "${workspaceFolder}/TestServer",
@@ -151,7 +81,7 @@
"address": "127.0.0.1",
"localRoot": "${workspaceFolder}/Probe",
"name": "Probe: Debug with Docker",
"port": 9229,
"port": 9655,
"remoteRoot": "/usr/src/app",
"request": "attach",
"skipFiles": [
@@ -163,8 +93,8 @@
},
{
"address": "127.0.0.1",
"localRoot": "${workspaceFolder}/ProbeIngest",
"name": "ProbeIngest: Debug with Docker",
"localRoot": "${workspaceFolder}/Ingestor",
"name": "Ingestor: Debug with Docker",
"port": 9932,
"remoteRoot": "/usr/src/app",
"request": "attach",
@@ -175,62 +105,6 @@
"restart": true,
"autoAttachChildProcesses": true
},
{
"address": "127.0.0.1",
"localRoot": "${workspaceFolder}/ServerMonitorIngest",
"name": "ServerMonitorIngest: Debug with Docker",
"port": 9941,
"remoteRoot": "/usr/src/app",
"request": "attach",
"skipFiles": [
"<node_internals>/**"
],
"type": "node",
"restart": true,
"autoAttachChildProcesses": true
},
{
"address": "127.0.0.1",
"localRoot": "${workspaceFolder}/IncomingRequestIngest",
"name": "IncomingRequestIngest: Debug with Docker",
"port": 9933,
"remoteRoot": "/usr/src/app",
"request": "attach",
"skipFiles": [
"<node_internals>/**"
],
"type": "node",
"restart": true,
"autoAttachChildProcesses": true
},
{
"address": "127.0.0.1",
"localRoot": "${workspaceFolder}/OpenTelemetryIngest",
"name": "OpenTelemetryIngest: Debug with Docker",
"port": 9938,
"remoteRoot": "/usr/src/app",
"request": "attach",
"skipFiles": [
"<node_internals>/**"
],
"type": "node",
"restart": true,
"autoAttachChildProcesses": true
},
{
"address": "127.0.0.1",
"localRoot": "${workspaceFolder}/FluentIngest",
"name": "Fluent Ingest: Debug with Docker",
"port": 9937,
"remoteRoot": "/usr/src/app",
"request": "attach",
"skipFiles": [
"<node_internals>/**"
],
"type": "node",
"restart": true,
"autoAttachChildProcesses": true
},
{
"address": "127.0.0.1",
"localRoot": "${workspaceFolder}/IsolatedVM",
@@ -273,6 +147,20 @@
"restart": true,
"autoAttachChildProcesses": true
},
{
"address": "127.0.0.1",
"localRoot": "${workspaceFolder}/Workers",
"name": "Workers: Debug with Docker",
"port": 9654,
"remoteRoot": "/usr/src/app",
"request": "attach",
"skipFiles": [
"<node_internals>/**"
],
"type": "node",
"restart": true,
"autoAttachChildProcesses": true
},
{
"address": "127.0.0.1",
"localRoot": "${workspaceFolder}/StatusPage",
@@ -330,12 +218,12 @@
"autoAttachChildProcesses": true
},
{
"name": "Common: Debug Tests",
"name": "CommonServer: Debug Tests",
"type": "node",
"restart": true,
"autoAttachChildProcesses": true,
"request": "launch",
"cwd": "${workspaceRoot}/Common",
"cwd": "${workspaceRoot}/CommonServer",
"runtimeExecutable": "npm",
"runtimeArgs": [
"run-script",

View File

@@ -1,30 +0,0 @@
# See https://help.github.com/ignore-files/ for more about ignoring files.
# dependencies
#/backend/node_modules
/kubernetes
/node_modules
.idea
# misc
.DS_Store
npm-debug.log*
yarn-debug.log*
yarn-error.log*
yarn.lock
**/*/paymentService.test.js
apiTest.rest
application_security_dir
container_security_dir
# coverage
/coverage
/.nyc_output
/greenlock.d/config.json
/greenlock.d/config.json.bak
/.greenlockrc

View File

@@ -1,8 +0,0 @@
{
"query": {
"age": {
"_type": "EqualTo",
value: 10
}
}
}

View File

@@ -1,8 +0,0 @@
{
"query": {
"age": {
"_type": "GreaterThanOrNull",
"value": 10
}
}
}

View File

@@ -1,11 +0,0 @@
{
"query": {
"labels": {
"_type": "Includes",
"value": [
"aaa00000-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
"bbb00000-bbbb-bbbb-bbbb-bbbbbbbbbbbb"
]
}
}
}

View File

@@ -1,8 +0,0 @@
{
"query": {
"age": {
"_type": "LessThanOrNull",
"value": 10
}
}
}

View File

@@ -1,52 +0,0 @@
import APIReferenceRoutes from "./Routes";
import { PromiseVoidFunction } from "Common/Types/FunctionTypes";
import InfrastructureStatus from "Common/Server/Infrastructure/Status";
import logger from "Common/Server/Utils/Logger";
import App from "Common/Server/Utils/StartServer";
import Telemetry from "Common/Server/Utils/Telemetry";
import "ejs";
const APP_NAME: string = "reference";
const init: PromiseVoidFunction = async (): Promise<void> => {
try {
// Initialize telemetry
Telemetry.init({
serviceName: APP_NAME,
});
const statusCheck: PromiseVoidFunction = async (): Promise<void> => {
// Check the status of infrastructure components
return await InfrastructureStatus.checkStatusWithRetry({
checkClickhouseStatus: false,
checkPostgresStatus: false,
checkRedisStatus: false,
retryCount: 3,
});
};
// Initialize the app with service name and status checks
await App.init({
appName: APP_NAME,
statusOptions: {
liveCheck: statusCheck,
readyCheck: statusCheck,
},
});
await APIReferenceRoutes.init();
// Add default routes to the app
await App.addDefaultRoutes();
} catch (err) {
logger.error("App Init Failed:");
logger.error(err);
throw err;
}
};
init().catch((err: Error) => {
logger.error(err);
logger.error("Exiting node process");
process.exit(1);
});

View File

@@ -1,29 +0,0 @@
# README
This README would normally document whatever steps are necessary to get your application up and running.
### What is this repository for?
- Quick summary
- Version
- [Learn Markdown](https://bitbucket.org/tutorials/markdowndemo)
### How do I get set up?
- Summary of set up
- Configuration
- Dependencies
- Database configuration
- How to run tests
- Deployment instructions
### Contribution guidelines
- Writing tests
- Code review
- Other guidelines
### Who do I talk to?
- Repo owner or admin
- Other community or team contact

View File

@@ -1,44 +0,0 @@
import {
Host,
HttpProtocol,
IsBillingEnabled,
} from "Common/Server/EnvironmentConfig";
import { ViewsPath } from "../Utils/Config";
import ResourceUtil, { ModelDocumentation } from "../Utils/Resources";
import { ExpressRequest, ExpressResponse } from "Common/Server/Utils/Express";
import URL from "Common/Types/API/URL";
// Fetch a list of resources used in the application
const Resources: Array<ModelDocumentation> = ResourceUtil.getResources();
export default class ServiceHandler {
// Handles the HTTP response for a given request
public static async executeResponse(
req: ExpressRequest,
res: ExpressResponse,
): Promise<void> {
let pageTitle: string = "";
let pageDescription: string = "";
// Get the 'page' parameter from the request
const page: string | undefined = req.params["page"];
const pageData: any = {
hostUrl: new URL(HttpProtocol, Host).toString(),
};
// Set the default page title and description
pageTitle = "OneUptime OpenAPI Specification";
pageDescription =
"Learn more about the OpenAPI specification for OneUptime";
// Render the response using the given view and data
return res.render(`${ViewsPath}/pages/index`, {
page: page,
resources: Resources,
pageTitle: pageTitle,
enableGoogleTagManager: IsBillingEnabled,
pageDescription: pageDescription,
pageData: pageData,
});
}
}

View File

@@ -1,3 +0,0 @@
export const ViewsPath: string = "/usr/src/app/views";
export const StaticPath: string = "/usr/src/app/Static";
export const CodeExamplesPath: string = "/usr/src/app/CodeExamples";

View File

@@ -1,10 +0,0 @@
{
"watch": ["./","../Common/Server", "../Common/Types", "../Common/Utils", "../Common/Models"],
"ext": "ts,json,tsx,env,js,jsx,hbs",
"ignore": [
"greenlock.d/*"
],
"watchOptions": {"useFsEvents": false, "interval": 500},
"env": {"TS_NODE_TRANSPILE_ONLY": "1", "TS_NODE_FILES": "false"},
"exec": "node --inspect=0.0.0.0:9229 -r ts-node/register/transpile-only Index.ts"
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,29 +0,0 @@
{
"name": "@oneuptime/api-reference",
"version": "1.0.0",
"description": "",
"main": "Index.ts",
"scripts": {
"start": "export NODE_OPTIONS='--max-old-space-size=8096' && node --require ts-node/register Index.ts",
"compile": "tsc",
"clear-modules": "rm -rf node_modules && rm package-lock.json && npm install",
"dev": "npx nodemon",
"audit": "npm audit --audit-level=low",
"dep-check": "npm install -g depcheck && depcheck ./ --skip-missing=true",
"test": "rm -rf build && jest --detectOpenHandles --passWithNoTests",
"coverage": "jest --detectOpenHandles --coverage"
},
"author": "OneUptime <hello@oneuptime.com> (https://oneuptime.com/)",
"license": "Apache-2.0",
"dependencies": {
"Common": "file:../Common",
"ejs": "^3.1.9",
"ts-node": "^10.9.1"
},
"devDependencies": {
"@types/jest": "^29.5.11",
"@types/node": "^17.0.31",
"jest": "^28.1.0",
"nodemon": "^2.0.20"
}
}

View File

@@ -1,112 +0,0 @@
{
"ts-node": {
// these options are overrides used only by ts-node
// same as the --compilerOptions flag and the TS_NODE_COMPILER_OPTIONS environment variable
"compilerOptions": {
"module": "commonjs",
"resolveJsonModule": true,
}
},
"compilerOptions": {
/* Visit https://aka.ms/tsconfig.json to read more about this file */
/* Projects */
// "incremental": true, /* Enable incremental compilation */
// "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
// "tsBuildInfoFile": "./", /* Specify the folder for .tsbuildinfo incremental compilation files. */
// "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects */
// "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
/* Language and Environment */
"target": "es2017" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,
// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
"jsx": "react" /* Specify what JSX code is generated. */,
"experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */
"emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
// "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */
// "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
// "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.` */
// "reactNamespace": "", /* Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. */
// "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
// "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
/* Modules */
// "module": "es2022" /* Specify what module code is generated. */,
// "rootDir": "./", /* Specify the root folder within your source files. */
"moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */
// "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
// "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
"typeRoots": [
"./node_modules/@types"
], /* Specify multiple folders that act like `./node_modules/@types`. */
"types": ["node", "jest"], /* Specify type package names to be included without being referenced in a source file. */
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
// "resolveJsonModule": true, /* Enable importing .json files */
// "noResolve": true, /* Disallow `import`s, `require`s or `<reference>`s from expanding the number of files TypeScript should add to a project. */
/* JavaScript Support */
// "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */
// "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
// "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */
/* Emit */
// "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
// "declarationMap": true, /* Create sourcemaps for d.ts files. */
// "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
"sourceMap": true, /* Create source map files for emitted JavaScript files. */
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */
"outDir": "./build/dist", /* Specify an output folder for all emitted files. */
// "removeComments": true, /* Disable emitting comments. */
// "noEmit": true, /* Disable emitting files from a compilation. */
// "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
// "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types */
// "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
// "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
// "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
// "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
// "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
// "newLine": "crlf", /* Set the newline character for emitting files. */
// "stripInternal": true, /* Disable emitting declarations that have `@internal` in their JSDoc comments. */
// "noEmitHelpers": true, /* Disable generating custom helper functions like `__extends` in compiled output. */
// "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
// "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */
// "declarationDir": "./", /* Specify the output directory for generated declaration files. */
// "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
/* Interop Constraints */
// "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
// "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
"esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */,
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
"forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */,
/* Type Checking */
"strict": true /* Enable all strict type-checking options. */,
"noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied `any` type.. */
"strictNullChecks": true, /* When type checking, take into account `null` and `undefined`. */
"strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
"strictBindCallApply": true, /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */
"strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
"noImplicitThis": true, /* Enable error reporting when `this` is given the type `any`. */
"useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */
"alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
"noUnusedLocals": true, /* Enable error reporting when a local variables aren't read. */
"noUnusedParameters": true, /* Raise an error when a function parameter isn't read */
"exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
"noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
"noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
"noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */
"noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
"noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type */
// "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
// "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
/* Completeness */
// "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
"skipLibCheck": true, /* Skip type checking all .d.ts files. */
"resolveJsonModule": true
}
}

View File

@@ -1,53 +0,0 @@
<main class="py-16">
<article class="prose ">
<h1>OneUptime OpenAPI Specification</h1>
<p class="lead">In this guide, we will look at how to import and work with the OneUptime OpenAPI specification. The OpenAPI spec provides a comprehensive reference for all available API endpoints.</p>
<p>The OneUptime API follows the OpenAPI 3.0 specification, which provides a standardized way to describe REST APIs. You can import our OpenAPI spec into various tools like Swagger Editor, Postman, or other API documentation tools to explore and test our endpoints.</p>
<h2 id="importing-spec" class="scroll-mt-24">
Importing the OpenAPI Spec
</h2>
<div class="grid grid-cols-1 items-start gap-x-16 gap-y-10">
<div class="[&amp;>:first-child]:mt-0 [&amp;>:last-child]:mb-0">
<p>To import the OneUptime OpenAPI specification into Swagger Editor, follow these simple steps:</p>
<div class="my-6">
<ol class="list-decimal pl-6">
<li class="mb-2">Open <a href="https://editor.swagger.io" target="_blank" class="text-blue-600 hover:text-blue-800">editor.swagger.io</a> in your web browser</li>
<li class="mb-2">Click on <strong>File</strong> in the menu bar</li>
<li class="mb-2">Select <strong>Import URL</strong> from the dropdown menu</li>
<li class="mb-2">Enter the URL: <code class="inline-code"><%= pageData.hostUrl %>api/openapi/spec</code></li>
<li class="mb-2">Click <strong>Import</strong> to load the specification</li>
</ol>
</div>
<h2 id="spec-url" class="scroll-mt-24">
Specification URL
</h2>
<div class="my-6">
<ul role="list"
class="m-0 list-none divide-y divide-zinc-900/5 p-0 ">
<li class="m-0 px-0 py-4 first:pt-0 last:pb-0">
<dl class="m-0 flex flex-wrap items-center gap-x-3 gap-y-2">
<dt class="sr-only">Endpoint</dt>
<dd><code class="inline-code"><%= pageData.hostUrl %>api/openapi/spec</code></dd>
<dt class="sr-only">Description</dt>
<dd class="w-full flex-none [&amp;>:first-child]:mt-0 [&amp;>:last-child]:mb-0">
<p>Complete OpenAPI 3.0 specification for the OneUptime API including all endpoints, request/response schemas, and authentication methods.</p>
</dd>
</dl>
</li>
</ul>
</div>
<h2 id="benefits" class="scroll-mt-24">
Benefits of Using the OpenAPI Spec
</h2>
<div class="my-6">
<ul class="list-disc pl-6">
<li class="mb-2"><strong>Interactive Documentation:</strong> Test API endpoints directly in Swagger Editor</li>
<li class="mb-2"><strong>Code Generation:</strong> Generate client SDKs in multiple programming languages</li>
<li class="mb-2"><strong>Validation:</strong> Ensure your requests match the expected schema</li>
<li class="mb-2"><strong>Import to Tools:</strong> Use with Postman, Insomnia, or other API testing tools</li>
</ul>
</div>
</div>
</div>
</article>
</main>

View File

@@ -3,14 +3,9 @@
#
# Pull base image nodejs image.
FROM public.ecr.aws/docker/library/node:23.8-alpine3.21
FROM node:21.7.3-alpine3.18
RUN mkdir /tmp/npm && chmod 2777 /tmp/npm && chown 1000:1000 /tmp/npm && npm config set cache /tmp/npm --global
RUN npm config set fetch-retries 5
RUN npm config set fetch-retry-mintimeout 100000
RUN npm config set fetch-retry-maxtimeout 600000
ARG GIT_SHA
ARG APP_VERSION
@@ -41,17 +36,33 @@ COPY ./Common /usr/src/Common
WORKDIR /usr/src/Model
COPY ./Model/package*.json /usr/src/Model/
# Set version in ./Model/package.json to the APP_VERSION
RUN sed -i "s/\"version\": \".*\"/\"version\": \"$APP_VERSION\"/g" /usr/src/Model/package.json
RUN npm install
COPY ./Model /usr/src/Model
WORKDIR /usr/src/CommonServer
COPY ./CommonServer/package*.json /usr/src/CommonServer/
# Set version in ./CommonServer/package.json to the APP_VERSION
RUN sed -i "s/\"version\": \".*\"/\"version\": \"$APP_VERSION\"/g" /usr/src/CommonServer/package.json
RUN npm install
COPY ./CommonServer /usr/src/CommonServer
# Install CommonUI
WORKDIR /usr/src/CommonUI
COPY ./CommonUI/package*.json /usr/src/CommonUI/
# Set version in ./CommonUI/package.json to the APP_VERSION
RUN sed -i "s/\"version\": \".*\"/\"version\": \"$APP_VERSION\"/g" /usr/src/CommonUI/package.json
RUN npm install --force
COPY ./CommonUI /usr/src/CommonUI
@@ -69,11 +80,12 @@ RUN npm install
# - 3003: accounts
EXPOSE 3003
RUN npm i -D webpack-cli
{{ if eq .Env.ENVIRONMENT "development" }}
RUN mkdir /usr/src/app/dev-env
RUN touch /usr/src/app/dev-env/.env
RUN npm i -D webpack-dev-server
#Run the app
CMD [ "npm", "run", "dev" ]
@@ -83,8 +95,6 @@ COPY ./Accounts /usr/src/app
# Bundle app source
RUN npm run build
# Set permission to write logs and cache in case container run as non root
RUN chown -R 1000:1000 "/tmp/npm" && chmod -R 2777 "/tmp/npm"
#Run the app
CMD [ "npm", "start" ]
{{ end }}

View File

@@ -35,7 +35,7 @@ See the section about [deployment](https://facebook.github.io/create-react-app/d
If you arent satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
Instead, it will copy all the configuration files and the transitive dependencies ( Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point youre on your own.
Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point youre on your own.
You dont have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldnt feel obligated to use this feature. However we understand that this tool wouldnt be useful if you couldnt customize it when you are ready for it.

View File

@@ -1,8 +1,7 @@
import { PromiseVoidFunction } from "Common/Types/FunctionTypes";
import Express, { ExpressApplication } from "Common/Server/Utils/Express";
import logger from "Common/Server/Utils/Logger";
import App from "Common/Server/Utils/StartServer";
import "ejs";
import Express, { ExpressApplication } from "CommonServer/Utils/Express";
import logger from "CommonServer/Utils/Logger";
import App from "CommonServer/Utils/StartServer";
export const APP_NAME: string = "accounts";

View File

@@ -1,12 +0,0 @@
const { createConfig, build, watch } = require('Common/UI/esbuild-config');
const config = createConfig({
serviceName: 'Accounts',
publicPath: '/accounts/dist/',
});
if (process.argv.includes('--watch')) {
watch(config, 'Accounts');
} else {
build(config, 'Accounts');
}

View File

@@ -1,14 +1,4 @@
{
"watch": ["./","../Common/UI", "../Common/Types", "../Common/Utils", "../Common/Models"],
"ext": "ts,json,tsx,env,js,jsx,hbs",
"ignore": [
"./public/**",
"./public/dist/**",
"./build/*",
"./build/**",
"./build/dist/*",
"./build/dist/**",
"../Common/Server/**"
],
"exec": "npm run dev-build && npm run start"
"watch": ["webpack.config.js"],
"exec": "export DEBUG=express:* && printenv > /usr/src/app/dev-env/.env && echo 'USE_HTTPS=false' >> /usr/src/app/dev-env/.env && webpack-dev-server --port=3003 --mode=development"
}

File diff suppressed because it is too large Load Diff

View File

@@ -3,10 +3,8 @@
"version": "0.1.0",
"private": false,
"scripts": {
"dev-build": "NODE_ENV=development node esbuild.config.js",
"dev": "npx nodemon",
"build": "NODE_ENV=production node esbuild.config.js",
"analyze": "analyze=true NODE_ENV=production node esbuild.config.js",
"build": "webpack build --mode=production",
"test": "",
"compile": "tsc",
"clear-modules": "rm -rf node_modules && rm package-lock.json && npm install",
@@ -29,11 +27,19 @@
},
"dependencies": {
"Common": "file:../Common",
"ejs": "^3.1.10",
"CommonServer": "file:../CommonServer",
"CommonUI": "file:../CommonUI",
"css-loader": "^6.11.0",
"dotenv": "^16.4.5",
"express": "^4.19.2",
"file-loader": "^6.2.0",
"Model": "file:../Model",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-router-dom": "^6.23.1",
"sass-loader": "^13.3.3",
"style-loader": "^3.3.4",
"ts-loader": "^9.5.1",
"use-async-effect": "^2.2.7"
},
"devDependencies": {
@@ -42,7 +48,7 @@
"@types/react-dom": "^18.0.4",
"@types/react-router-dom": "^5.3.3",
"nodemon": "^2.0.20",
"ts-node": "^10.9.1"
"ts-node": "^10.9.1",
"webpack": "^5.76.0"
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@@ -12,7 +12,6 @@
<meta name="slack-app-id" content="ACVBMTPJQ">
<meta name="description" content="OneUptime — the complete open-source observability platform.">
<% if(typeof enableGoogleTagManager !== 'undefined' ? enableGoogleTagManager : false){ %>
<!-- Google Tag Manager -->
<script>(function (w, d, s, l, i) {
w[l] = w[l] || []; w[l].push({
@@ -23,7 +22,6 @@
'https://www.googletagmanager.com/gtm.js?id=' + i + dl; f.parentNode.insertBefore(j, f);
})(window, document, 'script', 'dataLayer', 'GTM-PKQD5WH');</script>
<!-- End Google Tag Manager -->
<% } %>
<link rel="manifest" href="/accounts/assets/img/favicons/ma">
@@ -75,11 +73,18 @@
width: auto;
}
</style>
<script src="/accounts/assets/js/tailwind-3.4.5.js"></script>
<script src="https://cdn.tailwindcss.com"></script>
<title>OneUptime Accounts</title>
<!-- Preload light, regular, medium and bold, which are fonts that are used on home -->
<link rel="preload" href="/accounts/assets/fonts/camphor/font1.woff2" as="font" type="font/woff2" crossorigin="">
<link rel="preload" href="/accounts/assets/fonts/camphor/font2.woff2" as="font" type="font/woff2" crossorigin="">
<link rel="preload" href="/accounts/assets/fonts/camphor/font3.woff2" as="font" type="font/woff2" crossorigin="">
<link rel="preload" href="/accounts/assets/fonts/camphor/font4.woff2" as="font" type="font/woff2" crossorigin="">
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
@@ -97,16 +102,14 @@
</head>
<body class="h-full bg-gray-50">
<% if(typeof enableGoogleTagManager !== 'undefined' ? enableGoogleTagManager : false){ %>
<!-- Google Tag Manager (noscript) -->
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-PKQD5WH" height="0" width="0"
style="display:none;visibility:hidden"></iframe></noscript>
<!-- End Google Tag Manager (noscript) -->
<% } %>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<script type="module" src="/accounts/dist/Index.js"></script>
<script src="/accounts/dist/bundle.js"></script>
<script>
tailwind.config = {
theme: {

View File

@@ -1,4 +1,12 @@
import React, { ReactElement, lazy, Suspense } from "react";
import ForgotPasswordPage from "./Pages/ForgotPassword";
import LoginPage from "./Pages/Login";
import LoginWithSSO from "./Pages/LoginWithSSO";
import NotFound from "./Pages/NotFound";
import RegisterPage from "./Pages/Register";
import ResetPasswordPage from "./Pages/ResetPassword";
import VerifyEmail from "./Pages/VerifyEmail";
import Navigation from "CommonUI/src/Utils/Navigation";
import React, { ReactElement } from "react";
import {
Route,
Routes,
@@ -6,38 +14,6 @@ import {
useNavigate,
useParams,
} from "react-router-dom";
import Navigation from "Common/UI/Utils/Navigation";
import PageLoader from "Common/UI/Components/Loader/PageLoader";
// Lazy load page components
const ForbiddenPage: React.LazyExoticComponent<() => JSX.Element> = lazy(() => {
return import("./Pages/Forbidden");
});
const ForgotPasswordPage: React.LazyExoticComponent<() => JSX.Element> = lazy(
() => {
return import("./Pages/ForgotPassword");
},
);
const LoginPage: React.LazyExoticComponent<() => JSX.Element> = lazy(() => {
return import("./Pages/Login");
});
const LoginWithSSO: React.LazyExoticComponent<() => JSX.Element> = lazy(() => {
return import("./Pages/LoginWithSSO");
});
const NotFound: React.LazyExoticComponent<() => JSX.Element> = lazy(() => {
return import("./Pages/NotFound");
});
const RegisterPage: React.LazyExoticComponent<() => JSX.Element> = lazy(() => {
return import("./Pages/Register");
});
const ResetPasswordPage: React.LazyExoticComponent<() => JSX.Element> = lazy(
() => {
return import("./Pages/ResetPassword");
},
);
const VerifyEmail: React.LazyExoticComponent<() => JSX.Element> = lazy(() => {
return import("./Pages/VerifyEmail");
});
function App(): ReactElement {
Navigation.setNavigateHook(useNavigate());
@@ -46,29 +22,24 @@ function App(): ReactElement {
return (
<div className="m-auto h-screen">
<Suspense fallback={<PageLoader isVisible={true} />}>
<Routes>
<Route path="/accounts" element={<LoginPage />} />
<Route path="/accounts/login" element={<LoginPage />} />
<Route path="/accounts/forbidden" element={<ForbiddenPage />} />
<Route path="/accounts/sso" element={<LoginWithSSO />} />
<Route
path="/accounts/forgot-password"
element={<ForgotPasswordPage />}
/>
<Route
path="/accounts/reset-password/:token"
element={<ResetPasswordPage />}
/>
<Route path="/accounts/register" element={<RegisterPage />} />
<Route
path="/accounts/verify-email/:token"
element={<VerifyEmail />}
/>
{/* 👇️ only match this when no other routes match */}
<Route path="*" element={<NotFound />} />
</Routes>
</Suspense>
<Routes>
<Route path="/accounts" element={<LoginPage />} />
<Route path="/accounts/login" element={<LoginPage />} />
<Route path="/accounts/sso" element={<LoginWithSSO />} />
<Route
path="/accounts/forgot-password"
element={<ForgotPasswordPage />}
/>
<Route
path="/accounts/reset-password/:token"
element={<ResetPasswordPage />}
/>
<Route path="/accounts/register" element={<RegisterPage />} />
<Route path="/accounts/verify-email/:token" element={<VerifyEmail />} />
{/* 👇️ only match this when no other routes match */}
<Route path="*" element={<NotFound />} />
</Routes>
</div>
);
}

View File

@@ -1,11 +1,11 @@
import App from "./App";
import Telemetry from "Common/UI/Utils/Telemetry/Telemetry";
import Telemetry from "CommonUI/src/Utils/Telemetry";
import React from "react";
import ReactDOM from "react-dom/client";
import { BrowserRouter } from "react-router-dom";
Telemetry.init({
serviceName: "accounts",
serviceName: "Accounts",
});
const root: any = ReactDOM.createRoot(

View File

@@ -1,18 +0,0 @@
import React from "react";
const ForbiddenPage: () => JSX.Element = () => {
return (
<div className="flex min-h-full flex-col justify-center py-12 sm:px-6 lg:px-8">
<div className="sm:mx-auto sm:w-full sm:max-w-md">
<h2 className="mt-6 text-center text-2xl tracking-tight text-gray-900">
Forbidden
</h2>
<p className="mt-2 text-center text-sm text-gray-600">
You do not have permission to access this page.
</p>
</div>
</div>
);
};
export default ForbiddenPage;

View File

@@ -1,11 +1,11 @@
import { FORGOT_PASSWORD_API_URL } from "../Utils/ApiPaths";
import Route from "Common/Types/API/Route";
import URL from "Common/Types/API/URL";
import ModelForm, { FormType } from "Common/UI/Components/Forms/ModelForm";
import FormFieldSchemaType from "Common/UI/Components/Forms/Types/FormFieldSchemaType";
import Link from "Common/UI/Components/Link/Link";
import OneUptimeLogo from "Common/UI/Images/logos/OneUptimeSVG/3-transparent.svg";
import User from "Common/Models/DatabaseModels/User";
import ModelForm, { FormType } from "CommonUI/src/Components/Forms/ModelForm";
import FormFieldSchemaType from "CommonUI/src/Components/Forms/Types/FormFieldSchemaType";
import Link from "CommonUI/src/Components/Link/Link";
import OneUptimeLogo from "CommonUI/src/Images/logos/OneUptimeSVG/3-transparent.svg";
import User from "Model/Models/User";
import React, { useState } from "react";
const ForgotPassword: () => JSX.Element = () => {
@@ -56,7 +56,6 @@ const ForgotPassword: () => JSX.Element = () => {
title: "Email",
fieldType: FormFieldSchemaType.Email,
required: true,
disableSpellCheck: true,
},
]}
onSuccess={() => {

View File

@@ -1,28 +1,19 @@
import {
LOGIN_API_URL,
VERIFY_TWO_FACTOR_AUTH_API_URL,
} from "../Utils/ApiPaths";
import { LOGIN_API_URL } from "../Utils/ApiPaths";
import Route from "Common/Types/API/Route";
import URL from "Common/Types/API/URL";
import { JSONArray, JSONObject } from "Common/Types/JSON";
import ModelForm, { FormType } from "Common/UI/Components/Forms/ModelForm";
import FormFieldSchemaType from "Common/UI/Components/Forms/Types/FormFieldSchemaType";
import Link from "Common/UI/Components/Link/Link";
import { DASHBOARD_URL } from "Common/UI/Config";
import OneUptimeLogo from "Common/UI/Images/logos/OneUptimeSVG/3-transparent.svg";
import UiAnalytics from "Common/UI/Utils/Analytics";
import LoginUtil from "Common/UI/Utils/Login";
import UserTwoFactorAuth from "Common/Models/DatabaseModels/UserTwoFactorAuth";
import Navigation from "Common/UI/Utils/Navigation";
import UserUtil from "Common/UI/Utils/User";
import User from "Common/Models/DatabaseModels/User";
import { JSONObject } from "Common/Types/JSON";
import ModelForm, { FormType } from "CommonUI/src/Components/Forms/ModelForm";
import FormFieldSchemaType from "CommonUI/src/Components/Forms/Types/FormFieldSchemaType";
import Link from "CommonUI/src/Components/Link/Link";
import { DASHBOARD_URL } from "CommonUI/src/Config";
import OneUptimeLogo from "CommonUI/src/Images/logos/OneUptimeSVG/3-transparent.svg";
import UiAnalytics from "CommonUI/src/Utils/Analytics";
import LoginUtil from "CommonUI/src/Utils/Login";
import Navigation from "CommonUI/src/Utils/Navigation";
import UserUtil from "CommonUI/src/Utils/User";
import User from "Model/Models/User";
import React from "react";
import useAsyncEffect from "use-async-effect";
import StaticModelList from "Common/UI/Components/ModelList/StaticModelList";
import BasicForm from "Common/UI/Components/Forms/BasicForm";
import API from "Common/UI/Utils/API/API";
import HTTPErrorResponse from "Common/Types/API/HTTPErrorResponse";
import HTTPResponse from "Common/Types/API/HTTPResponse";
const LoginPage: () => JSX.Element = () => {
const apiUrl: URL = LOGIN_API_URL;
@@ -33,22 +24,6 @@ const LoginPage: () => JSX.Element = () => {
const [initialValues, setInitialValues] = React.useState<JSONObject>({});
const [showTwoFactorAuth, setShowTwoFactorAuth] =
React.useState<boolean>(false);
const [twoFactorAuthList, setTwoFactorAuthList] = React.useState<
UserTwoFactorAuth[]
>([]);
const [selectedTwoFactorAuth, setSelectedTwoFactorAuth] = React.useState<
UserTwoFactorAuth | undefined
>(undefined);
const [isTwoFactorAuthLoading, setIsTwoFactorAuthLoading] =
React.useState<boolean>(false);
const [twofactorAuthError, setTwoFactorAuthError] =
React.useState<string>("");
useAsyncEffect(async () => {
if (Navigation.getQueryStringByName("email")) {
setInitialValues({
@@ -57,20 +32,6 @@ const LoginPage: () => JSX.Element = () => {
}
}, []);
type LoginFunction = (user: User, miscData: JSONObject) => void;
const login: LoginFunction = (user: User, miscData: JSONObject): void => {
if (user instanceof User && user && user.email) {
UiAnalytics.userAuth(user.email);
UiAnalytics.capture("accounts/login");
}
LoginUtil.login({
user: user,
token: miscData ? miscData["token"] : undefined,
});
};
return (
<div className="flex min-h-full flex-col justify-center py-12 sm:px-6 lg:px-8">
<div className="">
@@ -79,213 +40,89 @@ const LoginPage: () => JSX.Element = () => {
src={OneUptimeLogo}
alt="OneUptime"
/>
{!showTwoFactorAuth && (
<>
<h2 className="mt-6 text-center text-2xl tracking-tight text-gray-900">
Sign in to your account
</h2>
<p className="mt-2 text-center text-sm text-gray-600">
Join thousands of business that use OneUptime to help them stay
online all the time.
</p>
</>
)}
{showTwoFactorAuth && (
<>
<h2 className="mt-6 text-center text-2xl tracking-tight text-gray-900">
Two Factor Authentication
</h2>
<p className="mt-2 text-center text-sm text-gray-600">
Select two factor authentication method. You will be asked to
enter a code from the selected method.
</p>
</>
)}
<h2 className="mt-6 text-center text-2xl tracking-tight text-gray-900">
Sign in to your account
</h2>
<p className="mt-2 text-center text-sm text-gray-600">
Join thousands of business that use OneUptime to help them stay online
all the time.
</p>
</div>
<div className="mt-8 sm:mx-auto sm:w-full sm:max-w-md">
<div className="bg-white py-8 px-4 shadow sm:rounded-lg sm:px-10">
{!showTwoFactorAuth && (
<ModelForm<User>
modelType={User}
id="login-form"
name="Login"
fields={[
{
field: {
email: true,
},
fieldType: FormFieldSchemaType.Email,
placeholder: "jeff@example.com",
required: true,
disabled: Boolean(initialValues && initialValues["email"]),
title: "Email",
dataTestId: "email",
disableSpellCheck: true,
<ModelForm<User>
modelType={User}
id="login-form"
name="Login"
fields={[
{
field: {
email: true,
},
{
field: {
password: true,
},
title: "Password",
required: true,
validation: {
minLength: 6,
},
fieldType: FormFieldSchemaType.Password,
sideLink: {
text: "Forgot password?",
url: new Route("/accounts/forgot-password"),
openLinkInNewTab: false,
},
dataTestId: "password",
disableSpellCheck: true,
fieldType: FormFieldSchemaType.Email,
placeholder: "jeff@example.com",
required: true,
disabled: Boolean(initialValues && initialValues["email"]),
title: "Email",
dataTestId: "email",
},
{
field: {
password: true,
},
]}
createOrUpdateApiUrl={apiUrl}
formType={FormType.Create}
submitButtonText={"Login"}
onBeforeCreate={(data: User) => {
setInitialValues(User.toJSON(data, User));
return Promise.resolve(data);
}}
onSuccess={(
value: User | JSONObject,
miscData: JSONObject | undefined,
) => {
if (
miscData &&
(miscData as JSONObject)["twoFactorAuth"] === true
) {
const twoFactorAuthList: Array<UserTwoFactorAuth> =
UserTwoFactorAuth.fromJSONArray(
(miscData as JSONObject)[
"twoFactorAuthList"
] as JSONArray,
UserTwoFactorAuth,
);
setTwoFactorAuthList(twoFactorAuthList);
setShowTwoFactorAuth(true);
return;
}
login(value as User, miscData as JSONObject);
}}
maxPrimaryButtonWidth={true}
footer={
<div className="actions text-center mt-4 hover:underline fw-semibold">
<div>
<Link to={new Route("/accounts/sso")}>
<div className="text-indigo-500 hover:text-indigo-900 cursor-pointer text-sm">
Use single sign-on (SSO) instead
</div>
</Link>
</div>
</div>
title: "Password",
required: true,
validation: {
minLength: 6,
},
fieldType: FormFieldSchemaType.Password,
sideLink: {
text: "Forgot password?",
url: new Route("/accounts/forgot-password"),
openLinkInNewTab: false,
},
dataTestId: "password",
},
]}
createOrUpdateApiUrl={apiUrl}
formType={FormType.Create}
submitButtonText={"Login"}
onSuccess={(value: User, miscData: JSONObject | undefined) => {
if (value && value.email) {
UiAnalytics.userAuth(value.email);
UiAnalytics.capture("accounts/login");
}
/>
)}
{showTwoFactorAuth && !selectedTwoFactorAuth && (
<StaticModelList<UserTwoFactorAuth>
titleField="name"
descriptionField=""
selectedItems={[]}
list={twoFactorAuthList}
onClick={(item: UserTwoFactorAuth) => {
setSelectedTwoFactorAuth(item);
}}
/>
)}
{showTwoFactorAuth && selectedTwoFactorAuth && (
<BasicForm
id="two-factor-auth-form"
name="Two Factor Auth"
fields={[
{
field: {
code: true,
},
title: "Code",
description: "Enter the code from your authenticator app",
required: true,
dataTestId: "code",
fieldType: FormFieldSchemaType.Text,
},
]}
submitButtonText={"Login"}
maxPrimaryButtonWidth={true}
isLoading={isTwoFactorAuthLoading}
error={twofactorAuthError}
onSubmit={async (data: JSONObject) => {
setIsTwoFactorAuthLoading(true);
try {
const code: string = data["code"] as string;
const twoFactorAuthId: string =
selectedTwoFactorAuth.id?.toString() as string;
const result: HTTPErrorResponse | HTTPResponse<JSONObject> =
await API.post(VERIFY_TWO_FACTOR_AUTH_API_URL, {
data: {
...initialValues,
code: code,
twoFactorAuthId: twoFactorAuthId,
},
});
if (result instanceof HTTPErrorResponse) {
throw result;
}
const user: User = User.fromJSON(
result["data"] as JSONObject,
User,
) as User;
const miscData: JSONObject = (result["data"] as JSONObject)[
"miscData"
] as JSONObject;
login(user as User, miscData as JSONObject);
} catch (error) {
setTwoFactorAuthError(
API.getFriendlyErrorMessage(error as Error),
);
}
setIsTwoFactorAuthLoading(false);
}}
/>
)}
LoginUtil.login({
user: value,
token: miscData ? miscData["token"] : undefined,
});
}}
maxPrimaryButtonWidth={true}
footer={
<div className="actions text-center mt-4 hover:underline fw-semibold">
<div>
<Link to={new Route("/accounts/sso")}>
<div className="text-indigo-500 hover:text-indigo-900 cursor-pointer text-sm">
Use single sign-on (SSO) instead
</div>
</Link>
</div>
</div>
}
/>
</div>
<div className="mt-10 text-center">
{!selectedTwoFactorAuth && (
<div className="text-muted mb-0 text-gray-500">
Don&apos;t have an account?{" "}
<Link
to={new Route("/accounts/register")}
className="text-indigo-500 hover:text-indigo-900 cursor-pointer"
>
Register.
</Link>
</div>
)}
{selectedTwoFactorAuth ? (
<div className="text-muted mb-0 text-gray-500">
<Link
onClick={() => {
setSelectedTwoFactorAuth(undefined);
}}
className="text-indigo-500 hover:text-indigo-900 cursor-pointer"
>
Select a different two factor authentication method
</Link>
</div>
) : (
<></>
)}
<div className="text-muted mb-0 text-gray-500">
Don&apos;t have an account?{" "}
<Link
to={new Route("/accounts/register")}
className="text-indigo-500 hover:text-indigo-900 cursor-pointer"
>
Register.
</Link>
</div>
</div>
</div>
</div>

View File

@@ -2,22 +2,22 @@ import { SERVICE_PROVIDER_LOGIN_URL } from "../Utils/ApiPaths";
import Route from "Common/Types/API/Route";
import URL from "Common/Types/API/URL";
import { JSONArray, JSONObject } from "Common/Types/JSON";
import FormFieldSchemaType from "Common/UI/Components/Forms/Types/FormFieldSchemaType";
import Link from "Common/UI/Components/Link/Link";
import { DASHBOARD_URL, IDENTITY_URL } from "Common/UI/Config";
import OneUptimeLogo from "Common/UI/Images/logos/OneUptimeSVG/3-transparent.svg";
import Navigation from "Common/UI/Utils/Navigation";
import UserUtil from "Common/UI/Utils/User";
import User from "Common/Models/DatabaseModels/User";
import FormFieldSchemaType from "CommonUI/src/Components/Forms/Types/FormFieldSchemaType";
import Link from "CommonUI/src/Components/Link/Link";
import { DASHBOARD_URL, IDENTITY_URL } from "CommonUI/src/Config";
import OneUptimeLogo from "CommonUI/src/Images/logos/OneUptimeSVG/3-transparent.svg";
import Navigation from "CommonUI/src/Utils/Navigation";
import UserUtil from "CommonUI/src/Utils/User";
import User from "Model/Models/User";
import React, { ReactElement, useState } from "react";
import ProjectSSO from "Common/Models/DatabaseModels/ProjectSso";
import PageLoader from "Common/UI/Components/Loader/PageLoader";
import API from "Common/UI/Utils/API/API";
import BasicForm from "Common/UI/Components/Forms/BasicForm";
import ProjectSSO from "Model/Models/ProjectSso";
import PageLoader from "CommonUI/src/Components/Loader/PageLoader";
import API from "CommonUI/src/Utils/API/API";
import BasicForm from "CommonUI/src/Components/Forms/BasicForm";
import Email from "Common/Types/Email";
import HTTPErrorResponse from "Common/Types/API/HTTPErrorResponse";
import HTTPResponse from "Common/Types/API/HTTPResponse";
import StaticModelList from "Common/UI/Components/ModelList/StaticModelList";
import StaticModelList from "CommonUI/src/Components/ModelList/StaticModelList";
const LoginPage: () => JSX.Element = () => {
const apiUrl: URL = SERVICE_PROVIDER_LOGIN_URL;
@@ -196,7 +196,6 @@ const LoginPage: () => JSX.Element = () => {
required: true,
title: "Email",
dataTestId: "email",
disableSpellCheck: true,
},
]}
maxPrimaryButtonWidth={true}
@@ -209,7 +208,7 @@ const LoginPage: () => JSX.Element = () => {
<div>
<Link to={new Route("/accounts/login")}>
<div className="text-indigo-500 hover:text-indigo-900 cursor-pointer text-sm">
Use username and password instead.
Use username and password insead.
</div>
</Link>
</div>

View File

@@ -3,23 +3,23 @@ import Route from "Common/Types/API/Route";
import URL from "Common/Types/API/URL";
import Dictionary from "Common/Types/Dictionary";
import { JSONObject } from "Common/Types/JSON";
import ErrorMessage from "Common/UI/Components/ErrorMessage/ErrorMessage";
import ModelForm, { FormType } from "Common/UI/Components/Forms/ModelForm";
import Fields from "Common/UI/Components/Forms/Types/Fields";
import FormFieldSchemaType from "Common/UI/Components/Forms/Types/FormFieldSchemaType";
import Link from "Common/UI/Components/Link/Link";
import PageLoader from "Common/UI/Components/Loader/PageLoader";
import { BILLING_ENABLED, DASHBOARD_URL } from "Common/UI/Config";
import OneUptimeLogo from "Common/UI/Images/logos/OneUptimeSVG/3-transparent.svg";
import BaseAPI from "Common/UI/Utils/API/API";
import UiAnalytics from "Common/UI/Utils/Analytics";
import LocalStorage from "Common/UI/Utils/LocalStorage";
import LoginUtil from "Common/UI/Utils/Login";
import ModelAPI, { ListResult } from "Common/UI/Utils/ModelAPI/ModelAPI";
import Navigation from "Common/UI/Utils/Navigation";
import UserUtil from "Common/UI/Utils/User";
import Reseller from "Common/Models/DatabaseModels/Reseller";
import User from "Common/Models/DatabaseModels/User";
import ErrorMessage from "CommonUI/src/Components/ErrorMessage/ErrorMessage";
import ModelForm, { FormType } from "CommonUI/src/Components/Forms/ModelForm";
import Fields from "CommonUI/src/Components/Forms/Types/Fields";
import FormFieldSchemaType from "CommonUI/src/Components/Forms/Types/FormFieldSchemaType";
import Link from "CommonUI/src/Components/Link/Link";
import PageLoader from "CommonUI/src/Components/Loader/PageLoader";
import { BILLING_ENABLED, DASHBOARD_URL } from "CommonUI/src/Config";
import OneUptimeLogo from "CommonUI/src/Images/logos/OneUptimeSVG/3-transparent.svg";
import BaseAPI from "CommonUI/src/Utils/API/API";
import UiAnalytics from "CommonUI/src/Utils/Analytics";
import LocalStorage from "CommonUI/src/Utils/LocalStorage";
import LoginUtil from "CommonUI/src/Utils/Login";
import ModelAPI, { ListResult } from "CommonUI/src/Utils/ModelAPI/ModelAPI";
import Navigation from "CommonUI/src/Utils/Navigation";
import UserUtil from "CommonUI/src/Utils/User";
import Reseller from "Model/Models/Reseller";
import User from "Model/Models/User";
import React, { useState } from "react";
import useAsyncEffect from "use-async-effect";
@@ -104,7 +104,6 @@ const RegisterPage: () => JSX.Element = () => {
disabled: Boolean(initialValues && initialValues["email"]),
title: "Email",
dataTestId: "email",
disableSpellCheck: true,
},
{
field: {
@@ -115,7 +114,6 @@ const RegisterPage: () => JSX.Element = () => {
required: true,
title: "Full Name",
dataTestId: "name",
disableSpellCheck: true,
},
];
@@ -130,7 +128,6 @@ const RegisterPage: () => JSX.Element = () => {
required: true,
title: "Company Name",
dataTestId: "companyName",
disableSpellCheck: true,
},
]);
@@ -162,7 +159,6 @@ const RegisterPage: () => JSX.Element = () => {
title: "Password",
required: true,
dataTestId: "password",
disableSpellCheck: true,
},
{
field: {
@@ -179,12 +175,11 @@ const RegisterPage: () => JSX.Element = () => {
required: true,
showEvenIfPermissionDoesNotExist: true,
dataTestId: "confirmPassword",
disableSpellCheck: true,
},
]);
if (error) {
return <ErrorMessage message={error} />;
return <ErrorMessage error={error} />;
}
if (isLoading) {

View File

@@ -1,12 +1,12 @@
import { RESET_PASSWORD_API_URL } from "../Utils/ApiPaths";
import Route from "Common/Types/API/Route";
import URL from "Common/Types/API/URL";
import ModelForm, { FormType } from "Common/UI/Components/Forms/ModelForm";
import FormFieldSchemaType from "Common/UI/Components/Forms/Types/FormFieldSchemaType";
import Link from "Common/UI/Components/Link/Link";
import OneUptimeLogo from "Common/UI/Images/logos/OneUptimeSVG/3-transparent.svg";
import Navigation from "Common/UI/Utils/Navigation";
import User from "Common/Models/DatabaseModels/User";
import ModelForm, { FormType } from "CommonUI/src/Components/Forms/ModelForm";
import FormFieldSchemaType from "CommonUI/src/Components/Forms/Types/FormFieldSchemaType";
import Link from "CommonUI/src/Components/Link/Link";
import OneUptimeLogo from "CommonUI/src/Images/logos/OneUptimeSVG/3-transparent.svg";
import Navigation from "CommonUI/src/Utils/Navigation";
import User from "Model/Models/User";
import React, { useState } from "react";
const RegisterPage: () => JSX.Element = () => {
@@ -68,7 +68,6 @@ const RegisterPage: () => JSX.Element = () => {
title: "New Password",
required: true,
showEvenIfPermissionDoesNotExist: true,
disableSpellCheck: true,
},
{
field: {
@@ -84,7 +83,6 @@ const RegisterPage: () => JSX.Element = () => {
overrideFieldKey: "confirmPassword",
required: true,
showEvenIfPermissionDoesNotExist: true,
disableSpellCheck: true,
},
]}
createOrUpdateApiUrl={apiUrl}

View File

@@ -3,14 +3,14 @@ import Route from "Common/Types/API/Route";
import URL from "Common/Types/API/URL";
import { PromiseVoidFunction } from "Common/Types/FunctionTypes";
import ObjectID from "Common/Types/ObjectID";
import { FormType } from "Common/UI/Components/Forms/ModelForm";
import Link from "Common/UI/Components/Link/Link";
import PageLoader from "Common/UI/Components/Loader/PageLoader";
import OneUptimeLogo from "Common/UI/Images/logos/OneUptimeSVG/3-transparent.svg";
import API from "Common/UI/Utils/API/API";
import ModelAPI from "Common/UI/Utils/ModelAPI/ModelAPI";
import Navigation from "Common/UI/Utils/Navigation";
import EmailVerificationToken from "Common/Models/DatabaseModels/EmailVerificationToken";
import { FormType } from "CommonUI/src/Components/Forms/ModelForm";
import Link from "CommonUI/src/Components/Link/Link";
import PageLoader from "CommonUI/src/Components/Loader/PageLoader";
import OneUptimeLogo from "CommonUI/src/Images/logos/OneUptimeSVG/3-transparent.svg";
import API from "CommonUI/src/Utils/API/API";
import ModelAPI from "CommonUI/src/Utils/ModelAPI/ModelAPI";
import Navigation from "CommonUI/src/Utils/Navigation";
import EmailVerificationToken from "Model/Models/EmailVerificationToken";
import React, { useEffect, useState } from "react";
const VerifyEmail: () => JSX.Element = () => {

View File

@@ -1,6 +1,6 @@
import Route from "Common/Types/API/Route";
import URL from "Common/Types/API/URL";
import { IDENTITY_URL } from "Common/UI/Config";
import { IDENTITY_URL } from "CommonUI/src/Config";
export const SIGNUP_API_URL: URL = URL.fromURL(IDENTITY_URL).addRoute(
new Route("/signup"),
@@ -9,10 +9,6 @@ export const LOGIN_API_URL: URL = URL.fromURL(IDENTITY_URL).addRoute(
new Route("/login"),
);
export const VERIFY_TWO_FACTOR_AUTH_API_URL: URL = URL.fromURL(
IDENTITY_URL,
).addRoute(new Route("/verify-two-factor-auth"));
export const SERVICE_PROVIDER_LOGIN_URL: URL = URL.fromURL(
IDENTITY_URL,
).addRoute(new Route("/service-provider-login"));

View File

@@ -0,0 +1,84 @@
require("ts-loader");
require("file-loader");
require("style-loader");
require("css-loader");
require("sass-loader");
const path = require("path");
const webpack = require("webpack");
const dotenv = require("dotenv");
const express = require("express");
const readEnvFile = (pathToFile) => {
const parsed = dotenv.config({ path: pathToFile }).parsed;
const env = {};
for (const key in parsed) {
env[key] = JSON.stringify(parsed[key]);
}
return env;
};
module.exports = {
entry: "./src/Index.tsx",
mode: "development",
output: {
filename: "bundle.js",
path: path.resolve(__dirname, "public", "dist"),
publicPath: "/accounts/dist/",
},
resolve: {
extensions: [".ts", ".tsx", ".js", ".jsx", ".json", ".css", ".scss"],
alias: {
react: path.resolve("./node_modules/react"),
},
},
externals: {
"react-native-sqlite-storage": "react-native-sqlite-storage",
},
plugins: [
new webpack.DefinePlugin({
process: {
env: {
...readEnvFile("/usr/src/app/dev-env/.env"),
},
},
}),
],
module: {
rules: [
{
test: /\.(ts|tsx)$/,
use: "ts-loader",
},
{
test: /\.s[ac]ss$/i,
use: ["style-loader", "css-loader", "sass-loader"],
},
{
test: /\.css$/i,
use: ["style-loader", "css-loader"],
},
{
test: /\.(jpe?g|png|gif|svg)$/i,
loader: "file-loader",
},
],
},
devServer: {
historyApiFallback: true,
devMiddleware: {
writeToDisk: true,
},
allowedHosts: "all",
setupMiddlewares: (middlewares, devServer) => {
devServer.app.use(
"/accounts/assets",
express.static(path.resolve(__dirname, "public", "assets")),
);
return middlewares;
},
},
devtool: "eval-source-map",
};

View File

@@ -3,14 +3,9 @@
#
# Pull base image nodejs image.
FROM public.ecr.aws/docker/library/node:23.8-alpine3.21
FROM node:21.7.3-alpine3.18
RUN mkdir /tmp/npm && chmod 2777 /tmp/npm && chown 1000:1000 /tmp/npm && npm config set cache /tmp/npm --global
RUN npm config set fetch-retries 5
RUN npm config set fetch-retry-mintimeout 100000
RUN npm config set fetch-retry-maxtimeout 600000
ARG GIT_SHA
ARG APP_VERSION
@@ -40,17 +35,33 @@ RUN npm install
COPY ./Common /usr/src/Common
WORKDIR /usr/src/Model
COPY ./Model/package*.json /usr/src/Model/
# Set version in ./Model/package.json to the APP_VERSION
RUN sed -i "s/\"version\": \".*\"/\"version\": \"$APP_VERSION\"/g" /usr/src/Model/package.json
RUN npm install
COPY ./Model /usr/src/Model
WORKDIR /usr/src/CommonServer
COPY ./CommonServer/package*.json /usr/src/CommonServer/
# Set version in ./CommonServer/package.json to the APP_VERSION
RUN sed -i "s/\"version\": \".*\"/\"version\": \"$APP_VERSION\"/g" /usr/src/CommonServer/package.json
RUN npm install
COPY ./CommonServer /usr/src/CommonServer
# Install CommonUI
WORKDIR /usr/src/CommonUI
COPY ./CommonUI/package*.json /usr/src/CommonUI/
# Set version in ./CommonUI/package.json to the APP_VERSION
RUN sed -i "s/\"version\": \".*\"/\"version\": \"$APP_VERSION\"/g" /usr/src/CommonUI/package.json
RUN npm install --force
COPY ./CommonUI /usr/src/CommonUI
@@ -67,20 +78,19 @@ RUN npm install
# - 3158: AdminDashboard
EXPOSE 3158
RUN npm i -D webpack-cli
{{ if eq .Env.ENVIRONMENT "development" }}
#Run the app
RUN mkdir /usr/src/app/dev-env
RUN touch /usr/src/app/dev-env/.env
RUN npm i -D webpack-dev-server
CMD [ "npm", "run", "dev" ]
{{ else }}
# Copy app source
COPY ./AdminDashboard /usr/src/app
# Bundle app source
RUN npm run build
# Set permission to write logs and cache in case container run as non root
RUN chown -R 1000:1000 "/tmp/npm" && chmod -R 2777 "/tmp/npm"
#Run the app
CMD [ "npm", "start" ]
{{ end }}

View File

@@ -35,7 +35,7 @@ See the section about [deployment](https://facebook.github.io/create-react-app/d
If you arent satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
Instead, it will copy all the configuration files and the transitive dependencies ( Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point youre on your own.
Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point youre on your own.
You dont have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldnt feel obligated to use this feature. However we understand that this tool wouldnt be useful if you couldnt customize it when you are ready for it.

View File

@@ -1,8 +1,7 @@
import { PromiseVoidFunction } from "Common/Types/FunctionTypes";
import Express, { ExpressApplication } from "Common/Server/Utils/Express";
import logger from "Common/Server/Utils/Logger";
import App from "Common/Server/Utils/StartServer";
import "ejs";
import Express, { ExpressApplication } from "CommonServer/Utils/Express";
import logger from "CommonServer/Utils/Logger";
import App from "CommonServer/Utils/StartServer";
export const APP_NAME: string = "admin";

View File

@@ -1,12 +0,0 @@
const { createConfig, build, watch } = require('Common/UI/esbuild-config');
const config = createConfig({
serviceName: 'AdminDashboard',
publicPath: '/admin/dist/',
});
if (process.argv.includes('--watch')) {
watch(config, 'AdminDashboard');
} else {
build(config, 'AdminDashboard');
}

View File

@@ -1,14 +1,4 @@
{
"watch": ["./","../Common/UI", "../Common/Types", "../Common/Utils", "../Common/Models"],
"ext": "ts,json,tsx,env,js,jsx,hbs",
"ignore": [
"./public/**",
"./public/dist/**",
"./build/*",
"./build/**",
"./build/dist/*",
"./build/dist/**",
"../Common/Server/**"
],
"exec": " npm run dev-build && npm run start"
"watch": ["webpack.config.js"],
"exec": "export DEBUG=express:* && printenv > /usr/src/app/dev-env/.env && echo 'USE_HTTPS=false' >> /usr/src/app/dev-env/.env && webpack-dev-server --port=3158 --mode=development"
}

File diff suppressed because it is too large Load Diff

View File

@@ -4,19 +4,21 @@
"private": false,
"dependencies": {
"Common": "file:../Common",
"ejs": "^3.1.10",
"CommonServer": "file:../CommonServer",
"CommonUI": "file:../CommonUI",
"dotenv": "^16.4.5",
"file-loader": "^6.2.0",
"Model": "file:../Model",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-router-dom": "^6.23.1"
"react-router-dom": "^6.23.1",
"style-loader": "^3.3.4"
},
"scripts": {
"dev-build": "NODE_ENV=development node esbuild.config.js",
"dev": "npx nodemon",
"build": "NODE_ENV=production node esbuild.config.js",
"analyze": "analyze=true NODE_ENV=production node esbuild.config.js",
"build": "webpack build --mode=production",
"test": "react-app-rewired test",
"eject": "echo 'esbuild does not require eject'",
"eject": "webpack eject",
"compile": "tsc",
"clear-modules": "rm -rf node_modules && rm package-lock.json && npm install",
"start": "node --require ts-node/register Serve.ts",
@@ -41,8 +43,13 @@
"@types/react": "^18.2.38",
"@types/react-dom": "^18.0.4",
"@types/react-router-dom": "^5.3.3",
"css-loader": "^6.8.1",
"nodemon": "^2.0.20",
"ts-node": "^10.9.1"
"react-app-rewired": "^2.2.1",
"sass": "^1.51.0",
"sass-loader": "^12.6.0",
"ts-loader": "^9.5.1",
"ts-node": "^10.9.1",
"webpack": "^5.76.0"
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@@ -11,7 +11,6 @@
<meta name="slack-app-id" content="ACVBMTPJQ">
<meta name="description" content="OneUptime — the complete open-source observability platform.">
<% if(typeof enableGoogleTagManager !== 'undefined' ? enableGoogleTagManager : false){ %>
<!-- Google Tag Manager -->
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
@@ -20,7 +19,6 @@
})(window,document,'script','dataLayer','GTM-PKQD5WH');
</script>
<!-- End Google Tag Manager -->
<% } %>
<link rel="manifest" href="/admin/assets/img/favicons/ma">
<link rel="apple-touch-icon" sizes="180x180" href="/admin/assets/img/favicons/apple-touch-icon.png">
@@ -68,13 +66,20 @@
width: auto;
}
</style>
<script src="/admin/assets/js/tailwind-3.4.5.js"></script>
<script src="https://cdn.tailwindcss.com"></script>
<script src="/admin/env.js"></script>
<title>OneUptime Admin Dashboard</title>
<!-- Preload light, regular, medium and bold, which are fonts that are used on home
<link rel="preload" href="/admin/assets/fonts/camphor/font1.woff2" as="font" type="font/woff2" crossorigin="">
<link rel="preload" href="/admin/assets/fonts/camphor/font2.woff2" as="font" type="font/woff2" crossorigin="">
<link rel="preload" href="/admin/assets/fonts/camphor/font3.woff2" as="font" type="font/woff2" crossorigin="">
<link rel="preload" href="/admin/assets/fonts/camphor/font4.woff2" as="font" type="font/woff2" crossorigin=""> -->
<!--
manifest.json provides metadata used when your web app is installed on a
@@ -91,16 +96,14 @@
-->
</head>
<body class="h-full bg-gray-50">
<% if(typeof enableGoogleTagManager !== 'undefined' ? enableGoogleTagManager : false){ %>
<!-- Google Tag Manager (noscript) -->
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-PKQD5WH"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<!-- End Google Tag Manager (noscript) -->
<% } %>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<script type="module" src="/admin/dist/Index.js"></script>
<script src="/admin/dist/bundle.js"></script>
<script>
tailwind.config = {
theme: {

View File

@@ -12,9 +12,9 @@ import Users from "./Pages/Users/Index";
import PageMap from "./Utils/PageMap";
import RouteMap from "./Utils/RouteMap";
import URL from "Common/Types/API/URL";
import { ACCOUNTS_URL, DASHBOARD_URL } from "Common/UI/Config";
import Navigation from "Common/UI/Utils/Navigation";
import User from "Common/UI/Utils/User";
import { ACCOUNTS_URL, DASHBOARD_URL } from "CommonUI/src/Config";
import Navigation from "CommonUI/src/Utils/Navigation";
import User from "CommonUI/src/Utils/User";
import React from "react";
import {
Route as PageRoute,
@@ -23,10 +23,6 @@ import {
useNavigate,
useParams,
} from "react-router-dom";
import UserView from "./Pages/Users/View/Index";
import UserDelete from "./Pages/Users/View/Delete";
import ProjectView from "./Pages/Projects/View/Index";
import ProjectDelete from "./Pages/Projects/View/Delete";
const App: () => JSX.Element = () => {
Navigation.setNavigateHook(useNavigate());
@@ -65,26 +61,6 @@ const App: () => JSX.Element = () => {
element={<Users />}
/>
<PageRoute
path={RouteMap[PageMap.USER_VIEW]?.toString() || ""}
element={<UserView />}
/>
<PageRoute
path={RouteMap[PageMap.USER_DELETE]?.toString() || ""}
element={<UserDelete />}
/>
<PageRoute
path={RouteMap[PageMap.PROJECT_VIEW]?.toString() || ""}
element={<ProjectView />}
/>
<PageRoute
path={RouteMap[PageMap.PROJECT_DELETE]?.toString() || ""}
element={<ProjectDelete />}
/>
<PageRoute
path={RouteMap[PageMap.LOGOUT]?.toString() || ""}
element={<Logout />}

View File

@@ -5,9 +5,9 @@ import BadDataException from "Common/Types/Exception/BadDataException";
import { PromiseVoidFunction } from "Common/Types/FunctionTypes";
import { JSONObject } from "Common/Types/JSON";
import API from "Common/Utils/API";
import Footer from "Common/UI/Components/Footer/Footer";
import ConfirmModal from "Common/UI/Components/Modal/ConfirmModal";
import { HOST, HTTP_PROTOCOL } from "Common/UI/Config";
import Footer from "CommonUI/src/Components/Footer/Footer";
import ConfirmModal from "CommonUI/src/Components/Modal/ConfirmModal";
import { HOST, HTTP_PROTOCOL } from "CommonUI/src/Config";
import React from "react";
const DashboardFooter: () => JSX.Element = () => {
@@ -67,7 +67,7 @@ const DashboardFooter: () => JSX.Element = () => {
return (
<>
<Footer
className="bg-white px-8"
className="bg-white h-16 inset-x-0 bottom-0 px-8"
copyright="HackerBay, Inc."
links={[
{

View File

@@ -1,10 +1,10 @@
import Help from "./Help";
import Logo from "./Logo";
import UserProfile from "./UserProfile";
import Button, { ButtonStyleType } from "Common/UI/Components/Button/Button";
import Header from "Common/UI/Components/Header/Header";
import { DASHBOARD_URL } from "Common/UI/Config";
import Navigation from "Common/UI/Utils/Navigation";
import Button, { ButtonStyleType } from "CommonUI/src/Components/Button/Button";
import Header from "CommonUI/src/Components/Header/Header";
import { DASHBOARD_URL } from "CommonUI/src/Config";
import Navigation from "CommonUI/src/Utils/Navigation";
import React, { FunctionComponent, ReactElement } from "react";
const DashboardHeader: FunctionComponent = (): ReactElement => {

View File

@@ -1,9 +1,9 @@
import URL from "Common/Types/API/URL";
import IconProp from "Common/Types/Icon/IconProp";
import HeaderIconDropdownButton from "Common/UI/Components/Header/HeaderIconDropdownButton";
import IconDropdownItem from "Common/UI/Components/Header/IconDropdown/IconDropdownItem";
import IconDropdownMenu from "Common/UI/Components/Header/IconDropdown/IconDropdownMenu";
import IconDropdownRow from "Common/UI/Components/Header/IconDropdown/IconDropdownRow";
import HeaderIconDropdownButton from "CommonUI/src/Components/Header/HeaderIconDropdownButton";
import IconDropdownItem from "CommonUI/src/Components/Header/IconDropdown/IconDropdownItem";
import IconDropdownMenu from "CommonUI/src/Components/Header/IconDropdown/IconDropdownMenu";
import IconDropdownRow from "CommonUI/src/Components/Header/IconDropdown/IconDropdownRow";
import React, { ReactElement, useState } from "react";
const Help: () => JSX.Element = (): ReactElement => {
@@ -37,7 +37,7 @@ const Help: () => JSX.Element = (): ReactElement => {
setIsDropdownVisible(false);
}}
url={URL.fromString(
"https://join.slack.com/t/oneuptimesupport/shared_invite/zt-2pz5p1uhe-Fpmc7bv5ZE5xRMe7qJnwmA",
"https://join.slack.com/t/oneuptimesupport/shared_invite/zt-1kavkds2f-gegm_wePorvwvM3M_SaoCQ",
)}
/>
<IconDropdownItem

View File

@@ -1,7 +1,7 @@
// Tailwind
import Route from "Common/Types/API/Route";
import Image from "Common/UI/Components/Image/Image";
import OneUptimeLogo from "Common/UI/Images/logos/OneUptimeSVG/3-transparent.svg";
import Image from "CommonUI/src/Components/Image/Image";
import OneUptimeLogo from "CommonUI/src/Images/logos/OneUptimeSVG/3-transparent.svg";
import React, { FunctionComponent, ReactElement } from "react";
export interface ComponentProps {
@@ -17,9 +17,7 @@ const Logo: FunctionComponent<ComponentProps> = (
<Image
className="block h-8 w-auto"
onClick={() => {
if (props.onClick) {
props.onClick();
}
props.onClick && props.onClick();
}}
imageUrl={Route.fromString(`${OneUptimeLogo}`)}
alt={"OneUptime"}

View File

@@ -1,7 +1,7 @@
import IconProp from "Common/Types/Icon/IconProp";
import HeaderIconDropdownButton from "Common/UI/Components/Header/HeaderIconDropdownButton";
import NotificationItem from "Common/UI/Components/Header/Notifications/NotificationItem";
import Notifications from "Common/UI/Components/Header/Notifications/Notifications";
import HeaderIconDropdownButton from "CommonUI/src/Components/Header/HeaderIconDropdownButton";
import NotificationItem from "CommonUI/src/Components/Header/Notifications/NotificationItem";
import Notifications from "CommonUI/src/Components/Header/Notifications/Notifications";
import React, { ReactElement, useState } from "react";
const DashboardHeader: () => JSX.Element = (): ReactElement => {

View File

@@ -1,16 +1,16 @@
import SubscriptionPlan from "Common/Types/Billing/SubscriptionPlan";
import IconProp from "Common/Types/Icon/IconProp";
import { FormType } from "Common/UI/Components/Forms/ModelForm";
import Field from "Common/UI/Components/Forms/Types/Field";
import FormFieldSchemaType from "Common/UI/Components/Forms/Types/FormFieldSchemaType";
import ProjectPicker from "Common/UI/Components/Header/ProjectPicker/ProjectPicker";
import ModelFormModal from "Common/UI/Components/ModelFormModal/ModelFormModal";
import { RadioButton } from "Common/UI/Components/RadioButtons/GroupRadioButtons";
import Toggle from "Common/UI/Components/Toggle/Toggle";
import { BILLING_ENABLED, getAllEnvVars } from "Common/UI/Config";
import { GetReactElementFunction } from "Common/UI/Types/FunctionTypes";
import ProjectUtil from "Common/UI/Utils/Project";
import Project from "Common/Models/DatabaseModels/Project";
import { FormType } from "CommonUI/src/Components/Forms/ModelForm";
import Field from "CommonUI/src/Components/Forms/Types/Field";
import FormFieldSchemaType from "CommonUI/src/Components/Forms/Types/FormFieldSchemaType";
import ProjectPicker from "CommonUI/src/Components/Header/ProjectPicker/ProjectPicker";
import ModelFormModal from "CommonUI/src/Components/ModelFormModal/ModelFormModal";
import { RadioButton } from "CommonUI/src/Components/RadioButtons/GroupRadioButtons";
import Toggle from "CommonUI/src/Components/Toggle/Toggle";
import { BILLING_ENABLED, getAllEnvVars } from "CommonUI/src/Config";
import { GetReactElementFunction } from "CommonUI/src/Types/FunctionTypes";
import ProjectUtil from "CommonUI/src/Utils/Project";
import Project from "Model/Models/Project";
import React, {
FunctionComponent,
ReactElement,
@@ -137,7 +137,7 @@ const DashboardProjectPicker: FunctionComponent<ComponentProps> = (
minLength: 6,
},
footerElement: getFooter(),
fieldType: FormFieldSchemaType.OptionChooserButton,
fieldType: FormFieldSchemaType.RadioButton,
radioButtonOptions: SubscriptionPlan.getSubscriptionPlans(
getAllEnvVars(),
).map((plan: SubscriptionPlan): RadioButton => {

View File

@@ -1,5 +1,5 @@
import SearchBox from "Common/UI/Components/Header/SearchBox";
import Project from "Common/Models/DatabaseModels/Project";
import SearchBox from "CommonUI/src/Components/Header/SearchBox";
import Project from "Model/Models/Project";
import React, { FunctionComponent, ReactElement } from "react";
export interface ComponentProps {

View File

@@ -2,13 +2,13 @@ import PageMap from "../../Utils/PageMap";
import RouteMap, { RouteUtil } from "../../Utils/RouteMap";
import Route from "Common/Types/API/Route";
import IconProp from "Common/Types/Icon/IconProp";
import HeaderIconDropdownButton from "Common/UI/Components/Header/HeaderIconDropdownButton";
import IconDropdownItem from "Common/UI/Components/Header/IconDropdown/IconDropdownItem";
import IconDropdownMenu from "Common/UI/Components/Header/IconDropdown/IconDropdownMenu";
import { DASHBOARD_URL } from "Common/UI/Config";
import BlankProfilePic from "Common/UI/Images/users/blank-profile.svg";
import Navigation from "Common/UI/Utils/Navigation";
import User from "Common/UI/Utils/User";
import HeaderIconDropdownButton from "CommonUI/src/Components/Header/HeaderIconDropdownButton";
import IconDropdownItem from "CommonUI/src/Components/Header/IconDropdown/IconDropdownItem";
import IconDropdownMenu from "CommonUI/src/Components/Header/IconDropdown/IconDropdownMenu";
import { DASHBOARD_URL } from "CommonUI/src/Config";
import BlankProfilePic from "CommonUI/src/Images/users/blank-profile.svg";
import Navigation from "CommonUI/src/Utils/Navigation";
import User from "CommonUI/src/Utils/User";
import React, { FunctionComponent, ReactElement, useState } from "react";
const DashboardUserProfile: FunctionComponent = (): ReactElement => {

View File

@@ -1,8 +1,8 @@
import Footer from "../Footer/Footer";
import Header from "../Header/Header";
import NavBar from "../NavBar/NavBar";
import MasterPage from "Common/UI/Components/MasterPage/MasterPage";
import TopAlert from "Common/UI/Components/TopAlert/TopAlert";
import MasterPage from "CommonUI/src/Components/MasterPage/MasterPage";
import TopAlert from "CommonUI/src/Components/TopAlert/TopAlert";
import React, { FunctionComponent, ReactElement } from "react";
export interface ComponentProps {

View File

@@ -2,33 +2,36 @@ import PageMap from "../../Utils/PageMap";
import RouteMap, { RouteUtil } from "../../Utils/RouteMap";
import Route from "Common/Types/API/Route";
import IconProp from "Common/Types/Icon/IconProp";
import NavBar, { NavItem } from "Common/UI/Components/Navbar/NavBar";
import NavBar from "CommonUI/src/Components/Navbar/NavBar";
import NavBarItem from "CommonUI/src/Components/Navbar/NavBarItem";
import React, { FunctionComponent, ReactElement } from "react";
const DashboardNavbar: FunctionComponent = (): ReactElement => {
// Build the navigation items
const navItems: NavItem[] = [
{
id: "users-nav-bar-item",
title: "Users",
icon: IconProp.User,
route: RouteUtil.populateRouteParams(RouteMap[PageMap.USERS] as Route),
},
{
id: "projects-nav-bar-item",
title: "Projects",
icon: IconProp.Folder,
route: RouteUtil.populateRouteParams(RouteMap[PageMap.PROJECTS] as Route),
},
{
id: "settings-nav-bar-item",
title: "Settings",
icon: IconProp.Settings,
route: RouteUtil.populateRouteParams(RouteMap[PageMap.SETTINGS] as Route),
},
];
return (
<NavBar>
<NavBarItem
title="Users"
icon={IconProp.User}
route={RouteUtil.populateRouteParams(RouteMap[PageMap.USERS] as Route)}
></NavBarItem>
return <NavBar items={navItems} />;
<NavBarItem
title="Projects"
icon={IconProp.Folder}
route={RouteUtil.populateRouteParams(
RouteMap[PageMap.PROJECTS] as Route,
)}
></NavBarItem>
<NavBarItem
title="Settings"
icon={IconProp.Settings}
route={RouteUtil.populateRouteParams(
RouteMap[PageMap.SETTINGS] as Route,
)}
></NavBarItem>
</NavBar>
);
};
export default DashboardNavbar;

View File

@@ -1,11 +1,11 @@
import App from "./App";
import Telemetry from "Common/UI/Utils/Telemetry/Telemetry";
import Telemetry from "CommonUI/src/Utils/Telemetry";
import React from "react";
import ReactDOM from "react-dom/client";
import { BrowserRouter } from "react-router-dom";
Telemetry.init({
serviceName: "admin-dashboard",
serviceName: "AdminDashboard",
});
const root: any = ReactDOM.createRoot(

View File

@@ -1,8 +1,8 @@
import PageMap from "../../Utils/PageMap";
import RouteMap from "../../Utils/RouteMap";
import PageLoader from "Common/UI/Components/Loader/PageLoader";
import Page from "Common/UI/Components/Page/Page";
import Navigation from "Common/UI/Utils/Navigation";
import PageLoader from "CommonUI/src/Components/Loader/PageLoader";
import Page from "CommonUI/src/Components/Page/Page";
import Navigation from "CommonUI/src/Utils/Navigation";
import React, { FunctionComponent, ReactElement, useEffect } from "react";
const Init: FunctionComponent = (): ReactElement => {

View File

@@ -2,13 +2,13 @@ import PageMap from "../../Utils/PageMap";
import RouteMap, { RouteUtil } from "../../Utils/RouteMap";
import Route from "Common/Types/API/Route";
import { PromiseVoidFunction } from "Common/Types/FunctionTypes";
import ErrorMessage from "Common/UI/Components/ErrorMessage/ErrorMessage";
import PageLoader from "Common/UI/Components/Loader/PageLoader";
import Page from "Common/UI/Components/Page/Page";
import { ACCOUNTS_URL } from "Common/UI/Config";
import UiAnalytics from "Common/UI/Utils/Analytics";
import Navigation from "Common/UI/Utils/Navigation";
import UserUtil from "Common/UI/Utils/User";
import ErrorMessage from "CommonUI/src/Components/ErrorMessage/ErrorMessage";
import PageLoader from "CommonUI/src/Components/Loader/PageLoader";
import Page from "CommonUI/src/Components/Page/Page";
import { ACCOUNTS_URL } from "CommonUI/src/Config";
import UiAnalytics from "CommonUI/src/Utils/Analytics";
import Navigation from "CommonUI/src/Utils/Navigation";
import UserUtil from "CommonUI/src/Utils/User";
import React, { FunctionComponent, ReactElement, useEffect } from "react";
const Logout: FunctionComponent = (): ReactElement => {
@@ -16,7 +16,7 @@ const Logout: FunctionComponent = (): ReactElement => {
const logout: PromiseVoidFunction = async (): Promise<void> => {
UiAnalytics.logout();
UserUtil.logout();
await UserUtil.logout();
Navigation.navigate(ACCOUNTS_URL);
};
@@ -41,7 +41,7 @@ const Logout: FunctionComponent = (): ReactElement => {
]}
>
{!error ? <PageLoader isVisible={true} /> : <></>}
{error ? <ErrorMessage message={error} /> : <></>}
{error ? <ErrorMessage error={error} /> : <></>}
</Page>
);
};

View File

@@ -3,18 +3,18 @@ import PageMap from "../../Utils/PageMap";
import RouteMap, { RouteUtil } from "../../Utils/RouteMap";
import Route from "Common/Types/API/Route";
import SubscriptionPlan from "Common/Types/Billing/SubscriptionPlan";
import Field from "Common/UI/Components/Forms/Types/Field";
import FormFieldSchemaType from "Common/UI/Components/Forms/Types/FormFieldSchemaType";
import ModelTable from "Common/UI/Components/ModelTable/ModelTable";
import Page from "Common/UI/Components/Page/Page";
import { RadioButton } from "Common/UI/Components/RadioButtons/GroupRadioButtons";
import Toggle from "Common/UI/Components/Toggle/Toggle";
import FieldType from "Common/UI/Components/Types/FieldType";
import { BILLING_ENABLED, getAllEnvVars } from "Common/UI/Config";
import { GetReactElementFunction } from "Common/UI/Types/FunctionTypes";
import Navigation from "Common/UI/Utils/Navigation";
import Project from "Common/Models/DatabaseModels/Project";
import User from "Common/Models/DatabaseModels/User";
import Field from "CommonUI/src/Components/Forms/Types/Field";
import FormFieldSchemaType from "CommonUI/src/Components/Forms/Types/FormFieldSchemaType";
import ModelTable from "CommonUI/src/Components/ModelTable/ModelTable";
import Page from "CommonUI/src/Components/Page/Page";
import { RadioButton } from "CommonUI/src/Components/RadioButtons/GroupRadioButtons";
import Toggle from "CommonUI/src/Components/Toggle/Toggle";
import FieldType from "CommonUI/src/Components/Types/FieldType";
import { BILLING_ENABLED, getAllEnvVars } from "CommonUI/src/Config";
import { GetReactElementFunction } from "CommonUI/src/Types/FunctionTypes";
import Navigation from "CommonUI/src/Utils/Navigation";
import Project from "Model/Models/Project";
import User from "Model/Models/User";
import React, {
FunctionComponent,
ReactElement,
@@ -75,7 +75,7 @@ const Projects: FunctionComponent = (): ReactElement => {
minLength: 6,
},
footerElement: getFooter(),
fieldType: FormFieldSchemaType.OptionChooserButton,
fieldType: FormFieldSchemaType.RadioButton,
radioButtonOptions: SubscriptionPlan.getSubscriptionPlans(
getAllEnvVars(),
).map((plan: SubscriptionPlan): RadioButton => {
@@ -187,7 +187,7 @@ const Projects: FunctionComponent = (): ReactElement => {
isEditable={false}
isCreateable={true}
name="Projects"
isViewable={true}
isViewable={false}
cardProps={{
title: "Projects",
description: "Here is a list of proejcts in OneUptime.",
@@ -241,10 +241,8 @@ const Projects: FunctionComponent = (): ReactElement => {
},
title: "Created At",
type: FieldType.DateTime,
hideOnMobile: true,
},
]}
userPreferencesKey="admin-projects-table"
/>
</Page>
);

View File

@@ -1,52 +0,0 @@
import PageMap from "../../../Utils/PageMap";
import RouteMap, { RouteUtil } from "../../../Utils/RouteMap";
import Route from "Common/Types/API/Route";
import ObjectID from "Common/Types/ObjectID";
import ModelDelete from "Common/UI/Components/ModelDelete/ModelDelete";
import Navigation from "Common/UI/Utils/Navigation";
import React, { FunctionComponent, ReactElement } from "react";
import SideMenuComponent from "./SideMenu";
import Project from "Common/Models/DatabaseModels/Project";
import ModelPage from "Common/UI/Components/Page/ModelPage";
const DeletePage: FunctionComponent = (): ReactElement => {
const modelId: ObjectID = Navigation.getLastParamAsObjectID(1);
return (
<ModelPage<Project>
modelId={modelId}
modelNameField="name"
modelType={Project}
title={"Project"}
breadcrumbLinks={[
{
title: "Admin Dashboard",
to: RouteUtil.populateRouteParams(RouteMap[PageMap.HOME] as Route),
},
{
title: "Projects",
to: RouteUtil.populateRouteParams(
RouteMap[PageMap.PROJECTS] as Route,
),
},
{
title: "Project",
to: RouteUtil.populateRouteParams(
RouteMap[PageMap.PROJECT_VIEW] as Route,
),
},
]}
sideMenu={<SideMenuComponent modelId={modelId} />}
>
<ModelDelete
modelType={Project}
modelId={modelId}
onDeleteSuccess={() => {
Navigation.navigate(RouteMap[PageMap.PROJECTS] as Route);
}}
/>
</ModelPage>
);
};
export default DeletePage;

View File

@@ -1,90 +0,0 @@
import ObjectID from "Common/Types/ObjectID";
import PageMap from "../../../Utils/PageMap";
import RouteMap, { RouteUtil } from "../../../Utils/RouteMap";
import Route from "Common/Types/API/Route";
import Navigation from "Common/UI/Utils/Navigation";
import Project from "Common/Models/DatabaseModels/Project";
import React, { FunctionComponent, ReactElement } from "react";
import CardModelDetail from "Common/UI/Components/ModelDetail/CardModelDetail";
import FormFieldSchemaType from "Common/UI/Components/Forms/Types/FormFieldSchemaType";
import FieldType from "Common/UI/Components/Types/FieldType";
import ModelPage from "Common/UI/Components/Page/ModelPage";
import SideMenuComponent from "./SideMenu";
const Projects: FunctionComponent = (): ReactElement => {
const modelId: ObjectID = Navigation.getLastParamAsObjectID();
return (
<ModelPage
modelId={modelId}
modelNameField="name"
modelType={Project}
title={"Project"}
breadcrumbLinks={[
{
title: "Admin Dashboard",
to: RouteUtil.populateRouteParams(RouteMap[PageMap.HOME] as Route),
},
{
title: "Projects",
to: RouteUtil.populateRouteParams(
RouteMap[PageMap.PROJECTS] as Route,
),
},
{
title: "Project",
to: RouteUtil.populateRouteParams(
RouteMap[PageMap.PROJECT_VIEW] as Route,
),
},
]}
sideMenu={<SideMenuComponent modelId={modelId} />}
>
<div>
<CardModelDetail<Project>
name="Project"
cardProps={{
title: "Project",
description: "Project details",
}}
isEditable={true}
editButtonText="Edit Project"
formFields={[
{
field: {
name: true,
},
title: "Name",
fieldType: FormFieldSchemaType.Text,
required: true,
},
]}
modelDetailProps={{
modelType: Project,
id: "model-detail-user",
fields: [
{
field: {
_id: true,
},
title: "Project ID",
fieldType: FieldType.Text,
placeholder: "-",
},
{
field: {
name: true,
},
title: "Name",
fieldType: FieldType.Text,
},
],
modelId: modelId,
}}
/>
</div>
</ModelPage>
);
};
export default Projects;

View File

@@ -1,53 +0,0 @@
import PageMap from "../../../Utils/PageMap";
import RouteMap, { RouteUtil } from "../../../Utils/RouteMap";
import Route from "Common/Types/API/Route";
import IconProp from "Common/Types/Icon/IconProp";
import ObjectID from "Common/Types/ObjectID";
import SideMenu from "Common/UI/Components/SideMenu/SideMenu";
import SideMenuItem from "Common/UI/Components/SideMenu/SideMenuItem";
import SideMenuSection from "Common/UI/Components/SideMenu/SideMenuSection";
import React, { FunctionComponent, ReactElement } from "react";
export interface SideMenuProps {
modelId: ObjectID;
}
const SideMenuComponent: FunctionComponent<SideMenuProps> = (
props: SideMenuProps,
): ReactElement => {
return (
<SideMenu>
<SideMenuSection title="Basic">
<SideMenuItem
link={{
title: "Overview",
to: RouteUtil.populateRouteParams(
RouteMap[PageMap.PROJECT_VIEW] as Route,
{
modelId: props.modelId,
},
),
}}
icon={IconProp.Info}
/>
</SideMenuSection>
<SideMenuSection title="Advanced">
<SideMenuItem
link={{
title: "Delete",
to: RouteUtil.populateRouteParams(
RouteMap[PageMap.PROJECT_DELETE] as Route,
{
modelId: props.modelId,
},
),
}}
icon={IconProp.Trash}
/>
</SideMenuSection>
</SideMenu>
);
};
export default SideMenuComponent;

View File

@@ -3,11 +3,11 @@ import RouteMap, { RouteUtil } from "../../../Utils/RouteMap";
import DashboardSideMenu from "../SideMenu";
import Route from "Common/Types/API/Route";
import ObjectID from "Common/Types/ObjectID";
import FormFieldSchemaType from "Common/UI/Components/Forms/Types/FormFieldSchemaType";
import CardModelDetail from "Common/UI/Components/ModelDetail/CardModelDetail";
import Page from "Common/UI/Components/Page/Page";
import FieldType from "Common/UI/Components/Types/FieldType";
import GlobalConfig from "Common/Models/DatabaseModels/GlobalConfig";
import FormFieldSchemaType from "CommonUI/src/Components/Forms/Types/FormFieldSchemaType";
import CardModelDetail from "CommonUI/src/Components/ModelDetail/CardModelDetail";
import Page from "CommonUI/src/Components/Page/Page";
import FieldType from "CommonUI/src/Components/Types/FieldType";
import GlobalConfig from "Model/Models/GlobalConfig";
import React, { FunctionComponent, ReactElement } from "react";
const Settings: FunctionComponent = (): ReactElement => {

View File

@@ -3,11 +3,11 @@ import RouteMap, { RouteUtil } from "../../../Utils/RouteMap";
import DashboardSideMenu from "../SideMenu";
import Route from "Common/Types/API/Route";
import ObjectID from "Common/Types/ObjectID";
import FormFieldSchemaType from "Common/UI/Components/Forms/Types/FormFieldSchemaType";
import CardModelDetail from "Common/UI/Components/ModelDetail/CardModelDetail";
import Page from "Common/UI/Components/Page/Page";
import FieldType from "Common/UI/Components/Types/FieldType";
import GlobalConfig from "Common/Models/DatabaseModels/GlobalConfig";
import FormFieldSchemaType from "CommonUI/src/Components/Forms/Types/FormFieldSchemaType";
import CardModelDetail from "CommonUI/src/Components/ModelDetail/CardModelDetail";
import Page from "CommonUI/src/Components/Page/Page";
import FieldType from "CommonUI/src/Components/Types/FieldType";
import GlobalConfig from "Model/Models/GlobalConfig";
import React, { FunctionComponent, ReactElement } from "react";
const Settings: FunctionComponent = (): ReactElement => {

View File

@@ -3,11 +3,11 @@ import RouteMap, { RouteUtil } from "../../../Utils/RouteMap";
import DashboardSideMenu from "../SideMenu";
import Route from "Common/Types/API/Route";
import ObjectID from "Common/Types/ObjectID";
import FormFieldSchemaType from "Common/UI/Components/Forms/Types/FormFieldSchemaType";
import CardModelDetail from "Common/UI/Components/ModelDetail/CardModelDetail";
import Page from "Common/UI/Components/Page/Page";
import FieldType from "Common/UI/Components/Types/FieldType";
import GlobalConfig from "Common/Models/DatabaseModels/GlobalConfig";
import FormFieldSchemaType from "CommonUI/src/Components/Forms/Types/FormFieldSchemaType";
import CardModelDetail from "CommonUI/src/Components/ModelDetail/CardModelDetail";
import Page from "CommonUI/src/Components/Page/Page";
import FieldType from "CommonUI/src/Components/Types/FieldType";
import GlobalConfig from "Model/Models/GlobalConfig";
import React, { FunctionComponent, ReactElement } from "react";
const Settings: FunctionComponent = (): ReactElement => {
@@ -72,9 +72,9 @@ const Settings: FunctionComponent = (): ReactElement => {
},
{
field: {
twilioPrimaryPhoneNumber: true,
twilioPhoneNumber: true,
},
title: "Primary Twilio Phone Number",
title: "Twilio Phone Number",
fieldType: FormFieldSchemaType.Phone,
required: true,
description: "You can find this in your Twilio console.",
@@ -83,20 +83,6 @@ const Settings: FunctionComponent = (): ReactElement => {
minLength: 2,
},
},
{
field: {
twilioSecondaryPhoneNumbers: true,
},
title: "Secondary Twilio Phone Number",
fieldType: FormFieldSchemaType.LongText,
required: true,
description:
"If you have bought more phone numbers from Twilio for specific countries, you can add them here.",
placeholder: "+1234567890, +4444444444",
validation: {
minLength: 2,
},
},
]}
modelDetailProps={{
modelType: GlobalConfig,
@@ -111,20 +97,12 @@ const Settings: FunctionComponent = (): ReactElement => {
},
{
field: {
twilioPrimaryPhoneNumber: true,
twilioPhoneNumber: true,
},
title: "Primary Twilio Phone Number",
title: "Twilio Phone Number",
fieldType: FieldType.Phone,
placeholder: "None",
},
{
field: {
twilioSecondaryPhoneNumbers: true,
},
title: "Secondary Twilio Phone Numbers",
fieldType: FieldType.LongText,
placeholder: "None",
},
],
modelId: ObjectID.getZeroObjectID(),
}}

View File

@@ -5,23 +5,21 @@ import Route from "Common/Types/API/Route";
import { Green, Red } from "Common/Types/BrandColors";
import { PromiseVoidFunction } from "Common/Types/FunctionTypes";
import ObjectID from "Common/Types/ObjectID";
import ErrorMessage from "Common/UI/Components/ErrorMessage/ErrorMessage";
import FormFieldSchemaType from "Common/UI/Components/Forms/Types/FormFieldSchemaType";
import PageLoader from "Common/UI/Components/Loader/PageLoader";
import CardModelDetail from "Common/UI/Components/ModelDetail/CardModelDetail";
import Page from "Common/UI/Components/Page/Page";
import Pill from "Common/UI/Components/Pill/Pill";
import FieldType from "Common/UI/Components/Types/FieldType";
import DropdownUtil from "Common/UI/Utils/Dropdown";
import ModelAPI from "Common/UI/Utils/ModelAPI/ModelAPI";
import GlobalConfig, {
EmailServerType,
} from "Common/Models/DatabaseModels/GlobalConfig";
import ErrorMessage from "CommonUI/src/Components/ErrorMessage/ErrorMessage";
import FormFieldSchemaType from "CommonUI/src/Components/Forms/Types/FormFieldSchemaType";
import PageLoader from "CommonUI/src/Components/Loader/PageLoader";
import CardModelDetail from "CommonUI/src/Components/ModelDetail/CardModelDetail";
import Page from "CommonUI/src/Components/Page/Page";
import Pill from "CommonUI/src/Components/Pill/Pill";
import FieldType from "CommonUI/src/Components/Types/FieldType";
import DropdownUtil from "CommonUI/src/Utils/Dropdown";
import ModelAPI from "CommonUI/src/Utils/ModelAPI/ModelAPI";
import GlobalConfig, { EmailServerType } from "Model/Models/GlobalConfig";
import React, { FunctionComponent, ReactElement, useEffect } from "react";
const Settings: FunctionComponent = (): ReactElement => {
const [emailServerType, setemailServerType] = React.useState<EmailServerType>(
EmailServerType.CustomSMTP,
EmailServerType.Internal,
);
const [isLoading, setIsLoading] = React.useState<boolean>(true);
@@ -43,7 +41,7 @@ const Settings: FunctionComponent = (): ReactElement => {
if (globalConfig) {
setemailServerType(
globalConfig.emailServerType || EmailServerType.CustomSMTP,
globalConfig.emailServerType || EmailServerType.Internal,
);
}
@@ -61,7 +59,7 @@ const Settings: FunctionComponent = (): ReactElement => {
}
if (error) {
return <ErrorMessage message={error} />;
return <ErrorMessage error={error} />;
}
return (
@@ -106,7 +104,6 @@ const Settings: FunctionComponent = (): ReactElement => {
title: "Admin Notification Email",
fieldType: FormFieldSchemaType.Email,
required: false,
disableSpellCheck: true,
},
]}
modelDetailProps={{
@@ -127,7 +124,7 @@ const Settings: FunctionComponent = (): ReactElement => {
/>
<CardModelDetail
name="Email Server Settings"
name="Internal SMTP Settings"
cardProps={{
title: "Email Server Settings",
description:
@@ -172,7 +169,7 @@ const Settings: FunctionComponent = (): ReactElement => {
cardProps={{
title: "Custom Email and SMTP Settings",
description:
"Please configure your SMTP server here to send emails.",
"If you have not enabled Internal SMTP server to send emails. Please configure your SMTP server here.",
}}
isEditable={true}
editButtonText="Edit SMTP Config"
@@ -200,7 +197,6 @@ const Settings: FunctionComponent = (): ReactElement => {
fieldType: FormFieldSchemaType.Hostname,
required: true,
placeholder: "smtp.server.com",
disableSpellCheck: true,
},
{
field: {
@@ -231,7 +227,6 @@ const Settings: FunctionComponent = (): ReactElement => {
fieldType: FormFieldSchemaType.Text,
required: false,
placeholder: "emailuser",
disableSpellCheck: true,
},
{
field: {
@@ -242,7 +237,6 @@ const Settings: FunctionComponent = (): ReactElement => {
fieldType: FormFieldSchemaType.EncryptedText,
required: false,
placeholder: "Password",
disableSpellCheck: true,
},
{
field: {
@@ -253,9 +247,8 @@ const Settings: FunctionComponent = (): ReactElement => {
fieldType: FormFieldSchemaType.Email,
required: true,
description:
"Email used to log in to this SMTP Server. This is also the email your customers will see. ",
"This is the display email your team and customers see, when they receive emails from OneUptime.",
placeholder: "email@company.com",
disableSpellCheck: true,
},
{
field: {
@@ -268,7 +261,6 @@ const Settings: FunctionComponent = (): ReactElement => {
description:
"This is the display name your team and customers see, when they receive emails from OneUptime.",
placeholder: "Company, Inc.",
disableSpellCheck: true,
},
]}
modelDetailProps={{

View File

@@ -7,16 +7,16 @@ import IsNull from "Common/Types/BaseDatabase/IsNull";
import { Green, Red } from "Common/Types/BrandColors";
import OneUptimeDate from "Common/Types/Date";
import { ErrorFunction, VoidFunction } from "Common/Types/FunctionTypes";
import Banner from "Common/UI/Components/Banner/Banner";
import { ButtonStyleType } from "Common/UI/Components/Button/Button";
import FormFieldSchemaType from "Common/UI/Components/Forms/Types/FormFieldSchemaType";
import ConfirmModal from "Common/UI/Components/Modal/ConfirmModal";
import ModelTable from "Common/UI/Components/ModelTable/ModelTable";
import Page from "Common/UI/Components/Page/Page";
import ProbeElement from "Common/UI/Components/Probe/Probe";
import Statusbubble from "Common/UI/Components/StatusBubble/StatusBubble";
import FieldType from "Common/UI/Components/Types/FieldType";
import Probe from "Common/Models/DatabaseModels/Probe";
import Banner from "CommonUI/src/Components/Banner/Banner";
import { ButtonStyleType } from "CommonUI/src/Components/Button/Button";
import FormFieldSchemaType from "CommonUI/src/Components/Forms/Types/FormFieldSchemaType";
import ConfirmModal from "CommonUI/src/Components/Modal/ConfirmModal";
import ModelTable from "CommonUI/src/Components/ModelTable/ModelTable";
import Page from "CommonUI/src/Components/Page/Page";
import ProbeElement from "CommonUI/src/Components/Probe/Probe";
import Statusbubble from "CommonUI/src/Components/StatusBubble/StatusBubble";
import FieldType from "CommonUI/src/Components/Types/FieldType";
import Probe from "Model/Models/Probe";
import React, { FunctionComponent, ReactElement, useState } from "react";
const Settings: FunctionComponent = (): ReactElement => {
@@ -54,11 +54,9 @@ const Settings: FunctionComponent = (): ReactElement => {
title="Need help with setting up Global Probes?"
description="Here is a guide which will help you get set up"
link={Route.fromString("/docs/probe/custom-probe")}
hideOnMobile={true}
/>
<ModelTable<Probe>
userPreferencesKey={"admin-probes-table"}
modelType={Probe}
id="probes-table"
name="Settings > Global Probes"
@@ -101,7 +99,7 @@ const Settings: FunctionComponent = (): ReactElement => {
},
title: "Description",
fieldType: FormFieldSchemaType.LongText,
required: false,
required: true,
placeholder: "This probe is to monitor all the internal services.",
},
@@ -153,7 +151,7 @@ const Settings: FunctionComponent = (): ReactElement => {
description: true,
},
title: "Description",
type: FieldType.LongText,
type: FieldType.Text,
},
]}
columns={[
@@ -172,10 +170,8 @@ const Settings: FunctionComponent = (): ReactElement => {
field: {
description: true,
},
noValueMessage: "-",
title: "Description",
type: FieldType.LongText,
hideOnMobile: true,
type: FieldType.Text,
},
{
field: {
@@ -183,7 +179,6 @@ const Settings: FunctionComponent = (): ReactElement => {
},
title: "Status",
type: FieldType.Text,
getElement: (item: Probe): ReactElement => {
if (
item &&

View File

@@ -2,9 +2,9 @@ import PageMap from "../../Utils/PageMap";
import RouteMap, { RouteUtil } from "../../Utils/RouteMap";
import Route from "Common/Types/API/Route";
import IconProp from "Common/Types/Icon/IconProp";
import SideMenu from "Common/UI/Components/SideMenu/SideMenu";
import SideMenuItem from "Common/UI/Components/SideMenu/SideMenuItem";
import SideMenuSection from "Common/UI/Components/SideMenu/SideMenuSection";
import SideMenu from "CommonUI/src/Components/SideMenu/SideMenu";
import SideMenuItem from "CommonUI/src/Components/SideMenu/SideMenuItem";
import SideMenuSection from "CommonUI/src/Components/SideMenu/SideMenuSection";
import React, { ReactElement } from "react";
const DashboardSideMenu: () => JSX.Element = (): ReactElement => {

View File

@@ -1,15 +1,31 @@
import PageMap from "../../Utils/PageMap";
import RouteMap, { RouteUtil } from "../../Utils/RouteMap";
import Route from "Common/Types/API/Route";
import FormFieldSchemaType from "Common/UI/Components/Forms/Types/FormFieldSchemaType";
import ModelTable from "Common/UI/Components/ModelTable/ModelTable";
import Page from "Common/UI/Components/Page/Page";
import FieldType from "Common/UI/Components/Types/FieldType";
import Navigation from "Common/UI/Utils/Navigation";
import User from "Common/Models/DatabaseModels/User";
import React, { FunctionComponent, ReactElement } from "react";
import { ErrorFunction } from "Common/Types/FunctionTypes";
import { ButtonStyleType } from "CommonUI/src/Components/Button/Button";
import FormFieldSchemaType from "CommonUI/src/Components/Forms/Types/FormFieldSchemaType";
import ConfirmModal from "CommonUI/src/Components/Modal/ConfirmModal";
import ModelTable from "CommonUI/src/Components/ModelTable/ModelTable";
import Page from "CommonUI/src/Components/Page/Page";
import FieldType from "CommonUI/src/Components/Types/FieldType";
import API from "CommonUI/src/Utils/API/API";
import ModelAPI from "CommonUI/src/Utils/ModelAPI/ModelAPI";
import Navigation from "CommonUI/src/Utils/Navigation";
import User from "Model/Models/User";
import React, { FunctionComponent, ReactElement, useState } from "react";
const Users: FunctionComponent = (): ReactElement => {
const [showConfirmVerifyEmailModal, setShowConfirmVerifyEmailModal] =
useState<boolean>(false);
const [selectedUser, setSelectedUser] = useState<User | null>(null);
const [error, setError] = useState<string | null>(null);
const [isConfimModalLoading, setIsConfirmModalLoading] =
useState<boolean>(false);
const [refreshItemsTrigger, setRefreshItemsTrigger] =
useState<boolean>(false);
return (
<Page
title={"Users"}
@@ -26,18 +42,42 @@ const Users: FunctionComponent = (): ReactElement => {
>
<ModelTable<User>
modelType={User}
userPreferencesKey="admin-users-table"
id="users-table"
isDeleteable={false}
isEditable={false}
showViewIdButton={true}
refreshToggle={refreshItemsTrigger}
isCreateable={true}
name="Users"
isViewable={true}
isViewable={false}
cardProps={{
title: "Users",
description: "Here is a list of users in OneUptime.",
}}
actionButtons={[
{
title: "Verify Email",
buttonStyleType: ButtonStyleType.NORMAL,
isVisible: (item: User) => {
return !item.isEmailVerified;
},
onClick: async (
item: User,
onCompleteAction: VoidFunction,
onError: ErrorFunction,
) => {
try {
setSelectedUser(item);
setShowConfirmVerifyEmailModal(true);
onCompleteAction();
} catch (err) {
onCompleteAction();
onError(err as Error);
}
},
},
]}
noItemsMessage={"No users found."}
formFields={[
{
@@ -48,7 +88,6 @@ const Users: FunctionComponent = (): ReactElement => {
fieldType: FormFieldSchemaType.Email,
required: true,
placeholder: "email@company.com",
disableSpellCheck: true,
},
{
field: {
@@ -58,7 +97,6 @@ const Users: FunctionComponent = (): ReactElement => {
fieldType: FormFieldSchemaType.Password,
required: true,
placeholder: "Password",
disableSpellCheck: true,
},
{
field: {
@@ -116,7 +154,6 @@ const Users: FunctionComponent = (): ReactElement => {
},
title: "Email Verified",
type: FieldType.Boolean,
hideOnMobile: true,
},
{
field: {
@@ -124,10 +161,56 @@ const Users: FunctionComponent = (): ReactElement => {
},
title: "Created At",
type: FieldType.DateTime,
hideOnMobile: true,
},
]}
/>
{error ? (
<ConfirmModal
title={`Error`}
description={error}
submitButtonText={"Close"}
onSubmit={async () => {
setError(null);
}}
submitButtonType={ButtonStyleType.NORMAL}
/>
) : (
<></>
)}
{showConfirmVerifyEmailModal && selectedUser ? (
<ConfirmModal
title={`Verify Email`}
description={`Are you sure you want to verify the email - ${selectedUser.email}?`}
isLoading={isConfimModalLoading}
submitButtonText={"Verify Email"}
onClose={async () => {
setShowConfirmVerifyEmailModal(false);
setSelectedUser(null);
}}
onSubmit={async () => {
try {
setIsConfirmModalLoading(true);
await ModelAPI.updateById<User>({
modelType: User,
id: selectedUser.id!,
data: {
isEmailVerified: true,
},
});
} catch (err) {
setError(API.getFriendlyMessage(err as Error));
}
setRefreshItemsTrigger(!refreshItemsTrigger);
setIsConfirmModalLoading(false);
setShowConfirmVerifyEmailModal(false);
}}
/>
) : (
<></>
)}
</Page>
);
};

Some files were not shown because too many files have changed in this diff Show More