Marketing Hub: RBAC, i18n (AR/EN), tasks overhaul, team/user merge, tutorial

Features:
- Full RBAC with 3 roles (superadmin/manager/contributor)
- Ownership tracking on posts, tasks, campaigns, projects
- Task system: assign to anyone, filter combobox, visibility scoping
- Team members merged into users table (single source of truth)
- Post thumbnails on kanban cards from attachments
- Publication link validation before publishing
- Interactive onboarding tutorial with Settings restart
- Full Arabic/English i18n with RTL layout support
- Language toggle in sidebar, IBM Plex Sans Arabic font
- Brand-based visibility filtering for non-superadmins
- Manager can only create contributors
- Profile completion flow for new users
- Cookie-based sessions (express-session + SQLite)
This commit is contained in:
fahed
2026-02-08 20:46:58 +03:00
commit 35d84b6bff
2240 changed files with 846749 additions and 0 deletions

56
server/node_modules/es-define-property/test/index.js generated vendored Normal file
View File

@@ -0,0 +1,56 @@
'use strict';
var $defineProperty = require('../');
var test = require('tape');
var gOPD = require('gopd');
test('defineProperty: supported', { skip: !$defineProperty }, function (t) {
t.plan(4);
t.equal(typeof $defineProperty, 'function', 'defineProperty is supported');
if ($defineProperty && gOPD) { // this `if` check is just to shut TS up
/** @type {{ a: number, b?: number, c?: number }} */
var o = { a: 1 };
$defineProperty(o, 'b', { enumerable: true, value: 2 });
t.deepEqual(
gOPD(o, 'b'),
{
configurable: false,
enumerable: true,
value: 2,
writable: false
},
'property descriptor is as expected'
);
$defineProperty(o, 'c', { enumerable: false, value: 3, writable: true });
t.deepEqual(
gOPD(o, 'c'),
{
configurable: false,
enumerable: false,
value: 3,
writable: true
},
'property descriptor is as expected'
);
}
t.equal($defineProperty, Object.defineProperty, 'defineProperty is Object.defineProperty');
t.end();
});
test('defineProperty: not supported', { skip: !!$defineProperty }, function (t) {
t.notOk($defineProperty, 'defineProperty is not supported');
t.match(
typeof $defineProperty,
/^(?:undefined|boolean)$/,
'`typeof defineProperty` is `undefined` or `boolean`'
);
t.end();
});