Skip to content

Feature/industry theme - #2

Merged
oxixes merged 15 commits into
Ficodes:mainfrom
rafitanba:feature/industry-theme
Nov 5, 2026
Merged

oxixes merged 15 commits into
Ficodes:mainfrom
rafitanba:feature/industry-theme

Conversation

@rafitanba

Copy link
Copy Markdown

Summary

Adds Industry, a new root theme (industrytheme, parent = None) with light and dark color schemes, and a set of theme extension points in the platform so themes can change more than CSS. Every hook defaults to the previous behaviour: defaulttheme and the FIWARE themes look and behave as before.

Platform: theme extension points (commit 1)

  • Theme config: ThemeInfo.config is read from the theme module (config = {...}, inherited by child themes) and exposed as Wirecloud.currentTheme.config.
  • Root state attributes on <html>: data-wc-theme, data-wc-view, data-wc-mode (view|edit|wiring|catalogue|marketplace), data-wc-color-scheme and data-wc-screen-size.
  • Wirecloud.ui.registry: the header, workspace view and toolbar, widget view (getTemplateComponents()), wiring components, My resources views, resource painter, embed/sharing dialogs and command palette are built through it, falling back to the platform classes.
  • Decoupled header: WirecloudHeader.defaults (button classes and icons) and buildUserMenu(). The workspace view and wiring editor expose getModes(), getPrimaryAction(), getSecondaryActions(), deleteSelection() and cancel(). The workspace view also tracks the selected widget in edit mode.
  • Wirecloud.commands: a command registry fed from the existing menu builders (workspace, tab, widget, marketplace), plus the workspace list, navigation and installed components.
  • Wirecloud.ui.shortcuts: ⌘/Ctrl+K, V/E/W, Delete and Esc. It is only active when the theme sets keyboard_shortcuts.
  • color-scheme platform preference (system|light|dark): shown only when the theme supports several schemes, and propagated to widget documents.
  • Optional click-to-connect in the wiring editor (wiring_click_to_connect): click an output, then an input; Esc or a click outside cancels.
  • Fix: get_theme_static_path no longer imports wirecloud.themes.None for root themes without a static/ dir.

Industry theme (commit 2)

  • Shell:
    • nav rail;
    • workspace header with workspace switcher, visibility tag, ⌘K trigger, View/Edit/Wiring switch, Share, workspace menu and primary action;
    • tab bar with numbered tabs, layout controls (Phone/Tablet/Desktop + Layout settings dialog applied live) and shortcut hints;
    • status bar.
  • Command palette, toasts with undo when removing widgets, and an embed dialog with "Copy code".
  • Dashboard: edit grid, minimal widget chrome in view mode, selection with size badge and resize square in edit mode, and the Add widget drawer.
  • Wiring: dot grid canvas, tagged components with square ports, accent connections and a draft connection hint.
  • My resources: type and vendor facets, grid and table views with incremental loading, and a detail pane.
  • Everything else restyled: StyledElements, dialogs, legacy catalogue views, tutorial, login and error pages, and a small token-based stylesheet for widgets.
  • Assets: self-hosted Barlow fonts (OFL) and Lucide icons (ISC, stroke-width 1.5). No Font Awesome: the FA class names used by the platform and widgets are mapped to Lucide icons (scripts/update_icons.py).
  • Translations and docs: Spanish translations; docs/themes.md documents the extension points.

Testing

  • npm run test:js: 4081 passing (new tests for the registry, commands, shortcuts, color scheme, platform commands, the workspace view API, click-to-connect and the theme-gated preference).
  • pytest (Python 3.9, as in CI): 592 passing, including a test that loads every Industry template for classic, smartphone and embedded. The 8 failures in test_packaging_build_hooks.py and test_workspace_crud.py also fail on main.
  • npm run build compiles every theme.
  • Manual checks in Chrome, with a local instance in light and dark:
    • view, edit and wiring (including click-to-connect), palette, My resources, dialogs, login and error pages, smartphone and embedded;
    • with defaulttheme active: no errors, shortcuts disabled, and the color-scheme preference hidden.

Notes

  • "In N workspaces" in My resources counts only the active workspace, because there is no usage API.
  • Previews with ?themeactive=industrytheme: while another theme is THEME_ACTIVE, fonts and icons 404, because relative static URLs resolve through THEME_ACTIVE. Fonts in defaulttheme have the same limitation.
  • Pre-existing issues found while testing (not changed here):
    • manage createsuperuser imports a non-existent create_user;
    • the unpinned elasticsearch client resolves to 9.x, which the Elasticsearch 8.13 in docker-compose.yml rejects.

Rafael Fernández and others added 2 commits October 28, 2026 15:44
Give themes more freedom without changing the behaviour of the existing
themes (every hook defaults to the previous behaviour):

- ThemeInfo.config: optional client configuration read from the theme
  module (child themes override their parent), exposed as
  Wirecloud.currentTheme.config.
- data-wc-theme/view/mode/color-scheme/screen-size attributes on the
  root element, so themes can style the platform state with CSS.
- Wirecloud.ui.registry: the header, workspace toolbar, widget view
  (getTemplateComponents), wiring components, catalogue views, resource
  painter, embed/sharing dialogs and command palette are built through
  it, falling back to the platform classes.
- WirecloudHeader presentation defaults and buildUserMenu() can be
  overridden; the workspace view and the wiring editor expose
  getModes(), getPrimaryAction(), getSecondaryActions(),
  deleteSelection() and cancel(); the workspace view tracks the selected
  widget while editing.
- Wirecloud.commands: command registry fed from the existing menu
  builders (workspace, tab, widget, marketplace), the workspace list,
  navigation and the installed components.
- Wirecloud.ui.shortcuts: Cmd/Ctrl+K, V/E/W, Delete and Esc, enabled by
  the `keyboard_shortcuts` theme config.
- "color-scheme" platform preference (system/light/dark), shown only
  when the theme supports several schemes, applied to the root element
  and propagated to the widget documents.
- Optional click-to-connect in the wiring editor
  (`wiring_click_to_connect` theme config).
- Fix get_theme_static_path for root themes without a static directory
  (it tried to import "wirecloud.themes.None").

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
New root theme (parent = None) written from scratch, with light and dark
color schemes, built on the theme extension points:

- Shell: navigation rail (workspaces, my resources, marketplace, color
  scheme, user menu), workspace header with workspace switcher,
  visibility tag, command palette trigger, View/Edit/Wiring mode switch,
  share, workspace menu and primary action, tab bar with numbered tabs,
  layout controls and shortcut hints, and a status bar.
- Command palette (Cmd/Ctrl+K) over Wirecloud.commands, toasts (undo
  when removing widgets), layout settings dialog (screen sizes, cell
  height and widget margin applied live) and an embed dialog with a
  "Copy code" button.
- Dashboard: edit grid, minimal widget chrome in view mode, selection
  with size badge and resize handle in edit mode, add widget drawer.
- Wiring: dot grid canvas, tagged components with square ports, accent
  connections, draft connection hint (click to connect).
- My resources: type/vendor facets, grid and table results with
  incremental loading and a detail pane.
- StyledElements, dialogs, legacy catalogue views, tutorial, login and
  error pages, and a small token based stylesheet for widgets.
- Self-hosted Barlow fonts (OFL) and Lucide icons (ISC) at stroke-width
  1.5; Font Awesome class names used by the platform and widgets are
  mapped to Lucide icons (scripts/update_icons.py copies new icons).
- Spanish translations, documentation and test of the theme templates.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@rafitanba
rafitanba requested a review from oxixes October 28, 2026 14:49
Rafael Fernández and others added 4 commits October 28, 2026 17:31
The `catalogue/` rule in .gitignore matches any directory with that name,
so the catalogue templates and stylesheets of the Industry theme were left
out of the previous commit. Force-add them, as the defaulttheme ones are.

The webpack entries skip missing files silently, so add a test that checks
every file referenced in theme.ts exists.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Widgets get the theme icon styles too, and the Markdown editor widget
(SimpleMDE) uses Font Awesome names that were not mapped, so its toolbar
showed filled squares: the generic `.fa::before` rule painted the current
color without any mask.

- Map the icons used by text editors (bold, italic, heading, quote, lists,
  image, table...) including their Font Awesome 4/5/6 aliases, and add
  their Lucide SVGs.
- Draw the mask only for mapped names, so an unknown name shows nothing
  (or the glyph of a Font Awesome stylesheet loaded by the widget) instead
  of a filled square. The mapped rules include the `.fa` class to win over
  that stylesheet, which is loaded after the theme ones.
- Test that every icon of the maps has its SVG.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Docks: SidebarLayout positions docked widgets relative to the dock grids,
  which cover the whole tab content, but they live in the main grid, which
  is shifted by the tab content padding. Cancel that padding (now exposed
  as --wc-tab-padding-x/y) so the panels are flush with the workspace edge
  when open and completely hidden when closed, keep the handles on that
  edge and drop the shadow of closed overlay panels.
- `loading` is a permanent marker of the containers whose disable layer
  shows a spinner, not a transient state. Stop fading it, which left the
  resource documentation and changelog, the upgrade changelog and the
  component lists at 45% opacity.
- Buttons that get the icon classes themselves (`fa fa-edit`, as the
  Markdown viewer widget does) draw the icon at a fixed size; it was 0px
  wide.
- Layout settings: use the width of the other dialogs with the screen
  sizes field, and keep the labels of that field at their full width.
- Map the crosshairs icon.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Rafael Fernández and others added 3 commits November 3, 2026 13:34
…stry-theme

Conflicts:
- WirecloudHeader.js: the new "App connections" user menu entry moves into
  buildUserMenu(), keeping its position and conditions, with its icon in
  WirecloudHeader.defaults.userMenuIconClasses.appconnections.
- wirecloud.platform.js.po (es): keep the entries added by both sides.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Industry is a root theme, so the pages added by wirecloud.oauth2provider
failed to render (TemplateNotFound) and its styles, icons and strings had no
fallback.

- Add wirecloud/oauth2provider/{base,consent,connections}.html keeping the
  page contract (blocks, form fields, data-se-* markers for pages.js) and the
  strict CSP: no inline scripts or styles, so the stored color scheme is
  applied by the standalone js/industry/ColorSchemeBoot.js.
- Style them in css/oauth2provider.scss (index bundle) and the App
  connections dialog in css/modals/app_connections.scss.
- Move the plain page header styles to pages.scss so the index bundle has them.
- Map fa-plug to the Lucide plug icon.
- Translate the new strings and the MCP scope descriptions (es).
- Error pages are now rendered with autoescape: stop escaping request_path
  again inside trans(), which showed "&lt;" to the user.
- Document the root theme requirements and the header icon keys.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Eight strings of AppConnectionsWindowMenu had no Spanish translation (the
catalog had an older wording of the empty state message).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@oxixes
oxixes requested a balanced review from Copilot November 3, 2026 16:11

Copilot AI left a comment

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.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota. Try requesting a review at a lower effort level.

Copilot AI left a comment

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.

🟡 Changes recommended

Active moderate accessibility and minor user-facing text issues remain unresolved in the changed files.

2 open issues

Review effort: Lite

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

@oxixes oxixes left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Also, one small bug I noticed is that, if a widget is docked on the bottom bar, it works but the widget is on top of the status bar, instead of under it, as the screen capture shows. Apart from this and the small comments I made, LGTM.

Image

Comment thread docs/oauth2.md Resolved
*
* @private
*/
const resolve_ui_class = function resolve_ui_class(name, defaultValue) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This function is used in several files, it may be better to put it in a utils file instead of copy-pasting it in several places.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Removed every copy: the registry itself is the shared helper, so callers use Wirecloud.ui.registry.get() directly (it already falls back to Wirecloud.ui.<name>); the JS tests that load these modules now load Registry.js too (ba7de76).


const screen_size_icon = function screen_size_icon(screenSize, index, count) {
const name = String(screenSize.name || '').toLowerCase();
if (/phone|mobile|small|móvil|movil/.test(name)) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This only accounts for the currently available languages and the user can rename the screen size. It's better to test the actual size to what is standard in order to show the correct icon

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

The icon now comes from the width range, compared to the default breakpoints: up to 767 px phone, up to 1199 px tablet, otherwise monitor. Names are ignored (29c58a5).

Rafael Fernández and others added 5 commits November 5, 2026 12:42
Requested in the PR review: docs/oauth2.md does not need theme specific notes; docs/themes.md already explains what root themes must provide.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Six modules carried a copy of resolve_ui_class and three more an inline variant, all guarding against a missing registry. Registry.js is part of every platform bundle and is loaded before these modules, so call Wirecloud.ui.registry.get() directly (it already falls back to Wirecloud.ui.<name>). The JS tests that load these modules now load Registry.js too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Screen size names are free text (users rename them, and they may be translated), so choosing the icon from the name was unreliable. Use the widest width each screen size applies to, compared to the platform default breakpoints (767 and 1199 px).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Bottom docked widgets are fixed right above the status bar and slide down when closed. The status bar was not positioned, so the closed widget was painted on top of it. Give the status bar its own layer above the docked widgets (z-index 105) and below popovers, menus and dialogs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
51abf82 fixed "appropiated" in the missing widget template but not in its msgid, so the suggestions were shown untranslated. The catalog test now covers every Industry template (parsed with Jinja) instead of only the OAuth pages, so edited strings without translation are caught.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@rafitanba

Copy link
Copy Markdown
Author

Thanks for the review! Fixed the bottom dock bug: closed bottom docked widgets now slide under the status bar (b1455af). I also synced the es catalog with the "appropriate" typo fix, which had left those suggestions untranslated, and the catalog test now covers every Industry template (c04daf1).

@rafitanba
rafitanba requested a review from oxixes November 5, 2026 11:49
@oxixes
oxixes merged commit 9f0e561 into Ficodes:main Nov 5, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants