Skip to content
Open
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
5 changes: 5 additions & 0 deletions .changeset/lucky-bees-push.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@nordeck/matrix-neoboard-standalone': minor
---

customize the open desk navbar according to theme colors via environment variables.
22 changes: 20 additions & 2 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,16 @@ REACT_APP_WIDGET_BASE=https://neoboard.example.com
# We specifically set NeoBoard to embedded mode.
REACT_APP_EMBEDDED=true

# The name of the product to be displayed.
REACT_APP_PRODUCT_NAME=NeoBoard

# An appearance to be shown. Either `neoboard` or `opendesk`.
REACT_APP_APPEARANCE=neoboard

REACT_APP_FAVICON_16=
REACT_APP_FAVICON_32=
REACT_APP_APPLE_TOUCH_ICON=

# A primary palette color for the light theme.
REACT_APP_LIGHT_PRIMARY_COLOR='#e85e10'

Expand All @@ -31,9 +38,20 @@ REACT_APP_LIGHT_BACKGROUND_CARD='#fce2cf'
# Required `opendesk` banner configuration variables
REACT_APP_OPENDESK_BANNER_ICS_NAVIGATION_JSON_URL=
REACT_APP_OPENDESK_BANNER_ICS_SILENT_URL=
REACT_APP_OPENDESK_BANNER_PORTAL_LOGO_SVG_URL=
REACT_APP_OPENDESK_BANNER_PORTAL_URL=
REACT_APP_OPENDESK_BANNER_PORTAL_LOGO_SVG_URL=

# Optional `opendesk` banner configuration variables
REACT_APP_OPENDESK_BANNER_TEXT_ACTION_ACCENT='#5e27dd'
REACT_APP_OPENDESK_BANNER_APP_HOME_ICON_SVG_URL=
REACT_APP_OPENDESK_BANNER_PORTAL_LOGO_WIDTH='120px'
REACT_APP_OPENDESK_BANNER_TEXT_ACTION_ACCENT='#EEEFF2'
REACT_APP_OPENDESK_BANNER_COLOR_TEXT_PRIMARY='#1b1d22'
REACT_APP_OPENDESK_BANNER_TEXT_PRIMARY_HOVER='#1b1d22'
REACT_APP_OPENDESK_BANNER_TEXT_PRIMARY_ACTIVE='#ffffff'

REACT_APP_OPENDESK_BANNER_HEIGHT='60px'
REACT_APP_OPENDESK_BANNER_BACKGROUND_COLOR='#ffffff'
REACT_APP_OPENDESK_BANNER_BACKGROUND_COLOR_HOVER='#f5f8fa'
REACT_APP_OPENDESK_BANNER_BACKGROUND_COLOR_ACTIVE='#571EFA'

REACT_APP_OPENDESK_BANNER_BORDER_BOTTOM='1px solid #d3d7de'
26 changes: 18 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ They can either be set via an environment variable or the `.env`-file.
| `REACT_APP_HOMESERVER` | If set, it uses this homeserver instead of showing an input field on the login screen. Either a domain name or homeserver URL. | `example.com` or `https://example.com` |
| `REACT_APP_SKIP_LOGIN` | If set to `true` and `REACT_APP_HOMESERVER` is set, then the application skips welcome/login screens and starts SSO immediately. It is not set by default. | `true` |
| `REACT_APP_LOGOUT_REDIRECT_URL` | If set, the application redirects the user to the specified URL after logout. | `https://id.example.com/logout` |
| `REACT_APP_PRODUCT_NAME` | The name of the product to be displayed. | `NeoBoard` |
| `REACT_APP_APPEARANCE` | An appearance to be shown. Either `neoboard` or `opendesk`. | `neoboard` |
| `REACT_APP_LIGHT_PRIMARY_COLOR` | This overrides a primary palette color for the light theme. | `#e85e10` |
| `REACT_APP_LIGHT_PRIMARY_COLOR_LIGHT` | This overrides a primary palette light color for the light theme. | `#ff8a42` |
Expand All @@ -27,14 +28,23 @@ They can either be set via an environment variable or the `.env`-file.

`opendesk` banner configurations:

| Name | Description | Example |
| --------------------------------------------------- | -------------------------------------------------------------------------------------------------- | ------------------------------------- |
| `REACT_APP_OPENDESK_BANNER_ICS_NAVIGATION_JSON_URL` | Required. The URL of the navigation.json file that contains the navigation structure for the user. | `https://example.com/navigation.json` |
| `REACT_APP_OPENDESK_BANNER_ICS_SILENT_URL` | Required. The URL of the silent endpoint that is used via inline frame to log in the user. | `https://example.com/silent` |
| `REACT_APP_OPENDESK_BANNER_PORTAL_LOGO_SVG_URL` | Required. The URL of the portal logo.svg file. | `https://example.com/logo.svg` |
| `REACT_APP_OPENDESK_BANNER_PORTAL_URL` | Required. The URL of the portal. | `https://example.com` |
| `REACT_APP_OPENDESK_BANNER_TEXT_ACTION_ACCENT` | Optional. Background of the launcher icon when expanded and the top border of the menu. | `#5e27dd` |
| `REACT_APP_OPENDESK_BANNER_COLOR_TEXT_PRIMARY` | Optional. Primary text color. | `#1b1d22` |
| Name | Description | Example |
| ----------------------------------------------------- | -------------------------------------------------------------------------------------------------- | ------------------------------------- |
| `REACT_APP_OPENDESK_BANNER_ICS_NAVIGATION_JSON_URL` | Required. The URL of the navigation.json file that contains the navigation structure for the user. | `https://example.com/navigation.json` |
| `REACT_APP_OPENDESK_BANNER_ICS_SILENT_URL` | Required. The URL of the silent endpoint that is used via inline frame to log in the user. | `https://example.com/silent` |
| `REACT_APP_OPENDESK_BANNER_PORTAL_URL` | Required. The URL of the portal. | `https://example.com` |
| `REACT_APP_OPENDESK_BANNER_PORTAL_LOGO_SVG_URL` | Required. The URL of the portal logo.svg file. | `https://example.com/logo.svg` |
| `REACT_APP_OPENDESK_BANNER_PORTAL_LOGO_WIDTH` | optional. The width of the portal logo. | `120` |
| `REACT_APP_OPENDESK_BANNER_APP_HOME_ICON_SVG_URL` | optional. The URL of the app home icon.svg file. | `https://example.com/home.svg` |
| `REACT_APP_OPENDESK_BANNER_TEXT_ACTION_ACCENT` | Optional. Background of the launcher icon when not expanded. | `#eeeff2` |
| `REACT_APP_OPENDESK_BANNER_COLOR_TEXT_PRIMARY` | Optional. Primary text color. | `#1b1d22` |
| `REACT_APP_OPENDESK_BANNER_COLOR_TEXT_PRIMARY_HOVER` | Optional. Primary text color when hovered. | `#1b1d22` |
| `REACT_APP_OPENDESK_BANNER_COLOR_TEXT_PRIMARY_ACTIVE` | Optional. Primary text color when active. | `#ffffff` |
| `REACT_APP_OPENDESK_BANNER_BACKGROUND_COLOR` | Optional. Background color of the navbar. | `#ffffff` |
| `REACT_APP_OPENDESK_BANNER_BACKGROUND_COLOR_HOVER` | Optional. Background color of the title when hovered. | `#eeeff2` |
| `REACT_APP_OPENDESK_BANNER_BACKGROUND_COLOR_ACTIVE` | Optional. Background color of the title when active. | `#571EFA` |
| `REACT_APP_OPENDESK_BANNER_HEIGHT` | Optional. Height of the navbar. | `60px` |
| `REACT_APP_OPENDESK_BANNER_BORDER_BOTTOM` | Optional. Border bottom of the navbar. | `1px solid #d3d7de` |

## Getting Started

Expand Down
Binary file added public/tmp/img.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
90 changes: 90 additions & 0 deletions public/tmp/navigation.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
{

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand these temporary files are useful for testing the new design but I think they should not be part of the repository, so let's not forget to remove them once this is completed.

"categories": [
{
"identifier": "od.applications",
"display_name": "Applications",
"entries": [
{
"identifier": "swp.fileshare_files",
"icon_url": "https://portal.opendesk.family/univention/portal/icons/entries/swp.fileshare_files.svg",
"display_name": "Files",
"link": "https://files.nightly.opendesk.run/apps/files",
"target": "tab_fileshare",
"keywords": {}
},
{
"identifier": "swp.groupware_mail",
"icon_url": "https://portal.opendesk.family/univention/portal/icons/entries/swp.groupware_mail.svg",
"display_name": "Email",
"link": "https://webmail.nightly.opendesk.run/appsuite/#app=io.ox/mail",
"target": "tab_groupware",
"keywords": {}
},
{
"identifier": "swp.groupware_calendar",
"icon_url": "https://portal.opendesk.family/univention/portal/icons/entries/swp.groupware_calendar.svg",
"display_name": "Calendar",
"link": "https://webmail.nightly.opendesk.run/appsuite/#app=io.ox/calendar",
"target": "tab_groupware",
"keywords": {}
},
{
"identifier": "swp.groupware_contacts",
"icon_url": "https://portal.opendesk.family/univention/portal/icons/entries/swp.groupware_contacts.svg",
"display_name": "Contacts",
"link": "https://webmail.nightly.opendesk.run/appsuite/#app=io.ox/contacts",
"target": "tab_groupware",
"keywords": {}
},
{
"identifier": "swp.groupware_tasks",
"icon_url": "https://portal.opendesk.family/univention/portal/icons/entries/swp.groupware_tasks.svg",
"display_name": "Tasks",
"link": "https://webmail.nightly.opendesk.run/appsuite/#app=io.ox/tasks",
"target": "tab_groupware",
"keywords": {}
},
{
"identifier": "swp.management_project",
"icon_url": "https://portal.opendesk.family/univention/portal/icons/entries/swp.management_project.svg",
"display_name": "Projects",
"link": "https://projects.nightly.opendesk.run/auth/keycloak",
"target": "tab_projectmanagement",
"keywords": {}
},
{
"identifier": "swp.management_knowledge",
"icon_url": "https://portal.opendesk.family/univention/portal/icons/entries/swp.management_knowledge.svg",
"display_name": "Knowledge",
"link": "https://wiki.nightly.opendesk.run",
"target": "tab_knowledgemanagement",
"keywords": {}
},
{
"identifier": "swp.realtime_videoconference",
"icon_url": "https://portal.opendesk.family/univention/portal/icons/entries/swp.realtime_videoconference.svg",
"display_name": "Videoconference",
"link": "https://meet.nightly.opendesk.run",
"target": "tab_realtime_videoconference",
"keywords": {}
},
{
"identifier": "swp.realtime_collaboration",
"icon_url": "https://portal.opendesk.family/univention/portal/icons/entries/swp.realtime_collaboration.svg",
"display_name": "Chat",
"link": "https://chat.nightly.opendesk.run",
"target": "tab_realtime_collaboration",
"keywords": {}
},
{
"identifier": "swp.realtime_whiteboard",
"icon_url": "/opendesk.svg",
"display_name": "Whiteboard",
"link": "/dashboard",
"target": "tab_realtime_whiteboard",
"keywords": {}
}
]
}
]
}
13 changes: 13 additions & 0 deletions public/tmp/silent.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!doctype html>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as the navigation.json, these should be used for testing and removed before merging.

<html lang="en">
<head></head>
<body>
<p>This is for the Frame for clients to load. Loggend in status: true</p>

<script type="text/javascript">
// TODO: Proper Session Handling: https://openid.net/specs/openid-connect-session-1_0.html
// TODO: Proper security assessment / restrict postmessage target origin as much as possible
parent.postMessage({ loggedIn: true, csrftoken: 'xyz' }, '*');
</script>
</body>
</html>
19 changes: 16 additions & 3 deletions src/AppContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
* along with NeoBoard Standalone. If not, see <https://www.gnu.org/licenses/>.
*/

import { getEnvironment } from '@matrix-widget-toolkit/mui';
import {
WhiteboardManager,
WhiteboardManagerProvider,
Expand All @@ -35,23 +36,35 @@ export const AppContainer = ({
}) => {
useLayoutEffect(() => {
const appearance = getEnvironmentAppearance();
const favicon16 = getEnvironment(
'REACT_APP_FAVICON_16',
`/${appearance}-16.png`,
);
const favicon32 = getEnvironment(
'REACT_APP_FAVICON_32',
`/${appearance}-32.png`,
);
const appleTouchIcon = getEnvironment(
'REACT_APP_APPLE_TOUCH_ICON',
`/${appearance}-apple-touch-icon.png`,
);

const logo32 = document.createElement('link');
logo32.setAttribute('rel', 'icon');
logo32.setAttribute('type', 'image/png');
logo32.setAttribute('sizes', '32x32');
logo32.setAttribute('href', `/${appearance}-32.png`);
logo32.setAttribute('href', favicon32);

const logo16 = document.createElement('link');
logo16.setAttribute('rel', 'icon');
logo16.setAttribute('type', 'image/png');
logo16.setAttribute('sizes', '16x16');
logo16.setAttribute('href', `/${appearance}-16.png`);
logo16.setAttribute('href', favicon16);

const appleTouch = document.createElement('link');
appleTouch.setAttribute('rel', 'apple-touch-icon');
appleTouch.setAttribute('sizes', '180x180');
appleTouch.setAttribute('href', `/${appearance}-apple-touch-icon.png`);
appleTouch.setAttribute('href', appleTouchIcon);

document.head.appendChild(logo32);
document.head.appendChild(logo16);
Expand Down
13 changes: 2 additions & 11 deletions src/components/Header/HeaderTitle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import { styled } from '@mui/material';
import React from 'react';
import { useTranslation } from 'react-i18next';
import { Link } from 'react-router';
import { getEnvironmentAppearance } from '../../lib';
import { Title } from './Title.tsx';

const TitleWrapper = styled('div')(() => ({
Expand All @@ -37,18 +36,10 @@ type Props = {
hasPadding?: boolean;
};

const appearance = getEnvironmentAppearance();

const ButtonStyled = styled('div')(({ theme }) => ({
const ButtonStyled = styled('div')({
cursor: 'pointer',
lineHeight: 0,
...(appearance === 'opendesk' && {
color: theme.navbar.color.textPrimary,
'&:active': {
color: theme.navbar.color.textActionAccent,
},
}),
}));
});

export function HeaderTitle({ title, roomId, homeIcon, hasPadding }: Props) {
const { t } = useTranslation();
Expand Down
1 change: 1 addition & 0 deletions src/components/Header/InvitesMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ export const InvitesMenu: React.FC = () => {
display: 'flex',
justifyContent: 'center',
width: 40,
color: 'inherit',
}}
>
<Badge
Expand Down
1 change: 1 addition & 0 deletions src/components/Header/ShareMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ export function ShareMenu({ roomId }: { roomId: string }) {
display: 'flex',
justifyContent: 'center',
width: 40,
color: 'inherit',
}}
>
<Share sx={{ width: 24, height: 24 }} />
Expand Down
29 changes: 25 additions & 4 deletions src/components/Header/Title.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,19 @@
import { styled, Tooltip } from '@mui/material';
import { useCallback, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { getEnvironmentAppearance } from '../../lib';
import { useDashboardList } from '../Dashboard/useDashboardList';
import { RenameDialog } from '../RenameDialog';

const appearance = getEnvironmentAppearance();
const StyledTitle = styled('div')(({ theme }) => ({
color: theme.palette.primary.main,
...(appearance === 'opendesk'
? {
color: theme.navbar.color.textPrimary,
}
: {
color: theme.palette.primary.main,
}),
flexGrow: 1,
fontSize: '25px',
fontWeight: '600',
Expand All @@ -45,9 +53,22 @@ const EditableTitle = styled('button')(({ theme }) => ({
fontWeight: 'inherit',
whiteSpace: 'inherit',
padding: '8px',
'&:hover': {
backgroundColor: theme.palette.grey[200],
},
...(appearance === 'opendesk'
? {
'&:hover': {
color: theme.navbar.color.textPrimaryHover,
backgroundColor: theme.palette.background.hover,
},
'&:active': {
color: theme.navbar.color.textPrimaryActive,
backgroundColor: theme.palette.background.active,
},
}
: {
'&:hover': {
backgroundColor: theme.palette.grey[200],
},
}),
}));

type TitleProps = {
Expand Down
29 changes: 29 additions & 0 deletions src/components/LoggedInLayout/HomeIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright 2026 Nordeck IT + Consulting GmbH
*
* NeoBoard Standalone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* NeoBoard Standalone is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE.
*
* See the GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with NeoBoard Standalone. If not, see <https://www.gnu.org/licenses/>.
*/

import { getEnvironment } from '@matrix-widget-toolkit/mui';
import { ImgHTMLAttributes } from 'react';

const home_icon_src = getEnvironment(
'REACT_APP_OPENDESK_BANNER_APP_HOME_ICON_SVG_URL',
`${window.location.origin}/opendesk.svg`,
);

export const HomeIcon = (props: ImgHTMLAttributes<HTMLImageElement>) => {
return <img src={home_icon_src} width={32} height={32} alt="" {...props} />;
};
Loading
Loading