Skip to content
Draft
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
71 changes: 42 additions & 29 deletions eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,36 +3,49 @@ import globals from 'globals'
import react from 'eslint-plugin-react'
import reactHooks from 'eslint-plugin-react-hooks'
import reactRefresh from 'eslint-plugin-react-refresh'
import tseslint from "@typescript-eslint/eslint-plugin"
import tsparser from "@typescript-eslint/parser"

export default [
{ ignores: ['dist'] },
{
files: ['**/*.{js,jsx}'],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
parserOptions: {
ecmaVersion: 'latest',
ecmaFeatures: { jsx: true },
sourceType: 'module',
},
{
ignores: ['dist'],
files: ['**/*.{js,jsx,ts,tsx}'],
languageOptions: {
parser: tsparser,
ecmaVersion: 2020,
globals: globals.browser,
parserOptions: {
ecmaVersion: 'latest',
ecmaFeatures: {jsx: true},
sourceType: 'module',
},
},
settings: {react: {version: 'detect'}},
plugins: {
react,
'react-hooks': reactHooks,
'react-refresh': reactRefresh,
'@typescript-eslint': tseslint,
},
// extends: [
// "eslint:recommended",
// "next/core-web-vitals",
// "plugin:react/recommended",
// "standard-with-typescript",
// "plugin:@typescript-eslint/recommended",
// ],
rules: {
...js.configs.recommended.rules,
...react.configs.recommended.rules,
...react.configs['jsx-runtime'].rules,
...reactHooks.configs.recommended.rules,
'@typescript-eslint/no-unused-vars': 'error',
'no-unused-vars': 'off',
'react/jsx-no-target-blank': 'off',
'react-refresh/only-export-components': [
'warn',
{allowConstantExport: true},
],
},
},
settings: { react: { version: '18.3' } },
plugins: {
react,
'react-hooks': reactHooks,
'react-refresh': reactRefresh,
},
rules: {
...js.configs.recommended.rules,
...react.configs.recommended.rules,
...react.configs['jsx-runtime'].rules,
...reactHooks.configs.recommended.rules,
'react/jsx-no-target-blank': 'off',
'react-refresh/only-export-components': [
'warn',
{ allowConstantExport: true },
],
},
},
]
53 changes: 30 additions & 23 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,32 +16,39 @@
"bootstrap": "^5.3.3",
"bootswatch": "^5.3.3",
"date-fns": "^4.1.0",
"i18next": "^23.15.1",
"i18next-http-backend": "^2.6.1",
"js-pkce": "^1.4.0",
"js-yaml": "^4.1.0",
"oidc-client-ts": "^3.0.1",
"i18next": "^25.7.3",
"i18next-http-backend": "^3.0.2",
"js-pkce": "^2.0.0",
"js-yaml": "^4.1.1",
"oidc-client-ts": "^3.4.1",
"prop-types": "^15.8.1",
"react": "^18.3.1",
"react-bootstrap": "^2.10.4",
"react-dom": "^18.3.1",
"react-i18next": "^15.0.2",
"react-oidc-context": "^3.1.1",
"react-router-dom": "^6.26.2",
"sass": "^1.79.1",
"swr": "^2.2.5",
"react": "^19.2.3",
"react-bootstrap": "^2.10.10",
"react-dom": "^19.2.3",
"react-i18next": "^16.5.0",
"react-oidc-context": "^3.3.0",
"react-router-dom": "^7.11.0",
"sass": "^1.97.0",
"swr": "^2.3.8",
"vite-plugin-compression": "^0.5.1"
},
"devDependencies": {
"@eslint/js": "^9.9.0",
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"@vitejs/plugin-react": "^4.3.1",
"eslint": "^9.9.0",
"eslint-plugin-react": "^7.35.0",
"eslint-plugin-react-hooks": "^5.1.0-rc.0",
"eslint-plugin-react-refresh": "^0.4.9",
"globals": "^15.9.0",
"vite": "^5.4.1"
"typescript":">=4.0.0",
"@eslint/js": "^9.39.2",
"@tsconfig/vite-react": "^7.0.2",
"@types/js-yaml": "^4.0.9",
"@types/react": "^19.2.7",
"@types/react-dom": "^19.2.3",
"@types/web": "^0.0.303",
"@typescript-eslint/eslint-plugin": "^8.50.0",
"@typescript-eslint/parser": "^8.50.0",
"@vitejs/plugin-react": "^5.1.2",
"eslint": "^9.39.2",
"eslint-plugin-react": "^7.37.5",
"eslint-plugin-react-hooks": "^7.0.1",
"eslint-plugin-react-refresh": "^0.4.26",
"globals": "^16.5.0",
"typescript-plugin-css-modules": "^5.2.0",
"vite": "^7.3.0"
}
}
55 changes: 0 additions & 55 deletions src/App.jsx

This file was deleted.

49 changes: 49 additions & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import {createElement} from 'react';
import {Container} from 'react-bootstrap';
import {Route, Routes} from 'react-router-dom';

import NavBar from './layout/NavBar.tsx';
import Footer from './layout/Footer.tsx';
import Sensors from './pages/Sensors.tsx';
import OauthCallback from './pages/OauthCallback.tsx';
import Logout from './pages/Logout.tsx';
import Login from './pages/Login.tsx';
import RequireLoggedIn from './widgets/RequireLoggedIn.tsx';
import ActionLog from './pages/ActionLog.tsx';
import {useVariant} from './hooks/useVariant.ts';
import {getDoorActions, getHvacActions, getLightActions} from "./utils/device.ts";
import Devices from "./pages/Devices.tsx";
import {useDocumentTitle} from '@uidotdev/usehooks';

function App() {
const variant = useVariant();
useDocumentTitle(variant.title);

return (<>
<NavBar/>
<main>
<Container as="section" className="mt-4">
<Routes>
<Route path="/" element={createElement(variant.dashboard)}/>
<Route path="/doors" element={<RequireLoggedIn>
<Devices deviceGroup="door" deviceActionMapper={getDoorActions}/>
</RequireLoggedIn>}/>
<Route path="/lights" element={<RequireLoggedIn>
<Devices deviceGroup="light" deviceActionMapper={getLightActions}/>
</RequireLoggedIn>}/>
<Route path="/hvac" element={<RequireLoggedIn>
<Devices deviceGroup="hvac" deviceActionMapper={getHvacActions}/>
</RequireLoggedIn>}/>
<Route path="/sensors" element={<Sensors/>}/>
<Route path="/action-log" element={<ActionLog/>}/>
<Route path="/oauth-callback" element={<OauthCallback/>}/>
<Route path="/login" element={<Login/>}/>
<Route path="/logout" element={<Logout/>}/>
</Routes>
</Container>
</main>
<Footer/>
</>);
}

export default App;
28 changes: 0 additions & 28 deletions src/config.js

This file was deleted.

53 changes: 53 additions & 0 deletions src/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import ColibriDashboard from "./widgets/Dashboards/ColibriDashboard.tsx";
import InitLabDashboard from "./widgets/Dashboards/InitLabDashboard.tsx";

import initlabLogo from './assets/initlab/logo.svg?no-inline';
import colibriLogo from './assets/colibri/logo.png?no-inline';
import type {ReactNode} from "react";

export const oidc = {
authority: import.meta.env.OIDC_AUTHORITY_URL,
client_id: import.meta.env.OIDC_CLIENT_ID,
redirect_uri: window.location.protocol + '//' + window.location.host + import.meta.env.BASE_URL + 'oauth-callback',
};

export type MqttConfig = {[topic: string]: {label: string}}
export const sensors: MqttConfig = {
'sensors/big-room': {label: 'Big room',},
'sensors/small-room': {label: 'Small room',},
'sensors/kitchen': {label: 'Kitchen',},
'sensors/outside': {label: 'Outside',},
};

export const variantHosts: {[hostname: string]: string} = {
'space.initlab.org': 'initlab',
'initlab.github.io': 'initlab',
'colibri.initlab.org': 'colibri',
}

type VariantConfig = {
dashboard: () => ReactNode,
navbar: any,
logo: {url: string, alt: string},
title: string,
}

export const variants: {[variant: string]: VariantConfig} = {
'initlab': {
dashboard: InitLabDashboard,
navbar: {bg: 'primary', variant: 'dark',},
logo: {url: initlabLogo, alt: 'init Lab logo',},
title: 'init Lab Space',
},
'colibri': {
dashboard: ColibriDashboard,
navbar: {bg: 'light',},
logo: {url: colibriLogo, alt: 'colibri logo',},
title: 'Casa Libri',
},
}

export const grafana = {
dashboard: {id: 'SGAb0ZXMk', name: 'temperature-and-humidity',},
panels: [4, 5, 10],
};
14 changes: 14 additions & 0 deletions src/fauna-types.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export type FaunaUser = {
roles: string[],
locale?: string,
}

export type FaunaPresentUser = {
id: number | null,
username: string,
picture: string,
twitter?: string,
github?: string,
url?: string,
};

9 changes: 9 additions & 0 deletions src/globals.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
declare module "*.css";
declare module "*.scss";

declare module "*.png";
declare module "*.svg";


declare module "*?inline";
declare module "*?no-inline";
8 changes: 8 additions & 0 deletions src/helpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import type {FaunaUser} from "./fauna-types";

export function hasRole(user: FaunaUser | undefined, roles: string | string[]) {
if (!user) return false;

const searchRoles = typeof roles === 'string' ? [roles] : Array.from(roles);
return (user?.roles || []).some(x => searchRoles.includes(x));
}
5 changes: 0 additions & 5 deletions src/hooks/useActionLog.js

This file was deleted.

Loading