Failed to execute template. Cause: [Access denied when checking [script] access to [xwiki:Collaboratory.UX.HbpSkin.WebHome] for user [xwiki:XWiki.Admin]]. Click on this message for details.

ExternalApps - HBP Wiki

IAM21 instance, do not create collab nor modify a team, your changes will be lost


Wiki source code of ExternalApps

Version 2.195 by bougault on 2019/05/17 10:51

Hide last authors
bougault 1.5 1 {{velocity}}
bougault 2.195 2 #set ($discard = $doc.use('InstalledApp.Code.InstalledAppClass'))
bougault 2.112 3 #set($query = 'select doc from Document doc, doc.object(ExternalApps.Code.ExternalAppsClass) as app')
bougault 2.114 4 #set($applications = $services.query.xwql($query).addFilter('hidden').execute())
bougault 2.195 5 #if ($xcontext.action == 'edit')
6 #set ($discard = $xwiki.ssx.use('Collaboratory.Apps.IFrameApp.Code.IFrameAppCss'))
7 #set ($discardjs = $xwiki.jsx.use('Collaboratory.Apps.IFrameApp.Code.IFrameAppJs'))
bougault 2.50 8
bougault 2.195 9 #macro( applications $applications)
10 <div class="applications">
11 #foreach($application in $applications)
12 #set($selectField = $application.toString().concat('-selected'))
13 #set($detailsField = $application.toString().concat('-details'))
14 <div class="application">
15 ## TODO: if not in edit mode, do not define the input + fieldname
16 <input type="radio" data-type="select" name="InstalledApp.Code.InstalledAppClass_0_app" id="$selectField" value="$application" />
17 <input type="checkbox" data-type="details" name="detailedView" id="$detailsField" />
18 <label for="$detailsField" class="details-overlay"></label>
19 #application( $application $selectField $detailsField)
20 </div>
21 #end
22 </div>
23 #end
24
25 #macro( application $application $selectField $detailsField)
26 #set($app = $xwiki.getDocument($application))
27 #set($title = $app.getDisplayTitle())
28 <div class="application-content">
29 #if($app.getAttachment('logo.png').isImage())
30 <img src="$app.getAttachmentURL('logo.png')" width="75" height="75" alt="$app.getValue('title').replace('"', '\"')">
31 #else
32 <img
33 src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mN89x8AAuEB74Y0o2cAAAAASUVORK5CYII="
34 width="75"
35 height="75"
36 alt=""
37 >
38 #end
39 <div class="tags"><span>$app.getValue('category')</span></div>
40 <h3 class="title">$title</h3>
41 <p class="description">$!app.getValue('description')</p>
42 <div class="application-buttons">
43 <label for="$detailsField" class="btn label-more"></label>
44 <label for="$selectField" class="btn btn-primary choose-app">Choose this App</label>
45 </div>
46 <div class="details">
47 <h4>Maintainers</h4>
48 [list of maintainers]
49 <h4>Documentation</h4>
50 App documentation link
51 <h4>URL</h4>
52 $app.getValue('url')
53 </div>
54 </div>
55 #end
56
57 {{html wiki="true"}}
58 (% class="xform" %)
59 (((
60 ; <label#if ($xcontext.action == 'edit') for="ExternalApps.Code.ExternalAppsClass_0_title"#end>$escapetool.xml($doc.displayPrettyName('title', false, false))</label>##
61 (% class="xHint" %)$services.localization.render('Required. This is how the item will be displayed in the navigation')
62 : $doc.display('title')
63 )))
64 {{/html}}
65
66 {{html clean="false"}}
67
68 ##{{html clean="false"}}
69 ##set ($displayDocExtra = false)
bougault 2.121 70 <style>
bougault 2.195 71 #document-title {
72 visibility: hidden;
73 }
74
bougault 2.179 75 .applications {
76 display: grid;
bougault 2.195 77 grid-gap: 20px;
bougault 2.179 78 }
79
bougault 2.182 80 @media screen and (min-width: 640px) {
bougault 2.183 81 .applications {
82 grid-template-columns: 1fr 1fr;
83 }
bougault 2.182 84 }
bougault 2.184 85 /*
bougault 2.182 86 @media screen and (min-width: 900px) {
bougault 2.183 87 .applications {
88 grid-template-columns: 1fr 1fr 1fr;
89 }
bougault 2.182 90 }
bougault 2.184 91 */
bougault 2.182 92
93 @media screen and (min-width: 1200px) {
bougault 2.183 94 .applications {
bougault 2.185 95 grid-template-columns: 1fr 1fr 1fr;
bougault 2.183 96 }
bougault 2.182 97 }
98
99 @media screen and (min-width: 1800px) {
bougault 2.183 100 .applications {
bougault 2.185 101 grid-template-columns: 1fr 1fr 1fr 1fr;
bougault 2.183 102 }
bougault 2.182 103 }
bougault 2.195 104 .application {
105 background: var(--color-support-light);
106 }
bougault 2.182 107
bougault 2.195 108 .application-content {
bougault 2.121 109 border: 1px solid var(--color-support-light);
bougault 2.195 110 background: var(--color-white);
bougault 2.125 111 padding: 1rem;
bougault 2.181 112 height: 100%;
bougault 2.195 113 font-weight: normal;
114 display: block;
115 position: relative;
116 padding-bottom: 3rem;
bougault 2.121 117 }
bougault 2.146 118
bougault 2.195 119 .application-content .details {
120 display: none;
121 }
122
123
124 .application .application-buttons {
125 display: flex;
126 position: absolute;
127 bottom: 0px;
128 left: 0;
129 right:0;
130 }
131
132 .application .application-buttons .btn {
133 width: 50%;
134 margin: 0;
135 border-radius: 0 !important;
136 }
137
bougault 2.146 138 .application img {
bougault 2.148 139 display: block;
bougault 2.170 140 margin: 0 auto 1.5rem auto;
bougault 2.146 141 }
bougault 2.149 142
143 .application .title {
144 text-align: center;
bougault 2.153 145 height: 3em;
bougault 2.149 146 }
bougault 2.160 147
bougault 2.167 148 .application .tags {
149 display: flex;
bougault 2.169 150 justify-content: space-around;
bougault 2.171 151 margin-bottom: 1.5rem;
bougault 2.167 152 }
153
154 .application .tags span {
bougault 2.160 155 font-size: .8rem;
bougault 2.174 156 border: 1px solid var(--color-support-dark);
bougault 2.175 157 padding: .2rem .3rem;
bougault 2.163 158 border-radius: var(--border-radius-default);
bougault 2.160 159 }
bougault 2.177 160
161 .application .description {
162 text-align: center;
163 }
bougault 2.195 164
165 .applications input[type="radio"],
166 .applications input[type="checkbox"]{
167 display: none;
168 }
169
170
171 .applications input[data-type="select"]:checked ~ div.application-content {
172 border: 1px solid var(--color-primary);
173 }
174
175
176 .applications input[data-type="details"]:checked ~ div.application-content {
177 position: fixed;
178 top: 50%;
179 left: 50%;
180 width: 80vw;
181 height: 80vh;
182 margin-left:-40vw;
183 margin-top: -40vh;
184 background: #FFF;
185 z-index: 255;
186 overflow: auto;
187 }
188
189 .label-more {
190 cursor: zoom-in;
191 }
192 .label-more::before {
193 content: "More";
194 }
195 .applications input[data-type="details"]:checked ~ .application-content .details {
196 display: block;
197 }
198
199 .details-overlay {
200 display: none;
201 cursor: zoom-out;
202 }
203
204 .applications input[data-type="details"]:checked ~ .details-overlay {
205 width:100vw;
206 height: 100vh;
207 background: var(--color-support-dark);
208 opacity: .7;
209 content: '';
210 display: block;
211 position: fixed;
212 margin: 0;
213 top:0;
214 left:0;
215 z-index: 254;
216 }
217
218 .applications input[data-type="details"]:checked ~ div .label-more {
219 cursor: zoom-out;
220 }
221 .applications input[data-type="details"]:checked ~ div .label-more::before {
222 content:"Close";
223 }
bougault 2.121 224 </style>
225
226
bougault 2.187 227
bougault 2.195 228 <div class="xform">
229 <dl>
230 <dt>
231 <label>Choose an application in the list below</label>
232 <dt>
233 </dl>
234 </div>
bougault 2.187 235
bougault 2.195 236 #applications( $applications )
237
238 <script>
239 document.addEventListener('DOMContentLoaded', function() {
240 let saveAndView = document.querySelector('input[name="action_save"]');
241 Array.from(document.querySelectorAll('label.choose-app')).forEach(function(button){
242 button.addEventListener('click', function() { setTimeout(function() { saveAndView.click() }, 250)});
243 });
244 });
245 </script>
246
247 {{/html}}
248 #else
249 ##set($discard = $doc.use('InstalledApp.Code.InstalledAppClass'))
250 #set($appId = $doc.display('app'))
251 #set($app = $xwiki.getDocument($appId))
252 #*{{html clean="false"}}
253 <style>
254 #external-app {
255 width: 100%;
256 height: 100vh;
257 }
258 </style>
259 <iframe id="external-app" src="$app.getValue('url')"></iframe>
260 {{/html}}
261 *#
262
263 {{html clean="false"}}
264 #set ($discard = $xwiki.ssx.use('Collaboratory.Apps.IFrameApp.Code.IFrameAppCss'))
265 #set ($discardjs = $xwiki.jsx.use('Collaboratory.Apps.IFrameApp.Code.IFrameAppJs'))
266 <style>
267 #iframeApp-container {
268 background: #FFF;
269 }
270 </style>
271
272 <div id="iframeApp-container">
273 <div class="app-toolbar">
274 <button id="iframeApp-fullscreen"><span class="fa fa-arrows-alt"></span></button>
bougault 2.120 275 </div>
bougault 2.195 276 <iframe id="iframeApp" src="$app.get('url')"></iframe>
bougault 2.120 277 </div>
bougault 1.5 278 {{/html}}
bougault 2.195 279 #end
280
bougault 1.5 281 {{/velocity}}