- Added new function generateJSModulesInclude to application/helpers/hlp_header_helper.php

- Added entry "customJSModules" to the application/views/templates/FHC-Footer.php to be passed to the generateJSModulesInclude function to generate JS modules tags
- The new VUE components are making use of the JS import and export functionalities
This commit is contained in:
Paolo
2022-06-24 15:07:50 +02:00
parent 9e48ba09d8
commit 24b78454d3
6 changed files with 400 additions and 64 deletions
+26
View File
@@ -149,6 +149,31 @@ function generateJSsInclude($JSs)
}
}
/**
* Generates tags for the javascript modules you want to include, the parameter could by a string or an array of strings
*/
function generateJSModulesInclude($JSModules)
{
$jsInclude = '<script type="module" src="%s"></script>';
$ci =& get_instance();
$cachetoken = '?'.$ci->config->item('fhcomplete_build_version');
if (isset($JSModules))
{
$tmpJSs = is_array($JSModules) ? $JSModules : array($JSModules);
for ($tmpJSsCounter = 0; $tmpJSsCounter < count($tmpJSs); $tmpJSsCounter++)
{
$toPrint = sprintf($jsInclude, base_url($tmpJSs[$tmpJSsCounter].$cachetoken)).PHP_EOL;
if ($tmpJSsCounter > 0) $toPrint = "\t\t".$toPrint;
echo $toPrint;
}
}
}
/**
* Generates all the includes needed by the Addons
*/
@@ -180,3 +205,4 @@ function generateBackwardCompatibleJSMsIe($js)
echo ' <script type="text/javascript" src="'.$js.'"></script>'."\n";
echo "<![endif]-->\n";
}
+45 -1
View File
@@ -14,7 +14,7 @@
'global' => array('mailAnXversandt'),
'ui' => array('bitteEintragWaehlen')
),
'customJSs' => array('public/js/apps/LogsViewer.js')
'customJSModules' => array('public/js/apps/LogsViewer.js')
);
$this->load->view('templates/FHC-Header', $includesArray);
@@ -36,6 +36,50 @@
<div>
<!-- Filter component -->
<core-filter-cmpt filter-type="LogsViewer" @nw-new-entry="newSideMenuEntryHandler"></core-filter-cmpt>
<!--
'datasetRepresentation' => 'tablesorter',
'columnsAliases' => array(
'Log id',
'Request id',
'Execution time',
'Executed by',
'Producer',
'Data',
'Webservice type'
),
'formatRow' => function($datasetRaw) {
$datasetRaw->ExecutionTime = date_format(date_create($datasetRaw->ExecutionTime), 'd.m.Y H:i:s:u');
return $datasetRaw;
},
'markRow' => function($datasetRaw) {
$mark = '';
if (strpos($datasetRaw->RequestId, 'error') != false)
{
$mark = 'text-red';
}
if (strpos($datasetRaw->RequestId, 'info') != false)
{
$mark = 'text-green';
}
if (strpos($datasetRaw->RequestId, 'warning') != false)
{
$mark = 'text-orange';
}
if (strpos($datasetRaw->RequestId, 'debug') != false)
{
$mark = 'text-info';
}
return $mark;
}
-->
</div>
</div>
</div>
+2 -9
View File
@@ -15,6 +15,7 @@
// By default set the parameters to null
$customJSs = isset($customJSs) ? $customJSs : null;
$customJSModules = isset($customJSModules) ? $customJSModules : null;
// --------------------------------------------------------------------------------------------------------
// Javascripts
@@ -118,24 +119,15 @@
// NOTE: to be used only if you know what you are doing!
if ($bootstrapper === true) generateJSsInclude('public/js/bootstrapper.js');
// VUE Navigation Component JS
if ($navigationcomponent === true) generateJSsInclude('public/js/components/Navigation.js');
// NavigationWidget JS
if ($navigationwidget === true) generateJSsInclude('public/js/NavigationWidget.js');
// VUE Filter Component JS
if ($filtercomponent === true) generateJSsInclude('public/js/components/Filter.js');
// FilterWidget JS
if ($filterwidget === true) generateJSsInclude('public/js/FilterWidget.js');
// PhrasesLib JS
if ($phrases != null) generateJSsInclude('public/js/PhrasesLib.js');
// VUE Table Component JS
if ($tablecomponent === true) generateJSsInclude('public/js/components/Table.js');
// TableWidget JS
if ($tablewidget === true) generateJSsInclude('public/js/TableWidget.js');
@@ -149,6 +141,7 @@
// Eventually required JS
// NOTE: keep it as the latest
generateJSsInclude($customJSs);
generateJSModulesInclude($customJSModules);
?>
</body>
</html>
+3
View File
@@ -1,3 +1,6 @@
import {CoreFilterCmpt} from '../components/Filter.js';
import {CoreNavigationCmpt} from '../components/Navigation.js';
const logsViewerApp = Vue.createApp({
data() {
return {
+314 -48
View File
@@ -1,15 +1,18 @@
const CoreFilterCmpt = {
export const CoreFilterCmpt = {
emits: ['nwNewEntry'],
data() {
return {
fields: null,
fieldsToDisplay: null,
dataset: null,
selectedFields: null
selectedFields: null,
notSelectedFields: null,
filterFields: null,
notFilterFields: null
};
},
created() {
this.fetchFilterData();
this.fetchFilterMenuData();
this._fetchFilterData();
},
updated() {
let filterCmptTablesorter = $("#filterTableDataset");
@@ -36,72 +39,179 @@ const CoreFilterCmpt = {
}
},
methods: {
fetchFilterData() {
saveCustomFilter(el) {
FHC_AjaxClient.ajaxCallPost(
"components/Filter/saveCustomFilter",
{
filterUniqueId: this._getCurrentPage(),
filterType: this.filterType,
customFilterName: document.getElementById('customFilterName').value
},
{
successCallback: function(data) {console.log(data)}
}
);
},
applyFilterFields(el) {
let filterFields = [];
let filterFieldDivs = document.getElementById('filterFields').getElementsByTagName('div');
for (let i = 0; i < filterFieldDivs.length; i++)
{
let filterField = {};
for (let j = 0; j < filterFieldDivs[i].children.length; j++)
{
if (filterFieldDivs[i].children[j].name != null)
{
// Name
if (filterFieldDivs[i].children[j].name == 'fieldName')
{
filterField.name = filterFieldDivs[i].children[j].value;
}
// Operation
if (filterFieldDivs[i].children[j].name == 'operation')
{
filterField.operation = filterFieldDivs[i].children[j].value;
}
// Condition
if (filterFieldDivs[i].children[j].name == 'condition')
{
filterField.condition = filterFieldDivs[i].children[j].value;
}
// Option
if (filterFieldDivs[i].children[j].name == 'option')
{
filterField.option = filterFieldDivs[i].children[j].value;
}
}
}
filterFields.push(filterField);
}
FHC_AjaxClient.ajaxCallPost(
"components/Filter/applyFilterFields",
{
filterUniqueId: this._getCurrentPage(),
filterType: this.filterType,
filterFields: filterFields
},
{
successCallback: this._fetchFilterData
}
);
},
addFilterField(el) {
FHC_AjaxClient.ajaxCallPost(
"components/Filter/addFilterField",
{
filterUniqueId: this._getCurrentPage(),
filterType: this.filterType,
filterField: el.currentTarget.value
},
{
successCallback: this._fetchFilterData
}
);
},
addSelectedField(el) {
FHC_AjaxClient.ajaxCallPost(
"components/Filter/addSelectedField",
{
filterUniqueId: this._getCurrentPage(),
filterType: this.filterType,
selectedField: el.currentTarget.value
},
{
successCallback: this._fetchFilterData
}
);
},
removeSelectedField(el) {
FHC_AjaxClient.ajaxCallPost(
"components/Filter/removeSelectedField",
{
filterUniqueId: this._getCurrentPage(),
filterType: this.filterType,
selectedField: el.currentTarget.getAttribute('field-to-remove')
},
{
successCallback: this._fetchFilterData
}
);
},
removeFilterField(el) {
FHC_AjaxClient.ajaxCallPost(
"components/Filter/removeFilterField",
{
filterUniqueId: this._getCurrentPage(),
filterType: this.filterType,
filterField: el.currentTarget.getAttribute('field-to-remove')
},
{
successCallback: this._fetchFilterData
}
);
},
fetchFilterDataById(el) {
FHC_AjaxClient.ajaxCallGet(
"components/Filter/getFilter",
{
filterUniqueId: this.getFilterUniqueIdPrefix(),
filterType: this.filterType, // props!!
filterId: 170
filterUniqueId: this._getCurrentPage(),
filterType: this.filterType,
filter_id: el.currentTarget.getAttribute("href").substring(1)
},
{
successCallback: this.renderTableSorter
successCallback: this._render
}
);
},
fetchFilterMenuData() {
_fetchFilterData() {
FHC_AjaxClient.ajaxCallGet(
"components/Filter/generateFilterMenu",
"components/Filter/getFilter",
{
filterUniqueId: this.getFilterUniqueIdPrefix(),
navigation_page: this.getNavigationPage()
filterUniqueId: this._getCurrentPage(),
filterType: this.filterType // props!!
},
{
successCallback: this.setSideMenu
successCallback: this._render
}
);
},
setSideMenu(data) {
// Set the menu
if (FHC_AjaxClient.hasData(data))
{
let filters = FHC_AjaxClient.getData(data).filters;
let personalFilters = FHC_AjaxClient.getData(data).personalFilters;
let filtersArray = [];
for (let filtersCount = 0; filtersCount < filters.length; filtersCount++)
{
filtersArray[filtersArray.length] = {
link: filters[filtersCount].link,
description: filters[filtersCount].desc,
sort: filtersCount
};
}
this.$emit(
'nwNewEntry',
[{
link: "#",
description: "Filters",
icon: "filter",
children: filtersArray
}]
);
}
},
getFilterUniqueIdPrefix() {
_getCurrentPage: function() {
return FHC_JS_DATA_STORAGE_OBJECT.called_path + "/" + FHC_JS_DATA_STORAGE_OBJECT.called_method;
},
getNavigationPage: function() {
return FHC_JS_DATA_STORAGE_OBJECT.called_path + "/" + FHC_JS_DATA_STORAGE_OBJECT.called_method;
},
renderTableSorter(data) {
_render(data) {
if (FHC_AjaxClient.hasData(data))
{
this._setFieldsToDisplay(FHC_AjaxClient.getData(data));
this.dataset = FHC_AjaxClient.getData(data).dataset;
this.fields = FHC_AjaxClient.getData(data).fields;
this.selectedFields = FHC_AjaxClient.getData(data).selectedFields;
this.notSelectedFields = this.fields.filter(x => this.selectedFields.indexOf(x) === -1);
this.filterFields = [];
let tmpFilterFields = [];
for (let i = 0; i < FHC_AjaxClient.getData(data).datasetMetadata.length; i++)
{
for (let j = 0; j < FHC_AjaxClient.getData(data).filters.length; j++)
{
if (FHC_AjaxClient.getData(data).datasetMetadata[i].name == FHC_AjaxClient.getData(data).filters[j].name)
{
let filter = FHC_AjaxClient.getData(data).filters[j];
filter.type = FHC_AjaxClient.getData(data).datasetMetadata[i].type;
this.filterFields.push(filter);
tmpFilterFields.push(filter.name);
break;
}
}
}
this.notFilterFields = this.fields.filter(x => tmpFilterFields.indexOf(x) === -1);
this._setFieldsToDisplay(FHC_AjaxClient.getData(data));
this._setSideMenu(FHC_AjaxClient.getData(data));
}
else
{
@@ -134,9 +244,165 @@ const CoreFilterCmpt = {
}
this.fieldsToDisplay = arrayFieldsToDisplay;
},
_setSideMenu(data) {
// Set the menu
let filters = data.sideMenu.filters;
let personalFilters = data.sideMenu.personalFilters;
let filtersArray = [];
for (let filtersCount = 0; filtersCount < filters.length; filtersCount++)
{
let link = filters[filtersCount].link;
if (link == null) link = '#';
filtersArray[filtersArray.length] = {
link: link + filters[filtersCount].filter_id,
description: filters[filtersCount].desc,
sort: filtersCount,
onClickCall: this.fetchFilterDataById
};
}
this.$emit(
'nwNewEntry',
[{
link: "#",
description: "Filters",
icon: "filter",
children: filtersArray
}]
);
}
},
template: `
<div class="card filter-filter-options">
<div class="card-header filter-header-title" data-bs-toggle="collapse" data-bs-target="#collapseFilterHeader">
Filter options
</div>
<div id="collapseFilterHeader" class="card-body collapse">
<!-- Filter fields options -->
<div class="filter-options-div">
<div class="filter-dnd-area">
<template v-for="fieldToDisplay in fieldsToDisplay">
<span class="filter-dnd-object">
{{ fieldToDisplay }}
<button
type="button"
class="btn-close"
v-bind:field-to-remove="fieldToDisplay"
@click=removeSelectedField>
</button>
</span>
</template>
</div>
<select class="form-select form-select-sm" @change=addSelectedField>
<option value="">Select a field to be displayed...</option>
<template v-for="hiddenField in notSelectedFields">
<option v-bind:value="hiddenField">{{ hiddenField }}</option>
</template>
</select>
</div>
<!-- Filter options -->
<div class="filter-options-div">
<div>
<select class="form-select form-select-sm" @change=addFilterField>
<option value="">Add a field to the filter...</option>
<template v-for="notFilterField in notFilterFields">
<option v-bind:value="notFilterField">{{ notFilterField }}</option>
</template>
</select>
</div>
<div id="filterFields" class="filter-filter-fields">
<template v-for="filterField in filterFields">
<!-- Numeric -->
<div v-if="filterField.type.toLowerCase().indexOf('int') >= 0" class="input-group mb-3">
<input type="hidden" name="fieldName" v-bind:value="filterField.name">
<span class="input-group-text">{{ filterField.name }}</span>
<select class="form-select form-select-sm" name="operation">
<option value="equal">Equal</option>
<option value="nequal">Not equal</option>
<option value="gt">Greater then</option>
<option value="lt">Less then</option>
</select>
<input type="number" class="form-control" v-bind:value="filterField.condition" name="condition">
<button
class="btn btn-sm btn-outline-dark"
type="button"
v-bind:field-to-remove="filterField.name"
@click=removeFilterField>
&emsp;X&emsp;
</button>
</div>
<!-- Text -->
<div
v-if="filterField.type.toLowerCase().indexOf('varchar') >= 0
|| filterField.type.toLowerCase().indexOf('text') >= 0
|| filterField.type.toLowerCase().indexOf('bpchar') >= 0"
class="input-group mb-3">
<input type="hidden" name="fieldName" v-bind:value="filterField.name">
<span class="input-group-text">{{ filterField.name }}</span>
<select class="form-select form-select-sm" name="operation">
<option value="contains">Conrains</option>
<option value="ncontains">Does not contain</option>
</select>
<input type="text" class="form-control" v-bind:value="filterField.condition" name="condition">
<button
class="btn btn-sm btn-outline-dark"
type="button"
v-bind:field-to-remove="filterField.name"
@click=removeFilterField>
&emsp;X&emsp;
</button>
</div>
<!-- Timestamp and date -->
<div
v-if="filterField.type.toLowerCase().indexOf('timestamp') >= 0
|| filterField.type.toLowerCase().indexOf('date') >= 0"
class="input-group mb-3">
<input type="hidden" name="fieldName" v-bind:value="filterField.name">
<span class="input-group-text">{{ filterField.name }}</span>
<select class="form-select form-select-sm" name="operation">
<option value="gt">Greater then</option>
<option value="lt">Less then</option>
<option value="set">Is set</option>
<option value="nset">Is not set</option>
</select>
<input type="number" class="form-control" v-bind:value="filterField.condition" name="condition">
<select class="form-select form-select-sm" name="option">
<option value="minutes">Minutes</option>
<option value="hours">Hours</option>
<option value="days">Days</option>
<option value="months">Months</option>
</select>
<button
class="btn btn-sm btn-outline-dark"
type="button"
v-bind:field-to-remove="filterField.name"
@click=removeFilterField>
&emsp;X&emsp;
</button>
</div>
</template>
</div>
<div>
<button type="button" class="btn btn-sm btn-outline-dark" @click=applyFilterFields>Apply changes</button>
</div>
</div>
<!-- Filter save options -->
<div class="input-group">
<input type="text" class="form-control" placeholder="Custom filter name" id="customFilterName">
<button type="button" class="btn btn-outline-secondary" @click=saveCustomFilter>Save</button>
</div>
</div>
</div>
<table class="tablesorter table-bordered table-responsive" id="filterTableDataset">
<thead>
<tr>
+10 -6
View File
@@ -1,4 +1,4 @@
const CoreNavigationCmpt = {
export const CoreNavigationCmpt = {
data() {
return {
headerMenu: {},
@@ -76,7 +76,7 @@ const CoreNavigationCmpt = {
<template v-for="header in headerMenuEntries">
<li class="nav-item dropdown">
<a class="nav-link header-menu-link-entry" v-bind:data-bs-toggle="this.getDataBsToggle(header)" v-bind:class="{ 'dropdown-toggle': header.children }" v-bind:href="header.link">
<i class="fa-solid" v-bind:class="'fa-' + header.icon" v-if="header.icon"></i> {{ header.description }}
<i class="fa-solid fa-fw header-menu-icon" v-bind:class="'fa-' + header.icon" v-if="header.icon"></i> {{ header.description }}
</a>
<ul class="dropdown-menu" v-if="header.children">
<!-- 2nd level -->
@@ -90,18 +90,22 @@ const CoreNavigationCmpt = {
</nav>
<!-- Left side menu -->
<nav class="navbar sidebar">
<nav class="navbar navbar-left-side">
<ul class="navbar-nav">
<!-- 1st level -->
<template v-for="menu in sideMenuEntries">
<li class="nav-item">
<a class="nav-link" v-bind:href="menu.link">
<a class="nav-link left-side-menu-link-entry" v-bind:href="menu.link" @click=menu.onClickCall>
<i class="fa fa-fw" v-bind:class="'fa-'+ menu.icon"></i> {{ menu.description }}
</a>
<ul class="nav-link" v-if="menu.children">
<ul class="nav-link left-side-menu-second-level" v-if="menu.children">
<!-- 2nd level -->
<template v-for="child in menu.children">
<li><a class="nav-link" v-bind:href="child.link">{{ child.description }}</a></li>
<li>
<a class="nav-link left-side-menu-link-entry" v-bind:href="child.link" @click=child.onClickCall>
&emsp;&emsp;{{ child.description }}
</a>
</li>
</template>
</ul>
</li>