Änderungen von Dokument Solr Search

Zuletzt geändert von Daniel Herrmann am 2026/02/04 20:23

Von Version 1.1 Icon
bearbeitet von admin
am 2025/02/23 19:33
Änderungskommentar: Install extension [org.xwiki.platform:xwiki-platform-search-solr-ui/17.0.0]
Auf Version Icon 2.1 Icon
bearbeitet von Daniel Herrmann
am 2025/12/16 11:14
Änderungskommentar: Install extension [org.xwiki.platform:xwiki-platform-search-solr-ui/17.10.0]

Zusammenfassung

Details

Icon Seiteneigenschaften
Dokument-Autor
... ... @@ -1,1 +1,1 @@
1 -XWiki.admin
1 +XWiki.dherrman
Icon XWiki.JavaScriptExtension[0]
Code
... ... @@ -1,11 +1,7 @@
1 1  require(['jquery', 'xwiki-events-bridge'], function($) {
2 2   var enhanceSearchResultHighlights = function() {
3 - var highlights = $(this).removeClass('hidden').parent().prev('.search-result-highlights').addClass('preview');
3 + const highlights = $(this).removeClass('hidden').prev('.search-result-highlights').addClass('preview');
4 4  
5 - // Workaround for IE8 which doesn't support :first-of-type CSS selector.
6 - highlights.find('.search-result-highlight').first().addClass('first').parent('dd').addClass('first')
7 - .prev('dt').addClass('first');
8 -
9 9   $(this).one('click', function(event) {
10 10   event.preventDefault();
11 11   $(event.target).remove();
... ... @@ -37,10 +37,16 @@
37 37   }
38 38   };
39 39  
40 - var addFacetValueCheckbox = function(index) {
36 + var addFacetValueCheckbox = function() {
41 41   // Create an id unique to the facet value.
42 42   let facetContainer = $(this).parents('.search-facet').first();
43 - $(this).attr('id', facetContainer.attr('data-name') + '-' + index.toString());
39 + // We need the ids of the target facet elements to stay stable through the change, in order to refocus the item
40 + // that was clicked and triggered the change.
41 + // We use the JQuery index, so that id indexes are reset across facetContainers.
42 + // This allows for stable indexes: when reloading the facets after changing the filter for the target facet X,
43 + // the ids of all the checkbox for the target facet X will keep the same index.
44 + // This property is lost if multiple facets are changed in the query at once.
45 + $(this).attr('id', facetContainer.attr('data-name') + '-' + facetContainer.find('a.itemName').index($(this)));
44 44   // Initialize the checkbox.
45 45   let checkBox = $(document.createElement('input')).attr('type', 'checkbox');
46 46   checkBox.attr('aria-labelledby', $(this).attr('id'));
... ... @@ -68,7 +68,7 @@
68 68   updateExpandCollapseAllFacetsState(facetsContainer);
69 69  
70 70   // Expand/Collapse toggle for each facet.
71 - facetsContainer.find('.facet-toggler').on('click', function(event) {
73 + facetsContainer.find('.facet-toggle').on('click', function(event) {
72 72   $(event.target).parents('.search-facet').toggleClass('expanded');
73 73   updateExpandCollapseAllFacetsState(facetsContainer);
74 74   });
... ... @@ -83,6 +83,11 @@
83 83   var queryIndex = url.indexOf('?');
84 84   return queryIndex < 0 ? '' : url.substr(queryIndex + 1);
85 85   };
88 +
89 + let removeQueryString = function(url) {
90 + let queryIndex = url.indexOf('?');
91 + return queryIndex < 0 ? url : url.substring(0, queryIndex);
92 + };
86 86  
87 87   var getSearchUIState = function() {
88 88   var expandedFacets = [];
... ... @@ -112,7 +112,9 @@
112 112  
113 113   var searchRequest = null;
114 114  
115 - var pushSearchUIState = function(viewURL) {
122 + // changeTargetSelector is the CSS selector of the facet anchor that initiated this reload. '
123 + // We expect the focus to go back to this place once the UI is reloaded.
124 + var pushSearchUIState = function(viewURL, changeTargetSelector) {
116 116   // If there is a request in progress, abort it to prevent its callback from being called.
117 117   searchRequest && searchRequest.abort();
118 118   $('.search-ui').attr('aria-busy', true);
... ... @@ -125,6 +125,7 @@
125 125   window.history.replaceState && window.history.replaceState(state, document.title);
126 126   // Make sure the browser address bar reflects the new state (and thus the new state can be bookmarked).
127 127   window.history.pushState && window.history.pushState(state, document.title, viewURL);
137 + document.querySelector(changeTargetSelector)?.focus();
128 128   });
129 129   };
130 130  
... ... @@ -131,12 +131,12 @@
131 131   var reloadSearchUI = function(event) {
132 132   event.preventDefault();
133 133   var anchor = $(event.target).closest('a');
134 - anchor.length && $(document).trigger('xwiki:search:update', anchor.attr('href'));
144 + anchor.length && anchor.first().trigger('xwiki:search:update', anchor.attr('href'));
135 135   };
136 136  
137 137   // Others (e.g. a custom facet) can trigger a search UI update by firing this event.
138 138   $(document).on('xwiki:search:update', function(event, viewURL) {
139 - pushSearchUIState(viewURL);
149 + pushSearchUIState(viewURL, `[data-facetvalue='${CSS.escape(event.target.dataset.facetvalue)}']`);
140 140   });
141 141  
142 142   $(window).on('popstate', function(event) {
... ... @@ -176,10 +176,41 @@
176 176   });
177 177  
178 178   var enhanceSearchUI = function() {
189 + // Enhance search options
190 + document.querySelectorAll('input.options-item').forEach(function (option){
191 + option.addEventListener('change', function() {
192 + let queryFieldName = this.getAttribute('data-query-name');
193 + let queryField = document.querySelector('input[name="' + queryFieldName + '"]');
194 + queryField.value = this.checked ? 'true' : 'false';
195 + // We want to build the URL the same way it's done in the velocimacro #extendQueryString
196 + // We retrieve the search parameters of the latest request
197 + let params = new URLSearchParams(window.location.search);
198 + let formParams = new URLSearchParams(new FormData(this.form));
199 + // We replace the existing parameters with their value from the form
200 + for (let param of formParams.keys()) {
201 + if (params.has(param)) params.delete(param);
202 + for (let paramValue of formParams.getAll(param)) {
203 + params.append(param,paramValue);
204 + }
205 + }
206 + pushSearchUIState(window.location.pathname + '?' + params.toString(),
207 + 'input[data-query-name="' + queryFieldName + '"]');
208 + });
209 + });
210 + // Enhance search result sorting
211 + document.querySelectorAll('.search-results-sort select#sort-by-input, ' +
212 + '.search-results-sort input#sort-order-input').forEach(function (sortInput){
213 + sortInput.addEventListener('change', function() {
214 + let baseURL = removeQueryString(this.form.getAttribute('action'));
215 + pushSearchUIState(baseURL + "?" +
216 + new URLSearchParams(new FormData(this.form)).toString(),
217 + 'input[data-query-name="' + this.getAttribute('name') + '"]');
218 + });
219 + });
220 +
179 179   $('.search-result-highlightAll').each(enhanceSearchResultHighlights);
180 180   $('.search-facets').each(enhanceSearchFacets);
181 181   $([
182 - '.search-results-sort a.sort-item',
183 183   '.search-options a.options-item',
184 184   '.pagination a',
185 185   '.controlPagination a',
Icon XWiki.StyleSheetExtension[0]
Code
... ... @@ -1,7 +1,7 @@
1 1  #template('colorThemeInit.vm')
2 2  
3 3  /* Hide the 'Created by', 'Modified by' and 'Tags' document sections. */
4 -.xdocLastModification, .skin-colibri #document-info, #xdocFooter {
4 +.xdocLastModification, #xdocFooter {
5 5   display: none;
6 6  }
7 7  #document-title > h1 {
... ... @@ -9,86 +9,99 @@
9 9   margin-bottom: 0;
10 10  }
11 11  
12 +/**
13 + * Layout for the search bar
14 + */
15 +.search-bar {
16 + margin: .5em 0;
17 +}
18 +
19 +@media (min-width: 768px) {
20 + .search-bar {
21 + max-width: 50%;
22 + }
23 +}
24 +
12 12  /**
13 - * Search form
26 + * Layout for search controls (sort + options)
14 14   */
15 15  
16 -.skin-colibri .search-form {
17 - /* There is no space after the title in Colibri. */
18 - margin-top: 1.5em;
29 +.search-results-controls {
30 + display: flex;
31 + flex-wrap: wrap;
32 + gap: 1em;
33 +
34 + & label {
35 + /* Reset the styles of the labels. */
36 + margin: 0;
37 + font-weight: unset;
38 + }
19 19  }
20 20  
21 -.skin-colibri .search-form input[type="search"] {
22 - /* Colibri doesn't have the grid system. */
23 - width: 50%;
41 +.search-results-sort,
42 +.search-options, .search-options > ul, .search-options > ul > li,
43 +.search-options > ul > li > label {
44 + display: flex;
45 + gap: .4em;
46 + align-items: center;
24 24  }
25 25  
26 26  /**
27 27   * Sort
28 28   */
52 +/* This select should be especially lightweight on the UI. We're removing the default border and shadow. */
53 +#sort-by-input {
54 + cursor: pointer;
29 29  
30 -ul.search-results-sort {
31 - color: $theme.textSecondaryColor;
32 - font-size: .9em;
33 - padding: 5px 0 2px 0;
56 + &:hover, &:focus {
57 + cursor: pointer;
58 + }
59 +}
60 +
61 +/* This checkbox input should be styled as a switch between ascending and descending states. */
62 +.search-results-sort #sort-order-input {
63 + /* Hide the default checkbox. We rely on the style of the icon in its label to make it work. */
64 + appearance: none;
34 34   margin: 0;
35 35  }
36 -.search-results-sort li {
37 - display: inline;
38 - list-style-type: none;
39 - padding-left: 1.5em;
67 +
68 +#sort-by-input, .search-results-sort label:has(>#sort-order-input) {
69 + /* We want most of the styles from "form-control", but not the shadow that comes from bootstrap. */
70 + box-shadow: none;
71 + & :hover,& :focus,& :focus-within {
72 + border-color: var(--input-border-focus);
73 + }
40 40  }
41 -.search-results-sort li:first-of-type {
42 - padding: 0;
75 +
76 +/* Flip the second icon so that it's the arrow going up and down. */
77 +.search-results-sort label #sort-order-input + * + * {
78 + transform: scaleY(-1);
43 43  }
44 -a.sort-item {
45 - color: inherit;
46 - text-decoration: none;
80 +
81 +/* When the box is checked, we want to hide the first icon.
82 +When the box is not checked, we want to hide the second icon. */
83 +.search-results-sort label #sort-order-input:checked + *,
84 +.search-results-sort label #sort-order-input:not(:checked) + * + * {
85 + display: none;
47 47  }
48 -a.sort-item:hover {
49 - color: $theme.linkColor;
50 - text-decoration: underline;
51 -}
52 -a.sort-item.active, a.sort-item.active:hover {
53 - font-weight: bold;
54 - color: $theme.textColor;
55 - text-decoration: none;
56 -}
57 -.sort-item-order {
58 - margin-left: .3em;
59 -}
60 60  
61 61  /**
62 62   * Options
63 63   */
64 64  
65 -ul.search-options {
66 - color: $theme.textSecondaryColor;
67 - font-size: .9em;
68 - padding: 5px 0 2px 0;
92 +.search-options ul {
69 69   margin: 0;
70 -}
71 -.search-options li {
72 - display: inline;
73 - list-style-type: none;
74 - padding-left: 1.5em;
75 -}
76 -.search-options li:first-of-type {
77 77   padding: 0;
95 +
96 + & input[type="checkbox"] {
97 + position: unset;
98 + margin: 0;
99 + }
100 +
101 + & label {
102 + margin-right: 1em;
103 + }
78 78  }
79 -a.options-item {
80 - color: inherit;
81 - text-decoration: none;
82 -}
83 -a.options-item:hover {
84 - color: $theme.linkColor;
85 - text-decoration: underline;
86 -}
87 -a.options-item.active, a.options-item.active:hover{
88 - font-weight: bold;
89 - color: $theme.textColor;
90 - text-decoration: none;
91 -}
92 92  
93 93  /**
94 94   * Search Results
... ... @@ -98,12 +98,6 @@
98 98   margin-top: 1em;
99 99  }
100 100  
101 -/* Colibri skin doesn't have the grid system. */
102 -.skin-colibri .search-results-left {
103 - margin: 0.5em 20em 0.5em 0;
104 - padding: 0.5em 0.5em 0.5em 0;
105 -}
106 -
107 107  .search-results {
108 108   padding: .3em 0 .8em 0;
109 109  }
... ... @@ -167,6 +167,8 @@
167 167  
168 168  dl.search-result-highlights > dt {
169 169   margin-top: .3em;
177 + color: var(--text-muted);
178 + font-weight: var(--font-weight-semibold);
170 170  }
171 171  
172 172  blockquote.search-result-highlight {
... ... @@ -187,11 +187,6 @@
187 187   font-weight: bold;
188 188  }
189 189  
190 -dl.search-result-highlights > dt {
191 - color: $theme.textSecondaryColor;
192 - font-weight: normal;
193 -}
194 -
195 195  dl.search-result-highlights.preview dt,
196 196  dl.search-result-highlights.preview dd > * {
197 197   display: none;
... ... @@ -198,17 +198,10 @@
198 198  }
199 199  
200 200  dl.search-result-highlights.preview dt:first-of-type,
201 -dl.search-result-highlights.preview dd:first-of-type blockquote:first-of-type,
202 -/* Workaround for IE8 which doesn't support :first-of-type CSS selector. */
203 -dl.search-result-highlights.preview dt.first,
204 -dl.search-result-highlights.preview dd.first blockquote.first {
205 +dl.search-result-highlights.preview dd:first-of-type blockquote:first-of-type {
205 205   display: block;
206 206  }
207 207  
208 -a.search-result-highlightAll:after {
209 - content: ' \bb';
210 -}
211 -
212 212  .search-result-debug {
213 213   white-space: pre;
214 214  }
... ... @@ -217,40 +217,23 @@
217 217   * Facets
218 218   */
219 219  
220 -.search-facets {
221 - background-color: $theme.backgroundSecondaryColor;
222 - box-shadow: 0 2px 2px rgba(0, 0, 0, 0.2);
223 - /* Leave space for the bottom shadow. */
224 - margin-bottom: 1em;
225 - border-radius: 7px;
217 +.search-facets-header{
218 + border-bottom: 1px solid var(--xwiki-border-color);
226 226  }
227 -/* Colibri skin doesn't have the grid system. */
228 -.skin-colibri .search-facets {
229 - float: right;
230 - max-width: 19.5em;
231 - width: 19.5em;
232 -}
233 233  
234 -.search-facets-header,
235 -.search-facets-actions,
236 -.search-facet {
237 - border-bottom: 1px solid $theme.borderColor;
238 - border-top: 1px solid $theme.pageContentBackgroundColor;
239 - position: relative;
221 +.search-facets-header strong {
222 + font-size: 1.25em;
240 240  }
241 241  
242 242  .search-facets-header,
243 243  .search-facets-actions {
244 - padding: 0.5em 1em;
227 + padding: .5em 0;
245 245  }
229 +
246 246  .search-facet {
247 - padding: 0.5em .8em;
231 + padding: .2em 0;
248 248  }
249 249  
250 -.search-facets-header {
251 - border-top: none;
252 -}
253 -
254 254  .search-facets-header > p,
255 255  .search-facets-actions > p {
256 256   /* The wiki syntax generates paragraphs which have bottom margin. */
... ... @@ -261,16 +261,6 @@
261 261   font-size: .8em;
262 262  }
263 263  
264 -.search-facets-actions a {
265 - color: $theme.textSecondaryColor;
266 - text-decoration: none;
267 -}
268 -
269 -.search-facets-actions a:hover {
270 - color: $theme.linkColor;
271 - text-decoration: underline;
272 -}
273 -
274 274  .search-facets-action-collapseAll,
275 275  .search-facets-action-expandAll {
276 276   float: right;
... ... @@ -282,35 +282,37 @@
282 282   margin: 0;
283 283  }
284 284  
285 -.search-facet:last-of-type {
286 - border-bottom: none;
255 +.search-facet-header, .search-facet-body {
256 + padding-left: .5em;
257 + border: 1px solid var(--xwiki-border-color);
258 + border-radius: var(--border-radius-small);
287 287  }
288 288  
289 289  .search-facet-header {
262 + background-color: var(--xwiki-background-secondary-color);
263 +}
264 +
265 +.search-facet-header label {
290 290   color: $theme.titleColor;
291 291   cursor: pointer;
292 - line-height: 1.4em;
293 - margin: 0 .2em;
294 294   display: flex;
295 295   justify-content: space-between;
296 - position: relative;
270 + align-items: center;
297 297  }
298 298  
299 -.search-facet:last-of-type .search-facet-header:after {
300 - border: medium none;
301 -}
273 +.search-facet-body {
274 + opacity: 0;
275 + visibility: hidden; /* This makes sure the element is removed from the accessibility tree. */
302 302  
303 -.search-facet.expanded:last-of-type .search-facet-header:after {
304 - border-bottom: 1px dotted $theme.pageContentBackgroundColor;
305 - border-top: 1px dotted $theme.borderColor;
277 + position: absolute;
278 + transform: translateY(-10px); /* Start the animation slightly above */
279 + padding-top: .5em;
280 +
281 + border-top-width: 0;
282 + border-top-left-radius: 0;
283 + border-top-right-radius: 0;
306 306  }
307 307  
308 -.search-facet-body {
309 - overflow: hidden; /* required for effect */
310 - display: none;
311 - margin-top: .5em;
312 -}
313 -
314 314  .search-facet-body ul,
315 315  .search-facet-body ol {
316 316   font-size: .9em;
... ... @@ -319,37 +319,55 @@
319 319  .search-facet-body li {
320 320   display: flex;
321 321   flex-wrap: wrap;
322 - padding: .1em .2em;
294 + padding: .3em .5em;
323 323  }
324 324  
325 -.search-facet .search-facet-header .facet-toggler, button.facet-value-toggler {
297 +.search-facet .search-facet-header .facet-toggle, button.facet-value-toggle {
326 326   background: transparent;
327 327   transition: background-color .2s ease-in-out;
328 328  }
329 329  
330 -.search-facet .search-facet-header .facet-toggler:active, button.facet-value-toggler:active {
302 +.search-facet .search-facet-header .facet-toggle:active, button.facet-value-toggle:active {
331 331   box-shadow: unset;
332 332  }
333 333  
334 -.search-facet .search-facet-header .facet-toggler > span, button.facet-value-toggler > span,
335 -.search-facet .search-facet-header .facet-toggler > img, button.facet-value-toggler > img {
306 +.search-facet .search-facet-header .facet-toggle > span, button.facet-value-toggle > span,
307 +.search-facet .search-facet-header .facet-toggle > img, button.facet-value-toggle > img {
336 336   transform: rotate(90deg);
337 337  }
338 338  
339 -.search-facet.expanded .search-facet-header .facet-toggler > span, .expanded > button.facet-value-toggler > span,
340 -.search-facet.expanded .search-facet-header .facet-toggler > img, .expanded > button.facet-value-toggler > img {
311 +.search-facet.expanded .search-facet-header .facet-toggle > span, .expanded > button.facet-value-toggle > span,
312 +.search-facet.expanded .search-facet-header .facet-toggle > img, .expanded > button.facet-value-toggle > img {
341 341   transform: rotate(0deg);
342 342  }
343 343  
344 -@media not (prefers-reduced-motion) {
345 - .search-facet .search-facet-header .facet-toggler > span, button.facet-value-toggler > span,
346 - .search-facet .search-facet-header .facet-toggler > img, button.facet-value-toggler > img {
316 +@media (prefers-reduced-motion: no-preference) {
317 + .search-facet .search-facet-header .facet-toggle > span, button.facet-value-toggle > span,
318 + .search-facet .search-facet-header .facet-toggle > img, button.facet-value-toggle > img {
347 347   transition: transform 0.2s ease;
348 348   }
321 +
322 + .search-facet-body {
323 + transition: opacity 0.3s ease, transform 0.3s ease;
324 + }
349 349  }
350 350  
351 -.search-facet.expanded .search-facet-body {
352 - display: block;
327 +.search-facet.expanded {
328 + & .search-facet-header {
329 + border-bottom-width: 0;
330 + border-bottom-left-radius: 0;
331 + border-bottom-right-radius: 0;
332 +
333 + & label {
334 + font-weight: var(--font-weight-semibold);
335 + }
336 + }
337 + & .search-facet-body {
338 + opacity: 1;
339 + position: unset; /* This element should be positioned normally when shown. */
340 + visibility: visible;
341 + transform: translateY(0);
342 + }
353 353  }
354 354  
355 355  .search-facet-body ul, .search-facet-body ul.users {
... ... @@ -360,10 +360,6 @@
360 360   margin: .5em 0;
361 361  }
362 362  
363 -.search-facet-body li:hover {
364 - background-color: $theme.highlightColor;
365 -}
366 -
367 367  .search-facet-body input[type="checkbox"] {
368 368   margin: .2em 0;
369 369  }
... ... @@ -388,7 +388,8 @@
388 388  }
389 389  
390 390  .search-facet-body .itemName,
391 -.search-facet-body .facet-value-toggler,
377 +.search-facet-body .itemNameempty,
378 +.search-facet-body .facet-value-toggle,
392 392  .search-facet-body .more {
393 393   /* Remove link styling */
394 394   color: $theme.textColor;
... ... @@ -406,8 +406,11 @@
406 406  }
407 407  
408 408  .search-facet-body .itemCount {
409 - padding: .1em 0;
396 + padding: .1em .5em;
410 410   margin-left: auto;
398 + background-color: var(--nav-link-hover-bg);
399 + /* We want those item count blocks to be pill shaped. */
400 + border-radius: 1em / 50%;
411 411  }
412 412  
413 413  @media (max-width: 768px) {
... ... @@ -427,17 +427,6 @@
427 427  }
428 428  
429 429  /**
430 - * Fix the breadcrumb in Colibri skin.
431 - */
432 -.skin-colibri .breadcrumb > li {
433 - display: inline;
434 -}
435 -.skin-colibri .breadcrumb > li + li:before {
436 - color: $theme.textSecondaryColor;
437 - content: ' \00BB ';
438 -}
439 -
440 -/**
441 441   * Miscellaneous
442 442   */
443 443  
... ... @@ -446,13 +446,3 @@
446 446   padding-left: 0;
447 447  }
448 448  
449 -.paginationFilter .resultsNo,
450 -.paginationFilter .controlPagination,
451 -.paginationFilter .pagination {
452 - line-height: 22px;
453 -}
454 -
455 -.iconRSS {
456 - background: url("$xwiki.getSkinFile('icons/silk/feed.png')") no-repeat scroll 0 0 transparent;
457 - padding-left: 20px;
458 -}

Community

https://wiki.makerspace-darmstadt.de/bin/download/Panels/MKSP%20Slack/Slack_MKSP.png

Wir benutzen Slack, um miteinander zu kommunizieren. Melde Dich an und werde Teil unserer Maker-Community!

Zum Slack Workspace

Frage? FAQ!

Du hast eine Frage, die sich nicht direkt im Wiki findet?

Natürlich kannst Du die Frage jederzeit gerne in der Slack Community stellen. Bevor Du das machst, schau doch bitte einmal auf unserer Homepage bei den Häufig gestellten Fragen vorbei. Wir versuchen diese Fragen stets aktuell zu halten, eventuell hilft Dir das ja schon weiter.

Offene Werkstatt

Ohne Anmeldung einfach vorbei kommen. Am besten bringst Du direkt den ausgefüllten Haftungsauschluss mit.

Jeden Donnerstag ab 19 Uhr

Während der offenen Werkstatt kannst Du einfach vorbei kommen und an Deinem Projekt arbeiten. Bitte beachte aber, dass zur Verwendung der Maschinen eine Einweisung erforderlich ist, die Du gegebenfalls vorher absolvieren musst. Wenn ein Mitglied mit entsprechender Einweisung vor Ort ist und Zeit hat, helfen wir natürlich gerne aus. Dies können wir aber nicht garantieren, da Rundgänge Priorität haben.

Sprich Dich idealerweise schon vor der offenen Werkstatt mit einem Mitglied in unserem Slack ab. So kannst Du sicherstellen, dass Du auf jeden Fall arbeiten kannst.

Übrigens: Du kannst Dich mit einem Mitglied gerne auch außerhalb der offenen Werkstattzeiten zum Arbeiten verabreden!

Führungen und Rundgänge

Im Rahmen der offenen Werkstatt bieten wir euch auch gerne einen Rundgang durch unsere Werkstatt. Hier könnt ihr den Verein und unser Konzept kennenlernen sowie die Maschinen und Möglichkeiten der Werkstatt gezeigt bekommen.

Jeden Donnerstag wird eine Führung angeboten:

  • Um 19:15 Uhr (bitte um 19:00 Uhr da sein)

Der Rundgang dauert ca. 45 Minuten und ihr habt natürlich auch die Möglichkeit, eure Fragen loszuwerden.

Bitte beachtet folgendes: Die Werkstatt beinhaltet gefährliche Maschinen. Bringt daher bitte nach Möglichkeit den ausgefüllten und unterschrieben Haftungsauschluss schon mit. Dieser kann aber auch vor Ort ausgefüllt werden, das verzögert allerdings die Abläufe.