Skip to content

task/FOUR-18749: Added print-pdf Blade layout #7451

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Oct 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
191 changes: 191 additions & 0 deletions resources/js/print-layout.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
import { BNavbar } from "bootstrap-vue";
import { Multiselect } from "@processmaker/vue-multiselect";
import moment from "moment-timezone";
import { sanitizeUrl } from "@braintree/sanitize-url";
import VueHtml2Canvas from "vue-html2canvas";
import Sidebaricon from "./components/Sidebaricon";
import SelectStatus from "./components/SelectStatus";
import SelectUser from "./components/SelectUser";
import SelectUserGroup from "./components/SelectUserGroup";
import CategorySelect from "./processes/categories/components/CategorySelect";
import ProjectSelect from "./components/shared/ProjectSelect";
import SelectFromApi from "./components/SelectFromApi";
import Breadcrumbs from "./components/Breadcrumbs";
import TimelineItem from "./components/TimelineItem";
import Required from "./components/shared/Required";
import { FileUpload, FileDownload } from "./processes/screen-builder/components";
import RequiredCheckbox from "./processes/screen-builder/components/inspector/RequiredCheckbox";
import WelcomeModal from "./Mobile/WelcomeModal";
/** ****
* Global adjustment parameters for moment.js.
*/
import __ from "./modules/lang";

require("bootstrap");

const { Vue } = window;

Vue.use(VueHtml2Canvas);

if (window.ProcessMaker && window.ProcessMaker.user) {
moment.tz.setDefault(window.ProcessMaker.user.timezone);
moment.defaultFormat = window.ProcessMaker.user.datetime_format;
moment.defaultFormatUtc = window.ProcessMaker.user.datetime_format;
}
if (document.documentElement.lang) {
moment.locale(document.documentElement.lang);
window.ProcessMaker.user.lang = document.documentElement.lang;
}
Vue.prototype.moment = moment;
// initializing global instance of a moment object
window.moment = moment;
/** ***** */

Vue.prototype.$sanitize = sanitizeUrl;

Vue.component("Multiselect", Multiselect);
Vue.component("Sidebaricon", Sidebaricon);
Vue.component("SelectStatus", SelectStatus);
Vue.component("SelectUser", SelectUser);
Vue.component("SelectUserGroup", SelectUserGroup);
Vue.component("CategorySelect", CategorySelect);
Vue.component("ProjectSelect", ProjectSelect);
Vue.component("SelectFromApi", SelectFromApi);
Vue.component("FileUpload", FileUpload);
Vue.component("FileDownload", FileDownload);
Vue.component("RequiredCheckbox", RequiredCheckbox);
Vue.component("Breadcrumbs", Breadcrumbs);
Vue.component("TimelineItem", TimelineItem);
Vue.component("Required", Required);
Vue.component("Welcome", WelcomeModal);

// Event bus ProcessMaker
window.ProcessMaker.events = new Vue();

window.ProcessMaker.nodeTypes = [];
window.ProcessMaker.nodeTypes.get = function (id) {
return this.find((node) => node.id === id);
};

// Assign our navbar component to our global ProcessMaker object
window.ProcessMaker.navbar = {};

// Set our own specific alert function at the ProcessMaker global object that could
// potentially be overwritten by some custom theme support
window.ProcessMaker.navbar.alerts = [];
window.ProcessMaker.alert = function (msg, variant, showValue = 5, stayNextScreen = false, showLoader = false, msgLink = "", msgTitle = "") {
if (showValue === 0) {
// Just show it indefinitely, no countdown
showValue = true;
}
// amount of items allowed in array
if (ProcessMaker.navbar.alerts.length > 5) {
ProcessMaker.navbar.alerts.shift();
}
ProcessMaker.navbar.alerts.push({
alertText: msg,
alertLink: msgLink,
alertTitle: msgTitle,
alertShow: showValue,
alertVariant: String(variant),
showLoader,
stayNextScreen,
timestamp: Date.now(),
});
};

// Set out own specific confirm modal.
window.ProcessMaker.confirmModal = function (title, message, variant, callback, size = "md", dataTestClose = "confirm-btn-close", dataTestOk = "confirm-btn-ok") {
ProcessMaker.navbar.confirmTitle = title || __("Confirm");
ProcessMaker.navbar.confirmMessage = message || __("Are you sure you want to delete?");
ProcessMaker.navbar.confirmVariant = variant;
ProcessMaker.navbar.confirmCallback = callback;
ProcessMaker.navbar.confirmShow = true;
ProcessMaker.navbar.confirmSize = size;
ProcessMaker.navbar.confirmDataTestClose = dataTestClose;
ProcessMaker.navbar.confirmDataTestOk = dataTestOk;
};

// Set out own specific message modal.
window.ProcessMaker.messageModal = function (title, message, variant, callback) {
ProcessMaker.navbar.messageTitle = title || __("Message");
ProcessMaker.navbar.messageMessage = message || __("");
ProcessMaker.navbar.messageVariant = variant;
ProcessMaker.navbar.messageCallback = callback;
ProcessMaker.navbar.messageShow = true;
};

// flags print forms
window.ProcessMaker.apiClient.requestCount = 0;
window.ProcessMaker.apiClient.requestCountFlag = false;

window.ProcessMaker.apiClient.interceptors.request.use((request) => {
// flags print forms
if (window.ProcessMaker.apiClient.requestCountFlag) {
window.ProcessMaker.apiClient.requestCount++;
}

window.ProcessMaker.EventBus.$emit("api-client-loading", request);
return request;
});

window.ProcessMaker.apiClient.interceptors.response.use((response) => {
// TODO: this could be used to show a default "created/upated/deleted resource" alert
// response.config.method (PUT, POST, DELETE)
// response.config.url (extract resource name)
window.ProcessMaker.EventBus.$emit("api-client-done", response);
// flags print forms
if (window.ProcessMaker.apiClient.requestCountFlag && window.ProcessMaker.apiClient.requestCount > 0) {
window.ProcessMaker.apiClient.requestCount--;
}
return response;
}, (error) => {
// Set in your .catch to false to not show the alert inside window.ProcessMaker.apiClient
if (!error?.response?.showAlert) {
return Promise.reject(error);
}

if (error.code && error.code === "ERR_CANCELED") {
return Promise.reject(error);
}
window.ProcessMaker.EventBus.$emit("api-client-error", error);
if (error.response && error.response.status && error.response.status === 401) {
// stop 401 error consuming endpoints with data-sources
const { url } = error.config;
if (url.includes("/data_sources/")) {
if (url.includes("requests/") || url.includes("/test")) {
throw error;
}
}
window.location = "/login";
} else {
if (_.has(error, "config.url") && !error.config.url.match("/debug")) {
window.ProcessMaker.apiClient.post("/debug", {
name: "Javascript ProcessMaker.apiClient Error",
message: JSON.stringify({
message: error.message,
code: error.code,
config: error.config,
}),
});
}
return Promise.reject(error);
}
});

// Display any uncaught promise rejections from axios in the Process Maker alert box
window.addEventListener("unhandledrejection", (event) => {
const error = event.reason;
if (error.config && error.config._defaultErrorShown) {
// Already handeled
event.preventDefault(); // stops the unhandled rejection error
} else if (error.response && error.response.data && error.response.data.message) {
if (!(error.code && error.code === "ECONNABORTED")) {
window.ProcessMaker.alert(error.response.data.message, "danger");
}
} else if (error.message) {
if (!(error.code && error.code === "ECONNABORTED")) {
window.ProcessMaker.alert(error.message, "danger");
}
}
});
142 changes: 142 additions & 0 deletions resources/views/layouts/print.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
<!DOCTYPE html>
<html lang="{{ app()->getLocale() }}">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta http-equiv="Content-Security-Policy"
content="script-src * 'unsafe-inline' 'unsafe-eval';
object-src 'self';
worker-src 'self' blob:;">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="csrf-token" content="{{ csrf_token() }}">
<meta name="is-prod" content="{{ config('app.env') == 'production' ? 'true' : 'false' }}">
<meta name="app-url" content="{{ config('app.url') }}">
<meta name="open-ai-nlq-to-pmql" content="{{ config('app.open_ai_nlq_to_pmql') }}">
<meta name="i18n-mdate" content='{!! json_encode(ProcessMaker\i18nHelper::mdates()) !!}'>
<meta name="screen-cache-enabled" content="{{ config('app.screen.cache_enabled') ? 'true' : 'false' }}">
<meta name="screen-cache-timeout" content="{{ config('app.screen.cache_timeout') }}">
@if(Auth::user())
<meta name="user-id" content="{{ Auth::user()->id }}">
<meta name="user-full-name" content="{{ Auth::user()->fullname }}">
<meta name="user-avatar" content="{{ Auth::user()->avatar }}">
<meta name="datetime-format" content="{{ Auth::user()->datetime_format ?: config('app.dateformat') }}">
<meta name="timezone" content="{{ Auth::user()->timezone ?: config('app.timezone') }}">
@yield('meta')
@endif
<meta name="timeout-worker" content="{{ mix('js/timeout.js') }}">
<meta name="timeout-length" content="{{ Session::has('rememberme') && Session::get('rememberme') ? "Number.MAX_SAFE_INTEGER" : config('session.lifetime') }}">
<meta name="timeout-warn-seconds" content="{{ config('session.expire_warning') }}">
@if(Session::has('_alert'))
<meta name="alert" content="show">
@php
list($type,$message) = json_decode(Session::get('_alert'));
Session::forget('_alert');
@endphp
<meta name="alertVariant" content="{{$type}}">
<meta name="alertMessage" content="{{$message}}">
@endif
<title>@yield('title',__('Welcome')) - {{ __('ProcessMaker') }}</title>
<link rel="icon" type="image/png" sizes="16x16" href="{{ \ProcessMaker\Models\Setting::getFavicon() }}">
<link href="{{ mix('css/app.css') }}" rel="stylesheet">
<link href="/css/bpmn-symbols/css/bpmn.css" rel="stylesheet">
@yield('css')
<script type="text/javascript">
@if(Auth::user())
window.Processmaker = {
csrfToken: "{{csrf_token()}}",
userId: "{{\Auth::user()->id}}",
messages: [],
apiTimeout: {{config('app.api_timeout')}}
};
@if(config('broadcasting.default') == 'redis')
window.Processmaker.broadcasting = {
broadcaster: "socket.io",
host: "{{config('broadcasting.connections.redis.host')}}",
key: "{{config('broadcasting.connections.redis.key')}}"
};
@endif
@if(config('broadcasting.default') == 'pusher')
window.Processmaker.broadcasting = {
broadcaster: "pusher",
key: "{{config('broadcasting.connections.pusher.key')}}",
cluster: "{{config('broadcasting.connections.pusher.options.cluster')}}",
forceTLS: {{config('broadcasting.connections.pusher.options.use_tls') ? 'true' : 'false'}},
debug: {{config('broadcasting.connections.pusher.options.debug') ? 'true' : 'false'}},
enabledTransports: ['ws', 'wss'],
disableStats: true,
};
@if(config('broadcasting.connections.pusher.options.host'))
window.Processmaker.broadcasting.wsHost = "{{config('broadcasting.connections.pusher.options.host')}}";
window.Processmaker.broadcasting.wsPort = "{{config('broadcasting.connections.pusher.options.port')}}";
window.Processmaker.broadcasting.wssPort = "{{config('broadcasting.connections.pusher.options.port')}}";
@endif
@endif
@endif
</script>
@isset($addons)
<script>
var addons = [];
</script>
@foreach ($addons as $addon)
@if (!empty($addon['script']))
{!! $addon['script'] !!}
@endif
@endforeach
@endisset
@if (config('global_header'))
<!-- Start Global Header -->
{!! config('global_header') !!}
<!-- End Global Header -->
@endif
</head>
<body>
<a class="skip-navigation alert alert-info" role="link" href="#main" tabindex="1">{{ __('Skip to Content') }}</a>
<div class="d-flex w-100 mw-100 h-100 mh-100" id="app-container">
<div class="d-flex flex-grow-1 flex-column overflow-hidden">
<div class="flex-grow-1 d-flex flex-column overflow-hidden h-100" id="mainbody">
<div
id="main"
class="main flex-grow-1 h-100
{{$content_margin ?? 'overflow-auto'}}
{{$content_margin ?? 'py-3'}}">
@yield('content')
</div>
</div>
</div>
</div>
<div id="navbar" style="display: none;"></div>
<div id="api-error" class="error-content">
<div>
<h1>{{__('Sorry! API failed to load')}}</h1>
<p>{{__('Something went wrong. Try refreshing the application')}}</p>
</div>
</div>
<!-- Scripts -->
@if(config('broadcasting.default') == 'redis')
<script src="{{config('broadcasting.connections.redis.host')}}/socket.io/socket.io.js"></script>
@endif
<script src="{{ mix('js/manifest.js') }}"></script>
<script src="{{ mix('js/vendor.js') }}"></script>
<script src="{{ mix('js/app.js') }}"></script>
<script>
window.ProcessMaker.packages = @json(\App::make(ProcessMaker\Managers\PackageManager::class)->listPackages());
</script>
<script src="{{ mix('js/print-layout.js') }}"></script>
@include('shared.monaco')
@foreach(GlobalScripts::getScripts() as $script)
<script src="{{$script}}"></script>
@endforeach
@isset($addons)
@foreach ($addons as $addon)
@if (!empty($addon['script_mix']))
<script type="text/javascript" src="{{ mix($addon['script_mix'][0], $addon['script_mix'][1]) }}"></script>
@endif
@if (!empty($addon['script_mix_module']))
<script type="module" src="{{ mix($addon['script_mix_module'][0], $addon['script_mix_module'][1]) }}"></script>
@endif
@endforeach
@endisset
<!--javascript!-->
@yield('js')
</body>
</html>
1 change: 1 addition & 0 deletions webpack.mix.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ mix
.copy("node_modules/bpmn-font/dist", "public/css/bpmn-symbols");

mix
.js("resources/js/print-layout.js", "public/js")
.js("resources/js/app-layout.js", "public/js")
.js("resources/js/process-map-layout.js", "public/js")
.js("resources/js/processes/modeler/index.js", "public/js/processes/modeler")
Expand Down
Loading