BEGYNTE PÅ GULVET OG ENDTE I GRAVEN
Guttene i lastegraven sender ut 10 000 Tysse tilhengere i året.
De er som et gammelt ektepar etter 20 år sammen i aksjon for Tysse. Rune Hagebø og Frank RIsholm regjerer i fabrikkens lastegrav, der tilhengere pakkes på lastebiler og sendes ut til hele Norge.
Error executing template "Designs/Swift/Paragraph/Swift_Poster_custom.cshtml" System.NullReferenceException: Object reference not set to an instance of an object. at CompiledRazorTemplates.Dynamic.RazorEngine_c485437cd9614addabf3abdc6d6b0d52.Execute() in D:\dynamicweb.net\Solutions\Mennt\tysse.staging.dynamicweb-cms.com\files\Templates\Designs\Swift\Paragraph\Swift_Poster_custom.cshtml:line 143 at RazorEngine.Templating.TemplateBase.RazorEngine.Templating.ITemplate.Run(ExecuteContext context, TextWriter reader) at RazorEngine.Templating.RazorEngineService.RunCompile(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag) at RazorEngine.Templating.RazorEngineServiceExtensions.<>c__DisplayClass16_0.<RunCompile>b__0(TextWriter writer) at RazorEngine.Templating.RazorEngineServiceExtensions.WithWriter(Action`1 withWriter) at Dynamicweb.Rendering.RazorTemplateRenderingProvider.Render(Template template) at Dynamicweb.Rendering.TemplateRenderingService.Render(Template template) at Dynamicweb.Rendering.Template.RenderRazorTemplate()
1 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.ParagraphViewModel> 2 @using Dynamicweb.Ecommerce.ProductCatalog 3 4 @{ 5 string layout = Model.Item.GetRawValueString("Layout", "align-middle-center-text-center"); 6 7 bool movePageBehind = false; 8 bool isFirstPoster = false; 9 string movePageBehindClass = ""; 10 if (Pageview.Page.PropertyItem != null) 11 { 12 string headerCssClass = Pageview.Page.PropertyItem["MoveThisPageBehindTheHeader"] != null ? Pageview.Page.PropertyItem["MoveThisPageBehindTheHeader"].ToString() : "sticky-top"; 13 movePageBehind = headerCssClass == "fixed-top" && !Pageview.IsVisualEditorMode ? true : false; 14 if (movePageBehind) 15 { 16 movePageBehindClass = " poster-behind"; 17 if (!Dynamicweb.Context.Current.Items.Contains("firstPosterIsRendered")) 18 { 19 isFirstPoster = true; 20 Dynamicweb.Context.Current.Items.Add("firstPosterIsRendered", true); 21 } 22 } 23 } 24 25 26 string posterHeight = Model.Item.GetRawValueString("PosterHeight", ""); 27 string posterSizeBase = posterHeight.Contains("%") || posterHeight.Contains("0") ? "aspect-ratio" : "height"; 28 29 posterHeight = posterHeight == "small" ? "min-vh-25 min-vh-md-50" : posterHeight; 30 posterHeight = posterHeight == "medium" ? "min-vh-50 min-vh-md-75" : posterHeight; 31 posterHeight = posterHeight == "large" ? "min-vh-75 min-vh-md-100" : posterHeight; 32 33 string ratio = posterHeight.Contains("%") || posterHeight.Contains("0") ? Model.Item.GetRawValueString("PosterHeight") : ""; 34 ratio = ratio != "0" ? ratio : ""; 35 string ratioCssClass = ratio != "" && ratio != "fill" ? " ratio" : ""; 36 string ratioVariable = ratio != "" ? "style=\"--bs-aspect-ratio: " + ratio + "\"" : ""; 37 38 string posterPadding = Model.Item.GetRawValueString("ContentPadding", ""); 39 posterPadding = posterPadding == "none" ? "p-3 px-xl-3 py-xl-4" : posterPadding; 40 posterPadding = posterPadding == "small" ? "p-3 p-xl-4" : posterPadding; 41 posterPadding = posterPadding == "large" ? "p-4 p-xl-5" : posterPadding; 42 43 string posterWidth = "container-xl"; 44 45 int xPos = Model.Item?.GetFile("Image")?.FocalPositionFromLeft ?? 50; 46 int yPos = Model.Item?.GetFile("Image")?.FocalPositionFromTop ?? 50; 47 48 string theme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("Theme")) ? " theme " + Model.Item.GetRawValueString("Theme").Replace(" ", "").Trim().ToLower() : ""; 49 string alignment = ""; 50 51 string maxWidth = Model.Item.GetRawValueString("TextReadability", "max-width-on"); 52 maxWidth = maxWidth == "max-width-on" ? "mw-75ch d-inline-block" : maxWidth; 53 maxWidth = maxWidth == "max-width-off" ? "" : maxWidth; 54 55 switch (layout) 56 { 57 case "align-top-left-text-left": 58 alignment = "text-start justify-content-start align-items-start"; 59 break; 60 case "align-top-center-text-center": 61 alignment = "text-center justify-content-start align-items-start"; 62 break; 63 case "align-top-right-text-right": 64 alignment = "text-end justify-content-start align-items-start"; 65 break; 66 case "align-middle-left-text-left": 67 alignment = "text-start justify-content-center align-items-center"; 68 break; 69 case "align-middle-center-text-center": 70 alignment = "text-center justify-content-center align-items-center"; 71 break; 72 case "align-middle-right-text-right": 73 alignment = "text-end justify-content-center align-items-center"; 74 break; 75 case "align-bottom-left-text-left": 76 alignment = "text-start justify-content-end align-items-end"; 77 break; 78 case "align-bottom-center-text-center": 79 alignment = "text-center justify-content-end align-items-end"; 80 break; 81 case "align-bottom-right-text-right": 82 alignment = "text-end justify-content-end align-items-end"; 83 break; 84 } 85 86 87 var parms = new Dictionary<string, object>(); 88 parms.Add("cssClass", "h-100 w-100"); 89 parms.Add("columns", Model.GridRowColumnCount); 90 91 string imageFilter = Model.Item.GetRawValueString("ImageFilter", ""); 92 imageFilter = imageFilter == "no-filter" ? "" : imageFilter; 93 imageFilter = imageFilter == "filter" ? " image-filter" : imageFilter; 94 } 95 96 97 @if (Pageview.Device == Dynamicweb.Frontend.Devices.DeviceType.Mobile || Pageview.Device == Dynamicweb.Frontend.Devices.DeviceType.Tablet) 98 { 99 100 <div class="position-relative @(theme)@(movePageBehindClass) mx-n3"> 101 @if (posterSizeBase == "height") { 102 if (!string.IsNullOrEmpty(Model.Item.GetString("Image"))) { 103 <div class="position-absolute top-0 bottom-0 end-0 start-0@(imageFilter)"> 104 @RenderPartial("Components/Image.cshtml", Model.Item.GetFile("Image") ?? new Dynamicweb.Frontend.FileViewModel(), parms) 105 </div> 106 } 107 108 <div class="@(posterWidth) h-100"> 109 <div class="h-100 position-relative grid grid-1 @posterPadding @(alignment) @(posterHeight)" id="Poster_@Pageview.CurrentParagraph.ID"> 110 <div class="grid grid-1 gap-3 gap-md-4"> 111 @RenderTitle(maxWidth) 112 @RenderText(maxWidth) 113 @RenderButton() 114 </div> 115 </div> 116 </div> 117 } 118 @if (posterSizeBase == "aspect-ratio") { 119 <div class="@(posterWidth) @posterPadding position-absolute h-100 w-100" style="z-index: 1"> 120 <div class="h-100 grid grid-1 @(alignment)" @ratioVariable id="Poster_@Pageview.CurrentParagraph.ID"> 121 <div class="grid grid-1 gap-3 gap-md-4"> 122 @RenderTitle(maxWidth) 123 @RenderText(maxWidth) 124 @RenderButton() 125 </div> 126 </div> 127 </div> 128 129 <div class="position-relative @(imageFilter)"> 130 <figure class="m-0@(ratioCssClass)" @ratioVariable> 131 @if (!string.IsNullOrEmpty(Model.Item.GetString("Image"))) { 132 @RenderPartial("Components/Image.cshtml", Model.Item.GetFile("Image") ?? new Dynamicweb.Frontend.FileViewModel(), parms) 133 } 134 </figure> 135 </div> 136 } 137 </div> 138 139 } else { 140 141 <div class="position-relative @(theme)@(movePageBehindClass)"> 142 @if (posterSizeBase == "height") { 143 if (!string.IsNullOrEmpty(Model.Item.GetString("Image"))) { 144 <div class="position-absolute top-0 bottom-0 end-0 start-0@(imageFilter) test"> 145 <img src='@Model.Item.GetFile("Image")' alt='@Model.Item.GetFile("Image").ToString().Replace("/Files/Images/", "")' sizes="(min-width: 992px) 50vw, 100vw" loading="lazy" decoding="async" class="h-100 w-100" style="object-fit: cover;object-position: 50% 50%;" /> 146 @*RenderPartial("Components/Image.cshtml", Model.Item.GetFile("Image") ?? new Dynamicweb.Frontend.FileViewModel(), parms)*@ 147 </div> 148 } 149 150 <div class="@(posterWidth) h-100"> 151 <div class="h-100 position-relative grid grid-1 @posterPadding @(alignment) @(posterHeight)" id="Poster_@Pageview.CurrentParagraph.ID"> 152 <div class="grid grid-1 gap-3 gap-md-4"> 153 @RenderTitle(maxWidth) 154 @RenderText(maxWidth) 155 @RenderButton() 156 </div> 157 </div> 158 </div> 159 } 160 @if (posterSizeBase == "aspect-ratio") { 161 <div class="@(posterWidth) @posterPadding position-absolute h-100 w-100 test" style="z-index: 1"> 162 <div class="h-100 grid grid-1 @(alignment)" @ratioVariable id="Poster_@Pageview.CurrentParagraph.ID"> 163 <div class="grid grid-1 gap-3 gap-md-4"> 164 @RenderTitle(maxWidth) 165 @RenderText(maxWidth) 166 @RenderButton() 167 </div> 168 </div> 169 </div> 170 171 <div class="position-relative @(imageFilter)"> 172 <figure class="m-0@(ratioCssClass)" @ratioVariable> 173 @if (!string.IsNullOrEmpty(Model.Item.GetString("Image"))) { 174 @RenderPartial("Components/Image.cshtml", Model.Item.GetFile("Image") ?? new Dynamicweb.Frontend.FileViewModel(), parms) 175 } 176 </figure> 177 </div> 178 } 179 </div> 180 } 181 182 @helper RenderTitle(string maxWidth) 183 { 184 185 186 if (!string.IsNullOrEmpty(Model.Item.GetString("Title")) && !Model.Item.GetBoolean("HideTitle")) 187 { 188 string titleFontSize = Model.Item.GetRawValueString("TitleFontSize", "display-1"); 189 190 <h1 class="@titleFontSize mb-0"> 191 <span class="@maxWidth fs-1 frontpage-banner frontpage-banner-mobil">@Model.Item.GetString("Title")</span> 192 </h1> 193 } 194 } 195 196 @helper RenderText(string maxWidth) 197 { 198 if (!string.IsNullOrEmpty(Model.Item.GetString("Text"))) 199 { 200 201 string subtitleFontSize = Model.Item.GetRawValueString("SubtitleFontSize", "fs-5"); 202 203 <p class="@subtitleFontSize lead mb-0"> 204 <span class="@maxWidth">@Model.Item.GetString("Text")</span> 205 </p> 206 } 207 } 208 209 @helper RenderButton() 210 { 211 string linkType = Model.Item.GetRawValueString("LinkType", "page"); 212 Dynamicweb.Frontend.LinkViewModel link = new Dynamicweb.Frontend.LinkViewModel(); 213 214 string StretchedLink = Model.Item.GetRawValueString("StretchedLink", ""); 215 StretchedLink = StretchedLink == "column-not-clickable" ? "" : StretchedLink; 216 StretchedLink = StretchedLink == "column-clickable" ? " stretched-link" : StretchedLink; 217 218 if (linkType == "page" && Model.Item.GetLink("ButtonLink") != null) 219 { 220 link = Model.Item.GetLink("ButtonLink"); 221 } 222 223 if (linkType == "product-group") 224 { 225 IList<ProductGroupViewModel> selectedGroups = Model.Item.GetValue<IList<ProductGroupViewModel>>("ProductGroupLink"); 226 IList<string> groupIds = new List<string> { }; 227 228 if (selectedGroups != null) 229 { 230 foreach (var fromGroup in selectedGroups) 231 { 232 groupIds.Add(fromGroup.Id); 233 } 234 } 235 236 link = new Dynamicweb.Frontend.LinkViewModel() 237 { 238 Url = "/Default.aspx?ID=" + GetPageIdByNavigationTag("Shop") + "&GroupID=" + string.Join(",", groupIds).Trim(), 239 IsExternal = false 240 }; 241 } 242 243 if (linkType == "product") 244 { 245 ProductListViewModel products = Model.Item.GetValue<ProductListViewModel>("ProductLink"); 246 IList<string> productIds = new List<string> { }; 247 248 if (products != null) 249 { 250 foreach (var product in products.Products) 251 { 252 productIds.Add(product.Id); 253 } 254 } 255 256 string productParameter = productIds.Count == 1 ? "ProductID" : "MainProductId"; 257 string pageTag = productIds.Count == 1 ? "ProductDetailPage" : "Shop"; 258 link = new Dynamicweb.Frontend.LinkViewModel() 259 { 260 Url = "/Default.aspx?ID=" + GetPageIdByNavigationTag(pageTag) + "&" + productParameter + "=" + string.Join(",", productIds).Trim(), 261 IsExternal = false 262 }; 263 } 264 265 if (link != null && !string.IsNullOrEmpty(Model.Item.GetString("ButtonLabel"))) 266 { 267 string target = link.IsExternal ? "target=\"_blank\"" : ""; 268 269 string buttonStyle = Model.Item.GetRawValueString("ButtonStyle", "primary"); 270 buttonStyle = buttonStyle == "primary" ? "btn-primary" : buttonStyle; 271 buttonStyle = buttonStyle == "secondary" ? "btn-secondary" : buttonStyle; 272 273 string ButtonSize = Model.Item.GetRawValueString("ButtonSize", "regular"); 274 ButtonSize = ButtonSize == "small" ? " btn-sm" : ButtonSize; 275 ButtonSize = ButtonSize == "regular" ? "" : ButtonSize; 276 ButtonSize = ButtonSize == "large" ? " btn-lg" : ButtonSize; 277 278 <div class="mt-0"> 279 <a href="@link.Url" class="btn @buttonStyle@(ButtonSize)@(StretchedLink)">@Model.Item.GetString("ButtonLabel")</a> 280 </div> 281 } 282 else if (link != null && !string.IsNullOrEmpty(link.Url)) 283 { 284 string target = link.IsExternal ? "target=\"_blank\"" : ""; 285 286 <a href="@link.Url" @target class="@StretchedLink"> 287 <span class="visually-hidden">@Model.Item.GetString("Title")</span> 288 </a> 289 } 290 } 291 292 @if (movePageBehind && isFirstPoster) 293 { 294 <script> 295 ['resize', 'load'].forEach(function (e) { 296 window.addEventListener(e, () => swift.Scroll.setContentPosition()); 297 }); 298 </script> 299 } 300
Høyt tempo og travle dager
Det meste vi har sendt ut på én uke er 427 tilhengere, sier Risholm. – Da er du ikke mye hjemme, kommer det raskt fra sidemannen. Stemningen er god, og det er bokstavelig talt høyt under taket i lokalet der duoen har tilbragt en stor del av livet. Høyt tempo er det også, og når Hagebø og Risholm har travle dager, er det gode nyheter for Osterøy-bedriften. Tysse er nemlig igjen Norges mest solgte tilhengermerke.
– Det er veldig bra. Da har vi en sikker arbeidsplass, sier Hagebø.
– Vi har jo vært med på både opp- og nedturer. Opp er best. Vi er skrudd sammen på den måten at det er mye bedre å ha mye å gjøre, enn lite. Vi liker hektiske dager og vi håndterer det. Det er ikke så ofte vi får kjeft, sier Risholm.
Kan gå en kule varmt
Hagebø er den med lengst fartstid i selskapet av de to arbeidskameratene. Til sommeren 2022 har den spreke 56-åringen, som bestiger den ene fjelltoppen etter den andre, 30-årsjubileum i Tysse.
– Jeg har vært i Tysse-systemet i 29 år. De siste 20 årene har jeg vært i lastegraven. Det handler om å få mest mulig på bilene. Lange dager når det er sesong, og ikke fullt så lange dager når det ikke er sesong. Vi jobber til vi er ferdige. Vi går ikke hjem før. Jeg begynte på gulvet og endte i graven, sier Hagebø med et glis.
– Vi har det fint her, og vi kjenner hverandre ganske godt etter hvert. Vi krangler og diskuterer og av og til blir det selvfølgelig litt temperatur, så når man blir forbanna er det viktig å få det ut. Men om vi ikke hadde trivdes her, hadde vi ikke vært her. Vi er på en måte et ektepar. Sjåførene som har vært innom har nok sett litt av hvert, vi er vant med å gi beskjed til hverandre når vi syns den andre er litt kokko, men vi tåler det, sier Risholm.
Båthengere gjøres klar for utsending.
Hagebø er glad det stadig vekk svinger kjente lastebilsjåfører innom for å hente nye lass med Tysse-tilhengere.
– Du kan si at vi er som et ektepar ja, men med begrensninger. Vi har en god kjemi her, og så er det også mange artige lastebilsjåfører som er innom. Sjåførene kjenner vi godt, og det kan av og til bli litt diskusjoner med sjåførene også om plassering av tilhengere på bilen. For å få plass til det vi ønsker, må vi av og til sette den hengeren som skal først av midt inne i lasten. Da får sjåføren det kanskje litt vanskelig, men det blir mye enklere for oss. Det går seg alltid til og vi blir alltid venner igjen.
Bestselgeren er favoritten
Rune og Frank jobber tett sammen hver dag, men rollene er forskjellige. Samme tankegang er uansett en fordel i jobben.
– Jeg planlegger alle bilene, altså planlegger hva som skal på de forskjellige lastebilene. Har jeg 300 hengere som skal sendes må jeg plassere de riktig på de forskjellige bilene. Hvilken retning de skal og sånt. Tar jeg en tilhenger til Kristiansand og en tilhenger til Trondheim på samme bil er jo det litt dumt. Og jeg må passe på at det er plass til alt vi skal ha ut. Om vi trenger en ekstra bil må jeg fikse det, sier Risholm.
– Jeg skal jo utføre det som han har planlagt, så jeg må tenke nesten helt likt som ham for å få sammen disse pakkene som han har tenkt. Og vi tenker veldig ofte likt. Det er så mange ulike typer hengere her, så det er mange måter å løse det på. Jeg er ute og plukker de tilhengerne som skal av gårde og får de inn i lastegraven klar for utsending. Og så er jeg kranfører. Vi er effektive sammen, sier Hagebø.
Hvilken tilhenger-modell er favoritten?
6301, svarer begge i kor. Duoens favoritthenger er Tysses bestselger og allroundhenger. Den har også fått en kraftig oppgradering, men det er en annen grunn til at herrene i lastegraven holder den høyest. – Det er den som er enklest å pakke på lastebilene. Mest effektivt. Vi får 16 av den typen på en lastebil, melder Risholm.
Stolte av Tysse
Kjærligheten til jobben, bedriften og produktet er sterk. Noen dager går som en lek, mens andre kan være tyngre. Sånn er det over alt. Men samarbeidet er nøkkelen til suksess, og over 20 år sammen i en lastegrav må uansett sies å være meget imponerende.
– Vi er jo stolte av å jobbe her på Tysse. Det er en veldig god arbeidsplass og det håper jeg fortsetter fremover også, sier Risholm. Hagebø er igjen enig, men viser også at det er uunngåelig å pådra seg milde symptomer og tegn til miljøskade etter lang fartstid i samme selskap. – Det er en solid bedrift og jeg trives veldig godt her. Når man er rundt omkring ser man jo etter Tysse-hengere. På ferie kan jeg si: Oi, der er en Tysse-henger. Ser jeg et annet merke tenker jeg fysj avslutter Hagebø.