Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ repos:
- id: debug-statements

- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.4.8
rev: v0.5.5
hooks:
- id: ruff
args:
Expand All @@ -31,7 +31,7 @@ repos:

## ES
- repo: https://github.com/pre-commit/mirrors-eslint
rev: v9.4.0
rev: v9.8.0
hooks:
- id: eslint
additional_dependencies:
Expand Down
3 changes: 3 additions & 0 deletions backend/ibutsu_server/controllers/widget_config_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
from ibutsu_server.util.query import get_offset
from ibutsu_server.util.uuid import validate_uuid

# TODO: pydantic validation of request data structure


def add_widget_config(widget_config=None, token_info=None, user=None):
"""Create a new widget config
Expand All @@ -25,6 +27,7 @@ def add_widget_config(widget_config=None, token_info=None, user=None):
data = connexion.request.json
if data["widget"] not in WIDGET_TYPES.keys():
return "Bad request, widget type does not exist", HTTPStatus.BAD_REQUEST

# add default weight of 10
if not data.get("weight"):
data["weight"] = 10
Expand Down
8 changes: 8 additions & 0 deletions frontend/eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// eslint.config.js
export default [
{
rules: {
"no-unused-vars": "warn", // this isn't actually working through pre-commit or webpack
}
}
];
5 changes: 5 additions & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@
"@babel/core": "^7.24.7",
"@babel/eslint-parser": "^7.24.7",
"@babel/helper-call-delegate": "^7.12.13",
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
"@babel/plugin-syntax-jsx": "^7.24.7",
"@babel/plugin-transform-class-properties": "^7.24.7",
"@babel/plugin-transform-private-methods": "^7.24.7",
"@babel/plugin-transform-private-property-in-object": "^7.24.7",
"@babel/preset-flow": "^7.24.7",
"@babel/preset-react": "^7.24.7",
"@greatsumini/react-facebook-login": "^3.3.3",
Expand Down Expand Up @@ -44,6 +46,9 @@
"typescript": "^4.9.5",
"wolfy87-eventemitter": "^5.2.9"
},
"devDependencies": {
"@babel/plugin-proposal-private-property-in-object": "^7.21.11"
},
"scripts": {
"start": "serve -s build -l tcp://0.0.0.0:8080",
"build": "./bin/write-version-file.js && react-scripts build",
Expand Down
52 changes: 17 additions & 35 deletions frontend/src/admin.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,18 @@
import React from 'react';

import {
Nav,
NavList
} from '@patternfly/react-core';

import { NavLink, Route, Routes } from 'react-router-dom';
import { Navigate, Route, Routes } from 'react-router-dom';
import EventEmitter from 'wolfy87-eventemitter';
import ElementWrapper from './components/elementWrapper';

import { IbutsuPage } from './components';
import { AdminHome } from './pages/admin/home';
import AdminHome from './pages/admin/home';
import { UserList } from './pages/admin/user-list';
import { UserEdit } from './pages/admin/user-edit';
import { ProjectList } from './pages/admin/project-list';
import { ProjectEdit } from './pages/admin/project-edit';
import { AuthService } from './services/auth';

import './app.css';
import AdminPage from './components/admin-page';


export class Admin extends React.Component {
Expand All @@ -34,34 +30,20 @@ export class Admin extends React.Component {
}

render() {
const navigation = (
<Nav onSelect={this.onNavSelect} theme="dark" aria-label="Nav">
<NavList>
<li className="pf-v5-c-nav__item">
<NavLink to="/admin" className="pf-v5-c-nav__link">Admin Home</NavLink>
</li>
<li className="pf-v5-c-nav__item">
<NavLink to="/admin/users" className="pf-v5-c-nav__link">Users</NavLink>
</li>
<li className="pf-v5-c-nav__item">
<NavLink to="/admin/projects" className="pf-v5-c-nav__link">Projects</NavLink>
</li>
</NavList>
</Nav>
);

return (
<React.Fragment>
<IbutsuPage eventEmitter={this.eventEmitter} navigation={navigation} title="Administration | Ibutsu">
<Routes>
<Route path="*" element={<AdminHome />}/>
<Route path="/users" element={<ElementWrapper routeElement={UserList} />} />
<Route path="/users/:id" element={<ElementWrapper routeElement={UserEdit} />} />
<Route path="/projects" element={<ElementWrapper routeElement={ProjectList} />} />
<Route path="/projects/:id" element={<ElementWrapper routeElement={ProjectEdit} />} />
</Routes>
</IbutsuPage>
</React.Fragment>
<Routes>
<Route
path=""
element={<AdminPage eventEmitter={this.eventEmitter} />}
>
<Route path="home" element={<AdminHome/>} />
<Route path="users" element={<ElementWrapper routeElement={UserList} emitter={this.eventEmitter} />} />
<Route path="users/:id" element={<ElementWrapper routeElement={UserEdit} emitter={this.eventEmitter} />} />
<Route path="projects" element={<ElementWrapper routeElement={ProjectList} emitter={this.eventEmitter} />} />
<Route path="projects/:id" element={<ElementWrapper routeElement={ProjectEdit} emitter={this.eventEmitter} />} />
</Route>
<Route path="*" element={<Navigate to="" replace />}/>
</Routes>
);
}
}
136 changes: 59 additions & 77 deletions frontend/src/app.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,23 @@
import React from 'react';

import {
Nav,
NavList
} from '@patternfly/react-core';
import EventEmitter from 'wolfy87-eventemitter';
import ElementWrapper from './components/elementWrapper';

import { NavLink, Route, Routes } from 'react-router-dom';
import { Route, Routes } from 'react-router-dom';

import { Dashboard } from './dashboard';
import { ReportBuilder } from './report-builder';
import { RunList } from './run-list';
import { Run } from './run';
import { ResultList } from './result-list';
import { Result } from './result';
import { Settings } from './settings';
import { View, IbutsuPage } from './components';
import { HttpClient } from './services/http';
import { getActiveProject } from './utilities';
import './app.css';
import { IbutsuContext } from './services/context';

import './app.css';

export class App extends React.Component {
static contextType = IbutsuContext;
constructor(props) {
super(props);
this.eventEmitter = new EventEmitter();
Expand All @@ -33,79 +28,66 @@ export class App extends React.Component {
searchValue: '',
views: []
};
this.eventEmitter.on('projectChange', () => {
this.getViews();
});
}

getViews() {
let params = {'filter': ['type=view', 'navigable=true']};
let project = getActiveProject();
if (project) {
params['filter'].push('project_id=' + project.id);
}
HttpClient.get([Settings.serverUrl, 'widget-config'], params)
.then(response => HttpClient.handleResponse(response))
.then(data => {
data.widgets.forEach(widget => {
if (project) {
widget.params['project'] = project.id;
}
else {
delete widget.params['project'];
}
});
this.setState({views: data.widgets});
});
}

componentDidMount() {
this.getViews();
}

render() {
document.title = 'Ibutsu';
const { views } = this.state;
const navigation = (
<Nav onSelect={this.onNavSelect} theme="dark" aria-label="Nav">
<NavList>
<li className="pf-v5-c-nav__item">
<NavLink to="/" className="pf-v5-c-nav__link">Dashboard</NavLink>
</li>
<li className="pf-v5-c-nav__item">
<NavLink to="/runs" className="pf-v5-c-nav__link">Runs</NavLink>
</li>
<li className="pf-v5-c-nav__item">
<NavLink to="/results" className="pf-v5-c-nav__link">Test Results</NavLink>
</li>
<li className="pf-v5-c-nav__item">
<NavLink to="/reports" className="pf-v5-c-nav__link">Report Builder</NavLink>
</li>
{views && views.map(view => (
view.widget !== "jenkins-analysis-view" && (
<li className="pf-v5-c-nav__item" key={view.id}>
<NavLink to={`/view/${view.id}`} className="pf-v5-c-nav__link">{view.title}</NavLink>
</li>
)
))}
</NavList>
</Nav>
);

return (
<React.Fragment>
<IbutsuPage eventEmitter={this.eventEmitter} navigation={navigation}>
<Routes>
<Route path="*" element={<Dashboard eventEmitter={this.eventEmitter} />} />
<Route path="/runs" element={<ElementWrapper routeElement={RunList} eventEmitter={this.eventEmitter} />} />
<Route path="/results" element={<ElementWrapper routeElement={ResultList} eventEmitter={this.eventEmitter} />} />
<Route path="/reports" element={<ElementWrapper routeElement={ReportBuilder} eventEmitter={this.eventEmitter} />} />
<Route path="/runs/:id" element={<ElementWrapper routeElement={Run} />} />
<Route path="/results/:id" element={<ElementWrapper routeElement={Result} />} />
<Route path="/view/:id" element={<ElementWrapper routeElement={View} />} />
</Routes>
</IbutsuPage>
</React.Fragment>
<Routes>
<Route
path=""
element={<ElementWrapper routeElement={IbutsuPage} eventEmitter={this.eventEmitter} />}
/>
<Route
path=":project_id/*"
element={<ElementWrapper routeElement={IbutsuPage} eventEmitter={this.eventEmitter} />}
>

{/* Nested project routes */}
<Route
path="dashboard/:dashboard_id"
element={
<ElementWrapper routeElement={Dashboard} eventEmitter={this.eventEmitter} />
}
/>
<Route
path="dashboard/*"
element={<ElementWrapper routeElement={Dashboard} eventEmitter={this.eventEmitter} />}
/>


<Route
path="runs"
element={
<ElementWrapper routeElement={RunList} eventEmitter={this.eventEmitter} />
}
/>
<Route
path="runs/:run_id"
element={<ElementWrapper routeElement={Run} />}
/>

<Route
path="results"
element={<ElementWrapper routeElement={ResultList} eventEmitter={this.eventEmitter} />}
/>
<Route
path="results/:result_id"
element={<ElementWrapper routeElement={Result} />}
/>

<Route
path="reports"
element={<ElementWrapper routeElement={ReportBuilder} eventEmitter={this.eventEmitter} />}
/>

<Route
path="view/:view_id"
element={<ElementWrapper routeElement={View} />}
/>
</Route>

</Routes>
);
}
}
46 changes: 25 additions & 21 deletions frontend/src/base.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,35 +3,39 @@ import React from 'react';
import { BrowserRouter as Router, Route, Routes, Navigate } from 'react-router-dom';
import { App } from './app';
import { Admin } from './admin';
import { Profile } from './profile';
import Profile from './profile';
import { Login } from './login';
import { SignUp } from './sign-up';
import { ForgotPassword } from './forgot-password';
import { ResetPassword } from './reset-password';
import { AuthService } from './services/auth';
import ElementWrapper from './components/elementWrapper';
import { IbutsuContextProvider } from './services/context';

export const Base = () => {
return (
<Router>
<Routes>
<Route path="/login" element={<ElementWrapper routeElement={Login} />} />
<Route path="/sign-up" element={<ElementWrapper routeElement={SignUp} />} />
<Route path="/forgot-password" element={<ElementWrapper routeElement={ForgotPassword} />} />
<Route path="/reset-password/:activationCode" element={<ElementWrapper routeElement={ResetPassword} />} />
<Route
path="/profile/*"
element={AuthService.isLoggedIn() ? <Profile /> : <Navigate to="/login" />}
/>
<Route
path="/admin/*"
element={AuthService.isLoggedIn() ? <Admin /> : <Navigate to="/" />}
/>
<Route
path="*"
element={AuthService.isLoggedIn() ? <App /> : <Navigate to="/login" />}
/>
</Routes>
</Router>
<IbutsuContextProvider>
<Router>
<Routes>
<Route path="login" element={<ElementWrapper routeElement={Login} />} />
<Route path="sign-up" element={<ElementWrapper routeElement={SignUp} />} />
<Route path="forgot-password" element={<ElementWrapper routeElement={ForgotPassword} />} />
<Route path="reset-password/:activationCode" element={<ElementWrapper routeElement={ResetPassword} />} />
<Route
path="profile/*"
element={AuthService.isLoggedIn() ? <Profile /> : <Navigate to="/login" />}
/>
<Route
path="admin/*"
element={AuthService.isLoggedIn() && AuthService.isSuperAdmin() ? <Admin /> : <Navigate to="/login" />}
/>
<Route
path="project/*"
element={AuthService.isLoggedIn() ? <App /> : <Navigate to="/login" />}
/>
<Route path="*" element={<Navigate to="project" replace />} />
</Routes>
</Router>
</IbutsuContextProvider>
);
};
Loading