PMA.UI Examples 2.43.3by Pathomation

QC Macro check

intermediateslide loadergallerymacroqc
Console
PMA.UI version: 2.43.3
Gallery & slide loader with macro image example
qc_macro_check.html
1<!doctype html>
2<html lang="en">
3
4<head>
5    <meta charset="utf-8">
6    <meta http-equiv="X-UA-Compatible" content="IE=10">
7    <meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width">
8
9    <!-- Include PMA.UI required libraries downloaded or from CDN -->
10    <script src="./pma.ui/jquery-3.1.0.js"></script>
11    <link href="./pma.ui/font-awesome.min.css" type="text/css" rel="stylesheet">
12
13    <!-- Include optional libraries downloaded or from CDN -->
14    <link rel="stylesheet" href="./pma.ui/bootstrap5.min.css">
15    <script src="./pma.ui/bootstrap5.bundle.min.js"></script>
16
17    <!-- Include PMA.UI script & css -->
18    <script src="./pma.ui/pma.ui.js"></script>
19    <link href="./pma.ui/pma.ui.css" type="text/css" rel="stylesheet">
20
21    <!-- Include custom script & css -->
22    <script src="./js/qc_macro_check.js"></script>
23    <link href="./css/qc_macro_check.css" type="text/css" rel="stylesheet">
24
25    <title>QC Macro check</title>
26</head>
27
28<body>
29    <div class="container-fluid">
30        <div class="row justify-content-center min-vh-100">
31            <div class="col">
32                <div class="d-flex flex-column h-100">
33                    <div class="row p-0 g-2 align-items-center">
34                        <div class="col-auto">
35                            <div id="gallery"></div>
36                        </div>
37                        <div class="col-auto d-flex flex-grow-1 justify-content-center aprroval-buttons hide">
38                            <div class="btn-group btn-group-lg" role="group" aria-label="Basic mixed styles example">
39                                <button type="button" class="btn btn-success"
40                                    onclick="showMessage(true)">Approve</button>
41                                <button type="button" class="btn btn-danger"
42                                    onclick="showMessage(false)">Reject</button>
43                            </div>
44                        </div>
45                    </div>
46                    <div class="row flex-grow-1">
47                        <!-- The element that will host annotation actions -->
48                        <div class="col-4 p-0">
49                            <div id="qc" class="hide w-100 h-100">
50                                <div id="macro_content_container" class="w-100 h-100">
51                                    <div id="mark_container_wrapper">
52                                        <div id="mark_container">
53                                            <div id="approve_mark" class="hide" aria-hidden="true"></div>
54                                            <div id="reject_mark" class="hide" aria-hidden="true"></div>
55                                        </div>
56                                    </div>
57                                    <div class="w-100 d-flex justify-content-center macro_link_wrapper">
58                                        <div class="macro_link_inner">
59                                            <a class="btn btn-secondary" id="macro_link" href="" target="_blank">
60                                                Open macro in new tab
61                                            </a>
62                                        </div>
63                                    </div>
64                                    <div id="macro-viewer"></div>
65                                </div>
66                            </div>
67                        </div>
68                        <div class="col p-0">
69                            <!-- The element that will host the slide loader -->
70                            <div id="viewer"></div>
71                        </div>
72                    </div>
73                </div>
74            </div>
75        </div>
76    </div>
77</body>
78
79</html>
qc_macro_check.css
1html,
2body {
3    height: 100%;
4    padding: 0px;
5    margin: 0px;
6    font-family: Arial, Helvetica, sans-serif;
7}
8
9body .pma-ui-viewport-container {
10    height: 100%;
11    width: 100%;
12}
13
14.mark-container {
15    position: relative;
16    height: 0;
17}
18
19.mark-container .mark-container-inner {
20    position: absolute;
21    bottom: 0;
22    right: 0;
23}
24
25#mark_container_wrapper {
26    position: relative;
27    height: 0;
28}
29
30#mark_container {
31    position: absolute;
32    top: 0;
33    right: 0;
34    z-index: 10;
35}
36
37#approve_mark {
38    border-top: 2vw solid rgba(65, 155, 69, 1);
39    border-left: 2vw solid rgba(255, 255, 255, 0);
40}
41
42#reject_mark {
43    border-top: 2vw solid rgba(247, 11, 0, 1);
44    border-left: 2vw solid rgba(255, 255, 255, 0);
45}
46
47#macro-viewer .ol-zoom.ol-control {
48    display: none;
49}
50
51.macro_link_wrapper {
52    position: relative;
53    height: 0;
54}
55
56.macro_link_inner {
57    position: absolute;
58    z-index: 10;
59}
qc_macro_check.js
1// Initial declarations
2var serverUrl = "https://host.pathomation.com/pma.core.3/";
3var serverUsername = "PMA_UI_demo";
4var serverPassword = "PMA_UI_demo";
5var galleryElementSelector = "#gallery";
6var slideLoaderElementSelector = "#viewer";
7var qcElementSelector = "#qc";
8var macroContainerElementSelector = "#macro_content_container";
9var macroElementSelector = "#macro_content";
10var figureMacroElementSelector = "#macro_figure";
11var macroLinkElementSelector = "#macro_link";
12var messageContentElementSelector = "#message_content";
13var approvalMessageContainerElementSelector = "#approval_message_container";
14var approveMarkElementSelector = "#approve_mark";
15var rejectMarkElementSelector = "#reject_mark";
16var caller = "DemoPortal";
17var galleryMode = "horizontal";
18var directoryPath = "Reference/Hamamatsu/Demo";
19var thumbnailWidth = 150;
20var thumbnailHeight = 100;
21var slideName = "Slide Name";
22var selectedSlideIndex = null;
23var statusSlideKey = null;
24var macroMagnifyImg = null;
25var macroViewport = null;
26
27// Message functionality →
28function showMessage(isApproved) {
29    let approval = isApproved ? "Approved" : "Denied";
30
31    if (statusSlideKey === null) {
32        $(approveMarkElementSelector).addClass("hide");
33        $(rejectMarkElementSelector).addClass("hide");
34
35        alert(`Please, select a slide in the gallery.`);
36        return;
37    } else {
38        let slideIndex = statusSlideKey.split("_").slice(-1)[0];
39        let galleryListItem = $(`#gallery ul li:eq(${slideIndex})`);
40        let statusUpIcon = `<div id=${statusSlideKey + "_up"} class="mark-container">
41        <div class="mark-container-inner">
42            <i class="fa fa-check-square mark text-success bg-white rounded" aria-hidden="true"></i>
43        </div>
44    </div>`;
45        let statusDownIcon = `<div id=${statusSlideKey + "_down"} class="mark-container">
46        <div class="mark-container-inner">
47            <i class="fa fa-window-close mark text-danger bg-white rounded" aria-hidden="true"></i>
48        </div>
49    </div>`;
50
51        if (isApproved) {
52            window.sessionStorage.setItem(statusSlideKey, "true");
53
54            $(approveMarkElementSelector).removeClass("hide");
55            $(rejectMarkElementSelector).addClass("hide");
56
57            $(`#${statusSlideKey}_down`).remove();
58            galleryListItem.append(statusUpIcon);
59        } else {
60            window.sessionStorage.setItem(statusSlideKey, "false");
61
62            $(approveMarkElementSelector).addClass("hide");
63            $(rejectMarkElementSelector).removeClass("hide");
64
65            $(`#${statusSlideKey}_up`).remove();
66            galleryListItem.append(statusDownIcon);
67        }
68    }
69
70    if (slideName !== "Slide Name") {
71        console.log(`The ${slideName} slide has been ${approval}.`);
72    } else {
73        alert(`Please, select a slide in the gallery.`);
74    }
75}
76// Message functionality ←
77
78jQuery(function () {
79    console.log(`PMA.UI version: ${PMA.UI.getVersion()}`);
80
81    // Create a context
82    var context = new PMA.UI.Components.Context({ caller: caller });
83
84    // Add an autologin authentication provider
85    new PMA.UI.Authentication.AutoLogin(context, [{ serverUrl: serverUrl, username: serverUsername, password: serverPassword }]);
86
87    // Create a gallery that will display the slides
88    var gallery = new PMA.UI.Components.Gallery(context, {
89        element: galleryElementSelector,
90        thumbnailWidth: thumbnailWidth,
91        thumbnailHeight: thumbnailHeight,
92        mode: galleryMode,
93        barcodeRotation: 90,
94    });
95
96    // Create an image loader that will allow us to load images easily
97    var slideLoader = new PMA.UI.Components.SlideLoader(context, {
98        element: slideLoaderElementSelector,
99        overview: false,
100        barcode: {
101            collapsed: false,
102            rotation: 90,
103        },
104        position: {
105            rotation: 1.570796325,
106        },
107    });
108
109    // Load the contents of a directory
110    gallery.loadDirectory(serverUrl, directoryPath, function () {
111        let sessStorage = window.sessionStorage;
112
113        for (let i = 0; i < sessStorage.length; i++) {
114            const key = sessStorage.key(i);
115
116            if (key.includes("status_")) {
117                let statusSlide = window.sessionStorage.getItem(key);
118                let slideIndex = key.split("_").slice(-1)[0];
119                let galleryListItem = $(`#gallery ul li:eq(${slideIndex})`);
120                let statusUpIcon = `<div id=${key + "_up"} class="mark-container">
121                <div class="mark-container-inner">
122                    <i class="fa fa-check-square mark text-success bg-white rounded" aria-hidden="true"></i>
123                </div>
124            </div>`;
125                let statusDownIcon = `<div id=${key + "_down"} class="mark-container">
126                <div class="mark-container-inner">
127                    <i class="fa fa-window-close mark text-danger bg-white rounded" aria-hidden="true"></i>
128                </div>
129            </div>`;
130
131                // Check the status of the slides and show status if possible
132                if (statusSlide === "true") {
133                    $(`#${key}_down`).remove();
134                    galleryListItem.append(statusUpIcon);
135                } else {
136                    if (statusSlide === "false") {
137                        $(`#${key}_up`).remove();
138                        galleryListItem.append(statusDownIcon);
139                    }
140                }
141            }
142        }
143
144        $(".aprroval-buttons").removeClass("hide");
145    });
146
147    // Listen for the slide selected event by the gallery
148    gallery.listen(PMA.UI.Components.Events.SlideSelected, function (args) {
149        console.log("Slide selected");
150        console.log(args);
151
152        // Status check →
153        // Set the index of the selected slide as value of the selectedSlideIndex variable
154        selectedSlideIndex = String(args.index);
155
156        // Get the approval status of the selected slide
157        statusSlideKey = "status_" + selectedSlideIndex;
158        let statusSelectedSlide = window.sessionStorage.getItem(statusSlideKey);
159
160        // Check the status of the selected slide and show status if needed
161        if (statusSelectedSlide === null) {
162            $(approveMarkElementSelector).addClass("hide");
163            $(rejectMarkElementSelector).addClass("hide");
164        } else {
165            if (statusSelectedSlide === "true") {
166                $(approveMarkElementSelector).removeClass("hide");
167                $(rejectMarkElementSelector).addClass("hide");
168            } else {
169                if (statusSelectedSlide === "false") {
170                    $(approveMarkElementSelector).addClass("hide");
171                    $(rejectMarkElementSelector).removeClass("hide");
172                }
173            }
174        }
175        // Status check ←
176
177        // Parse the slide name from the path
178        slideName = args.path.split("/").slice(-1)[0];
179
180        // Load the image selected from treeview
181        slideLoader.load(serverUrl, args.path);
182    });
183
184    // Listen for the slide deselected event by the gallery
185    gallery.listen(PMA.UI.Components.Events.SlideDeSelected, function (args) {
186        console.log("Slide deselected");
187        console.log(args);
188
189        // Clear approval state
190        statusSlideKey = null;
191
192        // Clear slide loader
193        slideLoader.load(serverUrl, null);
194
195        // Hide macro
196        $(qcElementSelector).addClass("hide");
197    });
198
199    // Listen for the slide loaded event by the slide loader
200    slideLoader.listen(PMA.UI.Components.Events.SlideLoaded, function (args) {
201        console.log("Slide loaded");
202        console.log(args);
203
204        if (!slideLoader.mainViewport) {
205            return;
206        }
207
208        const urlQuery = "?SessionID=" + slideLoader.mainViewport.getSessionID() + "&pathOrUid=" + args.path;
209        const macroImg = `${serverUrl}macro${urlQuery}`;
210
211        // Set the link to the Macro
212        $(macroLinkElementSelector).attr("href", macroImg);
213
214        // Show the Macro image
215        $(qcElementSelector).removeClass("hide");
216
217        macroViewport = new PMA.UI.View.Viewport(
218            {
219                element: "#macro-viewer",
220                referenceImage: {
221                    src: macroImg,
222                    width: 1000,
223                    height: 333,
224                    backgroundColor: "#ffffff",
225                },
226                digitalZoomLevels: 5,
227                overview: false,
228                dimensions: false,
229                barcode: false,
230                rotationControl: false,
231                filename: false,
232                scaleLine: false,
233                fullscreenControl: false,
234                loadingBar: false,
235                zoomSlider: false,
236                position: {
237                    rotation: 1.570796325,
238                }
239            },
240        );
241    });
242
243    // Listen for the slide info error event by slide loader
244    slideLoader.listen(PMA.UI.Components.Events.SlideInfoError, function (args) {
245        console.log("Slide info error");
246        console.log(args);
247    });
248});