Here will be referenced several ways to develop specific cases. This page aim is to collect best practices and ways to respond to situations frequently encountered by developers.
// Setup variables that will be use and display in the mail
const mailData = {
value_1: "my_value_1"
}
// Find the media mail you want to send
const media_mail = await models.E_media_mail.findOne({
where: {
id: 2
}
});
try {
// Execute the media mail
media_mail.execute(mailData);
} catch (err) {
console.error(err);
}
Don't forget to set true the socket.enabled and socket.notification in @config/application.json.
const media_notification = await models.E_media_notification.findOne({
where: {
id: 1
}
});
// Find the model instance corresponding to the main selected in the media creation
const main_media_entity_instance = await models.E_main_media_entity.findOne();
// Find the user to send the notification
const user_to_send = await models.E_user.findOne();
try {
// Here you can modify the default media behavior
media_notification.f_targets = `{user|${user_to_send.id}}`; // You can also send to a user group with {group|GROUP_ID} for example
// media_notification.f_title = "Override title";
// media_notification.f_description = "Override description";
// media_notification.f_url = "Override redirection url";
// Execute the media mail
media_notification.execute(main_media_entity_instance);
} catch (err) {
console.error(err);
}
First lets add the menu in the left sidebar of your module, here it will be home module.
So you have to add the module in the dust file views/layout_m_home.dust like that:
{#actionAccess entity="my_entity" action="read"}
<li class="nav-item">
<a href="/my_entity/list?id=1" class="nav-link">
<i class="fas fa-caret-right ml-3 mr-2"></i>
<p>
{#__ key="entity.e_my_entity.label_entity" /} - ID 1
</p>
</a>
</li>
{/actionAccess}
You can see that we add ?id=1in the href url. So we want to pre-filter the datalist with the ID 1.
Then we need to use this query parameter in the list entity hook, so in app/routes/my_entity.js:
list: {
start: async (data) => {
const { id } = data.req.query;
if(id)
data.tableUrl = `${data.tableUrl}?id=${id}`;
},
},
Finally, we retrieve in the ajax route /datalist via the corresponding hook of the entity the id that we have just passed via data.tableUrl:
datalist: {
beforeDatatableQuery: async (data) => {
const { id } = data.req.query;
if(id)
data.speWhere = { fk_id_status_partner_state: parseInt(id) };
},
},
Do you want to ensure that you have pages accessible outside of the standard Nodea authentication system?
This can make it possible to set up a front showcase while retaining the Nodea back office.
In our example, we have to make sure that when we arrive on / we are faced with an HTML page that does not require authentication.
To do this, the first choice to do is to go to your app/routes/root.js file and add an overload of the root() method which by default redirects to /login
class Root extends CoreRoot {
constructor() {
const additionalRoutes = [];
super(additionalRoutes);
}
// Overriding root ->
root() {
this.router.get('/', (req, res) => {
// Create a folder /app/views/front and a main.dust file in it
res.render('front/main');
});
}
get hooks() {
return {}
}
get middlewares() {
return {
root: [],
status_comment: [
middlewares.isLoggedIn
]
}
}
}
Now your default page on /. In order to add new additional front pages we will create a dedicated route file rather than writing everything in the app/routes/root.js file.
To do this, simply create an app/routes/front.js file with the following content:
const Route = require('@core/abstract_routes/route');
class Front extends Route {
constructor() {
const registeredRoutes = ['page_test'];
super(registeredRoutes);
}
// /test front page
page_test() {
this.router.get('/test', (req, res) => {
res.render('front/test');
});
}
}
module.exports = Front;
And you have to tell the indexer that the front.js file will be indexed on / and not /front. We must therefore modify the app/routes/index.js file like this:
const fs = require('fs-extra');
const path = require('path');
const basename = path.basename(module.filename);
const Route = require('@core/abstract_routes/route');
const Module = require('@core/routes/module');
const Entity = require('@core/abstract_routes/entity');
const Login = require('@core/routes/login');
const Root = require('@core/routes/root');
module.exports = app => {
fs.readdirSync(__dirname)
.filter(file => file.indexOf('.') !== 0 && file !== basename && file.slice(-3) === '.js')
.forEach(file => {
const FileRoute = require('./' + file); // eslint-disable-line
const route = new FileRoute();
file = file.slice(0, -3);
if (!(route instanceof Route))
throw new Error(`Route file '${file}' doesn't export @core/abstract_routes/route class`);
let url;
if (route instanceof Module)
url = '/module';
else if (route instanceof Entity || file.startsWith('c_'))
url = '/' + file.substring(2);
else if (route instanceof Login || route instanceof Root || file == 'front')//<-Add || file == 'front'
url = '/';
else
url = '/' + file;
app.use(url, ...route.defaultMiddlewares, route.routes);
});
}
Now you can freely (without any authentication) navigate between / et /test in your application.
Sometimes it will be necessary to display an enum / radio type column linked to an association of the parent entity. By default these values will not be translated correctly. The objective is therefore to explain how to translate these values.
In our example we have an entity Entity1 has many Entity2, Entity1 has a Type column of type enum with value_1 and value_2 to translate Value 1 and Value 2.
First of all, you must of course add the Type column in the Entity 2 list, for this you must modify the file /app/views/entity_2/list_fields.dust:
<th data-field="r_entity_1.f_type" data-col="r_entity_1.f_type" data-type="enum">
Type
</th>
This will display the Type column of Entity 1 in the list of Entity 2, the problem is that the values displayed are not translated in the list. It displays value_1 or value_2 instead of Value 1 or Value 2.
To translate, you have to enter the translation values in the data sent to the NodeaTable, to do this you have to go to the datalist.beforeResponse hook of the /routes/e_envelope.js file and add this:
Add entity_1 options as well as enum_radio translation management in file header:
const entity1_options = require('@app/models/options/e_entity_1');
const enums_radios = require('@core/utils/enum_radio');
And then in the datalist.beforeResponse hook:
beforeResponse: async(data) => {
const enumsTranslation = enums_radios.translated('e_entity_1', data.req.session.lang_user, entity1_options);
for (let i = 0; i < data.preparedData.data.length; i++) {
if(!data.preparedData.data[i].r_entity_1[0])
continue;
// Tranlate enums / radios
enums_radios.translateRow(data.preparedData.data[i].r_entity_1[0], 'e_entity_1', enumsTranslation, true);
// Translate alias using field too
enums_radios.translateUsingField(data.preparedData.data[i].r_entity_1[0], entity1_options, enumsTranslation, true);
}
}