Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
180d87d
Replace Webpack with Vite 8 build system
riccio82 Apr 24, 2026
818c824
Adapt source code for Vite compatibility
riccio82 Apr 24, 2026
f7d3160
Clean up post-migration config files
riccio82 Apr 24, 2026
d0c5972
Update submodule
riccio82 Apr 24, 2026
1e69d11
Fix PHPStan errors in Vite integration
riccio82 Apr 24, 2026
f1db594
Use AppConfig::$HTTPHOST instead of hardcoded dev URL in ViteAssets
riccio82 Apr 24, 2026
e4f5e8d
Apply suggestion from @Copilot
riccio82 Apr 24, 2026
09ce5e0
Added missing subfiltering_handlers in GetContributionWorker (#4519)
mauretto78 Apr 22, 2026
f3363a9
🐛 fix(project-creation): eliminate replication-lag race and make pre-…
Ostico Apr 22, 2026
8e33cba
fix: subfiltering handlers persist (#4521)
mauretto78 Apr 22, 2026
eec4aef
fix: correct handling of self closing PC tags (#4525)
mauretto78 Apr 23, 2026
659f115
🔧 chore(deps): update @translated/lara to 1.9.0 (#4516)
riccio82 Apr 27, 2026
88a6445
feat: add ed error_code to AI Worker messages (#4533)
mauretto78 Apr 27, 2026
921571a
🔧 chore(phpstan): regenerate baseline for new @throws rules
Ostico Apr 20, 2026
fa75811
📝 docs: add PR readiness checklist template and GitHub Actions validator
Ostico Apr 20, 2026
798a5b3
📝 docs(pr-template): simplify AI usage disclosure instructions
Ostico Apr 20, 2026
d601fcb
🔧 chore(jest): exclude .github/ from Jest test discovery
Ostico Apr 20, 2026
dfad79f
🔧 chore(phpstan): exclude APIDoc build artifacts from analysis
Ostico Apr 20, 2026
9367b15
🔧 chore(phpstan): mark APIDoc.php exclude path as optional
Ostico Apr 20, 2026
b8b3cbb
Update .github/workflows/pr-readiness-check.yml
Ostico Apr 20, 2026
09affd9
👷 ci: add conventional-commit message enforcement workflow
Ostico Apr 20, 2026
8a1c3e8
🐛 fix(ci): relax commit message check for Copilot and GitHub web edits
Ostico Apr 20, 2026
dec166e
🔧 chore(phpstan): add @throws \Throwable to FastAnalysis transaction …
Ostico Apr 21, 2026
12c9045
👷 ci(test-guard): add test adequacy gate workflow
Ostico Apr 21, 2026
8012fb8
👷 ci(test-guard): integrate test-guard into CI/CD pipeline
Ostico Apr 21, 2026
ef9e750
👷 ci(test-guard): bump ostico/test-guard to v1.0.3
Ostico Apr 21, 2026
331aef5
👷 ci(test-guard): bump ostico/test-guard to v1.0.5
Ostico Apr 21, 2026
4aa0604
👷 ci: add models:read permission to _ci-cd.yml
Ostico Apr 21, 2026
3aa2362
🐛 fix(ci): add models:read permission for test-guard AI analysis
Ostico Apr 21, 2026
9837941
👷 ci(test-guard): switch to floating tag ostico/test-guard@v1
Ostico Apr 21, 2026
068e928
👷 ci(permissions): replace statuses:write with checks:write in workflows
Ostico Apr 22, 2026
dbe6bb5
👷 ci(coverage): add JS coverage report to test-guard pipeline
Ostico Apr 23, 2026
1ba25de
Update submodule
riccio82 Apr 28, 2026
cb1793c
Remove unused test-entry.js placeholder
riccio82 Apr 28, 2026
728bd0a
Merge remote-tracking branch 'origin/develop' into spike/vite-migration
riccio82 Apr 28, 2026
b656357
Merge branch 'develop' into spike/vite-migration
riccio82 Apr 29, 2026
a543170
♻️ refactor(imports): convert lazy require() to async import() and up…
riccio82 Apr 29, 2026
d58e9c3
🐛 fix(hmr): prevent portal crash on hot reload and remove hardcoded d…
riccio82 Apr 29, 2026
9c863b6
fix: remove redundant dynamic imports and add error handling to updat…
Copilot Apr 29, 2026
530b7f6
🛡️ fix(imports): add defensive guards to async import getters
riccio82 Apr 29, 2026
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
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -84,4 +84,5 @@ certs
/.phpunit.cache
/CallGraph
/PHP-SQL-Parser
/storage
/storage
/public/build/
5 changes: 2 additions & 3 deletions .htaccess
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,8 @@ SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1

#RewriteRule ^offline\.html$ /lib/View/offline.html [L]
#RewriteCond %{REQUEST_URI} !/offline.html [NC]
#RewriteCond %{REQUEST_URI} !/public/build/runtime\.(.+)\.js [NC]
#RewriteCond %{REQUEST_URI} !/public/build/commonCss\.(.+)\.(css|js) [NC]
#RewriteCond %{REQUEST_URI} !/public/build/images/(.+)\.svg [NC]
#RewriteCond %{REQUEST_URI} !/public/build/(.+)\.js [NC]
#RewriteCond %{REQUEST_URI} !/public/build/assets/(.+)\.css [NC]
#RewriteCond %{REQUEST_URI} !/img/meta/favicon(.+)\.svg [NC]
#RewriteRule $ /offline.html [R=307,L]
RewriteCond %{REQUEST_URI} /offline.html
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ The following yarn commands are available for development and building:

### `yarn watch`

Watches for changes in the source files and automatically rebuilds the project in development mode. Useful for local development as it provides live updates.
Starts the Vite development server with Hot Module Replacement (HMR). Useful for local development as it provides instant updates without full page reloads.
Comment thread
riccio82 marked this conversation as resolved.

### `yarn build:dev`

Expand Down
2 changes: 0 additions & 2 deletions babel.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ module.exports = (api) => {
switch (api.env()) {
case 'test':
return getBabelPresets('node')
case 'development':
return getBabelPresets('browser')

default:
throw new Error('babel.config.js :: environment not supported, yet.')
Expand Down
52 changes: 26 additions & 26 deletions check-circular-deps.js
Original file line number Diff line number Diff line change
@@ -1,30 +1,30 @@
#!/usr/bin/env node
const {execSync} = require('child_process')
const madge = require('madge')

let cycles
try {
const output = execSync(
'npx madge --circular --extensions js --json public/js/',
{encoding: 'utf8', maxBuffer: 10 * 1024 * 1024},
)
cycles = JSON.parse(output)
} catch (e) {
if (e.stdout) {
cycles = JSON.parse(e.stdout)
} else {
console.error('Failed to run madge:', e.message)
process.exit(1)
}
}
madge('public/js/', {
fileExtensions: ['js'],
detectiveOptions: {
es6: {
skipAsyncImports: true,
},
},
})
.then((res) => {
const cycles = res.circular()

if (cycles.length > 0) {
console.error(
`\x1b[31m✖ Found ${cycles.length} circular dependencies:\x1b[0m\n`,
)
cycles.forEach((cycle, i) => {
console.error(` ${i + 1}) ${cycle.join(' → ')}`)
if (cycles.length > 0) {
console.error(
`\x1b[31m✖ Found ${cycles.length} circular dependencies:\x1b[0m\n`,
)
cycles.forEach((cycle, i) => {
console.error(` ${i + 1}) ${cycle.join(' → ')}`)
})
process.exit(1)
} else {
console.log('\x1b[32m✔ No circular dependencies\x1b[0m')
}
})
.catch((err) => {
console.error('Failed to run madge:', err.message)
process.exit(1)
})
process.exit(1)
} else {
console.log('\x1b[32m✔ No circular dependencies\x1b[0m')
}
2 changes: 1 addition & 1 deletion docker
33 changes: 26 additions & 7 deletions lib/Controller/Abstracts/BaseKleinViewController.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
use Utils\Templating\PHPTalMap;
use Utils\Templating\PHPTALWithAppend;
use Utils\Tools\Utils;
use Utils\Vite\ViteAssets;

/**
* Created by PhpStorm.
Expand Down Expand Up @@ -67,9 +68,21 @@ public function __construct(Request $request, Response $response, ?ServiceProvid
*/
public function setView(string $template_name, array $params = [], int $code = 200): void
{
$this->view = new PHPTALWithAppend(AppConfig::$TEMPLATE_ROOT . "/$template_name");
$viteDevMode = ViteAssets::isDevMode();

if ( $viteDevMode ) {
$templatePath = AppConfig::$TEMPLATE_ROOT . "/templates/_$template_name";
} else {
$templatePath = AppConfig::$TEMPLATE_ROOT . "/$template_name";
}

$this->view = new PHPTALWithAppend($templatePath);
$this->httpCode = $code;

if ( $viteDevMode ) {
$this->view->setTemplateRepository( AppConfig::$TEMPLATE_ROOT );
}

$this->view->{'basepath'} = AppConfig::$BASEURL;
$this->view->{'hostpath'} = AppConfig::$HTTPHOST;
$this->view->{'build_number'} = AppConfig::$BUILD_NUMBER;
Expand All @@ -92,7 +105,18 @@ public function setView(string $template_name, array $params = [], int $code = 2

$this->view->{'footer_js'} = [];
$this->view->{'config_js'} = [];
$this->view->{'css_resources'} = [];

/**
* This is a unique ID generated at runtime.
* It is injected into the nonce attribute of `< script >` tags to allow browsers to safely execute the contained CSS and JavaScript.
*/
$nonce = Utils::uuid4();
$this->view->{'x_nonce_unique_id'} = $nonce;

$this->view->{'vite_html'} = '';
if ( $viteDevMode ) {
$this->view->{'vite_html'} = ViteAssets::getHtml( $template_name, $nonce ?? '' );
}

// init oauth clients
$this->view->{'googleAuthURL'} = (AppConfig::$GOOGLE_OAUTH_CLIENT_ID) ? OauthClient::getInstance(GoogleProvider::PROVIDER_NAME)->getAuthorizationUrl($_SESSION) : "";
Expand All @@ -107,11 +131,6 @@ public function setView(string $template_name, array $params = [], int $code = 2
AppConfig::$HTTPHOST . "/gdrive/oauth/response"
)->getAuthorizationUrl($_SESSION, 'drive') : "";

/**
* This is a unique ID generated at runtime.
* It is injected into the nonce attribute of `< script >` tags to allow browsers to safely execute the contained CSS and JavaScript.
*/
$this->view->{'x_nonce_unique_id'} = Utils::uuid4();
$this->view->{'x_self_ajax_location_hosts'} = AppConfig::$ENABLE_MULTI_DOMAIN_API ? " *.ajax." . parse_url(AppConfig::$HTTPHOST)['host'] : null;

$this->addParamsToView($params);
Expand Down
89 changes: 89 additions & 0 deletions lib/Utils/Vite/ViteAssets.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<?php

namespace Utils\Vite;

use Utils\Registry\AppConfig;

class ViteAssets {

private const GROUPS_PATH = 'public/vite-entries/groups.json';

private static ?bool $devMode = null;

/** @var array<string, list<string>>|null */
private static ?array $groups = null;

public static function isDevMode(): bool {
if ( self::$devMode !== null ) {
return self::$devMode;
}
self::$devMode = !empty( $_ENV[ 'VITE_DEV' ] ) || !empty( $_SERVER[ 'VITE_DEV' ] );

return self::$devMode;
}

/**
* @return array<string, list<string>>
*/
private static function loadGroups(): array {
if ( self::$groups !== null ) {
return self::$groups;
}

$path = AppConfig::$ROOT . '/' . self::GROUPS_PATH;
if ( !file_exists( $path ) ) {
self::$groups = [];

return self::$groups;
}

$raw = file_get_contents( $path );
if ( $raw === false ) {
self::$groups = [];

return self::$groups;
}

self::$groups = json_decode( $raw, true ) ?: [];

return self::$groups;
}

public static function getHtml( string $templateName, string $nonce = '' ): string {
if ( !self::isDevMode() ) {
return '';
}

return self::buildDevHtml( $templateName, $nonce );
}

private static function buildDevHtml( string $templateName, string $nonce ): string {
$groups = self::loadGroups();
$entries = $groups[ $templateName ] ?? [];

if ( empty( $entries ) ) {
return '';
}

$host = AppConfig::$HTTPHOST;
$n = $nonce ? " nonce=\"{$nonce}\"" : '';
$lines = [];

$lines[] = '<script type="module"' . $n . '>'
. "import RefreshRuntime from '/@react-refresh'\n"
. "RefreshRuntime.injectIntoGlobalHook(window)\n"
. 'window.$RefreshReg$ = () => {}' . "\n"
. 'window.$RefreshSig$ = () => (type) => type' . "\n"
. 'window.__vite_plugin_react_preamble_installed__ = true'
. '</script>';

$lines[] = '<script type="module" src="' . $host . '/@vite/client"' . $n . '></script>';

foreach ( $entries as $entry ) {
$lines[] = '<script type="module" src="' . $host . '/public/vite-entries/' . $entry . '.js"' . $n . '></script>';
}

return implode( "\n", $lines );
}

}
4 changes: 1 addition & 3 deletions lib/View/templates/_manage.html
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,7 @@
</header>

<div id="manage-container" class="new-container">
<div class="ui active inverted dimmer">
<div class="ui massive text loader">Loading Projects</div>
</div>

Comment thread
riccio82 marked this conversation as resolved.
</div>
Comment thread
riccio82 marked this conversation as resolved.


Expand Down
4 changes: 1 addition & 3 deletions lib/View/templates/common.html
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,6 @@
<tal:block tal:repeat="js_source footer_js">
<script tal:attributes="src js_source; nonce x_nonce_unique_id"></script>
</tal:block>
<tal:block tal:repeat="css_url css_resources">
<link rel="stylesheet" tal:attributes="href css_url; nonce x_nonce_unique_id"/>
</tal:block>
${structure vite_html}
<div id="modal" style="z-index: 999999999"></div>
</div>
24 changes: 7 additions & 17 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
"lint": "eslint --ignore-path .gitignore .",
"test": "jest --watchAll",
"coverage": "jest --silent --coverage",
"watch": "sed -i \"s/version .*/version = \\\"v${npm_package_version}\\\"/g\" ./nodejs/config.ini && webpack --mode development --watch",
"build:dev": "sed -i \"s/version .*/version = \\\"v${npm_package_version}\\\"/g\" ./nodejs/config.ini && webpack --mode development",
"build:production": "webpack --mode production",
"watch": "vite",
"build:dev": "vite build --mode development",
"build:production": "vite build",
"check:circular-deps": "node check-circular-deps.js",
"prepare": "husky"
},
Expand All @@ -26,6 +26,7 @@
"crypto-js": "^4.1.1",
"diff-match-patch": "^1.0.5",
"draft-js": "^0.11.4",
"events": "^3.3.0",
"file-saver": "^2.0.5",
"flux": "^4.0.4",
"format-message": "^6.2.4",
Expand Down Expand Up @@ -60,18 +61,16 @@
"devDependencies": {
"@babel/core": "^7.28.5",
"@babel/eslint-parser": "^7.28.5",
"@babel/plugin-transform-runtime": "^7.28.5",
"@babel/preset-env": "^7.28.5",
"@babel/preset-react": "^7.28.5",
"@sentry/webpack-plugin": "4.9.1",
"@sentry/vite-plugin": "^5.2.0",
"@testing-library/dom": "^10.1.0",
"@testing-library/jest-dom": "^6.2.0",
"@testing-library/react": "^16.0.0",
"@testing-library/user-event": "^14.5.2",
"babel-loader": "10.1.1",
"@vitejs/plugin-react": "^6.0.1",
"baseline-browser-mapping": "^2.9.15",
"broadcast-channel": "^7.1.0",
"css-loader": "7.1.4",
"eslint": "^8.0.0",
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-jest": "^29.0.0",
Expand All @@ -81,28 +80,19 @@
"eslint-plugin-testing-library": "^7.0.0",
"fs-extra": "^11.1.1",
"glob": "^11.1.0",
"html-webpack-plugin": "5.6.6",
"husky": ">=6",
"ini": "^5.0.0",
"jest": "^30.0.0",
"jest-environment-jsdom": "^30.0.0",
"jest-transform-css": "^6.0.1",
"lint-staged": ">=10",
"madge": "^8.0.0",
"mini-css-extract-plugin": "^2.7.6",
"msw": "^2.7.3",
"prettier": "^3.0.0",
"sass": "^1.66.0",
"sass-loader": "16.0.7",
"style-loader": "4.0.0",
"terser-webpack-plugin": "^5.3.11",
"thread-loader": "^4.0.4",
"undici": "^5.28.2",
"vite": "^8.0.9",
"web-streams-polyfill": "^4.1.0",
"webpack": "5.104.1",
"webpack-bundle-analyzer": "^4.10.2",
"webpack-cli": "6.0.1",
"webpack-concat-files-plugin": "^0.5.2",
"whatwg-fetch": "^3.6.20"
},
"resolutions": {
Expand Down
2 changes: 1 addition & 1 deletion phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -6673,7 +6673,7 @@ parameters:
path: lib/Controller/Abstracts/BaseKleinViewController.php

-
message: '#^Access to an undefined property Utils\\Templating\\PHPTALWithAppend\:\:\$css_resources\.$#'
message: '#^Access to an undefined property Utils\\Templating\\PHPTALWithAppend\:\:\$vite_html\.$#'
identifier: property.notFound
count: 1
path: lib/Controller/Abstracts/BaseKleinViewController.php
Expand Down
2 changes: 1 addition & 1 deletion plugins/translated
8 changes: 4 additions & 4 deletions public/css/sass/components/common/Button.scss
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ a.button-component-container {
box-shadow: inset 0 0 0 1px var(--btnBorderColor);
color: var(--btnAltTextColor);

&:not(:disabled):global(.button--active) {
&:not(:disabled).button--active {
box-shadow: inset 0 0 0 1px var(--btnBorderColorActive);
background-color: var(--btnBgColorSemitransAlt);
}
Expand All @@ -80,8 +80,8 @@ a.button-component-container {
&.ghost {
color: var(--btnAltTextColor);

&:not(:disabled):global(.button--active),
&:not(:disabled):global(.button--active):hover {
&:not(:disabled).button--active,
&:not(:disabled).button--active:hover {
background-color: var(--btnBgColorSemitransAlt);
color: var(--btnAltTextColor);
}
Expand All @@ -99,7 +99,7 @@ a.button-component-container {
&.link {
color: var(--btnAltTextColor);

&:not(:disabled):global(.button--active) {
&:not(:disabled).button--active {
color: colors.$grey8;
}

Expand Down
3 changes: 0 additions & 3 deletions public/css/sass/mbc-style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -620,9 +620,6 @@ Close icon ballon - Right panel
Clearfix helpers
******
*/
.mbc-clearfix {
*zoom: 1;
}
.mbc-clearfix:before,
.mbc-clearfix:after {
display: table;
Expand Down
Loading
Loading