diff --git a/build/build.js b/build/build.js index dd4577f..791bf2f 100644 --- a/build/build.js +++ b/build/build.js @@ -3,7 +3,7 @@ const runSequence = require('gulp4-run-sequence'); var shelljs = require('shelljs'); gulp.task('pre-build', function (done) { - runSequence('copy-extensions-assets', 'update-extensions-export', 'clean', 'copy-dependent-scripts', 'copy-src-assets', done); + runSequence('copy-extensions-assets', 'update-extensions-export', 'clean', 'copy-src-assets', done); }) gulp.task('build', function (done) { diff --git a/build/copy.js b/build/copy.js index 9fc3413..1fd4d94 100644 --- a/build/copy.js +++ b/build/copy.js @@ -2,7 +2,7 @@ const gulp = require('gulp'); var shelljs = require('shelljs'); const fs = require('fs'); -const extensionsAssets = ['images', 'barcode.reportitem.css', 'barcode.reportitem.js', 'qrbarcode.reportitem.js', 'signature.reportitem.css','signature.dialog.css','signature.reportitem.js','signature.dialog.js','shape.reportitem.css','shape.reportitem.js','document.reportitem.css','pdfdocument.reportitem.js','htmldocument.reportitem.js']; +const extensionsAssets = ['images', 'barcode.reportitem.css', 'barcode.reportitem.js', 'qrbarcode.reportitem.js', 'signature.reportitem.css','signature.dialog.css','signature.reportitem.js','signature.dialog.js','shape.reportitem.css','shape.reportitem.js','document.reportitem.css','pdfdocument.reportitem.js','htmldocument.reportitem.js', 'pdf.signature.reportitem.css', 'pdf.signature.reportitem.js']; const extensionsItemSrcDir = 'node_modules/@boldreports/javascript-reporting-extensions/'; const extensionsItemDir = './src/controls/extensions/report-item-extensions/'; const extensionsExportTemp = { @@ -13,6 +13,7 @@ const extensionsExportTemp = { 'shape': 'export { EJShape }', 'pdfDocument': 'export { EJPdfDocument }', 'htmlDocument': 'export { EJHtmlDocument }', + 'pdfSignature': 'export { EJPDFSignature }' } gulp.task('copy-src-assets', function (done) { @@ -21,19 +22,6 @@ gulp.task('copy-src-assets', function (done) { done(); }); -gulp.task('copy-dependent-scripts', function (done) { - shelljs.mkdir('-p',`${process.cwd()}/public/assets/scripts`); - var dependentScriptLocation = `${process.cwd()}/public/assets/scripts`; - copyFile(`${process.cwd()}/node_modules/@boldreports/javascript-reporting-controls/Scripts/common/ej2-base.min.js`,dependentScriptLocation); - copyFile(`${process.cwd()}/node_modules/@boldreports/javascript-reporting-controls/Scripts/common/ej2-data.min.js`,dependentScriptLocation); - copyFile(`${process.cwd()}/node_modules/@boldreports/javascript-reporting-controls/Scripts/common/ej2-pdf-export.min.js`,dependentScriptLocation); - copyFile(`${process.cwd()}/node_modules/@boldreports/javascript-reporting-controls/Scripts/common/ej2-svg-base.min.js`,dependentScriptLocation); - copyFile(`${process.cwd()}/node_modules/@boldreports/javascript-reporting-controls/Scripts/data-visualization/ej2-lineargauge.min.js`,dependentScriptLocation); - copyFile(`${process.cwd()}/node_modules/@boldreports/javascript-reporting-controls/Scripts/data-visualization/ej2-circulargauge.min.js`,dependentScriptLocation); - copyFile(`${process.cwd()}/node_modules/@boldreports/javascript-reporting-controls/Scripts/data-visualization/ej2-maps.min.js`,dependentScriptLocation); - done(); -}); - gulp.task('copy-extensions-assets', (done) => { shelljs.mkdir('-p',`${process.cwd()}/src/controls/extensions/report-item-extensions/`); extensionsAssets.forEach(file => { @@ -51,6 +39,7 @@ gulp.task('update-extensions-export', (done) => { 'shape': ['shape.reportitem.js', 'shape'], 'pdfDocument': ['pdfdocument.reportitem.js', 'pdfDocument'], 'htmlDocument': ['htmldocument.reportitem.js', 'htmlDocument'], + 'pdfSignature': ['pdf.signature.reportitem.js', 'pdfSignature'] }; const updateFile = (key, [filename, exportKey]) => { const filePath = `${extensionsItemDir}${filename}`; diff --git a/package.json b/package.json index c4d50d2..3bc4244 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,10 @@ { "name": "react-sample-browser", - "version": "11.1.10", + "version": "12.1.12", "private": true, "dependencies": { - "@boldreports/react-reporting-components": "11.1.10", - "@boldreports/javascript-reporting-extensions": "11.1.10", + "@boldreports/react-reporting-components": "12.1.12", + "@boldreports/javascript-reporting-extensions": "12.1.12", "@testing-library/jest-dom": "5.11.9", "@testing-library/react": "11.2.5", "@testing-library/user-event": "12.8.3", diff --git a/src/App.js b/src/App.js index 2352c5c..e2e55ac 100644 --- a/src/App.js +++ b/src/App.js @@ -25,20 +25,42 @@ const samples = data.samples; class App extends React.Component { renderViewer = (routerProps) => { var previewUrl = routerProps.match.url.toString(); - previewUrl = previewUrl.substr(previewUrl.lastIndexOf('/') + 1, previewUrl.length - 1); + previewUrl = previewUrl.replace(/\/+$/, '').split('/').pop(); var isPreview = previewUrl === "preview" ? true : false; let samplePathName = routerProps.match.params.id; let foundViewer = samples.find(sample => sample.routerPath === samplePathName); - return (foundViewer ? isPreview ? : : ) + return (foundViewer ? isPreview ? : : ) } + + addTrailingSlash = () => { + const rawHash = window.location.hash || '#/'; + let [path, query = ''] = rawHash.slice(1).split('?'); + query = query ? `?${query}` : ''; + const redirectionMap = { + '/report-designer': '/report-designer/', + '/report-designer/rdlc': '/report-designer/rdlc/', + }; + let normalizedPath = redirectionMap[path] || path; + if (!normalizedPath.endsWith('/') && /^\/report-viewer\/[^/]+(?:\/preview)?$/.test(normalizedPath)) { + normalizedPath += '/'; + } + const normalizedHash = `${normalizedPath}${query}`; + if (normalizedHash !== rawHash.slice(1)) { + window.location.hash = normalizedHash; + } + } + state = { redirect: false } componentDidMount() { + this.addTrailingSlash(); + window.addEventListener('hashchange', this.addTrailingSlash, { passive: true }); this.id = setTimeout(() => this.setState({ redirect: true }), 2000); } componentWillUnmount() { - clearTimeout(this.id) + window.removeEventListener('hashchange', this.addTrailingSlash); + clearTimeout(this.id); } render() { return ( @@ -46,25 +68,25 @@ class App extends React.Component {
- + { this.state.redirect ? : } - + { this.state.redirect ? : } - + { - this.state.redirect ? this.renderViewer(routerProps)} exact /> : + this.state.redirect ? this.renderViewer(routerProps)} exact /> : } - this.renderViewer(routerProps)} exact> - this.renderViewer(routerProps)} exact> + this.renderViewer(routerProps)} exact> + this.renderViewer(routerProps)} exact> - + diff --git a/src/assets/sidebar/portrait.png b/src/assets/sidebar/portrait.png index cb3ae12..ac5b9e9 100644 Binary files a/src/assets/sidebar/portrait.png and b/src/assets/sidebar/portrait.png differ diff --git a/src/common/header/header.css b/src/common/header/header.css index bf32ce4..a96e413 100644 --- a/src/common/header/header.css +++ b/src/common/header/header.css @@ -86,6 +86,9 @@ font-family: "Roboto", "Segoe UI", "GeezaPro", "DejaVu Serif", "sans-serif"; justify-content: space-between; } +.ej-sb-header.designer-header { + z-index: 1 !important; +} .ej-sb-header .ej-sb-left-side { height: inherit; diff --git a/src/common/header/header.js b/src/common/header/header.js index 5bcd413..a1ad077 100644 --- a/src/common/header/header.js +++ b/src/common/header/header.js @@ -76,7 +76,7 @@ class Header extends Component { render() { return ( -
+
{this.props.isViewer ?
: ''} diff --git a/src/common/main-content/main-content.js b/src/common/main-content/main-content.js index 09ca3bc..a0f0331 100644 --- a/src/common/main-content/main-content.js +++ b/src/common/main-content/main-content.js @@ -36,7 +36,7 @@ class MainContentSample extends Component { } navigateNextOrPrev = (reportName, nextOrPrev) => { var previousOrNextSample = this.findSample(reportName, nextOrPrev); - window.location.href = window.location.href.substr(0, window.location.href.lastIndexOf("/")) + "/" + previousOrNextSample.routerPath; + window.location.hash = `/report-viewer/${previousOrNextSample.routerPath}/`; } findSample(reportName, nextOrPrev) { var currentIndex = Object.values(samples).indexOf(samples.find(sample => sample.sampleName === reportName)); @@ -44,7 +44,7 @@ class MainContentSample extends Component { return samples[currentIndex]; } newWindow = () => { - window.open(window.location.href + `/preview`, "_blank", "noreferrer"); + window.open(window.location.href + `preview/`, "_blank", "noreferrer"); } setReportsHeight() { var style = document.getElementById('reports-style'); diff --git a/src/common/sidebar/sidebar.css b/src/common/sidebar/sidebar.css index 52124a0..5e8be3c 100644 --- a/src/common/sidebar/sidebar.css +++ b/src/common/sidebar/sidebar.css @@ -52,7 +52,7 @@ width: 90px; margin: 8px; background-image: url('./../../assets/sidebar/portrait.png'); - background-size: 100% 2100%; + background-size: 100% 2200%; } .ej-sidebar-content .ej-sb-toc .ej-sb-toc-card .ej-sb-toc-card-link{ diff --git a/src/common/sidebar/sidebar.js b/src/common/sidebar/sidebar.js index 1f60bd9..4c8d75d 100644 --- a/src/common/sidebar/sidebar.js +++ b/src/common/sidebar/sidebar.js @@ -24,7 +24,7 @@ class Sidebar extends Component {
{samples.map((sample, index) => (
- +
{sample.sampleName}
diff --git a/src/controls/designer/designer.js b/src/controls/designer/designer.js index 44532ff..bb6272b 100644 --- a/src/controls/designer/designer.js +++ b/src/controls/designer/designer.js @@ -35,11 +35,22 @@ var reportItemExtensions = [{ className: 'EJSignature', imageClass: 'customitem-signature', displayName: 'Electronic', - category: 'Signature', + category: 'Signatures', toolTip: { requirements: 'Add a report item to the designer area.', description: 'This report item is used to add a graphic signature.', - title: 'Signature' + title: 'Electronic Signature' + } +}, { + name: 'PDFSignature', + className: 'EJPDFSignature', + imageClass: 'customitem-pdfsignature', + displayName: 'PDF', + category: 'Signatures', + toolTip: { + requirements: 'Add a report item to the designer area.', + description: 'This report item is used to add a digital PDF signature.', + title: 'PDF Signature' } }, { name: 'Shape', diff --git a/src/controls/hr-payroll.js b/src/controls/hr-payroll.js new file mode 100644 index 0000000..693ab48 --- /dev/null +++ b/src/controls/hr-payroll.js @@ -0,0 +1,40 @@ +/* eslint-disable */ +import React, { Component } from 'react'; +import { Globals } from '../globals'; + +class HRPayroll extends Component { + render() { + if (this.props.content !== 'desc') { + return ( + + ) + } + else { + return ( +
+

+ The HR Payroll report provides a comprehensive overview of employee compensation, departmental performance, and leave management. It helps HR teams analyze payroll trends and make informed decisions. +

+
    +
  • Displays gross salary, net salary, and deductions across departments.
  • +
  • Visualizes Loss of Pay (LOP)breakdown by leave type: sick, good, and compensation leave.
  • +
  • Includes employee demographics such as gender distribution and contract types.
  • +
  • Summarizes leave availability for sick and casual leave by department.
  • +
  • Highlights average performance and employee count per department.
  • +
+

+ For more information on how dynamic image report items enhance customization in multi-company HR reports, refer to + this documentation section. +

+
+ ); + } + } +} +export default HRPayroll; \ No newline at end of file diff --git a/src/controls/multi-language-report.js b/src/controls/multi-language-report.js index eff9a86..022f27a 100644 --- a/src/controls/multi-language-report.js +++ b/src/controls/multi-language-report.js @@ -6,6 +6,17 @@ const parameterSettings = { } let didMount = true; let languagesList, languages; +const tooltipLocales = { + "en-US": { header: "Edit Report", content: "Edit this report in designer" }, + "fr-CA": { header: "Modifier le rapport", content: "Modifier ce rapport dans le concepteur" }, + "de-DE": { header: "Bericht bearbeiten", content: "Bearbeiten Sie diesen Bericht im Designer" }, + "hi-IN": { header: "रिपोर्ट संपादित करें", content: "इस रिपोर्ट को डिज़ाइनर में संपादित करें" }, + "es-ES": { header: "Editar informe", content: "Editar este informe en el diseñador" }, + "nl-NL": { header: "Rapport bewerken", content: "Bewerk dit rapport in de ontwerper" }, + "ko-KR": { header: "보고서 편집", content: "디자이너에서 이 보고서를 편집합니다" }, + "he-IL": { header: "ערוך דוח", content: "ערוך דוח זה במעצב" }, + "ru-RU": { header: "Редактировать отчет", content: "Редактировать этот отчет в дизайнере" } +}; class MultiLanguageReport extends Component { render() { @@ -84,11 +95,20 @@ class MultiLanguageReport extends Component { loadReport = () => { const reportViewer = $("#report-viewer").boldReportViewer("instance"); const selectedLanguageId = languages.value.toString(); + const tooltipData = tooltipLocales[selectedLanguageId]; const selectedLanguage = languagesList.find(lang => lang.languageId === selectedLanguageId); const parameters = [{ name: 'Language', labels: [selectedLanguage.Name], values: [selectedLanguage.Name] }]; reportViewer.model.parameters = parameters; reportViewer.reload(); reportViewer.setModel({'locale': selectedLanguageId}); + const item = reportViewer.model.toolbarSettings.customGroups[0].items[0]; + item.tooltip = { + header: tooltipData.header, + content: tooltipData.content + }; + } + componentWillUnmount() { + didMount = true; } } export default MultiLanguageReport; diff --git a/src/globals.js b/src/globals.js index f48e6c0..5e48dce 100644 --- a/src/globals.js +++ b/src/globals.js @@ -35,6 +35,7 @@ import TranscriptReport from './controls/transcript-report'; import CMRReport from './controls/cmr-report'; import InfographicsReport from './controls/infographics-report'; import DynamicLogos from './controls/dynamic-logos'; +import HRPayroll from './controls/hr-payroll'; import MultiLanguageReport from './controls/multi-language-report'; import rdlcData from './rdlcData' @@ -114,6 +115,7 @@ const SampleComponents = { CMRReport: CMRReport, InfographicsReport: InfographicsReport, DynamicLogos: DynamicLogos, + HRPayroll: HRPayroll, MultiLanguageReport: MultiLanguageReport } diff --git a/src/index.js b/src/index.js index 666b81c..181b294 100644 --- a/src/index.js +++ b/src/index.js @@ -27,6 +27,10 @@ import './controls/extensions/report-item-extensions/document.reportitem.css'; import { EJPdfDocument } from './controls/extensions/report-item-extensions/pdfdocument.reportitem'; import { EJHtmlDocument } from './controls/extensions/report-item-extensions/htmldocument.reportitem'; +//PDF Signature +import './controls/extensions/report-item-extensions/pdf.signature.reportitem.css'; +import { EJPDFSignature } from './controls/extensions/report-item-extensions/pdf.signature.reportitem'; + let barcode = 'EJBarcode'; let qrBarcode = 'EJQRBarcode'; window[barcode] = EJBarcode; @@ -45,6 +49,9 @@ let htmlDocument = 'EJHtmlDocument'; window[pdfDocument] = EJPdfDocument; window[htmlDocument] = EJHtmlDocument; +let pdfSignature = 'EJPDFSignature'; +window[pdfSignature] = EJPDFSignature; + //code-mirror import 'codemirror/lib/codemirror'; import 'codemirror/addon/hint/show-hint'; diff --git a/src/samples.json b/src/samples.json index d7d3811..6221a0c 100644 --- a/src/samples.json +++ b/src/samples.json @@ -74,7 +74,6 @@ "sampleName": "Sales Report", "basePath": "report-viewer", "directoryName": "sales-report", - "status": "Updated", "imageDetails": { "isLandscape": false, "index": 9 @@ -469,7 +468,6 @@ "sampleName": "Dynamic Logos", "basePath": "report-viewer", "directoryName": "dynamic-logos", - "status": "New", "imageDetails": { "isLandscape": false, "index": 19 @@ -483,7 +481,6 @@ "sampleName": "Multi Language Report", "basePath": "report-viewer", "directoryName": "multi-language-report", - "status": "New", "imageDetails": { "isLandscape": false, "index": 5 @@ -491,6 +488,20 @@ "metaData": { "description": "This demo showcases a Multi Language Report that allows users to view report in various languages using the React Bold Report Viewer." } + }, + { + "routerPath": "hr-payroll", + "sampleName": "HR Payroll", + "basePath": "report-viewer", + "directoryName": "hr-payroll", + "status": "New", + "imageDetails": { + "isLandscape": false, + "index": 20 + }, + "metaData": { + "description": "This demo showcases an HR Payroll report showing salaries, deductions, demographics, and performance insights in the React Bold Report Viewer." + } } ] }