Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • applications/etuc/hubl
  • applications/hubl
  • decentral1se/hubl
  • rngadam/hubl
  • jvtrudel/hubl
  • 3wc/hubl
6 results
Show changes
Showing
with 596 additions and 677 deletions
.content-box.full-width.with-form
sib-router(default-route='admin-project-list', hidden)
sib-route(name='admin-project-list')
sib-route(name='admin-project-create')
sib-route(name='project-left')
div.content-box__header
h1.without-margin Administration
#project-left(hidden)
include ../project/page-project-left.pug
#admin-project-list(hidden)
include ../../templates/hd-user-avatar.pug
div.content-box__info
div.admin-header
div.admin-header__title Projects
sib-link(
class='button text-bold text-uppercase reversed button-yellow bordered with-icon icon-plus'
next='admin-project-create'
) Create a new project
.table
div.table-header.grey-color
div Name
div Admins
div Captain
div Leave
sib-widget(name="admin-project-leave-button")
template
sib-delete(
class='button text-bold text-uppercase reversed button-dark bordered with-icon icon-close'
data-src="${src}"
data-label='Leave'
)
sib-widget(name='project-captain')
template
sib-display.user-thumb(
data-src='${await value}'
fields='account.picture, sup(name), sub(username)'
class-account.picture='user-thumb__picture'
class-name='user-thumb__name'
class-username='user-thumb__username'
widget-account.picture='hd-user-avatar'
)
sib-widget(name='project-admins')
template
sib-display(
data-src='${value}'
fields='user'
search-fields='is_admin'
search-value-is_admin='true'
search-widget-is_admin='sib-form-hidden'
widget-user='project-captain'
)
sib-widget(name="admin-project-buttons")
template
sib-display(
data-src='${src}'
nested-field='members'
fields='relation'
action-relation='relation'
widget-relation='admin-project-leave-button'
search-fields='user'
search-widget-user='sib-form-hidden'
search-value-user="-"
hd-inherit-user-id="search-value-user"
)
sib-display(
class='table-body'
data-src=`${endpoints.projects || endpoints.get.projects}`
fields='name, members, captain, buttons'
class-name='w25 cell border cell-with-name hashtag'
class-members='w25 cell border'
class-captain='w25 cell border cell-with-id-card'
class-buttons='w25 cell border cell-with-buttons'
widget-buttons="admin-project-buttons"
action-buttons="buttons"
widget-captain='project-captain'
widget-members='project-admins'
)
#admin-project-create(hidden)
include page-admin-projects-create.pug
\ No newline at end of file
div.content-box__info
sib-link(class='backlink right', next='admin-users-list') Back
h1.centered Add a new user to the platform
sib-form(
data-src=`${endpoints.users || endpoints.post.users}`
range-groups=`${endpoints.groups || endpoints.get.groups}`
fields='line-1(first_name, last_name), line-2(username, email), line-3(password), line-4-border-top(groups)'
class-first_name='form-label is-light is-half-width'
class-last_name='form-label is-light is-half-width'
class-username='form-label is-light is-half-width'
class-email='form-label is-light is-half-width'
class-groups='form-label is-light is-half-width select-groups'
label-first_name='First Name *'
label-last_name='Last Name *'
label-username='Username *'
label-email='Email *'
label-groups='Groups'
multiple-groups='sib-multiple-select'
widget-groups='sib-form-auto-completion'
value-password=''
widget-password='sib-form-hidden'
next='admin-users-list'
submit-button='Create'
)
p Administrators of your platform can create new Groups on the Django Administration.
div.content-box__info
sib-link(class='backlink right', next='admin-users-list') Back
h1.centered
span Edit user
sib-display(
bind-resources=''
fields='name'
)
sib-form(
bind-resources=''
range-groups=`${endpoints.groups || endpoints.get.groups}`
fields='line-1(first_name, last_name), line-2(username, email), line-4-border-top(groups)'
class-first_name='form-label is-light is-half-width'
class-last_name='form-label is-light is-half-width'
class-username='form-label is-light is-half-width'
class-email='form-label is-light is-half-width'
class-groups='form-label is-light is-half-width select-groups'
label-first_name='First Name *'
label-last_name='Last Name *'
label-username='Username *'
label-email='Email *'
label-groups='Groups'
multiple-groups='sib-multiple-select'
widget-groups='sib-form-auto-completion'
next='admin-user-list'
submit-button='Save user'
)
.content-box.full-width.with-form
sib-router(default-route='admin-users-list', hidden)
sib-route(name='admin-users-list')
sib-route(name='admin-users-create')
sib-route(name='admin-users-edit')
div.content-box__header
h1.without-margin Administration
sib-widget(name='sib-action-hd-custom')
template
sib-ac-checker(data-src="${src}", permission='acl:Write')
sib-link(
class='button rounded reversed button-blue bordered icon-pencil'
data-src="${src}"
next="${value}"
)
sib-widget(name='hd-user-admin-groups-display')
template
sib-display(
data-src="${value}"
fields="name"
)
#admin-users-list(hidden)
div.content-box__info
div.admin-header
div.admin-header__title Users
sib-ac-checker(data-src=`${endpoints.users || endpoints.post.users}`, permission='acl:Append')
sib-link(
class='button text-bold text-uppercase reversed button-yellow bordered with-icon icon-plus'
next='admin-users-create'
) Create a new user
.table
div.table-header.grey-color
div Name
div Groups
div
sib-display(
class='table-body'
data-src=`${endpoints.users || endpoints.get.users}`
fields='cell-1(user-thumb(account.picture, sup(name), sub(username))), groups, actions'
class-account.picture='user-thumb__picture'
class-name='user-thumb__name'
class-username='user-thumb__username'
class-profile.city='user-thumb__city'
widget-account.picture='hd-user-avatar'
class-groups='w33 cell border cell-with-groups'
multiple-groups=''
widget-groups='hd-user-admin-groups-display'
label-actions='Edit'
action-actions='admin-users-edit'
class-actions='w33 cell border cell-with-buttons'
widget-actions='sib-action-hd-custom'
order-by='username'
)
#admin-users-create(hidden)
include page-admin-users-create.pug
#admin-users-edit(hidden)
include page-admin-users-edit.pug
.chat-view
sib-chat(
data-authentication='login',
data-auto-login='true',
data-bosh-service-url=`${xmpp}`,
data-debug='false',
data-locales-url='en',
bind-resources
)
\ No newline at end of file
div.content-box__info
include ../../templates/hd-user-avatar.pug
sib-widget(name='hd-user-groups')
template ${await value.name}
sib-widget(name='team-template-edit')
template
sib-display.user-thumb(
class='w50 cell border cell-with-id-card user-thumb'
data-src='${await value.user}'
fields='account.picture, sup(name, groups), sub(profile.city)'
class-account.picture='user-thumb__picture'
class-name='user-thumb__name'
class-groups='user-thumb__groups'
class-profile.city='user-thumb__city'
widget-account.picture='hd-user-avatar'
multiple-groups=''
widget-groups='hd-user-groups'
)
sib-ac-checker(
class='w50 cell border'
permission="acl:Delete"
data-src="${value['@id']}"
)
sib-delete(
class='button text-bold text-uppercase reversed button-dark bordered with-icon icon-close'
data-src="${value['@id']}"
data-label='Leave the circle'
)
//- Only to show the table grid
sib-ac-checker(
class='w50 cell border'
no-permission="acl:Delete"
data-src="${value['@id']}"
)
sib-link(class="backlink right", bind-resources, next='circle-profile') Back
sib-ac-checker(permission='acl:Write', bind-resources)
h1 Edit your circle
sib-form.form-edit(
bind-resources
fields='block-circle__info(name, owner), description'
range-owner=`${endpoints.users || endpoints.get.users}`
label-owner='owner'
label-description='circle subtitle'
class-name='form-label is-light is-half-width'
class-owner='form-label is-light is-half-width member-select color'
class-description='form-label is-light is-full-width'
widget-owner='sib-form-auto-completion'
partial=''
submit-button='Save'
next='circle-information'
)
h2 Members list
sib-ac-checker(permission='acl:Append', bind-resources, nested-field='members')
sib-form.block.select-add-member(
bind-resources
nested-field='members'
fields='user'
range-user=`${endpoints.users || endpoints.get.users}`
class-user='team form-label is-dark'
label-user=''
widget-user='sib-form-auto-completion'
submit-button='Add a member'
)
.table
div.table-header.grey-color
div Name
div Access
//-class='table-body'
sib-display(
class='table-body'
bind-resources
fields='members'
multiple-members=''
widget-members='team-template-edit'
)
#circle-left
div.content-box__info(style="padding: 15px")
p You have successfully left this circle
p This is a private group, to join again, go to the <sib-link next="admin-circle-list">administration</sib-link> panel and ask for an invite
sib-router(default-route='circle-profile', hidden)
sib-route(name='circle-profile')
sib-route(name='circle-edit')
#circle-profile(hidden)
include ../../templates/hd-circle-team.pug
.content-box__info
.space-between
sib-display(
bind-resources
fields='creationDateSet(title, creationDate)'
class-title='word-spacing-right'
value-title='Creation date: '
widget-creationDate='sib-display-date'
)
sib-ac-checker(permission='acl:Append', bind-resources, nested-field='members')
sib-link(class='button text-bold text-uppercase reversed button-blue bordered with-icon icon-pencil' next='circle-edit' bind-resources) Edit and add Members
h2 Members:
sib-display.block(
bind-resources
fields='members'
multiple-members=''
widget-members='circle-team-template'
)
div.box-button
sib-ac-checker(permission='acl:Delete', bind-resources)
sib-delete(
class='button text-bold text-uppercase button-blue bordered with-icon icon-trash'
bind-resources
data-label='Delete Circle'
)
sib-widget(name='circle-leave-button')
template
sib-delete(
class='button btn-margin-left text-bold text-uppercase reversed button-dark bordered with-icon icon-close'
data-src="${src}"
data-label='Leave Circle'
)
sib-widget(name='circle-join-button')
template
button.button.btn-margin-left.text-bold.text-uppercase.reversed.button-dark.bordered.with-icon.icon-arrow-right-circle.flex
sib-form(
data-src=''
nested-field='members'
fields='user.@id'
label-user.@id=''
value-user.@id=''
widget-user.@id='sib-form-hidden'
hd-inherit-bind-user2input="input[name='user.@id']"
submit-button='Join Circle'
)
sib-display(
bind-resources
nested-field='members'
fields='relation'
action-relation='relation'
widget-relation='circle-leave-button'
search-fields='user'
search-widget-user='sib-form-hidden'
search-value-user=""
empty-widget='circle-join-button'
hd-inherit-bind-resources='circle-join-button'
hd-inherit-user-id="search-value-user"
)
#circle-edit(hidden)
include page-circle-edit.pug
.content-box.with-padding.with-form
h1 Post a new job offer
sib-form(
data-src=`${endpoints.joboffers || endpoints.post.joboffers}`
range-skills=`${endpoints.skills || endpoints.get.skills}`
fields='title, description, skills, closingDate'
class-title='field form-label is-light is-expanded'
label-title='Title*'
class-description='field form-label is-light is-expanded'
label-description='Description*'
widget-description='sib-form-textarea'
class-skills='form-label is-dark select-skills'
label-skills='The required skills for this mission:*'
multiple-skills='sib-multiple-select'
widget-skills='sib-form-auto-completion'
class-closingDate='form-label is-dark'
label-closingDate='Publication end date:*'
widget-closingDate='sib-form-date'
next='job-offers'
)
.content-box.with-padding.with-form
h1 Edit your job offer
sib-form(
bind-resources
range-skills=`${endpoints.skills || endpoints.get.skills}`
fields='title, description, skills, closingDate'
class-title='field form-label is-light is-expanded'
label-title='Title*'
class-description='field form-label is-light is-expanded'
label-description='Description*'
widget-description='sib-form-textarea'
class-skills='form-label is-dark select-skills'
label-skills='The required skills for this mission:*'
multiple-skills='sib-multiple-select'
widget-skills='sib-form-auto-completion'
class-closingDate='form-label is-dark'
label-closingDate='Publication end date:*'
widget-closingDate='sib-form-date'
next='job-offers'
)
.content-box.with-padding.full-width.chat-view
sib-chat(
data-authentication='login',
data-auto-login='true',
data-bosh-service-url=`${xmpp}`,
data-debug='false',
data-locales-url='en',
bind-resources
)
div.content-box__info
include ../../templates/hd-user-avatar.pug
sib-widget(name='hd-fieldset-title')
template
label ${label}
sib-link(class='backlink right', bind-resources, next='project-profile') Back
h1 Edit your project
sib-form.form-edit(
bind-resources
fields='fieldset-info, block-project__info(customer, name, description), fieldset-fee, block-project__fee(businessProvider, businessProviderFee)'
class-customer='member-select form-label is-light is-half-width'
widget-customer='sib-form-auto-completion'
class-name='form-label is-light is-half-width'
class-description='form-label is-light is-full-width'
label-fieldset-info=''
label-customer='Customer'
range-customer=`${endpoints.customers || endpoints.get.customers}`
label-name='Project\'s name*'
label-description='Project description'
widget-fieldset-info='hd-fieldset-title'
widget-description='sib-form-textarea'
class-fieldset-fee='fieldset'
class-businessprovider='form-label is-light is-half-width'
class-businessproviderfee='form-label is-light is-half-width'
label-fieldset-fee='Fee'
label-businessprovider='Business provider'
label-businessproviderfee='Amount of the contribution'
widget-fieldset-fee='hd-fieldset-title'
submit-button='Save'
)
h2 Members List
sib-form.block.select-add-member(
bind-resources
nested-field='members'
fields='user'
range-user=`${endpoints.users || endpoints.get.users}`
class-user='team form-label is-dark'
label-user=''
widget-user='sib-form-auto-completion'
submit-button='Add a member'
)
.table
div.table-header.grey-color
div Name
div Access
//-class='table-body'
sib-display(
class='table-body'
bind-resources
fields='members'
multiple-members=''
widget-members='team-template-edit'
)
#project-left
div.content-box__info(style="padding: 15px")
p You have successfully left this project
p This is a private group, to join again, go to the <sib-link next="admin-project-list">administration</sib-link> panel and ask for an invite
sib-router(default-route='project-profile', hidden)
sib-route(name='project-profile')
sib-route(name='project-edit')
#project-profile(hidden)
include ../../templates/hd-business-provider.pug
include ../../templates/hd-captain.pug
include ../../templates/hd-circle-team.pug
include ../../templates/hd-customer.pug
include ../../templates/hd-project-team.pug
.content-box__info
.space-between
sib-display(
bind-resources
fields='creationDateSet(title, creationDate)'
class-title='word-spacing-right'
value-title='Creation date: '
widget-creationDate='sib-display-date'
)
sib-ac-checker(permission='acl:Append', bind-resources, nested-field='members')
sib-link(class='button text-bold text-uppercase reversed button-blue bordered with-icon icon-pencil' next='project-edit' bind-resources) Edit and add Members
.space-between
sib-display(
bind-resources
fields='label-captain, captain'
value-label-captain='Captain:'
class-label-captain='h2-like'
widget-captain='hd-captain'
)
sib-display(
class='customer-logo'
bind-resources
fields='customer.logo'
widget-customer.logo='sib-display-img'
)
h2 Contributions:
sib-link(next='project-contributions-help').button-question__position
button(aria-label='modal activator').icon-question.button-question__color
sib-display(
bind-resources
fields='businessProvider',
widget-businessProvider='hd-business-provider'
)
h2 Customer informations:
sib-display(
bind-resources
fields='customer'
widget-customer='hd-customer'
)
h2 Team:
sib-display(
bind-resources
fields='members'
widget-members='hd-project-team'
multiple-members
)
sib-widget(name='project-leave-button')
template
sib-delete(
class='button btn-margin-left text-bold text-uppercase reversed button-dark bordered with-icon icon-close'
data-src="${src}"
data-label='Leave Group'
)
sib-display(
class='position-end'
bind-resources
nested-field='members'
fields='relation'
action-relation='relation'
widget-relation='project-leave-button'
search-fields='user'
search-widget-user='sib-form-hidden'
search-value-user=""
hd-inherit-user-id="search-value-user"
)
#project-edit(hidden)
include page-project-edit.pug
import { resolve } from "node:path";
import { createHtmlPlugin } from 'vite-plugin-html'
import { defineConfig } from "vite";
import { VitePWA } from "vite-plugin-pwa";
import Handlebars from "handlebars";
import handlebars from "vite-plugin-handlebars";
import config from "./vite/generateConfig.mjs";
// Workaround for https://github.com/alexlafroscia/vite-plugin-handlebars/issues/192
function handlebarsOverride(options) {
const plugin = handlebars(options);
plugin.handleHotUpdate = async ({ server, file }) => {
if (file.endsWith(".html") || file.endsWith(".hbs"))
server.ws.send({
type: "full-reload",
});
};
return plugin;
}
export default defineConfig({
build: {
rollupOptions: {
input: {
app: resolve(__dirname, "index.html"),
},
},
},
css: {
preprocessorOptions: {
scss: {
quietDeps: true,
api: "modern-compiler"
},
},
},
define: config,
plugins: [
handlebarsOverride({
helpers: {
json: (value) => JSON.stringify(value),
year: () => new Date().getFullYear(),
isArray: (value) => Array.isArray(value),
mergeAttributes: (attributes) => {
let result = "";
for (const key in attributes) {
if (attributes.hasOwnProperty(key) && attributes[key] !== null) {
result += ` ${key}="${attributes[key]}"`;
}
}
return new Handlebars.SafeString(result);
},
hasComponent: (...component) =>
component.slice(0, -1).some((e) => config.componentSet.includes(e)),
hasComponentAll: (...component) =>
component.slice(0, -1).every((e) => config.componentSet.includes(e)),
hasNpmPackage: (...packages) =>
packages.slice(0, -1).every((e) => config.npm.filter(n => n.package === e).length > 0),
getComponent: (component) =>
config.components.find((c) => c.type === component),
getComponentFromRoute: (route) =>
config.components.find((c) => c.route === route),
getDefaultRoute: config.helpers.getDefaultRoute,
getRoute: config.helpers.getRoute,
get_legacy_view: (...name) => `legacy/${name.slice(0, -1).join('')}`,
is: (cond1, cond2) => cond1 === cond2,
any_are: (value, ...cond) => cond.slice(0, -1)?.includes(value),
includes: (arr, cond) => arr?.includes(cond),
},
partialDirectory: [resolve(__dirname, "src/partials")],
context: config,
}),
VitePWA({
devOptions: {
enabled: false,
},
injectRegister: "auto",
sourcemap: true,
manifest: {
lang: config.client.i18n.lang,
name: config.client.name,
short_name: config.client.shortName || config.client.name,
...config.client.pwa,
},
workbox: {
maximumFileSizeToCacheInBytes: 5000000,
runtimeCaching: [
{
urlPattern: /^https:\/\/fonts\.googleapis\.com\/.*/i,
handler: "CacheFirst",
options: {
cacheName: "google-fonts-cache",
expiration: {
maxEntries: 10,
maxAgeSeconds: 60 * 60 * 24 * 365,
},
cacheableResponse: {
statuses: [0, 200],
},
},
},
{
urlPattern: /^https:\/\/fonts\.gstatic\.com\/.*/i,
handler: "CacheFirst",
options: {
cacheName: "gstatic-fonts-cache",
expiration: {
maxEntries: 10,
maxAgeSeconds: 60 * 60 * 24 * 365,
},
cacheableResponse: {
statuses: [0, 200],
},
},
},
],
},
}),
createHtmlPlugin({
minify: true,
}),
],
resolve: {
alias: {
"@helpers": "/src/helpers",
"@partials": "/src/partials",
"@styles": "/src/styles",
},
},
});
{
"client": {
"name": "Sample of a functional Orbit",
"description": "",
"logo": "https://cdn.startinblox.com/logos/webp/startinblox.webp",
"server": "http://localhost:8000",
"favicon": "/pwa/favicon.ico",
"css": false,
"defaultAvatar": "/images/alien.webp",
"i18n": {
"lang": "en",
"force": false
},
"pwa": {
"dir": "ltr",
"icons": [
{
"src": "/pwa/pwa-192x192.png",
"sizes": "192x192",
"type": "image/png",
"purpose": "any"
},
{
"src": "/pwa/pwa-512x512.png",
"sizes": "512x512",
"type": "image/png",
"purpose": "any"
},
{
"src": "/pwa/pwa-maskable-192x192.png",
"sizes": "192x192",
"type": "image/png",
"purpose": "maskable"
},
{
"src": "/pwa/pwa-maskable-512x512.png",
"sizes": "512x512",
"type": "image/png",
"purpose": "maskable"
}
],
"start_url": "/",
"display": "standalone",
"orientation": "portrait",
"background_color": "#fff",
"theme_color": "#FFFFFF"
}
},
"components": [
{
"type": "routing",
"route": false
},
{
"type": "menu",
"route": false
},
{
"type": "menu-top",
"parameters": {
"isBeta": false
},
"route": false
}
],
"npm": []
}
{
"@startinblox/core": {
"version": "0.19",
"path": "https://cdn.jsdelivr.net/npm/@startinblox/core@0.19/dist/index.js"
},
"@startinblox/router": {
"version": "0.12",
"path": "https://cdn.jsdelivr.net/npm/@startinblox/router@0.12/+esm"
},
"@startinblox/oidc": {
"version": "0.16",
"path": "https://cdn.jsdelivr.net/npm/@startinblox/oidc@0.16/+esm",
"requiredBy": ["autoLogin", "registering"]
},
"@startinblox/component-chat": {
"version": "7.1.5",
"requiredBy": ["chat", "circles", "projects", "spaces"]
},
"@startinblox/component-communities": {
"version": "2.0.4",
"requiredBy": ["communities"]
},
"@startinblox/component-dashboard": {
"requiredBy": ["dashboard"]
},
"@startinblox/component-directory": {
"version": "8.0.2",
"requiredBy": ["directory"]
},
"@startinblox/component-event": {
"version": "5.0.7",
"requiredBy": ["events"]
},
"@startinblox/component-conversation": {
"version": "1.0.2",
"requiredBy": ["events", "polls", "resources"]
},
"@startinblox/component-invoicing": {
"requiredBy": ["invoices"]
},
"@startinblox/component-job-board": {
"requiredBy": ["job-board"]
},
"@startinblox/component-notifications": {
"version": "1.0.2",
"requiredBy": ["notification"]
},
"@startinblox/component-poll": {
"requiredBy": ["polls"]
},
"@startinblox/component-spaces": {
"requiredBy": ["spaces"]
},
"@startinblox/component-sales": {
"requiredBy": ["spaces"]
},
"@startinblox/component-resource": {
"version": "5.0.5",
"requiredBy": ["resources"]
},
"@startinblox/component-babelfish": {
"requiredBy": ["babelfish"]
},
"@startinblox/ontochain-directory": {
"requiredBy": ["ontochain-directory"]
},
"@startinblox/component-piswap": {
"requiredBy": ["piswap"]
},
"@startinblox/component-tamis": {
"requiredBy": [
"tamis-profile",
"tamis-commande",
"tamis-prestation",
"tamis-asset"
]
},
"@startinblox/components-tems": {
"requiredBy": ["tems-catalog"]
},
"moralis": {
"path": "https://unpkg.com/moralis/dist/moralis.js",
"requiredBy": ["piswap"]
}
}
import { defaultComposer } from "default-composer";
import { readdirSync, statSync } from "node:fs";
import { join } from "node:path";
import defaultNpm from "./default.npm.json";
import defaultConfig from "./default.config.json";
import convertStringToBoolean from "../src/helpers/convertStringToBoolean.js";
import generateUniq from "../src/helpers/generateUniq.js";
import generateUrl from "../src/helpers/generateUrl.js";
import rewriteServer from "../src/helpers/rewriteServer.js";
/*
Generate the client config from a combination of client.json, default.client.json, default.npm.json
Provide local federations and collision-free routes to each component.
*/
let userConfig;
try {
userConfig = (await import("../config.json")).default;
} catch {
userConfig = {};
}
try {
userConfig.context = (await import("../src/context.json")).default;
} catch {
userConfig.context = {};
}
const config = defaultComposer(defaultConfig, userConfig);
const componentSet = new Set(
[...defaultConfig.components, ...config.components].map((c) => c.type),
);
config.components.map((c) => {
if (c.extensions) {
for (const e of c.extensions) {
componentSet.add(e.type);
}
}
});
const defaultPackage = {
package: "",
version: "latest",
path: false,
};
// Those attributes will not be serialized on a component
const ignoredAttributes = ["replacement", "menu"];
const requiredPackages = Object.keys(defaultNpm)
.map((mod) => {
const replaced = config.npm.findIndex((e) => e.package === mod);
if (replaced === -1) {
const p = defaultNpm[mod];
if (!p.requiredBy || p.requiredBy?.some((dep) => componentSet.has(dep))) {
return defaultComposer(defaultPackage, {
package: mod,
version: p.version,
// path: p.path || `https://cdn.jsdelivr.net/npm/${mod}@${p.version || "latest"}`,
path: p.path,
});
}
} else {
return config.npm.splice(replaced, 1)[0];
}
return false;
})
.filter((p) => p);
const routes = new Set();
const federations = {};
const components = config.components.map((component) => {
if (typeof component.route === "undefined") {
component.route = component.type;
}
component.uniq = generateUniq();
if (component.route) {
let route = component.route;
if (routes.has(component.route)) {
route += `-${component.uniq}`;
}
routes.add(route);
component.route = route;
}
if (component.extensions) {
for (const extension of component.extensions) {
if (typeof extension.route === "undefined") {
extension.route = extension.type;
}
extension.uniq = generateUniq();
if (extension.route) {
let route = extension.route;
if (routes.has(extension.route)) {
route += `-${extension.uniq}`;
}
routes.add(route);
extension.route = route;
}
}
}
if (component.parameters) {
const federation = new Set();
if (config.client.server) {
federation.add(config.client.server);
}
if (config.client.servers) {
for (const server of config.client.servers) {
federation.add(server);
}
}
if (component.federation) {
for (const target of component.federation) {
federation.add(target);
}
}
component.federation = [...federation];
for (const [attribute, path] of Object.entries(component.parameters)) {
if (typeof path === "string") {
if (path.startsWith("federation://")) {
const contains = generateUrl(federation, path);
if (contains.length > 1) {
federations[`store://local.${component.uniq}/${attribute}/`] = {
"@cache": "false",
"@context": "https://cdn.startinblox.com/owl/context.jsonld",
"@type": "ldp:Container",
"@id": `store://local.${component.uniq}/${attribute}/`,
"ldp:contains": contains,
permissions: [{ mode: { "@type": "view" } }],
};
component.parameters[attribute] =
`store://local.${component.uniq}/${attribute}/`;
} else {
component.parameters[attribute] =
federation.values().next().value +
path.replace(/federation:\//, "");
}
}
}
component.parameters[attribute] = rewriteServer(component.parameters[attribute], {client: {server: config.client.server}});
}
/* Rewrite every parameters to kebab-case */
const rewriteParameters = {};
for (const [attribute, value] of Object.entries(component.parameters)) {
const attributeName = attribute.replace(/((?<=[a-z\d])[A-Z]|(?<=[A-Z\d])[A-Z](?=[a-z]))/g, "-$1").toLowerCase();
if(!ignoredAttributes.includes(attributeName)) {
rewriteParameters[attributeName] = value;
}
}
component.attributes = rewriteParameters;
component.attributes.route = component.route;
component.attributes.uniq = component.uniq;
}
if (component.extensions) {
component.extensions = component.extensions.map((extension) => {
if (extension.parameters) {
const federation = new Set();
if (config.client.server) {
federation.add(config.client.server);
}
if (config.client.servers) {
for (const server of config.client.servers) {
federation.add(server);
}
}
if (component.federation) {
for (const target of component.federation) {
federation.add(target);
}
}
if (extension.federation) {
for (const target of extension.federation) {
federation.add(target);
}
}
extension.federation = [...federation];
for (const [attribute, path] of Object.entries(extension.parameters)) {
if (typeof path === "string") {
if (path.startsWith("federation://")) {
const contains = generateUrl(federation, path);
if (contains.length > 1) {
federations[`store://local.${extension.uniq}/${attribute}/`] = {
"@cache": "false",
"@context": "https://cdn.startinblox.com/owl/context.jsonld",
"@type": "ldp:Container",
"@id": `store://local.${extension.uniq}/${attribute}/`,
"ldp:contains": contains,
permissions: [{ mode: { "@type": "view" } }],
};
extension.parameters[attribute] =
`store://local.${extension.uniq}/${attribute}/`;
} else {
component.parameters[attribute] =
federation.values().next().value +
path.replace(/federation:\//, "");
}
}
}
component.parameters[attribute] = rewriteServer(component.parameters[attribute], {client: {server: config.client.server}});
}
/* Rewrite every parameters to kebab-case */
const rewriteParameters = {};
for (const [attribute, value] of Object.entries(extension.parameters)) {
const attributeName = attribute.replace(/((?<=[a-z\d])[A-Z]|(?<=[A-Z\d])[A-Z](?=[a-z]))/g, "-$1").toLowerCase();
if(!ignoredAttributes.includes(attributeName)) {
rewriteParameters[attributeName] = value;
}
}
extension.attributes = rewriteParameters;
extension.attributes.uniq = extension.uniq;
}
return extension;
});
}
// Legacy: component.experimental to component.integration
if (component.experimental) {
component.integration = component.experimental;
}
return component;
});
const getRoute = (type, returnFirst = false, ignoreError = false) => {
const availables = components.filter(
(c) => c.type === type || c.uniq === type,
);
for (const c of components) {
if (c.extensions) {
for (const e of c.extensions) {
if (e.type === type || e.uniq === type) {
availables.push(e);
}
}
}
}
if (availables.length > 1) {
if (returnFirst) {
return availables[0].route;
}
return availables[availables.length - 1].route;
}
if (availables.length < 1) {
if (!ignoreError && import.meta.env.DEV)
console.error(`No component found for route ${type}`);
} else {
return availables[0].route;
}
return false;
};
const getDefaultRoute = () => {
const defaultComponent = components.filter(
(e) => e.defaultRoute !== undefined,
);
let defaultRoute = "dashboard";
if (defaultComponent.length === 1) {
defaultRoute = defaultComponent[0].route;
}
return defaultRoute;
};
const listFiles = (directory, subfolder) => {
try {
const files = readdirSync(directory);
const fileNames = files.filter((filePath) =>
statSync(join(directory, filePath)).isFile(),
);
return fileNames.map(
(file) => () => `${subfolder}/${file.replace(".hbs", "")}`,
);
} catch (err) {
console.error(err);
return [];
}
};
const notifications = listFiles(
"./src/partials/notifications",
"notifications",
);
const widgets = listFiles("./src/partials/widgets", "widgets");
const mandatoryComponents = defaultConfig.components.filter(
(component) =>
!config.components.some((c) => component["type"] === c["type"]),
);
const definitiveConfig = {
client: Object.fromEntries(
Object.entries(config.client).map(([k, c]) => [
k,
convertStringToBoolean(rewriteServer(c, config)),
]),
),
components: [...mandatoryComponents, ...config.components],
// Both handlebars and vite does not handle Set properly
componentSet: [...componentSet],
npm: requiredPackages.concat(config.npm),
federations,
files: {
notifications: notifications,
widgets: widgets,
},
helpers: {
getDefaultRoute,
getRoute,
listFiles,
},
};
export default definitiveConfig;