Compare commits

..

No commits in common. "main" and "v1.113.0" have entirely different histories.

14 changed files with 5560 additions and 5064 deletions

View File

@ -1,59 +0,0 @@
name: 'Build Container'
description: 'Build and publish OpenCost UI container image'
inputs:
actor:
description: 'GitHub actor'
required: true
GITHUB_TOKEN:
description: 'GitHub token for authentication'
required: true
image_tag:
description: 'Full image tag to use for the container'
required: true
release_version:
description: 'Release version for the container'
required: true
registry:
description: 'Container registry to use'
required: true
default: 'ghcr.io'
runs:
using: "composite"
steps:
- name: Log into registry
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772
with:
registry: ${{ inputs.registry }}
username: ${{ inputs.actor }}
password: ${{ inputs.GITHUB_TOKEN }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
buildkitd-flags: --debug
- name: Set up just
uses: extractions/setup-just@v3
- name: Install crane
uses: imjasonh/setup-crane@v0.3
- name: Install manifest-tool
run: |
mkdir -p manifest-tool
pushd manifest-tool
wget -q https://github.com/estesp/manifest-tool/releases/download/v2.0.8/binaries-manifest-tool-2.0.8.tar.gz
tar -xzf binaries-manifest-tool-2.0.8.tar.gz
cp manifest-tool-linux-amd64 manifest-tool
echo "$(pwd)" >> $GITHUB_PATH
shell: bash
- name: Build and push (multiarch)
env:
IMAGE_TAG: ${{ inputs.image_tag }}
RELEASE_VERSION: ${{ inputs.release_version }}
run: |
just build "$IMAGE_TAG" "$RELEASE_VERSION"
shell: bash

View File

@ -1,59 +0,0 @@
name: Build and Publish Develop UI
on:
workflow_run:
workflows: [Build/Test]
types: [completed]
branches: [main]
concurrency:
group: build-opencost-ui-develop
cancel-in-progress: false
env:
# Use docker.io for Docker Hub if empty
REGISTRY: ghcr.io
jobs:
build-and-publish-opencost-ui:
runs-on: ubuntu-latest
if: ${{ github.event.workflow_run.conclusion == 'success' }}
permissions:
contents: read
packages: write
steps:
- name: Checkout Repo
uses: actions/checkout@v4
- name: Set SHA
id: sha
run: |
echo "OC_SHORTHASH=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
- name: Set OpenCost Image Tags
id: tags
run: |
echo "IMAGE_TAG=ghcr.io/${{ github.repository_owner }}/opencost-ui:develop-${{ steps.sha.outputs.OC_SHORTHASH }}" >> $GITHUB_OUTPUT
- name: Build and publish container
uses: ./.github/actions/build-container
with:
actor: ${{ github.actor }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
image_tag: ${{ steps.tags.outputs.IMAGE_TAG }}
release_version: develop-${{ steps.sha.outputs.OC_SHORTHASH }}
registry: ${{ env.REGISTRY }}
- name: Install crane
uses: imjasonh/setup-crane@v0.4
- name: Tag and push latest image
run: |
# Extract the repository part (everything before the last colon)
REPO=$(echo "${{ steps.tags.outputs.IMAGE_TAG }}" | sed 's/:.*$//')
# Create the new tag
NEW_TAG="${REPO}:develop-latest"
echo "Copying ${{ steps.tags.outputs.IMAGE_TAG }} to ${NEW_TAG}"
crane copy "${{ steps.tags.outputs.IMAGE_TAG }}" "${NEW_TAG}"

View File

@ -59,12 +59,6 @@ jobs:
VERSION_NUMBER=${{ steps.version_number.outputs.RELEASE_VERSION }}
echo "BRANCH_NAME=v${VERSION_NUMBER%.*}" >> $GITHUB_ENV
# checkout opencost UI to allow access to actions
- name: Checkout actions
uses: actions/checkout@v4
with:
repository: 'opencost/opencost-ui'
- name: Checkout Repo
uses: actions/checkout@v4
with:
@ -79,6 +73,15 @@ jobs:
echo "OC_SHORTHASH=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
popd
# Login against a Docker registry except on PR
# https://github.com/docker/login-action
- name: Log into registry ${{ env.REGISTRY }}
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Set OpenCost Image Tags
id: tags
run: |
@ -86,17 +89,31 @@ jobs:
echo "IMAGE_TAG_UI_LATEST=ghcr.io/opencost/opencost-ui:latest" >> $GITHUB_OUTPUT
echo "IMAGE_TAG_UI_VERSION=ghcr.io/opencost/opencost-ui:${{ steps.version_number.outputs.RELEASE_VERSION }}" >> $GITHUB_OUTPUT
- name: Build and publish container
uses: ./.github/actions/build-container
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
actor: ${{ github.actor }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
image_tag: ${{ steps.tags.outputs.IMAGE_TAG_UI }}
release_version: ${{ steps.version_number.outputs.RELEASE_VERSION }}
registry: ${{ env.REGISTRY }}
buildkitd-flags: --debug
- name: Set up just
uses: extractions/setup-just@v2
- name: Install crane
uses: imjasonh/setup-crane@v0.4
- name: Tag and push latest image
uses: imjasonh/setup-crane@v0.3
## Install manifest-tool, which is required to combine multi-arch images
## https://github.com/estesp/manifest-tool
- name: Install manifest-tool
run: |
crane copy "${{ steps.tags.outputs.IMAGE_TAG_UI }}" "${{ steps.tags.outputs.IMAGE_TAG_UI_LATEST }}"
crane copy "${{ steps.tags.outputs.IMAGE_TAG_UI }}" "${{ steps.tags.outputs.IMAGE_TAG_UI_VERSION }}"
mkdir -p manifest-tool
pushd manifest-tool
wget -q https://github.com/estesp/manifest-tool/releases/download/v2.0.8/binaries-manifest-tool-2.0.8.tar.gz
tar -xzf binaries-manifest-tool-2.0.8.tar.gz
cp manifest-tool-linux-amd64 manifest-tool
echo "$(pwd)" >> $GITHUB_PATH
- name: Build and push (multiarch) OpenCost UI
working-directory: ./opencost-ui
run: |
just build '${{ steps.tags.outputs.IMAGE_TAG_UI }}' '${{ steps.version_number.outputs.RELEASE_VERSION }}'
crane copy '${{ steps.tags.outputs.IMAGE_TAG_UI }}' '${{ steps.tags.outputs.IMAGE_TAG_UI_LATEST }}'
crane copy '${{ steps.tags.outputs.IMAGE_TAG_UI }}' '${{ steps.tags.outputs.IMAGE_TAG_UI_VERSION }}'

View File

@ -1,61 +0,0 @@
name: Build and Publish UI Test Image
on:
merge_group:
types: [checks_requested]
pull_request_target:
branches:
- main
env:
REGISTRY: ghcr.io
jobs:
check_actor_permissions:
runs-on: ubuntu-latest
if: ${{ github.event_name == 'pull_request_target' }}
outputs:
ismaintainer: ${{ steps.determine-maintainer.outputs.ismaintainer }}
steps:
- name: Check team membership
uses: tspascoal/get-user-teams-membership@v3
id: teamAffiliation
with:
GITHUB_TOKEN: ${{ secrets.ORG_READER_PAT }}
username: ${{ github.actor }}
organization: opencost
- name: determine if actor is a maintainer
id: determine-maintainer
run: |
echo "Actor: ${{ github.actor }}"
echo "Is maintainer: ${{ contains(steps.teamAffiliation.outputs.teams, 'OpenCost Maintainers') || contains(github.actor, 'dependabot[bot]') }}"
echo "ismaintainer=${{ contains(steps.teamAffiliation.outputs.teams, 'OpenCost Maintainers') || contains(github.actor, 'dependabot[bot]') }}" >> $GITHUB_OUTPUT
build-and-publish-test-image:
runs-on: ubuntu-latest
needs: check_actor_permissions
if: ${{ (always() && !cancelled()) && ( github.event_name == 'merge_group' || needs.check_actor_permissions.outputs.ismaintainer == 'true') }}
permissions:
contents: read
packages: write
steps:
- name: Checkout Repo
uses: actions/checkout@v4
with:
ref: ${{ github.event.merge_group.head_sha || github.event.pull_request.head.sha }}
- name: Set SHA
id: sha
run: |
echo "OC_SHORTHASH=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
- name: Set OpenCost Image Tags
id: tags
run: |
echo "IMAGE_TAG=ghcr.io/${{ github.repository_owner }}/opencost-ui:test-${{ steps.sha.outputs.OC_SHORTHASH }}" >> $GITHUB_OUTPUT
- name: Build and publish container
uses: ./.github/actions/build-container
with:
actor: ${{ github.actor }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
image_tag: ${{ steps.tags.outputs.IMAGE_TAG }}
release_version: test-${{ steps.sha.outputs.OC_SHORTHASH }}
registry: ${{ env.REGISTRY }}

View File

@ -19,7 +19,7 @@ jobs:
-
name: Install just
uses: extractions/setup-just@v3
uses: extractions/setup-just@v2
-
name: Install node

View File

@ -1,39 +0,0 @@
name: Promote UI to Demo
on:
workflow_run:
workflows: [Build and Publish Develop UI]
types: [completed]
branches: [main]
concurrency:
group: build-opencost-ui-develop
cancel-in-progress: false
jobs:
prep-image-name:
runs-on: ubuntu-latest
if: ${{ github.event.workflow_run.conclusion == 'success' }}
outputs:
image_tag: ${{ steps.tags.outputs.IMAGE_TAG }}
steps:
- name: Checkout Repo
uses: actions/checkout@v4
- name: Set SHA
id: sha
run: |
echo "OC_SHORTHASH=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
- name: Set OpenCost Image Tags
id: tags
run: |
echo "IMAGE_TAG=ghcr.io/${{ github.repository_owner }}/opencost-ui:develop-${{ steps.sha.outputs.OC_SHORTHASH }}" >> $GITHUB_OUTPUT
install-on-demo:
needs: [prep-image-name]
uses: opencost/opencost-infra/.github/workflows/promote-to-oc-demo.yaml@main
secrets: inherit
with:
img-fqdn: ${{ needs.prep-image-name.outputs.image_tag }}
is_be: false
is_fe: true

View File

@ -2,16 +2,16 @@
# OpenCost UI
<img src="src/images/logo.png"/>
<img src="./opencost-header.png"/>
This is the web UI for the [OpenCost](http://github.com/opencost/opencost) project. You can learn more about the [User Interface](https://www.opencost.io/docs/installation/ui) in the OpenCost docs.
[![OpenCost UI Walkthrough](./src/thumbnail.png)](https://youtu.be/lCP4Ci9Kcdg)
[![OpenCost UI Walkthrough](./ui/src/thumbnail.png)](https://youtu.be/lCP4Ci9Kcdg)
*OpenCost UI Walkthrough*
## Installing
See [Installation Guide](https://opencost.io/docs/installation/install) for the full instructions.
See https://www.opencost.io/docs/install for the full instructions.
## Using

View File

@ -18,9 +18,8 @@ else
sed -i "s^PLACEHOLDER_FOOTER_CONTENT^OpenCost version: $VERSION ($HEAD)^g" /var/www/*.js
fi
if [[ ! -e /etc/nginx/conf.d/default.nginx.conf ]];then
envsubst '$API_PORT $API_SERVER $UI_PORT' < /etc/nginx/conf.d/default.nginx.conf.template > /etc/nginx/conf.d/default.nginx.conf
fi
envsubst '$API_PORT $API_SERVER $UI_PORT' < /etc/nginx/conf.d/default.nginx.conf.template > /etc/nginx/conf.d/default.nginx.conf
echo "Starting OpenCost UI version $VERSION ($HEAD)"
# Run the parent (nginx) container's entrypoint script

10294
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -14,14 +14,14 @@
"defaults"
],
"dependencies": {
"@babel/runtime": "^7.27.0",
"@date-io/core": "^3.2.0",
"@babel/runtime": "^7.23.9",
"@date-io/core": "^1.3.13",
"@date-io/date-fns": "^1.3.13",
"@material-ui/core": "^4.11.3",
"@material-ui/icons": "^4.11.2",
"@material-ui/pickers": "^3.3.10",
"@material-ui/styles": "^4.11.5",
"axios": "^1.8.4",
"axios": "^1.6.0",
"date-fns": "^2.30.0",
"html-to-react": "^1.7.0",
"material-design-icons-iconfont": "^6.1.0",
@ -29,15 +29,15 @@
"react": "^17.0.1",
"react-dom": "^17.0.1",
"react-router-dom": "^5.2.0",
"recharts": "^2.15.3"
"recharts": "^2.2.0"
},
"devDependencies": {
"@babel/core": "^7.28.0",
"@babel/core": "^7.13.10",
"@babel/plugin-proposal-class-properties": "^7.13.0",
"@babel/plugin-transform-runtime": "^7.26.10",
"@babel/preset-react": "^7.26.3",
"@babel/plugin-transform-runtime": "^7.23.9",
"@babel/preset-react": "^7.12.13",
"buffer": "^6.0.3",
"parcel": "^2.14.4",
"parcel": "^2.11.0",
"process": "^0.11.10",
"set-value": "4.1.0"
},

View File

@ -6,8 +6,6 @@ import { BarChart } from "@material-ui/icons";
import { Cloud } from "@material-ui/icons";
import { makeStyles } from "@material-ui/styles";
const logo = new URL("../../images/logo.png", import.meta.url).href;
const DRAWER_WIDTH = 200;
const SidebarNav = ({ active }) => {
@ -57,7 +55,7 @@ const SidebarNav = ({ active }) => {
variant={"permanent"}
>
<img
src={logo}
src={require("../../images/logo.png")}
alt="OpenCost"
style={{ flexShrink: 1, padding: "1rem" }}
/>

View File

@ -238,8 +238,8 @@ const AllocationReport = ({
rowsPerPage={rowsPerPage}
rowsPerPageOptions={[10, 25, 50]}
page={Math.min(page, lastPage)}
onPageChange={handleChangePage}
onRowsPerPageChange={handleChangeRowsPerPage}
onChangePage={handleChangePage}
onChangeRowsPerPage={handleChangeRowsPerPage}
/>
</div>
);

View File

@ -204,8 +204,8 @@ const CloudCost = ({
rowsPerPage={rowsPerPage}
rowsPerPageOptions={[10, 25, 50]}
page={Math.min(page, lastPage)}
onPageChange={handleChangePage}
onRowsPerPageChange={handleChangeRowsPerPage}
onChangePage={handleChangePage}
onChangeRowsPerPage={handleChangeRowsPerPage}
/>
</div>
</div>

View File

@ -56,7 +56,7 @@ const ExternalCostsTable = ({
const routerHistory = useHistory();
const [page, setPage] = React.useState(0);
const [rowsPerPage, setRowsPerPage] = React.useState(25);
const numData = tableData.customCosts?.length ?? 0;
const numData = tableData.customCosts?.length;
const lastPage = Math.floor(numData / rowsPerPage);
@ -67,20 +67,16 @@ const ExternalCostsTable = ({
setPage(0);
};
let pageRows = [];
if (tableData && 'customCosts' in tableData) {
pageRows = tableData.customCosts.slice(
page * rowsPerPage,
page * rowsPerPage + rowsPerPage
);
}
const pageRows = tableData.customCosts.slice(
page * rowsPerPage,
page * rowsPerPage + rowsPerPage
);
React.useEffect(() => {
setPage(0);
}, [numData]);
if ('customCosts' in tableData && tableData.customCosts.length === 0) {
if (tableData.customCosts.length === 0) {
return (
<Typography variant="body2" className={classes.noResults}>
No results
@ -172,8 +168,8 @@ const ExternalCostsTable = ({
rowsPerPage={rowsPerPage}
rowsPerPageOptions={[10, 25, 50]}
page={Math.min(page, lastPage)}
onPageChange={handleChangePage}
onRowsPerPageChange={handleChangeRowsPerPage}
onChangePage={handleChangePage}
onChangeRowsPerPage={handleChangeRowsPerPage}
/>
</div>
);