From de6528bcaf5047dce0fa5ad0c4ecf3eba4385426 Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 28 Feb 2019 12:36:54 +1000 Subject: [PATCH 001/826] Fixes #4742 - no assembly scanning for dashboards --- src/Umbraco.Core/Dashboards/IDashboard.cs | 2 +- src/Umbraco.Web/Runtime/WebRuntimeComposer.cs | 13 ++++++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Core/Dashboards/IDashboard.cs b/src/Umbraco.Core/Dashboards/IDashboard.cs index c990e2ba61..6e429d9b40 100644 --- a/src/Umbraco.Core/Dashboards/IDashboard.cs +++ b/src/Umbraco.Core/Dashboards/IDashboard.cs @@ -6,7 +6,7 @@ namespace Umbraco.Core.Dashboards /// /// Represents a dashboard. /// - public interface IDashboard : IDashboardSlim, IDiscoverable + public interface IDashboard : IDashboardSlim { /// /// Gets the aliases of sections/applications where this dashboard appears. diff --git a/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs b/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs index c8fc209768..8f420e708a 100644 --- a/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs +++ b/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs @@ -8,6 +8,7 @@ using Umbraco.Core.Composing; using Umbraco.Core.Dashboards; using Umbraco.Core.Dictionary; using Umbraco.Core.Events; +using Umbraco.Core.Manifest; using Umbraco.Core.Migrations.PostMigrations; using Umbraco.Web.Migrations.PostMigrations; using Umbraco.Core.Models.PublishedContent; @@ -238,7 +239,17 @@ namespace Umbraco.Web.Runtime // register core CMS dashboards and 3rd party types - will be ordered by weight attribute & merged with package.manifest dashboards composition.WithCollectionBuilder() - .Add(composition.TypeLoader.GetTypes()); + .Add() + .Add() + .Add() + .Add() + .Add() + .Add() + .Add() + .Add() + .Add() + .Add() + .Add(); // register back office trees // the collection builder only accepts types inheriting from TreeControllerBase From 3f84656c13fb5381574e9390098c88e66d343ed6 Mon Sep 17 00:00:00 2001 From: Shannon Date: Mon, 4 Mar 2019 13:42:27 +1000 Subject: [PATCH 002/826] removes duplicate registration --- src/Umbraco.Web/Runtime/WebRuntimeComposer.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs b/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs index 8f420e708a..602b2c91ec 100644 --- a/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs +++ b/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs @@ -248,7 +248,6 @@ namespace Umbraco.Web.Runtime .Add() .Add() .Add() - .Add() .Add(); // register back office trees From 5b713af96c674e2417f7dd1c21277f42cbe7efe7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Gregersen?= Date: Tue, 26 Nov 2019 21:00:45 +0100 Subject: [PATCH 003/826] Removed unused jQuery MEGA CHANGE! But every bit of jQuery removed from the internet is a good change :) --- src/Umbraco.Web.UI/config/splashes/noNodes.aspx | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Umbraco.Web.UI/config/splashes/noNodes.aspx b/src/Umbraco.Web.UI/config/splashes/noNodes.aspx index 46a27a4eba..52abd04af0 100644 --- a/src/Umbraco.Web.UI/config/splashes/noNodes.aspx +++ b/src/Umbraco.Web.UI/config/splashes/noNodes.aspx @@ -55,7 +55,5 @@ - - From c3937d6e622ce38a66c616d1dc85d8a1dfa08f3b Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Fri, 10 Jan 2020 12:58:58 +0100 Subject: [PATCH 004/826] Disable the actions menu button until there are actions available --- .../src/less/components/buttons/umb-button.less | 5 +++++ src/Umbraco.Web.UI.Client/src/less/components/editor.less | 5 +++++ .../src/views/components/editor/umb-editor-menu.html | 1 + 3 files changed, 11 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/less/components/buttons/umb-button.less b/src/Umbraco.Web.UI.Client/src/less/components/buttons/umb-button.less index 4127c2201c..d523b24141 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/buttons/umb-button.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/buttons/umb-button.less @@ -31,6 +31,11 @@ margin-left: 5px; } +.umb-button__button[disabled] .umb-button__caret { + border-top-color: @gray-7; + border-bottom-color: @gray-7; +} + .umb-button__progress { position: absolute; left: 50%; diff --git a/src/Umbraco.Web.UI.Client/src/less/components/editor.less b/src/Umbraco.Web.UI.Client/src/less/components/editor.less index bc84b0d35e..5713e8cc4d 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/editor.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/editor.less @@ -73,6 +73,11 @@ height: @editorHeaderHeight; } +.umb-editor-header .umb-button__button[disabled] { + // do not dim down the background color of disabled buttons in the header + background-color: unset; +} + .umb-editor-header__back { background: transparent; border: 0; diff --git a/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-menu.html b/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-menu.html index fe90fef07a..a7efaa505a 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-menu.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-menu.html @@ -8,6 +8,7 @@ show-caret="true" has-popup="true" is-expanded="dropdown.isOpen" + disabled="!actions || !actions.length" > From a9732cb2334868190cd19abecc7a31885591bae8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 6 Feb 2020 14:57:25 +0100 Subject: [PATCH 005/826] corrected button style to match new style --- .../src/views/propertyeditors/listview/listview.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.html index ee1847b430..55adb18c6e 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.html @@ -21,7 +21,7 @@
- From b893dd2c65e8c25eb1ffc9975a773afc64268c68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivo=20Kol=C3=A1=C5=99?= Date: Mon, 20 Apr 2020 11:53:26 +0200 Subject: [PATCH 006/826] - admin czech translation --- src/Umbraco.Web.UI/Umbraco/config/lang/cs.xml | 1587 +++++++++++++++-- 1 file changed, 1486 insertions(+), 101 deletions(-) diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/cs.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/cs.xml index fe7e8ac638..4126d1d224 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/cs.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/cs.xml @@ -1,8 +1,8 @@ - umbraco - http://umbraco.org + Umbraco komunita + https://our.umbraco.com/documentation/Extending-Umbraco/Language-Files Kultura a názvy hostitelů @@ -11,10 +11,13 @@ Změnit typ dokumentu Kopírovat Vytvořit + Exportovat Vytvořit balíček + Vytvořit skupinu Odstranit Deaktivovat Vyprázdnit koš + Aktivovat Exportovat typ dokumentu Importovat typ dokumentu Importovat balíček @@ -28,17 +31,64 @@ Znovu načíst uzly Znovu publikovat celý web Práva + Přejmenovat + Obnovit + Nastavit oprávnění pro stránku %0% + Kam zkopírovat + Kam přesunout + do struktury stromu pod + Choose where to copy the selected item(s) + Choose where to move the selected item(s) + bylo přesunuto + bylo zkopírováno + bylo smazáno Vrátit starší verzi Odeslat k publikování Odeslat k překladu + Nastavit skupinu Seřadit Přeložit Aktualizovat + Nastavit oprávnění + Odemknout + Vytvořit šablonu obsahu + Přeposlat pozvánku + + + Obsah + Administrace + Struktura + Ostatní + + + Povolit přístup k přiřazování kultury a názvů hostitelů + Povolit přístup k zobrazení protokolu historie uzlu + Povolit přístup k zobrazení uzlu + Povolit přístup ke změně typu dokumentu daného uzlu + Povolit přístup ke kopírování uzlu + Povolit přístup k vytváření uzlů + Povolit přístup k mazání uzlů + Povolit přístup k přesunutí uzlu + Povolit přístup k nastavení a změně veřejného přístupu k uzlu + Povolit přístup k publikování uzlu + Povolit přístup k zrušení publikování uzlu + Povolit přístup ke změně oprávnění pro uzel + Povolit přístup k vrácení uzlu do předchozího stavu + Povolit přístup k odeslání uzlu ke schválení před publikováním + Povolit přístup k odeslání uzlu k překladu + Povolit přístup ke změně pořadí uzlů + Povolit přístup k překladu uzlu + Povolit přístup k uložení uzlu + Povolit přístup k vytvoření šablony obsahu + + + Obsah + Info Přístup zakázán. Přidat novou doménu - odebrat + Odebrat Neplatný uzel. Neplatný tvar domény. Doména už byla přiřazena. @@ -49,16 +99,17 @@ Doména '%0%' už byla přiřazena Doména '%0%' byla aktualizována Editace aktuálních domén + + Dědit Kultura nebo dědění kultury po nadřazeném uzlu. Vztahuje se také
na aktivní uzel.]]>
Domény - - Zobrazení pro - + Zrušit výběr Vybrat Dělat něco jiného Tučně @@ -77,15 +128,62 @@ Číslovaný seznam Vložit makro Vložit obrázek + Publikovat a zavřít + Publikovat s potomky Editovat vztahy + Zpět na seznam Uložit + Uložit a zavřít Uložit a publikovat + Uložit a naplánovat Uložit a odeslat ke schválení Náhled + Uložit zobrazení seznamu + Naplánovat + Náhled Náhled je deaktivován, protože není přiřazena žádná šablona Vybrat styl Zobrazit styly Vložit tabulku + Generovat modely a zavřít + Uložit a generovat modely + Zpět + Znovu + Obnovit + Smazat štítek + Zrušit + Potvrdit + Další možnosti publikování + + + Zobrazení pro + Obsah smazán + Obsah nepublikován + Obsah nepublikován pro jazyky: %0% + Obsah publikován + Obsah publikován pro jazyky: %0% + Obsah uložen + Obsah uložen pro jazyky: %0% + Obsah přesunut + Obsah zkopírován + Obsah vrácen zpět + Obsah odeslán k publikování + Obsah odeslán k publikování pro jazyky: %0% + Seřadit podřízené položky prováděné uživatelem + Kopírovat + Publikovat + Publikovat + Přesunout + Uložit + Uložit + Smazat + Nepublikovat + Nepublikovat + Vrátit zpět + Odeslat k publikování + Odeslat k publikování + Seřadit + Historie (všechny jazyky) Abyste změnili typ dokumentu pro zvolený obsah, nejprve jej vyberte ze seznamu typů platných pro tohle umístění. @@ -107,7 +205,14 @@ Nelze dokončit mapování vlastností, neboť nejméně jedna z vlastností má definováno více než jedno mapování. Jsou zobrazeny pouze alternativní typy platné pro aktuální umístění. + + Nepodařilo se vytvořit složku pod rodičem s ID %0% + Nepodařilo se vytvořit složku pod rodičem s názvem %0% + Název složky nesmí obsahovat nepovolené znaky. + Odstranění položky se nezdařilo: %0% + + Is Published O této stránce Alias (jak byste popsali obrázek přes telefon) @@ -124,45 +229,146 @@ Tato položko byla změněna po publikování Tato položka není publikována Naposledy publikováno + There are no items to show + There are no items to show in the list. + No child items have been added + No members have been added Typ média Odkaz na položky medií Skupina členů Role Typ člena + No changes have been made Nevybráno žádné datum Titulek stránky + This media item has no link + No content can be added for this item Vlastnosti Tento dokument je publikován, ale není viditelný, protože jeho rodič '%0%' publikován není + Tato jazyková verze je publikována, ale není viditelná, protože její rodič '%0%' publikován není Jejda: tento dokument je publikován, ale není v mezipaměti (vnitřní chyba) + Could not get the url + This document is published but its url would collide with content %0% + This document is published but its url cannot be routed Publikovat + Published + Published (pending changes)> Stav publikování + Publish with descendants to publish %0% and all content items underneath and thereby making their content publicly available.]]> + Publish with descendants to publish the selected languages and the same languages of content items underneath and thereby making their content publicly available.]]> Datum publikování Datum ukončení publikování Datum odebrání + Set date Třídění je aktualizováno Abyste uzly setřídili, jednoduše je přetáhněte anebo klikněte na jednu z hlaviček sloupce. Podržením "shift" nebo "control" při výběru můžete označit uzlů více. Statistika Titulek (volitelně) + Alternative text (optional) Typ Nepublikovat + Draft + Not created Naposledy změněno Datum/čas poslední změny dokumentu Odebrat soubor(y) + Click here to remove the image from the media item + Click here to remove the file from the media item URL adresa dokumentu Člen skupin(y) Není člen skupin(y) Podřízené položky Cíl + This translates to the following time on the server: + What does this mean?]]> + Are you sure you want to delete this item? + Are you sure you want to delete all items? + Property %0% uses editor %1% which is not supported by Nested Content. + No content types are configured for this property. + Add element type + Select element type + Select the group whose properties should be displayed. If left blank, the first group on the element type will be used. + Enter an angular expression to evaluate against each item for its name. Use + to display the item index + Add another text box + Remove this text box + Content root + Include drafts: also publish unpublished content items. + This value is hidden. If you need access to view this value please contact your website administrator. + This value is hidden. + What languages would you like to publish? All languages with content are saved! + What languages would you like to publish? + What languages would you like to save? + All languages with content are saved on creation! + What languages would you like to send for approval? + What languages would you like to schedule? + Select the languages to unpublish. Unpublishing a mandatory language will unpublish all languages. + Published Languages + Unpublished Languages + Unmodified Languages + These languages haven't been created + Ready to Publish? + Ready to Save? + Send for approval + Select the date and time to publish and/or unpublish the content item. + Create new + Paste from clipboard + This item is in the Recycle Bin + + + Vytvořit novou šablonu obsahu z '%0%' + Prázdná + Vybrat obsahovou šablonu + Šablona obsahu byla vytvořena + Šablona obsahu byla vytvořena z '%0%' + Již existuje jiná šablona obsahu se stejným názvem + Šablona obsahu je předdefinovaný obsah, který si editor může vybrat jako základ pro vytváření nového obsahu Klikněte pro nahrání + nebo kliknutím sem vyberte soubory + Sem můžete přetáhnout a nahrát soubory. + Tento soubor nelze nahrát, nemá povolený typ souboru + Maximální velikost souboru je + Nejvyšší složka médií + Nepodařilo se přesunout média + Nadřazené a cílové složky nemohou být stejné + Médium se nepodařilo zkopírovat + Nepodařilo se vytvořit složku pod nadřazeným id %0% + Nepodařilo se přejmenovat složku s id %0% + Přetáhněte své soubory do oblasti + + + Vytvořit nového člena + Všichni členové + Členské skupiny nemají žádné další vlastnosti pro úpravy. Kde chcete vytvořit nový %0% Vytvořit položku pod + Vyberte typ dokumentu, pro který chcete vytvořit šablonu obsahu + Zadejte název složky Vyberte typ a titulek "typy dokumentů".]]> + Typy dokumentů v části Nastavení.]]> + Vybraná stránka ve stromu obsahu neumožňuje vytváření žádných stránek pod ní. + Oprávnění k úpravám pro tento typ dokumentu + Vytvořit nový typ dokumentu + Typy dokumentů v části Nastavení změnou možnosti Povolit jako root v části Oprávnění.]]> "typy medií".]]> + Vybraná média ve stromu neumožňuje vytváření pod nimi žádná další média. + Upravit oprávnění pro tento typ média + Typ dokumentu bez šablony + Nová složka + Nový datový typ + Nový skript JavaScript + Nová prázdná částečná šablona + Nové makro pro částečnou šablonu + Nová částečná šablona ze snippetu + Nové makro částečné šablony ze snippetu + Nové makro pro částečnou šablonu (bez makra) + Nový soubor stylů - stylopis + Nový soubor stylů Rich Text editoru Prohlédnout svůj web @@ -174,35 +380,42 @@ Vítejte - Stay - Discard changes - You have unsaved changes - Are you sure you want to navigate away from this page? - you have unsaved changes + Zůstat zde + Zahodit změny + Máte neuložené změny + Opravdu chcete opustit tuto stránku? Máte neuložené změny. + Publikování zviditelní vybrané položky na webu. + Zrušení publikování odstraní vybrané položky a všechny jejich potomky z webu. + Zrušení publikování odstraní tuto stránku a všechny její potomky z webu. + Máte neuložené změny. Provedením změn typu dokumentu změny zahodíte. - Done - Deleted %0% item - Deleted %0% items - Deleted %0% out of %1% item - Deleted %0% out of %1% items - Published %0% item - Published %0% items - Published %0% out of %1% item - Published %0% out of %1% items - Unpublished %0% item - Unpublished %0% items - Unpublished %0% out of %1% item - Unpublished %0% out of %1% items - Moved %0% item - Moved %0% items - Moved %0% out of %1% item - Moved %0% out of %1% items - Copied %0% item - Copied %0% items - Copied %0% out of %1% item - Copied %0% out of %1% items + Hotovo + Smazána %0% položka + Smazáno %0% položek + Smazána %0% z %1% položek + Smazáno %0% z %1% položek + Publikována %0% položka + Publikováno %0% položek + Publikována %0% z %1% položek + Publikováno %0% z %1% položek + Zrušeno publikování %0% položky + Zrušeno publikování %0% položek + Zrušeno publikování %0% z %1% položek + Zrušeno publikování %0% z %1% položek + Přesunuta %0% položka + Přesunuto %0% položek + Přesunuta %0% z %1% položek + Přesunuto %0% z %1% položek + Zkopírována %0% položka + Zkopírováno %0% položek + Zkopírována %0% z %1% položek + Zkopírováno %0% z %1% položek + Titulek odkazu + Odkaz + Kotva / dotaz Název Spravovat názvy hostitelů Zavřít toto okno @@ -213,6 +426,7 @@ Vyjmout Editovat položku slovníku Editovat jazyk + Edit selected media Vložit místní odkaz Vložit znak Vložit grafický titulek @@ -220,14 +434,20 @@ Vložit odkaz Kliknout pro přidání makra Vložit tabulku + Tím se odstraní jazyk + Změna kultury jazyka může být náročná operace a bude mít za následek opětovné sestavení mezipaměti obsahu a indexů Naposledy editováno Odkaz Místní odkaz: Při používání místních odkazů vložte znak "#" před odkaz Otevřít v novém okně? + Nastavení makra Toto makro nemá žádné vlastnosti, které by bylo možno editovat Vložit Editovat oprávnění pro + Nastavit oprávnění pro + Nastavit oprávnění pro %0% pro skupinu %1% + Vyberte skupiny uživatelů, pro které chcete nastavit oprávnění Položky koše jsou nyní mazány. Nezavírejte, prosím, toto okno, dokud operace probíhá Koš je nyní prázdný Odebrání položek z koše způsobí jejich trvalé odstranění @@ -243,21 +463,109 @@ Klikněte na obrázek pro zobrazení v plné velikosti Vybrat položku Zobrazit položku mezipaměti + Navázat na originál + Včetně potomků + Nejpřátelštější komunita + Odkaz na stránku + Otevře propojený dokument v novém okně nebo na kartě + Odkaz na média + Vybrat počáteční uzel obsahu + Vybrat média + Vybrat typ média + Vybrat ikonu + Vybrat položku + Vybrat odkaz + Vybrat makro + Vybrat obsah + Vybrat typ obsahu + Vybrat počáteční uzel média + Vybrat člena + Vybrat skupinu členů + Vybrat typ člena + Vybrat uzel + Vybrat sekce + Vybrat uživatele + Nebyly nalezeny žádné ikony + Pro toto makro neexistují žádné parametry + K dispozici nejsou žádná makra + Externí poskytovatelé přihlášení + Podrobnosti o výjimce + Stacktrace + Vnitřní výjimka + Propojit se + Odpojit se + účet + Vybrat editora + Vybrat snippet + Tímto odstraníte uzel a všechny jeho jazyky. Pokud chcete smazat pouze jeden jazyk, měli byste zrušit publikování uzlu v tomto jazyce. + + + Nejsou žádné položky ve slovníku. %0%' níže.
Můžete přidat další jazyky v nabídce 'jazyky' nalevo.]]>
Název jazyka + + Přehled slovníku + + + Konfigurovaní vyhledávače + Zobrazuje vlastnosti a nástroje pro libovolný konfigurovaný vyhledávač (např. pro víceindexový vyhledávač) + Hodnoty pole + Stav + Stav indexu a jeho čitelnost + Indexery + Informace o indexu + Uvádí vlastnosti indexu + Spravovat indexy Examine + Umožňuje zobrazit podrobnosti každého indexu a poskytuje některé nástroje pro správu indexů + Znovu vytvořit index + V závislosti na tom, kolik obsahu je na vašem webu, může to chvíli trvat.
Nedoporučuje se znovu vytvářet index v době vysokého provozu na webu nebo při úpravách obsahu editory. + ]]> +
+ Vyhledávače + Prohledat index a zobrazit výsledky + Nástroje + Nástroje pro správu indexu + pole + Index nelze číst a bude nutné jej znovu sestavit + Proces trvá déle, než se očekávalo, zkontrolujte Umbraco log a zkontrolujte, zda během této operace nedošlo k chybám + Tento index nelze znovu sestavit, protože nemá přiřazen + IIndexPopulator Zadejte Vaše uživatelské jméno Zadejte Vaše heslo + Potvrďte heslo Pojmenujte %0%... Zadejte jméno... + Zadejte e-mail... + Zadejte uživatelské jméno... + Popisek... + Zadejte popis... Pište pro vyhledání... Pište pro filtrování... + Pište pro vložení štítků (po každém stiskněte klávesu Enter)... + Vložte svůj e-mail + Vložte zprávu... + Vaše uživatelské jméno je obvykle váš e-mail + #hodnota or ?klíč=hodnota + Vložte alias... + Generování aliasu... + Vytvořit vlastní zobrazení seznamu + Odebrat vlastní zobrazení seznamu + Typ obsahu, typ média nebo typ člena s tímto aliasem již existuje + + + Přejmenováno + Sem zadejte nový název složky + %0% přejmenováno na %1% Přidat předlohu @@ -271,6 +579,15 @@ Související stylopisy Zobrazit jmenovku Šířka a výška + Všechny typy vlastností a údaje o nich + použití tohoto datového typu bude trvale smazáno, potvrďte, že je chcete odstranit + Ano, smazat + a všechny typy vlastností a data vlastností používající tento typ dat + Vyberte složku, kterou chcete přesunout + do stromové struktury níže + byla přesunuta pod + %0% vymažete vlastnosti a jejich data z následujících položek]]> + Rozumím, že tato akce odstraní vlastnosti a data založená na tomto datovém typu Vaše data byla uložena, ale než budete moci publikovat tuto stránku, je třeba odstranit některé chyby: @@ -286,10 +603,12 @@ %0% není ve správném formátu + Ze serveru byla přijata chyba Použití daného typu souboru bylo zakázáno adminitrátorem UPOZORNĚNÍ! I když CodeMirror je dle konfigurace povolený, je zakázaný v Internet Exploreru, protože není dost stabilní. Vyplňte, prosím, alias i název nového typu vlastností! Vyskytl se problém při čtení/zápisu do určeného souboru nebo adresáře + Chyba při načítání skriptu částečné šablony (soubor: %0%) Uveďte, prosím, titulek Vyberte, prosím, typ Chystáte se obrázek zvětšit více, než je jeho původní rozměr. Opravdu chcete pokračovat? @@ -298,34 +617,43 @@ Žádne aktivní styly nejsou dostupné Umístěte, prosím, kurzor nalevo od těch dvou buňek, které chcete sloučit Nemužete rozdělit buňku, která nebyla sloučená. + Tato vlastnost je neplatná + Volby O... Akce Akce Přidat Alias + Vše Jste si jistí? + Zpět + Zpět na přehled Okraj o Zrušit Okraj buňky Vybrat + Vyčistit Zavřít Zavřít okno Komentovat Potvrdit + Omezit Zachovat proporce + Obsah Pokračovat Kopírovat Vytvořit - Databáse + Databáze Datum Výchozí Odstranit Odstraněno Odstraňování... Vzhled + Slovník Rozměry Dolů Stáhnout @@ -334,55 +662,85 @@ Prvky Email Chyba + Pole Najít + První + Focal point + Obecné + Skupiny + Skupina Výška Nápověda + Skrýt + Historie Ikona + Id Import + Zahrnout podsložky do vyhledávání + Info Vnitřní okraj Vložit Instalovat + Neplatné Vyrovnat + Popisek Jazyk + Poslední Rozvržení + Odkazy Nahrávání Zamčeno Přihlášení Odhlášení Odhlášení Makro + Povinné + Zpráva Přesunout Název Nový Následující Ne z + Vypnuto OK Otevřít + Zapnuto nebo + Seřadit podle Heslo Cesta Moment, prosím... Předchozí Vlastnosti + Obnovit Email pro obdržení formulářových dat Koš + Váš koš je prázdný + Znovu načíst Zbývající + Odebrat Přejmenovat Obnovit Povinné + Načíst Zopakovat Oprávnění + Plánované publikování Hledat + Litujeme, ale nemůžeme najít to, co hledáte. + Nebyly přidány žádné položky Server + Nastavení Zobrazit Zobrazit stránku při odeslání Rozměr Seřadit - Submit - - Typ - Pro hledání pište... + Stav + Potvrdit + Zadejte + Pište pro vyhledávání... + pod Nahoru Aktualizovat Povýšit @@ -397,18 +755,57 @@ Ano Složka Výsledky hledání - Reorder - I am done reordering + Přesunout + Skončil jsem s přesouváním + Náhled + Změnit heslo + na + Seznam + Ukládám... + aktuální + Vložené + vybrané + Další + Články + Videa + Vyčistit + Instalování + + + Modrá + + + Přidat skupinu + Přidat vlastnost + Přidat editor + Přidat šablonu + Přidat vnořený uzel + Přidat potomka + Upravit datový typ + Navigace v sekcích + Klávesové zkratky + zobrazit klávesové zkratky + Přepnout zobrazení seznamu + Přepnout povolení jako root + Okomentovat/Odkomentovat řádky + Odebrat řádek + Kopírovat řádky nahoru + Kopírovat řádky dolů + Přesunout řádky nahoru + Přesunout řádky dolů + Obecný + Editor + Přepnout povolení jazykových verzí - Background color - Bold - Text color + Barva pozadí + Tučně + Barva písma Font Text - Page + Stránka Instalátor se nemůže připojit k databázi. @@ -441,7 +838,7 @@ Heslo výchozího uživatele bylo úspěšně změněno od doby instalace!

Netřeba nic dalšího dělat. Klikněte na Následující pro pokračování.]]> Heslo je změněno! Mějte skvělý start, sledujte naše uváděcí videa - Kliknutím na tlačítko následující (nebo modifikováním umbracoConfigurationStatus v souboru web.config) přijímáte licenci tohoto software tak, jak je uvedena v poli níže. Upozorňujeme, že tato distribuce umbraca se skládá ze dvou různých licencí, open source MIT licence pro framework a umbraco freeware licence, která pokrývá UI. + Kliknutím na tlačítko následující (nebo modifikováním umbracoConfigurationStatus v souboru web.config) přijímáte licenci tohoto software tak, jak je uvedena v poli níže. Upozorňujeme, že tato distribuce Umbraca se skládá ze dvou různých licencí, open source MIT licence pro framework a umbraco freeware licence, která pokrývá UI. Není nainstalováno. Dotčené soubory a složky Další informace o nastavování oprávnění pro umbraco zde @@ -515,8 +912,8 @@ Stiskněte "následující" pro spuštění průvodce.]]> - Kód kultury - Název kultury + Kód jazyka + Název jazyka Byli jste nečinní a odhlášení proběhne automaticky za @@ -531,8 +928,100 @@ Šťastný bláznivý pátek Šťastnou kočkobotu přihlašte se níže + Přihlásit se pomocí Relace vypršela © 2001 - %0%
umbraco.org

]]>
+ Zapomenuté heslo? + Na uvedenou adresu bude zaslán e-mail s odkazem pro obnovení hesla + Pokud odpovídá našim záznamům, bude na zadanou adresu zaslán e-mail s pokyny k obnovení hesla + Zobrazit heslo + Skrýt heslo + Vrátit se na přihlašovací obrazovku + Zadejte nové heslo + Vaše heslo bylo aktualizováno + Odkaz, na který jste klikli, je neplatný nebo jeho platnost vypršela + Umbraco: Resetování hesla + + + + + + + + + + + +
+ + + + + +
+ +
+ +
+
+ + + + + + +
+
+
+ + + + +
+ + + + +
+

+ Vyžadováno resetování hesla +

+

+ Vaše uživatelské jméno pro přihlášení do back-office Umbraco je: %0% +

+

+ + + + + + +
+ + Kliknutím na tento odkaz obnovíte své heslo + +
+

+

Pokud nemůžete kliknout na odkaz, zkopírujte a vložte tuto adresu URL do okna prohlížeče:

+ + + + +
+ + %1% + +
+

+
+
+


+
+
+ + + ]]>
Ovládací panel @@ -555,6 +1044,7 @@ Upravte vaše oznámení pro %0% + Nastavení oznámení bylo uloženo pro - Hi %0%

+ Následující jazyky byly změněny %0% + Ahoj %0%

Toto je automatická zpráva informující Vás, že úloha '%1%' byla provedena na stránce '%2%' @@ -595,14 +1086,68 @@

Mějte hezký den!

Zdraví umbraco robot

]]>
+ Byly změněny následující jazyky:

+ %0% + ]]>
[%0%] Upozornění o %1% na %2% Upozornění + Akce + Vytvořeno + Vytvořit balíček a výběrem balíčku. Balíčky umbraco mají obvykle přípony ".umb" nebo ".zip". ]]> + Tím se balíček odstraní + Přetáhněte sem pro nahrání + Zahrnout všechny podřízené uzly + nebo kliknutím sem vyberte soubor balíčku + Nahrát balíček + Nainstalujte místní balíček výběrem ze svého počítače. Instalujte pouze balíčky ze zdrojů, které znáte a kterým důvěřujete + Nahrát další balíček + Zrušit a nahrát další balíček + Přijímám + podmínky použití + Cesta k souboru + Absolutní cesta k souboru (ie: /bin/umbraco.bin) + Nainstalováno + Nainstalované balíčky + Instalovat místní + Dokončit + Tento balíček nemá žádné zobrazení konfigurace + Zatím nebyly vytvořeny žádné balíčky + Nemáte nainstalované žádné balíčky + Balíčky v pravém horním rohu obrazovky.]]> + Akce balíčku + Web autora + Obsah balíčku + Soubory balíčku + URL ikony + Nainstalovat balíček + Licence + URL licence + Vlastnosti balíčku + Hledat balíčky + Výsledky pro + Nemohli jsme nic najít + Zkuste prosím vyhledat jiný balíček nebo procházet jednotlivé kategorie + Oblíbené + Nové + + karma body + Informace + Vlastník + Přispěvatelé + Vytvořeno + Aktuální verze + .NET verze + Počet stažení + Počet lajků + kompatibilita + Tento balíček je kompatibilní s následujícími verzemi Umbraco, jak ohlásili členové komunity. Plnou kompatibilitu nelze zaručit u verzí hlášených pod 100% + Externí zdroje Autor Dokumentace Meta data balíčku @@ -621,6 +1166,17 @@ Upozornění: všechny dokumenty, media atd. závislé na položkách, které odstraníte, přestanou pracovat a mohou vést k nestabilitě systému, takže odinstalovávejte opatrně. Jste-li na pochybách, kontaktujte autora balíčku.]]>
Verze balíčku + Upgradování z verze + Balíček je již nainstalován + Tento balíček nelze nainstalovat, vyžaduje minimální verzi Umbraco + Odinstalovávám... + Stahuji... + Importuji... + Instaluji... + Restartuji, prosím čekejte... + Vše je hotovo, váš prohlížeč se nyní obnoví, prosím čekejte... + Klepnutím na tlačítko „Dokončit“ dokončete instalaci a znovu načtěte stránku. + Nahrávám balíček... Vložit s úplným formatováním (nedoporučeno) @@ -629,9 +1185,9 @@ Vložit, ale odstranit formátování (doporučeno) - Ochrana prostřednictvím rolí - použijte členské skupiny umbraca.]]> - Musíte vytvořit členskou skupinu před tím, než můžete použít autentizaci prostřednictvím rolí + Ochrana prostřednictvím rolí + použijte členské skupiny umbraca.]]> + Musíte vytvořit členskou skupinu před tím, než můžete použít autentizaci prostřednictvím rolí Chybová stránka Použita, když jsou lidé přihlášení, ale nemají přístup Vyberte, jak omezit přístup k této stránce @@ -640,16 +1196,28 @@ Přihlašovací stránka Vyberte stránku, která obsahuje přihlašovací formulář Odstranit ochranu + %0%?]]> Vyberte stránky, které obsahují přihlašovací formulář a chybová hlášení Vyberte role, které mají přístup k této stránce + %0%]]> + %0%]]> + Ochrana konkrétních členů + Pokud si přejete udělit přístup konkrétním členům Nastavte přihlašovací jmého a heslo pro tuto stránku Jednouživatelská ochrana Jestliže chcete nastavit jenom jednoduchou ochranu prostřednictvím uživatelského jména a hesla + Nedostatečná uživatelská oprávnění k publikování všech potomků + + @@ -659,7 +1227,9 @@ - Zahrnout nepublikované podřízené stránky + + + Ověření se nezdařilo pro požadovaný jazyk '% 0%'. Tento jazyk byl uložen, ale nezveřejněn. Probíhá publikování - počkejte, prosím... %0% ze %1% stránek bylo publikováno... %0% byla publikována @@ -668,23 +1238,49 @@ ok pro publikování %0% a tedy zveřejnění jejího obsahu.

Můžete publikovat tuto stránku a všechny její podstránky zatrhnutím publikovat všchny podstránky níže. ]]>
+ Zahrnout nepublikované podřízené stránky Nenakonfigurovali jste žádné schválené barvy + + Můžete vybrat pouze položky typu (typů): %0% + Vybrali jste aktuálně odstraněnou položku obsahu nebo položku v koši + Vybrali jste aktuálně odstraněné položky obsahu nebo položky v koši + + + Smazaná položka + Vybrali jste aktuálně odstraněnou položku média nebo položku v koši + Vybrali jste aktuálně odstraněné položky médií nebo položky médií v koši + V koši + + zadejte externí odkaz + zvolte interní stránku + Nadpis + Odkaz + Otevřít v novém okně + zadejte titulek + Zadejte odkaz + Přidat vnější odkaz Přidat vnitřní odkaz Přidat - Nadpis Vnitřní stránka URL Posunout dolů Posunout nahoru - Otevřít v novém okně Odebrat odkaz + + Zrušit oříznutí + Uložit oříznutí + Přidat nové oříznutí + Hotovo + Vrátit změny + + Vyberte verzi, kterou chcete porovnat s aktuální verzí Současná verze Červený text nebude ve vybrané verzi zobrazen, zelený znamená přidaný].]]> Dokument byl vrácen na starší verzi @@ -697,20 +1293,29 @@ Editovat skriptovací soubor - Domovník Obsah + Formuláře + Média + Členové + Balíčky + Nastavení + Překlad + Uživatelé + + Domovník Kurýr Vývojář Průvodce nastavením Umbraca - Media - Členové Zpravodaje - Nastavení Statistiky - Překlad - Uživatelé Nápověda + + Příručky + Nejlepší videopříručky Umbraco + Navštívit our.umbraco.com + Navštívit umbraco.tv + Výchozí šablona Pro importování typu dokumentu vyhledejte soubor ".udt" ve svém počítači tak, že kliknete na tlačítko "Prohledat" a pak kliknete na "Import" (na následující obrazovce budete vyzváni k potvrzení) @@ -726,16 +1331,25 @@ Tento typ obsahu používá jako nadřazený typ obsahu. Záložky z nadřazených typů obsahu nejsou zobrazeny a mohou byt editovány pouze na nadřazených typech obsahu samotných Na této záložce nejsou definovány žádné vlastnosti. Pro vytvoření nové vlastnosti klikněte na odkaz "přidat novou vlastnost" nahoře. + Vytvořit odpovídající šablonu + Přidat ikonu - Sort order - Creation date + Řazení + Datum vytvoření Třídění bylo ukončeno. Abyste nastavili, jak mají být položky seřazeny, přetáhněte jednotlivé z nich nahoru či dolů. Anebo klikněte na hlavičku sloupce pro setřídění celé kolekce + Tato položka nemá vnořené položky k seřazení - Publikování bylo zrušeno doplňkem třetí strany + Validace + Před uložením položky je nutné opravit chyby + Chyba + Uloženo + Nedostatečná uživatelská oprávnění, operace nemohla být dokončena + Zrušeno + Operace byla zrušena doplňkem třetí strany Typ vlastnosti už existuje Typ vlastnosti vytvořen Datový typ: %1%]]> @@ -749,108 +1363,332 @@ Stylopis byl uložen bez chyb Datový typ byl uložen Položka slovníku byla uložena - Publikování se nezdařilo, protože nadřazená stránka není publikována Obsah byl publikován a je viditelný na webu + %0% dokumentů zveřejněných a viditelných na webu + %0% zveřejněných a viditelných na webu + %0% dokumentů zveřejněných pro jazyky %1% a viditelných na webu Obsah byl uložen Nezapomeňte na publikování, aby se změny projevily + Načasování publikování bylo aktualizováno + %0% uloženo Odeslat ke schválení Změny byly odeslány ke schválení - Medium bylo uloženo - Medium bylo uloženo bez chyb + %0% změn bylo odesláno ke schválení + Médium bylo uloženo + Médium bylo uloženo bez chyb Člen byl uložen + Skupina členů byla uložena Vlastnost stylopisu byla uložena Stylopis byl uložen Šablona byla uložena Chyba při ukládání uživatele (zkontrolujte log) Uživatel byl uložen Typ uživatele byl uložen + Skupina uživatelů byla uložena + Jazyky a názvy hostitelů byly uloženy + Při ukládání jazyků a názvů hostitelů došlo k chybě Soubor nebyl uložen soubor nemohl být uložen. Zkontrolujte, prosím, oprávnění k souboru Soubor byl uložen Soubor byl uložen bez chyb Jazyk byl uložen + Typ média byl uložen + Typ člena byl uložen + Skupina členů byla uložena Šablona nebyla uložena Ujistěte se, prosím, že nemáte 2 šablony se stejným aliasem Šablona byla uložena Šablona byla uložena bez chyb! Publikování obsahu bylo zrušeno + Varianta obsahu %0% nebyla publikována + Povinný jazyk '%0%' nebyl publikován. Všechny jazyky pro tuto položku obsahu nejsou nyní publikovány. Částečný pohled byl uložen Částečný pohled byl uložen bez chyb! Částečný pohled nebyl uložen Při ukládání souboru došlo k chybě. + Oprávnění byla uložena pro + Smazáno %0% skupin uživatelů + %0% bylo smazáno + Povoleno %0% uživatelů + Zakázáno %0% uživatelů + %0% je nyní povoleno + %0% je nyní zakázáno + Skupiny uživatelů byly nastaveny + Odemčeno %0% uživatelů + %0% je nyný odemčeno + Člen byl exportován do souboru + Při exportu člena došlo k chybě + Uživatel %0% byl smazán + Pozvat uživatele + Pozvánka byla znovu odeslána na %0% + Dokument nelze publikovat, protože %0% není publikována + Ověření pro jazyk '%0%' se nezdařilo + Typ dokumentu byl exportován do souboru + Při exportu typu dokumentu došlo k chybě + Datum vydání nemůže být v minulosti + Nelze naplánovat publikování dokumentu, protože %0% není publikována + Dokument nelze naplánovat na publikování, protože „%0%“ má datum zveřejnění později než nepovinný jazyk + Datum vypršení platnosti nemůže být v minulosti + Datum vypršení nemůže být před datem vydání + + Publikování bylo zrušeno doplňkem třetí strany + Publikování se nezdařilo, protože nadřazená stránka není publikována - Používá CSS syntaxi např.: h1, .redHeader, .blueTex + Přidat styl + Upravit styl + Styly Rich Text editoru + Definujte styly, které by měly být k dispozici v editoru formátovaného textu pro tuto šablonu stylů Editovat stylopis Editovat vlastnost stylopisu Název, který identifikuje vlastnost stylu v editoru formátovaného textu Náhled + Jak bude text vypadat v Rich Text editoru. + CSS identifikátor nebo třída + Používá syntaxi CSS, např. "h1" nebo ".redHeader" Styly + CSS, který by měl být použit v editoru RTF, např. "color:red;" + Kód + Rich Text editor + + Používá CSS syntaxi např.: h1, .redHeader, .blueTex + Nepodařilo se odstranit šablonu s ID %0% Editovat šablonu + Sekce Vložit obsahovou oblast Vložit zástupce obsahové oblasti + Vložit + Vyberte, co chcete vložit do své šablony Vložit položku slovníku + Položka slovníku je zástupný symbol pro překladatelný text, což usnadňuje vytváření návrhů pro vícejazyčné webové stránky. Vložit makro + + Makro je konfigurovatelná součást, která je skvělá pro opakovaně použitelné části návrhu, kde potřebujete předat parametry, jako jsou galerie, formuláře a seznamy. + Vložit pole stránky umbraco + Zobrazuje hodnotu pojmenovaného pole z aktuální stránky s možnostmi upravit hodnotu nebo alternativní hodnoty. + Částečná šablona + + Částečná šablona je samostatný soubor šablony, který lze vykreslit uvnitř jiné šablony. Je to skvělé pro opakované použití nebo pro oddělení složitých šablon. + Nadřazená šablona - Rychlá příručka k šablonovým značkám umbraca + Žádný master + Vykreslit podřízenou šablonu + @RenderBody(). + ]]> + Definujte pojmenovanou sekci + @section {...}. Ta může být vykreslena v konkrétní oblasti nadřazené šablony pomocí @RenderSection. + ]]> + Vykreslit pojmenovanou sekci + @RenderSection(name). Tím se vykreslí oblast podřízené šablony, která je zabalena do odpovídající definice @section[name] {...}. + ]]> + Název sekce + Sekce je povinná + @section, jinak se zobrazí chyba. + ]]> + Tvůrce dotazů + položky vráceny, do + zkopírovat do schránky + Chci + veškerý obsah + obsah typu "%0%" + z(e) + můj web + kde + a + je + není + před + před (včetně zvoleného datumu) + po + po (včetně zvoleného datumu) + rovná se + nerovná se + obsahuje + neobsahuje + větší než + větší nebo rovno + menší než + menší nebo rovno + Id + Název + Datum vytvoření + Datum poslední aktualizace + řadit podle + vzestupně + sestupně Šablona + + Rychlá příručka k šablonovým značkám umbraca - Image - Macro - Choose type of content - Choose a layout - Add a row - Add content - Drop content - Settings applied - This content is not allowed here - This content is allowed here - Click to embed - Click to insert image - Image caption... - Write here... - Grid Layouts - Layouts are the overall work area for the grid editor, usually you only need one or two different layouts - Add Grid Layout - Adjust the layout by setting column widths and adding additional sections - Row configurations - Rows are predefined cells arranged horizontally - Add row configuration - Adjust the row by setting cell widths and adding additional cells - Columns - Total combined number of columns in the grid layout - Settings - Configure what settings editors can change - Styles - Configure what styling editors can change - Allow all editors - Allow all row configurations + Obrázek + Makro + Vybrat typ obsahu + Vybrat rozvržení + Přidat řádek + Přidat obsah + Zahodit obsah + Nastavení aplikováno + Tento obsah zde není povolen + Tento obsah je zde povolen + Klepněte pro vložení + Klepnutím vložíte obrázek + Titulek obrázku... + Zde pište... + Rozvržení mřížky + Rozvržení je celková pracovní oblast pro editor mřížky, obvykle potřebujete pouze jedno nebo dvě různá rozvržení + Přidat rozvržení mřížky + Upravte rozvržení nastavením šířky sloupců a přidáním dalších sekcí + Konfigurace řádků + Řádky jsou předdefinované buňky uspořádané vodorovně + Přidat konfiguraci řádku + Upravte řádek nastavením šířky buněk a přidáním dalších buněk + Sloupce + Celkový počet sloupců v rozvržení mřížky + Nastavení + Nakonfigurujte, jaká nastavení mohou editoři změnit + Styly + Nakonfigurujte, co mohou editoři stylů změnit + Povolit všechny editory + Povolit všechny konfigurace řádků + Maximální počet položek + Nechte prázdné nebo nastavte na 0 pro neomezené + Nastavit jako výchozí + Vyberat navíc + Zvolit výchozí + jsou přidány + Varování + Odstraňujete konfiguraci řádku + + Odstranění názvu konfigurace řádku povede ke ztrátě dat pro veškerý existující obsah založený na této konfiguraci. + + + + Složení + Skupina + Nepřidali jste žádné skupiny + Přidat skupinu + Zděděno od + Přidat vlastnost + Požadovaný popisek + Povolit zobrazení seznamu + Nakonfiguruje položku obsahu tak, aby zobrazovala seznam svých potomků a seznam potomků, které je možné prohledávat, potomci se nebudou zobrazovat ve stromu + Povolené šablony + Vyberte, kteří editoři šablon mohou používat obsah tohoto typu + Povolit jako root + Povolit editorům vytvářet obsah tohoto typu v kořenovém adresáři stromu obsahu. + Povolené typy podřízených uzlů + Povolit vytváření obsahu zadaných typů pod obsahem tohoto typu. + Vybrat podřízený uzel + Zdědí záložky a vlastnosti z existujícího typu dokumentu. Nové záložky budou přidány do aktuálního typu dokumentu nebo sloučeny, pokud existuje záložka se stejným názvem. + Tento typ obsahu se používá ve složení, a proto jej nelze poskládat. + Nejsou k dispozici žádné typy obsahu, které lze použít jako složení. + Odebráním složení odstraníte všechna související data vlastností. Jakmile uložíte typ dokumentu, již není cesta zpět. + Vytvořit nové + Použít existující + Nastavení editoru + Konfigurace + Ano, smazat + bylo přesunuto pod + bylo zkopírováno pod + Vybrat složku, kterou chcete přesunout + Vybrat složku, kterou chcete kopírovat + ve stromové struktuře níže + Všechny typy dokumentů + Všechny dokumenty + Všechny média + použití tohoto typu dokumentu bude trvale smazáno, prosím potvrďte, že je chcete také odstranit. + použití tohoto typu média bude trvale smazáno, potvrďte, že je chcete také odstranit. + použití tohoto typu člena bude trvale smazáno, potvrďte, že je chcete také odstranit + a všechny dokumenty používající tento typ + a všechny mediální položky používající tento typ + a všichni členové používající tento typ + Člen může upravovat + Povolit editaci této vlastnosti členem na jeho stránce profilu + Obsahuje citlivá data + Skrýt tuto hodnotu vlastnosti před editory obsahu, kteří nemají přístup k prohlížení citlivých informací + Zobrazit v profilu člena + Povolit zobrazení této vlastnosti na stránce profilu člena + záložka nemá žádné řazení + Kde se toto složení používá? + Toto složení se v současnosti používá ve složení následujících typů obsahu: + Povolit různé jazyky + Povolit editorům vytvářet obsah tohoto typu v různých jazycích. + Povolit různé jazyky + Typ prvku + Je typ prvku + Typ prvku je určen k použití například ve vnořeném obsahu, nikoli ve stromu. + Jakmile byl typ dokumentu použit k vytvoření jedné nebo více položek obsahu, nelze jej změnit na typ prvku. + To neplatí pro typ prvku + V této vlastnosti jste provedli změny. Opravdu je chcete zahodit? + + + Přidat jazyk + Povinný jazyk + Před publikováním uzlu je nutné vyplnit vlastnosti v tomto jazyce. + Výchozí jazyk + Web Umbraco může mít nastaven pouze jeden výchozí jazyk. + Přepnutí výchozího jazyka může mít za následek chybějící výchozí obsah. + Nahradit nepřeložený obsah za + Žádné nahrazení nepřeloženého jazyka + Chcete-li povolit automatické zobrazení vícejazyčného obsahu v jiném jazyce, pokud není v požadovaném jazyce přeložen, vyberte jej zde. + Nahrazujicí jazyk + žádný + + + Přidat parametr + Upravit parametr + Zadejte název makra + Parametry + Definujte parametry, které by měly být k dispozici při použití tohoto makra. + Vyberte soubor makra pro částečnou šablonu + + + Stavební modely + to může chvíli trvat, nebojte se + Generované modely + Modely nelze vygenerovat + Generování modelů selhalo, viz výjimka v logu Umbraca + Přidat záložní pole + Náhradní pole + Přidat výchozí hodnotu + Výchozí hodnota Alternativní pole Alternativní text Velká a malá písmena Kódování Vybrat pole - Konvertovat + Konvertovat + Ano, převést konce řádků Nahrazuje nové řádky html tagem <br> Vlastní pole Ano, pouze datum + Formát a kódování Formátovat jako datum + Naformátuje hodnotu jako datum nebo datum s časem podle aktivního jazyka HTML kódování Nahradí speciální znaky jejich HTML ekvivalentem. Bude vloženo za hodnotou pole Bude vloženo před hodnotou pole Malá písmena + Upravit výstup Nic + Ukázka výstupu Vložit za polem Vložit před polem Rekurzivní + Ano, udělej to rekurzivní + Oddělovač Standardní pole Velká písmena Kódování URL @@ -861,7 +1699,7 @@ Podrobnosti překladu - Stáhnout xml DTD + Stáhnout XML DTD Pole Zahrnout podstránky Žádní uživatelé překladatelé nebyli nalezeni. Vytvořte, prosím, překladatele před tím, než začnete posílat obsah k překladu Stránka '%0%' byla poslána k překladu @@ -892,6 +1730,9 @@ Nahrát xml překladu + Obsah + Šablony obsahu + Média Prohlížeč mezipaměti Koš Vytvořené balíčky @@ -909,8 +1750,11 @@ Role Typy členů Typy dokumentů + Typy vztahů/vazeb Balíčky Balíčky + Částečné šablony + Makra částečných šablon Instalovat z úložiště Instalovat Runway Moduly Runway @@ -918,9 +1762,14 @@ Skripty Stylopisy Šablony - Oprávnění Uživatele - Typy Uživatelů + Prohlížeč logu Uživatelé + Nastavení + Šablony + Třetí strana + + Oprávnění uživatele + Typy uživatelů Nová aktualizace je připrvena @@ -929,23 +1778,46 @@ Chyba při kontrole aktualizace. Zkontrolujte, prosím, trasovací zásobník pro další informace + Přístupy + Na základě přiřazených skupin a počátečních uzlů má uživatel přístup k následujícím uzlům + Přiřadit přístup Administrátor Pole kategorie + Uživatel byl vytvořen Změnit heslo + Změnit fotku Změnit heslo + nebyl uzamčen + Heslo nebylo změněno Potvrdit heslo Můžete změnit své heslo pro přístup do administrace Umbraca vyplněním formuláře níže a kliknutím na tlačítko 'Změnit Heslo' Kanál obsahu + Vytvořit dalšího uživatele + Vytvořte nové uživatele a udělte mu přístup do Umbraco. Po vytvoření nového uživatele bude vygenerováno heslo, které s ním můžete sdílet. Popis Deaktivovat uživatele Typ dokumentu Editor Výtah + Neúspěšné pokusy o přihlášení + Přejít na uživatelský profil + Přidáním skupin přidělte přístup a oprávnění + Pozvat dalšího uživatele + Pozvěte nové uživatele, a poskytněte jim přístup do Umbraco. Uživatelům bude zaslán e-mail s pozvánkou a s informacemi o tom, jak se přihlásit do Umbraco. Pozvánky mají platnost 72 hodin. Jazyk + Nastavte jazyk, který uvidíte v nabídkách a dialogových oknech + Poslední datum uzamčení + Poslední přihlášení + Heslo bylo naposledy změněno Přihlašovací jméno Úvodní uzel v knihovně medií + Omezte knihovnu médií na konkrétní počáteční uzel + Úvodní uzly v knihovně medií + Omezte knihovnu médií na konkrétní počáteční uzly Sekce Deaktivovat přistup k Umbracu + se dosud nepřihlásil + Staré heslo Heslo Resetovat heslo Vyše heslo bylo změněno! @@ -959,13 +1831,526 @@ Nahradit oprávnění podřízených uzlů Nyní měníte oprávnění pro stránky: Vyberte stránky, pro které chcete měnit oprávnění + Odebrat fotografii + Výchozí oprávnění + Upřesnění oprávnění + Nastavte oprávnění pro konkrétní uzly + Profil Prohledat všechny podřízené uzly + Přidejte sekce, do kterých mají uživatelé přístup + Vybrat skupiny uživatelů + Nebyl vybrán žádný počáteční uzel + Nebyly vybrány žádné počáteční uzly Úvodní uzel v obsahu + Omezte strom obsahu na konkrétní počáteční uzel + Úvodní uzly obsahu + Omezte strom obsahu na konkrétní počáteční uzly + Uživatel byl naposledy aktualizován + byl vytvořen + Nový uživatel byl úspěšně vytvořen. Pro přihlášení do Umbraco použijte heslo níže. + Správa uživatelů Uživatelské jméno Oprávnění uživatele + Uživatelská skupina + byl pozván + Novému uživateli byla zaslána pozvánka s informacemi, jak se přihlásit do Umbraco. + Dobrý den, vítejte v Umbraco! Za pouhou 1 minutu budete moci používat Umbraco. Jenom od vás potřebujeme, abyste si nastavili heslo a přidali obrázek pro svůj avatar. + Vítejte v Umbraco! Vaše pozvánka bohužel vypršela. Obraťte se na svého správce a požádejte jej, aby jí znovu odeslal. + Nahrání vaší fotografie usnadní ostatním uživatelům, aby vás poznali. Kliknutím na kruh výše nahrajte svou fotku. Spisovatel + Změnit Váš profil Vaše nedávná historie Relace vyprší za + Pozvat uživatele + Vytvořit uživatele + Odeslat pozvánku + Zpět na seznam uživatelů + Umbraco: Pozvánka + + + + + + + + + + + +
+ + + + + +
+ +
+ +
+
+ + + + + + +
+
+
+ + + + +
+ + + + +
+

+ Zdravím Vás, %0%, +

+

+ Byli jste pozváni %1% do CMS Umbraco. +

+

+ Zpráva od %1%: +
+ %2% +

+ + + + + + +
+ + + + + + +
+ + Kliknutím na tento odkaz přijměte pozvání + +
+
+

Pokud nemůžete kliknout na odkaz, zkopírujte a vložte tuto adresu URL do okna prohlížeče:

+ + + + +
+ + %3% + +
+

+
+
+


+
+
+ + ]]>
+ Pozvat + Zasílám pozvání... + Smazat uživatele + Opravdu chcete smazat tento uživatelský účet? + Vše + Aktivní + Zakázané + Uzamčeno + Pozváno + Neaktivní + Jméno (A-Z) + Jméno (Z-A) + Nejnovější + Nejstarší + Poslední přihlášení + Nebyly přidány žádné skupiny uživatelů + + + Validace + Ověřit jako e-mailovou adresu + Ověřit jako číslo + Ověřit jako URL + ...nebo zadat vlastní ověření + Pole je povinné + Zadat chybovou zprávu pro vlastní validaci (volitelné) + Zadat regulární výraz + Zadat chybovou zprávu pro vlastní validaci (volitelné) + Musíte přidat alespoň + Můžete jen mít + položky + vybrané položky + Neplatné datum + Není číslo + Neplatný e-mail + Hodnota nemůže být nulová + Hodnota nemůže být prázdná + Hodnota je neplatná, neodpovídá správnému vzoru + Vlastní ověření + %1% více.]]> + %1% příliš mnoho.]]> + + + + Hodnota je nastavena na doporučenou hodnotu: '%0%'. + Hodnota byla nastavena na '%1%' pro XPath '%2%' v konfiguračním souboru '%3%'. + Očekávaná hodnota '%1%' pro '%2%' v konfiguračním souboru '%3%', ale nalezeno '%0%'. + Nalezena neočekávaná hodnota '%0%' pro '%2%' v konfiguračním souboru '%3%'. + + Vlastní chyby jsou nastaveny na '%0%'. + Vlastní chyby jsou aktuálně nastaveny na '%0%'. Před nasazením se doporučuje nastavit na '%1%'. + Vlastní chyby byly úspěšně nastaveny na '%0%'. + MacroErrors jsou nastaveny na '%0%'. + MakroErrors jsou nastaveny na '%0%', což zabrání úplnému načtení některých nebo všech stránek na vašem webu, pokud dojde k chybám v makrech. Náprava nastaví hodnotu na '%1%'. + MakroErrors jsou nyní nastaveny na '%0%'. + + Try Skip IIS Custom Errors je nastaveno na '%0%' a používáte verzi IIS '%1%'. + Try Skip IIS Custom Errors je aktuálně nastaveno na '%0%'. Doporučuje se nastavit %1% pro vaši verzi služby IIS (%2%). + Try Skip IIS Custom Errors úspěšně nastaveno na '%0%'. + + Soubor neexistuje: '%0%'. + '% 0%' v konfiguračním souboru '% 1%'.]]> + Došlo k chybě, zkontrolujte ji v logu: %0%. + Databáze - Databázové schéma je pro tuto verzi Umbraco správné + Bylo zjištěno %0% problémů se schématem vaší databáze (podrobnosti najdete v logu) + Při ověřování databázového schématu vůči aktuální verzi Umbraco byly zjištěny některé chyby. + Certifikát vašeho webu je platný. + Chyba ověření certifikátu: '%0%' + Platnost SSL certifikátu vašeho webu vypršela. + Platnost certifikátu SSL vašeho webu vyprší za %0% dní. + Chyba při pingování adresy URL %0% - '%1%' + Aktuálně prohlížíte web pomocí schématu HTTPS. + AppSetting 'Umbraco.Core.UseHttps' je v souboru web.config nastaven na 'false'. Jakmile vstoupíte na tento web pomocí schématu HTTPS, mělo by být nastaveno na 'true'. + AppSetting 'Umbraco.Core.UseHttps' je v souboru web.config nastaven na '%0%', vaše cookies %1% jsou označeny jako zabezpečené. + V souboru web.config se nepodařilo aktualizovat nastavení 'Umbraco.Core.UseHttps'. Chyba: %0% + + Povolit HTTPS + Nastaví nastavení umbracoSSL na true v appSettings v souboru web.config. + AppSetting 'Umbraco.Core.UseHttps' je nyní nastaveno na 'true' v souboru web.config, vaše cookies budou označeny jako zabezpečené. + Fix + Nelze opravit kontrolu pro porovnání hodnot pomocí 'ShouldNotEqual'. + Nelze opravit kontrolu pro porovnání hodnot pomocí 'ShouldEqual' s poskytnutou hodnotou. + Hodnota k opravě nebyla poskytnuta. + Režim kompilace ladění je zakázán. + Režim ladění je aktuálně povolen. Před spuštěním webu se doporučuje toto nastavení deaktivovat. + Režim ladění byl úspěšně deaktivován. + Režim sledování je deaktivován. + Režim sledování je aktuálně povolen. Před spuštěním se doporučuje toto nastavení deaktivovat. + Režim sledování byl úspěšně deaktivován. + Všechny složky mají nastavena správná oprávnění. + + %0%.]]> + %0%. Pokud nejsou psány, není třeba podniknout žádné kroky.]]> + Všechny soubory mají nastavena správná oprávnění. + + %0%.]]> + %0%. Pokud nejsou psány, není třeba podniknout žádné kroky.]]> + X-Frame-Options, které určuje, zda může být obsah webu zobrazen na jiném webu pomocí IFRAME.]]> + X-Frame-Options, které určuje, zda může být obsah webu zobrazen na jiném webu pomocí IFRAME.]]> + Nastavit záhlaví v Konfiguraci + Přidá hodnotu do sekce httpProtocol/customHeaders do web.config, aby se zabránilo tomu, že web může být zobrazen na jiném webu pomocí IFRAME. + Do souboru web.config bylo přidáno nastavení pro vytvoření záhlaví, které zabrání jinému webu, zobrazit tento web pomocí IFRAME. + Nelze aktualizovat soubor web.config. Chyba: %0% + X-Content-Type-Options použitá k ochraně před zranitelnostmi čichání MIME.]]> + X-Content-Type-Options použité k ochraně před zranitelnostmi čichání MIME nebyly nalezeny.]]> + Přidá hodnotu do sekce httpProtocol/customHeaders v souboru web.config, která chrání před zranitelnostmi MIME. + Do souboru web.config bylo přidáno nastavení pro vytvoření záhlaví, které chrání před zranitelnostmi MIME. + Strict-Transport-Security, také známo jako HSTS-header, bylo nalezeno.]]> + Strict-Transport-Security nebylo nalezeno.]]> + Do sekce httpProtocol/customHeaders v souboru web.config přidá záhlaví 'Strict-Transport-Security' s hodnotou 'max-age = 10886400'. Tuto opravu použijte pouze v případě, že vaše domény budou spuštěny s https po dobu příštích 18 týdnů (minimálně). + Do vašeho souboru web.config bylo přidáno záhlaví HSTS. + X-XSS-Protection bylo nalezeno.]]> + X-XSS-Protection bylo nalezeno.]]> + Přidá záhlaví 'X-XSS-Protection' s hodnotou '1; mode=block' do sekce httpProtocol/customHeaders v souboru web.config. + Záhlaví X-XSS-Protection bylo přidáno do vašeho souboru web.config. + + %0%.]]> + Nebyly nalezeny žádné hlavičky odhalující informace o technologii webových stránek. + V souboru Web.config nelze najít system.net/mailsettings. + V části system.net/mailsettings v souboru web.config není hostitel nakonfigurován. + Nastavení SMTP jsou správně nakonfigurována a služba funguje jak má. + Server SMTP konfigurovaný s hostitelem '%0%' a portem '%1%' nelze nalézt. Zkontrolujte prosím, zda jsou nastavení SMTP v souboru Web.config a v sekci system.net/mailsettings správná. + %0%.]]> + %0%.]]> +

Výsledky plánovaných kontrol Umbraco Health Checks provedených na %0% v %1% jsou následující:

%2%]]>
+ Stav Umbraco Health Check: %0% + Zkontrolovat všechny skupiny + Zkontrolovat skupinu + + Kontrola vyhodnocuje různé oblasti vašeho webu z hlediska nastavení osvědčených postupů, konfigurace, potenciálních problémů atd. Problémy lze snadno vyřešit stisknutím tlačítka. Můžete přidat své vlastní kontroly, podívejte se na dokumentaci pro více informací o vlastních kontrolách.

+ ]]> +
+ + + Zakázat sledování URL + Povolit sledování URL + Jazyk + Originální URL + Přesměrováno na + Správa URL přesměrování + Na tuto položku obsahu přesměrovávají následující adresy URL: + Nebyla provedena žádná přesměrování + Jakmile bude publikovaná stránka přejmenována nebo přesunuta, bude automaticky provedeno přesměrování na novou stránku. + Opravdu chcete odstranit přesměrování z '%0%' na '%1%'? + Přesměrování bylo odstraněno. + Chyba při odebírání URL přesměrování. + Toto odstraní přesměrování + Opravdu chcete zakázat sledování URL adres? + Sledování URL adres je nyní zakázáno. + Při deaktivaci sledování URL adres došlo k chybě, další informace naleznete v logu. + Sledování URL adres je nyní povoleno. + Chyba při povolení sledování URL adres, další informace lze nalézt v logu. + + + Žádné položky ze slovníku na výběr + + + %0% znaků.]]> + %1% je moc.]]> + + + Obsah s ID: {0} v koši souvisí s původním nadřazeným obsahem s ID: {1} + Média s ID: {0} v koši souvisí s původním nadřazeným médiem s ID: {1} + Tuto položku nelze automaticky obnovit + Neexistuje žádné místo, kde lze tuto položku automaticky obnovit. Položku můžete přesunout ručně pomocí stromu níže. + byla obnovena pod + + + Směr + Nadřazený s potomkem + Obousměrný + Nadřazená + Potomek + Počet + Vazby + Vytvořeno + Komentář + Název + Žádné vazby pro tento typ vazby. + Typ vazby + Vazby + + + Začínáme + Správa přesměrování + Obsah + Vítejte + Správa Examine + Stav publikování + Tvůrce modelů + Health Check + Profilování + Začínáme + Instalovat Umbraco formuláře + + + Jít zpět + Aktivní rozvržení: + Skočit do + skupina + prošlo + varování + selhalo + návrh + Kontrola prošla + Kontrola selhala + Otevřít hledání v backoffice + Otevřít/zavřít nápovědu backoffice + Otevřít/zavřít možnosti vašeho profilu + Otevřít kontextové menu pro + Aktuální jazyk + Přepnout jazyk na + Vytvořit novou složku + Částečná šablona + Makro částečné šablony + Člen + Datový typ + Prohledat přesměrování + Prohledat skupiny uživatelů + Prohledat uživatele + Vytvořit položku + Vytvořit + Upravit + Název + + + Závislosti + Tento datový typ nemá žádné závislosti. + Použito v dokumentových typech + Žádné vazby na typy dokumentů. + Použito v typech médií + Žádné vazby na typy médií. + Použito v typech členů + Žádné vazby na typy členů. + Použito v + Použito v dokumentech + Použito ve členech + Použito v médiích + + + Úrovně logování + Uložená vyhledávání + Celkem položek + Časové razítko + Úroveň + Stroj + Zpráva + Výjimka + Vlastnosti + Vyhledat na Googlu + Vyhledat zprávu na Googlu + Vyhledat na Bing + Vyhledat zprávu na Bing + Prohledat naše Umbraco + Vyhledat tuto zprávu na našich fórech a dokumentech Umbraco + Vyhledat Our Umbraco na Googlu + Prohledat Our Umbraco fóra pomocí Googlu + Prohledat Umbraco Source + Vyhledat ve zdrojovém kódu Umbraco na Github + Prohledat Umbraco Issues + Prohledat Umbraco Issues na Github + Smazat toto vyhledávání + Najít logy s ID požadavku + Najít logy se jmenným prostorem + Najít logy s názvem stroje + Otevřít + + + Kopírovat %0% + %0% z %1% + Odebrat všechny položky + + + Otevřít akce vlastností + + + Čekejte + Stav obnovení + Cache paměť + + + + Znovu načíst + Cache databáze + + Znovuvytvoření může být náročné. Použijte jej, když nestačí obnovení stránky, a domníváte se, že mezipaměť databáze nebyla správně vygenerována - což by naznačovalo možný kritický problém Umbraco. + ]]> + + Obnovit + Internals + + nebudete muset používat. + ]]> + + Sběr + Stav publikované mezipaměti + Mezipaměti + + + Profilování výkonu + + Umbraco aktuálně běží v režimu ladění. To znamená, že můžete použít vestavěný profiler výkonu k vyhodnocení výkonu při vykreslování stránek.

Pokud chcete aktivovat profiler pro konkrétní vykreslení stránky, jednoduše při požadavku na stránku jednoduše přidejte umbDebug=true do URL.

Pokud chcete, aby byl profiler ve výchozím nastavení aktivován pro všechna vykreslení stránky, můžete použít přepínač níže. Ve vašem prohlížeči nastaví soubor cookie, který automaticky aktivuje profiler. Jinými slovy, profiler bude ve výchozím nastavení aktivní pouze ve vašem prohlížeči, ne v ostatních.

+ ]]> +
+ Ve výchozím stavu aktivovat profiler + Přátelské připomenutí + + + Nikdy byste neměli nechat produkční web běžet v režimu ladění. Režim ladění je vypnut nastavením debug="false" na elementu compilation v souboru web.config. +

+ ]]> +
+ + + Umbraco v současné době neběží v režimu ladění, takže nemůžete použít vestavěný profiler. Takto by to mělo být pro produkční web. +

+

+ Režim ladění je zapnut nastavením debug="true" na elementu compilation v souboru web.config. +

+ ]]> +
+ + + Hodiny tréninkových videí Umbraco jsou blíž než si myslíte + + Chcete ovládnout Umbraco? Stačí strávit pár minut sledování jednoho z těchto videí o používání Umbraco. Nebo navštivte umbraco.tv , kde najdete ještě více videí o Umbraco

+ ]]> +
+ Chcete-li začít + + + Začněte zde + Tato část obsahuje stavební bloky pro váš web Umbraco. Podle níže uvedených odkazů se dozvíte více o práci s položkami v části Nastavení + Zjistit více + + v sekci Dokumentace v Our Umbraco + ]]> + + + fóru komunity + ]]> + + + výuková videa (některá jsou zdarma, jiná vyžadují předplatné) + ]]> + + + nástrojích zvyšujících produktivitu a komerční podpoře + ]]> + + + školení a certifikace + ]]> + + + + Vítejte v přátelském CMS + Děkujeme, že jste si vybrali Umbraco - myslíme si, že by to mohl být začátek něčeho krásného. I když se to může zpočátku zdát ohromující, udělali jsme hodně pro to, aby byla křivka učení co nejhladší a nejrychlejší. + + + Umbraco formuláře + Vytvářejte formuláře pomocí intuitivního rozhraní drag and drop. Od jednoduchých kontaktních formulářů, které odesílají e-maily, až po pokročilé dotazníky, které se integrují do systémů CRM. Vaši klienti to budou milovat!
From 02a8beca2725c469edd71ed32c11dafb59c459c3 Mon Sep 17 00:00:00 2001 From: Bjarne Fyrstenborg Date: Fri, 1 May 2020 15:40:45 +0200 Subject: [PATCH 007/826] Replace umb-overlay using overlayService.ysod --- .../listview/listview.controller.js | 29 ++++++------------- .../propertyeditors/listview/listview.html | 7 ----- 2 files changed, 9 insertions(+), 27 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.controller.js index 16c1be98a0..18ff61608b 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.controller.js @@ -227,26 +227,21 @@ function listViewController($scope, $interpolate, $routeParams, $injector, $time if (err.status && err.status >= 500) { // Open ysod overlay - $scope.ysodOverlay = { - view: "ysod", - error: err, - show: true - }; + overlayService.ysod(err); } $timeout(function () { $scope.bulkStatus = ""; $scope.actionInProgress = false; - }, - 500); + }, 500); - if (successMsgPromise) { - localizationService.localize("bulk_done") - .then(function (v) { - successMsgPromise.then(function (successMsg) { - notificationsService.success(v, successMsg); - }) - }); + if (successMsgPromise) + { + localizationService.localize("bulk_done").then(function (v) { + successMsgPromise.then(function (successMsg) { + notificationsService.success(v, successMsg); + }) + }); } } @@ -271,7 +266,6 @@ function listViewController($scope, $interpolate, $routeParams, $injector, $time with simple values */ $scope.getContent = function (contentId) { - $scope.reloadView($scope.contentId, true); } @@ -327,8 +321,6 @@ function listViewController($scope, $interpolate, $routeParams, $injector, $time }); }; - - $scope.makeSearch = function() { if ($scope.options.filter !== null && $scope.options.filter !== undefined) { $scope.options.pageNumber = 1; @@ -408,7 +400,6 @@ function listViewController($scope, $interpolate, $routeParams, $injector, $time dialog.title = value; overlayService.open(dialog); }); - }; function performDelete() { @@ -704,8 +695,6 @@ function listViewController($scope, $interpolate, $routeParams, $injector, $time // set what we've got on the result result[alias] = value; }); - - } function isDate(val) { diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.html index ee1847b430..2eed825c7a 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.html @@ -230,11 +230,4 @@
- - - From 1d6849c578418bc6d9255b38011af8a9531239d5 Mon Sep 17 00:00:00 2001 From: Ronald Barendse Date: Tue, 9 Jun 2020 15:12:09 +0200 Subject: [PATCH 008/826] Return null in IsValue for PropertyValueLevel.Inter and Object --- .../PropertyEditors/PropertyValueConverterBase.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Umbraco.Core/PropertyEditors/PropertyValueConverterBase.cs b/src/Umbraco.Core/PropertyEditors/PropertyValueConverterBase.cs index 3b6ebc610c..1764b4b012 100644 --- a/src/Umbraco.Core/PropertyEditors/PropertyValueConverterBase.cs +++ b/src/Umbraco.Core/PropertyEditors/PropertyValueConverterBase.cs @@ -17,6 +17,10 @@ namespace Umbraco.Core.PropertyEditors { case PropertyValueLevel.Source: return value != null && (!(value is string) || string.IsNullOrWhiteSpace((string) value) == false); + case PropertyValueLevel.Inter: + return null; + case PropertyValueLevel.Object: + return null; default: throw new NotSupportedException($"Invalid level: {level}."); } From c3e58df3b5f06f517a455f09629d30b66f21d173 Mon Sep 17 00:00:00 2001 From: Ronald Barendse Date: Thu, 11 Jun 2020 00:45:12 +0200 Subject: [PATCH 009/826] Obsolete HasValue method --- .../PropertyEditors/PropertyValueConverterBase.cs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Core/PropertyEditors/PropertyValueConverterBase.cs b/src/Umbraco.Core/PropertyEditors/PropertyValueConverterBase.cs index 1764b4b012..57474eb2e1 100644 --- a/src/Umbraco.Core/PropertyEditors/PropertyValueConverterBase.cs +++ b/src/Umbraco.Core/PropertyEditors/PropertyValueConverterBase.cs @@ -16,7 +16,9 @@ namespace Umbraco.Core.PropertyEditors switch (level) { case PropertyValueLevel.Source: - return value != null && (!(value is string) || string.IsNullOrWhiteSpace((string) value) == false); + // the default implementation uses the old magic null & string comparisons, + // other implementations may be more clever, and/or test the final converted object values + return value != null && (!(value is string) || string.IsNullOrWhiteSpace((string)value) == false); case PropertyValueLevel.Inter: return null; case PropertyValueLevel.Object: @@ -26,16 +28,15 @@ namespace Umbraco.Core.PropertyEditors } } + [Obsolete("This method is not part of the IPropertyValueConverter contract and therefore not used, use IsValue instead.")] public virtual bool HasValue(IPublishedProperty property, string culture, string segment) { - // the default implementation uses the old magic null & string comparisons, - // other implementations may be more clever, and/or test the final converted object values var value = property.GetSourceValue(culture, segment); - return value != null && (!(value is string) || string.IsNullOrWhiteSpace((string) value) == false); + return value != null && (!(value is string) || string.IsNullOrWhiteSpace((string)value) == false); } public virtual Type GetPropertyValueType(IPublishedPropertyType propertyType) - => typeof (object); + => typeof(object); public virtual PropertyCacheLevel GetPropertyCacheLevel(IPublishedPropertyType propertyType) => PropertyCacheLevel.Snapshot; From eac6351c3f0336e8531d6c75126aa39c47dd5add Mon Sep 17 00:00:00 2001 From: Ronald Barendse Date: Thu, 11 Jun 2020 00:49:44 +0200 Subject: [PATCH 010/826] Simplified value check using type pattern matching --- .../PropertyEditors/PropertyValueConverterBase.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Core/PropertyEditors/PropertyValueConverterBase.cs b/src/Umbraco.Core/PropertyEditors/PropertyValueConverterBase.cs index 57474eb2e1..be8b0619f5 100644 --- a/src/Umbraco.Core/PropertyEditors/PropertyValueConverterBase.cs +++ b/src/Umbraco.Core/PropertyEditors/PropertyValueConverterBase.cs @@ -18,7 +18,7 @@ namespace Umbraco.Core.PropertyEditors case PropertyValueLevel.Source: // the default implementation uses the old magic null & string comparisons, // other implementations may be more clever, and/or test the final converted object values - return value != null && (!(value is string) || string.IsNullOrWhiteSpace((string)value) == false); + return value != null && (!(value is string stringValue) || !string.IsNullOrWhiteSpace(stringValue)); case PropertyValueLevel.Inter: return null; case PropertyValueLevel.Object: @@ -32,7 +32,7 @@ namespace Umbraco.Core.PropertyEditors public virtual bool HasValue(IPublishedProperty property, string culture, string segment) { var value = property.GetSourceValue(culture, segment); - return value != null && (!(value is string) || string.IsNullOrWhiteSpace((string)value) == false); + return value != null && (!(value is string stringValue) || !string.IsNullOrWhiteSpace(stringValue)); } public virtual Type GetPropertyValueType(IPublishedPropertyType propertyType) From 249b3b8609b70cad305e7accffe6b2f0203ad3ca Mon Sep 17 00:00:00 2001 From: Ronald Barendse Date: Thu, 11 Jun 2020 00:49:59 +0200 Subject: [PATCH 011/826] Update XML documentation --- .../PropertyEditors/PropertyValueConverterBase.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Core/PropertyEditors/PropertyValueConverterBase.cs b/src/Umbraco.Core/PropertyEditors/PropertyValueConverterBase.cs index be8b0619f5..4724295b3f 100644 --- a/src/Umbraco.Core/PropertyEditors/PropertyValueConverterBase.cs +++ b/src/Umbraco.Core/PropertyEditors/PropertyValueConverterBase.cs @@ -4,13 +4,16 @@ using Umbraco.Core.Models.PublishedContent; namespace Umbraco.Core.PropertyEditors { /// - /// Provides a default overridable implementation for that does nothing. + /// Provides a default implementation for . /// + /// public abstract class PropertyValueConverterBase : IPropertyValueConverter { + /// public virtual bool IsConverter(IPublishedPropertyType propertyType) => false; + /// public virtual bool? IsValue(object value, PropertyValueLevel level) { switch (level) @@ -35,18 +38,23 @@ namespace Umbraco.Core.PropertyEditors return value != null && (!(value is string stringValue) || !string.IsNullOrWhiteSpace(stringValue)); } + /// public virtual Type GetPropertyValueType(IPublishedPropertyType propertyType) => typeof(object); + /// public virtual PropertyCacheLevel GetPropertyCacheLevel(IPublishedPropertyType propertyType) => PropertyCacheLevel.Snapshot; + /// public virtual object ConvertSourceToIntermediate(IPublishedElement owner, IPublishedPropertyType propertyType, object source, bool preview) => source; + /// public virtual object ConvertIntermediateToObject(IPublishedElement owner, IPublishedPropertyType propertyType, PropertyCacheLevel referenceCacheLevel, object inter, bool preview) => inter; + /// public virtual object ConvertIntermediateToXPath(IPublishedElement owner, IPublishedPropertyType propertyType, PropertyCacheLevel referenceCacheLevel, object inter, bool preview) => inter?.ToString() ?? string.Empty; } From 78cba26afe8541d520cfab44c4f8287d2b1c68e0 Mon Sep 17 00:00:00 2001 From: Dan Russell <4387475+dangrussell@users.noreply.github.com> Date: Tue, 16 Jun 2020 10:12:22 -0400 Subject: [PATCH 012/826] Update variables.less Replace "0px" with unitless 0 --- src/Umbraco.Web.UI.Client/src/less/variables.less | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/less/variables.less b/src/Umbraco.Web.UI.Client/src/less/variables.less index d94e4e1fb1..4bb2cd0343 100644 --- a/src/Umbraco.Web.UI.Client/src/less/variables.less +++ b/src/Umbraco.Web.UI.Client/src/less/variables.less @@ -515,7 +515,7 @@ // ------------------------- @gridColumns: 12; @gridColumnWidth: 60px; -@gridGutterWidth: 0px; +@gridGutterWidth: 0; @gridRowWidth: (@gridColumns * @gridColumnWidth) + (@gridGutterWidth * (@gridColumns - 1)); // 1200px min From f5e4bef5311b299e7e48a9fb10a181f5544b9adc Mon Sep 17 00:00:00 2001 From: Emma Garland Date: Mon, 6 Jul 2020 11:45:47 +0100 Subject: [PATCH 013/826] Added initial Cypress test for BackOffice tour. --- .../integration/Tour/backofficeTour.ts | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 src/Umbraco.Tests.AcceptanceTest/cypress/integration/Tour/backofficeTour.ts diff --git a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Tour/backofficeTour.ts b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Tour/backofficeTour.ts new file mode 100644 index 0000000000..ed891a2eea --- /dev/null +++ b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Tour/backofficeTour.ts @@ -0,0 +1,49 @@ +/// +context('Backoffice Tour', () => { + + beforeEach(() => { + cy.umbracoLogin(Cypress.env('username'), Cypress.env('password')); + }); + + it('Backoffice introduction tour should run', () => { + //arrange + cy.umbracoGlobalHelp().should("be.visible"); + + //act + cy.umbracoGlobalHelp().click() + //assert + cy.get('[data-element="help-tours"]').should("be.visible"); + //act + cy.get('[data-element="help-tours"]').click(); + //assert + cy.get('[data-element="tour-umbIntroIntroduction"] .umb-button').should("be.visible"); + //act + cy.get('[data-element="tour-umbIntroIntroduction"] .umb-button').click(); + //assert + cy.get('.umb-tour-step', { timeout: 60000 }).should('be.visible'); + cy.get('.umb-tour-step__footer').should('be.visible'); + cy.get('.umb-tour-step__counter').should('be.visible'); + + for(let i=1;i<7;i++){ + cy.get('.umb-tour-step__counter').contains(i + '/12'); + cy.get('.umb-tour-step__footer .umb-button').should('be.visible').click(); + } + cy.umbracoGlobalUser().click() + cy.get('.umb-tour-step__counter').contains('8/12'); + cy.get('.umb-tour-step__footer .umb-button').should('be.visible').click(); + cy.get('.umb-tour-step__counter').contains('9/12'); + cy.get('.umb-overlay-drawer__align-right .umb-button').should('be.visible').click(); + cy.get('.umb-tour-step__counter').contains('10/12'); + cy.umbracoGlobalHelp().click() + + for(let i=11;i<13;i++){ + cy.get('.umb-tour-step__counter').contains(i + '/12'); + cy.get('.umb-tour-step__footer .umb-button').should('be.visible').click(); + } + cy.get('.umb-tour-step__footer .umb-button').should('be.visible').click(); + + //assert + cy.umbracoGlobalHelp().should("be.visible"); + cy.get('[data-element="help-tours"] .umb-progress-circle').contains('17%'); + }); +}); From 872731f72685a8284940117b29be2b4a24cd1c81 Mon Sep 17 00:00:00 2001 From: Ronald Barendse Date: Tue, 7 Jul 2020 23:30:34 +0200 Subject: [PATCH 014/826] Update HasValue obsolete message --- src/Umbraco.Core/PropertyEditors/PropertyValueConverterBase.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Core/PropertyEditors/PropertyValueConverterBase.cs b/src/Umbraco.Core/PropertyEditors/PropertyValueConverterBase.cs index 4724295b3f..2ec0438328 100644 --- a/src/Umbraco.Core/PropertyEditors/PropertyValueConverterBase.cs +++ b/src/Umbraco.Core/PropertyEditors/PropertyValueConverterBase.cs @@ -31,7 +31,7 @@ namespace Umbraco.Core.PropertyEditors } } - [Obsolete("This method is not part of the IPropertyValueConverter contract and therefore not used, use IsValue instead.")] + [Obsolete("This method is not part of the IPropertyValueConverter contract, therefore not used and will be removed in future versions; use IsValue instead.")] public virtual bool HasValue(IPublishedProperty property, string culture, string segment) { var value = property.GetSourceValue(culture, segment); From 77a4b2af8bddc389c9a2a1ac46397d8865c100f9 Mon Sep 17 00:00:00 2001 From: Ismail Mayat Date: Wed, 8 Jul 2020 14:23:55 +0100 Subject: [PATCH 015/826] fix for 8192 make call to add missing bits to userdto (#8399) --- .../Repositories/Implement/UserRepository.cs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/UserRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/UserRepository.cs index 3be5102b83..3d96d94413 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/UserRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/UserRepository.cs @@ -151,7 +151,7 @@ SELECT '4CountOfLockedOut' AS colName, COUNT(id) AS num FROM umbracoUser WHERE u UNION SELECT '5CountOfInvited' AS colName, COUNT(id) AS num FROM umbracoUser WHERE lastLoginDate IS NULL AND userDisabled = 1 AND invitedDate IS NOT NULL UNION -SELECT '6CountOfDisabled' AS colName, COUNT(id) AS num FROM umbracoUser WHERE userDisabled = 0 AND userNoConsole = 0 AND lastLoginDate IS NULL +SELECT '6CountOfDisabled' AS colName, COUNT(id) AS num FROM umbracoUser WHERE userDisabled = 0 AND userNoConsole = 0 AND lastLoginDate IS NULL ORDER BY colName"; var result = Database.Fetch(sql); @@ -562,9 +562,9 @@ ORDER BY colName"; { userDto.EmailConfirmedDate = null; userDto.SecurityStampToken = entity.SecurityStamp = Guid.NewGuid().ToString(); - + changedCols.Add("emailConfirmedDate"); - changedCols.Add("securityStampToken"); + changedCols.Add("securityStampToken"); } //only update the changed cols @@ -693,7 +693,13 @@ ORDER BY colName"; else sql.WhereNotIn(x => x.Id, inSql); - return ConvertFromDtos(Database.Fetch(sql)); + + var dtos = Database.Fetch(sql); + + //adds missing bits like content and media start nodes + PerformGetReferencedDtos(dtos); + + return ConvertFromDtos(dtos); } /// From ffb53109bcc719c69b314b02e53bc3917757437c Mon Sep 17 00:00:00 2001 From: Ismail Mayat Date: Thu, 9 Jul 2020 08:13:05 +0100 Subject: [PATCH 016/826] 8192 with integration test (#8403) --- .../Services/UserServiceTests.cs | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/src/Umbraco.Tests/Services/UserServiceTests.cs b/src/Umbraco.Tests/Services/UserServiceTests.cs index 016085c352..0bac25b297 100644 --- a/src/Umbraco.Tests/Services/UserServiceTests.cs +++ b/src/Umbraco.Tests/Services/UserServiceTests.cs @@ -7,6 +7,7 @@ using System.Threading; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Exceptions; +using Umbraco.Core.Models; using Umbraco.Core.Models.Membership; using Umbraco.Core.Persistence.DatabaseModelDefinitions; using Umbraco.Tests.TestHelpers.Entities; @@ -968,16 +969,72 @@ namespace Umbraco.Tests.Services Assert.That(updatedItem.AllowedSections.Count(), Is.EqualTo(originalUser.AllowedSections.Count())); } + [Test] + public void Can_Get_Assigned_StartNodes_For_User() + { + var startContentItems = BuildContentItems(3); + + var testUserGroup = CreateTestUserGroup(); + + var userGroupId = testUserGroup.Id; + + CreateTestUsers(startContentItems.Select(x => x.Id).ToArray(), testUserGroup, 3); + + var usersInGroup = ServiceContext.UserService.GetAllInGroup(userGroupId); + + foreach (var user in usersInGroup) + Assert.AreEqual(user.StartContentIds.Length, startContentItems.Length); + } + + private Content[] BuildContentItems(int numberToCreate) + { + var contentType = MockedContentTypes.CreateSimpleContentType(); + + ServiceContext.ContentTypeService.Save(contentType); + + var startContentItems = new List(); + + for (var i = 0; i < numberToCreate; i++) + startContentItems.Add(MockedContent.CreateSimpleContent(contentType)); + + ServiceContext.ContentService.Save(startContentItems); + + return startContentItems.ToArray(); + } + private IUser CreateTestUser(out IUserGroup userGroup) { userGroup = CreateTestUserGroup(); var user = ServiceContext.UserService.CreateUserWithIdentity("test1", "test1@test.com"); + user.AddGroup(userGroup.ToReadOnlyGroup()); + ServiceContext.UserService.Save(user); + return user; } + private List CreateTestUsers(int[] startContentIds, IUserGroup userGroup, int numberToCreate) + { + var users = new List(); + + for (var i = 0; i < numberToCreate; i++) + { + var user = ServiceContext.UserService.CreateUserWithIdentity($"test{i}", $"test{i}@test.com"); + user.AddGroup(userGroup.ToReadOnlyGroup()); + + var updateable = (User)user; + updateable.StartContentIds = startContentIds; + + ServiceContext.UserService.Save(user); + + users.Add(user); + } + + return users; + } + private UserGroup CreateTestUserGroup(string alias = "testGroup", string name = "Test Group") { var userGroup = new UserGroup From 327d5ae7fb5bd10ad80fed11db29b10794f7139d Mon Sep 17 00:00:00 2001 From: Bjarne Fyrstenborg Date: Thu, 9 Jul 2020 16:04:43 +0200 Subject: [PATCH 017/826] Adjust nested content overlay (#8044) --- .../nestedcontent/nestedcontent.controller.js | 72 +++++++++---------- .../nestedcontent.propertyeditor.html | 8 --- 2 files changed, 34 insertions(+), 46 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.controller.js index fad68acbee..e4812360d7 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.controller.js @@ -167,8 +167,6 @@ isDisabled: true } - - // helper to force the current form into the dirty state function setDirty() { if ($scope.$parent.$parent.propertyForm) { @@ -187,17 +185,28 @@ }; vm.openNodeTypePicker = function ($event) { - if (vm.overlayMenu || vm.nodes.length >= vm.maxItems) { + + if (vm.nodes.length >= vm.maxItems) { return; } - vm.overlayMenu = { - show: false, - style: {}, - filter: vm.scaffolds.length > 12 ? true : false, + var availableItems = []; + _.each(vm.scaffolds, function (scaffold) { + availableItems.push({ + alias: scaffold.contentTypeAlias, + name: scaffold.contentTypeName, + icon: iconHelper.convertFromLegacyIcon(scaffold.icon) + }); + }); + + const dialog = { + view: "itempicker", orderBy: "$index", view: "itempicker", event: $event, + filter: availableItems.length > 12, + size: availableItems.length > 6 ? "medium" : "small", + availableItems: availableItems, clickPasteItem: function (item) { if (item.type === "elementTypeArray") { _.each(item.data, function (entry) { @@ -206,44 +215,30 @@ } else { pasteFromClipboard(item.data); } - vm.overlayMenu.show = false; - vm.overlayMenu = null; + + overlayService.close(); }, submit: function (model) { if (model && model.selectedItem) { addNode(model.selectedItem.alias); } - vm.overlayMenu.show = false; - vm.overlayMenu = null; + + overlayService.close(); }, close: function () { - vm.overlayMenu.show = false; - vm.overlayMenu = null; + overlayService.close(); } }; - // this could be used for future limiting on node types - vm.overlayMenu.availableItems = []; - _.each(vm.scaffolds, function (scaffold) { - vm.overlayMenu.availableItems.push({ - alias: scaffold.contentTypeAlias, - name: scaffold.contentTypeName, - icon: iconHelper.convertFromLegacyIcon(scaffold.icon), - tooltip: scaffold.documentType.description - }); - }); - - if (vm.overlayMenu.availableItems.length === 0) { + if (dialog.availableItems.length === 0) { return; } - vm.overlayMenu.size = vm.overlayMenu.availableItems.length > 6 ? "medium" : "small"; - - vm.overlayMenu.pasteItems = []; + dialog.pasteItems = []; var singleEntriesForPaste = clipboardService.retriveEntriesOfType("elementType", contentTypeAliases); _.each(singleEntriesForPaste, function (entry) { - vm.overlayMenu.pasteItems.push({ + dialog.pasteItems.push({ type: "elementType", name: entry.label, data: entry.data, @@ -253,7 +248,7 @@ var arrayEntriesForPaste = clipboardService.retriveEntriesOfType("elementTypeArray", contentTypeAliases); _.each(arrayEntriesForPaste, function (entry) { - vm.overlayMenu.pasteItems.push({ + dialog.pasteItems.push({ type: "elementTypeArray", name: entry.label, data: entry.data, @@ -261,26 +256,27 @@ }); }); - vm.overlayMenu.title = labels.grid_addElement; - vm.overlayMenu.hideHeader = vm.overlayMenu.pasteItems.length > 0; + dialog.title = dialog.pasteItems.length > 0 ? labels.grid_addElement : labels.content_createEmpty; - vm.overlayMenu.clickClearPaste = function ($event) { + dialog.clickClearPaste = function ($event) { $event.stopPropagation(); $event.preventDefault(); clipboardService.clearEntriesOfType("elementType", contentTypeAliases); clipboardService.clearEntriesOfType("elementTypeArray", contentTypeAliases); - vm.overlayMenu.pasteItems = [];// This dialog is not connected via the clipboardService events, so we need to update manually. - vm.overlayMenu.hideHeader = false; + dialog.pasteItems = [];// This dialog is not connected via the clipboardService events, so we need to update manually. + dialog.overlayMenu.hideHeader = false; }; - if (vm.overlayMenu.availableItems.length === 1 && vm.overlayMenu.pasteItems.length === 0) { + if (dialog.availableItems.length === 1 && dialog.pasteItems.length === 0) { // only one scaffold type - no need to display the picker addNode(vm.scaffolds[0].contentTypeAlias); - vm.overlayMenu = null; + + dialog.close(); + return; } - vm.overlayMenu.show = true; + overlayService.open(dialog); }; vm.editNode = function (idx) { diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.propertyeditor.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.propertyeditor.html index da6e466b50..c41df689d4 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.propertyeditor.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.propertyeditor.html @@ -64,12 +64,4 @@ - - - From 7b106ebefb15bc1530f829e1653c089c3fb25423 Mon Sep 17 00:00:00 2001 From: Bjarne Fyrstenborg Date: Thu, 9 Jul 2020 16:48:27 +0200 Subject: [PATCH 018/826] Adjust example for overlay in umb-child-selector (#8045) --- .../components/umbchildselector.directive.js | 30 +++++++++---------- .../views/components/umb-child-selector.html | 2 +- .../permissions/permissions.controller.js | 21 ++++++------- .../permissions/permissions.controller.js | 23 +++++++------- 4 files changed, 38 insertions(+), 38 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbchildselector.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbchildselector.directive.js index 96ce8735eb..9a841e3e4a 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbchildselector.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbchildselector.directive.js @@ -21,14 +21,6 @@ Use this directive to render a ui component for selecting child items to a paren on-remove="vm.removeChild"> - - - - @@ -37,7 +29,7 @@ Use this directive to render a ui component for selecting child items to a paren (function () { "use strict"; - function Controller() { + function Controller(overlayService) { var vm = this; @@ -64,23 +56,29 @@ Use this directive to render a ui component for selecting child items to a paren vm.removeChild = removeChild; function addChild($event) { - vm.overlay = { + + const dialog = { view: "itempicker", title: "Choose child", availableItems: vm.availableChildren, selectedItems: vm.selectedChildren, event: $event, - show: true, submit: function(model) { - - // add selected child - vm.selectedChildren.push(model.selectedItem); + + if (model.selectedItem) { + // add selected child + vm.selectedChildren.push(model.selectedItem); + } // close overlay - vm.overlay.show = false; - vm.overlay = null; + overlayService.close(); + }, + close: function() { + overlayService.close(); } }; + + overlayService.open(dialog); } function removeChild($index) { diff --git a/src/Umbraco.Web.UI.Client/src/views/components/umb-child-selector.html b/src/Umbraco.Web.UI.Client/src/views/components/umb-child-selector.html index 1d88c0eb96..f038b8c4aa 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/umb-child-selector.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/umb-child-selector.html @@ -3,7 +3,7 @@
- +
{{ parentName }} diff --git a/src/Umbraco.Web.UI.Client/src/views/documenttypes/views/permissions/permissions.controller.js b/src/Umbraco.Web.UI.Client/src/views/documenttypes/views/permissions/permissions.controller.js index da8dee8e03..94e0b443ca 100644 --- a/src/Umbraco.Web.UI.Client/src/views/documenttypes/views/permissions/permissions.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/documenttypes/views/permissions/permissions.controller.js @@ -14,12 +14,9 @@ /* ----------- SCOPE VARIABLES ----------- */ var vm = this; - var childNodeSelectorOverlayTitle = ""; vm.contentTypes = []; vm.selectedChildren = []; - - vm.overlayTitle = ""; vm.showAllowSegmentationOption = Umbraco.Sys.ServerVariables.umbracoSettings.showAllowSegmentationForDocumentTypes || false; vm.addChild = addChild; @@ -65,16 +62,18 @@ } function addChild($event) { - var childNodeSelectorOverlay = { + + const dialog = { view: "itempicker", - title: childNodeSelectorOverlayTitle, availableItems: vm.contentTypes, selectedItems: vm.selectedChildren, position: "target", event: $event, - submit: function(model) { - vm.selectedChildren.push(model.selectedItem); - $scope.model.allowedContentTypes.push(model.selectedItem.id); + submit: function (model) { + if (model.selectedItem) { + vm.selectedChildren.push(model.selectedItem); + $scope.model.allowedContentTypes.push(model.selectedItem.id); + } overlayService.close(); }, close: function() { @@ -82,8 +81,10 @@ } }; - overlayService.open(childNodeSelectorOverlay); - + localizationService.localize("contentTypeEditor_chooseChildNode").then(value => { + dialog.title = value; + overlayService.open(dialog); + }); } function removeChild(selectedChild, index) { diff --git a/src/Umbraco.Web.UI.Client/src/views/mediatypes/views/permissions/permissions.controller.js b/src/Umbraco.Web.UI.Client/src/views/mediatypes/views/permissions/permissions.controller.js index 53a098a26e..7ff4793272 100644 --- a/src/Umbraco.Web.UI.Client/src/views/mediatypes/views/permissions/permissions.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/mediatypes/views/permissions/permissions.controller.js @@ -6,7 +6,6 @@ /* ----------- SCOPE VARIABLES ----------- */ var vm = this; - var childNodeSelectorOverlayTitle = ""; vm.mediaTypes = []; vm.selectedChildren = []; @@ -22,10 +21,6 @@ function init() { - localizationService.localize("contentTypeEditor_chooseChildNode").then(function(value){ - childNodeSelectorOverlayTitle = value; - }); - mediaTypeResource.getAll().then(function(mediaTypes){ vm.mediaTypes = mediaTypes; @@ -44,23 +39,29 @@ } function addChild($event) { - var childNodeSelectorOverlay = { + + var dialog = { view: "itempicker", - title: childNodeSelectorOverlayTitle, availableItems: vm.mediaTypes, selectedItems: vm.selectedChildren, position: "target", event: $event, - submit: function(model) { - vm.selectedChildren.push(model.selectedItem); - $scope.model.allowedContentTypes.push(model.selectedItem.id); + submit: function (model) { + if (model.selectedItem) { + vm.selectedChildren.push(model.selectedItem); + $scope.model.allowedContentTypes.push(model.selectedItem.id); + } overlayService.close(); }, close: function() { overlayService.close(); } }; - overlayService.open(childNodeSelectorOverlay); + + localizationService.localize("contentTypeEditor_chooseChildNode").then(value => { + dialog.title = value; + overlayService.open(dialog); + }); } function removeChild(selectedChild, index) { From 4bc1800d48e686c99f7c5313db14ea0b41bc6866 Mon Sep 17 00:00:00 2001 From: Bjarne Fyrstenborg Date: Thu, 9 Jul 2020 16:58:59 +0200 Subject: [PATCH 019/826] Use overlayService for user overlay (#8047) --- .../application/umbappheader.directive.js | 28 ++++++++----------- .../overlays/umboverlay.directive.js | 5 ++++ .../src/common/services/overlay.service.js | 11 ++++---- .../application/umb-app-header.html | 8 ------ .../components/overlays/umb-overlay.html | 2 +- .../Umbraco/Views/Default.cshtml | 2 ++ 6 files changed, 25 insertions(+), 31 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umbappheader.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umbappheader.directive.js index 8efaf0c024..b52b0a5763 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umbappheader.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umbappheader.directive.js @@ -1,7 +1,7 @@ (function () { "use strict"; - function AppHeaderDirective(eventsService, appState, userService, focusService, backdropService) { + function AppHeaderDirective(eventsService, appState, userService, focusService, backdropService, overlayService) { function link(scope, el, attr, ctrl) { @@ -71,21 +71,17 @@ }; scope.avatarClick = function () { - if (!scope.userDialog) { - backdropService.open(); - scope.userDialog = { - view: "user", - show: true, - close: function (oldModel) { - scope.userDialog.show = false; - scope.userDialog = null; - backdropService.close(); - } - }; - } else { - scope.userDialog.show = false; - scope.userDialog = null; - } + + const dialog = { + view: "user", + position: "right", + name: "overlay-user", + close: function () { + overlayService.close(); + } + }; + + overlayService.open(dialog); }; } diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/overlays/umboverlay.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/overlays/umboverlay.directive.js index ad396e7a9a..5a06edf617 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/overlays/umboverlay.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/overlays/umboverlay.directive.js @@ -221,6 +221,10 @@ Opens an overlay to show a custom YSOD.
$timeout(function () { + if (!scope.name) { + scope.name = 'overlay'; + } + if (scope.position === "target" && scope.model.event) { setTargetPosition(); @@ -530,6 +534,7 @@ Opens an overlay to show a custom YSOD.
view: "=", position: "@", size: "=?", + name: "=?", parentScope: "=?" }, link: link diff --git a/src/Umbraco.Web.UI.Client/src/common/services/overlay.service.js b/src/Umbraco.Web.UI.Client/src/common/services/overlay.service.js index 119f40e114..5e11d44bda 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/overlay.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/overlay.service.js @@ -15,7 +15,7 @@ function open(newOverlay) { // prevent two open overlays at the same time - if(currentOverlay) { + if (currentOverlay) { close(); } @@ -23,22 +23,22 @@ var overlay = newOverlay; // set the default overlay position to center - if(!overlay.position) { + if (!overlay.position) { overlay.position = "center"; } // set the default overlay size to small - if(!overlay.size) { + if (!overlay.size) { overlay.size = "small"; } // use a default empty view if nothing is set - if(!overlay.view) { + if (!overlay.view) { overlay.view = "views/common/overlays/default/default.html"; } // option to disable backdrop clicks - if(overlay.disableBackdropClick) { + if (overlay.disableBackdropClick) { backdropOptions.disableEventsOnClick = true; } @@ -85,7 +85,6 @@ } open(overlay); - } function confirmDelete(overlay) { diff --git a/src/Umbraco.Web.UI.Client/src/views/components/application/umb-app-header.html b/src/Umbraco.Web.UI.Client/src/views/components/application/umb-app-header.html index c6c4f98e25..984ac9337a 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/application/umb-app-header.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/application/umb-app-header.html @@ -45,12 +45,4 @@
- - -
diff --git a/src/Umbraco.Web.UI.Client/src/views/components/overlays/umb-overlay.html b/src/Umbraco.Web.UI.Client/src/views/components/overlays/umb-overlay.html index 39e0165fe8..7fe6df8ccc 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/overlays/umb-overlay.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/overlays/umb-overlay.html @@ -1,4 +1,4 @@ -
internal abstract class Builder { - - - private readonly IList _typeModels; protected Dictionary ModelsMap { get; } = new Dictionary(); diff --git a/src/Umbraco.ModelsBuilder.Embedded/Building/TextHeaderWriter.cs b/src/Umbraco.ModelsBuilder.Embedded/Building/TextHeaderWriter.cs index 0ffad1c5bc..de25501ecc 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/Building/TextHeaderWriter.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/Building/TextHeaderWriter.cs @@ -14,7 +14,7 @@ namespace Umbraco.ModelsBuilder.Embedded.Building sb.Append("// \n"); sb.Append("// This code was generated by a tool.\n"); sb.Append("//\n"); - sb.AppendFormat("// Umbraco.ModelsBuilder.Embedded v{0}\n", ApiVersion.Current.Version); + sb.AppendFormat((string) "// Umbraco.ModelsBuilder.Embedded v{0}\n", (object) ApiVersion.Current.Version); sb.Append("//\n"); sb.Append("// Changes to this file will be lost if the code is regenerated.\n"); sb.Append("// \n"); diff --git a/src/Umbraco.ModelsBuilder.Embedded/Compose/DisabledModelsBuilderComponent.cs b/src/Umbraco.ModelsBuilder.Embedded/Compose/DisabledModelsBuilderComponent.cs index c599785711..9d63f65f64 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/Compose/DisabledModelsBuilderComponent.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/Compose/DisabledModelsBuilderComponent.cs @@ -1,5 +1,4 @@ -using Umbraco.Core; -using Umbraco.Core.Composing; +using Umbraco.Core.Composing; using Umbraco.ModelsBuilder.Embedded.BackOffice; using Umbraco.Web.Features; diff --git a/src/Umbraco.ModelsBuilder.Embedded/Compose/ModelsBuilderComponent.cs b/src/Umbraco.ModelsBuilder.Embedded/Compose/ModelsBuilderComponent.cs index 32cfd3057e..e80af426bd 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/Compose/ModelsBuilderComponent.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/Compose/ModelsBuilderComponent.cs @@ -1,9 +1,7 @@ using System; using System.Collections.Generic; using System.Reflection; -using System.Web; -using System.Web.Mvc; -using System.Web.Routing; +using Microsoft.AspNetCore.Routing; using Umbraco.Configuration; using Umbraco.Core.Configuration; using Umbraco.Core.Composing; @@ -11,9 +9,11 @@ using Umbraco.Core.IO; using Umbraco.Core.Services; using Umbraco.Core.Services.Implement; using Umbraco.Core.Strings; +using Umbraco.Extensions; using Umbraco.ModelsBuilder.Embedded.BackOffice; -using Umbraco.Web; -using Umbraco.Web.Mvc; +using Umbraco.Net; +using Umbraco.Web.Common.Lifetime; +using Umbraco.Web.Common.ModelBinders; using Umbraco.Web.WebAssets; namespace Umbraco.ModelsBuilder.Embedded.Compose @@ -24,14 +24,22 @@ namespace Umbraco.ModelsBuilder.Embedded.Compose private readonly IShortStringHelper _shortStringHelper; private readonly LiveModelsProvider _liveModelsProvider; private readonly OutOfDateModelsStatus _outOfDateModels; + private readonly LinkGenerator _linkGenerator; + private readonly IUmbracoApplicationLifetime _umbracoApplicationLifetime; + private readonly IUmbracoRequestLifetime _umbracoRequestLifetime; - public ModelsBuilderComponent(IModelsBuilderConfig config, IShortStringHelper shortStringHelper, LiveModelsProvider liveModelsProvider, OutOfDateModelsStatus outOfDateModels) + public ModelsBuilderComponent(IModelsBuilderConfig config, IShortStringHelper shortStringHelper, + LiveModelsProvider liveModelsProvider, OutOfDateModelsStatus outOfDateModels, LinkGenerator linkGenerator, + IUmbracoRequestLifetime umbracoRequestLifetime, IUmbracoApplicationLifetime umbracoApplicationLifetime) { _config = config; _shortStringHelper = shortStringHelper; _liveModelsProvider = liveModelsProvider; _outOfDateModels = outOfDateModels; _shortStringHelper = shortStringHelper; + _linkGenerator = linkGenerator; + _umbracoRequestLifetime = umbracoRequestLifetime; + _umbracoApplicationLifetime = umbracoApplicationLifetime; } public void Initialize() @@ -39,6 +47,7 @@ namespace Umbraco.ModelsBuilder.Embedded.Compose // always setup the dashboard // note: UmbracoApiController instances are automatically registered InstallServerVars(); + _umbracoApplicationLifetime.ApplicationInit += InitializeApplication; ContentModelBinder.ModelBindingException += ContentModelBinder_ModelBindingException; @@ -55,6 +64,11 @@ namespace Umbraco.ModelsBuilder.Embedded.Compose public void Terminate() { } + private void InitializeApplication(object sender, EventArgs args) + { + _umbracoRequestLifetime.RequestEnd += (sender, context) => _liveModelsProvider.AppEndRequest(context); + } + private void InstallServerVars() { // register our url - for the backoffice api @@ -73,10 +87,7 @@ namespace Umbraco.ModelsBuilder.Embedded.Compose if (!(serverVars["umbracoPlugins"] is Dictionary umbracoPlugins)) throw new ArgumentException("Invalid umbracoPlugins"); - if (HttpContext.Current == null) throw new InvalidOperationException("HttpContext is null"); - var urlHelper = new UrlHelper(new RequestContext(new HttpContextWrapper(HttpContext.Current), new RouteData())); - - umbracoUrls["modelsBuilderBaseUrl"] = urlHelper.GetUmbracoApiServiceBaseUrl(controller => controller.BuildModels()); + umbracoUrls["modelsBuilderBaseUrl"] = _linkGenerator.GetUmbracoApiServiceBaseUrl(controller => controller.BuildModels()); umbracoPlugins["modelsBuilder"] = GetModelsBuilderSettings(); }; } diff --git a/src/Umbraco.ModelsBuilder.Embedded/Compose/ModelsBuilderComposer.cs b/src/Umbraco.ModelsBuilder.Embedded/Compose/ModelsBuilderComposer.cs index e582301740..d1765d5a41 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/Compose/ModelsBuilderComposer.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/Compose/ModelsBuilderComposer.cs @@ -9,8 +9,6 @@ using Umbraco.ModelsBuilder.Embedded.Building; namespace Umbraco.ModelsBuilder.Embedded.Compose { - - [ComposeBefore(typeof(IPublishedCacheComposer))] [RuntimeLevel(MinLevel = RuntimeLevel.Run)] public sealed class ModelsBuilderComposer : ICoreComposer diff --git a/src/Umbraco.ModelsBuilder.Embedded/Compose/ModelsBuilderInitializer.cs b/src/Umbraco.ModelsBuilder.Embedded/Compose/ModelsBuilderInitializer.cs deleted file mode 100644 index a86669b135..0000000000 --- a/src/Umbraco.ModelsBuilder.Embedded/Compose/ModelsBuilderInitializer.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System.Web; -using System.Web.Compilation; -using Umbraco.ModelsBuilder.Embedded.Compose; - -[assembly: PreApplicationStartMethod(typeof(ModelsBuilderInitializer), "Initialize")] - -namespace Umbraco.ModelsBuilder.Embedded.Compose -{ - public static class ModelsBuilderInitializer - { - public static void Initialize() - { - // for some reason, netstandard is missing from BuildManager.ReferencedAssemblies and yet, is part of - // the references that CSharpCompiler receives - in some cases eg when building views - but not when - // using BuildManager to build the PureLive models - where is it coming from? cannot figure it out - - // so... cheating here - - // this is equivalent to adding - // - // to web.config system.web/compilation/assemblies - - var netStandard = ReferencedAssemblies.GetNetStandardAssembly(); - if (netStandard != null) - BuildManager.AddReferencedAssembly(netStandard); - } - } -} diff --git a/src/Umbraco.ModelsBuilder.Embedded/ImplementPropertyTypeAttribute.cs b/src/Umbraco.ModelsBuilder.Embedded/ImplementPropertyTypeAttribute.cs index b7b2695a08..914f4912a9 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/ImplementPropertyTypeAttribute.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/ImplementPropertyTypeAttribute.cs @@ -6,7 +6,7 @@ namespace Umbraco.ModelsBuilder.Embedded /// Indicates that a property implements a given property alias. ///
/// And therefore it should not be generated. - [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)] + [AttributeUsage(AttributeTargets.Property /*, AllowMultiple = false, Inherited = false*/)] public class ImplementPropertyTypeAttribute : Attribute { public ImplementPropertyTypeAttribute(string alias) diff --git a/src/Umbraco.ModelsBuilder.Embedded/LiveModelsProvider.cs b/src/Umbraco.ModelsBuilder.Embedded/LiveModelsProvider.cs index 61d39cd373..596a744b27 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/LiveModelsProvider.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/LiveModelsProvider.cs @@ -1,7 +1,10 @@ using System; using System.Threading; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Extensions; using Umbraco.Core.Configuration; using Umbraco.Configuration; +using Umbraco.Core; using Umbraco.Core.Hosting; using Umbraco.Core.Logging; using Umbraco.ModelsBuilder.Embedded.Building; @@ -69,7 +72,7 @@ namespace Umbraco.ModelsBuilder.Embedded Interlocked.Exchange(ref _req, 1); } - public void GenerateModelsIfRequested(object sender, EventArgs args) + public void GenerateModelsIfRequested() { //if (HttpContext.Current.Items[this] == null) return; if (Interlocked.Exchange(ref _req, 0) == 0) return; @@ -108,6 +111,15 @@ namespace Umbraco.ModelsBuilder.Embedded _modelGenerator.GenerateModels(); } + public void AppEndRequest(HttpContext context) + { + var requestUri = new Uri(context.Request.GetEncodedUrl(), UriKind.RelativeOrAbsolute); + if (requestUri.IsClientSideRequest()) + return; + + if (!IsEnabled) return; + GenerateModelsIfRequested(); + } } } diff --git a/src/Umbraco.ModelsBuilder.Embedded/LiveModelsProviderModule.cs b/src/Umbraco.ModelsBuilder.Embedded/LiveModelsProviderModule.cs deleted file mode 100644 index a04723a05e..0000000000 --- a/src/Umbraco.ModelsBuilder.Embedded/LiveModelsProviderModule.cs +++ /dev/null @@ -1,47 +0,0 @@ -using System; -using System.Web; -using Umbraco.Core; -using Umbraco.Web.Composing; -using Umbraco.ModelsBuilder.Embedded; - -// will install only if configuration says it needs to be installed -[assembly: PreApplicationStartMethod(typeof(LiveModelsProviderModule), "Install")] - -namespace Umbraco.ModelsBuilder.Embedded -{ - // have to do this because it's the only way to subscribe to EndRequest, - // module is installed by assembly attribute at the top of this file - public class LiveModelsProviderModule : IHttpModule - { - private static LiveModelsProvider _liveModelsProvider; - - public void Init(HttpApplication app) - { - app.EndRequest += App_EndRequest; - } - - private void App_EndRequest(object sender, EventArgs e) - { - if (((HttpApplication)sender).Request.Url.IsClientSideRequest()) - return; - - // here we're using "Current." since we're in a module, it is possible in a round about way to inject into a module but for now we'll just use Current - if (_liveModelsProvider == null) - _liveModelsProvider = Current.Factory.TryGetInstance(); // will be null in upgrade mode or if embedded MB is disabled - - if (_liveModelsProvider?.IsEnabled ?? false) - _liveModelsProvider.GenerateModelsIfRequested(sender, e); - } - - public void Dispose() - { - // nothing - } - - public static void Install() - { - // always - don't read config in PreApplicationStartMethod - HttpApplication.RegisterModule(typeof(LiveModelsProviderModule)); - } - } -} diff --git a/src/Umbraco.ModelsBuilder.Embedded/ModelsBuilderDashboard.cs b/src/Umbraco.ModelsBuilder.Embedded/ModelsBuilderDashboard.cs index b8b1945f32..867b22d14b 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/ModelsBuilderDashboard.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/ModelsBuilderDashboard.cs @@ -15,5 +15,4 @@ namespace Umbraco.ModelsBuilder.Embedded public IAccessRule[] AccessRules => Array.Empty(); } - } diff --git a/src/Umbraco.ModelsBuilder.Embedded/Properties/AssemblyInfo.cs b/src/Umbraco.ModelsBuilder.Embedded/Properties/AssemblyInfo.cs deleted file mode 100644 index 5fa17d3c77..0000000000 --- a/src/Umbraco.ModelsBuilder.Embedded/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -[assembly: AssemblyTitle("Umbraco.ModelsBuilder.Embedded")] -[assembly: AssemblyDescription("Umbraco ModelsBuilder")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyProduct("Umbraco CMS")] - -[assembly: ComVisible(false)] -[assembly: Guid("52ac0ba8-a60e-4e36-897b-e8b97a54ed1c")] - -[assembly: InternalsVisibleTo("Umbraco.Tests")] diff --git a/src/Umbraco.ModelsBuilder.Embedded/PublishedElementExtensions.cs b/src/Umbraco.ModelsBuilder.Embedded/PublishedElementExtensions.cs index 8a0a688942..0611d466dc 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/PublishedElementExtensions.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/PublishedElementExtensions.cs @@ -2,12 +2,11 @@ using System.Linq.Expressions; using System.Reflection; using Umbraco.Core.Models.PublishedContent; -using Umbraco.ModelsBuilder; using Umbraco.ModelsBuilder.Embedded; // same namespace as original Umbraco.Web PublishedElementExtensions // ReSharper disable once CheckNamespace -namespace Umbraco.Web +namespace Umbraco.Core { /// /// Provides extension methods to models. @@ -17,11 +16,11 @@ namespace Umbraco.Web /// /// Gets the value of a property. /// - public static TValue ValueFor(this TModel model, Expression> property, string culture = null, string segment = null, Fallback fallback = default, TValue defaultValue = default) + public static TValue ValueFor(this TModel model, IPublishedValueFallback publishedValueFallback, Expression> property, string culture = null, string segment = null, Fallback fallback = default, TValue defaultValue = default) where TModel : IPublishedElement { var alias = GetAlias(model, property); - return model.Value(alias, culture, segment, fallback, defaultValue); + return model.Value(publishedValueFallback, alias, culture, segment, fallback, defaultValue); } // fixme that one should be public so ppl can use it diff --git a/src/Umbraco.ModelsBuilder.Embedded/Umbraco.ModelsBuilder.Embedded.csproj b/src/Umbraco.ModelsBuilder.Embedded/Umbraco.ModelsBuilder.Embedded.csproj index 87c20eca72..0046c568f1 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/Umbraco.ModelsBuilder.Embedded.csproj +++ b/src/Umbraco.ModelsBuilder.Embedded/Umbraco.ModelsBuilder.Embedded.csproj @@ -1,119 +1,19 @@ - - - - - Debug - AnyCPU - {52AC0BA8-A60E-4E36-897B-E8B97A54ED1C} - Library - Properties - Umbraco.ModelsBuilder.Embedded - Umbraco.ModelsBuilder.Embedded - v4.7.2 - 512 - true - 8 - - - true - portable - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - portable - true - bin\Release\ - TRACE - prompt - 4 - bin\Release\Umbraco.ModelsBuilder.Embedded.xml - - - - - - - - - - - - - - - - Properties\SolutionInfo.cs - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2.10.0 - - - 1.0.0 - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - 4.7.0 - - - - - {29aa69d9-b597-4395-8d42-43b1263c240a} - Umbraco.Core - - - {3ae7bf57-966b-45a5-910a-954d7c554441} - Umbraco.Infrastructure - - - {651e1350-91b6-44b7-bd60-7207006d7003} - Umbraco.Web - - - - - 5.2.7 - - - - \ No newline at end of file + + + + netcoreapp3.1 + Library + latest + + + + bin\Release\Umbraco.ModelsBuilder.Embedded.xml + + + + + + + + + diff --git a/src/Umbraco.Web.UI.NetCore/Umbraco.Web.UI.NetCore.csproj b/src/Umbraco.Web.UI.NetCore/Umbraco.Web.UI.NetCore.csproj index 0453c692df..f467ae28a1 100644 --- a/src/Umbraco.Web.UI.NetCore/Umbraco.Web.UI.NetCore.csproj +++ b/src/Umbraco.Web.UI.NetCore/Umbraco.Web.UI.NetCore.csproj @@ -1,4 +1,4 @@ - + netcoreapp3.1 @@ -6,6 +6,7 @@ + @@ -15,7 +16,6 @@ - diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj index 952e8e002f..f2e37bdc3f 100644 --- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj +++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj @@ -120,10 +120,6 @@ {0fad7d2a-d7dd-45b1-91fd-488bb6cdacea} Umbraco.Examine.Lucene - - {52ac0ba8-a60e-4e36-897b-e8b97a54ed1c} - Umbraco.ModelsBuilder.Embedded - {f6de8da0-07cc-4ef2-8a59-2bc81dbb3830} Umbraco.PublishedCache.NuCache @@ -360,4 +356,4 @@ - + \ No newline at end of file From e69c98ea9cd752bffc89b4ff84dc707ebd4308b8 Mon Sep 17 00:00:00 2001 From: Elitsa Marinovska Date: Mon, 13 Jul 2020 13:53:02 +0200 Subject: [PATCH 033/826] Removing redundant cast --- src/Umbraco.ModelsBuilder.Embedded/Building/TextHeaderWriter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.ModelsBuilder.Embedded/Building/TextHeaderWriter.cs b/src/Umbraco.ModelsBuilder.Embedded/Building/TextHeaderWriter.cs index de25501ecc..0ffad1c5bc 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/Building/TextHeaderWriter.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/Building/TextHeaderWriter.cs @@ -14,7 +14,7 @@ namespace Umbraco.ModelsBuilder.Embedded.Building sb.Append("// \n"); sb.Append("// This code was generated by a tool.\n"); sb.Append("//\n"); - sb.AppendFormat((string) "// Umbraco.ModelsBuilder.Embedded v{0}\n", (object) ApiVersion.Current.Version); + sb.AppendFormat("// Umbraco.ModelsBuilder.Embedded v{0}\n", ApiVersion.Current.Version); sb.Append("//\n"); sb.Append("// Changes to this file will be lost if the code is regenerated.\n"); sb.Append("// \n"); From 07c0402d2b22b228f32640b857205a698d5b38e6 Mon Sep 17 00:00:00 2001 From: Elitsa Marinovska Date: Mon, 13 Jul 2020 14:39:28 +0200 Subject: [PATCH 034/826] Injecting IPublishedSnapshotAccessor --- .../PublishedModelUtility.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.ModelsBuilder.Embedded/PublishedModelUtility.cs b/src/Umbraco.ModelsBuilder.Embedded/PublishedModelUtility.cs index 8a6ed83ce9..fd1d5128a0 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/PublishedModelUtility.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/PublishedModelUtility.cs @@ -2,7 +2,7 @@ using System.Linq; using System.Linq.Expressions; using Umbraco.Core.Models.PublishedContent; -using Umbraco.Web.Composing; +using Umbraco.Web.PublishedCache; namespace Umbraco.ModelsBuilder.Embedded { @@ -29,10 +29,10 @@ namespace Umbraco.ModelsBuilder.Embedded // var contentType = PublishedContentType.Get(itemType, alias); // // etc... //} - - public static IPublishedContentType GetModelContentType(PublishedItemType itemType, string alias) + + public static IPublishedContentType GetModelContentType(IPublishedSnapshotAccessor publishedSnapshotAccessor, PublishedItemType itemType, string alias) { - var facade = Current.UmbracoContext.PublishedSnapshot; // fixme inject! + var facade = publishedSnapshotAccessor.PublishedSnapshot; switch (itemType) { case PublishedItemType.Content: From 9f9cd0e11e784ace4f846cb6fd2a37700d7442d2 Mon Sep 17 00:00:00 2001 From: Sebastiaan Janssen Date: Mon, 13 Jul 2020 17:22:27 +0200 Subject: [PATCH 035/826] Trying to get CodeQL to run (#8415) --- .github/workflows/codeql-analysis.yml | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index e799432c71..46e09dee3e 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -2,7 +2,7 @@ name: "Code scanning - action" on: push: - branches: [v8/contrib] + branches: [v8/contrib,v8/codeql] pull_request: # The branches below must be a subset of the branches above branches: [v8/contrib] @@ -12,7 +12,7 @@ on: jobs: CodeQL-Build: - runs-on: ubuntu-latest + runs-on: windows-latest steps: - name: Checkout repository @@ -36,9 +36,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - - name: Autobuild - uses: github/codeql-action/autobuild@v1 - + # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -46,9 +44,9 @@ jobs: # and modify them (or add more) to build your code if your project # uses a compiled language - #- run: | - # make bootstrap - # make release + - run: | + echo "Run Umbraco-CMS build" + pwsh -command .\build\build.ps1 - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v1 From d7b818001ea9c210e8ecf8ea4e99512f3fb8fadf Mon Sep 17 00:00:00 2001 From: Elitsa Marinovska Date: Mon, 13 Jul 2020 21:49:09 +0200 Subject: [PATCH 036/826] Migrating MB tests and changing required accessibility lvls --- src/Umbraco.ModelsBuilder.Embedded/Building/Builder.cs | 6 +++--- src/Umbraco.ModelsBuilder.Embedded/UmbracoServices.cs | 2 +- .../Umbraco.Tests.Common}/ModelsBuilder/ConfigTests.cs | 1 - .../ModelsBuilder/StringExtensions.cs | 0 .../ModelsBuilder/UmbracoApplicationTests.cs | 0 .../Umbraco.Tests.UnitTests.csproj | 1 + src/Umbraco.Tests/Umbraco.Tests.csproj | 8 -------- 7 files changed, 5 insertions(+), 13 deletions(-) rename src/{Umbraco.Tests => Umbraco.Tests.UnitTests/Umbraco.Tests.Common}/ModelsBuilder/ConfigTests.cs (98%) rename src/{Umbraco.Tests => Umbraco.Tests.UnitTests/Umbraco.Tests.Common}/ModelsBuilder/StringExtensions.cs (100%) rename src/{Umbraco.Tests => Umbraco.Tests.UnitTests/Umbraco.Tests.Common}/ModelsBuilder/UmbracoApplicationTests.cs (100%) diff --git a/src/Umbraco.ModelsBuilder.Embedded/Building/Builder.cs b/src/Umbraco.ModelsBuilder.Embedded/Building/Builder.cs index 629d5e17b0..9985a5b1bd 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/Building/Builder.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/Building/Builder.cs @@ -16,7 +16,7 @@ namespace Umbraco.ModelsBuilder.Embedded.Building /// /// Provides a base class for all builders. /// - internal abstract class Builder + public abstract class Builder { private readonly IList _typeModels; @@ -59,7 +59,7 @@ namespace Umbraco.ModelsBuilder.Embedded.Building /// Gets the list of all models. /// /// Includes those that are ignored. - internal IList TypeModels => _typeModels; + public IList TypeModels => _typeModels; /// /// Initializes a new instance of the class with a list of models to generate, @@ -196,7 +196,7 @@ namespace Umbraco.ModelsBuilder.Embedded.Building return true; } - internal string ModelsNamespaceForTests; + public string ModelsNamespaceForTests; public string GetModelsNamespace() { diff --git a/src/Umbraco.ModelsBuilder.Embedded/UmbracoServices.cs b/src/Umbraco.ModelsBuilder.Embedded/UmbracoServices.cs index 8763da86a6..cc904cd015 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/UmbracoServices.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/UmbracoServices.cs @@ -189,7 +189,7 @@ namespace Umbraco.ModelsBuilder.Embedded return typeModels; } - internal static IList EnsureDistinctAliases(IList typeModels) + public static IList EnsureDistinctAliases(IList typeModels) { var groups = typeModels.GroupBy(x => x.Alias.ToLowerInvariant()); foreach (var group in groups.Where(x => x.Count() > 1)) diff --git a/src/Umbraco.Tests/ModelsBuilder/ConfigTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Tests.Common/ModelsBuilder/ConfigTests.cs similarity index 98% rename from src/Umbraco.Tests/ModelsBuilder/ConfigTests.cs rename to src/Umbraco.Tests.UnitTests/Umbraco.Tests.Common/ModelsBuilder/ConfigTests.cs index 5ed96365fd..2e15381d18 100644 --- a/src/Umbraco.Tests/ModelsBuilder/ConfigTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Tests.Common/ModelsBuilder/ConfigTests.cs @@ -1,6 +1,5 @@ using System.Configuration; using NUnit.Framework; -using Umbraco.Configuration; using Umbraco.Configuration.Legacy; using Umbraco.Core; using Umbraco.Core.Configuration; diff --git a/src/Umbraco.Tests/ModelsBuilder/StringExtensions.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Tests.Common/ModelsBuilder/StringExtensions.cs similarity index 100% rename from src/Umbraco.Tests/ModelsBuilder/StringExtensions.cs rename to src/Umbraco.Tests.UnitTests/Umbraco.Tests.Common/ModelsBuilder/StringExtensions.cs diff --git a/src/Umbraco.Tests/ModelsBuilder/UmbracoApplicationTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Tests.Common/ModelsBuilder/UmbracoApplicationTests.cs similarity index 100% rename from src/Umbraco.Tests/ModelsBuilder/UmbracoApplicationTests.cs rename to src/Umbraco.Tests.UnitTests/Umbraco.Tests.Common/ModelsBuilder/UmbracoApplicationTests.cs diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Tests.UnitTests.csproj b/src/Umbraco.Tests.UnitTests/Umbraco.Tests.UnitTests.csproj index 2cbf1549dd..6569a49a27 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Tests.UnitTests.csproj +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Tests.UnitTests.csproj @@ -7,6 +7,7 @@ + diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj index f66405b48f..ad92c7e635 100644 --- a/src/Umbraco.Tests/Umbraco.Tests.csproj +++ b/src/Umbraco.Tests/Umbraco.Tests.csproj @@ -130,10 +130,6 @@ - - - - @@ -497,10 +493,6 @@ {3ae7bf57-966b-45a5-910a-954d7c554441} Umbraco.Infrastructure - - {52ac0ba8-a60e-4e36-897b-e8b97a54ed1c} - Umbraco.ModelsBuilder.Embedded - {33085570-9bf2-4065-a9b0-a29d920d13ba} Umbraco.Persistance.SqlCe From 7983dcb305c6994cdb455b6b9c198d11eb35e26b Mon Sep 17 00:00:00 2001 From: Elitsa Marinovska Date: Mon, 13 Jul 2020 21:52:11 +0200 Subject: [PATCH 037/826] Fixing tests and methods after introducing IPublishedSnapshotAccessor service to PublishedModelUtility. Changing accessibility lvls from migrating tests to a different project --- .../Building/TextBuilder.cs | 11 +++++----- .../ModelsBuilder/BuilderTests.cs | 20 +++++++++++++------ 2 files changed, 20 insertions(+), 11 deletions(-) rename src/{Umbraco.Tests => Umbraco.Tests.UnitTests/Umbraco.Tests.Common}/ModelsBuilder/BuilderTests.cs (95%) diff --git a/src/Umbraco.ModelsBuilder.Embedded/Building/TextBuilder.cs b/src/Umbraco.ModelsBuilder.Embedded/Building/TextBuilder.cs index 723ee10f35..4e806a844e 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/Building/TextBuilder.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/Building/TextBuilder.cs @@ -10,7 +10,7 @@ namespace Umbraco.ModelsBuilder.Embedded.Building /// /// Implements a builder that works by writing text. /// - internal class TextBuilder : Builder + public class TextBuilder : Builder { /// /// Initializes a new instance of the class with a list of models to generate @@ -22,7 +22,7 @@ namespace Umbraco.ModelsBuilder.Embedded.Building { } // internal for unit tests only - internal TextBuilder() + public TextBuilder() { } /// @@ -174,6 +174,7 @@ namespace Umbraco.ModelsBuilder.Embedded.Building // write the constants & static methods // as 'new' since parent has its own - or maybe not - disable warning + sb.Append("\t\tprivate readonly IPublishedSnapshotAccessor _publishedSnapshotAccessor;\n\n"); sb.Append("\t\t// helpers\n"); sb.Append("#pragma warning disable 0109 // new is redundant\n"); WriteGeneratedCodeAttribute(sb, "\t\t"); @@ -185,7 +186,7 @@ namespace Umbraco.ModelsBuilder.Embedded.Building itemType); WriteGeneratedCodeAttribute(sb, "\t\t"); sb.Append("\t\tpublic new static IPublishedContentType GetModelContentType()\n"); - sb.Append("\t\t\t=> PublishedModelUtility.GetModelContentType(ModelItemType, ModelTypeAlias);\n"); + sb.Append("\t\t\t=> PublishedModelUtility.GetModelContentType(_publishedSnapshotAccessor, ModelItemType, ModelTypeAlias);\n"); WriteGeneratedCodeAttribute(sb, "\t\t"); sb.AppendFormat("\t\tpublic static IPublishedPropertyType GetModelPropertyType(Expression> selector)\n", type.ClrName); @@ -193,7 +194,7 @@ namespace Umbraco.ModelsBuilder.Embedded.Building sb.Append("#pragma warning restore 0109\n\n"); // write the ctor - sb.AppendFormat("\t\t// ctor\n\t\tpublic {0}(IPublished{1} content)\n\t\t\t: base(content)\n\t\t{{ }}\n\n", + sb.AppendFormat("\t\t// ctor\n\t\tpublic {0}(IPublished{1} content, IPublishedSnapshotAccessor publishedSnapshotAccessor)\n\t\t\t: base(content)\n\t\t{{\n\t\t\t_publishedSnapshotAccessor = publishedSnapshotAccessor;\n\t\t}}\n\n", type.ClrName, type.IsElement ? "Element" : "Content"); // write the properties @@ -416,7 +417,7 @@ namespace Umbraco.ModelsBuilder.Embedded.Building } // internal for unit tests - internal void WriteClrType(StringBuilder sb, Type type) + public void WriteClrType(StringBuilder sb, Type type) { var s = type.ToString(); diff --git a/src/Umbraco.Tests/ModelsBuilder/BuilderTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Tests.Common/ModelsBuilder/BuilderTests.cs similarity index 95% rename from src/Umbraco.Tests/ModelsBuilder/BuilderTests.cs rename to src/Umbraco.Tests.UnitTests/Umbraco.Tests.Common/ModelsBuilder/BuilderTests.cs index 6065570b13..22903ef768 100644 --- a/src/Umbraco.Tests/ModelsBuilder/BuilderTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Tests.Common/ModelsBuilder/BuilderTests.cs @@ -74,6 +74,8 @@ namespace Umbraco.Web.PublishedModels [PublishedModel(""type1"")] public partial class Type1 : PublishedContentModel { + private readonly IPublishedSnapshotAccessor _publishedSnapshotAccessor; + // helpers #pragma warning disable 0109 // new is redundant [global::System.CodeDom.Compiler.GeneratedCodeAttribute(""Umbraco.ModelsBuilder.Embedded"", """ + version + @""")] @@ -82,16 +84,18 @@ namespace Umbraco.Web.PublishedModels public new const PublishedItemType ModelItemType = PublishedItemType.Content; [global::System.CodeDom.Compiler.GeneratedCodeAttribute(""Umbraco.ModelsBuilder.Embedded"", """ + version + @""")] public new static IPublishedContentType GetModelContentType() - => PublishedModelUtility.GetModelContentType(ModelItemType, ModelTypeAlias); + => PublishedModelUtility.GetModelContentType(_publishedSnapshotAccessor, ModelItemType, ModelTypeAlias); [global::System.CodeDom.Compiler.GeneratedCodeAttribute(""Umbraco.ModelsBuilder.Embedded"", """ + version + @""")] public static IPublishedPropertyType GetModelPropertyType(Expression> selector) => PublishedModelUtility.GetModelPropertyType(GetModelContentType(), selector); #pragma warning restore 0109 // ctor - public Type1(IPublishedContent content) + public Type1(IPublishedContent content, IPublishedSnapshotAccessor publishedSnapshotAccessor) : base(content) - { } + { + _publishedSnapshotAccessor = publishedSnapshotAccessor; + } // properties @@ -189,6 +193,8 @@ namespace Umbraco.Web.PublishedModels [PublishedModel(""type1"")] public partial class Type1 : PublishedContentModel { + private readonly IPublishedSnapshotAccessor _publishedSnapshotAccessor; + // helpers #pragma warning disable 0109 // new is redundant [global::System.CodeDom.Compiler.GeneratedCodeAttribute(""Umbraco.ModelsBuilder.Embedded"", """ + version + @""")] @@ -197,16 +203,18 @@ namespace Umbraco.Web.PublishedModels public new const PublishedItemType ModelItemType = PublishedItemType.Content; [global::System.CodeDom.Compiler.GeneratedCodeAttribute(""Umbraco.ModelsBuilder.Embedded"", """ + version + @""")] public new static IPublishedContentType GetModelContentType() - => PublishedModelUtility.GetModelContentType(ModelItemType, ModelTypeAlias); + => PublishedModelUtility.GetModelContentType(_publishedSnapshotAccessor, ModelItemType, ModelTypeAlias); [global::System.CodeDom.Compiler.GeneratedCodeAttribute(""Umbraco.ModelsBuilder.Embedded"", """ + version + @""")] public static IPublishedPropertyType GetModelPropertyType(Expression> selector) => PublishedModelUtility.GetModelPropertyType(GetModelContentType(), selector); #pragma warning restore 0109 // ctor - public Type1(IPublishedContent content) + public Type1(IPublishedContent content, IPublishedSnapshotAccessor publishedSnapshotAccessor) : base(content) - { } + { + _publishedSnapshotAccessor = publishedSnapshotAccessor; + } // properties From 6b5e19fcf252568057cc063953f97e8bb678e258 Mon Sep 17 00:00:00 2001 From: Marc Goodson Date: Sun, 28 Jun 2020 18:08:03 +0100 Subject: [PATCH 038/826] Add the current culture to the cache key used for the CachedPartial Html Helper when using variants it's unlikely to need the same Html.Partial to be cached across all language variations, if we always add the current culture name to the cache key, we ensure this doesn't accidentally happen, and when not using variants, no harm to have the culture for the single site included here --- src/Umbraco.Web/HtmlHelperRenderExtensions.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Umbraco.Web/HtmlHelperRenderExtensions.cs b/src/Umbraco.Web/HtmlHelperRenderExtensions.cs index 4b1de86bcf..e19ae883e9 100644 --- a/src/Umbraco.Web/HtmlHelperRenderExtensions.cs +++ b/src/Umbraco.Web/HtmlHelperRenderExtensions.cs @@ -83,6 +83,12 @@ namespace Umbraco.Web Func contextualKeyBuilder = null) { var cacheKey = new StringBuilder(partialViewName); + //let's always cache by the current culture to allow variants to have different cache results + var cultureName = System.Threading.Thread.CurrentThread.CurrentUICulture.Name; + if (!String.IsNullOrEmpty(cultureName)) + { + cacheKey.AppendFormat("{0}-", cultureName); + } if (cacheByPage) { if (Current.UmbracoContext == null) From fbd2a306069b2712dce3709aa09780a4e843f181 Mon Sep 17 00:00:00 2001 From: Marc Goodson Date: Tue, 14 Jul 2020 12:24:21 +0100 Subject: [PATCH 039/826] Update 'default value' title + description of CheckBox Configuration (#8421) --- src/Umbraco.Web/PropertyEditors/TrueFalseConfiguration.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web/PropertyEditors/TrueFalseConfiguration.cs b/src/Umbraco.Web/PropertyEditors/TrueFalseConfiguration.cs index c6b3953e8c..3fa82aa37e 100644 --- a/src/Umbraco.Web/PropertyEditors/TrueFalseConfiguration.cs +++ b/src/Umbraco.Web/PropertyEditors/TrueFalseConfiguration.cs @@ -7,7 +7,7 @@ namespace Umbraco.Web.PropertyEditors /// public class TrueFalseConfiguration { - [ConfigurationField("default", "Default Value", "boolean")] + [ConfigurationField("default","Initial State", "boolean",Description = "The initial state for this checkbox, when it is displayed for the first time in the backoffice, eg. for a new content item.")] public string Default { get; set; } // TODO: well, true or false?! [ConfigurationField("labelOn", "Write a label text", "textstring")] From d347d368610c050fdc921241756b2c557c2ec8d8 Mon Sep 17 00:00:00 2001 From: Sebastiaan Janssen Date: Tue, 14 Jul 2020 13:48:46 +0200 Subject: [PATCH 040/826] Don't run CodeQL on PRs for now --- .github/workflows/codeql-analysis.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 46e09dee3e..b0984bd846 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -2,10 +2,11 @@ name: "Code scanning - action" on: push: - branches: [v8/contrib,v8/codeql] + branches: [v8/contrib] pull_request: # The branches below must be a subset of the branches above - branches: [v8/contrib] + # SJ: Don't run on PR branches for now + # branches: [v8/contrib] schedule: - cron: '0 7 * * 2' From 8c8c26bc9a81ffc0a137e1f9bcd7b3a287eace28 Mon Sep 17 00:00:00 2001 From: Bjarne Fyrstenborg Date: Tue, 14 Jul 2020 13:58:57 +0200 Subject: [PATCH 041/826] Adjust target overlay position using hotkey (#8431) --- .../overlays/umboverlay.directive.js | 20 ++++++++++++------- .../src/less/components/overlays.less | 2 +- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/overlays/umboverlay.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/overlays/umboverlay.directive.js index 5a06edf617..c85b37a8a4 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/overlays/umboverlay.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/overlays/umboverlay.directive.js @@ -407,11 +407,15 @@ Opens an overlay to show a custom YSOD.
function setTargetPosition() { - var container = $("#contentwrapper"); - var containerLeft = container[0].offsetLeft; - var containerRight = containerLeft + container[0].offsetWidth; - var containerTop = container[0].offsetTop; - var containerBottom = containerTop + container[0].offsetHeight; + var overlay = $(scope.model.event.target).closest('.umb-overlay'); + var container = overlay.length > 0 ? overlay : $("#contentwrapper"); + + let rect = container[0].getBoundingClientRect(); + + var containerLeft = rect.left; + var containerRight = containerLeft + rect.width; + var containerTop = rect.top; + var containerBottom = containerTop + rect.height; var mousePositionClickX = null; var mousePositionClickY = null; @@ -434,8 +438,9 @@ Opens an overlay to show a custom YSOD.
elementWidth = el[0].clientWidth; // move element to this position - position.left = mousePositionClickX - (elementWidth / 2); - position.top = mousePositionClickY - (elementHeight / 2); + // when using hotkey it fallback to center of container + position.left = mousePositionClickX ? mousePositionClickX - (elementWidth / 2) : (containerLeft + containerRight) / 2 - (elementWidth / 2); + position.top = mousePositionClickY ? mousePositionClickY - (elementHeight / 2) : (containerTop + containerBottom) / 2 - (elementHeight / 2); // check to see if element is outside screen // outside right @@ -463,6 +468,7 @@ Opens an overlay to show a custom YSOD.
} el.css(position); + el.css("visibility", "visible"); } scope.submitForm = function (model) { diff --git a/src/Umbraco.Web.UI.Client/src/less/components/overlays.less b/src/Umbraco.Web.UI.Client/src/less/components/overlays.less index 381157c8bc..5868408969 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/overlays.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/overlays.less @@ -106,7 +106,6 @@ height: auto; top: 50%; left: 50%; - transform: translate(-50%, 0); transform: translate(-50%, -50%); border-radius: @baseBorderRadius; } @@ -128,6 +127,7 @@ width: 400px; max-height: 100vh; box-sizing: border-box; + visibility: hidden; border-radius: @baseBorderRadius; &.umb-overlay--medium { From c89fa6fe69e0043d003cecb67051829fd837192e Mon Sep 17 00:00:00 2001 From: Bjarne Fyrstenborg Date: Tue, 14 Jul 2020 14:02:06 +0200 Subject: [PATCH 042/826] Listview columns grouping (#8423) --- .../listview/includeproperties.prevalues.html | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/includeproperties.prevalues.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/includeproperties.prevalues.html index 0499bea713..c8f2a8050c 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/includeproperties.prevalues.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/includeproperties.prevalues.html @@ -1,10 +1,12 @@ 
- + diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/layouts.prevalues.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/layouts.prevalues.controller.js index a02215f452..acfb114307 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/layouts.prevalues.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/layouts.prevalues.controller.js @@ -15,6 +15,8 @@ vm.focusLayoutName = false; vm.layoutsSortableOptions = { + axis: "y", + containment: "parent", distance: 10, tolerance: "pointer", opacity: 0.7, @@ -41,7 +43,6 @@ }; $scope.model.value.push(layout); - } function showPrompt(layout) { diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/layouts.prevalues.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/layouts.prevalues.html index 15b66d856d..d0348bb708 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/layouts.prevalues.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/layouts.prevalues.html @@ -1,47 +1,53 @@
-
+
-
+
- +
-
+ - +
-
- -
+ -
+
+ +
-
- - {{ layout.name }} - (system layout) -
+
-
- -
+
+ + {{ layout.name }} + (system layout) +
-
- -
- - - -
-
+
+ +
-
+
+ + +
+ + + +
+
+ +
+ +
From e6f264136c20e72a2796318595666ae93b7089dd Mon Sep 17 00:00:00 2001 From: Bjarne Fyrstenborg Date: Tue, 14 Jul 2020 14:56:25 +0200 Subject: [PATCH 044/826] Adjust tooltip position inside overlay (#8416) --- .../components/umbtooltip.directive.js | 62 +++++++++++-------- .../itempicker/itempicker.controller.js | 4 +- .../overlays/itempicker/itempicker.html | 16 ++--- .../nestedcontent/nestedcontent.controller.js | 3 +- 4 files changed, 47 insertions(+), 38 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbtooltip.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbtooltip.directive.js index ef7006be2c..ce1885a7cf 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbtooltip.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbtooltip.directive.js @@ -77,13 +77,17 @@ Use this directive to render a tooltip. scope.tooltipStyles.left = 0; scope.tooltipStyles.top = 0; - function setTooltipPosition(event) { + function setTooltipPosition(event) { - var container = $("#contentwrapper"); - var containerLeft = container[0].offsetLeft; - var containerRight = containerLeft + container[0].offsetWidth; - var containerTop = container[0].offsetTop; - var containerBottom = containerTop + container[0].offsetHeight; + var overlay = $(event.target).closest('.umb-overlay'); + var container = overlay.length > 0 ? overlay : $("#contentwrapper"); + + let rect = container[0].getBoundingClientRect(); + + var containerLeft = rect.left; + var containerRight = containerLeft + rect.width; + var containerTop = rect.top; + var containerBottom = containerTop + rect.height; var elementHeight = null; var elementWidth = null; @@ -102,39 +106,43 @@ Use this directive to render a tooltip. position.left = event.pageX - (elementWidth / 2); position.top = event.pageY; - // check to see if element is outside screen - // outside right - if (position.left + elementWidth > containerRight) { - position.right = 10; - position.left = "inherit"; + if (overlay.length > 0) { + position.left = event.pageX - rect.left - (elementWidth / 2); + position.top = event.pageY - rect.top; } + else { + // check to see if element is outside screen + // outside right + if (position.left + elementWidth > containerRight) { + position.right = 10; + position.left = "inherit"; + } - // outside bottom - if (position.top + elementHeight > containerBottom) { - position.bottom = 10; - position.top = "inherit"; - } + // outside bottom + if (position.top + elementHeight > containerBottom) { + position.bottom = 10; + position.top = "inherit"; + } - // outside left - if (position.left < containerLeft) { - position.left = containerLeft + 10; - position.right = "inherit"; - } + // outside left + if (position.left < containerLeft) { + position.left = containerLeft + 10; + position.right = "inherit"; + } - // outside top - if (position.top < containerTop) { - position.top = 10; - position.bottom = "inherit"; + // outside top + if (position.top < containerTop) { + position.top = 10; + position.bottom = "inherit"; + } } scope.tooltipStyles = position; el.css(position); - } setTooltipPosition(scope.event); - } var directive = { diff --git a/src/Umbraco.Web.UI.Client/src/views/common/overlays/itempicker/itempicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/overlays/itempicker/itempicker.controller.js index 17184ae9a3..ca8a2d7a47 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/overlays/itempicker/itempicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/overlays/itempicker/itempicker.controller.js @@ -24,11 +24,11 @@ function ItemPickerOverlay($scope, localizationService) { event: null }; - $scope.showTooltip = function(item, $event) { + $scope.showTooltip = function (item, $event) { if (!item.tooltip) { - $scope.mouseLeave(); return; } + $scope.tooltip = { show: true, event: $event, diff --git a/src/Umbraco.Web.UI.Client/src/views/common/overlays/itempicker/itempicker.html b/src/Umbraco.Web.UI.Client/src/views/common/overlays/itempicker/itempicker.html index ff2ce6379f..fb1a4ae6a5 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/overlays/itempicker/itempicker.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/overlays/itempicker/itempicker.html @@ -1,7 +1,7 @@
  • - @@ -35,10 +35,10 @@
    • -
    • diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.controller.js index e4812360d7..44b507b74b 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.controller.js @@ -195,7 +195,8 @@ availableItems.push({ alias: scaffold.contentTypeAlias, name: scaffold.contentTypeName, - icon: iconHelper.convertFromLegacyIcon(scaffold.icon) + icon: iconHelper.convertFromLegacyIcon(scaffold.icon), + tooltip: scaffold.documentType.description }); }); From 6fc81260768cddfa647f3d62bb4ffa5b1fcb4434 Mon Sep 17 00:00:00 2001 From: Gareth Evans Date: Fri, 10 Jul 2020 15:30:00 +1200 Subject: [PATCH 045/826] #8412 Set ng-maxlength and maxlength attributes on the tag input in umb-tags-editor.html to avoid a string or binary data would be truncated error when the entered tag exceeds the database column length --- .../src/views/components/tags/umb-tags-editor.html | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/views/components/tags/umb-tags-editor.html b/src/Umbraco.Web.UI.Client/src/views/components/tags/umb-tags-editor.html index 48623fe7d1..2929fd229c 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/tags/umb-tags-editor.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/tags/umb-tags-editor.html @@ -26,6 +26,8 @@ ng-model="vm.tagToAdd" ng-keydown="vm.addTagOnEnter($event)" ng-blur="vm.addTag()" + ng-maxlength="200" + maxlength="200" localize="placeholder" placeholder="@placeholders_enterTags" /> From 6da85dd47d0fe4dff7750755c637afddf0afa5fc Mon Sep 17 00:00:00 2001 From: Bjarne Fyrstenborg Date: Fri, 10 Jul 2020 00:05:16 +0200 Subject: [PATCH 046/826] Remove unnecessary translation to removed variable --- .../documenttypes/views/permissions/permissions.controller.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/documenttypes/views/permissions/permissions.controller.js b/src/Umbraco.Web.UI.Client/src/views/documenttypes/views/permissions/permissions.controller.js index 94e0b443ca..b0531d0c0a 100644 --- a/src/Umbraco.Web.UI.Client/src/views/documenttypes/views/permissions/permissions.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/documenttypes/views/permissions/permissions.controller.js @@ -34,10 +34,6 @@ function init() { - localizationService.localize("contentTypeEditor_chooseChildNode").then(function(value){ - childNodeSelectorOverlayTitle = value; - }); - contentTypeResource.getAll().then(function(contentTypes){ vm.contentTypes = _.where(contentTypes, {isElement: false}); From 0d7741d211c30f4a27f0cbf330d6abb1b321bb64 Mon Sep 17 00:00:00 2001 From: Bjarne Fyrstenborg Date: Fri, 10 Jul 2020 00:29:06 +0200 Subject: [PATCH 047/826] Allow editor info to shrink for longer datatype names --- .../src/less/components/umb-group-builder.less | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-group-builder.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-group-builder.less index 6eded29b8b..ae7d5a305d 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-group-builder.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-group-builder.less @@ -523,7 +523,7 @@ input.umb-group-builder__group-sort-value { } .editor-info { - flex: 1 0 auto; + flex: 1 1 auto; text-align: left; display: flex; align-items: center; From 2f7cf8cb0f4d4cc238a31e53a4cd6d1566cac128 Mon Sep 17 00:00:00 2001 From: Bjarne Fyrstenborg Date: Fri, 10 Jul 2020 00:40:12 +0200 Subject: [PATCH 048/826] Align group builder property actions to top --- .../src/less/components/umb-group-builder.less | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-group-builder.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-group-builder.less index ae7d5a305d..fa8dc39e0f 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-group-builder.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-group-builder.less @@ -347,12 +347,11 @@ input.umb-group-builder__group-title-input:disabled:hover { .umb-group-builder__property-actions { flex: 0 0 44px; display: flex; - align-items: center; + align-items: flex-start; justify-content: flex-end; } .umb-group-builder__property-action { - position: relative; margin: 5px 0; From 984214ea7ba00073733b61bbb017b741845457f6 Mon Sep 17 00:00:00 2001 From: hkooiker Date: Tue, 14 Jul 2020 15:47:33 +0200 Subject: [PATCH 049/826] Member picker value converter (#8401) --- .../ValueConverters/MemberPickerValueConverter.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Umbraco.Web/PropertyEditors/ValueConverters/MemberPickerValueConverter.cs b/src/Umbraco.Web/PropertyEditors/ValueConverters/MemberPickerValueConverter.cs index cd69fd9de6..71bb2fd2ee 100644 --- a/src/Umbraco.Web/PropertyEditors/ValueConverters/MemberPickerValueConverter.cs +++ b/src/Umbraco.Web/PropertyEditors/ValueConverters/MemberPickerValueConverter.cs @@ -31,6 +31,8 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters public override object ConvertSourceToIntermediate(IPublishedElement owner, IPublishedPropertyType propertyType, object source, bool preview) { + if (source == null) return null; + var attemptConvertInt = source.TryConvertTo(); if (attemptConvertInt.Success) return attemptConvertInt.Result; From f02a16f094e9f901acdcc5e3bb90bf128db55f71 Mon Sep 17 00:00:00 2001 From: Bjarne Fyrstenborg Date: Mon, 6 Jul 2020 16:33:19 +0200 Subject: [PATCH 050/826] Register dragover state of file upload --- .../components/upload/umbfileupload.directive.js | 11 +++++++++++ .../upload/umbpropertyfileupload.directive.js | 8 ++++++++ .../src/less/components/umb-property-file-upload.less | 6 ++++++ .../components/upload/umb-property-file-upload.html | 2 +- 4 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/upload/umbfileupload.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/upload/umbfileupload.directive.js index 6a8ffa7969..3581aed9e0 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/upload/umbfileupload.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/upload/umbfileupload.directive.js @@ -19,6 +19,17 @@ function umbFileUpload() { //clear the element value - this allows us to pick the same file again and again el.val(''); }); + + el.on('drag dragstart dragend dragover dragenter dragleave drop', function (e) { + e.preventDefault(); + e.stopPropagation(); + }) + .on('dragover dragenter', function () { + scope.$emit("isDragover", { value: true }); + }) + .on('dragleave dragend drop', function () { + scope.$emit("isDragover", { value: false }); + }); } }; } diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/upload/umbpropertyfileupload.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/upload/umbpropertyfileupload.directive.js index 653b4f427c..90dbbc650d 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/upload/umbpropertyfileupload.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/upload/umbpropertyfileupload.directive.js @@ -78,6 +78,8 @@ /** Called when the component initializes */ function onInit() { $scope.$on("filesSelected", onFilesSelected); + $scope.$on("isDragover", isDragover); + initialize(); } @@ -293,6 +295,11 @@ } } + function isDragover(e, args) { + vm.dragover = args.value; + angularHelper.safeApply($scope); + } + }; var umbPropertyFileUploadComponent = { @@ -303,6 +310,7 @@ propertyAlias: "@", value: "<", hideSelection: "<", + dragover: "<", /** * Called when a file is selected on this instance */ diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-property-file-upload.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-property-file-upload.less index 39b2f4002e..7a2883efd1 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-property-file-upload.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-property-file-upload.less @@ -26,4 +26,10 @@ width: 100%; } } + + .drag-over { + .umb-upload-button-big { + border-color: @gray-1; + } + } } diff --git a/src/Umbraco.Web.UI.Client/src/views/components/upload/umb-property-file-upload.html b/src/Umbraco.Web.UI.Client/src/views/components/upload/umb-property-file-upload.html index 9b4e60a413..2069707f20 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/upload/umb-property-file-upload.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/upload/umb-property-file-upload.html @@ -1,6 +1,6 @@ 
      - +
      Date: Tue, 14 Jul 2020 16:23:34 +0200 Subject: [PATCH 051/826] Show SVG preview on upload (#8387) --- .../upload/umbpropertyfileupload.directive.js | 15 +- .../components/imaging/umb-image-crop.html | 4 +- .../components/upload/umb-file-dropzone.html | 156 +++++++++--------- .../upload/umb-property-file-upload.html | 12 +- 4 files changed, 94 insertions(+), 93 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/upload/umbpropertyfileupload.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/upload/umbpropertyfileupload.directive.js index 90dbbc650d..db1e38adc6 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/upload/umbpropertyfileupload.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/upload/umbpropertyfileupload.directive.js @@ -120,7 +120,9 @@ isImage: mediaHelper.detectIfImageByExtension(file), extension: getExtension(file) }; + f.fileSrc = getThumbnail(f); + return f; }); @@ -230,19 +232,22 @@ var index = i; //capture var isImage = mediaHelper.detectIfImageByExtension(files[i].name); + var extension = getExtension(files[i].name); - //save the file object to the files collection - vm.files.push({ + var f = { isImage: isImage, - extension: getExtension(files[i].name), + extension: extension, fileName: files[i].name, isClientSide: true - }); + }; + + // Save the file object to the files collection + vm.files.push(f); //special check for a comma in the name newVal += files[i].name.split(',').join('-') + ","; - if (isImage) { + if (isImage || extension === "svg") { var deferred = $q.defer(); diff --git a/src/Umbraco.Web.UI.Client/src/views/components/imaging/umb-image-crop.html b/src/Umbraco.Web.UI.Client/src/views/components/imaging/umb-image-crop.html index 8fba4d1e3c..933551bbff 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/imaging/umb-image-crop.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/imaging/umb-image-crop.html @@ -7,7 +7,7 @@
      - +
      - +
      diff --git a/src/Umbraco.Web.UI.Client/src/views/components/upload/umb-file-dropzone.html b/src/Umbraco.Web.UI.Client/src/views/components/upload/umb-file-dropzone.html index b079b72be4..ff2f04f35c 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/upload/umb-file-dropzone.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/upload/umb-file-dropzone.html @@ -1,107 +1,105 @@
      - + - -
      + +
      +
      +

      + Drag and drop your file(s) into the area +

      -
      -

      - Drag and drop your file(s) into the area -

      - - + + - - - + + +
      -
      - -
        + +
          - -
        • + +
        • - -
          {{ file.name }}
          + +
          {{ file.name }}
          - -
          - -
          + +
          + +
          -
        • + -
        • +
        • - -
          {{ currentFile.name }}
          + +
          {{ currentFile.name }}
          - -
          - -
          -
        • + +
          + +
          + - -
        • + +
        • - -
          {{ queued.name }}
          -
        • + +
          {{ queued.name }}
          + -
        • +
        • - -
          + +
          - {{ file.name }} + {{ file.name }} - - - "{{maxFileSize}}" - + + + "{{maxFileSize}}" + - - {{file.serverErrorMessage}} - + + {{file.serverErrorMessage}} + -
          +
          - -
          - -
          + +
          + +
          -
        • -
        + +
      - +
      diff --git a/src/Umbraco.Web.UI.Client/src/views/components/upload/umb-property-file-upload.html b/src/Umbraco.Web.UI.Client/src/views/components/upload/umb-property-file-upload.html index 2069707f20..a6eb60d15c 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/upload/umb-property-file-upload.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/upload/umb-property-file-upload.html @@ -3,10 +3,8 @@ -
      - +
      +

      Click to upload

      @@ -19,8 +17,8 @@
      @@ -28,7 +26,7 @@
      - + From e66fd7b8e070d4c4f91c7ecfdbd05a12703eab3a Mon Sep 17 00:00:00 2001 From: Bjarne Fyrstenborg Date: Wed, 1 Jul 2020 14:49:24 +0200 Subject: [PATCH 052/826] Adjust border radius of button in button group if having sub buttons --- .../src/less/components/buttons/umb-button-group.less | 2 +- .../src/views/components/buttons/umb-button-group.html | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/less/components/buttons/umb-button-group.less b/src/Umbraco.Web.UI.Client/src/less/components/buttons/umb-button-group.less index 02b67460f6..24800c1142 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/buttons/umb-button-group.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/buttons/umb-button-group.less @@ -14,7 +14,7 @@ display: flex; } -.umb-button-group { +.umb-button-group.-with-button-group-toggle { .umb-button__button { border-radius: @baseBorderRadius 0 0 @baseBorderRadius; diff --git a/src/Umbraco.Web.UI.Client/src/views/components/buttons/umb-button-group.html b/src/Umbraco.Web.UI.Client/src/views/components/buttons/umb-button-group.html index 49827910d0..a3eadcfbc2 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/buttons/umb-button-group.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/buttons/umb-button-group.html @@ -1,4 +1,4 @@ -
      +
      + ng-class="{'-align-right': float === 'right'}"> From 888109f69b4fd995b33131e30a5c0a8255d9ce84 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 Jul 2020 20:36:45 +0000 Subject: [PATCH 058/826] Bump lodash from 4.17.15 to 4.17.19 in /src/Umbraco.Web.UI.Client Bumps [lodash](https://github.com/lodash/lodash) from 4.17.15 to 4.17.19. - [Release notes](https://github.com/lodash/lodash/releases) - [Commits](https://github.com/lodash/lodash/compare/4.17.15...4.17.19) Signed-off-by: dependabot[bot] --- src/Umbraco.Web.UI.Client/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/package.json b/src/Umbraco.Web.UI.Client/package.json index b1d38a8b3f..459f3325e9 100644 --- a/src/Umbraco.Web.UI.Client/package.json +++ b/src/Umbraco.Web.UI.Client/package.json @@ -77,7 +77,7 @@ "karma-phantomjs-launcher": "1.0.4", "karma-spec-reporter": "0.0.32", "less": "3.10.3", - "lodash": "4.17.15", + "lodash": "4.17.19", "marked": "^0.7.0", "merge-stream": "2.0.0", "run-sequence": "2.2.1" From 869f0e2d1164cf17d4501d620bbb3e58cd7fcc9a Mon Sep 17 00:00:00 2001 From: Callum Whyte Date: Wed, 22 Jul 2020 09:11:16 +0100 Subject: [PATCH 059/826] Improving umb-button link docs --- .../directives/components/buttons/umbbutton.directive.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/buttons/umbbutton.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/buttons/umbbutton.directive.js index dc012945dd..5e007a7ff4 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/buttons/umbbutton.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/buttons/umbbutton.directive.js @@ -55,8 +55,8 @@ Use this directive to render an umbraco button. The directive can be used to gen @param {callback} action The button action which should be performed when the button is clicked. -@param {string=} href Url/Path to navigato to. -@param {string=} type Set the button type ("button" or "submit"). +@param {string=} href Url/Path to navigato to. (requires "type" to be set to "link") +@param {string=} type Set the button type ("button", "link", "submit"). @param {string=} buttonStyle Set the style of the button. The directive uses the default bootstrap styles ("primary", "info", "success", "warning", "danger", "inverse", "link", "block"). Pass in array to add multple styles [success,block]. @param {string=} state Set a progress state on the button ("init", "busy", "success", "error"). @param {string=} shortcut Set a keyboard shortcut for the button ("ctrl+c"). From 7b8ef85541b993e375c98cc969c41f029e7c3142 Mon Sep 17 00:00:00 2001 From: Bjarne Fyrstenborg Date: Wed, 22 Jul 2020 18:55:47 +0200 Subject: [PATCH 060/826] Adjust toggle styling when checked and disabled (#8445) --- .../components/buttons/umbtoggle.directive.js | 2 +- .../less/components/buttons/umb-toggle.less | 50 ++++++++++++------- .../views/components/buttons/umb-toggle.html | 8 ++- 3 files changed, 35 insertions(+), 25 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/buttons/umbtoggle.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/buttons/umbtoggle.directive.js index 79cb99cf07..5cdd23d4af 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/buttons/umbtoggle.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/buttons/umbtoggle.directive.js @@ -78,6 +78,7 @@ scope.inputId = scope.inputId || "umb-toggle_" + String.CreateGuid(); setLabelText(); + // must wait until the current digest cycle is finished before we emit this event on init, // otherwise other property editors might not yet be ready to receive the event $timeout(function () { @@ -115,7 +116,6 @@ }; onInit(); - } var directive = { diff --git a/src/Umbraco.Web.UI.Client/src/less/components/buttons/umb-toggle.less b/src/Umbraco.Web.UI.Client/src/less/components/buttons/umb-toggle.less index ff4122b258..701af849cc 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/buttons/umb-toggle.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/buttons/umb-toggle.less @@ -41,9 +41,6 @@ } } - - - .umb-toggle__handler { position: absolute; top: 1px; @@ -59,10 +56,8 @@ transform: translateX(20px); background-color: @white; } - } - /* Icons */ .umb-toggle__icon { @@ -78,9 +73,7 @@ color:@white; transition: opacity 120ms; opacity: 0; - // .umb-toggle:hover & { - // color: @ui-btn-hover; - // } + .umb-toggle--checked & { opacity: 1; } @@ -93,6 +86,7 @@ right: 5px; color: @ui-btn; transition: opacity 120ms; + .umb-toggle--checked & { opacity: 0; } @@ -101,23 +95,41 @@ } } - - -.umb-toggle.umb-toggle--disabled.umb-toggle--checked, .umb-toggle.umb-toggle--disabled { .umb-toggle__toggle { cursor: not-allowed; - background-color: @gray-9; - border-color: @gray-9; } - .umb-toggle__icon--left { - color: @gray-6; + + &, &.umb-toggle--checked { + + .umb-toggle__toggle { + .umb-toggle__handler { + background-color: @gray-10; + } + } } - .umb-toggle__icon--right { - color: @gray-6; + + &:not(.umb-toggle--checked) { + .umb-toggle__toggle { + background-color: @gray-8; + border-color: @gray-8; + } + + .umb-toggle__icon--left, + .umb-toggle__icon--right { + color: @gray-6; + } } - .umb-toggle__handler { - background-color: @gray-10; + + &.umb-toggle--checked { + .umb-toggle__toggle { + background-color: lighten(@ui-btn, 50%); + border-color: lighten(@ui-btn, 50%); + } + .umb-toggle__icon--left, + .umb-toggle__icon--right { + color: @gray-9; + } } } diff --git a/src/Umbraco.Web.UI.Client/src/views/components/buttons/umb-toggle.html b/src/Umbraco.Web.UI.Client/src/views/components/buttons/umb-toggle.html index 185d852560..449c436149 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/buttons/umb-toggle.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/buttons/umb-toggle.html @@ -1,8 +1,7 @@ From 78c429c4afdd6b29b0290d92e9ff2d2408042337 Mon Sep 17 00:00:00 2001 From: Bjarne Fyrstenborg Date: Wed, 22 Jul 2020 18:56:58 +0200 Subject: [PATCH 061/826] Streamline umb-checkbox and umb-radiobutton components (#8441) --- .../components/forms/umbcheckbox.directive.js | 5 +++-- .../forms/umbradiobutton.directive.js | 12 ++++++++-- .../views/components/forms/umb-checkbox.html | 3 --- .../components/forms/umb-radiobutton.html | 22 ++++++++++++++++--- 4 files changed, 32 insertions(+), 10 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/umbcheckbox.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/umbcheckbox.directive.js index 389aec2044..3f55e385ac 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/umbcheckbox.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/umbcheckbox.directive.js @@ -31,8 +31,9 @@ @param {boolean} disabled Set the checkbox to be disabled. @param {boolean} required Set the checkbox to be required. @param {callback} onChange Callback when the value of the checkbox change by interaction. -@param {string} cssClass Set a css class modifier -@param {boolean} disableDirtyCheck Disable checking if the model is dirty +@param {string} cssClass Set a css class modifier. +@param {string} iconClass Set an icon next to checkbox. +@param {boolean} disableDirtyCheck Disable checking if the model is dirty. **/ diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/umbradiobutton.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/umbradiobutton.directive.js index d79140f947..99e2a8c633 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/umbradiobutton.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/umbradiobutton.directive.js @@ -26,10 +26,14 @@ @param {string} value Set the value of the radiobutton. @param {string} name Set the name of the radiobutton. @param {string} text Set the text for the radiobutton label. -@param {string} labelKey Set a dictinary/localization string for the checkbox label +@param {string} labelKey Set a dictinary/localization string for the checkbox label. +@param {string} serverValidationField Set the val-server-field of the radiobutton. @param {boolean} disabled Set the radiobutton to be disabled. @param {boolean} required Set the radiobutton to be required. @param {callback} onChange Callback when the value of the radiobutton change by interaction. +@param {string} cssClass Set a css class modifier. +@param {string} iconClass Set an icon next to radiobutton. +@param {boolean} disableDirtyCheck Disable checking if the model is dirty. **/ @@ -77,9 +81,13 @@ name: "@", text: "@", labelKey: "@?", + serverValidationField: "@", disabled: "<", required: "<", - onChange: "&?" + onChange: "&?", + cssClass: "@?", + iconClass: "@?", + disableDirtyCheck: "=?" } }; diff --git a/src/Umbraco.Web.UI.Client/src/views/components/forms/umb-checkbox.html b/src/Umbraco.Web.UI.Client/src/views/components/forms/umb-checkbox.html index 3f3ee59c1a..86771e7fac 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/forms/umb-checkbox.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/forms/umb-checkbox.html @@ -32,10 +32,7 @@ - - {{vm.text}} - diff --git a/src/Umbraco.Web.UI.Client/src/views/components/forms/umb-radiobutton.html b/src/Umbraco.Web.UI.Client/src/views/components/forms/umb-radiobutton.html index 356d99dbe2..fb4fbbd2a6 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/forms/umb-radiobutton.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/forms/umb-radiobutton.html @@ -1,10 +1,25 @@ -
- internal class GlobalSettings : IGlobalSettings + public class GlobalSettings { - private const string Prefix = Constants.Configuration.ConfigGlobalPrefix; - internal const string StaticReservedPaths = "~/app_plugins/,~/install/,~/mini-profiler-resources/,"; //must end with a comma! internal const string StaticReservedUrls = "~/config/splashes/noNodes.aspx,~/.well-known,"; //must end with a comma! - private readonly IConfiguration _configuration; + public string ReservedUrls { get; set; } = StaticReservedUrls; - public GlobalSettings(IConfiguration configuration) - { - _configuration = configuration; - } - - public string ReservedUrls => _configuration.GetValue(Prefix + "ReservedUrls", StaticReservedUrls); - public string ReservedPaths => _configuration.GetValue(Prefix + "ReservedPaths", StaticReservedPaths); + public string ReservedPaths { get; set; } = StaticReservedPaths; // TODO: https://github.com/umbraco/Umbraco-CMS/issues/4238 - stop having version in web.config appSettings - public string ConfigurationStatus - { - get => _configuration.GetValue(Prefix + "ConfigurationStatus"); - set => throw new NotImplementedException("We should remove this and only use the value from database"); - } + // TODO: previously this would throw on set, but presumably we can't do that if we do still want this in config. + public string ConfigurationStatus { get; set; } - public int TimeOutInMinutes => _configuration.GetValue(Prefix + "TimeOutInMinutes", 20); - public string DefaultUILanguage => _configuration.GetValue(Prefix + "DefaultUILanguage", "en-US"); + public int TimeOutInMinutes { get; set; } = 20; - public bool HideTopLevelNodeFromPath => - _configuration.GetValue(Prefix + "HideTopLevelNodeFromPath", false); + public string DefaultUILanguage { get; set; } = "en-US"; - public bool UseHttps => _configuration.GetValue(Prefix + "UseHttps", false); - public int VersionCheckPeriod => _configuration.GetValue(Prefix + "VersionCheckPeriod", 7); - public string UmbracoPath => _configuration.GetValue(Prefix + "UmbracoPath", "~/umbraco"); - public string UmbracoCssPath => _configuration.GetValue(Prefix + "UmbracoCssPath", "~/css"); + public bool HideTopLevelNodeFromPath { get; set; } = false; - public string UmbracoScriptsPath => - _configuration.GetValue(Prefix + "UmbracoScriptsPath", "~/scripts"); + public bool UseHttps { get; set; } = false; - public string UmbracoMediaPath => _configuration.GetValue(Prefix + "UmbracoMediaPath", "~/media"); + public int VersionCheckPeriod { get; set; } = 7; - public bool InstallMissingDatabase => - _configuration.GetValue(Prefix + "InstallMissingDatabase", false); + public string UmbracoPath { get; set; } = "~/umbraco"; - public bool InstallEmptyDatabase => _configuration.GetValue(Prefix + "InstallEmptyDatabase", false); + public string UmbracoCssPath { get; set; } = "~/css"; - public bool DisableElectionForSingleServer => - _configuration.GetValue(Prefix + "DisableElectionForSingleServer", false); + public string UmbracoScriptsPath { get; set; } = "~/scripts"; - public string RegisterType => _configuration.GetValue(Prefix + "RegisterType", string.Empty); + public string UmbracoMediaPath { get; set; } = "~/media"; - public string DatabaseFactoryServerVersion => - _configuration.GetValue(Prefix + "DatabaseFactoryServerVersion", string.Empty); + public bool InstallMissingDatabase { get; set; } = false; - public string MainDomLock => _configuration.GetValue(Prefix + "MainDomLock", string.Empty); + public bool InstallEmptyDatabase { get; set; } = false; - public string NoNodesViewPath => - _configuration.GetValue(Prefix + "NoNodesViewPath", "~/config/splashes/NoNodes.cshtml"); + public bool DisableElectionForSingleServer { get; set; } = false; - public bool IsSmtpServerConfigured => - _configuration.GetSection(Constants.Configuration.ConfigGlobalPrefix + "Smtp")?.GetChildren().Any() ?? false; + public string RegisterType { get; set; } = string.Empty; - public ISmtpSettings SmtpSettings => - new SmtpSettingsImpl(_configuration.GetSection(Constants.Configuration.ConfigGlobalPrefix + "Smtp")); + public string DatabaseFactoryServerVersion { get; set; } = string.Empty; - private class SmtpSettingsImpl : ISmtpSettings - { - private readonly IConfigurationSection _configurationSection; + public string MainDomLock { get; set; } = string.Empty; - public SmtpSettingsImpl(IConfigurationSection configurationSection) - { - _configurationSection = configurationSection; - } + public string NoNodesViewPath { get; set; } = "~/config/splashes/NoNodes.cshtml"; - public string From => _configurationSection.GetValue("From"); - public string Host => _configurationSection.GetValue("Host"); - public int Port => _configurationSection.GetValue("Port"); - public string PickupDirectoryLocation => _configurationSection.GetValue("PickupDirectoryLocation"); - public SmtpDeliveryMethod DeliveryMethod => _configurationSection.GetValue("DeliveryMethod"); + public bool IsSmtpServerConfigured => !string.IsNullOrWhiteSpace(SmtpSettings?.Host); - public string Username => _configurationSection.GetValue("Username"); - - public string Password => _configurationSection.GetValue("Password"); - } + [JsonPropertyName("Smtp")] + public SmtpSettings SmtpSettings { get; set; } } } diff --git a/src/Umbraco.Configuration/Models/HostingSettings.cs b/src/Umbraco.Configuration/Models/HostingSettings.cs index f0fbcf4cab..e096a207da 100644 --- a/src/Umbraco.Configuration/Models/HostingSettings.cs +++ b/src/Umbraco.Configuration/Models/HostingSettings.cs @@ -1,22 +1,17 @@ -using Microsoft.Extensions.Configuration; +using System.Text.Json.Serialization; +using Microsoft.Extensions.Configuration; using Umbraco.Core; using Umbraco.Core.Configuration; namespace Umbraco.Configuration.Models { - internal class HostingSettings : IHostingSettings + public class HostingSettings { - private const string Prefix = Constants.Configuration.ConfigPrefix + "Hosting:"; - private readonly IConfiguration _configuration; - - public HostingSettings(IConfiguration configuration) - { - _configuration = configuration; - } - - /// - public LocalTempStorage LocalTempStorageLocation => - _configuration.GetValue(Prefix+"LocalTempStorage", LocalTempStorage.Default); + /// + /// Gets the configuration for the location of temporary files. + /// + [JsonPropertyName("LocalTempStorage")] + public LocalTempStorage LocalTempStorageLocation { get; set; } = LocalTempStorage.Default; public string ApplicationVirtualPath => null; @@ -24,6 +19,7 @@ namespace Umbraco.Configuration.Models /// Gets a value indicating whether umbraco is running in [debug mode]. ///
/// true if [debug mode]; otherwise, false. - public bool DebugMode => _configuration.GetValue(Prefix+"Debug", false); + [JsonPropertyName("Debug")] + public bool DebugMode { get; set; } = false; } } diff --git a/src/Umbraco.Configuration/Models/ImagingCacheSettings.cs b/src/Umbraco.Configuration/Models/ImagingCacheSettings.cs new file mode 100644 index 0000000000..05e3cb4677 --- /dev/null +++ b/src/Umbraco.Configuration/Models/ImagingCacheSettings.cs @@ -0,0 +1,16 @@ +using System.Text.Json.Serialization; + +namespace Umbraco.Configuration.Models +{ + public class ImagingCacheSettings + { + public int MaxBrowserCacheDays { get; set; } = 7; + + public int MaxCacheDays { get; set; } = 365; + + public uint CachedNameLength { get; set; } = 7; + + [JsonPropertyName("Folder")] + public string CacheFolder { get; set; } = "../App_Data/Cache"; + } +} diff --git a/src/Umbraco.Configuration/Models/ImagingResizeSettings.cs b/src/Umbraco.Configuration/Models/ImagingResizeSettings.cs new file mode 100644 index 0000000000..1d7424c4f2 --- /dev/null +++ b/src/Umbraco.Configuration/Models/ImagingResizeSettings.cs @@ -0,0 +1,13 @@ +using System.Text.Json.Serialization; + +namespace Umbraco.Configuration.Models +{ + public class ImagingResizeSettings + { + [JsonPropertyName("MaxWidth")] + public int MaxResizeWidth { get; set; } = 5000; + + [JsonPropertyName("MaxHeight")] + public int MaxResizeHeight { get; set; } = 5000; + } +} diff --git a/src/Umbraco.Configuration/Models/ImagingSettings.cs b/src/Umbraco.Configuration/Models/ImagingSettings.cs index 4a9501b2ba..36a63d7766 100644 --- a/src/Umbraco.Configuration/Models/ImagingSettings.cs +++ b/src/Umbraco.Configuration/Models/ImagingSettings.cs @@ -1,26 +1,9 @@ -using Microsoft.Extensions.Configuration; -using Umbraco.Core; -using Umbraco.Core.Configuration; - -namespace Umbraco.Configuration.Models +namespace Umbraco.Configuration.Models { - internal class ImagingSettings : IImagingSettings + public class ImagingSettings { - private const string Prefix = Constants.Configuration.ConfigPrefix + "Imaging:"; - private const string CachePrefix = Prefix + "Cache:"; - private const string ResizePrefix = Prefix + "Resize:"; - private readonly IConfiguration _configuration; + public ImagingCacheSettings Cache { get; set; } - public ImagingSettings(IConfiguration configuration) - { - _configuration = configuration; - } - - public int MaxBrowserCacheDays => _configuration.GetValue(CachePrefix + "MaxBrowserCacheDays", 7); - public int MaxCacheDays => _configuration.GetValue(CachePrefix + "MaxCacheDays", 365); - public uint CachedNameLength => _configuration.GetValue(CachePrefix + "CachedNameLength", (uint) 8); - public string CacheFolder => _configuration.GetValue(CachePrefix + "Folder", "../App_Data/Cache"); - public int MaxResizeWidth => _configuration.GetValue(ResizePrefix + "MaxWidth", 5000); - public int MaxResizeHeight => _configuration.GetValue(ResizePrefix + "MaxHeight", 5000); + public ImagingResizeSettings Resize { get; set; } } } diff --git a/src/Umbraco.Configuration/Models/IndexCreatorSettings.cs b/src/Umbraco.Configuration/Models/IndexCreatorSettings.cs index b4bb000552..7738527ed7 100644 --- a/src/Umbraco.Configuration/Models/IndexCreatorSettings.cs +++ b/src/Umbraco.Configuration/Models/IndexCreatorSettings.cs @@ -1,20 +1,7 @@ -using Microsoft.Extensions.Configuration; -using Umbraco.Core; -using Umbraco.Core.Configuration; - -namespace Umbraco.Configuration.Models +namespace Umbraco.Configuration.Models { - internal class IndexCreatorSettings : IIndexCreatorSettings + public class IndexCreatorSettings { - private const string Prefix = Constants.Configuration.ConfigPrefix + "Examine:"; - private readonly IConfiguration _configuration; - - public IndexCreatorSettings(IConfiguration configuration) - { - _configuration = configuration; - } - - public string LuceneDirectoryFactory => - _configuration.GetValue(Prefix + "LuceneDirectoryFactory"); + public string LuceneDirectoryFactory { get; set; } } } diff --git a/src/Umbraco.Configuration/Models/KeepAliveSettings.cs b/src/Umbraco.Configuration/Models/KeepAliveSettings.cs index 04194e1a3c..c6f0b9a98c 100644 --- a/src/Umbraco.Configuration/Models/KeepAliveSettings.cs +++ b/src/Umbraco.Configuration/Models/KeepAliveSettings.cs @@ -1,23 +1,11 @@ -using Microsoft.Extensions.Configuration; -using Umbraco.Core; -using Umbraco.Core.Configuration.UmbracoSettings; +using Umbraco.Core.Configuration.UmbracoSettings; namespace Umbraco.Configuration.Models { - internal class KeepAliveSettings : IKeepAliveSettings + public class KeepAliveSettings : IKeepAliveSettings { - private const string Prefix = Constants.Configuration.ConfigPrefix + "KeepAlive:"; - private readonly IConfiguration _configuration; + public bool DisableKeepAliveTask { get; set; } = false; - public KeepAliveSettings(IConfiguration configuration) - { - _configuration = configuration; - } - - public bool DisableKeepAliveTask => - _configuration.GetValue(Prefix + "DisableKeepAliveTask", false); - - public string KeepAlivePingUrl => _configuration.GetValue(Prefix + "KeepAlivePingUrl", - "{umbracoApplicationUrl}/api/keepalive/ping"); + public string KeepAlivePingUrl { get; set; } = "{umbracoApplicationUrl}/api/keepalive/ping"; } } diff --git a/src/Umbraco.Configuration/Models/LoggingSettings.cs b/src/Umbraco.Configuration/Models/LoggingSettings.cs index b05fe03875..9cc0a084d2 100644 --- a/src/Umbraco.Configuration/Models/LoggingSettings.cs +++ b/src/Umbraco.Configuration/Models/LoggingSettings.cs @@ -1,19 +1,7 @@ -using Microsoft.Extensions.Configuration; -using Umbraco.Core; -using Umbraco.Core.Configuration.UmbracoSettings; - -namespace Umbraco.Configuration.Models +namespace Umbraco.Configuration.Models { - internal class LoggingSettings : ILoggingSettings + public class LoggingSettings { - private const string Prefix = Constants.Configuration.ConfigPrefix + "Logging:"; - private readonly IConfiguration _configuration; - - public LoggingSettings(IConfiguration configuration) - { - _configuration = configuration; - } - - public int MaxLogAge => _configuration.GetValue(Prefix + "MaxLogAge", -1); + public int MaxLogAge { get; set; } = -1; } } diff --git a/src/Umbraco.Configuration/Models/MemberPasswordConfigurationSettings.cs b/src/Umbraco.Configuration/Models/MemberPasswordConfigurationSettings.cs index 5a8313a351..32bed610fb 100644 --- a/src/Umbraco.Configuration/Models/MemberPasswordConfigurationSettings.cs +++ b/src/Umbraco.Configuration/Models/MemberPasswordConfigurationSettings.cs @@ -1,38 +1,21 @@ -using Microsoft.Extensions.Configuration; -using Umbraco.Core; -using Umbraco.Core.Configuration; +using Umbraco.Core; namespace Umbraco.Configuration.Models { - internal class MemberPasswordConfigurationSettings : IMemberPasswordConfiguration + public class MemberPasswordConfigurationSettings { - private const string Prefix = Constants.Configuration.ConfigSecurityPrefix + "MemberPassword:"; - private readonly IConfiguration _configuration; + public int RequiredLength { get; set; } = 10; - public MemberPasswordConfigurationSettings(IConfiguration configuration) - { - _configuration = configuration; - } + public bool RequireNonLetterOrDigit { get; set; } = false; - public int RequiredLength => - _configuration.GetValue(Prefix + "RequiredLength", 10); + public bool RequireDigit { get; set; } = false; - public bool RequireNonLetterOrDigit => - _configuration.GetValue(Prefix + "RequireNonLetterOrDigit", false); + public bool RequireLowercase { get; set; } = false; - public bool RequireDigit => - _configuration.GetValue(Prefix + "RequireDigit", false); + public bool RequireUppercase { get; set; } = false; - public bool RequireLowercase => - _configuration.GetValue(Prefix + "RequireLowercase", false); + public string HashAlgorithmType { get; set; } = Constants.Security.AspNetUmbraco8PasswordHashAlgorithmName; - public bool RequireUppercase => - _configuration.GetValue(Prefix + "RequireUppercase", false); - - public string HashAlgorithmType => - _configuration.GetValue(Prefix + "HashAlgorithmType", Constants.Security.AspNetUmbraco8PasswordHashAlgorithmName); // TODO: Need to change to current format when we do members - - public int MaxFailedAccessAttemptsBeforeLockout => - _configuration.GetValue(Prefix + "MaxFailedAccessAttemptsBeforeLockout", 5); + public int MaxFailedAccessAttemptsBeforeLockout { get; set; } = 5; } } diff --git a/src/Umbraco.Configuration/Models/ModelsBuilderConfig.cs b/src/Umbraco.Configuration/Models/ModelsBuilderConfig.cs index d111dbba70..d580ba1b7c 100644 --- a/src/Umbraco.Configuration/Models/ModelsBuilderConfig.cs +++ b/src/Umbraco.Configuration/Models/ModelsBuilderConfig.cs @@ -7,20 +7,9 @@ namespace Umbraco.Configuration.Models /// /// Represents the models builder configuration. /// - internal class ModelsBuilderConfig : IModelsBuilderConfig + public class ModelsBuilderConfig { - private const string Prefix = Constants.Configuration.ConfigModelsBuilderPrefix; - private readonly IConfiguration _configuration; - - /// - /// Initializes a new instance of the class. - /// - public ModelsBuilderConfig(IConfiguration configuration) - { - _configuration = configuration; - } - - public string DefaultModelsDirectory => "~/App_Data/Models"; + public static string DefaultModelsDirectory => "~/App_Data/Models"; /// /// Gets a value indicating whether the whole models experience is enabled. @@ -29,25 +18,26 @@ namespace Umbraco.Configuration.Models /// If this is false then absolutely nothing happens. /// Default value is false which means that unless we have this setting, nothing happens. /// - public bool Enable => _configuration.GetValue(Prefix+"Enable", false); + public bool Enable { get; set; } = false; /// /// Gets the models mode. /// - public ModelsMode ModelsMode => - _configuration.GetValue(Prefix+"ModelsMode", ModelsMode.Nothing); + public ModelsMode ModelsMode { get; set; } = ModelsMode.Nothing; /// /// Gets the models namespace. /// /// That value could be overriden by other (attribute in user's code...). Return default if no value was supplied. - public string ModelsNamespace => _configuration.GetValue(Prefix+"ModelsNamespace"); + public string ModelsNamespace { get; set; } /// /// Gets a value indicating whether we should enable the models factory. /// /// Default value is true because no factory is enabled by default in Umbraco. - public bool EnableFactory => _configuration.GetValue(Prefix+"EnableFactory", true); + public bool EnableFactory { get; set; } = true; + + private bool _flagOutOfDateModels; /// /// Gets a value indicating whether we should flag out-of-date models. @@ -57,15 +47,26 @@ namespace Umbraco.Configuration.Models /// setting is activated the ~/App_Data/Models/ood.txt file is then created. When models are /// generated through the dashboard, the files is cleared. Default value is false. /// - public bool FlagOutOfDateModels => - _configuration.GetValue(Prefix+"FlagOutOfDateModels", false) && !ModelsMode.IsLive(); + public bool FlagOutOfDateModels + { + get => _flagOutOfDateModels; + + set + { + if (!ModelsMode.IsLive()) + { + _flagOutOfDateModels = false; + } + + _flagOutOfDateModels = value; + } + } /// /// Gets the models directory. /// /// Default is ~/App_Data/Models but that can be changed. - public string ModelsDirectory => - _configuration.GetValue(Prefix+"ModelsDirectory", "~/App_Data/Models"); + public string ModelsDirectory { get; set; } = DefaultModelsDirectory; /// /// Gets a value indicating whether to accept an unsafe value for ModelsDirectory. @@ -74,13 +75,12 @@ namespace Umbraco.Configuration.Models /// An unsafe value is an absolute path, or a relative path pointing outside /// of the website root. /// - public bool AcceptUnsafeModelsDirectory => - _configuration.GetValue(Prefix+"AcceptUnsafeModelsDirectory", false); + public bool AcceptUnsafeModelsDirectory { get; set; } = false; /// /// Gets a value indicating the debug log level. /// /// 0 means minimal (safe on live site), anything else means more and more details (maybe not safe). - public int DebugLevel => _configuration.GetValue(Prefix+"DebugLevel", 0); + public int DebugLevel { get; set; } = 0; } } diff --git a/src/Umbraco.Configuration/Models/NuCacheSettings.cs b/src/Umbraco.Configuration/Models/NuCacheSettings.cs index 51b8b1fe08..0077146620 100644 --- a/src/Umbraco.Configuration/Models/NuCacheSettings.cs +++ b/src/Umbraco.Configuration/Models/NuCacheSettings.cs @@ -1,19 +1,7 @@ -using Microsoft.Extensions.Configuration; -using Umbraco.Core; -using Umbraco.Core.Configuration; - -namespace Umbraco.Configuration.Models +namespace Umbraco.Configuration.Models { - internal class NuCacheSettings : INuCacheSettings + public class NuCacheSettings { - private const string Prefix = Constants.Configuration.ConfigPrefix + "NuCache:"; - private readonly IConfiguration _configuration; - - public NuCacheSettings(IConfiguration configuration) - { - _configuration = configuration; - } - - public string BTreeBlockSize => _configuration.GetValue(Prefix+"BTreeBlockSize"); + public string BTreeBlockSize { get; set; } } } diff --git a/src/Umbraco.Configuration/Models/RuntimeSettings.cs b/src/Umbraco.Configuration/Models/RuntimeSettings.cs index ef129030b6..367a6c53a3 100644 --- a/src/Umbraco.Configuration/Models/RuntimeSettings.cs +++ b/src/Umbraco.Configuration/Models/RuntimeSettings.cs @@ -1,19 +1,9 @@ -using Microsoft.Extensions.Configuration; -using Umbraco.Core; -using Umbraco.Core.Configuration; - -namespace Umbraco.Configuration.Models +namespace Umbraco.Configuration.Models { - internal class RuntimeSettings : IRuntimeSettings + public class RuntimeSettings { - private const string Prefix = Constants.Configuration.ConfigPrefix + "Runtime:"; - private readonly IConfiguration _configuration; - public RuntimeSettings(IConfiguration configuration) - { - _configuration = configuration; - } + public int? MaxQueryStringLength { get; set; } - public int? MaxQueryStringLength => _configuration.GetValue(Prefix+"MaxRequestLength"); - public int? MaxRequestLength => _configuration.GetValue(Prefix+"MaxRequestLength"); + public int? MaxRequestLength { get; set; } } } diff --git a/src/Umbraco.Configuration/Models/SecuritySettings.cs b/src/Umbraco.Configuration/Models/SecuritySettings.cs index 297c95b1af..12ea6b7c17 100644 --- a/src/Umbraco.Configuration/Models/SecuritySettings.cs +++ b/src/Umbraco.Configuration/Models/SecuritySettings.cs @@ -1,33 +1,17 @@ -using Microsoft.Extensions.Configuration; -using Umbraco.Core; -using Umbraco.Core.Configuration.UmbracoSettings; - -namespace Umbraco.Configuration.Models +namespace Umbraco.Configuration.Models { - internal class SecuritySettings : ISecuritySettings + public class SecuritySettings { - private const string Prefix = Constants.Configuration.ConfigSecurityPrefix; - private readonly IConfiguration _configuration; + public bool KeepUserLoggedIn { get; set; } = false; - public SecuritySettings(IConfiguration configuration) - { - _configuration = configuration; - } + public bool HideDisabledUsersInBackoffice { get; set; } = false; - public bool KeepUserLoggedIn => _configuration.GetValue(Prefix + "KeepUserLoggedIn", false); + public bool AllowPasswordReset { get; set; } = true; - public bool HideDisabledUsersInBackoffice => - _configuration.GetValue(Prefix + "HideDisabledUsersInBackoffice", false); + public string AuthCookieName { get; set; } = "UMB_UCONTEXT"; - public bool AllowPasswordReset => - _configuration.GetValue(Prefix + "AllowPasswordResetAllowPasswordReset", true); + public string AuthCookieDomain { get; set; } - public string AuthCookieName => - _configuration.GetValue(Prefix + "AuthCookieName", "UMB_UCONTEXT"); - - public string AuthCookieDomain => - _configuration.GetValue(Prefix + "AuthCookieDomain"); - - public bool UsernameIsEmail => _configuration.GetValue(Prefix + "UsernameIsEmail", true); + public bool UsernameIsEmail { get; set; } = true; } } diff --git a/src/Umbraco.Configuration/Models/SmtpSettings.cs b/src/Umbraco.Configuration/Models/SmtpSettings.cs new file mode 100644 index 0000000000..c4a874c5ae --- /dev/null +++ b/src/Umbraco.Configuration/Models/SmtpSettings.cs @@ -0,0 +1,21 @@ +using System.Net.Mail; + +namespace Umbraco.Configuration.Models +{ + public class SmtpSettings + { + public string From { get; set; } + + public string Host { get; set; } + + public int Port { get; set; } + + public string PickupDirectoryLocation { get; set; } + + public SmtpDeliveryMethod DeliveryMethod { get; set; } + + public string Username { get; set; } + + public string Password { get; set; } + } +} diff --git a/src/Umbraco.Configuration/Models/TypeFinderSettings.cs b/src/Umbraco.Configuration/Models/TypeFinderSettings.cs index 8a1f7ac9e0..65690f9668 100644 --- a/src/Umbraco.Configuration/Models/TypeFinderSettings.cs +++ b/src/Umbraco.Configuration/Models/TypeFinderSettings.cs @@ -1,20 +1,7 @@ -using Microsoft.Extensions.Configuration; -using Umbraco.Core; -using Umbraco.Core.Configuration; - -namespace Umbraco.Configuration.Models +namespace Umbraco.Configuration.Models { - internal class TypeFinderSettings : ITypeFinderSettings + public class TypeFinderSettings { - private const string Prefix = Constants.Configuration.ConfigPrefix + "TypeFinder:"; - private readonly IConfiguration _configuration; - - public TypeFinderSettings(IConfiguration configuration) - { - _configuration = configuration; - } - - public string AssembliesAcceptingLoadExceptions => - _configuration.GetValue(Prefix+"AssembliesAcceptingLoadExceptions"); + public string AssembliesAcceptingLoadExceptions { get; set; } } } diff --git a/src/Umbraco.Configuration/Models/UserPasswordConfigurationSettings.cs b/src/Umbraco.Configuration/Models/UserPasswordConfigurationSettings.cs index 25ce3e3d9a..81724f9259 100644 --- a/src/Umbraco.Configuration/Models/UserPasswordConfigurationSettings.cs +++ b/src/Umbraco.Configuration/Models/UserPasswordConfigurationSettings.cs @@ -1,36 +1,22 @@ -using Microsoft.Extensions.Configuration; -using Umbraco.Core; +using Umbraco.Core; using Umbraco.Core.Configuration; namespace Umbraco.Configuration.Models { - internal class UserPasswordConfigurationSettings : IUserPasswordConfiguration + public class UserPasswordConfigurationSettings { - private const string Prefix = Constants.Configuration.ConfigSecurityPrefix + "UserPassword:"; - private readonly IConfiguration _configuration; + public int RequiredLength { get; set; } = 10; - public UserPasswordConfigurationSettings(IConfiguration configuration) - { - _configuration = configuration; - } + public bool RequireNonLetterOrDigit { get; set; } = false; - public int RequiredLength => _configuration.GetValue(Prefix + "RequiredLength", 10); + public bool RequireDigit { get; set; } = false; - public bool RequireNonLetterOrDigit => - _configuration.GetValue(Prefix + "RequireNonLetterOrDigit", false); + public bool RequireLowercase { get; set; } = false; - public bool RequireDigit => _configuration.GetValue(Prefix + "RequireDigit", false); + public bool RequireUppercase { get; set; } = false; - public bool RequireLowercase => - _configuration.GetValue(Prefix + "RequireLowercase", false); + public string HashAlgorithmType { get; set; } = Constants.Security.AspNetCoreV3PasswordHashAlgorithmName; - public bool RequireUppercase => - _configuration.GetValue(Prefix + "RequireUppercase", false); - - public string HashAlgorithmType => - _configuration.GetValue(Prefix + "HashAlgorithmType", Constants.Security.AspNetCoreV3PasswordHashAlgorithmName); - - public int MaxFailedAccessAttemptsBeforeLockout => - _configuration.GetValue(Prefix + "MaxFailedAccessAttemptsBeforeLockout", 5); + public int MaxFailedAccessAttemptsBeforeLockout { get; set; } = 5; } } diff --git a/src/Umbraco.Configuration/Models/WebRoutingSettings.cs b/src/Umbraco.Configuration/Models/WebRoutingSettings.cs index 9ac856ca9f..d0e36b4241 100644 --- a/src/Umbraco.Configuration/Models/WebRoutingSettings.cs +++ b/src/Umbraco.Configuration/Models/WebRoutingSettings.cs @@ -1,42 +1,23 @@ -using Microsoft.Extensions.Configuration; -using Umbraco.Core; -using Umbraco.Core.Configuration.UmbracoSettings; -using Umbraco.Core.Models.PublishedContent; +using Umbraco.Core.Models.PublishedContent; namespace Umbraco.Configuration.Models { - internal class WebRoutingSettings : IWebRoutingSettings + public class WebRoutingSettings { - private const string Prefix = Constants.Configuration.ConfigPrefix + "WebRouting:"; - private readonly IConfiguration _configuration; + public bool TrySkipIisCustomErrors { get; set; } = false; - public WebRoutingSettings(IConfiguration configuration) - { - _configuration = configuration; - } + public bool InternalRedirectPreservesTemplate { get; set; } = false; - public bool TrySkipIisCustomErrors => - _configuration.GetValue(Prefix + "TrySkipIisCustomErrors", false); + public bool DisableAlternativeTemplates { get; set; } = false; - public bool InternalRedirectPreservesTemplate => - _configuration.GetValue(Prefix + "InternalRedirectPreservesTemplate", false); + public bool ValidateAlternativeTemplates { get; set; } = false; - public bool DisableAlternativeTemplates => - _configuration.GetValue(Prefix + "DisableAlternativeTemplates", false); + public bool DisableFindContentByIdPath { get; set; } = false; - public bool ValidateAlternativeTemplates => - _configuration.GetValue(Prefix + "ValidateAlternativeTemplates", false); + public bool DisableRedirectUrlTracking { get; set; } = false; - public bool DisableFindContentByIdPath => - _configuration.GetValue(Prefix + "DisableFindContentByIdPath", false); + public string UrlProviderMode { get; set; } = UrlMode.Auto.ToString(); - public bool DisableRedirectUrlTracking => - _configuration.GetValue(Prefix + "DisableRedirectUrlTracking", false); - - public string UrlProviderMode => - _configuration.GetValue(Prefix + "UrlProviderMode", UrlMode.Auto.ToString()); - - public string UmbracoApplicationUrl => - _configuration.GetValue(Prefix + "UmbracoApplicationUrl"); + public string UmbracoApplicationUrl { get; set; } } } diff --git a/src/Umbraco.Web.Common/Extensions/UmbracoCoreServiceCollectionExtensions.cs b/src/Umbraco.Web.Common/Extensions/UmbracoCoreServiceCollectionExtensions.cs index 94e9062902..cbc374f93b 100644 --- a/src/Umbraco.Web.Common/Extensions/UmbracoCoreServiceCollectionExtensions.cs +++ b/src/Umbraco.Web.Common/Extensions/UmbracoCoreServiceCollectionExtensions.cs @@ -1,12 +1,9 @@ using System; using System.Data.Common; using System.Data.SqlClient; -using System.Globalization; using System.IO; -using System.Linq; using System.Reflection; using System.Runtime.InteropServices; -using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Configuration; @@ -28,13 +25,11 @@ using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.Runtime; using Umbraco.Web.Common.AspNetCore; -using Umbraco.Web.Common.Extensions; using Umbraco.Web.Common.Profiler; +using CoreDebugSettings = Umbraco.Configuration.Models.CoreDebugSettings; namespace Umbraco.Extensions { - - public static class UmbracoCoreServiceCollectionExtensions { /// @@ -107,6 +102,24 @@ namespace Umbraco.Extensions if (configuration == null) throw new ArgumentNullException(nameof(configuration)); services.Configure(configuration.GetSection(Constants.Configuration.ConfigPrefix + "Tours")); + services.Configure(configuration.GetSection(Constants.Configuration.ConfigPrefix + "Core:Debug")); + services.Configure(configuration.GetSection(Constants.Configuration.ConfigSecurityPrefix)); + services.Configure(configuration.GetSection(Constants.Configuration.ConfigSecurityPrefix + "UserPassword:")); + services.Configure(configuration.GetSection(Constants.Configuration.ConfigSecurityPrefix + "MemberPassword:")); + services.Configure(configuration.GetSection(Constants.Configuration.ConfigPrefix + "KeepAlive:")); + services.Configure(configuration.GetSection(Constants.Configuration.ConfigPrefix + "Content:")); + services.Configure(configuration.GetSection(Constants.Configuration.ConfigPrefix + "Logging:")); + services.Configure(configuration.GetSection(Constants.Configuration.ConfigPrefix + "ExceptionFilter:")); + services.Configure(configuration.GetSection(Constants.Configuration.ConfigPrefix + "ActiveDirectory:")); + services.Configure(configuration.GetSection(Constants.Configuration.ConfigPrefix + "Runtime:")); + services.Configure(configuration.GetSection(Constants.Configuration.ConfigPrefix + "TypeFinder:")); + services.Configure(configuration.GetSection(Constants.Configuration.ConfigPrefix + "NuCache:")); + services.Configure(configuration.GetSection(Constants.Configuration.ConfigPrefix + "WebRouting:")); + services.Configure(configuration.GetSection(Constants.Configuration.ConfigPrefix + "Examine:")); + services.Configure(configuration.GetSection(Constants.Configuration.ConfigModelsBuilderPrefix)); + services.Configure(configuration.GetSection(Constants.Configuration.ConfigPrefix + "Hosting:")); + services.Configure(configuration.GetSection(Constants.Configuration.ConfigGlobalPrefix)); + services.Configure(configuration.GetSection(Constants.Configuration.ConfigPrefix + "Imaging:")); var configsFactory = new AspNetCoreConfigsFactory(configuration); var configs = configsFactory.Create(); From 67c25ad39ba5a3cde45e866df706012b11a61ad8 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Thu, 20 Aug 2020 09:42:42 +0200 Subject: [PATCH 222/826] Fixes for ace editor in cypress tests --- .../integration/Settings/partialsViewMacroFiles.ts | 8 ++++---- .../cypress/integration/Settings/partialsViews.ts | 6 +++--- .../cypress/integration/Settings/templates.ts | 10 ++++++---- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/partialsViewMacroFiles.ts b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/partialsViewMacroFiles.ts index bf1c25c16d..563ff77658 100644 --- a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/partialsViewMacroFiles.ts +++ b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/partialsViewMacroFiles.ts @@ -104,9 +104,9 @@ context('Partial View Macro Files', () => { .withName(name) .withContent("@inherits Umbraco.Web.Macros.PartialViewMacroPage") .build(); - + cy.savePartialViewMacro(partialViewMacro); - + // Navigate to settings cy.umbracoSection('settings'); cy.get('li .umb-tree-root:contains("Settings")').should("be.visible"); @@ -133,7 +133,7 @@ context('Partial View Macro Files', () => { .withName(name) .withContent("@inherits Umbraco.Web.Macros.PartialViewMacroPage") .build(); - + cy.savePartialViewMacro(partialViewMacro); // Navigate to settings @@ -142,7 +142,7 @@ context('Partial View Macro Files', () => { cy.umbracoTreeItem("settings", ["Partial View Macro Files", fullName]).click(); // Type an edit - cy.get('.ace_content').type(" // test"); + cy.get('.ace_text-input').type(" // test", {force:true} ); // Save cy.get('.btn-success').click(); diff --git a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/partialsViews.ts b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/partialsViews.ts index 5fa4e15108..068338f8fa 100644 --- a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/partialsViews.ts +++ b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/partialsViews.ts @@ -107,11 +107,11 @@ context('Partial Views', () => { cy.umbracoContextMenuAction("action-delete").click(); cy.umbracoButtonByLabelKey("general_ok").click(); - // Assert + // Assert cy.contains(fileName).should('not.exist'); cy.umbracoPartialViewExists(fileName).then(exists => { expect(exists).to.be.false; }); - // Clean + // Clean cy.umbracoEnsurePartialViewNameNotExists(fileName); }); @@ -132,7 +132,7 @@ context('Partial Views', () => { // Open partial view cy.umbracoTreeItem("settings", ["Partial Views", fileName]).click(); // Edit - cy.get('.ace_content').type("var num = 5;"); + cy.get('.ace_text-input').type("var num = 5;", {force:true} ); cy.get('.btn-success').click(); // Assert diff --git a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/templates.ts b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/templates.ts index 194419ee88..aff1c38093 100644 --- a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/templates.ts +++ b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/templates.ts @@ -30,7 +30,7 @@ context('Templates', () => { /* Make an edit, if you don't the file will be create twice, only happens in testing though, probably because the test is too fast Certifiably mega wonk regardless */ - cy.get('.ace_content').type("var num = 5;"); + cy.get('.ace_text-input').type("var num = 5;", {force:true} ); //Save cy.get('.btn-success').click(); @@ -59,10 +59,11 @@ context('Templates', () => { // Open partial view cy.umbracoTreeItem("settings", ["Templates", name]).click(); // Edit - cy.get('.ace_content').type(edit); + cy.get('.ace_text-input').type(edit, {force:true} ); + // Navigate away cy.umbracoSection('content'); - // Click stay button + // Click stay button cy.get('umb-button[label="Stay"] button:enabled').click(); // Assert @@ -91,7 +92,8 @@ context('Templates', () => { // Open partial view cy.umbracoTreeItem("settings", ["Templates", name]).click(); // Edit - cy.get('.ace_content').type(edit); + cy.get('.ace_text-input').type(edit, {force:true} ); + // Navigate away cy.umbracoSection('content'); // Click discard From 4c0d05e4ea489f72709d6c81ee24a669ddb69606 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 20 Aug 2020 09:44:52 +0200 Subject: [PATCH 223/826] close tag --- .../src/views/propertyeditors/blocklist/blocklist.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/blocklist.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/blocklist.html index 8c3bced573..7a49783203 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/blocklist.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/blocklist.html @@ -1 +1 @@ - + From 268eca922f6bffd8b36cc8fe27bffd70bd322f30 Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Thu, 20 Aug 2020 09:08:05 +0100 Subject: [PATCH 224/826] Bump version to 8.7.0-rc .\build SetUmbracoVersion 8.7.0-rc --- src/SolutionInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SolutionInfo.cs b/src/SolutionInfo.cs index 5587979a6c..365c90423a 100644 --- a/src/SolutionInfo.cs +++ b/src/SolutionInfo.cs @@ -19,4 +19,4 @@ using System.Resources; // these are FYI and changed automatically [assembly: AssemblyFileVersion("8.7.0")] -[assembly: AssemblyInformationalVersion("8.7.0")] +[assembly: AssemblyInformationalVersion("8.7.0-rc")] From 8db0967d47e49330b94ce44e682db2c0afa574de Mon Sep 17 00:00:00 2001 From: Sebastiaan Janssen Date: Thu, 20 Aug 2020 10:19:14 +0200 Subject: [PATCH 225/826] Fix merge error --- src/Umbraco.Web.UI/Umbraco.Web.UI.csproj | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj index ea34857715..8b194f4481 100644 --- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj +++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj @@ -349,7 +349,6 @@ 8800 / http://localhost:8800 - http://localhost:8700 False False From 19037d0a89c219fb44eb2d3623c48fd92df5b012 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 20 Aug 2020 10:27:14 +0200 Subject: [PATCH 226/826] append date to the clipboard entry, and use it for sorting entries in the UI. --- .../src/common/services/clipboard.service.js | 95 +++++++++---------- .../umbBlockListPropertyEditor.component.js | 6 ++ .../nestedcontent/nestedcontent.controller.js | 10 +- 3 files changed, 61 insertions(+), 50 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/services/clipboard.service.js b/src/Umbraco.Web.UI.Client/src/common/services/clipboard.service.js index cb583546a5..0d2ca6623b 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/clipboard.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/clipboard.service.js @@ -11,13 +11,13 @@ * */ function clipboardService(notificationsService, eventsService, localStorageService, iconHelper) { - + var clearPropertyResolvers = []; - + var STORAGE_KEY = "umbClipboardService"; - + var retriveStorage = function() { if (localStorageService.isSupported === false) { return null; @@ -27,32 +27,32 @@ function clipboardService(notificationsService, eventsService, localStorageServi if (dataString != null) { dataJSON = JSON.parse(dataString); } - + if(dataJSON == null) { dataJSON = new Object(); } - + if(dataJSON.entries === undefined) { dataJSON.entries = []; } - + return dataJSON; } - + var saveStorage = function(storage) { var storageString = JSON.stringify(storage); - + try { var storageJSON = JSON.parse(storageString); localStorageService.set(STORAGE_KEY, storageString); - + eventsService.emit("clipboardService.storageUpdate"); - + return true; } catch(e) { return false; } - + return false; } @@ -86,17 +86,17 @@ function clipboardService(notificationsService, eventsService, localStorageServi var isEntryCompatible = function(entry, type, allowedAliases) { return entry.type === type - && + && ( (entry.alias && allowedAliases.filter(allowedAlias => allowedAlias === entry.alias).length > 0) - || + || (entry.aliases && entry.aliases.filter(entryAlias => allowedAliases.filter(allowedAlias => allowedAlias === entryAlias).length > 0).length === entry.aliases.length) ); } - - + + var service = {}; - + /** * @ngdoc method @@ -160,29 +160,29 @@ function clipboardService(notificationsService, eventsService, localStorageServi * Saves a single JS-object with a type and alias to the clipboard. */ service.copy = function(type, alias, data, displayLabel, displayIcon, uniqueKey, firstLevelClearupMethod) { - + var storage = retriveStorage(); displayLabel = displayLabel || data.name; displayIcon = displayIcon || iconHelper.convertFromLegacyIcon(data.icon); uniqueKey = uniqueKey || data.key || console.error("missing unique key for this content"); - + // remove previous copies of this entry: storage.entries = storage.entries.filter( (entry) => { return entry.unique !== uniqueKey; } ); - - var entry = {unique:uniqueKey, type:type, alias:alias, data:prepareEntryForStorage(data, firstLevelClearupMethod), label:displayLabel, icon:displayIcon}; + + var entry = {unique:uniqueKey, type:type, alias:alias, data:prepareEntryForStorage(data, firstLevelClearupMethod), label:displayLabel, icon:displayIcon, date:Date.now()}; storage.entries.push(entry); - + if (saveStorage(storage) === true) { notificationsService.success("Clipboard", "Copied to clipboard."); } else { notificationsService.error("Clipboard", "Couldnt copy this data to clipboard."); } - + }; @@ -203,32 +203,31 @@ function clipboardService(notificationsService, eventsService, localStorageServi * Saves a single JS-object with a type and alias to the clipboard. */ service.copyArray = function(type, aliases, datas, displayLabel, displayIcon, uniqueKey, firstLevelClearupMethod) { - + var storage = retriveStorage(); - + // Clean up each entry var copiedDatas = datas.map(data => prepareEntryForStorage(data, firstLevelClearupMethod)); - + // remove previous copies of this entry: storage.entries = storage.entries.filter( (entry) => { return entry.unique !== uniqueKey; } ); - - var entry = {unique:uniqueKey, type:type, aliases:aliases, data:copiedDatas, label:displayLabel, icon:displayIcon}; + var entry = {unique:uniqueKey, type:type, aliases:aliases, data:copiedDatas, label:displayLabel, icon:displayIcon, date:Date.now()}; storage.entries.push(entry); - + if (saveStorage(storage) === true) { notificationsService.success("Clipboard", "Copied to clipboard."); } else { notificationsService.error("Clipboard", "Couldnt copy this data to clipboard."); } - + }; - - + + /** * @ngdoc method * @name umbraco.services.supportsCopy#supported @@ -240,7 +239,7 @@ function clipboardService(notificationsService, eventsService, localStorageServi service.isSupported = function() { return localStorageService.isSupported; }; - + /** * @ngdoc method * @name umbraco.services.supportsCopy#hasEntriesOfType @@ -253,14 +252,14 @@ function clipboardService(notificationsService, eventsService, localStorageServi * Determines whether the current clipboard has entries that match a given type and one of the aliases. */ service.hasEntriesOfType = function(type, aliases) { - + if(service.retriveEntriesOfType(type, aliases).length > 0) { return true; } - + return false; }; - + /** * @ngdoc method * @name umbraco.services.supportsCopy#retriveEntriesOfType @@ -268,24 +267,24 @@ function clipboardService(notificationsService, eventsService, localStorageServi * * @param {string} type A string defining the type of data to recive. * @param {string} aliases A array of strings providing the alias of the data you want to recive. - * + * * @description * Returns an array of entries matching the given type and one of the provided aliases. */ service.retriveEntriesOfType = function(type, allowedAliases) { - + var storage = retriveStorage(); - + // Find entries that are fulfilling the criteria for this nodeType and nodeTypesAliases. var filteretEntries = storage.entries.filter( (entry) => { return isEntryCompatible(entry, type, allowedAliases); } ); - + return filteretEntries; }; - + /** * @ngdoc method * @name umbraco.services.supportsCopy#retriveEntriesOfType @@ -293,14 +292,14 @@ function clipboardService(notificationsService, eventsService, localStorageServi * * @param {string} type A string defining the type of data to recive. * @param {string} aliases A array of strings providing the alias of the data you want to recive. - * + * * @description * Returns an array of data of entries matching the given type and one of the provided aliases. */ service.retriveDataOfType = function(type, aliases) { return service.retriveEntriesOfType(type, aliases).map((x) => x.data); }; - + /** * @ngdoc method * @name umbraco.services.supportsCopy#retriveEntriesOfType @@ -308,12 +307,12 @@ function clipboardService(notificationsService, eventsService, localStorageServi * * @param {string} type A string defining the type of data to remove. * @param {string} aliases A array of strings providing the alias of the data you want to remove. - * + * * @description * Removes entries matching the given type and one of the provided aliases. */ service.clearEntriesOfType = function(type, allowedAliases) { - + var storage = retriveStorage(); // Find entries that are NOT fulfilling the criteria for this nodeType and nodeTypesAliases. @@ -322,14 +321,14 @@ function clipboardService(notificationsService, eventsService, localStorageServi return !isEntryCompatible(entry, type, allowedAliases); } ); - + storage.entries = filteretEntries; saveStorage(storage); }; - - - + + + return service; } diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umbBlockListPropertyEditor.component.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umbBlockListPropertyEditor.component.js index 489c1353ff..d3099154c7 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umbBlockListPropertyEditor.component.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/umbBlockListPropertyEditor.component.js @@ -456,6 +456,7 @@ blockPickerModel.clipboardItems.push( { type: "elementType", + date: entry.date, pasteData: entry.data, blockConfigModel: modelObject.getScaffoldFromAlias(entry.alias), elementTypeModel: { @@ -471,6 +472,7 @@ blockPickerModel.clipboardItems.push( { type: "elementTypeArray", + date: entry.date, pasteData: entry.data, blockConfigModel: {}, // no block configuration for paste items of elementTypeArray. elementTypeModel: { @@ -481,6 +483,10 @@ ); }); + blockPickerModel.clipboardItems.sort( (a, b) => { + return b.date - a.date + }); + // open block picker overlay editorService.open(blockPickerModel); diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.controller.js index fe9725a7d8..ee406caa8a 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.controller.js @@ -27,7 +27,7 @@ } } } - + clipboardService.registrerClearPropertyResolver(clearNestedContentPropertiesForStorage) @@ -49,7 +49,7 @@ } } } - + clipboardService.registrerClearPropertyResolver(clearInnerNestedContentPropertiesForStorage) }]); @@ -245,6 +245,7 @@ _.each(singleEntriesForPaste, function (entry) { vm.overlayMenu.pasteItems.push({ type: "elementType", + date: entry.date, name: entry.label, data: entry.data, icon: entry.icon @@ -255,12 +256,17 @@ _.each(arrayEntriesForPaste, function (entry) { vm.overlayMenu.pasteItems.push({ type: "elementTypeArray", + date: entry.date, name: entry.label, data: entry.data, icon: entry.icon }); }); + vm.overlayMenu.pasteItems.sort( (a, b) => { + return b.date - a.date + }); + vm.overlayMenu.title = labels.grid_addElement; vm.overlayMenu.hideHeader = vm.overlayMenu.pasteItems.length > 0; From 1c3090b07855b53b8ac45d677d7dc115ae762e83 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Thu, 20 Aug 2020 11:51:51 +0200 Subject: [PATCH 227/826] Remove files that should not have been added to git --- .../Smidge/Cache/BERG-DESKTOP/1/02f293c4.js | 1 - .../Smidge/Cache/BERG-DESKTOP/1/079d4891.js | 1 - .../Smidge/Cache/BERG-DESKTOP/1/08d18f13.js | 51 - .../Smidge/Cache/BERG-DESKTOP/1/3236157c.js | 1 - .../Smidge/Cache/BERG-DESKTOP/1/32a48b01.js | 3 - .../Smidge/Cache/BERG-DESKTOP/1/33d92ffb.js | 9 - .../Smidge/Cache/BERG-DESKTOP/1/40b550d3.js | 19 - .../Smidge/Cache/BERG-DESKTOP/1/447a38f2.js | 1 - .../Smidge/Cache/BERG-DESKTOP/1/45e461b4.css | 4 - .../Smidge/Cache/BERG-DESKTOP/1/46c812c6.js | 3 - .../Smidge/Cache/BERG-DESKTOP/1/4c3e68fb.css | 1 - .../Smidge/Cache/BERG-DESKTOP/1/5058ea9f.js | 1009 --------- .../Smidge/Cache/BERG-DESKTOP/1/512fe428.js | 255 --- .../Smidge/Cache/BERG-DESKTOP/1/527d537f.js | 51 - .../Smidge/Cache/BERG-DESKTOP/1/5ad527d4.js | 1 - .../Smidge/Cache/BERG-DESKTOP/1/5bf60ea6.js | 1 - .../Smidge/Cache/BERG-DESKTOP/1/5d12437f.js | 1 - .../Smidge/Cache/BERG-DESKTOP/1/5f4a2348.js | 41 - .../Smidge/Cache/BERG-DESKTOP/1/611d5a60.js | 1 - .../Smidge/Cache/BERG-DESKTOP/1/63dc80f8.js | 1303 ------------ .../Smidge/Cache/BERG-DESKTOP/1/6d7fdc6f.js | 949 --------- .../Smidge/Cache/BERG-DESKTOP/1/717925a2.js | 40 - .../Smidge/Cache/BERG-DESKTOP/1/80d3896f.js | 2 - .../Smidge/Cache/BERG-DESKTOP/1/8cc5072d.js | 1 - .../Smidge/Cache/BERG-DESKTOP/1/a139e144.js | 8 - .../Smidge/Cache/BERG-DESKTOP/1/a176e6b8.js | 14 - .../Smidge/Cache/BERG-DESKTOP/1/a715f34d.css | 1 - .../Smidge/Cache/BERG-DESKTOP/1/aa3c40bc.js | 189 -- .../Smidge/Cache/BERG-DESKTOP/1/be0d5a08.js | 2 - .../Smidge/Cache/BERG-DESKTOP/1/bee60e6f.js | 234 --- .../Smidge/Cache/BERG-DESKTOP/1/bfa798db.js | 1867 ----------------- .../Smidge/Cache/BERG-DESKTOP/1/c3fc92ad.js | 14 - .../Smidge/Cache/BERG-DESKTOP/1/c53cdd84.js | 33 - .../Smidge/Cache/BERG-DESKTOP/1/c980e938.js | 17 - .../Smidge/Cache/BERG-DESKTOP/1/cb35914a.js | 1 - .../Smidge/Cache/BERG-DESKTOP/1/cd2e37b0.js | 1 - .../Smidge/Cache/BERG-DESKTOP/1/cd415aa0.js | 22 - .../Smidge/Cache/BERG-DESKTOP/1/d1aa3809.js | 1 - .../Smidge/Cache/BERG-DESKTOP/1/da0e5fc7.js | 10 - .../Smidge/Cache/BERG-DESKTOP/1/daf64d0d.js | 11 - .../Smidge/Cache/BERG-DESKTOP/1/ddf7f64a.js | 8 - .../Smidge/Cache/BERG-DESKTOP/1/de682689.js | 7 - .../Smidge/Cache/BERG-DESKTOP/1/e12dee6b.js | 11 - .../Smidge/Cache/BERG-DESKTOP/1/e1519986.js | 13 - .../Smidge/Cache/BERG-DESKTOP/1/e3fbab10.js | 1 - .../Smidge/Cache/BERG-DESKTOP/1/f142a940.js | 5 - .../Smidge/Cache/BERG-DESKTOP/1/f48f9c37.js | 3 - .../Smidge/Cache/BERG-DESKTOP/1/faa84de5.js | 1 - .../Smidge/Cache/BERG-DESKTOP/1/fb8e5b2a.js | 13 - .../Smidge/Cache/BERG-DESKTOP/1/fc8a39cc.js | 1 - .../1/gzip/umbraco-backoffice-init-css.s | Bin 76916 -> 0 bytes .../1/gzip/umbraco-backoffice-js.s | Bin 613198 -> 0 bytes .../BERG-DESKTOP/1/gzip/umbraco-tinymce-js.s | Bin 189077 -> 0 bytes .../App_Data/Umbraco.sdf | Bin 1114112 -> 0 bytes 54 files changed, 6237 deletions(-) delete mode 100644 src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/02f293c4.js delete mode 100644 src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/079d4891.js delete mode 100644 src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/08d18f13.js delete mode 100644 src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/3236157c.js delete mode 100644 src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/32a48b01.js delete mode 100644 src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/33d92ffb.js delete mode 100644 src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/40b550d3.js delete mode 100644 src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/447a38f2.js delete mode 100644 src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/45e461b4.css delete mode 100644 src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/46c812c6.js delete mode 100644 src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/4c3e68fb.css delete mode 100644 src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/5058ea9f.js delete mode 100644 src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/512fe428.js delete mode 100644 src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/527d537f.js delete mode 100644 src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/5ad527d4.js delete mode 100644 src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/5bf60ea6.js delete mode 100644 src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/5d12437f.js delete mode 100644 src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/5f4a2348.js delete mode 100644 src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/611d5a60.js delete mode 100644 src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/63dc80f8.js delete mode 100644 src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/6d7fdc6f.js delete mode 100644 src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/717925a2.js delete mode 100644 src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/80d3896f.js delete mode 100644 src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/8cc5072d.js delete mode 100644 src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/a139e144.js delete mode 100644 src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/a176e6b8.js delete mode 100644 src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/a715f34d.css delete mode 100644 src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/aa3c40bc.js delete mode 100644 src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/be0d5a08.js delete mode 100644 src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/bee60e6f.js delete mode 100644 src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/bfa798db.js delete mode 100644 src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/c3fc92ad.js delete mode 100644 src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/c53cdd84.js delete mode 100644 src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/c980e938.js delete mode 100644 src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/cb35914a.js delete mode 100644 src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/cd2e37b0.js delete mode 100644 src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/cd415aa0.js delete mode 100644 src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/d1aa3809.js delete mode 100644 src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/da0e5fc7.js delete mode 100644 src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/daf64d0d.js delete mode 100644 src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/ddf7f64a.js delete mode 100644 src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/de682689.js delete mode 100644 src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/e12dee6b.js delete mode 100644 src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/e1519986.js delete mode 100644 src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/e3fbab10.js delete mode 100644 src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/f142a940.js delete mode 100644 src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/f48f9c37.js delete mode 100644 src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/faa84de5.js delete mode 100644 src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/fb8e5b2a.js delete mode 100644 src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/fc8a39cc.js delete mode 100644 src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/gzip/umbraco-backoffice-init-css.s delete mode 100644 src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/gzip/umbraco-backoffice-js.s delete mode 100644 src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/gzip/umbraco-tinymce-js.s delete mode 100644 src/Umbraco.Web.UI.NetCore/App_Data/Umbraco.sdf diff --git a/src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/02f293c4.js b/src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/02f293c4.js deleted file mode 100644 index 80d078b4e2..0000000000 --- a/src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/02f293c4.js +++ /dev/null @@ -1 +0,0 @@ -!function(m){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),y=function(){},x=function(n,r){return function(){for(var e=[],t=0;tn.maxRow()||sn.maxCol()||(mn.getAt(t,l,s).filter(r).isNone()?(o=f,i=e[l].element(),u=xe.fromTag("td"),Rt(u,xe.fromTag("br")),(o?Rt:Ct)(i,u)):f=!0)}(m,g,h,d),o=e,f=h,s=A(tn.firstLayer(o,"tr"),function(e){return 0===e.dom().childElementCount}),k(s,Nt),f.minCol()!==f.maxCol()&&f.minRow()!==f.maxRow()||k(tn.firstLayer(o,"th,td"),function(e){he(e,"rowspan"),he(e,"colspan")}),he(o,"width"),he(o,"height"),Ae(o,"width"),Ae(o,"height"),e},pn=(Gt=le,Yt="text",{get:function(e){if(!Gt(e))throw new Error("Can only get "+Yt+" value of a "+Yt+" node");return Xt(e).getOr("")},getOption:Xt=function(e){return Gt(e)?R.from(e.dom().nodeValue):R.none()},set:function(e,t){if(!Gt(e))throw new Error("Can only set raw "+Yt+" value of a "+Yt+" node");e.dom().nodeValue=t}}),vn=function(e){return pn.get(e)},bn=function(e){return pn.getOption(e)},wn=function(e,t){pn.set(e,t)},yn=function(e){return"img"===oe(e)?1:bn(e).fold(function(){return bt(e).length},function(e){return e.length})},xn=["img","br"],Cn=function(e){return bn(e).filter(function(e){return 0!==e.trim().length||-1=e.startCol()&&t.column()+t.colspan()-1<=e.finishCol()&&t.row()>=e.startRow()&&t.row()+t.rowspan()-1<=e.finishRow()},_n=function(e,t){var n=t.column(),r=t.column()+t.colspan()-1,o=t.row(),i=t.row()+t.rowspan()-1;return n<=e.finishCol()&&r>=e.startCol()&&o<=e.finishRow()&&i>=e.startRow()},Ln=function(e,t){for(var n=!0,r=b(Mn,t),o=t.startRow();o<=t.finishRow();o++)for(var i=t.startCol();i<=t.finishCol();i++)n=n&&mn.getAt(e,o,i).exists(r);return n?R.some(t):R.none()},Fn=function(e,t,n){var r=mn.findItem(e,t,ft),o=mn.findItem(e,n,ft);return r.bind(function(r){return o.map(function(e){return t=r,n=e,jt(Math.min(t.row(),n.row()),Math.min(t.column(),n.column()),Math.max(t.row()+t.rowspan()-1,n.row()+n.rowspan()-1),Math.max(t.column()+t.colspan()-1,n.column()+n.colspan()-1));var t,n})})},jn=Fn,zn=function(t,e,n){return Fn(t,e,n).bind(function(e){return Ln(t,e)})},Hn=function(r,e,o,i){return mn.findItem(r,e,ft).bind(function(e){var t=0=t.length-1)return R.none();var e=t[n].fold(function(){var e=F(t.slice(0,n));return xo(e,function(e,t){return e.map(function(e){return{value:e,delta:t+1}})})},function(e){return R.some({value:e,delta:0})}),r=t[n+1].fold(function(){var e=t.slice(n+1);return xo(e,function(e,t){return e.map(function(e){return{value:e,delta:t+1}})})},function(e){return R.some({value:e,delta:1})});return e.bind(function(n){return r.map(function(e){var t=e.delta+n.delta;return Math.abs(e.value-n.value)/t})})},Bo=function(e,t,n){var r=e();return B(r,t).orThunk(function(){return R.from(r[0]).orThunk(n)}).map(function(e){return e.element()})},Wo=function(n){var e=n.grid(),t=Po(0,e.columns()),r=Po(0,e.rows());return E(t,function(t){return Bo(function(){return _(r,function(e){return mn.getAt(n,e,t).filter(function(e){return e.column()===t}).fold(C([]),function(e){return[e]})})},function(e){return 1===e.colspan()},function(){return mn.getAt(n,0,t)})})},Mo=function(n){var e=n.grid(),t=Po(0,e.rows()),r=Po(0,e.columns());return E(t,function(t){return Bo(function(){return _(r,function(e){return mn.getAt(n,t,e).filter(function(e){return e.row()===t}).fold(C([]),function(e){return[e]})})},function(e){return 1===e.rowspan()},function(){return mn.getAt(n,t,0)})})},_o=function(e){var t=e.replace(/\./g,"-");return{resolve:function(e){return t+"-"+e}}},Lo={resolve:_o("ephox-snooker").resolve},Fo=function(e,t,n,r,o){var i=xe.fromTag("div");return Oe(i,{position:"absolute",left:t-r/2+"px",top:n+"px",height:o+"px",width:r+"px"}),de(i,{"data-column":e,role:"presentation"}),i},jo=function(e,t,n,r,o){var i=xe.fromTag("div");return Oe(i,{position:"absolute",left:t+"px",top:n-o/2+"px",height:o+"px",width:r+"px"}),de(i,{"data-row":e,role:"presentation"}),i},zo=Lo.resolve("resizer-bar"),Ho=Lo.resolve("resizer-rows"),Uo=Lo.resolve("resizer-cols"),qo=function(e){var t=qt(e.parent(),"."+zo);k(t,Nt)},Vo=function(n,e,r){var o=n.origin();k(e,function(e,t){e.each(function(e){var t=r(o,e);Eo(t,zo),Rt(n.parent(),t)})})},Go=function(e,t,n,r,o,i){var u,a,c,l,f=no(t),s=0=t.length||e.column()>ni.cellLength(t[0]))return pi.error("invalid start address out of table bounds, row: "+e.row()+", column: "+e.column());var r=t.slice(e.row()),o=r[0].cells().slice(e.column()),i=ni.cellLength(n[0]),u=n.length;return pi.value({rowDelta:C(r.length-u),colDelta:C(o.length-i)})},xi=function(e,t){var n=ni.cellLength(e[0]),r=ni.cellLength(t[0]);return{rowDelta:C(0),colDelta:C(n-r)}},Ci=function(e,t,n){var r=t.colDelta()<0?wi:o;return(t.rowDelta()<0?bi:o)(r(e,Math.abs(t.colDelta()),n),Math.abs(t.rowDelta()),n)},Ri=function(e,t,n,r){if(0===e.length)return e;for(var o=t.startRow();o<=t.finishRow();o++)for(var i=t.startCol();i<=t.finishCol();i++)ni.mutateCell(e[o],i,Mt(r(),!1));return e},Si=function(e,t,n,r){for(var o=!0,i=0;i',t.insertBefore(r,t.firstChild)),ga(e,t),o.align&&da(e,t,o.align),e.focus(),e.addVisual()})},Pa=function(t,e){var n,r,o,i,u,a,c,l,f,s,d=t.dom,m={};!0===e?(n=d.getParent(t.selection.getStart(),"table"))&&(c=n,l=(a=t).dom,f={width:l.getStyle(c,"width")||l.getAttrib(c,"width"),height:l.getStyle(c,"height")||l.getAttrib(c,"height"),cellspacing:l.getStyle(c,"border-spacing")||l.getAttrib(c,"cellspacing"),cellpadding:l.getAttrib(c,"data-mce-cell-padding")||l.getAttrib(c,"cellpadding")||pa(a.dom,c,"padding"),border:l.getAttrib(c,"data-mce-border")||l.getAttrib(c,"border")||pa(a.dom,c,"border"),borderColor:l.getAttrib(c,"data-mce-border-color"),caption:!!l.select("caption",c)[0],"class":l.getAttrib(c,"class")},sa.each("left center right".split(" "),function(e){a.formatter.matchNode(c,"align"+e)&&(f.align=e)}),Zu(a)&&sa.extend(f,wa.extractAdvancedStyles(l,c)),m=f):(r={label:"Cols",name:"cols"},o={label:"Rows",name:"rows"}),0=e.left&&t<=e.right&&n>=e.top&&n<=e.bottom},Nc=function(n,r,e,t,o){var i=function(e){var t=n.dom().createRange();return t.setStart(r.dom(),e),t.collapse(!0),t},u=vn(r).length,a=function(e,t,n,r,o){if(0===o)return 0;if(t===r)return o-1;for(var i=r,u=1;ur.left&&o.left ("+e.right()+", "+e.bottom()+")"}},Ml=function(e){return Wl.nu({left:e.left,top:e.top,right:e.right,bottom:e.bottom})},_l=function(e,t){return R.some(e.getRect(t))},Ll=function(e,t,n){return ce(t)?_l(e,t).map(Ml):le(t)?(r=e,o=t,i=n,0<=i&&in.right();var t,n})});var n,o,i},Hl={point:Wl.getTop,adjuster:function(e,t,n,r,o){var i=Wl.moveUp(o,5);return Math.abs(n.top()-r.top())<1?jl.retry(i):n.bottom()o.bottom()?jl.retry(i):n.top()===o.bottom()?jl.retry(Wl.moveDown(o,1)):zl(e,t,o)?jl.retry(Wl.translate(i,5,0)):jl.none()},move:Wl.moveDown,gather:Cl},ql=function(n,r,o,i,u){return 0===u?R.some(i):(c=n,l=i.left(),f=r.point(i),c.elementFromPoint(l,f).filter(function(e){return"table"===oe(e)}).isSome()?(t=i,a=u-1,ql(n,e=r,o,e.move(t,5),a)):n.situsFromPoint(i.left(),r.point(i)).bind(function(e){return e.start().fold(R.none,function(t){return Fl(n,t).bind(function(e){return r.adjuster(n,t,e,o,i).fold(R.none,function(e){return ql(n,r,o,e,u-1)})}).orThunk(function(){return R.some(i)})},R.none)}));var e,t,a,c,l,f},Vl=function(t,n,e){var r,o,i,u=t.move(e,5),a=ql(n,t,e,u,100).getOr(u);return(r=t,o=a,i=n,r.point(o)>i.getInnerHeight()?R.some(r.point(o)-i.getInnerHeight()):r.point(o)<0?R.some(-r.point(o)):R.none()).fold(function(){return n.situsFromPoint(a.left(),t.point(a))},function(e){return n.scrollBy(0,e),n.situsFromPoint(a.left(),t.point(a)-e)})},Gl={tryUp:b(Vl,Hl),tryDown:b(Vl,Ul),ieTryUp:function(e,t){return e.situsFromPoint(t.left(),t.top()-5)},ieTryDown:function(e,t){return e.situsFromPoint(t.left(),t.bottom()+5)},getJumpSize:C(5)},Yl=it.detect(),Xl=function(r,o,i,u,a,c){return 0===c?R.none():$l(r,o,i,u,a).bind(function(e){var t=r.fromSitus(e),n=Dl.verify(r,i,u,t.finish(),t.foffset(),a.failure,o);return Dl.cata(n,function(){return R.none()},function(){return R.some(e)},function(e){return ft(i,e)&&0===u?Kl(r,i,u,Wl.moveUp,a):Xl(r,o,e,0,a,c-1)},function(e){return ft(i,e)&&u===yn(e)?Kl(r,i,u,Wl.moveDown,a):Xl(r,o,e,yn(e),a,c-1)})})},Kl=function(t,e,n,r,o){return Ll(t,e,n).bind(function(e){return Jl(t,o,r(e,Gl.getJumpSize()))})},Jl=function(e,t,n){return Yl.browser.isChrome()||Yl.browser.isSafari()||Yl.browser.isFirefox()||Yl.browser.isEdge()?t.otherRetry(e,n):Yl.browser.isIE()?t.ieRetry(e,n):R.none()},$l=function(t,e,n,r,o){return Ll(t,n,r).bind(function(e){return Jl(t,o,e)})},Ql=function(t,n,r){return(o=t,i=n,u=r,o.getSelection().bind(function(r){return Pl(i,r.finish(),r.foffset(),u).fold(function(){return R.some(Rl(r.finish(),r.foffset()))},function(e){var t=o.fromSitus(e),n=Dl.verify(o,r.finish(),r.foffset(),t.finish(),t.foffset(),u.failure,i);return Il(n)})})).bind(function(e){return Xl(t,n,e.element(),e.offset(),r,20).map(t.fromSitus)});var o,i,u},Zl=it.detect(),ef=function(e,t){return Kt(e,function(e){return gt(e).exists(function(e){return ft(e,t)})},n).isSome();var n},tf=function(t,r,o,e,i){return Zt(e,"td,th",r).bind(function(n){return Zt(n,"table",r).bind(function(e){return ef(i,e)?Ql(t,r,o).bind(function(t){return Zt(t.finish(),"td,th",r).map(function(e){return{start:C(n),finish:C(e),range:C(t)}})}):R.none()})})},nf=function(e,t,n,r,o,i){return Zl.browser.isIE()?R.none():i(r,t).orThunk(function(){return tf(e,t,n,r,o).map(function(e){var t=e.range();return rl.create(R.some(il.makeSitus(t.start(),t.soffset(),t.finish(),t.foffset())),!0)})})},rf=function(e,t,n,r,o,i,u){return tf(e,n,r,o,i).bind(function(e){return al.detect(t,n,e.start(),e.finish(),u)})},of=function(e,u){return Zt(e,"tr",u).bind(function(i){return Zt(i,"table",u).bind(function(e){var t,n,r,o=qt(e,"tr");return ft(i,o[0])?(t=e,n=function(e){return Sn(e).isSome()},r=u,bl(yl,t,n,r)).map(function(e){var t=yn(e);return rl.create(R.some(il.makeSitus(e,t,e,t)),!0)}):R.none()})})},uf=function(e,u){return Zt(e,"tr",u).bind(function(i){return Zt(i,"table",u).bind(function(e){var t,n,r,o=qt(e,"tr");return ft(i,o[o.length-1])?(t=e,n=function(e){return Rn(e).isSome()},r=u,wl(yl,t,n,r)).map(function(e){return rl.create(R.some(il.makeSitus(e,0,e,0)),!0)}):R.none()})})},af=function(e,t){return Zt(e,"td,th",t)},cf={down:{traverse:vt,gather:Cl,relative:pc.before,otherRetry:Gl.tryDown,ieRetry:Gl.ieTryDown,failure:Dl.failedDown},up:{traverse:pt,gather:xl,relative:pc.before,otherRetry:Gl.tryUp,ieRetry:Gl.ieTryUp,failure:Dl.failedUp}},lf=function(t){return function(e){return e===t}},ff=lf(38),sf=lf(40),df={ltr:{isBackward:lf(37),isForward:lf(39)},rtl:{isBackward:lf(39),isForward:lf(37)},isUp:ff,isDown:sf,isNavigation:function(e){return 37<=e&&e<=40}},mf=function(e){return{left:e.left(),top:e.top(),right:e.right(),bottom:e.bottom(),width:e.width(),height:e.height()}},gf=(it.detect().browser.isSafari(),function(a){return{elementFromPoint:function(e,t){return xe.fromPoint(xe.fromDom(a.document),e,t)},getRect:function(e){return e.dom().getBoundingClientRect()},getRangedRect:function(e,t,n,r){var o=bc.exact(e,t,n,r);return Yc(a,o).map(mf)},getSelection:function(){return Gc(a).map(function(e){return il.convertToRange(a,e)})},fromSitus:function(e){var t=bc.relative(e.start(),e.finish());return il.convertToRange(a,t)},situsFromPoint:function(e,t){return Xc(a,e,t).map(function(e){return ol(e.start(),e.soffset(),e.finish(),e.foffset())})},clearSelection:function(){a.getSelection().removeAllRanges()},setSelection:function(e){var t,n,r,o,i,u;t=a,n=e.start(),r=e.soffset(),o=e.finish(),i=e.foffset(),u=Lc(n,r,o,i),Hc(t,u)},setRelativeSelection:function(e,t){var n,r;n=a,r=_c(e,t),Hc(n,r)},selectContents:function(e){Vc(a,e)},getInnerHeight:function(){return a.innerHeight},getScrollY:function(){var e,t,n,r;return(e=xe.fromDom(a.document),t=e!==undefined?e.dom():m.document,n=t.body.scrollLeft||t.documentElement.scrollLeft,r=t.body.scrollTop||t.documentElement.scrollTop,eo(n,r)).top()},scrollBy:function(e,t){var n,r,o;n=e,r=t,((o=xe.fromDom(a.document))!==undefined?o.dom():m.document).defaultView.scrollBy(n,r)}}}),hf=q("rows","cols"),pf={mouse:function(e,t,n,r){var o,i,u,a,c,l,f=gf(e),s=(o=f,i=t,u=n,a=r,c=R.none(),l=function(){c=R.none()},{mousedown:function(e){a.clear(i),c=af(e.target(),u)},mouseover:function(e){c.each(function(r){a.clear(i),af(e.target(),u).each(function(n){sr(r,n,u).each(function(e){var t=e.boxes().getOr([]);(1";for(var n=0;n<10;n++)e+='';e+=""}return e+="",e+=''}(),onPostRender:function(){this.lastX=this.lastY=0},onmousemove:function(e){var t,n,r=e.target;"A"===r.tagName.toUpperCase()&&(t=parseInt(r.getAttribute("data-mce-x"),10),n=parseInt(r.getAttribute("data-mce-y"),10),(this.isRtl()||"tl-tr"===this.parent().rel)&&(t=9-t),t===this.lastX&&n===this.lastY||(s(o,t,n,e.control),this.lastX=t,this.lastY=n))},onclick:function(e){var t=this;"A"===e.target.tagName.toUpperCase()&&(e.preventDefault(),e.stopPropagation(),t.parent().cancel(),o.undoManager.transact(function(){Na(o,t.lastX+1,t.lastY+1)}),o.addVisual())}}]};function m(e){return function(){o.execCommand(e)}}var g={text:"Table properties",context:"table",onPostRender:e,onclick:m("mceTableProps")},h={text:"Delete table",context:"table",onPostRender:e,cmd:"mceTableDelete"},p={text:"Row",context:"table",menu:[{text:"Insert row before",onclick:m("mceTableInsertRowBefore"),onPostRender:t},{text:"Insert row after",onclick:m("mceTableInsertRowAfter"),onPostRender:t},{text:"Delete row",onclick:m("mceTableDeleteRow"),onPostRender:t},{text:"Row properties",onclick:m("mceTableRowProps"),onPostRender:t},{text:"-"},{text:"Cut row",onclick:m("mceTableCutRow"),onPostRender:t},{text:"Copy row",onclick:m("mceTableCopyRow"),onPostRender:t},{text:"Paste row before",onclick:m("mceTablePasteRowBefore"),onPostRender:t},{text:"Paste row after",onclick:m("mceTablePasteRowAfter"),onPostRender:t}]},v={text:"Column",context:"table",menu:[{text:"Insert column before",onclick:m("mceTableInsertColBefore"),onPostRender:t},{text:"Insert column after",onclick:m("mceTableInsertColAfter"),onPostRender:t},{text:"Delete column",onclick:m("mceTableDeleteCol"),onPostRender:t}]},b={separator:"before",text:"Cell",context:"table",menu:[{text:"Cell properties",onclick:m("mceTableCellProps"),onPostRender:t},{text:"Merge cells",onclick:m("mceTableMergeCells"),onPostRender:function(){var t=this;a.push(t),r.fold(function(){l(t)},function(e){t.disabled(e.mergable().isNone())})}},{text:"Split cell",onclick:m("mceTableSplitCells"),onPostRender:function(){var t=this;c.push(t),r.fold(function(){l(t)},function(e){t.disabled(e.unmergable().isNone())})}}]};o.addMenuItem("inserttable",d),o.addMenuItem("tableprops",g),o.addMenuItem("deletetable",h),o.addMenuItem("row",p),o.addMenuItem("column",v),o.addMenuItem("cell",b)},Tf=function(n,r){return{insertTable:function(e,t){return Na(n,e,t)},setClipboardRows:function(e){return t=r,n=E(e,xe.fromDom),void t.set(R.from(n));var t,n},getClipboardRows:function(){return r.get().fold(function(){},function(e){return E(e,function(e){return e.dom()})})}}};e.add("table",function(t){var n,r=cc(t),e=yf(t,r.lazyResize),o=la(t,r.lazyWire),i=(n=t,{get:function(){var e=Fu(n);return hr(e,yr.selectedSelector()).fold(function(){return n.selection.getStart()===undefined?Rr.none():Rr.single(n.selection)},function(e){return Rr.multiple(e)})}}),u=lu(R.none());return Ba(t,o,e,i,u),Ar(t,i,o,e),Sf(t,i),Cf(t),Rf(t),t.on("PreInit",function(){t.serializer.addTempAttr(yr.firstSelected()),t.serializer.addTempAttr(yr.lastSelected())}),t.getParam("table_tab_navigation",!0,"boolean")&&t.on("keydown",function(e){nl(e,t,o,r.lazyWire)}),t.on("remove",function(){r.destroy(),e.destroy()}),Tf(t,u)})}(window); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/079d4891.js b/src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/079d4891.js deleted file mode 100644 index 1238a1d231..0000000000 --- a/src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/079d4891.js +++ /dev/null @@ -1 +0,0 @@ -!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),i=tinymce.util.Tools.resolve("tinymce.Env"),m=function(e){return e.getParam("autolink_pattern",/^(https?:\/\/|ssh:\/\/|ftp:\/\/|file:\/|www\.|(?:mailto:)?[A-Z0-9._%+\-]+@)(.+)$/i)},y=function(e){return e.getParam("default_link_target","")},o=function(e,t){if(t<0&&(t=0),3===e.nodeType){var n=e.data.length;n127)&&(c<2048)){utftext+=String.fromCharCode((c>>6)|192);utftext+=String.fromCharCode((c&63)|128);} -else{utftext+=String.fromCharCode((c>>12)|224);utftext+=String.fromCharCode(((c>>6)&63)|128);utftext+=String.fromCharCode((c&63)|128);}} -return utftext;};} -if(!String.prototype.utf8Decode){String.prototype.utf8Decode=function(){var utftext=this;var string="";var i=0;var c=c1=c2=0;while(i191)&&(c<224)){c2=utftext.charCodeAt(i+1);string+=String.fromCharCode(((c&31)<<6)|(c2&63));i+=2;} -else{c2=utftext.charCodeAt(i+1);c3=utftext.charCodeAt(i+2);string+=String.fromCharCode(((c&15)<<12)|((c2&63)<<6)|(c3&63));i+=3;}} -return string;};} -if(!String.prototype.base64Encode){String.prototype.base64Encode=function(){var keyStr="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";var output="";var chr1,chr2,chr3,enc1,enc2,enc3,enc4;var i=0;var input=this.utf8Encode();while(i>2;enc2=((chr1&3)<<4)|(chr2>>4);enc3=((chr2&15)<<2)|(chr3>>6);enc4=chr3&63;if(isNaN(chr2)){enc3=enc4=64;}else if(isNaN(chr3)){enc4=64;} -output=output+ -keyStr.charAt(enc1)+keyStr.charAt(enc2)+ -keyStr.charAt(enc3)+keyStr.charAt(enc4);} -return output;};} -if(!String.prototype.base64Decode){String.prototype.base64Decode=function(){var input=this;var keyStr="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";var output="";var chr1,chr2,chr3;var enc1,enc2,enc3,enc4;var i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,"");while(i>4);chr2=((enc2&15)<<4)|(enc3>>2);chr3=((enc3&3)<<6)|enc4;output=output+String.fromCharCode(chr1);if(enc3!=64){output=output+String.fromCharCode(chr2);} -if(enc4!=64){output=output+String.fromCharCode(chr3);}} -return output.utf8Decode();};} -if(!Math.randomRange){Math.randomRange=function(from,to){return Math.floor(Math.random()*(to-from+1)+from);};} -if(!String.prototype.toCamelCase){String.prototype.toCamelCase=function(){var s=this.toPascalCase();if($.trim(s)=="") -return"";if(s.length>1){var regex=/^([A-Z]*)([A-Z].*)/g;if(s.match(regex)){var match=regex.exec(s);s=match[1].toLowerCase()+match[2];s=s.substr(0,1).toLowerCase()+s.substr(1);}}else{s=s.toLowerCase();} -return s;};} -if(!String.prototype.toPascalCase){String.prototype.toPascalCase=function(){var s="";$.each($.trim(this).split(/[\s\.-]+/g),function(idx,val){if($.trim(val)=="") -return;if(val.length>1) -s+=val.substr(0,1).toUpperCase()+val.substr(1);else -s+=val.toUpperCase();});return s;};} -if(!String.prototype.toUmbracoAlias){String.prototype.toUmbracoAlias=function(){var s=this.replace(/[^a-zA-Z0-9\s\.-]+/g,'');return s.toCamelCase();};} -if(!String.prototype.toFunction){String.prototype.toFunction=function(){var arr=this.split(".");var fn=(window||this);for(var i=0,len=arr.length;i',i=0;i",a=0;a
'+s+"
"}else t+=""}t+=""}return t+=""},d=function(e){for(;e;){if("TD"===e.nodeName)return e;e=e.parentNode}},m=function(n){var o,e={type:"container",html:u(s(n)),onclick:function(e){var t=e.target;if(/^(TD|DIV)$/.test(t.nodeName)){var a=d(t).firstChild;if(a&&a.hasAttribute("data-chr")){var i=a.getAttribute("data-chr"),r=parseInt(i,10);isNaN(r)||l(n,String.fromCharCode(r)),e.ctrlKey||o.close()}}},onmouseover:function(e){var t=d(e.target);t&&t.firstChild?(o.find("#preview").text(t.firstChild.firstChild.data),o.find("#previewTitle").text(t.title)):(o.find("#preview").text(" "),o.find("#previewTitle").text(" "))}};o=n.windowManager.open({title:"Special character",spacing:10,padding:10,items:[e,{type:"container",layout:"flex",direction:"column",align:"center",spacing:5,minWidth:160,minHeight:160,items:[{type:"label",name:"preview",text:" ",style:"font-size: 40px; text-align: center",border:1,minWidth:140,minHeight:80},{type:"spacer",minHeight:20},{type:"label",name:"previewTitle",text:" ",style:"white-space: pre-wrap;",border:1,minWidth:140}]}],buttons:[{text:"Close",onclick:function(){o.close()}}]})},g=function(e){e.addCommand("mceShowCharmap",function(){m(e)})},p=function(e){e.addButton("charmap",{icon:"charmap",tooltip:"Special character",cmd:"mceShowCharmap"}),e.addMenuItem("charmap",{icon:"charmap",text:"Special character",cmd:"mceShowCharmap",context:"insert"})};e.add("charmap",function(e){return g(e),p(e),t(e)})}(); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/32a48b01.js b/src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/32a48b01.js deleted file mode 100644 index 4bfe94221c..0000000000 --- a/src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/32a48b01.js +++ /dev/null @@ -1,3 +0,0 @@ -/*! 12.2.13 */ -!window.XMLHttpRequest||window.FileAPI&&FileAPI.shouldLoad||(window.XMLHttpRequest.prototype.setRequestHeader=function(a){return function(b,c){if("__setXHR_"===b){var d=c(this);d instanceof Function&&d(this)}else a.apply(this,arguments)}}(window.XMLHttpRequest.prototype.setRequestHeader));var ngFileUpload=angular.module("ngFileUpload",[]);ngFileUpload.version="12.2.13",ngFileUpload.service("UploadBase",["$http","$q","$timeout",function(a,b,c){function d(d){function e(a){j.notify&&j.notify(a),k.progressFunc&&c(function(){k.progressFunc(a)})}function h(a){return null!=d._start&&g?{loaded:a.loaded+d._start,total:d._file&&d._file.size||a.total,type:a.type,config:d,lengthComputable:!0,target:a.target}:a}function i(){a(d).then(function(a){if(g&&d._chunkSize&&!d._finished&&d._file){var b=d._file&&d._file.size||0;e({loaded:Math.min(d._end,b),total:b,config:d,type:"progress"}),f.upload(d,!0)}else d._finished&&delete d._finished,j.resolve(a)},function(a){j.reject(a)},function(a){j.notify(a)})}d.method=d.method||"POST",d.headers=d.headers||{};var j=d._deferred=d._deferred||b.defer(),k=j.promise;return d.disableProgress||(d.headers.__setXHR_=function(){return function(a){a&&a.upload&&a.upload.addEventListener&&(d.__XHR=a,d.xhrFn&&d.xhrFn(a),a.upload.addEventListener("progress",function(a){a.config=d,e(h(a))},!1),a.upload.addEventListener("load",function(a){a.lengthComputable&&(a.config=d,e(h(a)))},!1))}}),g?d._chunkSize&&d._end&&!d._finished?(d._start=d._end,d._end+=d._chunkSize,i()):d.resumeSizeUrl?a.get(d.resumeSizeUrl).then(function(a){d._start=d.resumeSizeResponseReader?d.resumeSizeResponseReader(a.data):parseInt((null==a.data.size?a.data:a.data.size).toString()),d._chunkSize&&(d._end=d._start+d._chunkSize),i()},function(a){throw a}):d.resumeSize?d.resumeSize().then(function(a){d._start=a,d._chunkSize&&(d._end=d._start+d._chunkSize),i()},function(a){throw a}):(d._chunkSize&&(d._start=0,d._end=d._start+d._chunkSize),i()):i(),k.success=function(a){return k.then(function(b){a(b.data,b.status,b.headers,d)}),k},k.error=function(a){return k.then(null,function(b){a(b.data,b.status,b.headers,d)}),k},k.progress=function(a){return k.progressFunc=a,k.then(null,null,function(b){a(b)}),k},k.abort=k.pause=function(){return d.__XHR&&c(function(){d.__XHR.abort()}),k},k.xhr=function(a){return d.xhrFn=function(b){return function(){b&&b.apply(k,arguments),a.apply(k,arguments)}}(d.xhrFn),k},f.promisesCount++,k["finally"]&&k["finally"]instanceof Function&&k["finally"](function(){f.promisesCount--}),k}function e(a){var b={};for(var c in a)a.hasOwnProperty(c)&&(b[c]=a[c]);return b}var f=this;f.promisesCount=0,this.isResumeSupported=function(){return window.Blob&&window.Blob.prototype.slice};var g=this.isResumeSupported();this.isUploadInProgress=function(){return f.promisesCount>0},this.rename=function(a,b){return a.ngfName=b,a},this.jsonBlob=function(a){null==a||angular.isString(a)||(a=JSON.stringify(a));var b=new window.Blob([a],{type:"application/json"});return b._ngfBlob=!0,b},this.json=function(a){return angular.toJson(a)},this.isFile=function(a){return null!=a&&(a instanceof window.Blob||a.flashId&&a.name&&a.size)},this.upload=function(a,b){function c(b,c){if(b._ngfBlob)return b;if(a._file=a._file||b,null!=a._start&&g){a._end&&a._end>=b.size&&(a._finished=!0,a._end=b.size);var d=b.slice(a._start,a._end||b.size);return d.name=b.name,d.ngfName=b.ngfName,a._chunkSize&&(c.append("_chunkSize",a._chunkSize),c.append("_currentChunkSize",a._end-a._start),c.append("_chunkNumber",Math.floor(a._start/a._chunkSize)),c.append("_totalSize",a._file.size)),d}return b}function h(b,d,e){if(void 0!==d)if(angular.isDate(d)&&(d=d.toISOString()),angular.isString(d))b.append(e,d);else if(f.isFile(d)){var g=c(d,b),i=e.split(",");i[1]&&(g.ngfName=i[1].replace(/^\s+|\s+$/g,""),e=i[0]),a._fileKey=a._fileKey||e,b.append(e,g,g.ngfName||g.name)}else if(angular.isObject(d)){if(d.$$ngfCircularDetection)throw"ngFileUpload: Circular reference in config.data. Make sure specified data for Upload.upload() has no circular reference: "+e;d.$$ngfCircularDetection=!0;try{for(var j in d)if(d.hasOwnProperty(j)&&"$$ngfCircularDetection"!==j){var k=null==a.objectKey?"[i]":a.objectKey;d.length&&parseInt(j)>-1&&(k=null==a.arrayKey?k:a.arrayKey),h(b,d[j],e+k.replace(/[ik]/g,j))}}finally{delete d.$$ngfCircularDetection}}else b.append(e,d)}function i(){a._chunkSize=f.translateScalars(a.resumeChunkSize),a._chunkSize=a._chunkSize?parseInt(a._chunkSize.toString()):null,a.headers=a.headers||{},a.headers["Content-Type"]=void 0,a.transformRequest=a.transformRequest?angular.isArray(a.transformRequest)?a.transformRequest:[a.transformRequest]:[],a.transformRequest.push(function(b){var c,d=new window.FormData;b=b||a.fields||{},a.file&&(b.file=a.file);for(c in b)if(b.hasOwnProperty(c)){var e=b[c];a.formDataAppender?a.formDataAppender(d,c,e):h(d,e,c)}return d})}return b||(a=e(a)),a._isDigested||(a._isDigested=!0,i()),d(a)},this.http=function(b){return b=e(b),b.transformRequest=b.transformRequest||function(b){return window.ArrayBuffer&&b instanceof window.ArrayBuffer||b instanceof window.Blob?b:a.defaults.transformRequest[0].apply(this,arguments)},b._chunkSize=f.translateScalars(b.resumeChunkSize),b._chunkSize=b._chunkSize?parseInt(b._chunkSize.toString()):null,d(b)},this.translateScalars=function(a){if(angular.isString(a)){if(a.search(/kb/i)===a.length-2)return parseFloat(1024*a.substring(0,a.length-2));if(a.search(/mb/i)===a.length-2)return parseFloat(1048576*a.substring(0,a.length-2));if(a.search(/gb/i)===a.length-2)return parseFloat(1073741824*a.substring(0,a.length-2));if(a.search(/b/i)===a.length-1)return parseFloat(a.substring(0,a.length-1));if(a.search(/s/i)===a.length-1)return parseFloat(a.substring(0,a.length-1));if(a.search(/m/i)===a.length-1)return parseFloat(60*a.substring(0,a.length-1));if(a.search(/h/i)===a.length-1)return parseFloat(3600*a.substring(0,a.length-1))}return a},this.urlToBlob=function(c){var d=b.defer();return a({url:c,method:"get",responseType:"arraybuffer"}).then(function(a){var b=new Uint8Array(a.data),e=a.headers("content-type")||"image/WebP",f=new window.Blob([b],{type:e}),g=c.match(/.*\/(.+?)(\?.*)?$/);g.length>1&&(f.name=g[1]),d.resolve(f)},function(a){d.reject(a)}),d.promise},this.setDefaults=function(a){this.defaults=a||{}},this.defaults={},this.version=ngFileUpload.version}]),ngFileUpload.service("Upload",["$parse","$timeout","$compile","$q","UploadExif",function(a,b,c,d,e){function f(a,b,c){var e=[i.emptyPromise()];return angular.forEach(a,function(d,f){0===d.type.indexOf("image/jpeg")&&i.attrGetter("ngfFixOrientation",b,c,{$file:d})&&e.push(i.happyPromise(i.applyExifRotation(d),d).then(function(b){a.splice(f,1,b)}))}),d.all(e)}function g(a,b,c,e){var f=i.attrGetter("ngfResize",b,c);if(!f||!i.isResizeSupported()||!a.length)return i.emptyPromise();if(f instanceof Function){var g=d.defer();return f(a).then(function(d){h(d,a,b,c,e).then(function(a){g.resolve(a)},function(a){g.reject(a)})},function(a){g.reject(a)})}return h(f,a,b,c,e)}function h(a,b,c,e,f){function g(d,g){if(0===d.type.indexOf("image")){if(a.pattern&&!i.validatePattern(d,a.pattern))return;a.resizeIf=function(a,b){return i.attrGetter("ngfResizeIf",c,e,{$width:a,$height:b,$file:d})};var j=i.resize(d,a);h.push(j),j.then(function(a){b.splice(g,1,a)},function(a){d.$error="resize",(d.$errorMessages=d.$errorMessages||{}).resize=!0,d.$errorParam=(a?(a.message?a.message:a)+": ":"")+(d&&d.name),f.$ngfValidations.push({name:"resize",valid:!1}),i.applyModelValidation(f,b)})}}for(var h=[i.emptyPromise()],j=0;j-1:!0},i.emptyPromise=function(){var a=d.defer(),c=arguments;return b(function(){a.resolve.apply(a,c)}),a.promise},i.rejectPromise=function(){var a=d.defer(),c=arguments;return b(function(){a.reject.apply(a,c)}),a.promise},i.happyPromise=function(a,c){var e=d.defer();return a.then(function(a){e.resolve(a)},function(a){b(function(){throw a}),e.resolve(c)}),e.promise},i.updateModel=function(c,d,e,h,j,k,l){function m(f,g,j,l,m){d.$$ngfPrevValidFiles=f,d.$$ngfPrevInvalidFiles=g;var n=f&&f.length?f[0]:null,o=g&&g.length?g[0]:null;c&&(i.applyModelValidation(c,f),c.$setViewValue(m?n:f)),h&&a(h)(e,{$files:f,$file:n,$newFiles:j,$duplicateFiles:l,$invalidFiles:g,$invalidFile:o,$event:k});var p=i.attrGetter("ngfModelInvalid",d);p&&b(function(){a(p).assign(e,m?o:g)}),b(function(){})}function n(){function a(a,b){return a.name===b.name&&(a.$ngfOrigSize||a.size)===(b.$ngfOrigSize||b.size)&&a.type===b.type}function b(b){var c;for(c=0;c-1&&(v.splice(d,1),u.push(c)),a()}}})}var q,r,s,t=[],u=[],v=[];r=d.$$ngfPrevValidFiles||[],s=d.$$ngfPrevInvalidFiles||[],c&&c.$modelValue&&(r=o(c.$modelValue));var w=i.attrGetter("ngfKeep",d,e);q=(j||[]).slice(0),("distinct"===w||i.attrGetter("ngfKeepDistinct",d,e)===!0)&&n(d,e);var x=!w&&!i.attrGetter("ngfMultiple",d,e)&&!i.attrGetter("multiple",d);if(!w||q.length){i.attrGetter("ngfBeforeModelChange",d,e,{$files:j,$file:j&&j.length?j[0]:null,$newFiles:q,$duplicateFiles:t,$event:k});var y=i.attrGetter("ngfValidateAfterResize",d,e),z=i.attrGetter("ngfModelOptions",d,e);i.validate(q,w?r.length:0,c,d,e).then(function(a){l?m(q,[],j,t,x):(z&&z.allowInvalid||y?v=q:(v=a.validFiles,u=a.invalidFiles),i.attrGetter("ngfFixOrientation",d,e)&&i.isExifSupported()?f(v,d,e).then(function(){p()}):p())})}},i}]),ngFileUpload.directive("ngfSelect",["$parse","$timeout","$compile","Upload",function(a,b,c,d){function e(a){var b=a.match(/Android[^\d]*(\d+)\.(\d+)/);if(b&&b.length>2){var c=d.defaults.androidFixMinorVersion||4;return parseInt(b[1])<4||parseInt(b[1])===c&&parseInt(b[2])'),c=angular.element("");return c.css("visibility","hidden").css("position","absolute").css("overflow","hidden").css("width","0px").css("height","0px").css("border","none").css("margin","0px").css("padding","0px").attr("tabindex","-1"),n(a,c),g.push({el:b,ref:c}),document.body.appendChild(c.append(a)[0]),a}function p(c){if(b.attr("disabled"))return!1;if(!t("ngfSelectDisabled",a)){var d=q(c);if(null!=d)return d;r(c);try{k()||document.body.contains(x[0])||(g.push({el:b,ref:x.parent()}),document.body.appendChild(x.parent()[0]),x.bind("change",m))}catch(f){}return e(navigator.userAgent)?setTimeout(function(){x[0].click()},0):x[0].click(),!1}}function q(a){var b=a.changedTouches||a.originalEvent&&a.originalEvent.changedTouches;if(b){if("touchstart"===a.type)return w=b[0].clientX,v=b[0].clientY,!0;if("touchend"===a.type){var c=b[0].clientX,d=b[0].clientY;if(Math.abs(c-w)>20||Math.abs(d-v)>20)return a.stopPropagation(),a.preventDefault(),!1}return!0}}function r(b){j.shouldUpdateOn("click",c,a)&&x.val()&&(x.val(null),j.updateModel(d,c,a,l(),null,b,!0))}function s(a){if(x&&!x.attr("__ngf_ie10_Fix_")){if(!x[0].parentNode)return void(x=null);a.preventDefault(),a.stopPropagation(),x.unbind("click");var b=x.clone();return x.replaceWith(b),x=b,x.attr("__ngf_ie10_Fix_","true"),x.bind("change",m),x.bind("click",s),x[0].click(),!1}x.removeAttr("__ngf_ie10_Fix_")}var t=function(a,b){return j.attrGetter(a,c,b)};j.registerModelChangeValidator(d,c,a);var u=[];t("ngfMultiple")&&u.push(a.$watch(t("ngfMultiple"),function(){x.attr("multiple",t("ngfMultiple",a))})),t("ngfCapture")&&u.push(a.$watch(t("ngfCapture"),function(){x.attr("capture",t("ngfCapture",a))})),t("ngfAccept")&&u.push(a.$watch(t("ngfAccept"),function(){x.attr("accept",t("ngfAccept",a))})),u.push(c.$observe("accept",function(){x.attr("accept",t("accept"))}));var v=0,w=0,x=b;k()||(x=o()),x.bind("change",m),k()?b.bind("click",r):b.bind("click touchstart touchend",p),-1!==navigator.appVersion.indexOf("MSIE 10")&&x.bind("click",s),d&&d.$formatters.push(function(a){return(null==a||0===a.length)&&x.val()&&x.val(null),a}),a.$on("$destroy",function(){k()||x.parent().remove(),angular.forEach(u,function(a){a()})}),h(function(){for(var a=0;a-1&&l.height&&l.height.indexOf("px")>-1&&(k={width:parseInt(l.width.slice(0,-2)),height:parseInt(l.height.slice(0,-2))})}return angular.isString(c)?(e.removeClass("ng-hide"),i?e.css("background-image","url('"+c+"')"):e.attr("src",c)):void(!c||!c.type||0!==c.type.search(a(e[0]))||i&&0!==c.type.indexOf("image")?e.addClass("ng-hide"):k&&b.isResizeSupported()?(k.resizeIf=function(a,e){return b.attrGetter("ngfResizeIf",f,d,{$width:a,$height:e,$file:c})},b.resize(c,k).then(function(a){j(a)},function(a){throw a})):j(c))});d.$on("$destroy",function(){c()})})}ngFileUpload.service("UploadDataUrl",["UploadBase","$timeout","$q",function(a,b,c){var d=a;return d.base64DataUrl=function(a){if(angular.isArray(a)){var b=c.defer(),e=0;return angular.forEach(a,function(c){d.dataUrl(c,!0)["finally"](function(){if(e++,e===a.length){var c=[];angular.forEach(a,function(a){c.push(a.$ngfDataUrl)}),b.resolve(c,a)}})}),b.promise}return d.dataUrl(a,!0)},d.dataUrl=function(a,e){if(!a)return d.emptyPromise(a,a);if(e&&null!=a.$ngfDataUrl||!e&&null!=a.$ngfBlobUrl)return d.emptyPromise(e?a.$ngfDataUrl:a.$ngfBlobUrl,a);var f=e?a.$$ngfDataUrlPromise:a.$$ngfBlobUrlPromise;if(f)return f;var g=c.defer();return b(function(){if(window.FileReader&&a&&(!window.FileAPI||-1===navigator.userAgent.indexOf("MSIE 8")||a.size<2e4)&&(!window.FileAPI||-1===navigator.userAgent.indexOf("MSIE 9")||a.size<4e6)){var c=window.URL||window.webkitURL;if(c&&c.createObjectURL&&!e){var f;try{f=c.createObjectURL(a)}catch(h){return void b(function(){a.$ngfBlobUrl="",g.reject()})}b(function(){if(a.$ngfBlobUrl=f,f){g.resolve(f,a),d.blobUrls=d.blobUrls||[],d.blobUrlsTotalSize=d.blobUrlsTotalSize||0,d.blobUrls.push({url:f,size:a.size}),d.blobUrlsTotalSize+=a.size||0;for(var b=d.defaults.blobUrlsMaxMemory||268435456,e=d.defaults.blobUrlsMaxQueueSize||200;(d.blobUrlsTotalSize>b||d.blobUrls.length>e)&&d.blobUrls.length>1;){var h=d.blobUrls.splice(0,1)[0];c.revokeObjectURL(h.url),d.blobUrlsTotalSize-=h.size}}})}else{var i=new FileReader;i.onload=function(c){b(function(){a.$ngfDataUrl=c.target.result,g.resolve(c.target.result,a),b(function(){delete a.$ngfDataUrl},1e3)})},i.onerror=function(){b(function(){a.$ngfDataUrl="",g.reject()})},i.readAsDataURL(a)}}else b(function(){a[e?"$ngfDataUrl":"$ngfBlobUrl"]="",g.reject()})}),f=e?a.$$ngfDataUrlPromise=g.promise:a.$$ngfBlobUrlPromise=g.promise,f["finally"](function(){delete a[e?"$$ngfDataUrlPromise":"$$ngfBlobUrlPromise"]}),f},d}]),ngFileUpload.directive("ngfSrc",["Upload","$timeout",function(a,c){return{restrict:"AE",link:function(d,e,f){b(a,c,d,e,f,"ngfSrc",a.attrGetter("ngfResize",f,d),!1)}}}]),ngFileUpload.directive("ngfBackground",["Upload","$timeout",function(a,c){return{restrict:"AE",link:function(d,e,f){b(a,c,d,e,f,"ngfBackground",a.attrGetter("ngfResize",f,d),!0)}}}]),ngFileUpload.directive("ngfThumbnail",["Upload","$timeout",function(a,c){return{restrict:"AE",link:function(d,e,f){var g=a.attrGetter("ngfSize",f,d);b(a,c,d,e,f,"ngfThumbnail",g,a.attrGetter("ngfAsBackground",f,d))}}}]),ngFileUpload.config(["$compileProvider",function(a){a.imgSrcSanitizationWhitelist&&a.imgSrcSanitizationWhitelist(/^\s*(https?|ftp|mailto|tel|webcal|local|file|data|blob):/),a.aHrefSanitizationWhitelist&&a.aHrefSanitizationWhitelist(/^\s*(https?|ftp|mailto|tel|webcal|local|file|data|blob):/)}]),ngFileUpload.filter("ngfDataUrl",["UploadDataUrl","$sce",function(a,b){return function(c,d,e){if(angular.isString(c))return b.trustAsResourceUrl(c);var f=c&&((d?c.$ngfDataUrl:c.$ngfBlobUrl)||c.$ngfDataUrl);return c&&!f?(!c.$ngfDataUrlFilterInProgress&&angular.isObject(c)&&(c.$ngfDataUrlFilterInProgress=!0,a.dataUrl(c,d)),""):(c&&delete c.$ngfDataUrlFilterInProgress,(c&&f?e?b.trustAsResourceUrl(f):f:c)||"")}}])}(),ngFileUpload.service("UploadValidate",["UploadDataUrl","$q","$timeout",function(a,b,c){function d(a){var b="",c=[];if(a.length>2&&"/"===a[0]&&"/"===a[a.length-1])b=a.substring(1,a.length-1);else{var e=a.split(",");if(e.length>1)for(var f=0;f|:\\-]","g"),"\\$&")+"$",b=b.replace(/\\\*/g,".*").replace(/\\\?/g,"."))}return{regexp:b,excludes:c}}function e(a,b){null==b||a.$dirty||(a.$setDirty?a.$setDirty():a.$dirty=!0)}var f=a;return f.validatePattern=function(a,b){if(!b)return!0;var c=d(b),e=!0;if(c.regexp&&c.regexp.length){var f=new RegExp(c.regexp,"i");e=null!=a.type&&f.test(a.type)||null!=a.name&&f.test(a.name)}for(var g=c.excludes.length;g--;){var h=new RegExp(c.excludes[g],"i");e=e&&(null==a.type||h.test(a.type))&&(null==a.name||h.test(a.name))}return e},f.ratioToFloat=function(a){var b=a.toString(),c=b.search(/[x:]/i);return b=c>-1?parseFloat(b.substring(0,c))/parseFloat(b.substring(c+1)):parseFloat(b)},f.registerModelChangeValidator=function(a,b,c){a&&a.$formatters.push(function(d){if(a.$dirty){var e=d;d&&!angular.isArray(d)&&(e=[d]),f.validate(e,0,a,b,c).then(function(){f.applyModelValidation(a,e)})}return d})},f.applyModelValidation=function(a,b){e(a,b),angular.forEach(a.$ngfValidations,function(b){a.$setValidity(b.name,b.valid)})},f.getValidationAttr=function(a,b,c,d,e){var g="ngf"+c[0].toUpperCase()+c.substr(1),h=f.attrGetter(g,a,b,{$file:e});if(null==h&&(h=f.attrGetter("ngfValidate",a,b,{$file:e}))){var i=(d||c).split(".");h=h[i[0]],i.length>1&&(h=h&&h[i[1]])}return h},f.validate=function(a,c,d,e,g){function h(b,c,h){if(a){for(var i=a.length,j=null;i--;){var n=a[i];if(n){var o=f.getValidationAttr(e,g,b,c,n);null!=o&&(h(n,o,i)||(-1===k.indexOf(b)?(n.$error=b,(n.$errorMessages=n.$errorMessages||{})[b]=!0,n.$errorParam=o,-1===m.indexOf(n)&&m.push(n),l||a.splice(i,1),j=!1):a.splice(i,1)))}}null!==j&&d.$ngfValidations.push({name:b,valid:j})}}function i(c,h,i,n,o){function p(b,d,e){function f(f){if(f())if(-1===k.indexOf(c)){if(d.$error=c,(d.$errorMessages=d.$errorMessages||{})[c]=!0,d.$errorParam=e,-1===m.indexOf(d)&&m.push(d),!l){var g=a.indexOf(d);g>-1&&a.splice(g,1)}b.resolve(!1)}else{var h=a.indexOf(d);h>-1&&a.splice(h,1),b.resolve(!0)}else b.resolve(!0)}null!=e?n(d,e).then(function(a){f(function(){return!o(a,e)})},function(){f(function(){return j("ngfValidateForce",{$file:d})})}):b.resolve(!0)}var q=[f.emptyPromise(!0)];a&&(a=void 0===a.length?[a]:a,angular.forEach(a,function(a){var d=b.defer();return q.push(d.promise),!i||null!=a.type&&0===a.type.search(i)?void("dimensions"===c&&null!=f.attrGetter("ngfDimensions",e)?f.imageDimensions(a).then(function(b){p(d,a,j("ngfDimensions",{$file:a,$width:b.width,$height:b.height}))},function(){d.resolve(!1)}):"duration"===c&&null!=f.attrGetter("ngfDuration",e)?f.mediaDuration(a).then(function(b){p(d,a,j("ngfDuration",{$file:a,$duration:b}))},function(){d.resolve(!1)}):p(d,a,f.getValidationAttr(e,g,c,h,a))):void d.resolve(!0)}));var r=b.defer();return b.all(q).then(function(a){for(var b=!0,e=0;e=f.translateScalars(b)}),h("maxSize","size.max",function(a,b){return a.size-.1<=f.translateScalars(b)});var n=0;if(h("maxTotalSize",null,function(b,c){return n+=b.size,n>f.translateScalars(c)?(a.splice(0,a.length),!1):!0}),h("validateFn",null,function(a,b){return b===!0||null===b||""===b}),!a.length)return f.emptyPromise({validFiles:[],invalidFiles:m});var o=b.defer(),p=[];return p.push(i("maxHeight","height.max",/image/,this.imageDimensions,function(a,b){return a.height<=b})),p.push(i("minHeight","height.min",/image/,this.imageDimensions,function(a,b){return a.height>=b})),p.push(i("maxWidth","width.max",/image/,this.imageDimensions,function(a,b){return a.width<=b})),p.push(i("minWidth","width.min",/image/,this.imageDimensions,function(a,b){return a.width>=b})),p.push(i("dimensions",null,/image/,function(a,b){return f.emptyPromise(b)},function(a){return a})),p.push(i("ratio",null,/image/,this.imageDimensions,function(a,b){for(var c=b.toString().split(","),d=!1,e=0;e-1e-4})),p.push(i("maxDuration","duration.max",/audio|video/,this.mediaDuration,function(a,b){return a<=f.translateScalars(b)})),p.push(i("minDuration","duration.min",/audio|video/,this.mediaDuration,function(a,b){return a>=f.translateScalars(b)})),p.push(i("duration",null,/audio|video/,function(a,b){return f.emptyPromise(b)},function(a){return a})),p.push(i("validateAsyncFn",null,null,function(a,b){return b},function(a){return a===!0||null===a||""===a})),b.all(p).then(function(){if(l)for(var b=0;bc+d}),o.resolve({validFiles:a,invalidFiles:m})}),o.promise},f.imageDimensions=function(a){if(a.$ngfWidth&&a.$ngfHeight){var d=b.defer();return c(function(){d.resolve({width:a.$ngfWidth,height:a.$ngfHeight})}),d.promise}if(a.$ngfDimensionPromise)return a.$ngfDimensionPromise;var e=b.defer();return c(function(){return 0!==a.type.indexOf("image")?void e.reject("not image"):void f.dataUrl(a).then(function(b){function d(){var b=h[0].naturalWidth||h[0].clientWidth,c=h[0].naturalHeight||h[0].clientHeight;h.remove(),a.$ngfWidth=b,a.$ngfHeight=c,e.resolve({width:b,height:c})}function f(){h.remove(),e.reject("load error")}function g(){c(function(){h[0].parentNode&&(h[0].clientWidth?d():i++>10?f():g())},1e3)}var h=angular.element("").attr("src",b).css("visibility","hidden").css("position","fixed").css("max-width","none !important").css("max-height","none !important");h.on("load",d),h.on("error",f);var i=0;g(),angular.element(document.getElementsByTagName("body")[0]).append(h)},function(){e.reject("load error")})}),a.$ngfDimensionPromise=e.promise,a.$ngfDimensionPromise["finally"](function(){delete a.$ngfDimensionPromise}),a.$ngfDimensionPromise},f.mediaDuration=function(a){if(a.$ngfDuration){var d=b.defer();return c(function(){d.resolve(a.$ngfDuration)}),d.promise}if(a.$ngfDurationPromise)return a.$ngfDurationPromise;var e=b.defer();return c(function(){return 0!==a.type.indexOf("audio")&&0!==a.type.indexOf("video")?void e.reject("not media"):void f.dataUrl(a).then(function(b){function d(){var b=h[0].duration;a.$ngfDuration=b,h.remove(),e.resolve(b)}function f(){h.remove(),e.reject("load error")}function g(){c(function(){h[0].parentNode&&(h[0].duration?d():i>10?f():g())},1e3)}var h=angular.element(0===a.type.indexOf("audio")?"
';vm.hasReferences=false;vm.references=[];vm.performDelete=function(){$scope.currentNode.loading=true;dataTypeResource.deleteById($scope.currentNode.id).then(function(){$scope.currentNode.loading=false;var rootNode=treeService.getTreeRoot($scope.currentNode);treeService.removeNode($scope.currentNode);navigationService.hideMenu();});};vm.performContainerDelete=function(){$scope.currentNode.loading=true;dataTypeResource.deleteContainerById($scope.currentNode.id).then(function(){$scope.currentNode.loading=false;var rootNode=treeService.getTreeRoot($scope.currentNode);treeService.removeNode($scope.currentNode);navigationService.hideMenu();});};vm.cancel=function(){navigationService.hideDialog();};vm.onReferenceClicked=function(event){if(event.metaKey!==true){navigationService.hideDialog();}};vm.labels={};localizationService.localize('editdatatype_acceptDeleteConsequence',[$scope.currentNode.name]).then(function(data){vm.labels.deleteConfirm=data;});var init=function init(){if($scope.currentNode.nodeType==='dataTypes'){vm.loading=true;dataTypeResource.getReferences($scope.currentNode.id).then(function(data){vm.loading=false;vm.references=data;vm.hasReferences=data.documentTypes.length>0||data.mediaTypes.length>0||data.memberTypes.length>0;});}};init();} -angular.module('umbraco').controller('Umbraco.Editors.DataType.DeleteController',DataTypeDeleteController);'use strict';function DataTypeEditController($scope,$routeParams,appState,navigationService,dataTypeResource,serverValidationManager,contentEditingHelper,formHelper,editorState,dataTypeHelper,eventsService,localizationService){var evts=[];var vm=this;vm.header={};vm.header.editorfor='visuallyHiddenTexts_newDataType';vm.header.setPageTitle=true;vm.page={};vm.page.loading=false;vm.page.menu={};vm.page.menu.currentSection=appState.getSectionState('currentSection');vm.page.menu.currentNode=null;vm.properties={selectedEditor:{alias:'selectedEditor',description:'Select a property editor',label:'Property editor'}};vm.preValues=[];function createPreValueProps(preVals){vm.preValues=[];for(var i=0;i0||data.mediaTypes.length>0||data.memberTypes.length>0;});}} -function openDocumentType(id,event){open(id,event,'documentType');} -function openMediaType(id,event){open(id,event,'mediaType');} -function openMemberType(id,event){open(id,event,'memberType');} -function open(id,event,type){if(event.ctrlKey||event.shiftKey||event.metaKey||event.button&&event.button===1){return;} -event.stopPropagation();event.preventDefault();var editor={id:id,submit:function submit(model){editorService.close();vm.view.loading=true;referencesLoaded=false;loadRelations();},close:function close(){editorService.close();}};switch(type){case'documentType':editorService.documentTypeEditor(editor);break;case'mediaType':editorService.mediaTypeEditor(editor);break;case'memberType':editorService.memberTypeEditor(editor);break;}} -evts.push(eventsService.on('app.tabChange',function(event,args){$timeout(function(){if(args.alias==='info'){loadRelations();}});}));$scope.$on('$destroy',function(){for(var e in evts){eventsService.unsubscribe(evts[e]);}});} -angular.module('umbraco').controller('Umbraco.Editors.DataType.InfoController',DataTypeInfoController);'use strict';function DictionaryCreateController($scope,$location,dictionaryResource,navigationService,notificationsService,formHelper,appState){var vm=this;vm.itemKey='';vm.createItem=createItem;function createItem(){if(formHelper.submitForm({scope:$scope,formCtrl:this.createDictionaryForm})){var node=$scope.currentNode;dictionaryResource.create(node.id,vm.itemKey).then(function(data){navigationService.hideMenu();var currPath=node.path?node.path:'-1';navigationService.syncTree({tree:'dictionary',path:currPath+','+data,forceReload:true,activate:true});formHelper.resetForm({scope:$scope});var currentSection=appState.getSectionState('currentSection');$location.path('/'+currentSection+'/dictionary/edit/'+data);},function(err){if(err.data&&err.data.message){notificationsService.error(err.data.message);navigationService.hideMenu();}});}}} -angular.module('umbraco').controller('Umbraco.Editors.Dictionary.CreateController',DictionaryCreateController);'use strict';function DictionaryDeleteController($scope,$location,dictionaryResource,treeService,navigationService,appState){var vm=this;function cancel(){navigationService.hideDialog();} -function performDelete(){if($scope.busy){return false;} -$scope.currentNode.loading=true;$scope.busy=true;dictionaryResource.deleteById($scope.currentNode.id).then(function(){$scope.currentNode.loading=false;var parentId=$scope.currentNode.parentId;treeService.removeNode($scope.currentNode);navigationService.hideMenu();var currentSection=appState.getSectionState('currentSection');if(parentId!=='-1'){$location.path('/'+currentSection+'/dictionary/edit/'+parentId);}else{$location.path('/'+currentSection+'/');}});} -vm.cancel=cancel;vm.performDelete=performDelete;} -angular.module('umbraco').controller('Umbraco.Editors.Dictionary.DeleteController',DictionaryDeleteController);'use strict';function DictionaryEditController($scope,$routeParams,$location,dictionaryResource,navigationService,appState,editorState,contentEditingHelper,formHelper,notificationsService,localizationService){var vm=this;vm.nameDirty=false;vm.header={};vm.header.editorfor='template_insertDictionaryItem';vm.header.setPageTitle=true;vm.page={};vm.page.loading=false;vm.page.nameLocked=false;vm.page.menu={};vm.page.menu.currentSection=appState.getSectionState('currentSection');vm.page.menu.currentNode=null;vm.description='';vm.showBackButton=true;vm.save=saveDictionary;vm.back=back;function loadDictionary(){vm.page.loading=true;dictionaryResource.getById($routeParams.id).then(function(data){bindDictionary(data);vm.page.loading=false;});} -function createTranslationProperty(translation){return{alias:translation.isoCode,label:translation.displayName,hideLabel:false};} -function bindDictionary(data){localizationService.localize('dictionaryItem_description').then(function(value){vm.description=value.replace('%0%',data.name);});for(var i=0;i-1){collectionItemIcon=icons[i];}} -contentTypeResource.createCollection(node.id,$scope.model.collectionName,$scope.model.collectionCreateTemplate,$scope.model.collectionItemName,$scope.model.collectionItemCreateTemplate,collectionIcon,collectionItemIcon).then(function(collectionData){navigationService.hideMenu();$location.search('create',null);$location.search('notemplate',null);formHelper.resetForm({scope:$scope});var section=appState.getSectionState('currentSection');$location.path('/'+section+'/documenttypes/edit/'+collectionData.containerId);},function(err){$scope.error=err;if(Utilities.isArray(err.data.notifications)){for(var i=0;i0){navigationService.hasTree('templates').then(function(treeExists){if(treeExists){navigationService.syncTree({tree:'templates',path:[],forceReload:true}).then(function(syncArgs){navigationService.reloadNode(syncArgs.node);});}});}}));evts.push(eventsService.on('editors.groupsBuilder.changed',function(name,args){angularHelper.getCurrentForm($scope).$setDirty();}));$scope.$on('$destroy',function(){for(var e in evts){eventsService.unsubscribe(evts[e]);}});$scope.$watch('vm.contentType.allowedContentTypes.length + vm.contentType.allowAsRoot + vm.contentType.allowCultureVariant + vm.contentType.isElement + '+'vm.contentType.allowedTemplates.length + vm.contentType.isContainer + vm.contentType.compositeContentTypes.length',function(newVal,oldVal){if(oldVal===undefined){return;} -angularHelper.getCurrentForm($scope).$setDirty();});} -angular.module('umbraco').controller('Umbraco.Editors.DocumentTypes.EditController',DocumentTypesEditController);}());'use strict';angular.module('umbraco').controller('Umbraco.Editors.DocumentTypes.ExportController',function($scope,contentTypeResource,navigationService){$scope.export=function(){contentTypeResource.export($scope.currentNode.id);navigationService.hideMenu();};$scope.cancel=function(){navigationService.hideDialog();};});'use strict';angular.module('umbraco').controller('Umbraco.Editors.DocumentTypes.ImportController',function($scope,contentTypeResource,navigationService,Upload,umbRequestHelper){var vm=this;vm.serverErrorMessage='';vm.state='upload';vm.model={};vm.uploadStatus='';$scope.handleFiles=function(files,event){if(files&&files.length>0){$scope.upload(files[0]);}};$scope.upload=function(file){Upload.upload({url:umbRequestHelper.getApiUrl('contentTypeApiBaseUrl','Upload'),fields:{},file:file}).success(function(data,status,headers,config){if(data.notifications&&data.notifications.length>0){vm.uploadStatus='error';vm.serverErrorMessage=data.notifications[0].message;}else{vm.uploadStatus='done';vm.model=data;vm.state='confirm';}}).error(function(evt,status,headers,config){$scope.uploadStatus='error';if(status===404){$scope.serverErrorMessage='File not found';}else if(status==400){$scope.serverErrorMessage=evt.message;}else{if(evt.InnerException){$scope.serverErrorMessage=evt.InnerException.ExceptionMessage;if(evt.InnerException.StackTrace&&evt.InnerException.StackTrace.indexOf('ValidateRequestEntityLength')>0){$scope.serverErrorMessage='File too large to upload';}}else if(evt.Message){$scope.serverErrorMessage=evt.Message;}}});};$scope.import=function(){contentTypeResource.import(vm.model.tempFileName);vm.state='done';};$scope.close=function(){navigationService.hideDialog();};});'use strict';angular.module('umbraco').controller('Umbraco.Editors.DocumentTypes.MoveController',function($scope,contentTypeResource,treeService,navigationService,notificationsService,appState,eventsService){$scope.dialogTreeApi={};$scope.source=_.clone($scope.currentNode);function nodeSelectHandler(args){args.event.preventDefault();args.event.stopPropagation();if($scope.target){$scope.target.selected=false;} -$scope.target=args.node;$scope.target.selected=true;} -$scope.move=function(){$scope.busy=true;$scope.error=false;contentTypeResource.move({parentId:$scope.target.id,id:$scope.source.id}).then(function(path){$scope.error=false;$scope.success=true;$scope.busy=false;treeService.removeNode($scope.currentNode);var activeNode=appState.getTreeState('selectedNode');navigationService.syncTree({tree:'documentTypes',path:path,forceReload:true,activate:false}).then(function(args){if(activeNode){var activeNodePath=treeService.getPath(activeNode).join();navigationService.syncTree({tree:'documentTypes',path:activeNodePath,forceReload:false,activate:true});}});eventsService.emit('app.refreshEditor');},function(err){$scope.success=false;$scope.error=err;$scope.busy=false;});};$scope.onTreeInit=function(){$scope.dialogTreeApi.callbacks.treeNodeSelect(nodeSelectHandler);};$scope.close=function(){navigationService.hideDialog();};});'use strict';angular.module('umbraco').controller('Umbraco.Editors.ContentTypeContainers.RenameController',function($scope,$injector,navigationService,notificationsService,localizationService){var notificationHeader;function reportSuccessAndClose(treeName){var lastComma=$scope.currentNode.path.lastIndexOf(','),path=lastComma===-1?$scope.currentNode.path:$scope.currentNode.path.substring(0,lastComma-1);navigationService.syncTree({tree:treeName,path:path,forceReload:true,activate:true});localizationService.localize('renamecontainer_folderWasRenamed',[$scope.currentNode.name,$scope.model.folderName]).then(function(msg){notificationsService.showNotification({type:0,header:notificationHeader,message:msg});});navigationService.hideMenu();} -localizationService.localize('renamecontainer_renamed').then(function(s){notificationHeader=s;});$scope.model={folderName:$scope.currentNode.name};$scope.renameContainer=function(resourceKey,treeName){var resource=$injector.get(resourceKey);resource.renameContainer($scope.currentNode.id,$scope.model.folderName).then(function(){reportSuccessAndClose(treeName);},function(err){$scope.error=err;});};});'use strict';(function(){'use strict';function PermissionsController($scope,$timeout,contentTypeResource,iconHelper,contentTypeHelper,localizationService,overlayService){var vm=this;var childNodeSelectorOverlayTitle='';vm.contentTypes=[];vm.selectedChildren=[];vm.overlayTitle='';vm.showAllowSegmentationOption=Umbraco.Sys.ServerVariables.umbracoSettings.showAllowSegmentationForDocumentTypes||false;vm.addChild=addChild;vm.removeChild=removeChild;vm.sortChildren=sortChildren;vm.toggleAllowAsRoot=toggleAllowAsRoot;vm.toggleAllowCultureVariants=toggleAllowCultureVariants;vm.toggleAllowSegmentVariants=toggleAllowSegmentVariants;vm.canToggleIsElement=false;vm.toggleIsElement=toggleIsElement;init();function init(){localizationService.localize('contentTypeEditor_chooseChildNode').then(function(value){childNodeSelectorOverlayTitle=value;});contentTypeResource.getAll().then(function(contentTypes){vm.contentTypes=_.where(contentTypes,{isElement:false});iconHelper.formatContentTypeIcons(vm.contentTypes);vm.selectedChildren=contentTypeHelper.makeObjectArrayFromId($scope.model.allowedContentTypes,contentTypes);if($scope.model.id===0){contentTypeHelper.insertChildNodePlaceholder(vm.contentTypes,$scope.model.name,$scope.model.icon,$scope.model.id);}});if($scope.model.id>0&&!$scope.model.isElement){contentTypeResource.hasContentNodes($scope.model.id).then(function(result){vm.canToggleIsElement=!result;});}else{vm.canToggleIsElement=true;}} -function addChild($event){var childNodeSelectorOverlay={view:'itempicker',title:childNodeSelectorOverlayTitle,availableItems:vm.contentTypes,selectedItems:vm.selectedChildren,position:'target',event:$event,submit:function submit(model){vm.selectedChildren.push(model.selectedItem);$scope.model.allowedContentTypes.push(model.selectedItem.id);overlayService.close();},close:function close(){overlayService.close();}};overlayService.open(childNodeSelectorOverlay);} -function removeChild(selectedChild,index){vm.selectedChildren.splice(index,1);var selectedChildIndex=$scope.model.allowedContentTypes.indexOf(selectedChild.id);$scope.model.allowedContentTypes.splice(selectedChildIndex,1);} -function sortChildren(){$timeout(function(){$scope.model.allowedContentTypes=_.pluck(vm.selectedChildren,'id');});} -function toggleAllowAsRoot(){$scope.model.allowAsRoot=$scope.model.allowAsRoot?false:true;} -function toggleAllowCultureVariants(){$scope.model.allowCultureVariant=$scope.model.allowCultureVariant?false:true;} -function toggleAllowSegmentVariants(){$scope.model.allowSegmentVariant=$scope.model.allowSegmentVariant?false:true;} -function toggleIsElement(){$scope.model.isElement=$scope.model.isElement?false:true;}} -angular.module('umbraco').controller('Umbraco.Editors.DocumentType.PermissionsController',PermissionsController);}());'use strict';(function(){'use strict';function TemplatesController($scope,entityResource,contentTypeHelper,templateResource,contentTypeResource,$routeParams){var vm=this;vm.availableTemplates=[];vm.canCreateTemplate=false;vm.updateTemplatePlaceholder=false;vm.loadingTemplates=false;vm.isElement=$scope.model.isElement;vm.createTemplate=createTemplate;function onInit(){vm.loadingTemplates=true;entityResource.getAll('Template').then(function(templates){vm.availableTemplates=templates;if(!$routeParams.notemplate&&$scope.model.id===0){vm.updateTemplatePlaceholder=true;vm.availableTemplates=contentTypeHelper.insertTemplatePlaceholder(vm.availableTemplates);} -vm.loadingTemplates=false;checkIfTemplateExists();});} -function createTemplate(){vm.createTemplateButtonState='busy';contentTypeResource.createDefaultTemplate($scope.model.id).then(function(savedTemplate){savedTemplate.icon='icon-layout';vm.availableTemplates.push(savedTemplate);vm.canCreateTemplate=false;$scope.model.allowedTemplates.push(savedTemplate);if($scope.model.defaultTemplate===null){$scope.model.defaultTemplate=savedTemplate;} -vm.createTemplateButtonState='success';},function(){vm.createTemplateButtonState='error';});};function checkIfTemplateExists(){if($scope.model.id===0){return;} -var existingTemplate=vm.availableTemplates.find(function(availableTemplate){return availableTemplate.name===$scope.model.name||availableTemplate.placeholder;});vm.canCreateTemplate=existingTemplate?false:true;} -var unbindWatcher=$scope.$watch('model.isElement',function(newValue,oldValue){vm.isElement=newValue;});$scope.$on('$destroy',function(){unbindWatcher();});onInit();} -angular.module('umbraco').controller('Umbraco.Editors.DocumentType.TemplatesController',TemplatesController);}());'use strict';(function(){'use strict';function LanguagesEditController($scope,$q,$timeout,$location,$routeParams,overlayService,navigationService,notificationsService,localizationService,languageResource,contentEditingHelper,formHelper,eventsService){var vm=this;vm.page={};vm.showBackButton=true;vm.language={};vm.availableCultures=null;vm.breadcrumbs=[];vm.labels={};vm.initIsDefault=false;vm.showDefaultLanguageInfo=false;vm.save=save;vm.back=back;vm.goToPage=goToPage;vm.toggleMandatory=toggleMandatory;vm.toggleDefault=toggleDefault;var currCulture=null;function init(){var labelKeys=['treeHeaders_languages','languages_mandatoryLanguage','languages_mandatoryLanguageHelp','languages_defaultLanguage','languages_defaultLanguageHelp','languages_addLanguage','languages_noFallbackLanguageOption','languages_fallbackLanguageDescription','languages_fallbackLanguage','defaultdialogs_confirmSure'];localizationService.localizeMany(labelKeys).then(function(values){vm.labels.languages=values[0];vm.labels.mandatoryLanguage=values[1];vm.labels.mandatoryLanguageHelp=values[2];vm.labels.defaultLanguage=values[3];vm.labels.defaultLanguageHelp=values[4];vm.labels.addLanguage=values[5];vm.labels.noFallbackLanguageOption=values[6];vm.labels.areYouSure=values[9];$scope.properties={fallbackLanguage:{alias:'fallbackLanguage',description:values[7],label:values[8]}};if($routeParams.create){vm.page.name=vm.labels.addLanguage;}});vm.loading=true;var promises=[];promises.push(languageResource.getCultures().then(function(culturesDictionary){var cultures=[];angular.forEach(culturesDictionary,function(value,key){cultures.push({name:key,displayName:value});});vm.availableCultures=cultures;}));promises.push(languageResource.getAll().then(function(languages){vm.availableLanguages=languages.filter(function(l){return $routeParams.id!=l.id;});vm.loading=false;}));if(!$routeParams.create){promises.push(languageResource.getById($routeParams.id).then(function(lang){vm.language=lang;vm.page.name=vm.language.name;vm.initIsDefault=Utilities.copy(vm.language.isDefault);makeBreadcrumbs();currCulture=vm.language.culture;}));} -$q.all(promises,function(){vm.loading=false;});$timeout(function(){navigationService.syncTree({tree:'languages',path:'-1'});});} -function save(){if(formHelper.submitForm({scope:$scope})){vm.page.saveButtonState='busy';if(currCulture&&vm.language.culture!==currCulture){var changeCultureAlert={title:vm.labels.areYouSure,view:'views/languages/overlays/change.html',submitButtonLabelKey:'general_continue',submit:function submit(model){saveLanguage();overlayService.close();},close:function close(){overlayService.close();vm.page.saveButtonState='init';}};overlayService.open(changeCultureAlert);}else{saveLanguage();}}} -function saveLanguage(){languageResource.save(vm.language).then(function(lang){formHelper.resetForm({scope:$scope});vm.language=lang;vm.page.saveButtonState='success';localizationService.localize('speechBubbles_languageSaved').then(function(value){notificationsService.success(value);});var args={language:lang,isNew:$routeParams.create?true:false};eventsService.emit('editors.languages.languageSaved',args);back();},function(err){vm.page.saveButtonState='error';formHelper.handleError(err);});} -function back(){$location.path('settings/languages/overview');} -function goToPage(ancestor){$location.path(ancestor.path);} -function toggleMandatory(){vm.language.isMandatory=!vm.language.isMandatory;} -function toggleDefault(){if(vm.initIsDefault){return;} -vm.language.isDefault=!vm.language.isDefault;if(vm.language.isDefault){vm.showDefaultLanguageInfo=true;}else{vm.showDefaultLanguageInfo=false;}} -function makeBreadcrumbs(){vm.breadcrumbs=[{'name':vm.labels.languages,'path':'/settings/languages/overview'},{'name':vm.language.name}];} -init();} -angular.module('umbraco').controller('Umbraco.Editors.Languages.EditController',LanguagesEditController);}());'use strict';(function(){'use strict';function LanguagesOverviewController($location,$timeout,navigationService,localizationService,languageResource,eventsService,overlayService){var vm=this;vm.page={};vm.languages=[];vm.labels={};vm.addLanguage=addLanguage;vm.editLanguage=editLanguage;vm.deleteLanguage=deleteLanguage;vm.getLanguageById=function(id){for(var i=0;i 1000'},{'name':'Find all logs that are from the namespace \'Umbraco.Core\'','query':'StartsWith(SourceContext, \'Umbraco.Core\')'},{'name':'Find all logs that use a specific log message template','query':'@MessageTemplate = \'[Timing {TimingId}] {EndMessage} ({TimingDuration}ms)\''}];});var numOfErrors=logViewerResource.getNumberOfErrors(vm.startDate,vm.endDate).then(function(data){vm.numberOfErrors=data;});var logCounts=logViewerResource.getLogLevelCounts(vm.startDate,vm.endDate).then(function(data){vm.logTypeData=[];var _loop=function _loop(){var _Object$entries$_i=_slicedToArray(_Object$entries[_i],2),key=_Object$entries$_i[0],value=_Object$entries$_i[1];var index=vm.logTypeLabels.findIndex(function(x){return key.startsWith(x);});if(index>-1){vm.logTypeData[index]=value;}};for(var _i=0,_Object$entries=Object.entries(data);_i<_Object$entries.length;_i++){_loop();}});var commonMsgs=logViewerResource.getMessageTemplates(vm.startDate,vm.endDate).then(function(data){vm.commonLogMessages=data;});var logLevel=logViewerResource.getLogLevel().then(function(data){vm.logLevel=data;var index=vm.logTypeLabels.findIndex(function(x){return vm.logLevel.startsWith(x);});vm.logLevelColor=index>-1?vm.logTypeColors[index]:'#000';});$q.all([savedSearches,numOfErrors,logCounts,commonMsgs,logLevel]).then(function(){vm.loading=false;});$timeout(function(){navigationService.syncTree({tree:'logViewer',path:'-1'});});} -function searchLogQuery(logQuery){$location.path('/settings/logViewer/search').search({lq:logQuery,startDate:vm.startDate,endDate:vm.endDate});} -function findMessageTemplate(template){var logQuery='@MessageTemplate=\''+template.MessageTemplate+'\'';searchLogQuery(logQuery);} -function getDateRangeLabel(suffix){return'Log Overview for '+suffix;} -function searchErrors(){var logQuery='@Level=\'Fatal\' or @Level=\'Error\' or Has(@Exception)';searchLogQuery(logQuery);} -preFlightCheck();vm.config={enableTime:false,dateFormat:'Y-m-d',time_24hr:false,mode:'range',maxDate:'today',conjunction:' to '};vm.dateRangeChange=function(selectedDates,dateStr,instance){if(selectedDates.length>0){var startDate=selectedDates[0].toIsoDateString();var endDate=selectedDates[selectedDates.length-1].toIsoDateString();$location.path('/settings/logViewer/overview').search({startDate:startDate,endDate:endDate});}};} -angular.module('umbraco').controller('Umbraco.Editors.LogViewer.OverviewController',LogViewerOverviewController);}());'use strict';(function(){'use strict';function LogViewerSearchController($location,logViewerResource,overlayService){var vm=this;vm.loading=false;vm.logsLoading=false;vm.showBackButton=true;vm.page={};vm.logLevels=[{name:'Verbose',logTypeColor:''},{name:'Debug',logTypeColor:'gray'},{name:'Information',logTypeColor:'success'},{name:'Warning',logTypeColor:'primary'},{name:'Error',logTypeColor:'warning'},{name:'Fatal',logTypeColor:'danger'}];vm.searches=[];vm.logItems={};vm.logOptions={};vm.logOptions.orderDirection='Descending';vm.fromDatePickerConfig={pickDate:true,pickTime:true,useSeconds:false,useCurrent:false,format:'YYYY-MM-DD HH:mm',icons:{time:'icon-time',date:'icon-calendar',up:'icon-chevron-up',down:'icon-chevron-down'}};vm.toDatePickerConfig={pickDate:true,pickTime:true,useSeconds:false,format:'YYYY-MM-DD HH:mm',icons:{time:'icon-time',date:'icon-calendar',up:'icon-chevron-up',down:'icon-chevron-down'}};vm.getLogs=getLogs;vm.changePageNumber=changePageNumber;vm.search=search;vm.getFilterName=getFilterName;vm.setLogLevelFilter=setLogLevelFilter;vm.toggleOrderBy=toggleOrderBy;vm.selectSearch=selectSearch;vm.resetSearch=resetSearch;vm.findItem=findItem;vm.checkForSavedSearch=checkForSavedSearch;vm.addToSavedSearches=addToSavedSearches;vm.deleteSavedSearch=deleteSavedSearch;vm.back=back;function init(){var querystring=$location.search();if(querystring.lq){vm.logOptions.filterExpression=querystring.lq;} -if(querystring.startDate){vm.logOptions.startDate=querystring.startDate;} -if(querystring.endDate){vm.logOptions.endDate=querystring.endDate;} -vm.loading=true;logViewerResource.getSavedSearches().then(function(data){vm.searches=data;vm.loading=false;},function(){vm.searches=[{'name':'Find all logs where the Level is NOT Verbose and NOT Debug','query':'Not(@Level=\'Verbose\') and Not(@Level=\'Debug\')'},{'name':'Find all logs that has an exception property (Warning, Error & Fatal with Exceptions)','query':'Has(@Exception)'},{'name':'Find all logs that have the property \'Duration\'','query':'Has(Duration)'},{'name':'Find all logs that have the property \'Duration\' and the duration is greater than 1000ms','query':'Has(Duration) and Duration > 1000'},{'name':'Find all logs that are from the namespace \'Umbraco.Core\'','query':'StartsWith(SourceContext, \'Umbraco.Core\')'},{'name':'Find all logs that use a specific log message template','query':'@MessageTemplate = \'[Timing {TimingId}] {EndMessage} ({TimingDuration}ms)\''}];});getLogs();} -function search(){$location.search('lq',vm.logOptions.filterExpression);vm.logOptions.pageNumber=1;getLogs();} -function changePageNumber(pageNumber){vm.logOptions.pageNumber=pageNumber;getLogs();} -function getLogs(){vm.logsLoading=true;logViewerResource.getLogs(vm.logOptions).then(function(data){vm.logItems=data;vm.logsLoading=false;setLogTypeColor(vm.logItems.items);},function(err){vm.logsLoading=false;});} -function setLogTypeColor(logItems){logItems.forEach(function(logItem){return logItem.logTypeColor=vm.logLevels.find(function(x){return x.name===logItem.Level;}).logTypeColor;});} -function getFilterName(array){var name='All';var found=false;angular.forEach(array,function(item){if(item.selected){if(!found){name=item.name;found=true;}else{name=name+', '+item.name;}}});return name;} -function setLogLevelFilter(logLevel){if(!vm.logOptions.logLevels){vm.logOptions.logLevels=[];} -if(logLevel.selected){vm.logOptions.logLevels.push(logLevel.name);}else{var index=vm.logOptions.logLevels.indexOf(logLevel.name);vm.logOptions.logLevels.splice(index,1);} -getLogs();} -function toggleOrderBy(){vm.logOptions.orderDirection=vm.logOptions.orderDirection==='Descending'?'Ascending':'Descending';getLogs();} -function selectSearch(searchItem){vm.logOptions.filterExpression=searchItem.query;vm.dropdownOpen=false;search();} -function resetSearch(){vm.logOptions.filterExpression='';search();} -function findItem(key,value){if(isNaN(value)){vm.logOptions.filterExpression=key+'=\''+value+'\'';}else{vm.logOptions.filterExpression=key+'='+value;} -search();} -function checkForSavedSearch(){if(!vm.logOptions.filterExpression){return false;}else{var findQuery=_.findWhere(vm.searches,{query:vm.logOptions.filterExpression});return!findQuery?true:false;}} -function addToSavedSearches(){var overlay={title:'Save Search',subtitle:'Enter a friendly name for your search query',closeButtonLabel:'Cancel',submitButtonLabel:'Save Search',disableSubmitButton:true,view:'logviewersearch',query:vm.logOptions.filterExpression,submit:function submit(model){logViewerResource.postSavedSearch(model.name,model.query).then(function(data){vm.searches=data;overlayService.close();});},close:function close(){overlayService.close();}};overlayService.open(overlay);} -function deleteSavedSearch(searchItem){var overlay={title:'Delete Saved Search',subtitle:'Are you sure you wish to delete?',closeButtonLabel:'Cancel',submitButtonLabel:'Delete Saved Search',submitButtonStyle:'danger',view:'default',submit:function submit(model){logViewerResource.deleteSavedSearch(searchItem.name,searchItem.query).then(function(data){vm.searches=data;overlayService.close();});},close:function close(){overlayService.close();}};overlayService.open(overlay);} -function back(){$location.path('settings/logViewer/overview').search('lq',null);} -init();} -angular.module('umbraco').controller('Umbraco.Editors.LogViewer.SearchController',LogViewerSearchController);}());'use strict';(function(){'use strict';function ParameterEditorController($scope,formHelper,editorService){var vm=this;vm.submit=submit;vm.close=close;vm.openMacroParameterPicker=openMacroParameterPicker;function openMacroParameterPicker(parameter){vm.focusOnMandatoryField=false;var overlay={parameter:$scope.model.parameter,view:'views/common/infiniteeditors/macroparameterpicker/macroparameterpicker.html',size:'small',submit:function submit(model){vm.focusOnMandatoryField=true;parameter.editor=model.parameter.editor;editorService.close();},close:function close(model){editorService.close();}};editorService.open(overlay);} -function submit(){console.log('model',$scope.model);if($scope.model&&$scope.model.submit&&formHelper.submitForm({scope:$scope})){$scope.model.submit($scope.model);}} -function close(){if($scope.model&&$scope.model.close){$scope.model.close();}}} -angular.module('umbraco').controller('Umbraco.Editors.ParameterEditorController',ParameterEditorController);}());'use strict';function MacrosCreateController($scope,$location,macroResource,navigationService,notificationsService,formHelper,appState){var vm=this;vm.itemKey='';function createItem(){if(formHelper.submitForm({scope:$scope,formCtrl:this.createMacroForm})){var node=$scope.currentNode;macroResource.createMacro(vm.itemKey).then(function(data){navigationService.hideMenu();var currPath=node.path?node.path:'-1';navigationService.syncTree({tree:'macros',path:currPath+','+data,forceReload:true,activate:true});formHelper.resetForm({scope:$scope});var currentSection=appState.getSectionState('currentSection');$location.path('/'+currentSection+'/macros/edit/'+data);},function(err){if(err.data&&err.data.message){notificationsService.error(err.data.message);navigationService.hideMenu();}});}} -vm.createItem=createItem;} -angular.module('umbraco').controller('Umbraco.Editors.Macros.CreateController',MacrosCreateController);'use strict';function MacrosDeleteController($scope,macroResource,navigationService,treeService){var vm=this;vm.name=$scope.currentNode.name;function performDelete(){$scope.currentNode.loading=true;macroResource.deleteById($scope.currentNode.id).then(function(){$scope.currentNode.loading=false;treeService.removeNode($scope.currentNode);navigationService.hideMenu();});} -function cancel(){navigationService.hideDialog();} -vm.performDelete=performDelete;vm.cancel=cancel;} -angular.module('umbraco').controller('Umbraco.Editors.Macros.DeleteController',MacrosDeleteController);'use strict';function MacrosEditController($scope,$q,$routeParams,macroResource,editorState,navigationService,formHelper,contentEditingHelper,localizationService,angularHelper){var vm=this;vm.promises={};vm.header={};vm.header.editorfor='general_macro';vm.header.setPageTitle=true;vm.page={};vm.page.loading=false;vm.page.saveButtonState='init';vm.page.menu={};vm.labels={};function toggleValue(key){vm.macro[key]=!vm.macro[key];} -vm.toggle=toggleValue;function saveMacro(){if(formHelper.submitForm({scope:$scope,statusMessage:'Saving...'})){vm.page.saveButtonState='busy';macroResource.saveMacro(vm.macro).then(function(data){formHelper.resetForm({scope:$scope,notifications:data.notifications});bindMacro(data);vm.page.saveButtonState='success';},function(error){contentEditingHelper.handleSaveError({err:error});vm.page.saveButtonState='error';});}} -vm.save=saveMacro;function setFormDirty(){var currentForm=angularHelper.getCurrentForm($scope);if(currentForm){currentForm.$setDirty();}} -vm.setDirty=setFormDirty;function getPartialViews(){var deferred=$q.defer();macroResource.getPartialViews().then(function(data){deferred.resolve(data);},function(){deferred.reject();});return deferred.promise;} -function getMacro(){var deferred=$q.defer();macroResource.getById($routeParams.id).then(function(data){deferred.resolve(data);},function(){deferred.reject();});return deferred.promise;} -function bindMacro(data){vm.macro=data;if(vm.macro&&vm.macro.view){vm.macro.node={icon:'icon-article',name:vm.macro.view};} -editorState.set(vm.macro);navigationService.syncTree({tree:'macros',path:vm.macro.path,forceReload:true}).then(function(syncArgs){vm.page.menu.currentNode=syncArgs.node;});} -function init(){vm.page.loading=true;vm.promises['partialViews']=getPartialViews();vm.promises['macro']=getMacro();vm.views=[];vm.node=null;$q.all(vm.promises).then(function(values){var keys=Object.keys(values);for(var i=0;i div.control-group',handle:'.handle',tolerance:'pointer',update:function update(e,ui){setDirty();}};function remove(parameter,evt){evt.preventDefault();$scope.model.macro.parameters=_.without($scope.model.macro.parameters,parameter);setDirty();} -function add(evt){evt.preventDefault();openOverlay({},vm.labels.addParameter,function(newParameter){if(!$scope.model.macro.parameters){$scope.model.macro.parameters=[];} -$scope.model.macro.parameters.push(newParameter);setDirty();});} -function edit(parameter,evt){evt.preventDefault();var promises=[getParameterEditorByAlias(parameter.editor)];$q.all(promises).then(function(values){parameter.dataTypeName=values[0].name;openOverlay(parameter,vm.labels.editParameter,function(newParameter){parameter.key=newParameter.key;parameter.label=newParameter.label;parameter.editor=newParameter.editor;setDirty();});});} -function getParameterEditorByAlias(alias){var deferred=$q.defer();macroResource.getParameterEditorByAlias(alias).then(function(data){deferred.resolve(data);},function(){deferred.reject();});return deferred.promise;} -function openOverlay(parameter,title,onSubmit){var ruleDialog={title:title,parameter:_.clone(parameter),view:'views/macros/infiniteeditors/parameter.html',size:'small',submit:function submit(model){onSubmit(model.parameter);editorService.close();},close:function close(){editorService.close();}};editorService.open(ruleDialog);} -function setDirty(){$scope.model.setDirty();} -function init(){localizationService.localizeMany(['macro_addParameter','macro_editParameter']).then(function(data){vm.labels.addParameter=data[0];vm.labels.editParameter=data[1];});} -init();} -angular.module('umbraco').controller('Umbraco.Editors.Macros.ParametersController',MacrosParametersController);'use strict';function MacrosSettingsController($scope,editorService,localizationService){var vm=this;$scope.model.openViewPicker=openViewPicker;$scope.model.removeMacroView=removeMacroView;var labels={};localizationService.localizeMany(['macro_selectViewFile']).then(function(data){labels.selectViewFile=data[0];});function openViewPicker(){var controlPicker={title:labels.selectViewFile,section:'settings',treeAlias:'partialViewMacros',entityType:'partialView',onlyInitialized:false,filter:function filter(i){if(i.name.indexOf('.cshtml')===-1&&i.name.indexOf('.vbhtml')===-1){return true;}},filterCssClass:'not-allowed',select:function select(node){var id=decodeURIComponent(node.id.replace(/\+/g,' '));$scope.model.macro.view='~/Views/MacroPartials/'+id;$scope.model.macro.node={icon:node.icon,name:$scope.model.macro.view};editorService.close();},close:function close(){editorService.close();}};editorService.treePicker(controlPicker);} -function removeMacroView(){$scope.model.macro.node=null;$scope.model.macro.view=null;} -function init(){} -init();} -angular.module('umbraco').controller('Umbraco.Editors.Macros.SettingsController',MacrosSettingsController);'use strict';(function(){'use strict';function MediaAppContentController($scope){var vm=this;} -angular.module('umbraco').controller('Umbraco.Editors.Media.Apps.ContentController',MediaAppContentController);}());'use strict';function mediaCreateController($scope,$location,mediaTypeResource,iconHelper,navigationService,authResource,mediaResource){function initialize(){$scope.allowedTypes=null;mediaTypeResource.getAllowedTypes($scope.currentNode.id).then(function(data){$scope.allowedTypes=iconHelper.formatContentTypeIcons(data);});if($scope.currentNode.id>-1){authResource.getCurrentUser().then(function(currentUser){if(currentUser.allowedSections.indexOf('settings')>-1){$scope.hasSettingsAccess=true;mediaResource.getById($scope.currentNode.id).then(function(data){$scope.mediaTypeId=data.contentType.id;});}});}} -$scope.createMediaItem=function(docType){$location.path('/media/media/edit/'+$scope.currentNode.id).search('doctype',docType.alias).search('create','true');navigationService.hideMenu();};$scope.close=function(){navigationService.hideMenu();};$scope.closeDialog=function(){var showMenu=true;navigationService.hideDialog(showMenu);};var unbindModelWatcher=$scope.$watch('currentNode',initialize);$scope.$on('$destroy',function(){unbindModelWatcher();});} -angular.module('umbraco').controller('Umbraco.Editors.Media.CreateController',mediaCreateController);'use strict';function MediaDeleteController($scope,mediaResource,treeService,navigationService,editorState,$location,overlayService){$scope.performDelete=function(){if($scope.busy){return false;} -$scope.currentNode.loading=true;$scope.busy=true;mediaResource.deleteById($scope.currentNode.id).then(function(){$scope.currentNode.loading=false;var rootNode=treeService.getTreeRoot($scope.currentNode);treeService.removeNode($scope.currentNode);if(rootNode){var recycleBin=treeService.getDescendantNode(rootNode,-21);if(recycleBin){recycleBin.hasChildren=true;if(recycleBin.expanded){treeService.loadNodeChildren({node:recycleBin,section:'media'});}}} -if(editorState.current&&editorState.current.id==$scope.currentNode.id){var location='/media';if($scope.currentNode.parentId.toString()==='-21') -location='/media/media/recyclebin';else if($scope.currentNode.parentId.toString()!=='-1') -location='/media/media/edit/'+$scope.currentNode.parentId;$location.path(location);} -$scope.success=true;},function(err){$scope.currentNode.loading=false;$scope.busy=false;if(err.status&&err.status>=500){overlayService.ysod(err);}});};$scope.close=function(){navigationService.hideDialog();};} -angular.module('umbraco').controller('Umbraco.Editors.Media.DeleteController',MediaDeleteController);'use strict';function mediaEditController($scope,$routeParams,$q,appState,mediaResource,entityResource,navigationService,notificationsService,localizationService,serverValidationManager,contentEditingHelper,fileManager,formHelper,editorState,umbRequestHelper,$http,eventsService,$location){var evts=[];var nodeId=null;var create=false;var infiniteMode=$scope.model&&$scope.model.infiniteMode;if(infiniteMode&&$scope.model.id){nodeId=$scope.model.id;}else{nodeId=$routeParams.id;} -if(infiniteMode){create=$scope.model.create;}else{create=$routeParams.create;} -$scope.currentSection=appState.getSectionState('currentSection');$scope.currentNode=null;$scope.header={};$scope.header.setPageTitle=$scope.currentSection==='media';$scope.page={};$scope.page.loading=false;$scope.page.menu={};$scope.page.menu.currentSection=appState.getSectionState('currentSection');$scope.page.menu.currentNode=null;$scope.page.listViewPath=null;$scope.page.saveButtonState='init';$scope.page.submitButtonLabelKey='buttons_save';$scope.app=null;if(create){$scope.page.loading=true;mediaResource.getScaffold(nodeId,$routeParams.doctype).then(function(data){$scope.content=data;init();$scope.page.loading=false;});}else{$scope.page.loading=true;loadMedia().then(function(){$scope.page.loading=false;});} -function init(){var content=$scope.content;var isAppPresent=false;if($scope.app){content.apps.forEach(function(app){if(app===$scope.app){isAppPresent=true;}});if(isAppPresent===false){content.apps.forEach(function(app){if(app.alias===$scope.app.alias){isAppPresent=true;app.active=true;$scope.appChanged(app);}});}} -if(isAppPresent===false){content.apps[0].active=true;$scope.appChanged(content.apps[0]);} -editorState.set($scope.content);bindEvents();} -function bindEvents(){for(var e in evts){eventsService.unsubscribe(evts[e]);} -evts.push(eventsService.on('editors.mediaType.saved',function(name,args){if(args&&args.mediaType&&args.mediaType.key===$scope.content.contentType.key){$scope.page.loading=true;loadMedia().then(function(){$scope.page.loading=false;});}}));} -$scope.page.submitButtonLabelKey='buttons_save';function syncTreeNode(content,path,initialLoad){if(infiniteMode){return;} -if(!$scope.content.isChildOfListView){navigationService.syncTree({tree:'media',path:path.split(','),forceReload:initialLoad!==true}).then(function(syncArgs){$scope.page.menu.currentNode=syncArgs.node;});}else if(initialLoad===true){navigationService.syncTree({tree:'media',path:path.substring(0,path.lastIndexOf(',')).split(','),forceReload:initialLoad!==true});umbRequestHelper.resourcePromise($http.get(content.treeNodeUrl),'Failed to retrieve data for child node '+content.id).then(function(node){$scope.page.menu.currentNode=node;});}} -function showValidationNotification(){localizationService.localizeMany(['speechBubbles_validationFailedHeader','speechBubbles_validationFailedMessage']).then(function(data){notificationsService.error(data[0],data[1]);});} -$scope.save=function(){if(formHelper.submitForm({scope:$scope})){$scope.page.saveButtonState='busy';mediaResource.save($scope.content,create,fileManager.getFiles()).then(function(data){formHelper.resetForm({scope:$scope});if(infiniteMode&&$scope.model.submit){$scope.model.mediaNode=$scope.content;$scope.model.submit($scope.model);}else{contentEditingHelper.handleSuccessfulSave({scope:$scope,savedContent:data,rebindCallback:contentEditingHelper.reBindChangedProperties($scope.content,data)});editorState.set($scope.content);syncTreeNode($scope.content,data.path);$scope.page.saveButtonState='success';init();}},function(err){contentEditingHelper.handleSaveError({err:err,rebindCallback:contentEditingHelper.reBindChangedProperties($scope.content,err.data)});editorState.set($scope.content);$scope.page.saveButtonState='error';});}else{showValidationNotification();}};function loadMedia(){return mediaResource.getById(nodeId).then(function(data){$scope.content=data;if(data.isChildOfListView&&data.trashed===false){$scope.page.listViewPath=$routeParams.page?'/media/media/edit/'+data.parentId+'?page='+$routeParams.page:'/media/media/edit/'+data.parentId;} -editorState.set($scope.content);serverValidationManager.notifyAndClearAllSubscriptions();if(!infiniteMode){syncTreeNode($scope.content,data.path,true);} -if($scope.content.parentId&&$scope.content.parentId!==-1&&$scope.content.parentId!==-21){entityResource.getAncestors(nodeId,'media').then(function(anc){$scope.ancestors=anc;});} -init();$scope.page.loading=false;$q.resolve($scope.content);});} -$scope.close=function(){if($scope.model.close){$scope.model.close($scope.model);}};$scope.appChanged=function(app){$scope.app=app;if(infiniteMode){$scope.page.submitButtonLabelKey='buttons_saveAndClose';}};$scope.showBack=function(){return!infiniteMode&&!!$scope.page.listViewPath;};$scope.onBack=function(){if($scope.page.listViewPath){$location.path($scope.page.listViewPath.split('?')[0]);}};$scope.$on('$destroy',function(){for(var e in evts){eventsService.unsubscribe(evts[e]);}});} -angular.module('umbraco').controller('Umbraco.Editors.Media.EditController',mediaEditController);'use strict';function MediaEmptyRecycleBinController($scope,mediaResource,treeService,navigationService,notificationsService,$route){$scope.busy=false;$scope.performDelete=function(){$scope.busy=true;$scope.currentNode.loading=true;mediaResource.emptyRecycleBin($scope.currentNode.id).then(function(result){$scope.busy=false;$scope.currentNode.loading=false;treeService.removeChildNodes($scope.currentNode);navigationService.hideMenu();$route.reload();});};$scope.cancel=function(){navigationService.hideDialog();};} -angular.module('umbraco').controller('Umbraco.Editors.Media.EmptyRecycleBinController',MediaEmptyRecycleBinController);'use strict';angular.module('umbraco').controller('Umbraco.Editors.Media.MoveController',function($scope,userService,eventsService,mediaResource,appState,treeService,navigationService){$scope.dialogTreeApi={};$scope.source=_.clone($scope.currentNode);$scope.busy=false;$scope.searchInfo={searchFromId:null,searchFromName:null,showSearch:false,results:[],selectedSearchResults:[]};$scope.treeModel={hideHeader:false};userService.getCurrentUser().then(function(userData){$scope.treeModel.hideHeader=userData.startMediaIds.length>0&&userData.startMediaIds.indexOf(-1)==-1;});function treeLoadedHandler(args){if($scope.source&&$scope.source.path){$scope.dialogTreeApi.syncTree({path:$scope.source.path,activate:false});}} -function nodeSelectHandler(args){if(args&&args.event){args.event.preventDefault();args.event.stopPropagation();} -eventsService.emit('editors.media.moveController.select',args);if($scope.target){$scope.target.selected=false;} -$scope.target=args.node;$scope.target.selected=true;} -function nodeExpandedHandler(args){if(args.node.metaData.isContainer){openMiniListView(args.node);}} -$scope.onTreeInit=function(){$scope.dialogTreeApi.callbacks.treeLoaded(treeLoadedHandler);$scope.dialogTreeApi.callbacks.treeNodeSelect(nodeSelectHandler);$scope.dialogTreeApi.callbacks.treeNodeExpanded(nodeExpandedHandler);};$scope.close=function(){navigationService.hideDialog();};$scope.hideSearch=function(){$scope.searchInfo.showSearch=false;$scope.searchInfo.searchFromId=null;$scope.searchInfo.searchFromName=null;$scope.searchInfo.results=[];};$scope.selectResult=function(evt,result){result.selected=result.selected===true?false:true;nodeSelectHandler({event:evt,node:result});};$scope.onSearchResults=function(results){$scope.searchInfo.results=results;$scope.searchInfo.showSearch=true;};$scope.move=function(){$scope.busy=true;mediaResource.move({parentId:$scope.target.id,id:$scope.source.id}).then(function(path){$scope.busy=false;$scope.error=false;$scope.success=true;treeService.removeNode($scope.currentNode);var activeNode=appState.getTreeState('selectedNode');navigationService.syncTree({tree:'media',path:path,forceReload:true,activate:false}).then(function(args){if(activeNode){var activeNodePath=treeService.getPath(activeNode).join();navigationService.syncTree({tree:'media',path:activeNodePath,forceReload:false,activate:true});}});},function(err){$scope.success=false;$scope.error=err;});};$scope.selectListViewNode=function(node){node.selected=node.selected===true?false:true;nodeSelectHandler({node:node});};$scope.closeMiniListView=function(){$scope.miniListView=undefined;};function openMiniListView(node){$scope.miniListView=node;}});'use strict';function MediaRecycleBinController($scope,$routeParams,mediaResource,navigationService,localizationService){$scope.page={};$scope.page.name='Recycle Bin';$scope.page.nameLocked=true;$scope.listViewPath=null;$routeParams.id='-21';mediaResource.getRecycleBin().then(function(result){$scope.content=result;});navigationService.syncTree({tree:'media',path:['-1',$routeParams.id],forceReload:false});localizePageName();function localizePageName(){var pageName='general_recycleBin';localizationService.localize(pageName).then(function(value){$scope.page.name=value;});}} -angular.module('umbraco').controller('Umbraco.Editors.Media.RecycleBinController',MediaRecycleBinController);'use strict';angular.module('umbraco').controller('Umbraco.Editors.Media.RestoreController',function($scope,relationResource,mediaResource,entityResource,navigationService,appState,treeService,userService,localizationService){$scope.source=_.clone($scope.currentNode);$scope.error=null;$scope.loading=true;$scope.moving=false;$scope.success=false;$scope.dialogTreeApi={};$scope.searchInfo={showSearch:false,results:[],selectedSearchResults:[]};$scope.treeModel={hideHeader:false};userService.getCurrentUser().then(function(userData){$scope.treeModel.hideHeader=userData.startContentIds.length>0&&userData.startContentIds.indexOf(-1)==-1;});$scope.labels={};localizationService.localizeMany(['treeHeaders_media']).then(function(data){$scope.labels.treeRoot=data[0];});function nodeSelectHandler(args){if(args&&args.event){args.event.preventDefault();args.event.stopPropagation();} -if($scope.target){$scope.target.selected=false;} -$scope.target=args.node;$scope.target.selected=true;} -function nodeExpandedHandler(args){if(args.node.metaData.isContainer){openMiniListView(args.node);}} -$scope.hideSearch=function(){$scope.searchInfo.showSearch=false;$scope.searchInfo.results=[];};$scope.selectResult=function(evt,result){result.selected=result.selected===true?false:true;nodeSelectHandler({event:evt,node:result});};$scope.onSearchResults=function(results){$scope.searchInfo.results=results;$scope.searchInfo.showSearch=true;};$scope.onTreeInit=function(){$scope.dialogTreeApi.callbacks.treeNodeSelect(nodeSelectHandler);$scope.dialogTreeApi.callbacks.treeNodeExpanded(nodeExpandedHandler);};$scope.selectListViewNode=function(node){node.selected=node.selected===true?false:true;nodeSelectHandler({node:node});};$scope.closeMiniListView=function(){$scope.miniListView=undefined;};function openMiniListView(node){$scope.miniListView=node;} -relationResource.getByChildId($scope.source.id,'relateParentMediaFolderOnDelete').then(function(data){$scope.loading=false;if(!data.length){$scope.moving=true;return;} -$scope.relation=data[0];if($scope.relation.parentId===-1){$scope.target={id:-1,name:$scope.labels.treeRoot};}else{$scope.loading=true;entityResource.getById($scope.relation.parentId,'media').then(function(data){$scope.loading=false;$scope.target=data;if($scope.target.path.indexOf('-21')!==-1){$scope.moving=true;$scope.target=null;}},function(err){$scope.loading=false;$scope.error=err;});}},function(err){$scope.loading=false;$scope.error=err;});$scope.restore=function(){$scope.loading=true;mediaResource.move({parentId:$scope.target.id,id:$scope.source.id}).then(function(path){$scope.loading=false;$scope.success=true;treeService.removeNode($scope.currentNode);var activeNode=appState.getTreeState('selectedNode');navigationService.syncTree({tree:'media',path:path,forceReload:true,activate:false}).then(function(args){if(activeNode){var activeNodePath=treeService.getPath(activeNode).join();navigationService.syncTree({tree:'media',path:activeNodePath,forceReload:false,activate:true});}});},function(err){$scope.loading=false;$scope.error=err;});};$scope.close=function(){navigationService.hideDialog();};});'use strict';(function(){'use strict';function MediaSortController($scope,$filter,mediaResource,navigationService,eventsService){var vm=this;var id=$scope.currentNode.id;vm.loading=false;vm.children=[];vm.saveButtonState='init';vm.sortOrder={};vm.sortableOptions={distance:10,tolerance:'pointer',opacity:0.7,scroll:true,cursor:'move',helper:fixSortableHelper,update:function update(){vm.sortOrder.column='';vm.sortOrder.reverse=false;}};vm.save=save;vm.sort=sort;vm.close=close;function onInit(){vm.loading=true;mediaResource.getChildren(id).then(function(data){vm.children=data.items;vm.loading=false;});} -function save(){vm.saveButtonState='busy';var args={parentId:id,sortedIds:_.map(vm.children,function(child){return child.id;})};mediaResource.sort(args).then(function(){navigationService.syncTree({tree:'media',path:$scope.currentNode.path,forceReload:true}).then(function(){return navigationService.reloadNode($scope.currentNode);});eventsService.emit('sortCompleted',{id:id});vm.saveButtonState='success';},function(error){vm.error=error;vm.saveButtonState='error';});} -function fixSortableHelper(e,ui){ui.children().each(function(){$(this).width($(this).width());});return ui;} -function sort(column){if(vm.sortOrder.column===column){vm.sortOrder.reverse=!vm.sortOrder.reverse;}else{vm.sortOrder.column=column;vm.sortOrder.reverse=false;} -vm.children=$filter('orderBy')(vm.children,vm.sortOrder.column,vm.sortOrder.reverse);} -function close(){navigationService.hideDialog();} -onInit();} -angular.module('umbraco').controller('Umbraco.Editors.Media.SortController',MediaSortController);}());'use strict';angular.module('umbraco').controller('Umbraco.Editors.MediaTypes.CopyController',function($scope,mediaTypeResource,treeService,navigationService,notificationsService,appState,eventsService){$scope.dialogTreeApi={};$scope.source=_.clone($scope.currentNode);function nodeSelectHandler(args){args.event.preventDefault();args.event.stopPropagation();if($scope.target){$scope.target.selected=false;} -$scope.target=args.node;$scope.target.selected=true;} -$scope.copy=function(){$scope.busy=true;$scope.error=false;mediaTypeResource.copy({parentId:$scope.target.id,id:$scope.source.id}).then(function(path){$scope.error=false;$scope.success=true;$scope.busy=false;var activeNode=appState.getTreeState('selectedNode');navigationService.syncTree({tree:'mediaTypes',path:path,forceReload:true,activate:false}).then(function(args){if(activeNode){var activeNodePath=treeService.getPath(activeNode).join();navigationService.syncTree({tree:'mediaTypes',path:activeNodePath,forceReload:false,activate:true});}});},function(err){$scope.success=false;$scope.error=err;$scope.busy=false;});};$scope.onTreeInit=function(){$scope.dialogTreeApi.callbacks.treeNodeSelect(nodeSelectHandler);};$scope.close=function(){navigationService.hideDialog();};});'use strict';function MediaTypesCreateController($scope,$location,navigationService,mediaTypeResource,formHelper,appState,localizationService){$scope.model={folderName:'',creatingFolder:false};var node=$scope.currentNode;$scope.showCreateFolder=function(){$scope.model.creatingFolder=true;};$scope.createContainer=function(){if(formHelper.submitForm({scope:$scope,formCtrl:this.createFolderForm})){mediaTypeResource.createContainer(node.id,$scope.model.folderName).then(function(folderId){navigationService.hideMenu();var currPath=node.path?node.path:'-1';navigationService.syncTree({tree:'mediatypes',path:currPath+','+folderId,forceReload:true,activate:true});formHelper.resetForm({scope:$scope});var section=appState.getSectionState('currentSection');},function(err){$scope.error=err;});};};$scope.createMediaType=function(){$location.search('create',null);$location.path('/settings/mediatypes/edit/'+node.id).search('create','true');navigationService.hideMenu();};$scope.close=function(){var showMenu=true;navigationService.hideDialog(showMenu);};} -angular.module('umbraco').controller('Umbraco.Editors.MediaTypes.CreateController',MediaTypesCreateController);'use strict';function MediaTypesDeleteController($scope,mediaTypeResource,treeService,navigationService,localizationService){$scope.performDelete=function(){$scope.currentNode.loading=true;mediaTypeResource.deleteById($scope.currentNode.id).then(function(){$scope.currentNode.loading=false;var rootNode=treeService.getTreeRoot($scope.currentNode);treeService.removeNode($scope.currentNode);navigationService.hideMenu();});};$scope.performContainerDelete=function(){$scope.currentNode.loading=true;mediaTypeResource.deleteContainerById($scope.currentNode.id).then(function(){$scope.currentNode.loading=false;var rootNode=treeService.getTreeRoot($scope.currentNode);treeService.removeNode($scope.currentNode);navigationService.hideMenu();});};$scope.cancel=function(){navigationService.hideDialog();};$scope.labels={};localizationService.format(['contentTypeEditor_yesDelete','contentTypeEditor_andAllMediaItems'],'%0% '+$scope.currentNode.name+' %1%').then(function(data){$scope.labels.deleteConfirm=data;});} -angular.module('umbraco').controller('Umbraco.Editors.MediaTypes.DeleteController',MediaTypesDeleteController);'use strict';(function(){'use strict';function MediaTypesEditController($scope,$routeParams,mediaTypeResource,dataTypeResource,editorState,contentEditingHelper,formHelper,navigationService,iconHelper,contentTypeHelper,notificationsService,$q,localizationService,overlayHelper,eventsService,angularHelper){var vm=this;var evts=[];var mediaTypeId=$routeParams.id;var create=$routeParams.create;var infiniteMode=$scope.model&&$scope.model.infiniteMode;vm.save=save;vm.close=close;vm.currentNode=null;vm.header={};vm.header.editorfor='content_mediatype';vm.header.setPageTitle=true;vm.contentType={};vm.page={};vm.page.loading=false;vm.page.saveButtonState='init';vm.labels={};vm.saveButtonKey='buttons_save';vm.generateModelsKey='buttons_saveAndGenerateModels';onInit();function onInit(){if(infiniteMode){mediaTypeId=$scope.model.id;create=$scope.model.create;vm.saveButtonKey='buttons_saveAndClose';vm.generateModelsKey='buttons_generateModelsAndClose';}} -var labelKeys=['general_design','general_listView','general_rights','main_sections','shortcuts_navigateSections','shortcuts_addGroup','shortcuts_addProperty','shortcuts_addEditor','shortcuts_editDataType','shortcuts_toggleListView','shortcuts_toggleAllowAsRoot','shortcuts_addChildNode'];localizationService.localizeMany(labelKeys).then(function(values){vm.labels.design=values[0];vm.labels.listview=values[1];vm.labels.permissions=values[2];vm.labels.sections=values[3];vm.labels.navigateSections=values[4];vm.labels.addGroup=values[5];vm.labels.addProperty=values[6];vm.labels.addEditor=values[7];vm.labels.editDataType=values[8];vm.labels.toggleListView=values[9];vm.labels.allowAsRoot=values[10];vm.labels.addChildNode=values[11];vm.page.navigation=[{'name':vm.labels.design,'alias':'design','icon':'icon-document-dashed-line','view':'views/mediatypes/views/design/design.html'},{'name':vm.labels.listview,'alias':'listView','icon':'icon-list','view':'views/mediatypes/views/listview/listview.html'},{'name':vm.labels.permissions,'alias':'permissions','icon':'icon-keychain','view':'views/mediatypes/views/permissions/permissions.html'}];vm.page.keyboardShortcutsOverview=[{'name':vm.labels.sections,'shortcuts':[{'description':vm.labels.navigateSections,'keys':[{'key':'1'},{'key':'3'}],'keyRange':true}]},{'name':vm.labels.design,'shortcuts':[{'description':vm.labels.addGroup,'keys':[{'key':'alt'},{'key':'shift'},{'key':'g'}]},{'description':vm.labels.addProperty,'keys':[{'key':'alt'},{'key':'shift'},{'key':'p'}]},{'description':vm.labels.addEditor,'keys':[{'key':'alt'},{'key':'shift'},{'key':'e'}]},{'description':vm.labels.editDataType,'keys':[{'key':'alt'},{'key':'shift'},{'key':'d'}]}]},{'name':vm.labels.listview,'shortcuts':[{'description':vm.labels.toggleListView,'keys':[{'key':'alt'},{'key':'shift'},{'key':'l'}]}]},{'name':vm.labels.permissions,'shortcuts':[{'description':vm.labels.allowAsRoot,'keys':[{'key':'alt'},{'key':'shift'},{'key':'r'}]},{'description':vm.labels.addChildNode,'keys':[{'key':'alt'},{'key':'shift'},{'key':'c'}]}]}];initializeActiveNavigationPanel();});function initializeActiveNavigationPanel(){var initialViewSetFromRouteParams=false;var view=$routeParams.view;if(view){var viewPath='views/mediatypes/views/'+view+'/'+view+'.html';for(var i=0;i=0;});vm.templates=templates;});entityResource.getAll('Stylesheet').then(function(stylesheets){stylesheets.forEach(function(stylesheet){stylesheet.selected=vm.package.stylesheets.indexOf(stylesheet.name)>=0;});vm.stylesheets=stylesheets;});entityResource.getAll('Macro').then(function(macros){macros.forEach(function(macro){macro.id=macro.id.toString();macro.selected=vm.package.macros.indexOf(macro.id)!==-1;});vm.macros=macros;});entityResource.getAll('Language').then(function(languages){languages.forEach(function(language){language.id=language.id.toString();language.selected=vm.package.languages.indexOf(language.id)!==-1;});vm.languages=languages;});entityResource.getAll('DictionaryItem').then(function(dictionaryItems){dictionaryItems.forEach(function(dictionaryItem){dictionaryItem.id=dictionaryItem.id.toString();dictionaryItem.selected=vm.package.dictionaryItems.indexOf(dictionaryItem.id)!==-1;});vm.dictionaryItems=dictionaryItems;});entityResource.getAll('DataType').then(function(dataTypes){dataTypes.forEach(function(dataType){dataType.id=dataType.id.toString();dataType.selected=vm.package.dataTypes.indexOf(dataType.id)!==-1;});vm.dataTypes=dataTypes;});} -function downloadFile(id){var url=umbRequestHelper.getApiUrl('packageApiBaseUrl','DownloadCreatedPackage',{id:id});umbRequestHelper.downloadFile(url).then(function(){});} -function back(){$location.path('packages/packages/created').search('create',null).search('packageId',null);} -function createOrUpdatePackage(editPackageForm){var contributors=vm.contributorsEditor.value.map(function(o){return o.value;});vm.package.contributors=contributors;if(formHelper.submitForm({formCtrl:editPackageForm,scope:$scope})){vm.buttonState='busy';packageResource.savePackage(vm.package).then(function(updatedPackage){vm.package=updatedPackage;vm.buttonState='success';formHelper.resetForm({scope:$scope});if(create){$location.path('packages/packages/edit/'+vm.package.id).search('create',null);$location.replace();}},function(err){formHelper.handleError(err);vm.buttonState='error';});}} -function removeContentItem(){vm.package.contentNodeId=null;} -function openContentPicker(){var contentPicker={submit:function submit(model){if(model.selection&&model.selection.length>0){vm.package.contentNodeId=model.selection[0].id.toString();vm.contentNodeDisplayModel=model.selection[0];} -editorService.close();},close:function close(){editorService.close();}};editorService.contentPicker(contentPicker);} -function openFilePicker(){var selection=Utilities.copy(vm.package.files);var filePicker={title:'Select files',section:'settings',treeAlias:'files',entityType:'file',multiPicker:true,isDialog:true,select:function select(node){node.selected=!node.selected;var id=decodeURIComponent(node.id.replace(/\+/g,' '));var index=selection.indexOf(id);if(node.selected){if(index===-1){selection.push(id);}}else{selection.splice(index,1);}},submit:function submit(){vm.package.files=selection;editorService.close();},close:function close(){editorService.close();}};editorService.treePicker(filePicker);} -function removeFile(index){vm.package.files.splice(index,1);} -function openViewPicker(){var controlPicker={title:'Select view',section:'settings',treeAlias:'files',entityType:'file',onlyInitialized:false,filter:function filter(i){if(i.name.indexOf('.html')===-1&&i.name.indexOf('.htm')===-1){return true;}},filterCssClass:'not-allowed',select:function select(node){var id=decodeURIComponent(node.id.replace(/\+/g,' '));vm.package.packageView=id;editorService.close();},close:function close(){editorService.close();}};editorService.treePicker(controlPicker);} -function removePackageView(){vm.package.packageView=null;} -function selectDocumentType(doctype){var index=vm.package.documentTypes.indexOf(doctype.id);if(index===-1){vm.package.documentTypes.push(doctype.id);}else{vm.package.documentTypes.splice(index,1);}} -function selectTemplate(template){var index=vm.package.templates.indexOf(template.id);if(index===-1){vm.package.templates.push(template.id);}else{vm.package.templates.splice(index,1);}} -function selectStyleSheet(stylesheet){var index=vm.package.stylesheets.indexOf(stylesheet.name);if(index===-1){vm.package.stylesheets.push(stylesheet.name);}else{vm.package.stylesheets.splice(index,1);}} -function selectMacro(macro){var index=vm.package.macros.indexOf(macro.id);if(index===-1){vm.package.macros.push(macro.id);}else{vm.package.macros.splice(index,1);}} -function selectLanguage(language){var index=vm.package.languages.indexOf(language.id);if(index===-1){vm.package.languages.push(language.id);}else{vm.package.languages.splice(index,1);}} -function selectDictionaryItem(dictionaryItem){var index=vm.package.dictionaryItems.indexOf(dictionaryItem.id);if(index===-1){vm.package.dictionaryItems.push(dictionaryItem.id);}else{vm.package.dictionaryItems.splice(index,1);}} -function selectDataType(dataType){var index=vm.package.dataTypes.indexOf(dataType.id);if(index===-1){vm.package.dataTypes.push(dataType.id);}else{vm.package.dataTypes.splice(index,1);}} -function buildContributorsEditor(pkg){vm.contributorsEditor={alias:'contributors',editor:'Umbraco.MultipleTextstring',label:'Contributors',description:'',hideLabel:true,view:'views/propertyeditors/multipletextbox/multipletextbox.html',value:getVals(pkg.contributors),validation:{mandatory:false,pattern:null},config:{min:0,max:0}};} -function getVals(array){var vals=[];for(var i=0;i0){vm.zipFile.uploadStatus='error';vm.zipFile.serverErrorMessage=data.notifications[0].message;}else{vm.zipFile.uploadStatus='done';loadPackage();vm.zipFile.uploadProgress=100;vm.localPackage=data;}}).error(function(evt,status,headers,config){vm.zipFile.uploadStatus='error';if(status===404){vm.zipFile.serverErrorMessage='File not found';}else if(status==400){vm.zipFile.serverErrorMessage=evt.message;}else{if(evt.InnerException){vm.zipFile.serverErrorMessage=evt.InnerException.ExceptionMessage;if(evt.InnerException.StackTrace&&evt.InnerException.StackTrace.indexOf('ValidateRequestEntityLength')>0){vm.zipFile.serverErrorMessage='File too large to upload';}}else if(evt.Message){vm.zipFile.serverErrorMessage=evt.Message;}}});} -function loadPackage(){if(vm.zipFile.uploadStatus==='done'){vm.state='packageDetails';}} -function installPackage(){vm.installState.status=labels.installStateImporting;vm.installState.progress='0';packageResource.import(vm.localPackage).then(function(pack){vm.installState.progress='25';vm.installState.status=labels.installStateInstalling;return packageResource.installFiles(pack);},installError).then(function(pack){vm.installState.status=labels.installStateRestarting;vm.installState.progress='50';var deferred=$q.defer();var count=0;function checkRestart(){$timeout(function(){packageResource.checkRestart(pack).then(function(d){count++;if(d.isRestarting&&count<10){checkRestart();}else{deferred.resolve(d);}},installError);},2000);} -checkRestart();return deferred.promise;},installError).then(function(pack){vm.installState.status=labels.installStateInstalling;vm.installState.progress='75';return packageResource.installData(pack);},installError).then(function(pack){vm.installState.status=labels.installStateComplete;vm.installState.progress='100';return packageResource.cleanUp(pack);},installError).then(function(result){localStorageService.set('packageInstallData',result);vm.installState.status=labels.installStateCompleted;vm.installCompleted=true;},installError);} -function installError(){return $q.reject();} -vm.reloadPage=function(){$timeout(function(){$window.location.reload(true);});};} -angular.module('umbraco').controller('Umbraco.Editors.Packages.InstallLocalController',PackagesInstallLocalController);}());'use strict';(function(){'use strict';function PackagesInstalledController($scope,$route,$location,packageResource,$timeout,$window,localStorageService,localizationService){var vm=this;vm.confirmUninstall=confirmUninstall;vm.uninstallPackage=uninstallPackage;vm.packageOptions=packageOptions;vm.state='list';vm.installState={status:''};vm.package={};var labels={};function init(){packageResource.getInstalled().then(function(packs){vm.installedPackages=packs;});vm.installState.status='';vm.state='list';var labelKeys=['packager_installStateUninstalling','packager_installStateComplete'];localizationService.localizeMany(labelKeys).then(function(values){labels.installStateUninstalling=values[0];labels.installStateComplete=values[1];});} -function packageOptions(pck){$location.path('packages/packages/options/'+pck.id).search('packageId',null);} -function confirmUninstall(pck){vm.state='packageDetails';vm.package=pck;} -function uninstallPackage(installedPackage){vm.installState.status=labels.installStateUninstalling;vm.installState.progress='0';packageResource.uninstall(installedPackage.id).then(function(){if(installedPackage.files.length>0){vm.installState.status=labels.installStateComplete;vm.installState.progress='100';localStorageService.set('packageInstallData','installed');$timeout(function(){$window.location.reload(true);});}else{init();}});} -init();} -angular.module('umbraco').controller('Umbraco.Editors.Packages.InstalledController',PackagesInstalledController);}());'use strict';(function(){'use strict';function PackagesRepoController($scope,$route,$location,$timeout,ourPackageRepositoryResource,$q,packageResource,localStorageService,localizationService){var vm=this;vm.packageViewState='packageList';vm.categories=[];vm.loading=true;vm.pagination={pageNumber:1,totalPages:10,pageSize:24};vm.searchQuery='';vm.installState={status:'',progress:0,type:'ok'};vm.selectCategory=selectCategory;vm.showPackageDetails=showPackageDetails;vm.setPackageViewState=setPackageViewState;vm.nextPage=nextPage;vm.prevPage=prevPage;vm.goToPage=goToPage;vm.installPackage=installPackage;vm.downloadPackage=downloadPackage;vm.openLightbox=openLightbox;vm.closeLightbox=closeLightbox;vm.search=search;vm.installCompleted=false;var labels={};var defaultSort='Latest';var currSort=defaultSort;var canceler=null;function getActiveCategory(){if(vm.searchQuery!==''){return'';} -for(var i=0;i0;$scope.model.items=[];var items=[];if(Utilities.isArray($scope.model.prevalues)){for(var i in $scope.model.prevalues){var oldValue=$scope.model.prevalues[i];if(!isValidHex(oldValue.value||oldValue)) -continue;if(oldValue.hasOwnProperty('value')){var hexCode=toFullHex(oldValue.value);items.push({value:hexCode.substr(1,hexCode.length),label:oldValue.label,id:i});}else{var hexCode=toFullHex(oldValue);items.push({value:hexCode.substr(1,hexCode.length),label:oldValue,id:i});}} -$scope.model.items=items;} -function toFullHex(hex){if(hex.length===4&&hex.charAt(0)==='#'){hex='#'+hex.charAt(1)+hex.charAt(1)+hex.charAt(2)+hex.charAt(2)+hex.charAt(3)+hex.charAt(3);} -return hex.toLowerCase();} -function isValidHex(str){return /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(str);}});'use strict';function imageFilePickerController($scope,editorService){$scope.add=function(){var mediaPickerOptions={view:'mediapicker',multiPicker:false,disableFolderSelect:true,onlyImages:true,submit:function submit(model){$scope.model.value=model.selection[0].image;editorService.close();},close:function close(){editorService.close();}};editorService.mediaPicker(mediaPickerOptions);};$scope.remove=function(){$scope.model.value=null;};} -angular.module('umbraco').controller('Umbraco.PrevalueEditors.ImageFilePickerController',imageFilePickerController);'use strict';function mediaFolderPickerController($scope,editorService,entityResource){$scope.folderName='';function retriveFolderData(){var id=$scope.model.value;if(id==null){$scope.folderName='';return;} -entityResource.getById(id,'Media').then(function(media){$scope.media=media;});} -retriveFolderData();$scope.add=function(){var mediaPickerOptions={view:'mediapicker',multiPicker:false,disableFolderSelect:false,onlyImages:false,onlyFolders:true,submit:function submit(model){$scope.model.value=model.selection[0].udi;retriveFolderData();editorService.close();},close:function close(){editorService.close();}};editorService.mediaPicker(mediaPickerOptions);};$scope.remove=function(){$scope.model.value=null;retriveFolderData();};} -angular.module('umbraco').controller('Umbraco.PrevalueEditors.MediaFolderPickerController',mediaFolderPickerController);'use strict';function mediaPickerController($scope,entityResource,iconHelper,editorService,angularHelper){function trim(str,chr){var rgxtrim=!chr?new RegExp('^\\s+|\\s+$','g'):new RegExp('^'+chr+'+|'+chr+'+$','g');return str.replace(rgxtrim,'');} -$scope.renderModel=[];$scope.allowRemove=true;$scope.allowEdit=true;$scope.sortable=false;var dialogOptions={multiPicker:false,entityType:'Media',section:'media',treeAlias:'media',idType:'udi'};if($scope.model.config){angular.extend(dialogOptions,$scope.model.config);} -$scope.openTreePicker=function(){var treePicker=dialogOptions;treePicker.submit=function(model){if(treePicker.multiPicker){_.each(model.selection,function(item,i){$scope.add(item);});}else{$scope.clear();$scope.add(model.selection[0]);} -editorService.close();};treePicker.close=function(){editorService.close();};editorService.treePicker(treePicker);};$scope.remove=function(index){$scope.renderModel.splice(index,1);syncModelValue();};$scope.clear=function(){$scope.renderModel=[];syncModelValue();};$scope.add=function(item){var itemId=dialogOptions.idType==='udi'?item.udi:item.id;var currIds=_.map($scope.renderModel,function(i){return dialogOptions.idType==='udi'?i.udi:i.id;});if(currIds.indexOf(itemId)<0){item.icon=iconHelper.convertFromLegacyIcon(item.icon);$scope.renderModel.push({name:item.name,id:item.id,icon:item.icon,udi:item.udi});var itemRenderIndex=$scope.renderModel.length-1;entityResource.getUrl(item.id,dialogOptions.entityType).then(function(data){$scope.renderModel[itemRenderIndex].path=data;});} -syncModelValue();};function syncModelValue(){var currIds=_.map($scope.renderModel,function(i){return dialogOptions.idType==='udi'?i.udi:i.id;});$scope.model.value=trim(currIds.join(),',');angularHelper.getCurrentForm($scope).$setDirty();} -var modelIds=$scope.model.value?$scope.model.value.split(','):[];if(modelIds.length>0){entityResource.getByIds(modelIds,dialogOptions.entityType).then(function(data){_.each(data,function(item,i){item.icon=iconHelper.convertFromLegacyIcon(item.icon);$scope.renderModel.push({name:item.name,id:item.id,icon:item.icon,udi:item.udi});var itemRenderIndex=$scope.renderModel.length-1;entityResource.getUrl(item.id,dialogOptions.entityType).then(function(data){$scope.renderModel[itemRenderIndex].path=data;});});});}} -angular.module('umbraco').controller('Umbraco.PrevalueEditors.MediaPickerController',mediaPickerController);'use strict';angular.module('umbraco').controller('Umbraco.PrevalueEditors.MultiValuesController',function($scope,$timeout){$scope.newItem='';$scope.hasError=false;$scope.focusOnNew=false;if(!Utilities.isArray($scope.model.value)){var items=[];for(var i in $scope.model.value){items.push({value:$scope.model.value[i].value,sortOrder:$scope.model.value[i].sortOrder,id:i});} -items.sort(function(a,b){return a.sortOrder>b.sortOrder?1:b.sortOrder>a.sortOrder?-1:0;});$scope.model.value=items;} -$scope.remove=function(item,evt){evt.preventDefault();$scope.model.value=_.reject($scope.model.value,function(x){return x.value===item.value;});};$scope.add=function(evt){evt.preventDefault();if($scope.newItem){if(!_.contains($scope.model.value,$scope.newItem)){$scope.model.value.push({value:$scope.newItem});$scope.newItem='';$scope.hasError=false;$scope.focusOnNew=true;return;}} -$scope.hasError=true;};$scope.sortableOptions={axis:'y',containment:'parent',cursor:'move',items:'> div.control-group',tolerance:'pointer',update:function update(e,ui){var newIndex=ui.item.index();var movedPrevalueText=$('input[type="text"]',ui.item).val();var originalIndex=getElementIndexByPrevalueText(movedPrevalueText);if(originalIndex>-1){var movedElement=$scope.model.value[originalIndex];$scope.model.value.splice(originalIndex,1);$scope.model.value.splice(newIndex,0,movedElement);}}};$scope.createNew=function(event){if(event.keyCode==13){$scope.add(event);}};function getElementIndexByPrevalueText(value){for(var i=0;i<$scope.model.value.length;i++){if($scope.model.value[i].value===value){return i;}} -return-1;}});'use strict';angular.module('umbraco').controller('Umbraco.PrevalueEditors.TreePickerController',function($scope,entityResource,iconHelper,editorService){$scope.renderModel=[];$scope.ids=[];$scope.allowRemove=true;$scope.allowEdit=true;$scope.sortable=false;var config={multiPicker:false,entityType:'Document',type:'content',treeAlias:'content',idType:'udi'};if($scope.model.config){angular.extend(config,$scope.model.config);} -if($scope.model.value){if(Array.isArray($scope.model.value)){$scope.ids=$scope.model.value.split(',');}else{$scope.ids.push($scope.model.value);} -entityResource.getByIds($scope.ids,config.entityType).then(function(data){_.each(data,function(item,i){item.icon=iconHelper.convertFromLegacyIcon(item.icon);$scope.renderModel.push({name:item.name,id:item.id,icon:item.icon,udi:item.udi});var itemRenderIndex=$scope.renderModel.length-1;entityResource.getUrl(item.id,config.entityType).then(function(data){$scope.renderModel[itemRenderIndex].path=data;});});});} -$scope.openContentPicker=function(){var treePicker=config;treePicker.section=config.type;treePicker.submit=function(model){if(config.multiPicker){populate(model.selection);}else{populate(model.selection[0]);} -editorService.close();};treePicker.close=function(){editorService.close();};editorService.treePicker(treePicker);};$scope.remove=function(index){$scope.renderModel.splice(index,1);$scope.ids.splice(index,1);$scope.model.value=trim($scope.ids.join(),',');};$scope.clear=function(){$scope.model.value='';$scope.renderModel=[];$scope.ids=[];};$scope.add=function(item){var itemId=config.idType==='udi'?item.udi:item.id;if($scope.ids.indexOf(itemId)<0){item.icon=iconHelper.convertFromLegacyIcon(item.icon);$scope.ids.push(itemId);$scope.renderModel.push({name:item.name,id:item.id,icon:item.icon,udi:item.udi});$scope.model.value=trim($scope.ids.join(),',');var itemRenderIndex=$scope.renderModel.length-1;entityResource.getUrl(item.id,config.entityType).then(function(data){$scope.renderModel[itemRenderIndex].path=data;});}};var unsubscribe=$scope.$on('formSubmitting',function(ev,args){$scope.model.value=trim($scope.ids.join(),',');});$scope.$on('$destroy',function(){unsubscribe();});function trim(str,chr){var rgxtrim=!chr?new RegExp('^\\s+|\\s+$','g'):new RegExp('^'+chr+'+|'+chr+'+$','g');return str.replace(rgxtrim,'');} -function populate(data){if(Utilities.isArray(data)){_.each(data,function(item,i){$scope.add(item);});}else{$scope.clear();$scope.add(data);}}});'use strict';angular.module('umbraco').controller('Umbraco.PrevalueEditors.TreeSourceController',function($scope,$timeout,entityResource,iconHelper,editorService,eventsService){if(!$scope.model){$scope.model={};} -if(!$scope.model.value){$scope.model.value={type:'content'};} -if(!$scope.model.config){$scope.model.config={idType:'udi'};} -if($scope.model.value.id&&$scope.model.value.type!=='member'){entityResource.getById($scope.model.value.id,entityType()).then(function(item){populate(item);});}else{$timeout(function(){treeSourceChanged();},100);} -function entityType(){var ent='Document';if($scope.model.value.type==='media'){ent='Media';}else if($scope.model.value.type==='member'){ent='Member';} -return ent;} -$scope.openContentPicker=function(){var treePicker={idType:$scope.model.config.idType,section:$scope.model.value.type,treeAlias:$scope.model.value.type,multiPicker:false,submit:function submit(model){var item=model.selection[0];populate(item);editorService.close();},close:function close(){editorService.close();}};editorService.treePicker(treePicker);};$scope.clear=function(){$scope.model.value.id=null;$scope.node=null;$scope.model.value.query=null;treeSourceChanged();};function treeSourceChanged(){eventsService.emit('treeSourceChanged',{value:$scope.model.value.type});} -var unsubscribe=$scope.$on('formSubmitting',function(ev,args){if($scope.model.value.type==='member'){$scope.model.value.id=null;$scope.model.value.query='';}});$scope.$on('$destroy',function(){unsubscribe();});function populate(item){$scope.clear();item.icon=iconHelper.convertFromLegacyIcon(item.icon);$scope.node=item;$scope.node.path='';$scope.model.value.id=$scope.model.config.idType==='udi'?item.udi:item.id;entityResource.getUrl(item.id,entityType()).then(function(data){$scope.node.path=data;});}});'use strict';function TreeSourceTypePickerController($scope,contentTypeResource,mediaTypeResource,memberTypeResource,editorService,eventsService,angularHelper){var vm=this;vm.loading=false;vm.itemTypes=[];vm.remove=remove;vm.add=add;var allItemTypes=null;var currentItemType=null;function init(){vm.loading=true;switch(currentItemType){case'content':contentTypeResource.getAll().then(getAllItemTypesCallback);break;case'media':mediaTypeResource.getAll().then(getAllItemTypesCallback);break;case'member':memberTypeResource.getTypes().then(getAllItemTypesCallback);break;}} -function getAllItemTypesCallback(all){allItemTypes=all;vm.loading=false;var currentItemTypes=_.map(($scope.model.value||'').split(','),function(s){return s.trim();});vm.itemTypes=_.filter(allItemTypes,function(itemType){return currentItemTypes.indexOf(itemType.alias)>=0;});} -function add(){if(!currentItemType){return;} -var editor={multiPicker:true,filterCssClass:'not-allowed not-published',filter:function filter(item){return item.nodeType==='container'||item.metaData.isElement||!!_.findWhere(vm.itemTypes,{udi:item.udi});},submit:function submit(model){var newItemTypes=_.map(model.selection,function(selected){return _.findWhere(allItemTypes,{udi:selected.udi});});vm.itemTypes=_.uniq(_.union(vm.itemTypes,newItemTypes));updateModel();editorService.close();},close:function close(){editorService.close();}};switch(currentItemType){case'content':editorService.contentTypePicker(editor);break;case'media':editorService.mediaTypePicker(editor);break;case'member':editorService.memberTypePicker(editor);break;}} -function remove(itemType){vm.itemTypes=_.without(vm.itemTypes,itemType);updateModel();} -function updateModel(){$scope.model.value=_.pluck(vm.itemTypes,'alias').join();angularHelper.getCurrentForm($scope).$setDirty();} -eventsService.on('treeSourceChanged',function(e,args){if(!!currentItemType&¤tItemType!==args.value){vm.itemTypes=[];updateModel();} -currentItemType=args.value;init();});} -angular.module('umbraco').controller('Umbraco.PrevalueEditors.TreeSourceTypePickerController',TreeSourceTypePickerController);'use strict';(function(){'use strict';function InlineBlockEditor($scope){var bc=this;bc.openBlock=function(block){if(block.active===true){$scope.$broadcast('formSubmitting',{scope:$scope});$scope.$broadcast('postFormSubmitting',{scope:$scope});block.active=false;}else{$scope.api.activateBlock(block);}};} -angular.module('umbraco').controller('Umbraco.PropertyEditors.BlockEditor.InlineBlockEditor',InlineBlockEditor);}());'use strict';(function(){'use strict';function TransferProperties(fromObject,toObject){for(var p in fromObject){toObject[p]=fromObject[p];}} -function BlockConfigurationController($scope,elementTypeResource,overlayService,localizationService,editorService,eventsService){var unsubscribe=[];var vm=this;vm.openBlock=null;function onInit(){if(!$scope.model.value){$scope.model.value=[];} -loadElementTypes();} -function loadElementTypes(){return elementTypeResource.getAll().then(function(elementTypes){vm.elementTypes=elementTypes;});} -function updateUsedElementTypes(event,args){var key=args.documentType.key;for(var i=0;ib.sortOrder?1:b.sortOrder>a.sortOrder?-1:0;});vm.configItems=sortedItems;if($scope.model.value===null||$scope.model.value===undefined){$scope.model.value=[];} -generateViewModel($scope.model.value);$scope.$watchCollection('model.value',updateViewModel);}} -function updateViewModel(newVal){var i=vm.configItems.length;while(i--){var item=vm.configItems[i];if(item.checked!==(newVal.indexOf(item.value)!==-1)){generateViewModel(newVal);return;}}} -function generateViewModel(newVal){vm.viewItems=[];var iConfigItem;for(var i=0;i=0){$scope.model.value.splice(index,1);}}} -init();});'use strict';function ColorPickerController($scope,$timeout){var config={items:[],multiple:false};angular.extend(config,$scope.model.config);$scope.model.config=config;$scope.isConfigured=$scope.model.config&&$scope.model.config.items&&_.keys($scope.model.config.items).length>0;if($scope.isConfigured){for(var key in $scope.model.config.items){if(!$scope.model.config.items[key].hasOwnProperty('value')) -$scope.model.config.items[key]={value:$scope.model.config.items[key],label:$scope.model.config.items[key]};} -$scope.model.useLabel=isTrue($scope.model.config.useLabel);initActiveColor();} -if(!Utilities.isArray($scope.model.config.items)){var items=[];for(var i in $scope.model.config.items){var oldValue=$scope.model.config.items[i];if(oldValue.hasOwnProperty('value')){items.push({value:oldValue.value,label:oldValue.label,sortOrder:oldValue.sortOrder,id:i});}else{items.push({value:oldValue,label:oldValue,sortOrder:sortOrder,id:i});}} -items.sort(function(a,b){return a.sortOrder>b.sortOrder?1:b.sortOrder>a.sortOrder?-1:0;});$scope.model.config.items=items;} -$scope.selectColor=function(color){$timeout(function(){var newColor=color?color.value:null;$scope.propertyForm.selectedColor.$setViewValue(newColor);});};$scope.validateMandatory=function(){var isValid=!$scope.model.validation.mandatory||$scope.model.value!=null&&$scope.model.value!=''&&(!$scope.model.value.hasOwnProperty('value')||$scope.model.value.value!=='');return{isValid:isValid,errorMsg:$scope.model.validation.mandatoryMessage||'Value cannot be empty',errorKey:'required'};};$scope.isConfigured=$scope.model.config&&$scope.model.config.items&&_.keys($scope.model.config.items).length>0;function initActiveColor(){if(!$scope.model.value) -return;if(typeof $scope.model.value==='string'){$scope.model.value={value:$scope.model.value,label:$scope.model.value};} -if(!$scope.model.value.hasOwnProperty('value')) -return;var modelColor=$scope.model.value.value;var modelLabel=$scope.model.value.label;var foundItem=null;for(var key in $scope.model.config.items){var item=$scope.model.config.items[key];if(item.value==modelColor&&item.label==modelLabel){foundItem=item;break;}} -if(!foundItem){for(var key in $scope.model.config.items){var item=$scope.model.config.items[key];if(item.value==modelColor){foundItem=item;break;}}} -if(!foundItem){for(var key in $scope.model.config.items){var item=$scope.model.config.items[key];if(item.label==modelLabel){foundItem=item;break;}}} -if(foundItem){$scope.model.value.value=foundItem.value;$scope.model.value.label=foundItem.label;}} -function isTrue(bool){return!!bool&&bool!=='0'&&bool.toString().toLowerCase()!=='false';}} -angular.module('umbraco').controller('Umbraco.PropertyEditors.ColorPickerController',ColorPickerController);'use strict';angular.module('umbraco').controller('Umbraco.PrevalueEditors.MultiColorPickerController',function($scope,$timeout,assetsService,angularHelper,$element,localizationService,eventsService){var defaultColor='000000';var defaultLabel=null;$scope.newColor=defaultColor;$scope.newLabel=defaultLabel;$scope.hasError=false;$scope.focusOnNew=false;$scope.labels={};var labelKeys=['general_cancel','general_choose'];$scope.labelEnabled=false;eventsService.on('toggleValue',function(e,args){$scope.labelEnabled=args.value;});localizationService.localizeMany(labelKeys).then(function(values){$scope.labels.cancel=values[0];$scope.labels.choose=values[1];});assetsService.load(['lib/spectrum/spectrum.js'],$scope).then(function(){var elem=$element.find('input[name=\'newColor\']');elem.spectrum({color:null,showInitial:false,chooseText:$scope.labels.choose,cancelText:$scope.labels.cancel,preferredFormat:'hex',showInput:true,clickoutFiresChange:true,hide:function hide(color){$element.find('.btn.add').show();},change:function change(color){angularHelper.safeApply($scope,function(){$scope.newColor=color.toHexString().trimStart('#');});},show:function show(){$element.find('.btn.add').hide();}});});if(!Utilities.isArray($scope.model.value)){var items=[];for(var i in $scope.model.value){var oldValue=$scope.model.value[i];if(oldValue.hasOwnProperty('value')){items.push({value:oldValue.value,label:oldValue.label,sortOrder:oldValue.sortOrder,id:i});}else{items.push({value:oldValue,label:oldValue,sortOrder:sortOrder,id:i});}} -items.sort(function(a,b){return a.sortOrder>b.sortOrder?1:b.sortOrder>a.sortOrder?-1:0;});$scope.model.value=items;} -for(var i=0;i<$scope.model.value.length;i++){var item=$scope.model.value[i];item.label=item.hasOwnProperty('label')?item.label:item.value;} -function validLabel(label){return label!==null&&typeof label!=='undefined'&&label!==''&&label.length&&label.length>0;} -$scope.remove=function(item,evt){evt.preventDefault();$scope.model.value=_.reject($scope.model.value,function(x){return x.value===item.value&&x.label===item.label;});angularHelper.getCurrentForm($scope).$setDirty();};$scope.add=function(evt){evt.preventDefault();if($scope.newColor){var newLabel=validLabel($scope.newLabel)?$scope.newLabel:$scope.newColor;var exists=_.find($scope.model.value,function(item){return item.value.toUpperCase()===$scope.newColor.toUpperCase()||item.label.toUpperCase()===newLabel.toUpperCase();});if(!exists){$scope.model.value.push({value:$scope.newColor,label:newLabel});$scope.newLabel='';$scope.hasError=false;$scope.focusOnNew=true;angularHelper.getCurrentForm($scope).$setDirty();return;} -$scope.hasError=true;}};$scope.sortableOptions={axis:'y',containment:'parent',cursor:'move',items:'> div.control-group',tolerance:'pointer',update:function update(e,ui){angularHelper.getCurrentForm($scope).$setDirty();}};assetsService.loadCss('lib/spectrum/spectrum.css',$scope);});'use strict';function contentPickerController($scope,entityResource,editorState,iconHelper,$routeParams,angularHelper,navigationService,$location,localizationService,editorService,$q){var vm={labels:{general_recycleBin:'',general_add:''}};var unsubscribe;function subscribe(){unsubscribe=$scope.$on('formSubmitting',function(ev,args){var currIds=_.map($scope.renderModel,function(i){return $scope.model.config.idType==='udi'?i.udi:i.id;});$scope.model.value=trim(currIds.join(),',');});} -function trim(str,chr){var rgxtrim=!chr?new RegExp('^\\s+|\\s+$','g'):new RegExp('^'+chr+'+|'+chr+'+$','g');return str.replace(rgxtrim,'');} -function validate(){if($scope.contentPickerForm){if($scope.model.config&&$scope.model.config.minNumber&&parseInt($scope.model.config.minNumber)>$scope.renderModel.length){$scope.contentPickerForm.minCount.$setValidity('minCount',false);}else{$scope.contentPickerForm.minCount.$setValidity('minCount',true);} -if($scope.model.config&&$scope.model.config.maxNumber&&parseInt($scope.model.config.maxNumber)<$scope.renderModel.length){$scope.contentPickerForm.maxCount.$setValidity('maxCount',false);}else{$scope.contentPickerForm.maxCount.$setValidity('maxCount',true);}}} -function startWatch(){$scope.$watchCollection('sortableModel',function(newVal,oldVal){$scope.model.value=newVal.join();});$scope.$watch('model.value',function(newVal,oldVal){if(newVal!==oldVal){syncRenderModel(true);}});} -$scope.renderModel=[];$scope.sortableModel=[];$scope.labels=vm.labels;$scope.dialogEditor=editorState&&editorState.current&&editorState.current.isDialogEditor===true;var defaultConfig={multiPicker:false,showOpenButton:false,showEditButton:false,showPathOnHover:false,dataTypeKey:null,maxNumber:1,minNumber:0,startNode:{query:'',type:'content',id:$scope.model.config.startNodeId?$scope.model.config.startNodeId:-1}};$scope.sortableOptions={axis:'y',containment:'parent',distance:10,opacity:0.7,tolerance:'pointer',scroll:true,zIndex:6000,update:function update(e,ui){angularHelper.getCurrentForm($scope).$setDirty();}};if($scope.model.config){if(!$scope.model.config.startNode){delete $scope.model.config.startNode;} -$scope.model.config=angular.extend(defaultConfig,$scope.model.config);if($scope.model.validation&&$scope.model.validation.mandatory&&!$scope.model.config.minNumber){$scope.model.config.minNumber=1;}} -$scope.model.config.multiPicker=Object.toBoolean($scope.model.config.multiPicker);$scope.model.config.showOpenButton=Object.toBoolean($scope.model.config.showOpenButton);$scope.model.config.showEditButton=Object.toBoolean($scope.model.config.showEditButton);$scope.model.config.showPathOnHover=Object.toBoolean($scope.model.config.showPathOnHover);var entityType=$scope.model.config.startNode.type==='member'?'Member':$scope.model.config.startNode.type==='media'?'Media':'Document';$scope.allowOpenButton=entityType==='Document';$scope.allowEditButton=entityType==='Document';$scope.allowRemoveButton=true;var dialogOptions={multiPicker:$scope.model.config.multiPicker,entityType:entityType,filterCssClass:'not-allowed not-published',startNodeId:null,dataTypeKey:$scope.model.dataTypeKey,currentNode:editorState?editorState.current:null,callback:function callback(data){if(Utilities.isArray(data)){_.each(data,function(item,i){$scope.add(item);});}else{$scope.clear();$scope.add(data);} -angularHelper.getCurrentForm($scope).$setDirty();},treeAlias:$scope.model.config.startNode.type,section:$scope.model.config.startNode.type,idType:'udi'};angular.extend(dialogOptions,$scope.model.config);dialogOptions.dataTypeKey=$scope.model.dataTypeKey;if($scope.model.config.maxNumber&&parseInt($scope.model.config.maxNumber)===1){dialogOptions.multiPicker=false;} -if($scope.model.config.filter){localizationService.localize('contentPicker_allowedItemTypes',[$scope.model.config.filter]).then(function(data){dialogOptions.filterTitle=data;});} -if(entityType==='Member'){dialogOptions.filterCssClass='not-allowed';var currFilter=dialogOptions.filter;dialogOptions.filter=function(i){if(i.metaData.isContainer){return true;} -if(!currFilter){return false;} -var filterItem=currFilter.toLowerCase().split(',');var itemContentType=i.metaData.contentType||i.metaData.ContentTypeAlias;var found=filterItem.indexOf(itemContentType.toLowerCase())>=0;if(!currFilter.startsWith('!')&&!found||currFilter.startsWith('!')&&found){return true;} -return false;};} -if($routeParams.section==='settings'&&$routeParams.tree==='documentTypes'){dialogOptions.startNodeId=-1;}else if($scope.model.config.startNode.query){var rootId=$routeParams.id;entityResource.getByQuery($scope.model.config.startNode.query,rootId,'Document').then(function(ent){dialogOptions.startNodeId=($scope.model.config.idType==='udi'?ent.udi:ent.id).toString();});}else{dialogOptions.startNodeId=$scope.model.config.startNode.id;} -$scope.openCurrentPicker=function(){$scope.currentPicker=dialogOptions;$scope.currentPicker.submit=function(model){if(Utilities.isArray(model.selection)){_.each(model.selection,function(item,i){$scope.add(item);});angularHelper.getCurrentForm($scope).$setDirty();} -angularHelper.getCurrentForm($scope).$setDirty();editorService.close();};$scope.currentPicker.close=function(){editorService.close();};switch(entityType){case'Document':editorService.contentPicker($scope.currentPicker);break;case'Media':editorService.mediaPicker($scope.currentPicker);break;case'Member':editorService.memberPicker($scope.currentPicker);break;default:}};$scope.remove=function(index){var currIds=$scope.model.value?$scope.model.value.split(','):[];if(currIds.length>0){currIds.splice(index,1);angularHelper.getCurrentForm($scope).$setDirty();$scope.model.value=currIds.join();}};$scope.showNode=function(index){var item=$scope.renderModel[index];var id=item.id;var section=$scope.model.config.startNode.type.toLowerCase();entityResource.getPath(id,entityType).then(function(path){navigationService.changeSection(section);navigationService.showTree(section,{tree:section,path:path,forceReload:false,activate:true});var routePath=section+'/'+section+'/edit/'+id.toString();$location.path(routePath).search('');});};$scope.add=function(item){var currIds=$scope.model.value?$scope.model.value.split(','):[];var itemId=($scope.model.config.idType==='udi'?item.udi:item.id).toString();if(currIds.indexOf(itemId)<0){currIds.push(itemId);$scope.model.value=currIds.join();}};$scope.clear=function(){$scope.model.value=null;};$scope.openContentEditor=function(node){var contentEditor={id:node.id,submit:function submit(model){node.name=model.contentNode.name;node.published=model.contentNode.hasPublishedVersion;if(entityType!=='Member'){entityResource.getUrl(model.contentNode.id,entityType).then(function(data){node.url=data;});} -editorService.close();},close:function close(){editorService.close();}};editorService.contentEditor(contentEditor);};$scope.$on('$destroy',function(){if(unsubscribe){unsubscribe();}});function syncRenderModel(doValidation){var valueIds=$scope.model.value?$scope.model.value.split(','):[];$scope.sortableModel=valueIds;if(valueIds.length>0){var renderModelIds=_.map($scope.renderModel,function(d){return($scope.model.config.idType==='udi'?d.udi:d.id).toString();});var toRemove=_.difference(renderModelIds,valueIds);for(var j=0;j0){return entityResource.getByIds(missingIds,entityType).then(function(data){_.each(valueIds,function(id,i){var entity=_.find(data,function(d){return $scope.model.config.idType==='udi'?d.udi==id:d.id==id;});if(entity){addSelectedItem(entity);}});if(doValidation){validate();} -setSortingState($scope.renderModel);return $q.when(true);});}else{var current=$scope.renderModel;$scope.renderModel=[];for(var k=0;k1){$scope.sortableOptions.disabled=false;}else{$scope.sortableOptions.disabled=true;}} -function init(){localizationService.localizeMany(['general_recycleBin','general_add']).then(function(data){vm.labels.general_recycleBin=data[0];vm.labels.general_add=data[1];syncRenderModel(false).then(function(){startWatch();subscribe();validate();});});} -init();} -angular.module('umbraco').controller('Umbraco.PropertyEditors.ContentPickerController',contentPickerController);'use strict';function dateTimePickerController($scope,angularHelper,dateHelper,validationMessageService){var flatPickr=null;function onInit(){$scope.hasDatetimePickerValue=$scope.model.value?true:false;$scope.model.datetimePickerValue=null;$scope.serverTime=null;$scope.serverTimeNeedsOffsetting=false;var config={pickDate:true,pickTime:true,useSeconds:true,format:'YYYY-MM-DD HH:mm:ss',icons:{time:'icon-time',date:'icon-calendar',up:'icon-chevron-up',down:'icon-chevron-down'}};$scope.model.config=angular.extend(config,$scope.model.config);if($scope.model.config.format===''||$scope.model.config.format===undefined||$scope.model.config.format===null){$scope.model.config.format=$scope.model.config.pickTime?'YYYY-MM-DD HH:mm:ss':'YYYY-MM-DD';} -if(Umbraco.Sys.ServerVariables.application.serverTimeOffset!==undefined){var serverOffset=Umbraco.Sys.ServerVariables.application.serverTimeOffset;var localOffset=new Date().getTimezoneOffset();$scope.serverTimeNeedsOffsetting=-serverOffset!==localOffset;} -var dateFormat=$scope.model.config.pickTime?'Y-m-d H:i:S':'Y-m-d';$scope.datePickerConfig={enableTime:$scope.model.config.pickTime,dateFormat:dateFormat,time_24hr:true};if($scope.model.config.format==='HH:mm:ss'||$scope.model.config.format==='HH:mm'||$scope.model.config.format==='HH'){$scope.datePickerConfig.enableTime=true;$scope.datePickerConfig.noCalendar=true;} -setDatePickerVal();validationMessageService.getMandatoryMessage($scope.model.validation).then(function(value){$scope.mandatoryMessage=value;});} -$scope.clearDate=function(){$scope.hasDatetimePickerValue=false;if($scope.model){$scope.model.datetimePickerValue=null;$scope.model.value=null;} -if($scope.datePickerForm&&$scope.datePickerForm.datepicker){$scope.datePickerForm.datepicker.$setValidity('pickerError',true);}};$scope.datePickerSetup=function(instance){flatPickr=instance;};$scope.datePickerChange=function(date){var momentDate=moment(date);setDate(momentDate);setDatePickerVal();};$scope.inputChanged=function(){if($scope.model.datetimePickerValue===''&&$scope.hasDatetimePickerValue){$scope.clearDate();}else if($scope.model.datetimePickerValue){var momentDate=moment($scope.model.datetimePickerValue,$scope.model.config.format,true);if(!momentDate||!momentDate.isValid()){momentDate=moment(new Date($scope.model.datetimePickerValue));} -if(momentDate&&momentDate.isValid()){setDate(momentDate);} -setDatePickerVal();flatPickr.setDate($scope.model.value,false);}};$scope.model.onValueChanged=function(newVal,oldVal){if(newVal!=oldVal){var minDate=moment('0001-01-01');var newDate=moment(newVal);if(newDate.isAfter(minDate)){setDate(newDate);}else{$scope.clearDate();}}};function setDate(momentDate){angularHelper.safeApply($scope,function(){if(momentDate&&momentDate.isValid()){$scope.datePickerForm.datepicker.$setValidity('pickerError',true);$scope.hasDatetimePickerValue=true;$scope.model.datetimePickerValue=momentDate.format($scope.model.config.format);}else{$scope.hasDatetimePickerValue=false;$scope.model.datetimePickerValue=null;} -updateModelValue(momentDate);});} -function updateModelValue(momentDate){if($scope.hasDatetimePickerValue){if($scope.model.config.pickTime){if($scope.model.value&&Object.toBoolean($scope.model.config.offsetTime)&&Umbraco.Sys.ServerVariables.application.serverTimeOffset!==undefined){$scope.model.value=dateHelper.convertToServerStringTime(momentDate,Umbraco.Sys.ServerVariables.application.serverTimeOffset);$scope.serverTime=dateHelper.convertToServerStringTime(momentDate,Umbraco.Sys.ServerVariables.application.serverTimeOffset,'YYYY-MM-DD HH:mm:ss Z');}else{$scope.model.value=momentDate.format('YYYY-MM-DD HH:mm:ss');}}else{$scope.model.value=momentDate.format('YYYY-MM-DD');}}else{$scope.model.value=null;} -angularHelper.getCurrentForm($scope).$setDirty();} -function setDatePickerVal(){if($scope.model.value){var dateVal;if($scope.model.value&&Object.toBoolean($scope.model.config.offsetTime)&&$scope.serverTimeNeedsOffsetting){dateVal=dateHelper.convertToLocalMomentTime($scope.model.value,Umbraco.Sys.ServerVariables.application.serverTimeOffset);$scope.serverTime=dateHelper.convertToServerStringTime(dateVal,Umbraco.Sys.ServerVariables.application.serverTimeOffset,'YYYY-MM-DD HH:mm:ss Z');}else{var dateVal=$scope.model.value?moment($scope.model.value,'YYYY-MM-DD HH:mm:ss'):moment();} -$scope.model.datetimePickerValue=dateVal.format($scope.model.config.format);}else{$scope.clearDate();}} -$scope.$watch('model.value',function(newVal,oldVal){if(newVal!==oldVal){$scope.hasDatetimePickerValue=newVal?true:false;setDatePickerVal();}});onInit();} -angular.module('umbraco').controller('Umbraco.PropertyEditors.DatepickerController',dateTimePickerController);'use strict';angular.module('umbraco').controller('Umbraco.PropertyEditors.DropdownFlexibleController',function($scope,validationMessageService){var config={items:[],multiple:false};angular.extend(config,$scope.model.config);$scope.model.config=config;$scope.model.config.multiple=Object.toBoolean($scope.model.config.multiple);$scope.$on('formSubmitting',function(){if($scope.model.value.length===0||$scope.model.value[0]===null){$scope.model.value=null;}});function convertArrayToDictionaryArray(model){var newItems=[];for(var i=0;ib.sortOrder?1:b.sortOrder>a.sortOrder?-1:0;});if($scope.model.value===null||$scope.model.value===undefined){if($scope.model.config.multiple){$scope.model.value=[];}else{$scope.model.value='';}} -$scope.model.singleDropdownValue='';if(!Object.toBoolean($scope.model.config.multiple)&&$scope.model.value){$scope.model.singleDropdownValue=Array.isArray($scope.model.value)?$scope.model.value[0]:$scope.model.value;} -if($scope.model.config.multiple==='1'&&$scope.model.value){$scope.model.value=!Array.isArray($scope.model.value)?[$scope.model.value]:$scope.model.value;if($scope.model.value.length===0){$scope.model.value=null;}} -validationMessageService.getMandatoryMessage($scope.model.validation).then(function(value){$scope.mandatoryMessage=value;});});'use strict';function emailController($scope,validationMessageService){validationMessageService.getMandatoryMessage($scope.model.validation).then(function(value){$scope.mandatoryMessage=value;});} -angular.module('umbraco').controller('Umbraco.PropertyEditors.EmailController',emailController);'use strict';function entityPicker($scope,entityResource){if(!$scope.model.config.entityType){$scope.model.config.entityType='DocumentType';} -if(!$scope.model.config.publishBy){$scope.selectOptions='entity.id as entity.name for entity in entities';}else{$scope.selectOptions='entity.'+$scope.model.config.publishBy+' as entity.name for entity in entities';} -entityResource.getAll($scope.model.config.entityType).then(function(data){_.each(data,function(d){d.id=d.id.toString();});$scope.entities=data;});if($scope.model.value===null||$scope.model.value===undefined){if($scope.model.config.multiple){$scope.model.value=[];}else{$scope.model.value='';}}else{if(Object.toBoolean($scope.model.config.multiple)){if(_.isString($scope.model.value)){$scope.model.value=$scope.model.value.split(',');}}}} -angular.module('umbraco').controller('Umbraco.PropertyEditors.EntityPickerController',entityPicker);'use strict';(function(){'use strict';function fileUploadController($scope,fileManager){$scope.fileChanged=onFileChanged;$scope.model.onValueChanged=onValueChanged;function onFileChanged(value){$scope.model.value=value;} -function onValueChanged(newVal,oldVal){fileManager.setFiles({propertyAlias:$scope.model.alias,culture:$scope.model.culture,segment:$scope.model.segment,files:[]});}};angular.module('umbraco').controller('Umbraco.PropertyEditors.FileUploadController',fileUploadController);}());'use strict';function ConfigController($scope){var vm=this;vm.submit=submit;vm.close=close;function submit(){if($scope.model&&$scope.model.submit){$scope.model.submit($scope.model);}} -function close(){if($scope.model.close){$scope.model.close();}}} -angular.module('umbraco').controller('Umbraco.PropertyEditors.GridPrevalueEditor.ConfigController',ConfigController);'use strict';function EditConfigController($scope){var vm=this;vm.submit=submit;vm.close=close;function submit(){if($scope.model&&$scope.model.submit){$scope.model.submit($scope.model);}} -function close(){if($scope.model.close){$scope.model.close();}}} -angular.module('umbraco').controller('Umbraco.PropertyEditors.GridPrevalueEditor.EditConfigController',EditConfigController);'use strict';angular.module('umbraco').controller('Umbraco.PropertyEditors.GridPrevalueEditor.LayoutConfigController',function($scope,localizationService){function init(){setTitle();} -function setTitle(){if(!$scope.model.title){localizationService.localize('grid_addGridLayout').then(function(data){$scope.model.title=data;});}} -$scope.currentLayout=$scope.model.currentLayout;$scope.columns=$scope.model.columns;$scope.rows=$scope.model.rows;$scope.currentSection=undefined;$scope.scaleUp=function(section,max,overflow){var add=1;if(overflow!==true){add=max>1?1:max;} -section.grid=section.grid+add;};$scope.scaleDown=function(section){var remove=section.grid>1?1:0;section.grid=section.grid-remove;};$scope.percentage=function(spans){return(spans/$scope.columns*100).toFixed(8);};$scope.configureSection=function(section,template){if(section===undefined){var space=$scope.availableLayoutSpace>4?4:$scope.availableLayoutSpace;section={grid:space};template.sections.push(section);} -$scope.currentSection=section;$scope.currentSection.allowAll=section.allowAll||!section.allowed||!section.allowed.length;};$scope.toggleAllowed=function(section){if(section.allowed){delete section.allowed;}else{section.allowed=[];}};$scope.deleteSection=function(section,template){if($scope.currentSection===section){$scope.currentSection=undefined;} -var index=template.sections.indexOf(section);template.sections.splice(index,1);};$scope.close=function(){if($scope.model.close){$scope.model.close();}};$scope.submit=function(){if($scope.model.submit){$scope.model.submit($scope.currentLayout);}};$scope.$watch('currentLayout',function(layout){if(layout){var total=0;_.forEach(layout.sections,function(section){total=total+section.grid;});$scope.availableLayoutSpace=$scope.columns-total;}},true);init();});'use strict';function RowConfigController($scope,localizationService){function init(){setTitle();} -function setTitle(){if(!$scope.model.title){localizationService.localize('grid_addRowConfiguration').then(function(data){$scope.model.title=data;});}} -$scope.currentRow=$scope.model.currentRow;$scope.editors=$scope.model.editors;$scope.columns=$scope.model.columns;$scope.scaleUp=function(section,max,overflow){var add=1;if(overflow!==true){add=max>1?1:max;} -section.grid=section.grid+add;};$scope.scaleDown=function(section){var remove=section.grid>1?1:0;section.grid=section.grid-remove;};$scope.percentage=function(spans){return(spans/$scope.columns*100).toFixed(8);};$scope.configureCell=function(cell,row){if($scope.currentCell&&$scope.currentCell===cell){delete $scope.currentCell;}else{if(cell===undefined){var available=$scope.availableRowSpace;var space=4;if(available<4&&available>0){space=available;} -cell={grid:space};row.areas.push(cell);} -$scope.currentCell=cell;$scope.currentCell.allowAll=cell.allowAll||!cell.allowed||!cell.allowed.length;}};$scope.toggleAllowed=function(cell){if(cell.allowed){delete cell.allowed;}else{cell.allowed=[];}};$scope.deleteArea=function(cell,row){if($scope.currentCell===cell){$scope.currentCell=undefined;} -var index=row.areas.indexOf(cell);row.areas.splice(index,1);};$scope.closeArea=function(){$scope.currentCell=undefined;};$scope.close=function(){if($scope.model.close){$scope.model.close();}};$scope.submit=function(){if($scope.model.submit){$scope.model.submit($scope.currentRow);}};$scope.nameChanged=false;var originalName=$scope.currentRow.name;$scope.$watch('currentRow',function(row){if(row){var total=0;_.forEach(row.areas,function(area){total=total+area.grid;});$scope.availableRowSpace=$scope.columns-total;if(originalName){if(originalName!=row.name){$scope.nameChanged=true;}else{$scope.nameChanged=false;}}}},true);init();} -angular.module('umbraco').controller('Umbraco.PropertyEditors.GridPrevalueEditor.RowConfigController',RowConfigController);'use strict';function DeleteRowConfirmController($scope){$scope.close=function(){if($scope.model.close){$scope.model.close();}};$scope.submit=function(){if($scope.model&&$scope.model.submit){$scope.model.submit($scope.model);}};} -angular.module('umbraco').controller('Umbraco.PropertyEditors.GridPrevalueEditor.DeleteRowConfirmController',DeleteRowConfirmController);'use strict';angular.module('umbraco').controller('Umbraco.PropertyEditors.Grid.EmbedController',function($scope,$timeout,$sce,editorService){function onInit(){var embedPreview=Utilities.isObject($scope.control.value)&&$scope.control.value.preview?$scope.control.value.preview:$scope.control.value;$scope.trustedValue=embedPreview?$sce.trustAsHtml(embedPreview):null;if(!$scope.control.value){$timeout(function(){if($scope.control.$initializing){$scope.setEmbed();}},200);}} -$scope.setEmbed=function(){var original=Utilities.isObject($scope.control.value)?$scope.control.value:null;var embed={original:original,submit:function submit(model){var embed={constrain:model.embed.constrain,height:model.embed.height,width:model.embed.width,url:model.embed.url,info:model.embed.info,preview:model.embed.preview};$scope.control.value=embed;$scope.trustedValue=$sce.trustAsHtml(embed.preview);editorService.close();},close:function close(){editorService.close();}};editorService.embed(embed);};onInit();});'use strict';angular.module('umbraco').controller('Umbraco.PropertyEditors.Grid.MacroController',function($scope,$timeout,editorService,macroResource,macroService,$routeParams){$scope.title='Click to insert macro';$scope.setMacro=function(){var dialogData={richTextEditor:true,macroData:$scope.control.value||{macroAlias:$scope.control.editor.config&&$scope.control.editor.config.macroAlias?$scope.control.editor.config.macroAlias:''}};var macroPicker={dialogData:dialogData,submit:function submit(model){var macroObject=macroService.collectValueData(model.selectedMacro,model.macroParams,dialogData.renderingEngine);$scope.control.value={macroAlias:macroObject.macroAlias,macroParamsDictionary:macroObject.macroParamsDictionary};$scope.setPreview($scope.control.value);editorService.close();},close:function close(){editorService.close();}};editorService.macroPicker(macroPicker);};$scope.setPreview=function(macro){var contentId=$routeParams.id;macroResource.getMacroResultAsHtmlForEditor(macro.macroAlias,contentId,macro.macroParamsDictionary).then(function(htmlResult){$scope.title=macro.macroAlias;if(htmlResult.trim().length>0&&htmlResult.indexOf('Macro:')<0){$scope.preview=htmlResult;}});};$timeout(function(){if($scope.control.$initializing){$scope.setMacro();}else if($scope.control.value){$scope.setPreview($scope.control.value);}},200);});'use strict';angular.module('umbraco').controller('Umbraco.PropertyEditors.Grid.MediaController',function($scope,userService,editorService,mediaHelper){setThumbnailUrl();if(!$scope.model.config.startNodeId){if($scope.model.config.ignoreUserStartNodes===true){$scope.model.config.startNodeId=-1;$scope.model.config.startNodeIsVirtual=true;}else{userService.getCurrentUser().then(function(userData){$scope.model.config.startNodeId=userData.startMediaIds.length!==1?-1:userData.startMediaIds[0];$scope.model.config.startNodeIsVirtual=userData.startMediaIds.length!==1;});}} -$scope.setImage=function(){var startNodeId=$scope.model.config&&$scope.model.config.startNodeId?$scope.model.config.startNodeId:undefined;var startNodeIsVirtual=startNodeId?$scope.model.config.startNodeIsVirtual:undefined;var mediaPicker={startNodeId:startNodeId,startNodeIsVirtual:startNodeIsVirtual,cropSize:$scope.control.editor.config&&$scope.control.editor.config.size?$scope.control.editor.config.size:undefined,showDetails:true,disableFolderSelect:true,onlyImages:true,dataTypeKey:$scope.model.dataTypeKey,submit:function submit(model){var selectedImage=model.selection[0];$scope.control.value={focalPoint:selectedImage.focalPoint,id:selectedImage.id,udi:selectedImage.udi,image:selectedImage.image,caption:selectedImage.altText};editorService.close();},close:function close(){editorService.close();}};editorService.mediaPicker(mediaPicker);};$scope.$watch('control.value',function(newValue,oldValue){if(angular.equals(newValue,oldValue)){return;} -setThumbnailUrl();},true);function setThumbnailUrl(){if($scope.control.value&&$scope.control.value.image){var url=$scope.control.value.image;var imageOptions={};if(url.indexOf('?')==-1){imageOptions.animationprocessmode=false;imageOptions.width=800;}else{if($scope.control.editor.config&&$scope.control.editor.config.size){imageOptions.animationprocessmode='first';imageOptions.height=$scope.control.editor.config.size.height;imageOptions.width=$scope.control.editor.config.size.width;} -if($scope.control.value.focalPoint){imageOptions.focalPoint={left:$scope.control.value.focalPoint.left,top:$scope.control.value.focalPoint.top};imageOptions.mode='crop';}} -mediaHelper.getProcessedImageUrl($scope.control.value.image,imageOptions).then(function(url){$scope.thumbnailUrl=url;});}};});'use strict';(function(){'use strict';function GridRichTextEditorController(){var vm=this;} -angular.module('umbraco').controller('Umbraco.PropertyEditors.Grid.RichTextEditorController',GridRichTextEditorController);}());'use strict';angular.module('umbraco').controller('Umbraco.PropertyEditors.Grid.TextStringController',function(){});'use strict';angular.module('umbraco').controller('Umbraco.PropertyEditors.GridController',function($scope,localizationService,gridService,umbRequestHelper,angularHelper,$element,eventsService,editorService,overlayService,$interpolate){var placeHolder='';var currentForm=angularHelper.getCurrentForm($scope);$scope.currentRowWithActiveChild=null;$scope.currentCellWithActiveChild=null;$scope.active=null;$scope.currentRow=null;$scope.currentCell=null;$scope.currentToolsControl=null;$scope.currentControl=null;$scope.openRTEToolbarId=null;$scope.hasSettings=false;$scope.showRowConfigurations=true;$scope.sortMode=false;$scope.reorderKey='general_reorder';var draggedRteSettings;$scope.sortableOptionsRow={distance:10,cursor:'move',placeholder:'ui-sortable-placeholder',handle:'.umb-row-title-bar',helper:'clone',forcePlaceholderSize:true,tolerance:'pointer',zIndex:1000000000000000000,scrollSensitivity:100,cursorAt:{top:40,left:60},sort:function sort(event,ui){var max=$('.umb-grid').width()-150;if(parseInt(ui.helper.css('left'))>max){ui.helper.css({'left':max+'px'});} -if(parseInt(ui.helper.css('left'))<20){ui.helper.css({'left':20});}},start:function start(e,ui){ui.item[0].style.display='block';ui.item[0].style.opacity='0.5';draggedRteSettings={};ui.item.find('.umb-rte').each(function(key,value){var rteId=value.id;var editor=_.findWhere(tinyMCE.editors,{id:rteId});if(editor){draggedRteSettings[rteId]=editor.settings;}});},stop:function stop(e,ui){ui.item[0].style.opacity='1';ui.item.parents('.umb-column').find('.umb-rte').each(function(key,value){var rteId=value.id;var settings=draggedRteSettings[rteId];if(!settings){var editor=_.findWhere(tinyMCE.editors,{id:rteId});if(editor){settings=editor.settings;}} -if(settings){tinyMCE.execCommand('mceRemoveEditor',false,rteId);tinyMCE.init(settings);}});currentForm.$setDirty();}};var notIncludedRte=[];var cancelMove=false;var startingArea;$scope.sortableOptionsCell={distance:10,cursor:'move',uiFloating:true,placeholder:'ui-sortable-placeholder',handle:'.umb-control-handle',helper:'clone',connectWith:'.umb-cell-inner',forcePlaceholderSize:true,tolerance:'pointer',zIndex:1000000000000000000,scrollSensitivity:100,cursorAt:{top:45,left:90},sort:function sort(event,ui){var position=parseInt(ui.item.parent().offset().left)+parseInt(ui.helper.css('left'))-parseInt($('.umb-grid').offset().left);var max=$('.umb-grid').width()-220;if(position>max){ui.helper.css({'left':max-parseInt(ui.item.parent().offset().left)+parseInt($('.umb-grid').offset().left)+'px'});} -if(position<0){ui.helper.css({'left':0-parseInt(ui.item.parent().offset().left)+parseInt($('.umb-grid').offset().left)+'px'});}},over:function over(event,ui){var area=event.target.getScope_HackForSortable().area;var allowedEditors=area.allowed;if($.inArray(ui.item[0].getScope_HackForSortable().control.editor.alias,allowedEditors)<0&&allowedEditors||startingArea!=area&&area.maxItems!=''&&area.maxItems>0&&area.maxItemsi;i++){var section=$scope.model.value.sections[i];if(section.rows&§ion.rows.length>0){return true;}}}};$scope.openEditorOverlay=function(event,area,index,key){var dialog={view:'itempicker',filter:area.$allowedEditors.length>15,availableItems:area.$allowedEditors,event:event,submit:function submit(model){if(model.selectedItem){$scope.addControl(model.selectedItem,area,index);overlayService.close();}},close:function close(){overlayService.close();}};localizationService.localize('grid_insertControl').then(function(value){dialog.title=value;overlayService.open(dialog);});};$scope.addTemplate=function(template){$scope.model.value=Utilities.copy(template);_.forEach($scope.model.value.sections,function(section){$scope.initSection(section);});};$scope.clickRow=function(index,rows,$event){$scope.currentRowWithActiveChild=null;$scope.active=rows[index];$event.stopPropagation();};function getAllowedLayouts(section){var layouts=$scope.model.config.items.layouts;if(section.allowed&§ion.allowed.length>0){return _.filter(layouts,function(layout){return _.indexOf(section.allowed,layout.name)>=0;});}else{return layouts;}} -$scope.addRow=function(section,layout,isInit){var row=Utilities.copy(layout);row=$scope.initRow(row);if(row){section.rows.push(row);} -if(!isInit){currentForm.$setDirty();} -$scope.showRowConfigurations=false;eventsService.emit('grid.rowAdded',{scope:$scope,element:$element,row:row});setTimeout(function(){var newRowEl=$element.find('[data-rowid=\''+row.$uniqueId+'\']');if(newRowEl!==null){newRowEl.focus();}},0);};$scope.removeRow=function(section,$index){if(section.rows.length>0){section.rows.splice($index,1);$scope.currentRow=null;$scope.currentRowWithActiveChild=null;$scope.openRTEToolbarId=null;currentForm.$setDirty();} -if(section.rows.length===0){$scope.showRowConfigurations=true;}};var shouldApply=function shouldApply(item,itemType,gridItem){if(item.applyTo===undefined||item.applyTo===null||item.applyTo===''){return true;} -if(typeof item.applyTo==='string'){return item.applyTo===itemType;} -if(itemType==='row'){if(item.applyTo.row===undefined){return false;} -if(item.applyTo.row===null||item.applyTo.row===''){return true;} -var rows=item.applyTo.row.split(',');return _.indexOf(rows,gridItem.name)!==-1;}else if(itemType==='cell'){if(item.applyTo.cell===undefined){return false;} -if(item.applyTo.cell===null||item.applyTo.cell===''){return true;} -var cells=item.applyTo.cell.split(',');var cellSize=gridItem.grid.toString();return _.indexOf(cells,cellSize)!==-1;}};$scope.editGridItemSettings=function(gridItem,itemType){placeHolder='{0}';var styles,config;if(itemType==='control'){styles=null;config=Utilities.copy(gridItem.editor.config.settings);}else{styles=_.filter(Utilities.copy($scope.model.config.items.styles),function(item){return shouldApply(item,itemType,gridItem);});config=_.filter(Utilities.copy($scope.model.config.items.config),function(item){return shouldApply(item,itemType,gridItem);});} -if(Utilities.isObject(gridItem.config)){_.each(config,function(cfg){var val=gridItem.config[cfg.key];if(val){cfg.value=stripModifier(val,cfg.modifier);}});} -if(Utilities.isObject(gridItem.styles)){_.each(styles,function(style){var val=gridItem.styles[style.key];if(val){style.value=stripModifier(val,style.modifier);}});} -var dialogOptions={view:'views/propertyeditors/grid/dialogs/config.html',size:'small',styles:styles,config:config,submit:function submit(model){var styleObject={};var configObject={};_.each(model.styles,function(style){if(style.value){styleObject[style.key]=addModifier(style.value,style.modifier);}});_.each(model.config,function(cfg){cfg.alias=cfg.key;cfg.label=cfg.value;if(cfg.value){configObject[cfg.key]=addModifier(cfg.value,cfg.modifier);}});gridItem.styles=styleObject;gridItem.config=configObject;gridItem.hasConfig=gridItemHasConfig(styleObject,configObject);currentForm.$setDirty();editorService.close();},close:function close(){editorService.close();}};localizationService.localize('general_settings').then(function(value){dialogOptions.title=value;editorService.open(dialogOptions);});};function stripModifier(val,modifier){if(!val||!modifier||modifier.indexOf(placeHolder)<0){return val;}else{var paddArray=modifier.split(placeHolder);if(paddArray.length==1){if(modifier.indexOf(placeHolder)===0){return val.slice(0,-paddArray[0].length);}else{return val.slice(paddArray[0].length,0);}}else{if(paddArray[1].length===0){return val.slice(paddArray[0].length);} -return val.slice(paddArray[0].length,-paddArray[1].length);}}} -var addModifier=function addModifier(val,modifier){if(!modifier||modifier.indexOf(placeHolder)<0){return val;}else{return modifier.replace(placeHolder,val);}};function gridItemHasConfig(styles,config){if(_.isEmpty(styles)&&_.isEmpty(config)){return false;}else{return true;}} -$scope.clickCell=function(index,cells,row,$event){$scope.currentCellWithActiveChild=null;$scope.active=cells[index];$scope.currentRowWithActiveChild=row;$event.stopPropagation();};$scope.cellPreview=function(cell){if(cell&&cell.$allowedEditors){var editor=cell.$allowedEditors[0];return editor.icon;}else{return'icon-layout';}};$scope.clickControl=function(index,controls,cell,$event){$scope.active=controls[index];$scope.currentCellWithActiveChild=cell;$event.stopPropagation();};function hasActiveChild(item,children){var activeChild=false;for(var i=0;children.length>i;i++){var child=children[i];if(child.active){activeChild=true;}} -if(activeChild){return true;}} -var guid=function(){function s4(){return Math.floor((1+Math.random())*65536).toString(16).substring(1);} -return function(){return s4()+s4()+'-'+s4()+'-'+s4()+'-'+s4()+'-'+s4()+s4()+s4();};}();$scope.setUniqueId=function(cell,index){return guid();};$scope.addControl=function(editor,cell,index,initialize){initialize=initialize!==false;var newControl={value:null,editor:editor,$initializing:initialize};if(index===undefined){index=cell.controls.length;} -$scope.active=newControl;$scope.initControl(newControl,index+1);cell.controls.push(newControl);eventsService.emit('grid.itemAdded',{scope:$scope,element:$element,cell:cell,item:newControl});};$scope.addTinyMce=function(cell){var rte=$scope.getEditor('rte');$scope.addControl(rte,cell);};$scope.getEditor=function(alias){return _.find($scope.availableEditors,function(editor){return editor.alias===alias;});};$scope.removeControl=function(cell,$index){$scope.currentControl=null;cell.controls.splice($index,1);};$scope.percentage=function(spans){return(spans/$scope.model.config.items.columns*100).toFixed(8);};$scope.clearPrompt=function(scopedObject,e){scopedObject.deletePrompt=false;e.preventDefault();e.stopPropagation();};$scope.togglePrompt=function(scopedObject){scopedObject.deletePrompt=!scopedObject.deletePrompt;};$scope.hidePrompt=function(scopedObject){scopedObject.deletePrompt=false;};$scope.toggleAddRow=function(){$scope.showRowConfigurations=!$scope.showRowConfigurations;};$scope.getTemplateName=function(control){var templateName=control.editor.name;if(control.editor.nameExp){var valueOfTemplate=control.editor.nameExp(control);if(valueOfTemplate!=''){templateName+=': ';templateName+=valueOfTemplate;}} -return templateName;};$scope.initContent=function(){var clear=true;if($scope.model.config.items.config&&$scope.model.config.items.config.length>0||$scope.model.config.items.styles&&$scope.model.config.items.styles.length>0){$scope.hasSettings=true;} -if(!$scope.model.config.items.columns){$scope.model.config.items.columns=12;}else if(Utilities.isString($scope.model.config.items.columns)){$scope.model.config.items.columns=parseInt($scope.model.config.items.columns);} -if($scope.model.value&&$scope.model.value.sections&&$scope.model.value.sections.length>0&&$scope.model.value.sections[0].rows&&$scope.model.value.sections[0].rows.length>0){if($scope.model.value.name&&Utilities.isArray($scope.model.config.items.templates)){var found=_.find($scope.model.config.items.templates,function(t){return t.name===$scope.model.value.name;});if(found&&Utilities.isArray(found.sections)&&found.sections.length===$scope.model.value.sections.length){_.each(found.sections,function(templateSection,index){angular.extend($scope.model.value.sections[index],Utilities.copy(templateSection));});}} -_.forEach($scope.model.value.sections,function(section,index){if(section.grid>0){$scope.initSection(section);if(section.rows.length>0){clear=false;}}else{$scope.model.value.sections.splice(index,1);}});}else if($scope.model.config.items.templates&&$scope.model.config.items.templates.length===1){$scope.addTemplate($scope.model.config.items.templates[0]);clear=false;} -if(clear){$scope.model.value=undefined;}};$scope.initSection=function(section){section.$percentage=$scope.percentage(section.grid);section.$allowedLayouts=getAllowedLayouts(section);if(!section.rows||section.rows.length===0){section.rows=[];if(section.$allowedLayouts.length===1){$scope.addRow(section,section.$allowedLayouts[0],true);}}else{_.forEach(section.rows,function(row,index){if(!row.$initialized){var initd=$scope.initRow(row);if(!initd){section.rows.splice(index,1);}else{section.rows[index]=initd;}}});$scope.showRowConfigurations=false;}};$scope.initRow=function(row){var original=_.find($scope.model.config.items.layouts,function(o){return o.name===row.name;});if(!original){return null;}else{original=Utilities.copy(original);original.styles=row.styles;original.config=row.config;original.hasConfig=gridItemHasConfig(row.styles,row.config);_.each(original.areas,function(area,areaIndex){if(area.grid>0){var currentArea=row.areas[areaIndex];if(currentArea){area.config=currentArea.config;area.styles=currentArea.styles;area.hasConfig=gridItemHasConfig(currentArea.styles,currentArea.config);} -if(!area.allowed||area.allowAll===true){area.$allowedEditors=$scope.availableEditors;area.$allowsRTE=true;}else{area.$allowedEditors=_.filter($scope.availableEditors,function(editor){return _.indexOf(area.allowed,editor.alias)>=0;});if(_.indexOf(area.allowed,'rte')>=0){area.$allowsRTE=true;}} -if(row.areas.length>areaIndex&&row.areas[areaIndex].controls){area.controls=currentArea.controls;_.forEach(area.controls,function(control,controlIndex){$scope.initControl(control,controlIndex);});}else{area.controls=[];if(area.$allowedEditors.length===1){$scope.addControl(area.$allowedEditors[0],area,0,false);}} -area.$percentage=$scope.percentage(area.grid);area.$uniqueId=$scope.setUniqueId();}else{original.areas.splice(areaIndex,1);}});original.$initialized=true;original.$uniqueId=$scope.setUniqueId();original.id=!row.id?$scope.setUniqueId():row.id;return original;}};$scope.initControl=function(control,index){control.$index=index;control.$uniqueId=$scope.setUniqueId();if(!control.editor){control.$editorPath='views/propertyeditors/grid/editors/error.html';} -if(!control.$editorPath){var editorConfig=$scope.getEditor(control.editor.alias);if(editorConfig){control.editor=editorConfig;if(control.editor.view.startsWith('/')||control.editor.view.startsWith('~/')){control.$editorPath=umbRequestHelper.convertVirtualToAbsolutePath(control.editor.view);}else{control.$editorPath='views/propertyeditors/grid/editors/'+control.editor.view+'.html';}}else{control.$editorPath='views/propertyeditors/grid/editors/error.html';}}};gridService.getGridEditors().then(function(response){$scope.availableEditors=response.data;angular.forEach($scope.availableEditors,function(value,key){localizationService.localize('grid_'+value.alias,undefined,value.name).then(function(v){value.name=v;});value.nameExp=!!value.nameTemplate?$interpolate(value.nameTemplate):undefined;});$scope.contentReady=true;eventsService.emit('grid.initializing',{scope:$scope,element:$element});$scope.initContent();eventsService.emit('grid.initialized',{scope:$scope,element:$element});});var unsubscribe=$scope.$on('formSubmitting',function(e,args){if(args.action==='save'&&$scope.model.value&&$scope.model.value.sections){_.each($scope.model.value.sections,function(section){if(section.rows){_.each(section.rows,function(row){if(row.areas){_.each(row.areas,function(area){if(area.editors){delete area.editors;} -if(area.controls){_.each(area.controls,function(control){if(control.editor){var alias=control.editor.alias;control.editor={alias:alias};}});}});}});}});}});$scope.$on('$destroy',function(){unsubscribe();});});'use strict';(function(){'use strict';function umbGridHackScope(){function link($scope,$element){$element[0].getScope_HackForSortable=function(){return $scope;};} -var directive={restrict:'A',link:link};return directive;} -angular.module('umbraco').directive('umbGridHackScope',umbGridHackScope);}());'use strict';angular.module('umbraco').controller('Umbraco.PropertyEditors.GridPrevalueEditorController',function($scope,gridService,editorService){var emptyModel={styles:[{label:'Set a background image',description:'Set a row background',key:'background-image',view:'imagepicker',modifier:'url({0})'}],config:[{label:'Class',description:'Set a css class',key:'class',view:'textstring'}],columns:12,templates:[{name:'1 column layout',sections:[{grid:12}]},{name:'2 column layout',sections:[{grid:4},{grid:8}]}],layouts:[{label:'Headline',name:'Headline',areas:[{grid:12,editors:['headline']}]},{label:'Article',name:'Article',areas:[{grid:4},{grid:8}]}]};$scope.configureTemplate=function(template){var index=$scope.model.value.templates.indexOf(template);if(template===undefined){template={name:'',sections:[]};} -var layoutConfigOverlay={currentLayout:Utilities.copy(template),rows:$scope.model.value.layouts,columns:$scope.model.value.columns,view:'views/propertyEditors/grid/dialogs/layoutconfig.html',size:'small',submit:function submit(model){if(index===-1){$scope.model.value.templates.push(model);}else{$scope.model.value.templates[index]=model;} -editorService.close();},close:function close(model){editorService.close();}};editorService.open(layoutConfigOverlay);};$scope.deleteTemplate=function(index){$scope.model.value.templates.splice(index,1);};$scope.configureLayout=function(layout){var index=$scope.model.value.layouts.indexOf(layout);if(layout===undefined){layout={name:'',areas:[]};} -var rowConfigOverlay={currentRow:Utilities.copy(layout),editors:$scope.editors,columns:$scope.model.value.columns,view:'views/propertyEditors/grid/dialogs/rowconfig.html',size:'small',submit:function submit(model){if(index===-1){$scope.model.value.layouts.push(model);}else{$scope.model.value.layouts[index]=model;} -editorService.close();},close:function close(model){editorService.close();}};editorService.open(rowConfigOverlay);};$scope.deleteLayout=function(index){var rowDeleteOverlay={dialogData:{rowName:$scope.model.value.layouts[index].name},view:'views/propertyEditors/grid/dialogs/rowdeleteconfirm.html',size:'small',submit:function submit(model){$scope.model.value.layouts.splice(index,1);editorService.close();},close:function close(model){editorService.close();}};editorService.open(rowDeleteOverlay);};$scope.toggleCollection=function(collection,toggle){if(toggle){collection=[];}else{collection=null;}};$scope.percentage=function(spans){return(spans/$scope.model.value.columns*100).toFixed(8);};$scope.zeroWidthFilter=function(cell){return cell.grid>0;};$scope.removeConfigValue=function(collection,index){collection.splice(index,1);};var editConfigCollection=function editConfigCollection(configValues,title,callback){var editConfigCollectionOverlay={config:configValues,title:title,view:'views/propertyeditors/grid/dialogs/editconfig.html',size:'small',submit:function submit(model){callback(model.config);editorService.close();},close:function close(model){editorService.close();}};editorService.open(editConfigCollectionOverlay);};$scope.editConfig=function(){editConfigCollection($scope.model.value.config,'Settings',function(data){$scope.model.value.config=data;});};$scope.editStyles=function(){editConfigCollection($scope.model.value.styles,'Styling',function(data){$scope.model.value.styles=data;});};gridService.getGridEditors().then(function(response){$scope.editors=response.data;});if(!$scope.model.value||$scope.model.value===''||!$scope.model.value.templates){$scope.model.value=emptyModel;}else{if(!$scope.model.value.columns){$scope.model.value.columns=emptyModel.columns;} -if(!$scope.model.value.config){$scope.model.value.config=[];} -if(!$scope.model.value.styles){$scope.model.value.styles=[];}} -var unsubscribe=$scope.$on('formSubmitting',function(ev,args){var ts=$scope.model.value.templates;var ls=$scope.model.value.layouts;_.each(ts,function(t){_.each(t.sections,function(section,index){if(section.grid===0){t.sections.splice(index,1);}});});_.each(ls,function(l){_.each(l.areas,function(area,index){if(area.grid===0){l.areas.splice(index,1);}});});});$scope.$on('$destroy',function(){unsubscribe();});});'use strict';function IdWithGuidValueController($rootScope,$scope,$filter){function formatDisplayValue(){if($scope.model.value.length>1){$scope.displayid=$scope.model.value[0];$scope.displayguid=$scope.model.value[1];}else{$scope.displayid=$scope.model.value;}} -formatDisplayValue();} -angular.module('umbraco').controller('Umbraco.PropertyEditors.IdWithGuidValueController',IdWithGuidValueController);'use strict';angular.module('umbraco').controller('Umbraco.PropertyEditors.ImageCropperController',function($scope,fileManager,$timeout){var config=Utilities.copy($scope.model.config);$scope.filesSelected=onFileSelected;$scope.filesChanged=onFilesChanged;$scope.fileUploaderInit=onFileUploaderInit;$scope.imageLoaded=imageLoaded;$scope.crop=crop;$scope.done=done;$scope.clear=clear;$scope.reset=reset;$scope.close=close;$scope.isCustomCrop=isCustomCrop;$scope.focalPointChanged=focalPointChanged;$scope.model.onValueChanged=onValueChanged;function focalPointChanged(left,top){$scope.model.value.focalPoint={left:left,top:top};$scope.imageCropperForm.$setDirty();} -function setModelValueWithSrc(src){if(!$scope.model.value||!$scope.model.value.src){$scope.model.value=angular.extend(Utilities.copy($scope.model.config),{src:src});}} -function onValueChanged(newVal,oldVal){fileManager.setFiles({propertyAlias:$scope.model.alias,culture:$scope.model.culture,segment:$scope.model.segment,files:[]});} -function onFileSelected(value,files){setModelValueWithSrc(value);$scope.imageCropperForm.$setDirty();} -function imageLoaded(isCroppable,hasDimensions){$scope.isCroppable=isCroppable;$scope.hasDimensions=hasDimensions;};function onFilesChanged(files){if(files&&files[0]){$scope.imageSrc=files[0].fileSrc;$scope.imageCropperForm.$setDirty();}} -function onFileUploaderInit(value,files){if($scope.model.value){if(Utilities.isString($scope.model.value)){setModelValueWithSrc($scope.model.value);}else{_.each($scope.model.value.crops,function(saved){var configured=_.find(config.crops,function(item){return item.alias===saved.alias;});if(configured&&configured.height===saved.height&&configured.width===saved.width){configured.coordinates=saved.coordinates;}});$scope.model.value.crops=config.crops;if(!$scope.model.value.focalPoint){$scope.model.value.focalPoint={left:0.5,top:0.5};}} -if(files&&files[0]){$scope.imageSrc=files[0].fileSrc;}else{$scope.imageSrc=$scope.model.value.src;}}} -function crop(targetCrop){if(!$scope.currentCrop){$scope.currentCrop=Utilities.copy(targetCrop);$scope.currentPoint=null;$scope.imageCropperForm.$setDirty();}else{close();$timeout(function(){crop(targetCrop);$scope.pendingCrop=false;});$scope.pendingCrop=true;}};function done(){if(!$scope.currentCrop){return;} -var editedCrop=_.find($scope.model.value.crops,function(crop){return crop.alias===$scope.currentCrop.alias;});editedCrop.coordinates=$scope.currentCrop.coordinates;$scope.close();$scope.imageCropperForm.$setDirty();};function reset(){$scope.currentCrop.coordinates=undefined;$scope.done();} -function close(){$scope.currentCrop=undefined;$scope.currentPoint=undefined;} -function clear(crop){fileManager.setFiles({propertyAlias:$scope.model.alias,culture:$scope.model.culture,segment:$scope.model.segment,files:[]});$scope.imageSrc=null;if($scope.model.value){$scope.model.value=null;} -$scope.imageCropperForm.$setDirty();};function isCustomCrop(crop){return!!crop.coordinates;} -var unsubscribe=$scope.$on('formSubmitting',function(){$scope.currentCrop=null;$scope.currentPoint=null;});$scope.$on('$destroy',function(){unsubscribe();});}).run(function(mediaHelper,umbRequestHelper){if(mediaHelper&&mediaHelper.registerFileResolver){mediaHelper.registerFileResolver('Umbraco.ImageCropper',function(property,entity,thumbnail){if(property.value&&property.value.src){if(thumbnail===true){return property.value.src+'?width=500&mode=max&animationprocessmode=first';}else{return property.value.src;}}else if(Utilities.isString(property.value)){if(thumbnail){if(mediaHelper.detectIfImageByExtension(property.value)){var thumbnailUrl=umbRequestHelper.getApiUrl('imagesApiBaseUrl','GetBigThumbnail',[{originalImagePath:property.value}]);return thumbnailUrl;}else{return null;}}else{return property.value;}} -return null;});}});'use strict';angular.module('umbraco').controller('Umbraco.PrevalueEditors.CropSizesController',function($scope){if(!$scope.model.value){$scope.model.value=[];} -$scope.editMode=false;$scope.setFocus=false;$scope.remove=function(item,evt){evt.preventDefault();$scope.model.value=_.reject($scope.model.value,function(x){return x.alias===item.alias;});};$scope.edit=function(item,evt){evt.preventDefault();$scope.editMode=true;$scope.setFocus=false;$scope.newItem=item;};$scope.cancel=function(evt){evt.preventDefault();$scope.editMode=false;$scope.setFocus=true;$scope.newItem=null;};$scope.change=function(){if($scope.setFocus){$scope.setFocus=false;return;}};$scope.add=function(evt){evt.preventDefault();$scope.editMode=false;$scope.setFocus=true;if($scope.newItem&&$scope.newItem.alias&&Utilities.isNumber($scope.newItem.width)&&Utilities.isNumber($scope.newItem.height)&&$scope.newItem.width>0&&$scope.newItem.height>0){var exists=_.find($scope.model.value,function(item){return $scope.newItem.alias===item.alias;});if(!exists){$scope.model.value.push($scope.newItem);$scope.newItem={};$scope.hasError=false;$scope.cropAdded=false;return;}else{$scope.newItem=null;$scope.hasError=false;return;}} -$scope.hasError=true;};$scope.sortableOptions={axis:'y'};});'use strict';function iconPreValsController($scope,editorService){if(!$scope.model.value){$scope.model.value='icon-list';} -$scope.openIconPicker=function(){var iconPicker={icon:$scope.model.value.split(' ')[0],color:$scope.model.value.split(' ')[1],submit:function submit(model){if(model.icon){if(model.color){$scope.model.value=model.icon+' '+model.color;}else{$scope.model.value=model.icon;} -$scope.iconForm.$setDirty();} -editorService.close();},close:function close(){editorService.close();}};editorService.iconPicker(iconPicker);};} -angular.module('umbraco').controller('Umbraco.PrevalueEditors.IconPickerController',iconPreValsController);'use strict';function includePropsPreValsController($rootScope,$scope,localizationService,contentTypeResource){if(!$scope.model.value){$scope.model.value=[];} -$scope.hasError=false;$scope.errorMsg='';$scope.propertyAliases=[];$scope.selectedField=null;$scope.systemFields=[{value:'sortOrder'},{value:'updateDate'},{value:'updater'},{value:'createDate'},{value:'owner'},{value:'published'},{value:'contentTypeAlias'},{value:'email'},{value:'username'}];$scope.getLocalizedKey=function(alias){switch(alias){case'name':return'general_name';case'sortOrder':return'general_sort';case'updateDate':return'content_updateDate';case'updater':return'content_updatedBy';case'createDate':return'content_createDate';case'owner':return'content_createBy';case'published':return'content_isPublished';case'contentTypeAlias':return'content_documentType';case'email':return'general_email';case'username':return'general_username';} -return alias;};$scope.changeField=function(){$scope.hasError=false;$scope.errorMsg='';};$scope.removeField=function(e){var index=$scope.model.value.indexOf(e);$scope.model.value.splice(index,1);};_.each($scope.systemFields,function(e,i){var key=$scope.getLocalizedKey(e.value);localizationService.localize(key).then(function(v){e.name=v;switch(e.value){case'updater':e.name+=' (Content only)';break;case'published':e.name+=' (Content only)';break;case'email':e.name+=' (Members only)';break;case'username':e.name+=' (Members only)';break;}});});var fixHelper=function fixHelper(e,ui){ui.children().each(function(){$(this).width($(this).width());});var row=ui.clone();row.css('background-color','lightgray');return row;};$scope.sortableOptions={helper:fixHelper,handle:'.handle',opacity:0.5,axis:'y',containment:'parent',cursor:'move',items:'> tr',tolerance:'pointer',forcePlaceholderSize:true,start:function start(e,ui){ui.placeholder.height(ui.item.height());},update:function update(e,ui){var newIndex=ui.item.index();var movedAlias=$('.alias-value',ui.item).text().trim();var originalIndex=getAliasIndexByText(movedAlias);if(originalIndex>-1){var movedElement=$scope.model.value[originalIndex];$scope.model.value.splice(originalIndex,1);$scope.model.value.splice(newIndex,0,movedElement);}}};contentTypeResource.getAllPropertyTypeAliases().then(function(data){$scope.propertyAliases=data;});$scope.addField=function(){var val=$scope.selectedField;if(val){var isSystem=val.startsWith('_system_');if(isSystem){val=val.trimStart('_system_');} -var exists=_.find($scope.model.value,function(i){return i.alias===val;});if(!exists){$scope.hasError=false;$scope.errorMsg='';$scope.model.value.push({alias:val,isSystem:isSystem?1:0});}else{$scope.hasError=true;$scope.errorMsg='Property is already added';}}else{$scope.hasError=true;$scope.errorMsg='No property selected';}};function getAliasIndexByText(value){for(var i=0;i<$scope.model.value.length;i++){if($scope.model.value[i].alias===value){return i;}} -return-1;}} -angular.module('umbraco').controller('Umbraco.PrevalueEditors.IncludePropertiesListViewController',includePropsPreValsController);'use strict';(function(){'use strict';function ListViewLayoutsPreValsController($scope,editorService){var vm=this;vm.focusLayoutName=false;vm.layoutsSortableOptions={distance:10,tolerance:'pointer',opacity:0.7,scroll:true,cursor:'move',handle:'.list-view-layout__sort-handle'};vm.addLayout=addLayout;vm.showPrompt=showPrompt;vm.hidePrompt=hidePrompt;vm.removeLayout=removeLayout;vm.openIconPicker=openIconPicker;function addLayout(){vm.focusLayoutName=false;var layout={'name':'','path':'','icon':'icon-stop','selected':true};$scope.model.value.push(layout);} -function showPrompt(layout){layout.deletePrompt=true;} -function hidePrompt(layout){layout.deletePrompt=false;} -function removeLayout($index,layout){$scope.model.value.splice($index,1);} -function openIconPicker(layout){var iconPicker={icon:layout.icon.split(' ')[0],color:layout.icon.split(' ')[1],submit:function submit(model){if(model.icon){if(model.color){layout.icon=model.icon+' '+model.color;}else{layout.icon=model.icon;}} -vm.focusLayoutName=true;editorService.close();},close:function close(){editorService.close();}};editorService.iconPicker(iconPicker);}} -angular.module('umbraco').controller('Umbraco.PrevalueEditors.ListViewLayoutsPreValsController',ListViewLayoutsPreValsController);}());'use strict';(function(){'use strict';function ListViewGridLayoutController($scope,mediaHelper,$location,listViewHelper,mediaTypeHelper){var vm=this;var umbracoSettings=Umbraco.Sys.ServerVariables.umbracoSettings;vm.nodeId=$scope.contentId;vm.acceptedFileTypes=mediaHelper.formatFileTypes(umbracoSettings.allowedUploadFiles);if(vm.acceptedFileTypes===''){vm.acceptedFileTypes=!mediaHelper.formatFileTypes(umbracoSettings.disallowedUploadFiles);} -vm.maxFileSize=umbracoSettings.maxFileSize+'KB';vm.activeDrag=false;vm.mediaDetailsTooltip={};vm.itemsWithoutFolders=[];vm.isRecycleBin=$scope.contentId==='-21'||$scope.contentId==='-20';vm.acceptedMediatypes=[];vm.dragEnter=dragEnter;vm.dragLeave=dragLeave;vm.onFilesQueue=onFilesQueue;vm.onUploadComplete=onUploadComplete;vm.hoverMediaItemDetails=hoverMediaItemDetails;vm.selectContentItem=selectContentItem;vm.selectItem=selectItem;vm.selectFolder=selectFolder;vm.goToItem=goToItem;function activate(){vm.itemsWithoutFolders=filterOutFolders($scope.items);if($scope.entityType==='media'&&!vm.isRecycleBin){mediaTypeHelper.getAllowedImagetypes(vm.nodeId).then(function(types){vm.acceptedMediatypes=types;});}} -function filterOutFolders(items){var newArray=[];if(items&&items.length){for(var i=0;items.length>i;i++){var item=items[i];var isFolder=!mediaHelper.hasFilePropertyType(item);if(!isFolder){newArray.push(item);}}} -return newArray;} -function dragEnter(el,event){vm.activeDrag=true;} -function dragLeave(el,event){vm.activeDrag=false;} -function onFilesQueue(){vm.activeDrag=false;} -function onUploadComplete(){$scope.getContent($scope.contentId);} -function hoverMediaItemDetails(item,event,hover){if(hover&&!vm.mediaDetailsTooltip.show){vm.mediaDetailsTooltip.event=event;vm.mediaDetailsTooltip.item=item;vm.mediaDetailsTooltip.show=true;}else if(!hover&&vm.mediaDetailsTooltip.show){vm.mediaDetailsTooltip.show=false;}} -function selectContentItem(item,$event,$index){listViewHelper.selectHandler(item,$index,$scope.items,$scope.selection,$event);} -function selectItem(item,$event,$index){listViewHelper.selectHandler(item,$index,vm.itemsWithoutFolders,$scope.selection,$event);} -function selectFolder(folder,$event,$index){listViewHelper.selectHandler(folder,$index,$scope.folders,$scope.selection,$event);} -function goToItem(item,$event,$index){listViewHelper.editItem(item);} -activate();} -angular.module('umbraco').controller('Umbraco.PropertyEditors.ListView.GridLayoutController',ListViewGridLayoutController);}());'use strict';(function(){'use strict';function ListViewListLayoutController($scope,listViewHelper,mediaHelper,mediaTypeHelper,urlHelper){var vm=this;var umbracoSettings=Umbraco.Sys.ServerVariables.umbracoSettings;vm.nodeId=$scope.contentId;vm.acceptedFileTypes=mediaHelper.formatFileTypes(umbracoSettings.allowedUploadFiles);if(vm.acceptedFileTypes===''){vm.acceptedFileTypes=!mediaHelper.formatFileTypes(umbracoSettings.disallowedUploadFiles);} -vm.maxFileSize=umbracoSettings.maxFileSize+'KB';vm.activeDrag=false;vm.isRecycleBin=$scope.contentId==='-21'||$scope.contentId==='-20';vm.acceptedMediatypes=[];vm.selectItem=selectItem;vm.clickItem=clickItem;vm.selectAll=selectAll;vm.isSelectedAll=isSelectedAll;vm.isSortDirection=isSortDirection;vm.sort=sort;vm.dragEnter=dragEnter;vm.dragLeave=dragLeave;vm.onFilesQueue=onFilesQueue;vm.onUploadComplete=onUploadComplete;markAsSensitive();function activate(){if($scope.entityType==='media'){mediaTypeHelper.getAllowedImagetypes(vm.nodeId).then(function(types){vm.acceptedMediatypes=types;});}} -function selectAll(){listViewHelper.selectAllItemsToggle($scope.items,$scope.selection);} -function isSelectedAll(){return listViewHelper.isSelectedAll($scope.items,$scope.selection);} -function selectItem(selectedItem,$index,$event){listViewHelper.selectHandler(selectedItem,$index,$scope.items,$scope.selection,$event);} -function clickItem(item){listViewHelper.editItem(item);} -function isSortDirection(col,direction){return listViewHelper.setSortingDirection(col,direction,$scope.options);} -function sort(field,allow,isSystem){if(allow){$scope.options.orderBySystemField=isSystem;listViewHelper.setSorting(field,allow,$scope.options);$scope.getContent($scope.contentId);}} -function dragEnter(el,event){vm.activeDrag=true;} -function dragLeave(el,event){vm.activeDrag=false;} -function onFilesQueue(){vm.activeDrag=false;} -function onUploadComplete(){$scope.getContent($scope.contentId);} -function markAsSensitive(){angular.forEach($scope.options.includeProperties,function(option){option.isSensitive=false;angular.forEach($scope.items,function(item){angular.forEach(item.properties,function(property){if(option.alias===property.alias){option.isSensitive=property.isSensitive;}});});});} -activate();} -angular.module('umbraco').controller('Umbraco.PropertyEditors.ListView.ListLayoutController',ListViewListLayoutController);}());'use strict';function listViewController($scope,$interpolate,$routeParams,$injector,$timeout,currentUserResource,notificationsService,iconHelper,editorState,localizationService,appState,$location,listViewHelper,navigationService,editorService,overlayService,languageResource,mediaHelper,eventsService){if($routeParams.create){$scope.isNew=true;return;} -var contentResource,getContentTypesCallback,getListResultsCallback,deleteItemCallback,getIdCallback,createEditUrlCallback;if($scope.model.config.entityType&&$scope.model.config.entityType==='member'||appState.getSectionState('currentSection')==='member'){$scope.entityType='member';contentResource=$injector.get('memberResource');getContentTypesCallback=$injector.get('memberTypeResource').getTypes;getListResultsCallback=contentResource.getPagedResults;deleteItemCallback=contentResource.deleteByKey;getIdCallback=function getIdCallback(selected){return selected.key;};createEditUrlCallback=function createEditUrlCallback(item){return'/'+$scope.entityType+'/'+$scope.entityType+'/edit/'+item.key+'?page='+$scope.options.pageNumber+'&listName='+$scope.contentId;};}else{if($scope.model.config.entityType&&$scope.model.config.entityType==='media'||appState.getSectionState('currentSection')==='media'){$scope.entityType='media';contentResource=$injector.get('mediaResource');getContentTypesCallback=$injector.get('mediaTypeResource').getAllowedTypes;}else{$scope.entityType='content';contentResource=$injector.get('contentResource');getContentTypesCallback=$injector.get('contentTypeResource').getAllowedTypes;} -getListResultsCallback=contentResource.getChildren;deleteItemCallback=contentResource.deleteById;getIdCallback=function getIdCallback(selected){return selected.id;};createEditUrlCallback=function createEditUrlCallback(item){return'/'+$scope.entityType+'/'+$scope.entityType+'/edit/'+item.id+'?list='+$routeParams.id+'&page='+$scope.options.pageNumber+'&filter='+$scope.options.filter+'&orderBy='+$scope.options.orderBy+'&orderDirection='+$scope.options.orderDirection;};} -$scope.pagination=[];$scope.isNew=false;$scope.actionInProgress=false;$scope.selection=[];$scope.folders=[];$scope.page={createDropdownOpen:false};$scope.listViewResultSet={totalPages:0,items:[]};$scope.createAllowedButtonSingle=false;$scope.createAllowedButtonSingleWithBlueprints=false;$scope.createAllowedButtonMultiWithBlueprints=false;$scope.currentNodePermissions=null;if($scope.entityType==='content'){if(editorState.current){var currentUserPermissions=editorState.current.allowedActions;$scope.currentNodePermissions={'canCopy':_.contains(currentUserPermissions,'O'),'canCreate':_.contains(currentUserPermissions,'C'),'canDelete':_.contains(currentUserPermissions,'D'),'canMove':_.contains(currentUserPermissions,'M'),'canPublish':_.contains(currentUserPermissions,'U'),'canUnpublish':_.contains(currentUserPermissions,'U')};}} -$scope.buttonPermissions=null;if($scope.entityType==='content'){var idsWithPermissions=null;$scope.buttonPermissions={canCopy:true,canCreate:true,canDelete:true,canMove:true,canPublish:true,canUnpublish:true};$scope.$watch('selection.length',function(newVal,oldVal){if(idsWithPermissions==null&&newVal>0||idsWithPermissions!=null){var ids=_.map($scope.selection,function(i){return i.id.toString();});var filtered={};_.each(idsWithPermissions,function(value,key,list){if(_.contains(ids,key)){filtered[key]=value;}});idsWithPermissions=filtered;var existingIds=_.keys(idsWithPermissions);var missingLookup=_.map(_.difference(ids,existingIds),function(i){return Number(i);});if(missingLookup.length>0){currentUserResource.getPermissions(missingLookup).then(function(p){$scope.buttonPermissions=listViewHelper.getButtonPermissions(p,idsWithPermissions);});}else{$scope.buttonPermissions=listViewHelper.getButtonPermissions({},idsWithPermissions);}}});} -var listParamsForCurrent=$routeParams.id==$routeParams.list;$scope.options={pageSize:$scope.model.config.pageSize?$scope.model.config.pageSize:10,pageNumber:listParamsForCurrent&&$routeParams.page&&Number($routeParams.page)!=NaN&&Number($routeParams.page)>0?$routeParams.page:1,filter:(listParamsForCurrent&&$routeParams.filter?$routeParams.filter:'').trim(),orderBy:(listParamsForCurrent&&$routeParams.orderBy?$routeParams.orderBy:$scope.model.config.orderBy?$scope.model.config.orderBy:'VersionDate').trim(),orderDirection:(listParamsForCurrent&&$routeParams.orderDirection?$routeParams.orderDirection:$scope.model.config.orderDirection?$scope.model.config.orderDirection:'desc').trim(),orderBySystemField:true,includeProperties:$scope.model.config.includeProperties?$scope.model.config.includeProperties:[{alias:'updateDate',header:'Last edited',isSystem:1},{alias:'updater',header:'Last edited by',isSystem:1}],layout:{layouts:$scope.model.config.layouts,activeLayout:listViewHelper.getLayout($routeParams.id,$scope.model.config.layouts)},allowBulkPublish:$scope.entityType==='content'&&$scope.model.config.bulkActionPermissions.allowBulkPublish,allowBulkUnpublish:$scope.entityType==='content'&&$scope.model.config.bulkActionPermissions.allowBulkUnpublish,allowBulkCopy:$scope.entityType==='content'&&$scope.model.config.bulkActionPermissions.allowBulkCopy,allowBulkMove:$scope.entityType!=='member'&&$scope.model.config.bulkActionPermissions.allowBulkMove,allowBulkDelete:$scope.model.config.bulkActionPermissions.allowBulkDelete,cultureName:$routeParams.cculture?$routeParams.cculture:$routeParams.mculture};_.each($scope.options.includeProperties,function(property){property.nameExp=!!property.nameTemplate?$interpolate(property.nameTemplate):undefined;});$scope.$watch(function(){return $routeParams.cculture?$routeParams.cculture:$routeParams.mculture;},function(newVal,oldVal){if(newVal&&newVal!==oldVal){$scope.options.cultureName=newVal;$scope.reloadView($scope.contentId);}});for(var j=0;j<$scope.options.includeProperties.length;j++){var includedProperty=$scope.options.includeProperties[j];if(includedProperty.alias.toLowerCase()===$scope.options.orderBy.toLowerCase()){$scope.options.orderBySystemField=includedProperty.isSystem===1;break;}} -_.each($scope.options.includeProperties,function(e,i){e.allowSorting=true;if(e.isSystem&&$scope.entityType==='member'){e.allowSorting=e.alias==='username'||e.alias==='email'||e.alias==='updateDate'||e.alias==='createDate'||e.alias==='contentTypeAlias';} -if(e.isSystem){var key=getLocalizedKey(e.alias);localizationService.localize(key).then(function(v){e.header=v;});}});$scope.selectLayout=function(layout){$scope.options.layout.activeLayout=listViewHelper.setLayout($routeParams.id,layout,$scope.model.config.layouts);};function showNotificationsAndReset(err,reload,successMsgPromise){if(err.status&&err.status>=500){$scope.ysodOverlay={view:'ysod',error:err,show:true};} -$timeout(function(){$scope.bulkStatus='';$scope.actionInProgress=false;},500);if(successMsgPromise){localizationService.localize('bulk_done').then(function(v){successMsgPromise.then(function(successMsg){notificationsService.success(v,successMsg);});});}} -$scope.next=function(pageNumber){$scope.options.pageNumber=pageNumber;$scope.reloadView($scope.contentId);};$scope.goToPage=function(pageNumber){$scope.options.pageNumber=pageNumber;$scope.reloadView($scope.contentId);};$scope.prev=function(pageNumber){$scope.options.pageNumber=pageNumber;$scope.reloadView($scope.contentId);};$scope.getContent=function(contentId){$scope.reloadView($scope.contentId,true);};$scope.reloadView=function(id,reloadActiveNode){if(!id){return;} -$scope.viewLoaded=false;$scope.folders=[];listViewHelper.clearSelection($scope.listViewResultSet.items,$scope.folders,$scope.selection);getListResultsCallback(id,$scope.options).then(function(data){$scope.actionInProgress=false;$scope.listViewResultSet=data;var section=appState.getSectionState('currentSection');if($scope.listViewResultSet.items){_.each($scope.listViewResultSet.items,function(e,index){setPropertyValues(e);if(section==='media'&&!mediaHelper.hasFilePropertyType(e)){$scope.folders.push(e);}});} -$scope.viewLoaded=true;if($scope.options.pageNumber>$scope.listViewResultSet.totalPages){$scope.options.pageNumber=$scope.listViewResultSet.totalPages;$scope.reloadView(id,reloadActiveNode);} -else if(reloadActiveNode&§ion==='media'){var activeNode=appState.getTreeState('selectedNode');if(activeNode){if(activeNode.expanded){navigationService.reloadNode(activeNode);}}else{navigationService.reloadSection(section);}}});};$scope.makeSearch=function(){if($scope.options.filter!==null&&$scope.options.filter!==undefined){$scope.options.pageNumber=1;$scope.reloadView($scope.contentId);}};$scope.onSearchStartTyping=function(){$scope.viewLoaded=false;};$scope.selectedItemsCount=function(){return $scope.selection.length;};$scope.clearSelection=function(){listViewHelper.clearSelection($scope.listViewResultSet.items,$scope.folders,$scope.selection);};$scope.getIcon=function(entry){return iconHelper.convertFromLegacyIcon(entry.icon);};function serial(selected,fn,getStatusMsg,index){return fn(selected,index).then(function(content){index++;getStatusMsg(index,selected.length).then(function(value){$scope.bulkStatus=value;});return index0;showNotificationsAndReset(err,reload);return err;});} -function applySelected(fn,getStatusMsg,getSuccessMsg,confirmMsg){var selected=$scope.selection;if(selected.length===0) -return;if(confirmMsg&&!confirm(confirmMsg)) -return;$scope.actionInProgress=true;getStatusMsg(0,selected.length).then(function(value){$scope.bulkStatus=value;});return serial(selected,fn,getStatusMsg,0).then(function(result){if(!(result.data&&Utilities.isArray(result.data.notifications))) -showNotificationsAndReset(result,true,getSuccessMsg(selected.length));});} -$scope.delete=function(){var dialog={view:'views/propertyeditors/listview/overlays/delete.html',deletesVariants:selectionHasVariants(),isTrashed:$scope.isTrashed,submitButtonLabelKey:'contentTypeEditor_yesDelete',submitButtonStyle:'danger',submit:function submit(model){performDelete();overlayService.close();},close:function close(){overlayService.close();}};localizationService.localize('general_delete').then(function(value){dialog.title=value;overlayService.open(dialog);});};function performDelete(){applySelected(function(selected,index){return deleteItemCallback(getIdCallback(selected[index]));},function(count,total){var key=total===1?'bulk_deletedItemOfItem':'bulk_deletedItemOfItems';return localizationService.localize(key,[count,total]);},function(total){var key=total===1?'bulk_deletedItem':'bulk_deletedItems';return localizationService.localize(key,[total]);}).then(function(){$scope.reloadView($scope.contentId,true);});} -function selectionHasVariants(){var variesByCulture=false;$scope.selection.forEach(function(selectedItem){$scope.listViewResultSet.items.forEach(function(resultItem){if((selectedItem.id===resultItem.id||selectedItem.key===resultItem.key)&&resultItem.variesByCulture){variesByCulture=true;}});});return variesByCulture;} -$scope.publish=function(){var dialog={view:'views/propertyeditors/listview/overlays/listviewpublish.html',submitButtonLabelKey:'actions_publish',submit:function submit(model){var selectedCultures=[];if(model.languages&&model.languages.length>0){model.languages.forEach(function(language){if(language.publish){selectedCultures.push(language.culture);}});} -performPublish(selectedCultures);overlayService.close();},close:function close(){overlayService.close();}};if(selectionHasVariants()){languageResource.getAll().then(function(languages){dialog.languages=languages;overlayService.open(dialog);},function(error){notificationsService.error(error);});}else{overlayService.open(dialog);}};function performPublish(cultures){applySelected(function(selected,index){return contentResource.publishById(getIdCallback(selected[index]),cultures);},function(count,total){var key=total===1?'bulk_publishedItemOfItem':'bulk_publishedItemOfItems';return localizationService.localize(key,[count,total]);},function(total){var key=total===1?'bulk_publishedItem':'bulk_publishedItems';return localizationService.localize(key,[total]);}).then(function(){$scope.reloadView($scope.contentId);});} -$scope.unpublish=function(){var dialog={view:'views/propertyeditors/listview/overlays/listviewunpublish.html',submitButtonLabelKey:'actions_unpublish',submitButtonStyle:'warning',submit:function submit(model){var selectedCultures=[];if(model.languages&&model.languages.length>0){model.languages.forEach(function(language){if(language.unpublish){selectedCultures.push(language.culture);}});} -performUnpublish(selectedCultures);overlayService.close();},close:function close(){overlayService.close();}};if(selectionHasVariants()){languageResource.getAll().then(function(languages){dialog.languages=languages;overlayService.open(dialog);},function(error){notificationsService.error(error);});}else{overlayService.open(dialog);}};function performUnpublish(cultures){applySelected(function(selected,index){return contentResource.unpublish(getIdCallback(selected[index]),cultures);},function(count,total){var key=total===1?'bulk_unpublishedItemOfItem':'bulk_unpublishedItemOfItems';return localizationService.localize(key,[count,total]);},function(total){var key=total===1?'bulk_unpublishedItem':'bulk_unpublishedItems';return localizationService.localize(key,[total]);}).then(function(){$scope.reloadView($scope.contentId,true);});} -$scope.move=function(){var move={section:$scope.entityType,currentNode:$scope.contentId,submit:function submit(model){if(model.target){performMove(model.target);} -editorService.close();},close:function close(){editorService.close();}};editorService.move(move);};function performMove(target){var newPath=null;applySelected(function(selected,index){return contentResource.move({parentId:target.id,id:getIdCallback(selected[index])}).then(function(path){newPath=path;return path;});},function(count,total){var key=total===1?'bulk_movedItemOfItem':'bulk_movedItemOfItems';return localizationService.localize(key,[count,total]);},function(total){var key=total===1?'bulk_movedItem':'bulk_movedItems';return localizationService.localize(key,[total]);}).then(function(){if(newPath){$scope.reloadView($scope.contentId);navigationService.syncTree({tree:target.nodeType?target.nodeType:target.metaData.treeAlias,path:newPath,forceReload:true,activate:false}).then(function(args){var activeNode=appState.getTreeState('selectedNode');if(activeNode){navigationService.reloadNode(activeNode);}});}});} -$scope.copy=function(){var copyEditor={section:$scope.entityType,currentNode:$scope.contentId,submit:function submit(model){if(model.target){performCopy(model.target,model.relateToOriginal,model.includeDescendants);} -editorService.close();},close:function close(){editorService.close();}};editorService.copy(copyEditor);};function performCopy(target,relateToOriginal,includeDescendants){applySelected(function(selected,index){return contentResource.copy({parentId:target.id,id:getIdCallback(selected[index]),relateToOriginal:relateToOriginal,recursive:includeDescendants});},function(count,total){var key=total===1?'bulk_copiedItemOfItem':'bulk_copiedItemOfItems';return localizationService.localize(key,[count,total]);},function(total){var key=total===1?'bulk_copiedItem':'bulk_copiedItems';return localizationService.localize(key,[total]);});} -function getCustomPropertyValue(alias,properties){var value='';var index=0;var foundAlias=false;for(var i=0;i1){$scope.createAllowedButtonMultiWithBlueprints=true;}});} -$scope.reloadView($scope.contentId);} -function getLocalizedKey(alias){switch(alias){case'sortOrder':return'general_sort';case'updateDate':return'content_updateDate';case'updater':return'content_updatedBy';case'createDate':return'content_createDate';case'owner':return'content_createBy';case'published':return'content_isPublished';case'contentTypeAlias':return $scope.entityType==='content'?'content_documentType':$scope.entityType==='media'?'content_mediatype':'content_membertype';case'email':return'general_email';case'username':return'general_username';} -return alias;} -function getItemKey(itemId){for(var i=0;i<$scope.listViewResultSet.items.length;i++){var item=$scope.listViewResultSet.items[i];if(item.id===itemId){return item.key;}}} -function createBlank(entityType,docTypeAlias){$location.path('/'+entityType+'/'+entityType+'/edit/'+$scope.contentId).search('doctype',docTypeAlias).search('create','true');} -function createFromBlueprint(entityType,docTypeAlias,blueprintId){$location.path('/'+entityType+'/'+entityType+'/edit/'+$scope.contentId).search('doctype',docTypeAlias).search('create','true').search('blueprintId',blueprintId);} -function toggleDropdown(){$scope.page.createDropdownOpen=!$scope.page.createDropdownOpen;} -function leaveDropdown(){$scope.page.createDropdownOpen=false;} -$scope.createBlank=createBlank;$scope.createFromBlueprint=createFromBlueprint;$scope.toggleDropdown=toggleDropdown;$scope.leaveDropdown=leaveDropdown;if(_.find($scope.options.includeProperties,function(property){return property.alias==='sortOrder';})){var eventSubscription=eventsService.on('sortCompleted',function(e,args){if(parseInt(args.id)===parseInt($scope.contentId)){$scope.reloadView($scope.contentId);}});$scope.$on('$destroy',function(){eventsService.unsubscribe(eventSubscription);});} -initView();} -angular.module('umbraco').controller('Umbraco.PropertyEditors.ListViewController',listViewController);'use strict';(function(){'use strict';function ListViewPublishController($scope,$routeParams,localizationService){var vm=this;vm.loading=true;vm.changeSelection=changeSelection;function changeSelection(language){var firstSelected=_.find(vm.languages,function(language){return language.publish;});$scope.model.disableSubmitButton=!firstSelected;language.save=language.publish;} -function onInit(){vm.languages=$scope.model.languages;if(!$scope.model.title){localizationService.localize('content_readyToPublish').then(function(value){$scope.model.title=value;});} -if(vm.languages&&vm.languages.length>0){var culture=$routeParams.cculture?$routeParams.cculture:$routeParams.mculture;if(culture){vm.languages=_.sortBy(vm.languages,function(language){return language.culture===culture?0:1;});var active=_.find(vm.languages,function(language){return language.culture===culture;});if(active){active.publish=true;}}} -vm.loading=false;} -onInit();$scope.$on('$destroy',function(){if(vm.languages&&vm.languages.length>0){for(var i=0;i0){var culture=$routeParams.cculture?$routeParams.cculture:$routeParams.mculture;if(culture){vm.languages=_.sortBy(vm.languages,function(language){return language.culture===culture?0:1;});var active=_.find(vm.languages,function(language){return language.culture===culture;});if(active){active.unpublish=true;changeSelection(active);}}} -vm.loading=false;} -onInit();$scope.$on('$destroy',function(){if(vm.languages&&vm.languages.length>0){for(var i=0;i div.textbox-wrapper',tolerance:'pointer'};if(!$scope.model.value){$scope.model.value=[];} -if($scope.model.config.min>0){for(var i=0;i<$scope.model.config.min;i++){if(i+1>$scope.model.value.length){$scope.model.value.push({value:''});}}} -$scope.addRemoveOnKeyDown=function(event,index){var txtBoxValue=$scope.model.value[index];event.preventDefault();switch(event.keyCode){case 13:if($scope.model.config.max<=0&&txtBoxValue.value||$scope.model.value.length<$scope.model.config.max&&txtBoxValue.value){var newItemIndex=index+1;$scope.model.value.splice(newItemIndex,0,{value:''});$scope.model.value[newItemIndex].hasFocus=true;} -break;case 8:if($scope.model.value.length>$scope.model.config.min){var remainder=[];if(txtBoxValue.value===''){backspaceHits++;}else{backspaceHits=0;} -if(txtBoxValue.value===''&&backspaceHits===2){for(var x=0;x<$scope.model.value.length;x++){if(x!==index){remainder.push($scope.model.value[x]);}} -$scope.model.value=remainder;var prevItemIndex=index-1;if(prevItemIndex>=0){$scope.model.value[prevItemIndex].hasFocus=false;$timeout(function(){$scope.model.value[prevItemIndex].hasFocus=true;});} -backspaceHits=0;}} -break;default:} -validate();};$scope.add=function(){if($scope.model.config.max<=0||$scope.model.value.length<$scope.model.config.max){$scope.model.value.push({value:''});var newItemIndex=$scope.model.value.length-1;$scope.model.value[newItemIndex].hasFocus=true;} -validate();};$scope.remove=function(index){$scope.hidePrompt();var remainder=[];for(var x=0;x<$scope.model.value.length;x++){if(x!==index){remainder.push($scope.model.value[x]);}} -$scope.model.value=remainder;};$scope.showPrompt=function(idx,item){var i=$scope.model.value.indexOf(item);if(i===idx){$scope.promptIsVisible=i;}};$scope.hidePrompt=function(){$scope.promptIsVisible='-1';};function validate(){if($scope.multipleTextboxForm){var invalid=$scope.model.validation.mandatory&&!$scope.model.value.length;$scope.multipleTextboxForm.mandatory.$setValidity('minCount',!invalid);}} -$timeout(function(){validate();});} -angular.module('umbraco').controller('Umbraco.PropertyEditors.MultipleTextBoxController',MultipleTextBoxController);'use strict';function multiUrlPickerController($scope,angularHelper,localizationService,entityResource,iconHelper,editorService){var vm={labels:{general_recycleBin:''}};$scope.renderModel=[];if($scope.preview){return;} -if(!Array.isArray($scope.model.value)){$scope.model.value=[];} -var currentForm=angularHelper.getCurrentForm($scope);$scope.sortableOptions={axis:'y',containment:'parent',distance:10,opacity:0.7,tolerance:'pointer',scroll:true,zIndex:6000,update:function update(){currentForm.$setDirty();}};$scope.model.value.forEach(function(link){link.icon=iconHelper.convertFromLegacyIcon(link.icon);$scope.renderModel.push(link);});$scope.$on('formSubmitting',function(){$scope.model.value=$scope.renderModel;});$scope.$watch(function(){return $scope.renderModel.length;},function(){if($scope.model.config&&$scope.model.config.minNumber&&parseInt($scope.model.config.minNumber)>$scope.renderModel.length){$scope.multiUrlPickerForm.minCount.$setValidity('minCount',false);}else{$scope.multiUrlPickerForm.minCount.$setValidity('minCount',true);} -if($scope.model.config&&$scope.model.config.maxNumber&&parseInt($scope.model.config.maxNumber)<$scope.renderModel.length){$scope.multiUrlPickerForm.maxCount.$setValidity('maxCount',false);}else{$scope.multiUrlPickerForm.maxCount.$setValidity('maxCount',true);} -$scope.sortableOptions.disabled=$scope.renderModel.length===1;});$scope.remove=function($index){$scope.renderModel.splice($index,1);currentForm.$setDirty();};$scope.openLinkPicker=function(link,$index){var target=link?{name:link.name,anchor:link.queryString,udi:link.udi,url:link.url,target:link.target}:null;var linkPicker={currentTarget:target,dataTypeKey:$scope.model.dataTypeKey,ignoreUserStartNodes:$scope.model.config&&$scope.model.config.ignoreUserStartNodes?$scope.model.config.ignoreUserStartNodes:'0',hideAnchor:$scope.model.config&&$scope.model.config.hideAnchor?true:false,submit:function submit(model){if(model.target.url||model.target.anchor){if(model.target.anchor&&model.target.anchor[0]!=='?'&&model.target.anchor[0]!=='#'){model.target.anchor=(model.target.anchor.indexOf('=')===-1?'#':'?')+model.target.anchor;} -if(link){link.udi=model.target.udi;link.name=model.target.name||model.target.url||model.target.anchor;link.queryString=model.target.anchor;link.target=model.target.target;link.url=model.target.url;}else{link={name:model.target.name||model.target.url||model.target.anchor,queryString:model.target.anchor,target:model.target.target,udi:model.target.udi,url:model.target.url};$scope.renderModel.push(link);} -if(link.udi){var entityType=model.target.isMedia?'Media':'Document';entityResource.getById(link.udi,entityType).then(function(data){link.icon=iconHelper.convertFromLegacyIcon(data.icon);link.published=data.metaData&&data.metaData.IsPublished===false&&entityType==='Document'?false:true;link.trashed=data.trashed;if(link.trashed){item.url=vm.labels.general_recycleBin;}});}else{link.icon='icon-link';link.published=true;} -currentForm.$setDirty();} -editorService.close();},close:function close(){editorService.close();}};editorService.linkPicker(linkPicker);};function init(){localizationService.localizeMany(['general_recycleBin']).then(function(data){vm.labels.general_recycleBin=data[0];});if($scope.model.validation&&$scope.model.validation.mandatory&&!$scope.model.config.minNumber){$scope.model.config.minNumber=1;} -_.each($scope.model.value,function(item){if(item.udi&&item.udi.indexOf('/document/')>0){item.url=null;entityResource.getUrlByUdi(item.udi).then(function(data){item.url=data;});}});} -init();} -angular.module('umbraco').controller('Umbraco.PropertyEditors.MultiUrlPickerController',multiUrlPickerController);'use strict';function _typeof(obj){if(typeof Symbol==='function'&&typeof Symbol.iterator==='symbol'){_typeof=function _typeof(obj){return typeof obj;};}else{_typeof=function _typeof(obj){return obj&&typeof Symbol==='function'&&obj.constructor===Symbol&&obj!==Symbol.prototype?'symbol':typeof obj;};} -return _typeof(obj);} -(function(){'use strict';angular.module('umbraco').run(['clipboardService',function(clipboardService){function clearNestedContentPropertiesForStorage(prop,propClearingMethod){if(_typeof(prop)==='object'&&prop.editor==='Umbraco.NestedContent'){var value=prop.value;for(var i=0;i0&&prop[0].ncContentTypeAlias!==undefined){for(var i=0;i
Minimum %0% entries, needs %1% more.
Maximum %0% entries, %1% too many.
',controller:NestedContentController,controllerAs:'vm',require:{umbProperty:'?^umbProperty',umbVariantContent:'?^^umbVariantContent'}});function NestedContentController($scope,$interpolate,$filter,serverValidationManager,contentResource,localizationService,iconHelper,clipboardService,eventsService,overlayService){var vm=this;var model=$scope.$parent.$parent.model;var contentTypeAliases=[];_.each(model.config.contentTypes,function(contentType){contentTypeAliases.push(contentType.ncAlias);});_.each(model.config.contentTypes,function(contentType){contentType.nameExp=!!contentType.nameTemplate?$interpolate(contentType.nameTemplate):undefined;});vm.nodes=[];vm.currentNode=null;vm.scaffolds=null;vm.sorting=false;vm.inited=false;vm.minItems=model.config.minItems||0;vm.maxItems=model.config.maxItems||0;if(vm.maxItems===0) -vm.maxItems=1000;vm.singleMode=vm.minItems===1&&vm.maxItems===1&&model.config.contentTypes.length===1;;vm.showIcons=Object.toBoolean(model.config.showIcons);vm.wideMode=Object.toBoolean(model.config.hideLabel);vm.hasContentTypes=model.config.contentTypes.length>0;var labels={};vm.labels=labels;localizationService.localizeMany(['grid_addElement','content_createEmpty','actions_copy']).then(function(data){labels.grid_addElement=data[0];labels.content_createEmpty=data[1];labels.copy_icon_title=data[2];});function setCurrentNode(node){updateModel();vm.currentNode=node;} -var copyAllEntries=function copyAllEntries(){syncCurrentNode();var aliases=vm.nodes.map(function(node){return node.contentTypeAlias;});aliases=aliases.filter(function(item,index){return aliases.indexOf(item)===index;});var nodeName='';if(vm.umbVariantContent){nodeName=vm.umbVariantContent.editor.content.name;} -localizationService.localize('clipboard_labelForArrayOfItemsFrom',[model.label,nodeName]).then(function(data){clipboardService.copyArray('elementTypeArray',aliases,vm.nodes,data,'icon-thumbnail-list',model.id,clearNodeForCopy);});};var copyAllEntriesAction={labelKey:'clipboard_labelForCopyAllEntries',labelTokens:[model.label],icon:'documents',method:copyAllEntries,isDisabled:true};var removeAllEntries=function removeAllEntries(){localizationService.localizeMany(['content_nestedContentDeleteAllItems','general_delete']).then(function(data){overlayService.confirmDelete({title:data[1],content:data[0],close:function close(){overlayService.close();},submit:function submit(){vm.nodes=[];setDirty();updateModel();overlayService.close();}});});};var removeAllEntriesAction={labelKey:'clipboard_labelForRemoveAllEntries',labelTokens:[],icon:'trash',method:removeAllEntries,isDisabled:true};function setDirty(){if($scope.$parent.$parent.propertyForm){$scope.$parent.$parent.propertyForm.$setDirty();}};function addNode(alias){var scaffold=getScaffold(alias);var newNode=createNode(scaffold,null);setCurrentNode(newNode);setDirty();validate();};vm.openNodeTypePicker=function($event){if(vm.overlayMenu||vm.nodes.length>=vm.maxItems){return;} -vm.overlayMenu={show:false,style:{},filter:vm.scaffolds.length>12?true:false,orderBy:'$index',view:'itempicker',event:$event,clickPasteItem:function clickPasteItem(item){if(item.type==='elementTypeArray'){_.each(item.data,function(entry){pasteFromClipboard(entry);});}else{pasteFromClipboard(item.data);} -vm.overlayMenu.show=false;vm.overlayMenu=null;},submit:function submit(model){if(model&&model.selectedItem){addNode(model.selectedItem.alias);} -vm.overlayMenu.show=false;vm.overlayMenu=null;},close:function close(){vm.overlayMenu.show=false;vm.overlayMenu=null;}};vm.overlayMenu.availableItems=[];_.each(vm.scaffolds,function(scaffold){vm.overlayMenu.availableItems.push({alias:scaffold.contentTypeAlias,name:scaffold.contentTypeName,icon:iconHelper.convertFromLegacyIcon(scaffold.icon),tooltip:scaffold.documentType.description});});if(vm.overlayMenu.availableItems.length===0){return;} -vm.overlayMenu.size=vm.overlayMenu.availableItems.length>6?'medium':'small';vm.overlayMenu.pasteItems=[];var singleEntriesForPaste=clipboardService.retriveEntriesOfType('elementType',contentTypeAliases);_.each(singleEntriesForPaste,function(entry){vm.overlayMenu.pasteItems.push({type:'elementType',name:entry.label,data:entry.data,icon:entry.icon});});var arrayEntriesForPaste=clipboardService.retriveEntriesOfType('elementTypeArray',contentTypeAliases);_.each(arrayEntriesForPaste,function(entry){vm.overlayMenu.pasteItems.push({type:'elementTypeArray',name:entry.label,data:entry.data,icon:entry.icon});});vm.overlayMenu.title=labels.grid_addElement;vm.overlayMenu.hideHeader=vm.overlayMenu.pasteItems.length>0;vm.overlayMenu.clickClearPaste=function($event){$event.stopPropagation();$event.preventDefault();clipboardService.clearEntriesOfType('elementType',contentTypeAliases);clipboardService.clearEntriesOfType('elementTypeArray',contentTypeAliases);vm.overlayMenu.pasteItems=[];vm.overlayMenu.hideHeader=false;};if(vm.overlayMenu.availableItems.length===1&&vm.overlayMenu.pasteItems.length===0){addNode(vm.scaffolds[0].contentTypeAlias);vm.overlayMenu=null;return;} -vm.overlayMenu.show=true;};vm.editNode=function(idx){if(vm.currentNode&&vm.currentNode.key===vm.nodes[idx].key){setCurrentNode(null);}else{setCurrentNode(vm.nodes[idx]);}};vm.canDeleteNode=function(idx){return vm.nodes.length>vm.minItems?true:model.config.contentTypes.length>1;};function deleteNode(idx){var removed=vm.nodes.splice(idx,1);setDirty();removed.forEach(function(x){serverValidationManager.removePropertyError(x.key,vm.umbProperty.property.culture,vm.umbProperty.property.segment,'',{matchType:'contains'});});updateModel();validate();};vm.requestDeleteNode=function(idx){if(!vm.canDeleteNode(idx)){return;} -if(model.config.confirmDeletes===true){localizationService.localizeMany(['content_nestedContentDeleteItem','general_delete','general_cancel','contentTypeEditor_yesDelete']).then(function(data){var overlay={title:data[1],content:data[0],closeButtonLabel:data[2],submitButtonLabel:data[3],submitButtonStyle:'danger',close:function close(){overlayService.close();},submit:function submit(){deleteNode(idx);overlayService.close();}};overlayService.open(overlay);});}else{deleteNode(idx);}};vm.getName=function(idx){if(!model.value||!model.value.length){return'';} -var name='';if(model.value[idx]){var contentType=getContentTypeConfig(model.value[idx].ncContentTypeAlias);if(contentType!=null){if(contentType.nameExp){var item=model.value[idx];item['$index']=idx+1;var newName=contentType.nameExp(item);if(newName&&(newName=$.trim(newName))){name=newName;} -delete item['$index'];} -if(!name&&vm.scaffolds.length>1){var scaffold=getScaffold(contentType.ncAlias);if(scaffold){name=scaffold.contentTypeName;}}}} -if(!name){name='Item '+(idx+1);} -if(vm.nodes[idx].name!==name){vm.nodes[idx].name=name;} -return name;};vm.getIcon=function(idx){if(!model.value||!model.value.length){return'';} -var scaffold=getScaffold(model.value[idx].ncContentTypeAlias);return scaffold&&scaffold.icon?iconHelper.convertFromLegacyIcon(scaffold.icon):'icon-folder';};vm.sortableOptions={axis:'y',cursor:'move',handle:'.umb-nested-content__header-bar',distance:10,opacity:0.7,tolerance:'pointer',scroll:true,start:function start(ev,ui){updateModel();$('#umb-nested-content--'+model.id+' .umb-rte textarea').each(function(){tinymce.execCommand('mceRemoveEditor',false,$(this).attr('id'));$(this).css('visibility','hidden');});$scope.$apply(function(){vm.sorting=true;});},update:function update(ev,ui){setDirty();},stop:function stop(ev,ui){$('#umb-nested-content--'+model.id+' .umb-rte textarea').each(function(){tinymce.execCommand('mceAddEditor',true,$(this).attr('id'));$(this).css('visibility','visible');});$scope.$apply(function(){vm.sorting=false;updateModel();});}};function getScaffold(alias){return _.find(vm.scaffolds,function(scaffold){return scaffold.contentTypeAlias===alias;});} -function getContentTypeConfig(alias){return _.find(model.config.contentTypes,function(contentType){return contentType.ncAlias===alias;});} -function clearNodeForCopy(clonedData){delete clonedData.key;delete clonedData.$$hashKey;} -vm.showCopy=clipboardService.isSupported();vm.showPaste=false;vm.clickCopy=function($event,node){syncCurrentNode();clipboardService.copy('elementType',node.contentTypeAlias,node,null,null,null,clearNodeForCopy);$event.stopPropagation();};function pasteFromClipboard(newNode){if(newNode===undefined){return;} -newNode.key=String.CreateGuid();vm.nodes.push(newNode);setDirty();setCurrentNode(newNode);} -function checkAbilityToPasteContent(){vm.showPaste=clipboardService.hasEntriesOfType('elementType',contentTypeAliases)||clipboardService.hasEntriesOfType('elementTypeArray',contentTypeAliases);} -eventsService.on('clipboardService.storageUpdate',checkAbilityToPasteContent);var notSupported=['Umbraco.Tags','Umbraco.UploadField','Umbraco.ImageCropper','Umbraco.BlockList'];var scaffoldsLoaded=0;vm.scaffolds=[];_.each(model.config.contentTypes,function(contentType){contentResource.getScaffold(-20,contentType.ncAlias).then(function(scaffold){if(scaffold.isElement){var tabs=scaffold.variants[0].tabs;var tab=_.find(tabs,function(tab){return tab.id!==0&&(tab.alias.toLowerCase()===contentType.ncTabAlias.toLowerCase()||contentType.ncTabAlias==='');});scaffold.variants[0].tabs=[];if(tab){scaffold.variants[0].tabs.push(tab);angular.forEach(tab.properties,function(property){if(_.find(notSupported,function(x){return x===property.editor;})){property.notSupported=true;property.notSupportedMessage='Property '+property.label+' uses editor '+property.editor+' which is not supported by Nested Content.';}});} -vm.scaffolds.push(scaffold);} -scaffoldsLoaded++;initIfAllScaffoldsHaveLoaded();},function(error){scaffoldsLoaded++;initIfAllScaffoldsHaveLoaded();});});var initIfAllScaffoldsHaveLoaded=function initIfAllScaffoldsHaveLoaded(){if(model.config.contentTypes.length===scaffoldsLoaded){contentTypeAliases=[];_.each(model.config.contentTypes,function(contentType){contentTypeAliases.push(contentType.ncAlias);});vm.scaffolds=$filter('orderBy')(vm.scaffolds,function(s){return contentTypeAliases.indexOf(s.contentTypeAlias);});if(model.value){for(var i=0;ivm.maxItems){$scope.nestedContentForm.maxCount.$setValidity('maxCount',false);}else{$scope.nestedContentForm.maxCount.$setValidity('maxCount',true);}};var watcher=$scope.$watch(function(){return vm.nodes.length;},function(){validate();});$scope.$on('$destroy',function(){unsubscribe();watcher();});}}());'use strict';angular.module('umbraco').controller('Umbraco.PropertyEditors.NestedContent.DocTypePickerController',['$scope','Umbraco.PropertyEditors.NestedContent.Resources','overlayService','localizationService','iconHelper',function($scope,ncResources,overlayService,localizationService,iconHelper){var selectElementTypeModalTitle='';$scope.elemTypeTabs=[];init();function init(){localizationService.localize('content_nestedContentSelectElementTypeModalTitle').then(function(value){selectElementTypeModalTitle=value;});ncResources.getContentTypes().then(function(elemTypes){$scope.model.elemTypes=elemTypes;iconHelper.formatContentTypeIcons($scope.model.elemTypes);var elTypeNameOccurrences=_.countBy(elemTypes,'name');elemTypes.forEach(function(value){$scope.elemTypeTabs[value.alias]=value.tabs;if(elTypeNameOccurrences[value.name]>1){value.name+=' ('+value.alias+')';}});});} -$scope.add=function(){$scope.model.value.push({ncAlias:'',ncTabAlias:'',nameTemplate:''});};$scope.remove=function(index){$scope.model.value.splice(index,1);};$scope.sortableOptions={axis:'y',cursor:'move',handle:'.handle',placeholder:'sortable-placeholder',forcePlaceholderSize:true,helper:function helper(e,ui){ui.children().each(function(){$(this).width($(this).width());});return ui;},start:function start(e,ui){var cellHeight=ui.item.height();var cellCount=0;$('td, th',ui.helper).each(function(){var colspan=1;var colspanAttr=$(this).attr('colspan');if(colspanAttr>1){colspan=colspanAttr;} -cellCount+=colspan;});ui.placeholder.html('').height(cellHeight);}};$scope.placeholder=function(config){return _.find($scope.model.elemTypes,function(elType){return elType.alias===config.ncAlias;});};$scope.selectableElemTypesFor=function(config){return _.filter($scope.model.elemTypes,function(elType){return elType.alias===config.ncAlias||!_.find($scope.model.value,function(c){return elType.alias===c.ncAlias;});});};$scope.canAdd=function(){return!$scope.model.value||_.some($scope.model.elemTypes,function(elType){return!_.find($scope.model.value,function(c){return elType.alias===c.ncAlias;});});};$scope.openElemTypeModal=function($event,config){var selectedItems=_.each($scope.model.value,function(obj){obj.alias=obj.ncAlias;return obj;});var elemTypeSelectorOverlay={view:'itempicker',title:selectElementTypeModalTitle,availableItems:$scope.selectableElemTypesFor(config),selectedItems:selectedItems,position:'target',event:$event,submit:function submit(model){config.ncAlias=model.selectedItem.alias;if(model.selectedItem.tabs.length===1){config.ncTabAlias=model.selectedItem.tabs[0];} -overlayService.close();},close:function close(){overlayService.close();}};overlayService.open(elemTypeSelectorOverlay);};if(!$scope.model.value){$scope.model.value=[];$scope.add();}}]);'use strict';angular.module('umbraco').controller('Umbraco.PropertyEditors.RadioButtonsController',function($scope,validationMessageService){var vm=this;vm.viewItems=[];function init(){if(Utilities.isObject($scope.model.config.items)){var sortedItems=[];var vals=_.values($scope.model.config.items);var keys=_.keys($scope.model.config.items);for(var i=0;ib.sortOrder?1:b.sortOrder>a.sortOrder?-1:0;});vm.viewItems=sortedItems;} -validationMessageService.getMandatoryMessage($scope.model.validation).then(function(value){$scope.mandatoryMessage=value;});} -init();});'use strict';function ReadOnlyValueController($rootScope,$scope,$filter){function formatDisplayValue(){if($scope.model.config&&$scope.model.config.filter){if($scope.model.config.format){$scope.displayvalue=$filter($scope.model.config.filter)($scope.model.value,$scope.model.config.format);}else{$scope.displayvalue=$filter($scope.model.config.filter)($scope.model.value);}}else{$scope.displayvalue=$scope.model.value;}} -formatDisplayValue();$scope.$watch('model.value',function(newVal,oldVal){if(newVal!==null&&newVal!==undefined&&newVal!==oldVal){formatDisplayValue();}});} -angular.module('umbraco').controller('Umbraco.PropertyEditors.ReadOnlyValueController',ReadOnlyValueController);'use strict';angular.module('umbraco').controller('Umbraco.PropertyEditors.RelatedLinksController',function($scope,iconHelper,editorService){if(!$scope.model.value){$scope.model.value=[];} -$scope.model.config.max=isNumeric($scope.model.config.max)&&$scope.model.config.max!==0?$scope.model.config.max:Number.MAX_VALUE;$scope.newCaption='';$scope.newLink='http://';$scope.newNewWindow=false;$scope.newInternal=null;$scope.newInternalName='';$scope.newInternalIcon=null;$scope.addExternal=true;$scope.currentEditLink=null;$scope.hasError=false;$scope.internal=function($event){$scope.currentEditLink=null;var contentPicker={section:'content',treeAlias:'content',multiPicker:false,idType:$scope.model.config.idType?$scope.model.config.idType:'int',submit:function submit(model){select(model.selection[0]);editorService.close();},close:function close(){editorService.close();}};editorService.treePicker(contentPicker);$event.preventDefault();};$scope.selectInternal=function($event,link){$scope.currentEditLink=link;var contentPicker={section:'content',treeAlias:'content',multiPicker:false,idType:$scope.model.config.idType?$scope.model.config.idType:'udi',submit:function submit(model){select(model.selection[0]);editorService.close();},close:function close(){editorService.close();}};editorService.treePicker(contentPicker);$event.preventDefault();};$scope.edit=function(idx){for(var i=0;i<$scope.model.value.length;i++){$scope.model.value[i].edit=false;} -$scope.model.value[idx].edit=true;};$scope.saveEdit=function(idx){$scope.model.value[idx].title=$scope.model.value[idx].caption;$scope.model.value[idx].edit=false;};$scope.delete=function(idx){$scope.model.value.splice(idx,1);};$scope.add=function($event){if(!Utilities.isArray($scope.model.value)){$scope.model.value=[];} -if($scope.newCaption==''){$scope.hasError=true;}else{if($scope.addExternal){var newExtLink=new function(){this.caption=$scope.newCaption;this.link=$scope.newLink;this.newWindow=$scope.newNewWindow;this.edit=false;this.isInternal=false;this.type='external';this.title=$scope.newCaption;}();$scope.model.value.push(newExtLink);}else{var newIntLink=new function(){this.caption=$scope.newCaption;this.link=$scope.newInternal;this.newWindow=$scope.newNewWindow;this.internal=$scope.newInternal;this.edit=false;this.isInternal=true;this.internalName=$scope.newInternalName;this.internalIcon=$scope.newInternalIcon;this.type='internal';this.title=$scope.newCaption;}();$scope.model.value.push(newIntLink);} -$scope.newCaption='';$scope.newLink='http://';$scope.newNewWindow=false;$scope.newInternal=null;$scope.newInternalName='';$scope.newInternalIcon=null;} -$event.preventDefault();};$scope.switch=function($event){$scope.addExternal=!$scope.addExternal;$event.preventDefault();};$scope.switchLinkType=function($event,link){link.isInternal=!link.isInternal;link.type=link.isInternal?'internal':'external';if(!link.isInternal) -link.link=$scope.newLink;$event.preventDefault();};$scope.move=function(index,direction){var temp=$scope.model.value[index];$scope.model.value[index]=$scope.model.value[index+direction];$scope.model.value[index+direction]=temp;};$scope.canAdd=function(){return $scope.model.config.max<=0||$scope.model.config.max>countVisible();};$scope.canSort=function(){return countVisible()>1;};$scope.sortableOptions={axis:'y',handle:'.handle',cursor:'move',cancel:'.no-drag',containment:'parent',placeholder:'sortable-placeholder',forcePlaceholderSize:true,helper:function helper(e,ui){ui.children().each(function(){$(this).width($(this).width());});return ui;},items:'> tr:not(.unsortable)',tolerance:'pointer',update:function update(e,ui){var newIndex=ui.item.index();var movedLinkUrl=ui.item.attr('data-link');var originalIndex=getElementIndexByUrl(movedLinkUrl);var movedElement=$scope.model.value[originalIndex];$scope.model.value.splice(originalIndex,1);$scope.model.value.splice(newIndex,0,movedElement);},start:function start(e,ui){var cellCount=0;$('td, th',ui.helper).each(function(){var colspan=1;var colspanAttr=$(this).attr('colspan');if(colspanAttr>1){colspan=colspanAttr;} -cellCount+=colspan;});ui.placeholder.html('').height(ui.item.height());}};function countVisible(){return $scope.model.value.length;} -function isNumeric(n){return!isNaN(parseFloat(n))&&isFinite(n);} -function getElementIndexByUrl(url){for(var i=0;i<$scope.model.value.length;i++){if($scope.model.value[i].link==url){return i;}} -return-1;} -function select(data){if($scope.currentEditLink!=null){$scope.currentEditLink.internal=$scope.model.config.idType==='udi'?data.udi:data.id;$scope.currentEditLink.internalName=data.name;$scope.currentEditLink.internalIcon=iconHelper.convertFromLegacyIcon(data.icon);$scope.currentEditLink.link=$scope.model.config.idType==='udi'?data.udi:data.id;}else{$scope.newInternal=$scope.model.config.idType==='udi'?data.udi:data.id;$scope.newInternalName=data.name;$scope.newInternalIcon=iconHelper.convertFromLegacyIcon(data.icon);}}});'use strict';(function(){'use strict';function CodeEditorController($scope,localizationService){var vm=this;vm.submit=submit;vm.close=close;vm.aceOption={};vm.aceOption={mode:'razor',theme:'chrome',showPrintMargin:false,autoFocus:true,advanced:{fontSize:'14px',enableSnippets:false,enableBasicAutocompletion:true,enableLiveAutocompletion:false,wrap:true},onLoad:function onLoad(aceEditor){vm.aceEditor=aceEditor;}};vm.template={};vm.template.content=$scope.model.content;function onInit(){if(!$scope.model.title){$scope.model.title='Edit source code';}} -function submit(model){model.content=vm.aceEditor.getValue();if($scope.model.submit){$scope.model.submit(model);}} -function close(){if($scope.model.close){$scope.model.close();}} -onInit();} -angular.module('umbraco').controller('Umbraco.PropertyEditors.RTECodeEditorController',CodeEditorController);}());'use strict';angular.module('umbraco').controller('Umbraco.PropertyEditors.RTEController',function($scope,$q,assetsService,$timeout,tinyMceService,angularHelper,tinyMceAssets){var _this=this;$scope.isLoading=true;$scope.textAreaHtmlId=$scope.model.alias+'_'+String.CreateGuid();var editorConfig=$scope.model.config?$scope.model.config.editor:null;if(!editorConfig||Utilities.isString(editorConfig)){editorConfig=tinyMceService.defaultPrevalues();} -if(!editorConfig.maxImageSize&&editorConfig.maxImageSize!==0){editorConfig.maxImageSize=tinyMceService.defaultPrevalues().maxImageSize;} -var width=editorConfig.dimensions?parseInt(editorConfig.dimensions.width,10)||null:null;var height=editorConfig.dimensions?parseInt(editorConfig.dimensions.height,10)||null:null;$scope.containerWidth=editorConfig.mode==='distraction-free'?width?width:'auto':'auto';$scope.containerHeight=editorConfig.mode==='distraction-free'?height?height:'auto':'auto';$scope.containerOverflow=editorConfig.mode==='distraction-free'?height?'auto':'inherit':'inherit';var promises=[];var initPromise=$q(function(resolve,reject){_this.$onInit=resolve;});promises.push(initPromise);tinyMceAssets.forEach(function(tinyJsAsset){promises.push(assetsService.loadJs(tinyJsAsset,$scope));});var tinyMceEditor=null;promises.push(tinyMceService.getTinyMceEditorConfig({htmlId:$scope.textAreaHtmlId,stylesheets:editorConfig.stylesheets,toolbar:editorConfig.toolbar,mode:editorConfig.mode}));$q.all(promises).then(function(result){var standardConfig=result[promises.length-1];if(height!==null){standardConfig.plugins.splice(standardConfig.plugins.indexOf('autoresize'),1);} -var baseLineConfigObj={maxImageSize:editorConfig.maxImageSize,width:width,height:height};baseLineConfigObj.setup=function(editor){tinyMceEditor=editor;tinyMceEditor.on('init',function(e){$timeout(function(){$scope.isLoading=false;});});tinyMceService.initializeEditor({editor:editor,model:$scope.model,currentForm:angularHelper.getCurrentForm($scope)});};angular.extend(baseLineConfigObj,standardConfig);$timeout(function(){tinymce.init(baseLineConfigObj);},150);var unsubscribe=$scope.$on('formSubmitting',function(){if(tinyMceEditor!==undefined&&tinyMceEditor!=null&&!$scope.isLoading){$scope.model.value=tinyMceEditor.getContent();}});$scope.focus=function(){tinyMceEditor.focus();};$scope.$on('$destroy',function(){unsubscribe();if(tinyMceEditor!==undefined&&tinyMceEditor!=null){tinyMceEditor.destroy();}});});});'use strict';angular.module('umbraco').controller('Umbraco.PrevalueEditors.RteController',function($scope,$timeout,$log,tinyMceService,stylesheetResource,assetsService){var cfg=tinyMceService.defaultPrevalues();if($scope.model.value){if(Utilities.isString($scope.model.value)){$scope.model.value=cfg;}}else{$scope.model.value=cfg;} -if(!$scope.model.value.stylesheets){$scope.model.value.stylesheets=[];} -if(!$scope.model.value.toolbar){$scope.model.value.toolbar=[];} -if(!$scope.model.value.maxImageSize&&$scope.model.value.maxImageSize!=0){$scope.model.value.maxImageSize=cfg.maxImageSize;} -if(!$scope.model.value.mode){$scope.model.value.mode='classic';} -tinyMceService.configuration().then(function(config){$scope.tinyMceConfig=config;$scope.tinyMceConfig.commands=_.map($scope.tinyMceConfig.commands,function(obj){var icon=getFontIcon(obj.alias);return angular.extend(obj,{fontIcon:icon.name,isCustom:icon.isCustom,selected:$scope.model.value.toolbar.indexOf(obj.alias)>=0});});});stylesheetResource.getAll().then(function(stylesheets){$scope.stylesheets=stylesheets;var cssPath=Umbraco.Sys.ServerVariables.umbracoSettings.cssPath;$scope.model.value.stylesheets=$scope.model.value.stylesheets.filter(function(sheet){return sheet.startsWith(cssPath);});$scope.stylesheets.forEach(function(stylesheet){stylesheet.selected=$scope.model.value.stylesheets.indexOf(stylesheet.path)>=0||$scope.model.value.stylesheets.indexOf(stylesheet.name)>=0;});});$scope.selectCommand=function(command){var index=$scope.model.value.toolbar.indexOf(command.alias);if(command.selected&&index===-1){$scope.model.value.toolbar.push(command.alias);}else if(index>=0){$scope.model.value.toolbar.splice(index,1);}};$scope.selectStylesheet=function(css){var index=$scope.model.value.stylesheets.indexOf(css.path);if(index===-1){index=$scope.model.value.stylesheets.indexOf(css.name);} -if(index===-1){$scope.model.value.stylesheets.push(css.path);}else{$scope.model.value.stylesheets.splice(index,1);}};function getFontIcon(alias){var icon={name:alias,isCustom:false};switch(alias){case'ace':icon.name='code';icon.isCustom=false;break;case'styleselect':case'fontsizeselect':icon.name='icon-list';icon.isCustom=true;break;case'umbembeddialog':icon.name='icon-tv';icon.isCustom=true;break;case'umbmediapicker':icon.name='icon-picture';icon.isCustom=true;break;case'umbmacro':icon.name='icon-settings-alt';icon.isCustom=true;break;case'umbmacro':icon.name='icon-settings-alt';icon.isCustom=true;break;default:icon.name=alias;icon.isCustom=false;} -return icon;} -var unsubscribe=$scope.$on('formSubmitting',function(ev,args){var commands=_.where($scope.tinyMceConfig.commands,{selected:true});$scope.model.value.toolbar=_.pluck(commands,'alias');});$scope.$on('$destroy',function(){unsubscribe();});assetsService.loadCss('lib/tinymce/skins/lightgray/skin.min.css',$scope);});'use strict';function sliderController($scope,angularHelper){var sliderRef=null;function configureDefaults(){$scope.model.config.enableRange=$scope.model.config.enableRange?Object.toBoolean($scope.model.config.enableRange):false;$scope.model.config.initVal1=$scope.model.config.initVal1?parseFloat($scope.model.config.initVal1):0;$scope.model.config.initVal2=$scope.model.config.initVal2?parseFloat($scope.model.config.initVal2):0;$scope.model.config.minVal=$scope.model.config.minVal?parseFloat($scope.model.config.minVal):0;$scope.model.config.maxVal=$scope.model.config.maxVal?parseFloat($scope.model.config.maxVal):100;$scope.model.config.step=$scope.model.config.step?parseFloat($scope.model.config.step):1;} -function setModelValue(values){$scope.model.value=values?values.toString():null;angularHelper.getCurrentForm($scope).$setDirty();} -$scope.setup=function(slider){sliderRef=slider;};$scope.change=function(values){setModelValue(values);};function init(){configureDefaults();var start=$scope.model.config.enableRange?[$scope.model.config.initVal1,$scope.model.config.initVal2]:[$scope.model.config.initVal1];var step=$scope.model.config.step;var tooltips=$scope.model.config.enableRange?[true,true]:[true];var min=$scope.model.config.minVal?[$scope.model.config.minVal]:[$scope.model.config.minVal];var max=$scope.model.config.maxVal?[$scope.model.config.maxVal]:[$scope.model.config.maxVal];if(!$scope.model.value){$scope.model.value=start.toString();} -$scope.sliderValue=$scope.model.value?$scope.model.value.split(','):null;var stepDecimalPlaces=$scope.model.config.step%1==0?0:_.last($scope.model.config.step.toString().replace(',','.').split('.')).length;$scope.sliderOptions={'start':start,'step':step,'tooltips':tooltips,'format':{to:function to(value){return value.toFixed(stepDecimalPlaces);},from:function from(value){return Number(value);}},'range':{'min':min,'max':max},'pips':{mode:'steps',density:100,filter:filterPips}};function filterPips(value){return value===$scope.model.config.minVal||value===$scope.model.config.maxVal?1:-1;}} -$scope.$watch('model.value',function(newValue,oldValue){if(newValue&&newValue!==oldValue){$scope.sliderValue=newValue.split(',');sliderRef.noUiSlider.set($scope.sliderValue);}});init();} -angular.module('umbraco').controller('Umbraco.PropertyEditors.SliderController',sliderController);'use strict';angular.module('umbraco').controller('Umbraco.PropertyEditors.TagsController',function($scope){$scope.valueChanged=function(value){$scope.model.value=value;};});'use strict';function textAreaController($scope,validationMessageService){if(!$scope.model.config){$scope.model.config={};} -$scope.model.count=0;if(!$scope.model.config.maxChars){$scope.model.config.maxChars=false;} -$scope.model.maxlength=false;if($scope.model.config&&$scope.model.config.maxChars){$scope.model.maxlength=true;} -$scope.$on('formSubmitting',function(){if($scope.isLengthValid()){$scope.textareaFieldForm.textarea.$setValidity('maxChars',true);}else{$scope.textareaFieldForm.textarea.$setValidity('maxChars',false);}});$scope.isLengthValid=function(){if(!$scope.model.maxlength){return true;} -return $scope.model.config.maxChars>=$scope.model.count;};$scope.model.change=function(){if($scope.model.value){$scope.model.count=$scope.model.value.length;}};$scope.model.change();validationMessageService.getMandatoryMessage($scope.model.validation).then(function(value){$scope.mandatoryMessage=value;});} -angular.module('umbraco').controller('Umbraco.PropertyEditors.textAreaController',textAreaController);'use strict';function textboxController($scope,validationMessageService){if(!$scope.model.config){$scope.model.config={};} -$scope.model.count=0;if(!$scope.model.config.maxChars){$scope.model.config.maxChars=500;} -$scope.$on('formSubmitting',function(){if($scope.isLengthValid()){$scope.textboxFieldForm.textbox.$setValidity('maxChars',true);}else{$scope.textboxFieldForm.textbox.$setValidity('maxChars',false);}});$scope.isLengthValid=function(){return $scope.model.config.maxChars>=$scope.model.count;};$scope.model.change=function(){if($scope.model.value){$scope.model.count=$scope.model.value.length;}};$scope.model.change();validationMessageService.getMandatoryMessage($scope.model.validation).then(function(value){$scope.mandatoryMessage=value;});} -angular.module('umbraco').controller('Umbraco.PropertyEditors.textboxController',textboxController);'use strict';angular.module('umbraco').controller('Umbraco.PropertyEditors.UrlListController',function($rootScope,$scope,$filter){function formatDisplayValue(){if(Utilities.isArray($scope.model.value)){$scope.renderModel=_.map($scope.model.value,function(item){return{url:item.url,linkText:item.linkText,urlTarget:item.target?item.target:'_blank',icon:item.icon?item.icon:'icon-out'};});}else{$scope.renderModel=_.map($scope.model.value.split(','),function(item){return{url:item,linkText:'',urlTarget:$scope.config&&$scope.config.target?$scope.config.target:'_blank',icon:$scope.config&&$scope.config.icon?$scope.config.icon:'icon-out'};});}} -$scope.getUrl=function(valueUrl){if(valueUrl.indexOf('/')>=0){return valueUrl;} -return'#';};formatDisplayValue();$scope.model.onValueChanged=function(newVal,oldVal){formatDisplayValue();};});'use strict';function RelationTypeCreateController($scope,$location,relationTypeResource,navigationService,formHelper,appState,notificationsService){var vm=this;vm.relationType={};vm.objectTypes={};vm.createRelationType=createRelationType;init();function init(){$scope.$emit('$changeTitle','');relationTypeResource.getRelationObjectTypes().then(function(data){vm.objectTypes=data;},function(err){notificationsService.error('Could not load form.');});} -function createRelationType(){if(formHelper.submitForm({scope:$scope,formCtrl:this.createRelationTypeForm,statusMessage:'Creating relation type...'})){var node=$scope.currentNode;relationTypeResource.create(vm.relationType).then(function(data){navigationService.hideMenu();var currentPath=node.path?node.path:'-1';navigationService.syncTree({tree:'relationTypes',path:currentPath+','+data,forceReload:true,activate:true});formHelper.resetForm({scope:$scope});var currentSection=appState.getSectionState('currentSection');$location.path('/'+currentSection+'/relationTypes/edit/'+data);},function(err){if(err.data&&err.data.message){notificationsService.error(err.data.message);navigationService.hideMenu();}});}}} -angular.module('umbraco').controller('Umbraco.Editors.RelationTypes.CreateController',RelationTypeCreateController);'use strict';function RelationTypeDeleteController($scope,$location,relationTypeResource,treeService,navigationService,appState){var vm=this;vm.cancel=cancel;vm.performDelete=performDelete;function cancel(){navigationService.hideDialog();} -function performDelete(){if($scope.busy){return false;} -$scope.currentNode.loading=true;$scope.busy=true;relationTypeResource.deleteById($scope.currentNode.id).then(function(){$scope.currentNode.loading=false;treeService.removeNode($scope.currentNode);navigationService.hideMenu();var currentSection=appState.getSectionState('currentSection');$location.path('/'+currentSection+'/');});}} -angular.module('umbraco').controller('Umbraco.Editors.RelationTypes.DeleteController',RelationTypeDeleteController);'use strict';function RelationTypeEditController($scope,$routeParams,relationTypeResource,editorState,navigationService,dateHelper,userService,entityResource,formHelper,contentEditingHelper,localizationService,eventsService){var vm=this;vm.header={};vm.header.editorfor='relationType_tabRelationType';vm.header.setPageTitle=true;vm.page={};vm.page.loading=false;vm.page.saveButtonState='init';vm.page.menu={};vm.save=saveRelationType;init();function init(){vm.page.loading=true;vm.relationsLoading=true;vm.changePageNumber=changePageNumber;vm.options={};var labelKeys=['relationType_tabRelationType','relationType_tabRelations'];localizationService.localizeMany(labelKeys).then(function(data){vm.page.navigation=[{'name':data[0],'alias':'relationType','icon':'icon-info','view':'views/relationTypes/views/relationType.html','active':true},{'name':data[1],'alias':'relations','icon':'icon-trafic','view':'views/relationTypes/views/relations.html'}];});eventsService.on('app.tabChange',function(event,args){if(args.alias==='relations'){loadRelations();}});relationTypeResource.getById($routeParams.id).then(function(data){bindRelationType(data);vm.page.loading=false;});} -function changePageNumber(pageNumber){vm.options.pageNumber=pageNumber;loadRelations();} -function loadRelations(){relationTypeResource.getPagedResults($routeParams.id,vm.options).then(function(data){formatDates(data.items);vm.relationsLoading=false;vm.relations=data;});} -function bindRelationType(relationType){relationType.isBidirectional=(relationType.isBidirectional||false).toString();vm.relationType=relationType;editorState.set(vm.relationType);navigationService.syncTree({tree:'relationTypes',path:relationType.path,forceReload:true}).then(function(syncArgs){vm.page.menu.currentNode=syncArgs.node;});} -function formatDates(relations){if(relations){userService.getCurrentUser().then(function(currentUser){angular.forEach(relations,function(relation){relation.timestampFormatted=dateHelper.getLocalDate(relation.createDate,currentUser.locale,'LLL');});});}} -function saveRelationType(){if(formHelper.submitForm({scope:$scope,statusMessage:'Saving...'})){vm.page.saveButtonState='busy';relationTypeResource.save(vm.relationType).then(function(data){formHelper.resetForm({scope:$scope,notifications:data.notifications});bindRelationType(data);vm.page.saveButtonState='success';},function(error){contentEditingHelper.handleSaveError({err:error});notificationsService.error(error.data.message);vm.page.saveButtonState='error';});}}} -angular.module('umbraco').controller('Umbraco.Editors.RelationTypes.EditController',RelationTypeEditController);'use strict';function RelationTypeSettingsController($scope,localizationService){var vm=this;vm.labels={};function init(){var labelKeys=['relationType_parentToChild','relationType_bidirectional'];localizationService.localizeMany(labelKeys).then(function(data){vm.labels.parentToChild=data[0];vm.labels.bidirectional=data[1];});} -init();} -angular.module('umbraco').controller('Umbraco.Editors.RelationTypes.SettingsController',RelationTypeSettingsController);'use strict';(function(){'use strict';function ScriptsCreateController($scope,$location,navigationService,formHelper,codefileResource,localizationService,appState){var vm=this;var node=$scope.currentNode;vm.creatingFolder=false;vm.folderName='';vm.createFolderError='';vm.fileExtension='';vm.createFile=createFile;vm.showCreateFolder=showCreateFolder;vm.createFolder=createFolder;vm.close=close;function createFile(){$location.path('/settings/scripts/edit/'+node.id).search('create','true');navigationService.hideMenu();} -function showCreateFolder(){vm.creatingFolder=true;} -function createFolder(form){if(formHelper.submitForm({scope:$scope,formCtrl:form})){codefileResource.createContainer('scripts',node.id,vm.folderName).then(function(saved){navigationService.hideMenu();navigationService.syncTree({tree:'scripts',path:saved.path,forceReload:true,activate:true});formHelper.resetForm({scope:$scope});var section=appState.getSectionState('currentSection');},function(err){vm.createFolderError=err;});}} -function close(){var showMenu=true;navigationService.hideDialog(showMenu);}} -angular.module('umbraco').controller('Umbraco.Editors.Scripts.CreateController',ScriptsCreateController);}());'use strict';function ScriptsDeleteController($scope,codefileResource,treeService,navigationService){$scope.performDelete=function(){$scope.currentNode.loading=true;codefileResource.deleteByPath('scripts',$scope.currentNode.id).then(function(){$scope.currentNode.loading=false;var rootNode=treeService.getTreeRoot($scope.currentNode);treeService.removeNode($scope.currentNode);navigationService.hideMenu();});};$scope.cancel=function(){navigationService.hideDialog();};} -angular.module('umbraco').controller('Umbraco.Editors.Scripts.DeleteController',ScriptsDeleteController);'use strict';(function(){'use strict';function ScriptsEditController($scope,$routeParams,$timeout,appState,editorState,navigationService,assetsService,codefileResource,contentEditingHelper,notificationsService,localizationService,templateHelper,angularHelper){var vm=this;var currentPosition=null;vm.header={};vm.header.editorfor='settings_script';vm.header.setPageTitle=true;vm.page={};vm.page.loading=true;vm.page.menu={};vm.page.menu.currentSection=appState.getSectionState('currentSection');vm.page.menu.currentNode=null;vm.page.saveButtonState='init';vm.showKeyboardShortcut=false;vm.page.keyboardShortcutsOverview=[];templateHelper.getGeneralShortcuts().then(function(shortcuts){vm.page.keyboardShortcutsOverview.push(shortcuts);});templateHelper.getEditorShortcuts().then(function(shortcuts){vm.page.keyboardShortcutsOverview.push(shortcuts);});vm.script={};vm.save=save;function save(){vm.page.saveButtonState='busy';vm.script.content=vm.editor.getValue();contentEditingHelper.contentEditorPerformSave({saveMethod:codefileResource.save,scope:$scope,content:vm.script,rebindCallback:function rebindCallback(orignal,saved){}}).then(function(saved){localizationService.localizeMany(['speechBubbles_fileSavedHeader','speechBubbles_fileSavedText']).then(function(data){var header=data[0];var message=data[1];notificationsService.success(header,message);});if(vm.script.id!==saved.id){contentEditingHelper.redirectToRenamedContent(saved.id);}else{vm.page.saveButtonState='success';vm.script=saved;editorState.set(vm.script);navigationService.syncTree({tree:'scripts',path:vm.script.path,forceReload:true}).then(function(syncArgs){vm.page.menu.currentNode=syncArgs.node;});}},function(err){vm.page.saveButtonState='error';localizationService.localizeMany(['speechBubbles_validationFailedHeader','speechBubbles_validationFailedMessage']).then(function(data){var header=data[0];var message=data[1];notificationsService.error(header,message);});});} -function init(){assetsService.loadCss('lib/ace-razor-mode/theme/razor_chrome.css',$scope);if($routeParams.create){codefileResource.getScaffold('scripts',$routeParams.id).then(function(script){ready(script,false);});}else{codefileResource.getByPath('scripts',$routeParams.id).then(function(script){ready(script,true);});}} -function ready(script,syncTree){vm.page.loading=false;vm.script=script;editorState.set(vm.script);if(syncTree){navigationService.syncTree({tree:'scripts',path:vm.script.path,forceReload:true}).then(function(syncArgs){vm.page.menu.currentNode=syncArgs.node;});} -vm.aceOption={mode:'javascript',theme:'chrome',showPrintMargin:false,advanced:{fontSize:'14px',enableSnippets:true,enableBasicAutocompletion:true,enableLiveAutocompletion:false},onLoad:function onLoad(_editor){vm.editor=_editor;_editor.commands.bindKey('ctrl-alt-space','startAutocomplete');_editor.commands.bindKey('ctrl-space',null);_editor.commands.addCommands([{name:'unSelectOrFindPrevious',bindKey:'Alt-Shift-K',exec:function exec(){$scope.$apply(function(){vm.showKeyboardShortcut=!vm.showKeyboardShortcut;});},readOnly:true}]);if(!$routeParams.create){$timeout(function(){vm.editor.navigateFileEnd();vm.editor.focus();});} -vm.editor.on('change',changeAceEditor);}};function changeAceEditor(){setFormState('dirty');} -function setFormState(state){var currentForm=angularHelper.getCurrentForm($scope);if(state==='dirty'){currentForm.$setDirty();}else if(state==='pristine'){currentForm.$setPristine();}}} -init();} -angular.module('umbraco').controller('Umbraco.Editors.Scripts.EditController',ScriptsEditController);}());'use strict';(function(){'use strict';function StyleSheetsCreateController($scope,$location,navigationService,formHelper,codefileResource){var vm=this;var node=$scope.currentNode;vm.createFile=createFile;vm.createRichtextStyle=createRichtextStyle;vm.close=close;vm.creatingFolder=false;vm.showCreateFolder=showCreateFolder;vm.createFolder=createFolder;function createFile(){$location.path('/settings/stylesheets/edit/'+node.id).search('create','true');navigationService.hideMenu();} -function createRichtextStyle(){$location.path('/settings/stylesheets/edit/'+node.id).search('create','true').search('rtestyle','true');navigationService.hideMenu();} -function showCreateFolder(){vm.creatingFolder=true;} -function createFolder(form){if(formHelper.submitForm({scope:$scope,formCtrl:form})){codefileResource.createContainer('stylesheets',node.id,vm.folderName).then(function(saved){navigationService.hideMenu();navigationService.syncTree({tree:'stylesheets',path:saved.path,forceReload:true,activate:true});formHelper.resetForm({scope:$scope});},function(err){vm.createFolderError=err;});}} -function close(){var showMenu=true;navigationService.hideDialog(showMenu);}} -angular.module('umbraco').controller('Umbraco.Editors.StyleSheets.CreateController',StyleSheetsCreateController);}());'use strict';function StyleSheetsDeleteController($scope,codefileResource,treeService,navigationService){$scope.performDelete=function(){$scope.currentNode.loading=true;codefileResource.deleteByPath('stylesheets',$scope.currentNode.id).then(function(){$scope.currentNode.loading=false;treeService.removeNode($scope.currentNode);navigationService.hideMenu();});};$scope.cancel=function(){navigationService.hideDialog();};} -angular.module('umbraco').controller('Umbraco.Editors.StyleSheets.DeleteController',StyleSheetsDeleteController);'use strict';(function(){'use strict';function StyleSheetsEditController($scope,$routeParams,$timeout,$http,appState,editorState,navigationService,assetsService,codefileResource,contentEditingHelper,notificationsService,localizationService,templateHelper,angularHelper,umbRequestHelper){var vm=this;vm.page={};vm.page.loading=true;vm.page.menu={};vm.page.menu.currentSection=appState.getSectionState('currentSection');vm.page.menu.currentNode=null;vm.page.saveButtonState='init';vm.header={};vm.header.editorfor='settings_stylesheet';vm.header.setPageTitle=true;vm.showKeyboardShortcut=false;vm.page.keyboardShortcutsOverview=[];templateHelper.getGeneralShortcuts().then(function(shortcuts){vm.page.keyboardShortcutsOverview.push(shortcuts);});templateHelper.getEditorShortcuts().then(function(shortcuts){vm.page.keyboardShortcutsOverview.push(shortcuts);});vm.stylesheet={content:'',rules:[]};vm.save=interpolateAndSave;function interpolateAndSave(){vm.page.saveButtonState='busy';var activeApp=_.find(vm.page.navigation,function(item){return item.active;});if(activeApp.alias==='rules'){interpolateRules().then(function(content){vm.stylesheet.content=content;save(activeApp);},function(err){});}else{vm.stylesheet.content=vm.editor.getValue();save(activeApp);}} -function save(activeApp){contentEditingHelper.contentEditorPerformSave({saveMethod:codefileResource.save,scope:$scope,content:vm.stylesheet,rebindCallback:function rebindCallback(orignal,saved){}}).then(function(saved){localizationService.localizeMany(['speechBubbles_fileSavedHeader','speechBubbles_fileSavedText']).then(function(data){var header=data[0];var message=data[1];notificationsService.success(header,message);});if(vm.stylesheet.id!==saved.id){contentEditingHelper.redirectToRenamedContent(saved.id);}else{vm.page.saveButtonState='success';vm.stylesheet=saved;editorState.set(vm.stylesheet);navigationService.syncTree({tree:'stylesheets',path:vm.stylesheet.path,forceReload:true}).then(function(syncArgs){vm.page.menu.currentNode=syncArgs.node;});if(activeApp.alias==='rules'){$scope.selectApp(activeApp);}}},function(err){vm.page.saveButtonState='error';localizationService.localizeMany(['speechBubbles_validationFailedHeader','speechBubbles_validationFailedMessage']).then(function(data){var header=data[0];var message=data[1];notificationsService.error(header,message);});});} -function init(){assetsService.loadCss('lib/ace-razor-mode/theme/razor_chrome.css',$scope);if($routeParams.create){codefileResource.getScaffold('stylesheets',$routeParams.id).then(function(stylesheet){var mode=$routeParams.rtestyle?'RTE':null;ready(stylesheet,false);generateNavigation(mode);});}else{codefileResource.getByPath('stylesheets',$routeParams.id).then(function(stylesheet){ready(stylesheet,true);extractRules().then(function(rules){vm.stylesheet.rules=rules;var mode=rules&&rules.length>0?'RTE':null;generateNavigation(mode);});});}} -function generateNavigation(mode){localizationService.localizeMany(['stylesheet_tabRules','stylesheet_tabCode']).then(function(data){vm.page.navigation=[{'name':data[0],'alias':'rules','icon':'icon-font','view':'views/stylesheets/views/rules/rules.html'},{'name':data[1],'alias':'code','icon':'icon-brackets','view':'views/stylesheets/views/code/code.html'}];if(mode==='RTE'){vm.page.navigation[0].active=true;}else{vm.page.navigation[1].active=true;}});} -function ready(stylesheet,syncTree){vm.page.loading=false;vm.stylesheet=stylesheet;vm.setDirty=function(){setFormState('dirty');};editorState.set(vm.stylesheet);if(syncTree){navigationService.syncTree({tree:'stylesheets',path:vm.stylesheet.path,forceReload:true}).then(function(syncArgs){vm.page.menu.currentNode=syncArgs.node;});} -vm.aceOption={mode:'css',theme:'chrome',showPrintMargin:false,advanced:{fontSize:'14px',enableSnippets:true,enableBasicAutocompletion:true,enableLiveAutocompletion:false},onLoad:function onLoad(_editor){vm.editor=_editor;_editor.commands.bindKey('ctrl-alt-space','startAutocomplete');_editor.commands.bindKey('ctrl-space',null);_editor.commands.addCommands([{name:'unSelectOrFindPrevious',bindKey:'Alt-Shift-K',exec:function exec(){$scope.$apply(function(){vm.showKeyboardShortcut=!vm.showKeyboardShortcut;});},readOnly:true}]);if(!$routeParams.create){$timeout(function(){vm.editor.navigateFileEnd();vm.editor.focus();});} -vm.editor.on('change',changeAceEditor);}};function changeAceEditor(){setFormState('dirty');} -function setFormState(state){var currentForm=angularHelper.getCurrentForm($scope);if(state==='dirty'){currentForm.$setDirty();}else if(state==='pristine'){currentForm.$setPristine();}}} -function interpolateRules(){return codefileResource.interpolateStylesheetRules(vm.stylesheet.content,vm.stylesheet.rules);} -function extractRules(){return codefileResource.extractStylesheetRules(vm.stylesheet.content);} -$scope.selectApp=function(app){vm.page.loading=true;if(app.alias==='code'){interpolateRules().then(function(content){vm.stylesheet.content=content;vm.page.loading=false;},function(err){});}else{extractRules().then(function(rules){vm.stylesheet.rules=rules;vm.page.loading=false;},function(err){});}};init();} -angular.module('umbraco').controller('Umbraco.Editors.StyleSheets.EditController',StyleSheetsEditController);}());'use strict';(function(){'use strict';function RichTextRuleController($scope,formHelper){var vm=this;vm.submit=submit;vm.close=close;function submit(){if($scope.model&&$scope.model.submit&&formHelper.submitForm({scope:$scope})){$scope.model.submit($scope.model);}} -function close(){if($scope.model&&$scope.model.close){$scope.model.close();}}} -angular.module('umbraco').controller('Umbraco.Editors.RichTextRuleController',RichTextRuleController);}());'use strict';angular.module('umbraco').controller('Umbraco.Editors.StyleSheets.RulesController',function($scope,localizationService,editorService){$scope.sortableOptions={axis:'y',containment:'parent',cursor:'move',items:'div.umb-stylesheet-rules__listitem',handle:'.handle',tolerance:'pointer',update:function update(e,ui){setDirty();}};$scope.add=function(evt){evt.preventDefault();openOverlay({},$scope.labels.addRule,function(newRule){if(!$scope.model.stylesheet.rules){$scope.model.stylesheet.rules=[];} -$scope.model.stylesheet.rules.push(newRule);setDirty();});};$scope.edit=function(rule,evt){evt.preventDefault();openOverlay(rule,$scope.labels.editRule,function(newRule){rule.name=newRule.name;rule.selector=newRule.selector;rule.styles=newRule.styles;setDirty();});};$scope.remove=function(rule,evt){evt.preventDefault();$scope.model.stylesheet.rules=_.without($scope.model.stylesheet.rules,rule);setDirty();};function openOverlay(rule,title,onSubmit){var ruleDialog={title:title,rule:_.clone(rule),view:'views/stylesheets/infiniteeditors/richtextrule/richtextrule.html',size:'small',submit:function submit(model){onSubmit(model.rule);editorService.close();},close:function close(){editorService.close();}};editorService.open(ruleDialog);} -function setDirty(){$scope.model.setDirty();} -function init(){localizationService.localizeMany(['stylesheet_addRule','stylesheet_editRule']).then(function(data){$scope.labels={addRule:data[0],editRule:data[1]};});} -init();});'use strict';function TemplatesDeleteController($scope,templateResource,treeService,navigationService){$scope.performDelete=function(){$scope.currentNode.loading=true;$scope.error=null;templateResource.deleteById($scope.currentNode.id).then(function(){$scope.currentNode.loading=false;var rootNode=treeService.getTreeRoot($scope.currentNode);treeService.removeNode($scope.currentNode);navigationService.hideMenu();},function(err){$scope.currentNode.loading=false;$scope.error=err;});};$scope.cancel=function(){navigationService.hideDialog();};} -angular.module('umbraco').controller('Umbraco.Editors.Templates.DeleteController',TemplatesDeleteController);'use strict';(function(){'use strict';function TemplatesEditController($scope,$routeParams,$timeout,templateResource,assetsService,notificationsService,editorState,navigationService,appState,macroService,treeService,contentEditingHelper,localizationService,angularHelper,templateHelper,editorService){var vm=this;var oldMasterTemplateAlias=null;var infiniteMode=$scope.model&&$scope.model.infiniteMode;var id=infiniteMode?$scope.model.id:$routeParams.id;var create=infiniteMode?$scope.model.create:$routeParams.create;vm.header={};vm.header.editorfor='template_template';vm.header.setPageTitle=true;vm.page={};vm.page.loading=true;vm.templates=[];vm.page.menu={};vm.page.menu.currentSection=appState.getSectionState('currentSection');vm.page.menu.currentNode=null;vm.page.insertDefaultButton={labelKey:'general_insert',addEllipsis:'true',handler:function handler(){vm.openInsertOverlay();}};vm.page.insertSubButtons=[{labelKey:'template_insertPageField',addEllipsis:'true',handler:function handler(){vm.openPageFieldOverlay();}},{labelKey:'template_insertPartialView',addEllipsis:'true',handler:function handler(){vm.openPartialOverlay();}},{labelKey:'template_insertDictionaryItem',addEllipsis:'true',handler:function handler(){vm.openDictionaryItemOverlay();}},{labelKey:'template_insertMacro',addEllipsis:'true',handler:function handler(){vm.openMacroOverlay();}}];vm.showKeyboardShortcut=false;vm.page.keyboardShortcutsOverview=[];templateHelper.getGeneralShortcuts().then(function(data){vm.page.keyboardShortcutsOverview.push(data);});templateHelper.getEditorShortcuts().then(function(data){vm.page.keyboardShortcutsOverview.push(data);});templateHelper.getTemplateEditorShortcuts().then(function(data){vm.page.keyboardShortcutsOverview.push(data);});vm.save=function(suppressNotification){vm.page.saveButtonState='busy';vm.template.content=vm.editor.getValue();contentEditingHelper.contentEditorPerformSave({saveMethod:templateResource.save,scope:$scope,content:vm.template,rebindCallback:function rebindCallback(orignal,saved){}}).then(function(saved){if(!suppressNotification){localizationService.localizeMany(['speechBubbles_templateSavedHeader','speechBubbles_templateSavedText']).then(function(data){var header=data[0];var message=data[1];notificationsService.success(header,message);});} -vm.page.saveButtonState='success';vm.template=saved;if(!infiniteMode){editorState.set(vm.template);} -if(!infiniteMode&&oldMasterTemplateAlias!==vm.template.masterTemplateAlias){if(vm.page.menu.currentNode.id!=='-1'){treeService.removeNode(vm.page.menu.currentNode);} -oldMasterTemplateAlias=vm.template.masterTemplateAlias;navigationService.syncTree({tree:'templates',path:vm.template.path,forceReload:true,activate:true}).then(function(args){vm.page.menu.currentNode=args.node;});}else{if(!infiniteMode){navigationService.syncTree({tree:'templates',path:vm.template.path,forceReload:true}).then(function(syncArgs){vm.page.menu.currentNode=syncArgs.node;});}} -setFormState('pristine');if(infiniteMode){submit();}},function(err){if(suppressNotification){vm.page.saveButtonState='error';localizationService.localizeMany(['speechBubbles_validationFailedHeader','speechBubbles_validationFailedMessage']).then(function(data){var header=data[0];var message=data[1];notificationsService.error(header,message);});}});};vm.init=function(){assetsService.loadCss('lib/ace-razor-mode/theme/razor_chrome.css',$scope);templateResource.getAll().then(function(templates){vm.templates=templates;});if(create){templateResource.getScaffold(id).then(function(template){vm.ready(template);});}else{templateResource.getById(id).then(function(template){vm.ready(template);});}};vm.ready=function(template){vm.page.loading=false;vm.template=template;if(create){$timeout(function(){var nameField=$('[data-element="editor-name-field"]');if(nameField){nameField.on('blur',function(event){if(event.target.value){vm.save(true);}});}});} -if(!infiniteMode){editorState.set(vm.template);navigationService.syncTree({tree:'templates',path:vm.template.path,forceReload:true}).then(function(syncArgs){vm.page.menu.currentNode=syncArgs.node;});} -oldMasterTemplateAlias=Utilities.copy(template.masterTemplateAlias);vm.aceOption={mode:'razor',theme:'chrome',showPrintMargin:false,advanced:{fontSize:'14px',enableSnippets:false,enableBasicAutocompletion:true,enableLiveAutocompletion:false},onLoad:function onLoad(_editor){vm.editor=_editor;_editor.commands.bindKey('ctrl-alt-space','startAutocomplete');_editor.commands.bindKey('ctrl-space',null);_editor.commands.addCommands([{name:'unSelectOrFindPrevious',bindKey:'Alt-Shift-K',exec:function exec(){$scope.$apply(function(){vm.showKeyboardShortcut=!vm.showKeyboardShortcut;});},readOnly:true},{name:'insertUmbracoValue',bindKey:'Alt-Shift-V',exec:function exec(){$scope.$apply(function(){openPageFieldOverlay();});},readOnly:true},{name:'insertPartialView',bindKey:'Alt-Shift-P',exec:function exec(){$scope.$apply(function(){openPartialOverlay();});},readOnly:true},{name:'insertDictionary',bindKey:'Alt-Shift-D',exec:function exec(){$scope.$apply(function(){openDictionaryItemOverlay();});},readOnly:true},{name:'insertUmbracoMacro',bindKey:'Alt-Shift-M',exec:function exec(){$scope.$apply(function(){openMacroOverlay();});},readOnly:true},{name:'insertQuery',bindKey:'Alt-Shift-Q',exec:function exec(){$scope.$apply(function(){openQueryBuilderOverlay();});},readOnly:true},{name:'insertSection',bindKey:'Alt-Shift-S',exec:function exec(){$scope.$apply(function(){openSectionsOverlay();});},readOnly:true},{name:'chooseMasterTemplate',bindKey:'Alt-Shift-T',exec:function exec(){$scope.$apply(function(){openMasterTemplateOverlay();});},readOnly:true}]);if(!create){$timeout(function(){vm.editor.navigateFileEnd();vm.editor.focus();persistCurrentLocation();});} -vm.editor.on('blur',persistCurrentLocation);vm.editor.on('focus',persistCurrentLocation);vm.editor.on('change',changeAceEditor);}};};vm.openPageFieldOverlay=openPageFieldOverlay;vm.openDictionaryItemOverlay=openDictionaryItemOverlay;vm.openQueryBuilderOverlay=openQueryBuilderOverlay;vm.openMacroOverlay=openMacroOverlay;vm.openInsertOverlay=openInsertOverlay;vm.openSectionsOverlay=openSectionsOverlay;vm.openPartialOverlay=openPartialOverlay;vm.openMasterTemplateOverlay=openMasterTemplateOverlay;vm.selectMasterTemplate=selectMasterTemplate;vm.getMasterTemplateName=getMasterTemplateName;vm.removeMasterTemplate=removeMasterTemplate;vm.closeShortcuts=closeShortcuts;vm.submit=submit;vm.close=close;function openInsertOverlay(){var insertOverlay={allowedTypes:{macro:true,dictionary:true,partial:true,umbracoField:true},submit:function submit(model){switch(model.insert.type){case'macro':var macroObject=macroService.collectValueData(model.insert.selectedMacro,model.insert.macroParams,'Mvc');insert(macroObject.syntax);break;case'dictionary':var code=templateHelper.getInsertDictionarySnippet(model.insert.node.name);insert(code);break;case'partial':var code=templateHelper.getInsertPartialSnippet(model.insert.node.parentId,model.insert.node.name);insert(code);break;case'umbracoField':insert(model.insert.umbracoField);break;} -editorService.close();},close:function close(oldModel){editorService.close();vm.editor.focus();}};editorService.insertCodeSnippet(insertOverlay);} -function openMacroOverlay(){var macroPicker={dialogData:{},submit:function submit(model){var macroObject=macroService.collectValueData(model.selectedMacro,model.macroParams,'Mvc');insert(macroObject.syntax);editorService.close();},close:function close(){editorService.close();vm.editor.focus();}};editorService.macroPicker(macroPicker);} -function openPageFieldOverlay(){var insertFieldEditor={submit:function submit(model){insert(model.umbracoField);editorService.close();},close:function close(){editorService.close();vm.editor.focus();}};editorService.insertField(insertFieldEditor);} -function openDictionaryItemOverlay(){var labelKeys=['template_insertDictionaryItem','emptyStates_emptyDictionaryTree'];localizationService.localizeMany(labelKeys).then(function(values){var title=values[0];var emptyStateMessage=values[1];var dictionaryItem={section:'translation',treeAlias:'dictionary',entityType:'dictionary',multiPicker:false,title:title,emptyStateMessage:emptyStateMessage,select:function select(node){var code=templateHelper.getInsertDictionarySnippet(node.name);insert(code);editorService.close();},close:function close(model){editorService.close();vm.editor.focus();}};editorService.treePicker(dictionaryItem);});} -function openPartialOverlay(){localizationService.localize('template_insertPartialView').then(function(value){var title=value;var partialItem={section:'settings',treeAlias:'partialViews',entityType:'partialView',multiPicker:false,title:title,filter:function filter(i){if(i.name.indexOf('.cshtml')===-1&&i.name.indexOf('.vbhtml')===-1){return true;}},filterCssClass:'not-allowed',select:function select(node){var code=templateHelper.getInsertPartialSnippet(node.parentId,node.name);insert(code);editorService.close();},close:function close(model){editorService.close();vm.editor.focus();}};editorService.treePicker(partialItem);});} -function openQueryBuilderOverlay(){var queryBuilder={submit:function submit(model){var code=templateHelper.getQuerySnippet(model.result.queryExpression);insert(code);editorService.close();},close:function close(){editorService.close();vm.editor.focus();}};editorService.queryBuilder(queryBuilder);} -function openSectionsOverlay(){var templateSections={isMaster:vm.template.isMasterTemplate,submit:function submit(model){if(model.insertType==='renderBody'){var code=templateHelper.getRenderBodySnippet();insert(code);} -if(model.insertType==='renderSection'){var code=templateHelper.getRenderSectionSnippet(model.renderSectionName,model.mandatoryRenderSection);insert(code);} -if(model.insertType==='addSection'){var code=templateHelper.getAddSectionSnippet(model.sectionName);wrap(code);} -editorService.close();},close:function close(model){editorService.close();vm.editor.focus();}};editorService.templateSections(templateSections);} -function openMasterTemplateOverlay(){var availableMasterTemplates=[];angular.forEach(vm.templates,function(template){if(template.alias!==vm.template.alias&&template.alias!==vm.template.masterTemplateAlias){var templatePathArray=template.path.split(',');if(templatePathArray.indexOf(String(vm.template.id))===-1){availableMasterTemplates.push(template);}}});localizationService.localize('template_mastertemplate').then(function(value){var title=value;var masterTemplate={title:title,availableItems:availableMasterTemplates,submit:function submit(model){var template=model.selectedItem;if(template&&template.alias){vm.template.masterTemplateAlias=template.alias;setLayout(template.alias+'.cshtml');}else{vm.template.masterTemplateAlias=null;setLayout(null);} -editorService.close();},close:function close(oldModel){editorService.close();vm.editor.focus();}};editorService.itemPicker(masterTemplate);});} -function selectMasterTemplate(template){if(template&&template.alias){vm.template.masterTemplateAlias=template.alias;setLayout(template.alias+'.cshtml');}else{vm.template.masterTemplateAlias=null;setLayout(null);}} -function getMasterTemplateName(masterTemplateAlias,templates){if(masterTemplateAlias){var templateName='';angular.forEach(templates,function(template){if(template.alias===masterTemplateAlias){templateName=template.name;}});return templateName;}} -function removeMasterTemplate(){vm.template.masterTemplateAlias=null;setLayout();} -function setLayout(templatePath){var templateCode=vm.editor.getValue();var newValue=templatePath;var layoutDefRegex=new RegExp('(@{[\\s\\S]*?Layout\\s*?=\\s*?)("[^"]*?"|null)(;[\\s\\S]*?})','gi');if(newValue!==undefined&&newValue!==''){if(layoutDefRegex.test(templateCode)){templateCode=templateCode.replace(layoutDefRegex,'$1"'+newValue+'"$3');}else{templateCode='@{\n\tLayout = "'+newValue+'";\n}\n'+templateCode;}}else{if(layoutDefRegex.test(templateCode)){templateCode=templateCode.replace(layoutDefRegex,'$1null$3');}} -vm.editor.setValue(templateCode);vm.editor.clearSelection();vm.editor.navigateFileStart();vm.editor.focus();setFormState('dirty');} -function insert(str){vm.editor.focus();vm.editor.moveCursorToPosition(vm.currentPosition);vm.editor.insert(str);setFormState('dirty');} -function wrap(str){var selectedContent=vm.editor.session.getTextRange(vm.editor.getSelectionRange());str=str.replace('{0}',selectedContent);vm.editor.insert(str);vm.editor.focus();setFormState('dirty');} -function persistCurrentLocation(){vm.currentPosition=vm.editor.getCursorPosition();} -function changeAceEditor(){setFormState('dirty');} -function setFormState(state){var currentForm=angularHelper.getCurrentForm($scope);if(state==='dirty'){currentForm.$setDirty();}else if(state==='pristine'){currentForm.$setPristine();}} -function closeShortcuts(){vm.showKeyboardShortcut=false;} -function submit(){if($scope.model.submit){$scope.model.template=vm.template;$scope.model.submit($scope.model);}} -function close(){if($scope.model.close){$scope.model.close();}} -vm.init();} -angular.module('umbraco').controller('Umbraco.Editors.Templates.EditController',TemplatesEditController);}());'use strict';(function(){'use strict';function UserGroupEditController($scope,$location,$routeParams,userGroupsResource,localizationService,contentEditingHelper,editorService){var vm=this;var contentPickerOpen=false;vm.page={};vm.page.rootIcon='icon-folder';vm.userGroup={};vm.labels={};vm.showBackButton=true;vm.goToPage=goToPage;vm.openSectionPicker=openSectionPicker;vm.openContentPicker=openContentPicker;vm.openMediaPicker=openMediaPicker;vm.openUserPicker=openUserPicker;vm.removeSelectedItem=removeSelectedItem;vm.clearStartNode=clearStartNode;vm.save=save;vm.openGranularPermissionsPicker=openGranularPermissionsPicker;vm.setPermissionsForNode=setPermissionsForNode;function init(){vm.loading=true;var labelKeys=['general_cancel','defaultdialogs_selectContentStartNode','defaultdialogs_selectMediaStartNode','defaultdialogs_selectNode','general_groups','content_contentRoot','media_mediaRoot'];localizationService.localizeMany(labelKeys).then(function(values){vm.labels.cancel=values[0];vm.labels.selectContentStartNode=values[1];vm.labels.selectMediaStartNode=values[2];vm.labels.selectNode=values[3];vm.labels.groups=values[4];vm.labels.contentRoot=values[5];vm.labels.mediaRoot=values[6];});localizationService.localize('general_add').then(function(name){vm.labels.add=name;});localizationService.localize('user_noStartNode').then(function(name){vm.labels.noStartNode=name;});if($routeParams.create){userGroupsResource.getUserGroupScaffold().then(function(userGroup){vm.userGroup=userGroup;setSectionIcon(vm.userGroup.sections);makeBreadcrumbs();vm.loading=false;});}else{userGroupsResource.getUserGroup($routeParams.id).then(function(userGroup){vm.userGroup=userGroup;formatGranularPermissionSelection();setSectionIcon(vm.userGroup.sections);makeBreadcrumbs();vm.loading=false;});}} -function save(){vm.page.saveButtonState='busy';contentEditingHelper.contentEditorPerformSave({saveMethod:userGroupsResource.saveUserGroup,scope:$scope,content:vm.userGroup,rebindCallback:function rebindCallback(orignal,saved){}}).then(function(saved){vm.userGroup=saved;formatGranularPermissionSelection();setSectionIcon(vm.userGroup.sections);makeBreadcrumbs();vm.page.saveButtonState='success';},function(err){vm.page.saveButtonState='error';});} -function goToPage(ancestor){$location.path(ancestor.path);} -function openSectionPicker(){var currentSelection=[];Utilities.copy(vm.userGroup.sections,currentSelection);var sectionPicker={selection:currentSelection,submit:function submit(model){vm.userGroup.sections=model.selection;editorService.close();},close:function close(){editorService.close();}};editorService.sectionPicker(sectionPicker);} -function openContentPicker(){var contentPicker={title:vm.labels.selectContentStartNode,section:'content',treeAlias:'content',hideSubmitButton:true,hideHeader:false,submit:function submit(model){if(model.selection){vm.userGroup.contentStartNode=model.selection[0];if(vm.userGroup.contentStartNode.id==='-1'){vm.userGroup.contentStartNode.name=vm.labels.contentRoot;vm.userGroup.contentStartNode.icon='icon-folder';}} -editorService.close();},close:function close(){editorService.close();}};editorService.treePicker(contentPicker);} -function openMediaPicker(){var mediaPicker={title:vm.labels.selectMediaStartNode,section:'media',treeAlias:'media',entityType:'media',hideSubmitButton:true,hideHeader:false,submit:function submit(model){if(model.selection){vm.userGroup.mediaStartNode=model.selection[0];if(vm.userGroup.mediaStartNode.id==='-1'){vm.userGroup.mediaStartNode.name=vm.labels.mediaRoot;vm.userGroup.mediaStartNode.icon='icon-folder';}} -editorService.close();},close:function close(){editorService.close();}};editorService.treePicker(mediaPicker);} -function openUserPicker(){var currentSelection=[];Utilities.copy(vm.userGroup.users,currentSelection);var userPicker={selection:currentSelection,submit:function submit(model){vm.userGroup.users=model.selection;editorService.close();},close:function close(){editorService.close();}};editorService.userPicker(userPicker);} -function formatGranularPermissionSelection(){angular.forEach(vm.userGroup.assignedPermissions,function(node){formatGranularPermissionSelectionForNode(node);});} -function formatGranularPermissionSelectionForNode(node){node.allowedPermissions=[];angular.forEach(node.permissions,function(permissions,key){angular.forEach(permissions,function(p){if(p.checked){node.allowedPermissions.push(p);}});});} -function openGranularPermissionsPicker(){var contentPicker={title:vm.labels.selectNode,section:'content',treeAlias:'content',hideSubmitButton:true,submit:function submit(model){if(model.selection){var node=model.selection[0];var found=_.find(vm.userGroup.assignedPermissions,function(i){return i.id===node.id;});node=found?found:node;setPermissionsForNode(node);}},close:function close(){editorService.close();}};editorService.treePicker(contentPicker);contentPickerOpen=true;} -function setPermissionsForNode(node){if(!node.permissions){node.permissions=Utilities.copy(vm.userGroup.defaultPermissions);} -vm.nodePermissions={node:node,submit:function submit(model){if(model&&model.node&&model.node.permissions){formatGranularPermissionSelectionForNode(node);if(!vm.userGroup.assignedPermissions){vm.userGroup.assignedPermissions=[];} -var found=_.find(vm.userGroup.assignedPermissions,function(i){return i.id===node.id;});if(!found){vm.userGroup.assignedPermissions.push(node);}} -editorService.close();if(contentPickerOpen){editorService.close();contentPickerOpen=false;}},close:function close(){editorService.close();}};editorService.nodePermissions(vm.nodePermissions);} -function removeSelectedItem(index,selection){if(selection&&selection.length>0){selection.splice(index,1);}} -function clearStartNode(type){if(type==='content'){vm.userGroup.contentStartNode=null;}else if(type==='media'){vm.userGroup.mediaStartNode=null;}} -function makeBreadcrumbs(){vm.breadcrumbs=[{'name':vm.labels.groups,'path':'/users/users/groups'},{'name':vm.userGroup.name}];} -function setSectionIcon(sections){angular.forEach(sections,function(section){section.icon='icon-section';});} -init();} -angular.module('umbraco').controller('Umbraco.Editors.Users.GroupController',UserGroupEditController);}());'use strict';(function(){'use strict';function UsersOverviewController($scope,$location,$routeParams,localizationService){var vm=this;var usersUri=$routeParams.method;vm.page={};vm.page.labels={};vm.page.name='';vm.page.navigation=[];function onInit(){loadNavigation();} -function loadNavigation(){var labels=['sections_users','general_groups','user_userManagement'];localizationService.localizeMany(labels).then(function(data){vm.page.labels.users=data[0];vm.page.labels.groups=data[1];vm.page.name=data[2];vm.page.navigation=[{'name':vm.page.labels.users,'icon':'icon-user','action':function action(){$location.path('/users/users/users').search('create',null);},'view':!usersUri||usersUri==='users'?'views/users/views/users/users.html':null,'active':!usersUri||usersUri==='users','alias':'users'},{'name':vm.page.labels.groups,'icon':'icon-users','action':function action(){$location.path('/users/users/groups').search('create',null);},'view':usersUri==='groups'?'views/users/views/groups/groups.html':null,'active':usersUri==='groups','alias':'userGroups'}];});} -onInit();} -angular.module('umbraco').controller('Umbraco.Editors.Users.OverviewController',UsersOverviewController);}());'use strict';(function(){'use strict';function UserEditController($scope,eventsService,$q,$location,$routeParams,formHelper,usersResource,userService,contentEditingHelper,localizationService,mediaHelper,Upload,umbRequestHelper,usersHelper,authResource,dateHelper,editorService,overlayService){var vm=this;vm.page={};vm.page.rootIcon='icon-folder';vm.user={changePassword:null};vm.breadcrumbs=[];vm.showBackButton=true;vm.avatarFile={};vm.labels={};vm.maxFileSize=Umbraco.Sys.ServerVariables.umbracoSettings.maxFileSize+'KB';vm.acceptedFileTypes=mediaHelper.formatFileTypes(Umbraco.Sys.ServerVariables.umbracoSettings.imageFileTypes);vm.usernameIsEmail=Umbraco.Sys.ServerVariables.umbracoSettings.usernameIsEmail;vm.changePasswordModel={config:{},isChanging:false,value:{}};vm.goToPage=goToPage;vm.openUserGroupPicker=openUserGroupPicker;vm.openContentPicker=openContentPicker;vm.openMediaPicker=openMediaPicker;vm.removeSelectedItem=removeSelectedItem;vm.disableUser=disableUser;vm.enableUser=enableUser;vm.unlockUser=unlockUser;vm.resendInvite=resendInvite;vm.deleteNonLoggedInUser=deleteNonLoggedInUser;vm.changeAvatar=changeAvatar;vm.clearAvatar=clearAvatar;vm.save=save;vm.changePassword=changePassword;vm.toggleChangePassword=toggleChangePassword;function init(){vm.loading=true;var labelKeys=['general_saving','general_cancel','defaultdialogs_selectContentStartNode','defaultdialogs_selectMediaStartNode','sections_users','content_contentRoot','media_mediaRoot','user_noStartNodes','user_defaultInvitationMessage','user_deleteUserConfirmation'];localizationService.localizeMany(labelKeys).then(function(values){vm.labels.saving=values[0];vm.labels.cancel=values[1];vm.labels.selectContentStartNode=values[2];vm.labels.selectMediaStartNode=values[3];vm.labels.users=values[4];vm.labels.contentRoot=values[5];vm.labels.mediaRoot=values[6];vm.labels.noStartNodes=values[7];vm.labels.defaultInvitationMessage=values[8];vm.labels.deleteUserConfirmation=values[9];});usersResource.getUser($routeParams.id).then(function(user){vm.user=user;makeBreadcrumbs(vm.user);setUserDisplayState();formatDatesToLocal(vm.user);vm.usernameIsEmail=Umbraco.Sys.ServerVariables.umbracoSettings.usernameIsEmail&&user.email===user.username;authResource.getPasswordConfig(user.id).then(function(data){vm.changePasswordModel.config=data;vm.changePasswordModel.config.hasPassword=vm.user.userState!==3&&vm.user.userState!==4;vm.changePasswordModel.config.disableToggle=true;$scope.$emit('$setAccessibleHeader',false,'general_user',false,vm.user.name,'',true);vm.loading=false;});});} -function getLocalDate(date,culture,format){if(date){var dateVal;var serverOffset=Umbraco.Sys.ServerVariables.application.serverTimeOffset;var localOffset=new Date().getTimezoneOffset();var serverTimeNeedsOffsetting=-serverOffset!==localOffset;if(serverTimeNeedsOffsetting){dateVal=dateHelper.convertToLocalMomentTime(date,serverOffset);}else{dateVal=moment(date,'YYYY-MM-DD HH:mm:ss');} -return dateVal.locale(culture).format(format);}} -function toggleChangePassword(){vm.user.changePassword=null;localizationService.localizeMany(['general_cancel','general_confirm','general_changePassword']).then(function(data){var overlay={view:'changepassword',title:data[2],changePassword:vm.user.changePassword,config:vm.changePasswordModel.config,closeButtonLabel:data[0],submitButtonLabel:data[1],submitButtonStyle:'success',close:function close(){return overlayService.close();},submit:function submit(model){overlayService.close();vm.changePasswordModel.value=model.changePassword;changePassword();}};overlayService.open(overlay);});} -function save(){if(formHelper.submitForm({scope:$scope})){vm.page.saveButtonState='busy';var currentNav=vm.user.navigation;usersResource.saveUser(vm.user).then(function(saved){extendedSave(saved).then(function(result){formHelper.resetForm({scope:$scope});},Utilities.noop);vm.user=_.omit(saved,'navigation');vm.user.navigation=currentNav;setUserDisplayState();formatDatesToLocal(vm.user);vm.page.saveButtonState='success';},function(err){contentEditingHelper.handleSaveError({err:err,showNotifications:true});vm.page.saveButtonState='error';});}} -function changePassword(){if(vm.changePasswordModel.value){vm.changePasswordModel.value.reset=!vm.changePasswordModel.value.oldPassword&&!vm.user.isCurrentUser||vm.changePasswordModel.config.allowManuallyChangingPassword;} -vm.changePasswordModel.value.id=vm.user.id;usersResource.changePassword(vm.changePasswordModel.value).then(function(){vm.changePasswordModel.isChanging=false;vm.changePasswordModel.value={};vm.changePasswordModel.config.hasPassword=vm.user.userState!==3&&vm.user.userState!==4;},function(err){contentEditingHelper.handleSaveError({err:err,showNotifications:true});});} -function extendedSave(savedUser){var promises=[];var args={user:savedUser,addPromise:function addPromise(p){promises.push(p);}};eventsService.emit('editors.user.editController.save',args);var resultPromise=$q.all(promises);return resultPromise;} -function goToPage(ancestor){$location.path(ancestor.path);} -function openUserGroupPicker(){var currentSelection=[];Utilities.copy(vm.user.userGroups,currentSelection);var userGroupPicker={selection:currentSelection,submit:function submit(model){if(model.selection){vm.user.userGroups=model.selection;} -editorService.close();},close:function close(){editorService.close();}};editorService.userGroupPicker(userGroupPicker);} -function openContentPicker(){var contentPicker={title:vm.labels.selectContentStartNode,section:'content',treeAlias:'content',multiPicker:true,selection:vm.user.startContentIds,hideHeader:false,submit:function submit(model){if(model.selection){angular.forEach(model.selection,function(item){if(item.id==='-1'){item.name=vm.labels.contentRoot;item.icon='icon-folder';} -multiSelectItem(item,vm.user.startContentIds);});} -editorService.close();},close:function close(){editorService.close();}};editorService.treePicker(contentPicker);} -function openMediaPicker(){var mediaPicker={title:vm.labels.selectMediaStartNode,section:'media',treeAlias:'media',entityType:'media',multiPicker:true,hideHeader:false,show:true,submit:function submit(model){if(model.selection){angular.forEach(model.selection,function(item){if(item.id==='-1'){item.name=vm.labels.mediaRoot;item.icon='icon-folder';} -multiSelectItem(item,vm.user.startMediaIds);});} -editorService.close();},close:function close(){editorService.close();}};editorService.treePicker(mediaPicker);} -function multiSelectItem(item,selection){var found=false;if(selection.length>0){angular.forEach(selection,function(selectedItem){if(selectedItem.udi===item.udi){found=true;}});} -if(!found){selection.push(item);}} -function removeSelectedItem(index,selection){selection.splice(index,1);} -function disableUser(){vm.disableUserButtonState='busy';usersResource.disableUsers([vm.user.id]).then(function(data){vm.user.userState=1;setUserDisplayState();vm.disableUserButtonState='success';},function(error){vm.disableUserButtonState='error';});} -function enableUser(){vm.enableUserButtonState='busy';usersResource.enableUsers([vm.user.id]).then(function(data){vm.user.userState=0;setUserDisplayState();vm.enableUserButtonState='success';},function(error){vm.enableUserButtonState='error';});} -function unlockUser(){vm.unlockUserButtonState='busy';usersResource.unlockUsers([vm.user.id]).then(function(data){vm.user.userState=0;vm.user.failedPasswordAttempts=0;setUserDisplayState();vm.unlockUserButtonState='success';},function(error){vm.unlockUserButtonState='error';});} -function resendInvite(){vm.resendInviteButtonState='busy';if(vm.resendInviteMessage){vm.user.message=vm.resendInviteMessage;}else{vm.user.message=vm.labels.defaultInvitationMessage;} -usersResource.inviteUser(vm.user).then(function(data){vm.resendInviteButtonState='success';vm.resendInviteMessage='';formHelper.showNotifications(data);},function(error){vm.resendInviteButtonState='error';formHelper.showNotifications(error.data);});} -function deleteNonLoggedInUser(){vm.deleteNotLoggedInUserButtonState='busy';var confirmationMessage=vm.labels.deleteUserConfirmation;localizationService.localizeMany(['general_delete','general_cancel','contentTypeEditor_yesDelete']).then(function(data){var overlay={view:'confirm',title:data[0],content:confirmationMessage,closeButtonLabel:data[1],submitButtonLabel:data[2],submitButtonStyle:'danger',close:function close(){vm.deleteNotLoggedInUserButtonState='danger';overlayService.close();},submit:function submit(){performDelete();overlayService.close();}};overlayService.open(overlay);});} -function performDelete(){usersResource.deleteNonLoggedInUser(vm.user.id).then(function(data){formHelper.showNotifications(data);goToPage(vm.breadcrumbs[0]);},function(error){vm.deleteNotLoggedInUserButtonState='error';formHelper.showNotifications(error.data);});} -function clearAvatar(){usersResource.clearAvatar(vm.user.id).then(function(data){vm.user.avatars=data;});} -function changeAvatar(files,event){if(files&&files.length>0){upload(files[0]);}};function upload(file){vm.avatarFile.uploadProgress=0;Upload.upload({url:umbRequestHelper.getApiUrl('userApiBaseUrl','PostSetAvatar',{id:vm.user.id}),fields:{},file:file}).progress(function(evt){if(vm.avatarFile.uploadStatus!=='done'&&vm.avatarFile.uploadStatus!=='error'){vm.avatarFile.uploadStatus='uploading';var progressPercentage=parseInt(100*evt.loaded/evt.total,10);vm.avatarFile.uploadProgress=progressPercentage;}}).success(function(data,status,headers,config){vm.avatarFile.uploadStatus='done';vm.avatarFile.uploadProgress=100;vm.user.avatars=data;}).error(function(evt,status,headers,config){vm.avatarFile.uploadStatus='error';if(status===404){vm.avatarFile.serverErrorMessage='File not found';}else if(status==400){vm.avatarFile.serverErrorMessage=evt.message;}else{if(evt.InnerException){vm.avatarFile.serverErrorMessage=evt.InnerException.ExceptionMessage;if(evt.InnerException.StackTrace&&evt.InnerException.StackTrace.indexOf('ValidateRequestEntityLength')>0){vm.avatarFile.serverErrorMessage='File too large to upload';}}else if(evt.Message){vm.avatarFile.serverErrorMessage=evt.Message;}}});} -function makeBreadcrumbs(){vm.breadcrumbs=[{'name':vm.labels.users,'path':'/users/users/users'},{'name':vm.user.name}];} -function setUserDisplayState(){vm.user.userDisplayState=usersHelper.getUserStateFromValue(vm.user.userState);} -function formatDatesToLocal(user){userService.getCurrentUser().then(function(currentUser){user.formattedLastLogin=getLocalDate(user.lastLoginDate,currentUser.locale,'LLL');user.formattedLastLockoutDate=getLocalDate(user.lastLockoutDate,currentUser.locale,'LLL');user.formattedCreateDate=getLocalDate(user.createDate,currentUser.locale,'LLL');user.formattedUpdateDate=getLocalDate(user.updateDate,currentUser.locale,'LLL');user.formattedLastPasswordChangeDate=getLocalDate(user.lastPasswordChangeDate,currentUser.locale,'LLL');});} -init();} -angular.module('umbraco').controller('Umbraco.Editors.Users.UserController',UserEditController);}());'use strict';(function(){'use strict';function UserGroupsController($scope,$timeout,$location,$filter,userService,userGroupsResource,formHelper,localizationService,listViewHelper,overlayService){var vm=this;vm.userGroups=[];vm.selection=[];vm.clickUserGroupName=clickUserGroupName;vm.createUserGroup=createUserGroup;vm.clearSelection=clearSelection;vm.selectUserGroup=selectUserGroup;vm.deleteUserGroups=deleteUserGroups;vm.filter=null;var currentUser=null;function onInit(){vm.loading=true;userService.getCurrentUser().then(function(user){currentUser=user;userGroupsResource.getUserGroups({onlyCurrentUserGroups:false}).then(function(userGroups){vm.userGroups=_.map(userGroups,function(ug){ug.hasAccess=user.userGroups.indexOf(ug.alias)!==-1||user.userGroups.indexOf('admin')!==-1;return ug;});vm.filteredUserGroups=vm.userGroups;vm.loading=false;});});} -function createUserGroup(){$location.search({});$location.path('users/users/group/-1').search('create','true');;} -function goToUserGroup(userGroup,$event){if(currentUser.userGroups.indexOf(userGroup.alias)===-1&¤tUser.userGroups.indexOf('admin')===-1){return;} -$location.path(getEditPath(userGroup)).search('create',null);} -function clickUserGroupName(item,$event){if(!($event.metaKey||$event.ctrlKey)){goToUserGroup(item,$event);$event.preventDefault();} -$event.stopPropagation();};function getEditPath(userGroup){if(currentUser.userGroups.indexOf(userGroup.alias)===-1&¤tUser.userGroups.indexOf('admin')===-1){return'';} -return'users/users/group/'+userGroup.id;} -function selectUserGroup(userGroup,$index,$event){if(currentUser.userGroups.indexOf(userGroup.alias)===-1&¤tUser.userGroups.indexOf('admin')===-1){return;} -if(userGroup.isSystemUserGroup) -return;listViewHelper.selectHandler(userGroup,$index,vm.userGroups,vm.selection,$event);if(event){event.stopPropagation();}} -function deleteUserGroups(){if(vm.selection.length>0){localizationService.localizeMany(['general_delete','defaultdialogs_confirmdelete','general_cancel','contentTypeEditor_yesDelete']).then(function(data){var overlay={title:data[0],content:data[1]+'?',closeButtonLabel:data[2],submitButtonLabel:data[3],submitButtonStyle:'danger',close:function close(){overlayService.close();},submit:function submit(){userGroupsResource.deleteUserGroups(_.pluck(vm.selection,'id')).then(function(data){clearSelection();onInit();},Utilities.noop);overlayService.close();}};overlayService.open(overlay);});}} -function clearSelection(){angular.forEach(vm.userGroups,function(userGroup){userGroup.selected=false;});vm.selection=[];} -var unbindFilterWatcher=$scope.$watch('vm.filter',function(newVal,oldVal){vm.filteredUserGroups=$filter('filter')(vm.userGroups,vm.filter);});$scope.$on('$destroy',function(){unbindFilterWatcher();});onInit();} -angular.module('umbraco').controller('Umbraco.Editors.Users.GroupsController',UserGroupsController);}());'use strict';(function(){'use strict';function UsersController($scope,$timeout,$location,$routeParams,usersResource,userGroupsResource,userService,localizationService,usersHelper,formHelper,dateHelper,editorService,listViewHelper){var vm=this;vm.page={};vm.users=[];vm.userGroups=[];vm.userStates=[];vm.selection=[];vm.newUser={};vm.usersOptions={};vm.userSortData=[{label:'Name (A-Z)',key:'Name',direction:'Ascending'},{label:'Name (Z-A)',key:'Name',direction:'Descending'},{label:'Newest',key:'CreateDate',direction:'Descending'},{label:'Oldest',key:'CreateDate',direction:'Ascending'},{label:'Last login',key:'LastLoginDate',direction:'Descending'}];localizationService.localizeMany(_.map(vm.userSortData,function(userSort){return'user_sort'+userSort.key+userSort.direction;})).then(function(data){var reg=/^\[[\S\s]*]$/g;_.each(data,function(value,index){if(!reg.test(value)){vm.userSortData[index].label=value;}});});vm.labels={};localizationService.localizeMany(['user_stateAll']).then(function(data){vm.labels.all=data[0];});vm.userStatesFilter=[];vm.newUser.userGroups=[];vm.usersViewState='overview';vm.selectedBulkUserGroups=[];vm.usernameIsEmail=Umbraco.Sys.ServerVariables.umbracoSettings.usernameIsEmail;vm.allowDisableUser=true;vm.allowEnableUser=true;vm.allowUnlockUser=true;vm.allowSetUserGroup=true;vm.layouts=[{'icon':'icon-thumbnails-small','path':'1','selected':true},{'icon':'icon-list','path':'2','selected':true}];vm.activeLayout=listViewHelper.getLayout('users',vm.layouts);if(Umbraco.Sys.ServerVariables.umbracoSettings.showUserInvite){vm.defaultButton={labelKey:'user_inviteUser',handler:function handler(){vm.setUsersViewState('inviteUser');}};vm.subButtons=[{labelKey:'user_createUser',handler:function handler(){vm.setUsersViewState('createUser');}}];}else{vm.defaultButton={labelKey:'user_createUser',handler:function handler(){vm.setUsersViewState('createUser');}};} -vm.toggleFilter=toggleFilter;vm.setUsersViewState=setUsersViewState;vm.selectLayout=selectLayout;vm.isSelectable=isSelectable;vm.selectUser=selectUser;vm.clearSelection=clearSelection;vm.clickUser=clickUser;vm.getEditPath=getEditPath;vm.disableUsers=disableUsers;vm.enableUsers=enableUsers;vm.unlockUsers=unlockUsers;vm.openBulkUserGroupPicker=openBulkUserGroupPicker;vm.openUserGroupPicker=openUserGroupPicker;vm.removeSelectedUserGroup=removeSelectedUserGroup;vm.selectAll=selectAll;vm.areAllSelected=areAllSelected;vm.searchUsers=searchUsers;vm.onBlurSearch=onBlurSearch;vm.getFilterName=getFilterName;vm.setUserStatesFilter=setUserStatesFilter;vm.setUserGroupFilter=setUserGroupFilter;vm.setOrderByFilter=setOrderByFilter;vm.changePageNumber=changePageNumber;vm.createUser=createUser;vm.inviteUser=inviteUser;vm.getSortLabel=getSortLabel;vm.toggleNewUserPassword=toggleNewUserPassword;vm.copySuccess=copySuccess;vm.copyError=copyError;vm.goToUser=goToUser;function init(){initViewOptions();if($routeParams.create){setUsersViewState('createUser');}else if($routeParams.invite){setUsersViewState('inviteUser');} -getUsers();userGroupsResource.getUserGroups({onlyCurrentUserGroups:false}).then(function(userGroups){vm.userGroups=userGroups;initUserGroupSelections();});} -function initViewOptions(){vm.usersOptions.filter='';vm.usersOptions.orderBy='Name';vm.usersOptions.orderDirection='Ascending';initViewOptionFromQueryString('filter');initViewOptionFromQueryString('orderBy');initViewOptionFromQueryString('orderDirection');initViewOptionFromQueryString('pageNumber');initViewOptionFromQueryString('userStates',true);initViewOptionFromQueryString('userGroups',true);} -function initViewOptionFromQueryString(key,isCollection){var value=$location.search()[key];if(value){if(isCollection){value=value.split(',');} -vm.usersOptions[key]=value;}} -function initUserStateSelections(){initUsersOptionsFilterSelections(vm.userStatesFilter,vm.usersOptions.userStates,'key');} -function initUserGroupSelections(){initUsersOptionsFilterSelections(vm.userGroups,vm.usersOptions.userGroups,'alias');} -function initUsersOptionsFilterSelections(filterCollection,selectedCollection,keyField){if(selectedCollection&&selectedCollection.length>0&&filterCollection&&filterCollection.length>0){for(var i=0;ib.alias?1:a.alias=0){vm.usersOptions.userStates.splice(indexOfAll,1);}} -if(userState.selected){vm.usersOptions.userStates.push(userState.key);}else{var index=vm.usersOptions.userStates.indexOf(userState.key);vm.usersOptions.userStates.splice(index,1);} -updateLocation('userStates',vm.usersOptions.userStates.join(','));changePageNumber(1);} -function setUserGroupFilter(userGroup){if(!vm.usersOptions.userGroups){vm.usersOptions.userGroups=[];} -if(userGroup.selected){vm.usersOptions.userGroups.push(userGroup.alias);}else{var index=vm.usersOptions.userGroups.indexOf(userGroup.alias);vm.usersOptions.userGroups.splice(index,1);} -updateLocation('userGroups',vm.usersOptions.userGroups.join(','));changePageNumber(1);} -function setOrderByFilter(value,direction){vm.usersOptions.orderBy=value;vm.usersOptions.orderDirection=direction;updateLocation('orderBy',value);updateLocation('orderDirection',direction);getUsers();} -function changePageNumber(pageNumber){vm.usersOptions.pageNumber=pageNumber;updateLocation('pageNumber',pageNumber);getUsers();} -function updateLocation(key,value){$location.search('filter',vm.usersOptions.filter);$location.search(key,value);} -function createUser(addUserForm){if(formHelper.submitForm({formCtrl:addUserForm,scope:$scope})){vm.newUser.id=-1;vm.newUser.parentId=-1;vm.page.createButtonState='busy';usersResource.createUser(vm.newUser).then(function(saved){vm.page.createButtonState='success';vm.newUser=saved;setUsersViewState('createUserSuccess');getUsers();},function(err){formHelper.handleError(err);vm.page.createButtonState='error';});}} -function inviteUser(addUserForm){if(formHelper.submitForm({formCtrl:addUserForm,scope:$scope})){vm.newUser.id=-1;vm.newUser.parentId=-1;vm.page.createButtonState='busy';usersResource.inviteUser(vm.newUser).then(function(saved){vm.page.createButtonState='success';vm.newUser=saved;setUsersViewState('inviteUserSuccess');getUsers();},function(err){formHelper.handleError(err);vm.page.createButtonState='error';});}} -function toggleNewUserPassword(){vm.newUser.showPassword=!vm.newUser.showPassword;} -function copySuccess(){if(vm.page.copyPasswordButtonState!=='success'){$timeout(function(){vm.page.copyPasswordButtonState='success';});$timeout(function(){resetClipboardButtonState();},1000);}} -function copyError(){if(vm.page.copyPasswordButtonState!=='error'){$timeout(function(){vm.page.copyPasswordButtonState='error';});$timeout(function(){resetClipboardButtonState();},1000);}} -function resetClipboardButtonState(){vm.page.copyPasswordButtonState='init';} -function goToUser(user){$location.path(pathToUser(user)).search('orderBy',vm.usersOptions.orderBy).search('orderDirection',vm.usersOptions.orderDirection).search('pageNumber',vm.usersOptions.pageNumber).search('userStates',getUsersOptionsFilterCollectionAsDelimitedStringOrNull(vm.usersOptions.userStates)).search('userGroups',getUsersOptionsFilterCollectionAsDelimitedStringOrNull(vm.usersOptions.userGroups)).search('create',null).search('invite',null);} -function getUsersOptionsFilterCollectionAsDelimitedStringOrNull(collection){if(collection&&collection.length>0){return collection.join(',');} -return null;} -function getEditPath(user){return pathToUser(user)+usersOptionsAsQueryString();} -function pathToUser(user){return'/users/users/user/'+user.id;} -function usersOptionsAsQueryString(){var qs='?orderBy='+vm.usersOptions.orderBy+'&orderDirection='+vm.usersOptions.orderDirection+'&pageNumber='+vm.usersOptions.pageNumber+'&filter='+vm.usersOptions.filter;qs+=addUsersOptionsFilterCollectionToQueryString('userStates',vm.usersOptions.userStates);qs+=addUsersOptionsFilterCollectionToQueryString('userGroups',vm.usersOptions.userGroups);qs+='&mculture='+$location.search().mculture;return qs;} -function addUsersOptionsFilterCollectionToQueryString(name,collection){if(collection&&collection.length>0){return'&'+name+'='+collection.join(',');} -return'';} -function getUsers(){vm.loading=true;usersResource.getPagedResults(vm.usersOptions).then(function(data){vm.users=data.items;vm.usersOptions.pageNumber=data.pageNumber;vm.usersOptions.pageSize=data.pageSize;vm.usersOptions.totalItems=data.totalItems;vm.usersOptions.totalPages=data.totalPages;formatDates(vm.users);setUserDisplayState(vm.users);vm.userStatesFilter=usersHelper.getUserStatesFilter(data.userStates);initUserStateSelections();vm.loading=false;},function(error){vm.loading=false;});} -function setUserDisplayState(users){angular.forEach(users,function(user){user.userDisplayState=usersHelper.getUserStateFromValue(user.userState);});} -function formatDates(users){angular.forEach(users,function(user){if(user.lastLoginDate){var dateVal;var serverOffset=Umbraco.Sys.ServerVariables.application.serverTimeOffset;var localOffset=new Date().getTimezoneOffset();var serverTimeNeedsOffsetting=-serverOffset!==localOffset;if(serverTimeNeedsOffsetting){dateVal=dateHelper.convertToLocalMomentTime(user.lastLoginDate,serverOffset);}else{dateVal=moment(user.lastLoginDate,'YYYY-MM-DD HH:mm:ss');} -userService.getCurrentUser().then(function(currentUser){user.formattedLastLogin=dateVal.locale(currentUser.locale).format('LLL');});}});} -function setBulkActions(users){vm.allowDisableUser=true;vm.allowEnableUser=true;vm.allowUnlockUser=true;vm.allowSetUserGroup=true;var firstSelectedUserGroups;angular.forEach(users,function(user){if(!user.selected){return;} -if(user.isCurrentUser){vm.allowDisableUser=false;vm.allowEnableUser=false;vm.allowUnlockUser=false;vm.allowSetUserGroup=false;return false;} -if(user.userDisplayState&&user.userDisplayState.key==='Disabled'){vm.allowDisableUser=false;} -if(user.userDisplayState&&user.userDisplayState.key==='Active'){vm.allowEnableUser=false;} -if(user.userDisplayState&&user.userDisplayState.key==='Invited'){vm.allowEnableUser=false;} -if(user.userDisplayState&&user.userDisplayState.key==='LockedOut'){vm.allowEnableUser=false;} -if(user.userDisplayState&&user.userDisplayState.key!=='LockedOut'){vm.allowUnlockUser=false;} -if(vm.allowSetUserGroup===true){if(!firstSelectedUserGroups){firstSelectedUserGroups=user.userGroups.map(function(ug){return ug.alias;});}else{var userGroups=user.userGroups.map(function(ug){return ug.alias;});if(_.difference(firstSelectedUserGroups,userGroups).length>0){vm.allowSetUserGroup=false;}}}});} -function clearAddUserForm(){vm.newUser.name='';vm.newUser.email='';vm.newUser.userGroups=[];vm.newUser.message='';vm.page.createButtonState='init';$scope.$emit('$setAccessibleHeader',true,'general_user',false,'','',true);} -init();} -angular.module('umbraco').controller('Umbraco.Editors.Users.UsersController',UsersController);}());}());; \ No newline at end of file diff --git a/src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/c3fc92ad.js b/src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/c3fc92ad.js deleted file mode 100644 index 9f71ed7455..0000000000 --- a/src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/c3fc92ad.js +++ /dev/null @@ -1,14 +0,0 @@ -/* - AngularJS v1.7.9 - (c) 2010-2018 Google, Inc. http://angularjs.org - License: MIT -*/ -(function(t,l){'use strict';var c="BUTTON A INPUT TEXTAREA SELECT DETAILS SUMMARY".split(" "),m=function(a,e){if(-1!==e.indexOf(a[0].nodeName))return!0};l.module("ngAria",["ng"]).info({angularVersion:"1.7.9"}).provider("$aria",function(){function a(a,c,n,g){return function(d,f,b){if(!b.hasOwnProperty("ngAriaDisable")){var p=b.$normalize(c);!e[p]||m(f,n)||b[p]||d.$watch(b[a],function(b){b=g?!b:!!b;f.attr(c,b)})}}}var e={ariaHidden:!0,ariaChecked:!0,ariaReadonly:!0,ariaDisabled:!0,ariaRequired:!0,ariaInvalid:!0, -ariaValue:!0,tabindex:!0,bindKeydown:!0,bindRoleForClick:!0};this.config=function(a){e=l.extend(e,a)};this.$get=function(){return{config:function(a){return e[a]},$$watchExpr:a}}}).directive("ngShow",["$aria",function(a){return a.$$watchExpr("ngShow","aria-hidden",[],!0)}]).directive("ngHide",["$aria",function(a){return a.$$watchExpr("ngHide","aria-hidden",[],!1)}]).directive("ngValue",["$aria",function(a){return a.$$watchExpr("ngValue","aria-checked",c,!1)}]).directive("ngChecked",["$aria",function(a){return a.$$watchExpr("ngChecked", -"aria-checked",c,!1)}]).directive("ngReadonly",["$aria",function(a){return a.$$watchExpr("ngReadonly","aria-readonly",c,!1)}]).directive("ngRequired",["$aria",function(a){return a.$$watchExpr("ngRequired","aria-required",c,!1)}]).directive("ngModel",["$aria",function(a){function e(e,g,d,f){return a.config(g)&&!d.attr(e)&&(f||!m(d,c))&&("hidden"!==d.attr("type")||"INPUT"!==d[0].nodeName)}function k(a,e){return!e.attr("role")&&e.attr("type")===a&&!m(e,c)}function h(a,e){var d=a.type,f=a.role;return"checkbox"=== -(d||f)||"menuitemcheckbox"===f?"checkbox":"radio"===(d||f)||"menuitemradio"===f?"radio":"range"===d||"progressbar"===f||"slider"===f?"range":""}return{restrict:"A",require:"ngModel",priority:200,compile:function(c,g){if(!g.hasOwnProperty("ngAriaDisable")){var d=h(g,c);return{post:function(f,b,c,g){function h(){return g.$modelValue}function m(a){b.attr("aria-checked",c.value==g.$viewValue)}function n(){b.attr("aria-checked",!g.$isEmpty(g.$viewValue))}var l=e("tabindex","tabindex",b,!1);switch(d){case "radio":case "checkbox":k(d, -b)&&b.attr("role",d);e("aria-checked","ariaChecked",b,!1)&&f.$watch(h,"radio"===d?m:n);l&&b.attr("tabindex",0);break;case "range":k(d,b)&&b.attr("role","slider");if(a.config("ariaValue")){var q=!b.attr("aria-valuemin")&&(c.hasOwnProperty("min")||c.hasOwnProperty("ngMin")),r=!b.attr("aria-valuemax")&&(c.hasOwnProperty("max")||c.hasOwnProperty("ngMax")),s=!b.attr("aria-valuenow");q&&c.$observe("min",function(a){b.attr("aria-valuemin",a)});r&&c.$observe("max",function(a){b.attr("aria-valuemax",a)}); -s&&f.$watch(h,function(a){b.attr("aria-valuenow",a)})}l&&b.attr("tabindex",0)}!c.hasOwnProperty("ngRequired")&&g.$validators.required&&e("aria-required","ariaRequired",b,!1)&&c.$observe("required",function(){b.attr("aria-required",!!c.required)});e("aria-invalid","ariaInvalid",b,!0)&&f.$watch(function(){return g.$invalid},function(a){b.attr("aria-invalid",!!a)})}}}}}}]).directive("ngDisabled",["$aria",function(a){return a.$$watchExpr("ngDisabled","aria-disabled",c,!1)}]).directive("ngMessages",function(){return{restrict:"A", -require:"?ngMessages",link:function(a,c,k,h){k.hasOwnProperty("ngAriaDisable")||c.attr("aria-live")||c.attr("aria-live","assertive")}}}).directive("ngClick",["$aria","$parse",function(a,e){return{restrict:"A",compile:function(k,h){if(!h.hasOwnProperty("ngAriaDisable")){var l=e(h.ngClick);return function(e,d,f){if(!m(d,c)&&(a.config("bindRoleForClick")&&!d.attr("role")&&d.attr("role","button"),a.config("tabindex")&&!d.attr("tabindex")&&d.attr("tabindex",0),a.config("bindKeydown")&&!f.ngKeydown&&!f.ngKeypress&& -!f.ngKeyup))d.on("keydown",function(a){function d(){l(e,{$event:a})}var f=a.which||a.keyCode;if(13===f||32===f)-1!==c.indexOf(a.target.nodeName)||a.target.isContentEditable||a.preventDefault(),e.$apply(d)})}}}}}]).directive("ngDblclick",["$aria",function(a){return function(e,k,h){h.hasOwnProperty("ngAriaDisable")||!a.config("tabindex")||k.attr("tabindex")||m(k,c)||k.attr("tabindex",0)}}])})(window,window.angular); -//# sourceMappingURL=angular-aria.min.js.map diff --git a/src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/c53cdd84.js b/src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/c53cdd84.js deleted file mode 100644 index c3993246c4..0000000000 --- a/src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/c53cdd84.js +++ /dev/null @@ -1,33 +0,0 @@ -/* - 2017 Julian Garnier - Released under the MIT license -*/ -var $jscomp={scope:{}};$jscomp.defineProperty="function"==typeof Object.defineProperties?Object.defineProperty:function(e,r,p){if(p.get||p.set)throw new TypeError("ES3 does not support getters and setters.");e!=Array.prototype&&e!=Object.prototype&&(e[r]=p.value)};$jscomp.getGlobal=function(e){return"undefined"!=typeof window&&window===e?e:"undefined"!=typeof global&&null!=global?global:e};$jscomp.global=$jscomp.getGlobal(this);$jscomp.SYMBOL_PREFIX="jscomp_symbol_"; -$jscomp.initSymbol=function(){$jscomp.initSymbol=function(){};$jscomp.global.Symbol||($jscomp.global.Symbol=$jscomp.Symbol)};$jscomp.symbolCounter_=0;$jscomp.Symbol=function(e){return $jscomp.SYMBOL_PREFIX+(e||"")+$jscomp.symbolCounter_++}; -$jscomp.initSymbolIterator=function(){$jscomp.initSymbol();var e=$jscomp.global.Symbol.iterator;e||(e=$jscomp.global.Symbol.iterator=$jscomp.global.Symbol("iterator"));"function"!=typeof Array.prototype[e]&&$jscomp.defineProperty(Array.prototype,e,{configurable:!0,writable:!0,value:function(){return $jscomp.arrayIterator(this)}});$jscomp.initSymbolIterator=function(){}};$jscomp.arrayIterator=function(e){var r=0;return $jscomp.iteratorPrototype(function(){return rb&&(b+=1);1b?c:b<2/3?a+(c-a)*(2/3-b)*6:a}var d=/hsl\((\d+),\s*([\d.]+)%,\s*([\d.]+)%\)/g.exec(a)||/hsla\((\d+),\s*([\d.]+)%,\s*([\d.]+)%,\s*([\d.]+)\)/g.exec(a);a=parseInt(d[1])/360;var b=parseInt(d[2])/100,f=parseInt(d[3])/100,d=d[4]||1;if(0==b)f=b=a=f;else{var n=.5>f?f*(1+b):f+b-f*b,k=2*f-n,f=c(k,n,a+1/3),b=c(k,n,a);a=c(k,n,a-1/3)}return"rgba("+ -255*f+","+255*b+","+255*a+","+d+")"}function y(a){if(a=/([\+\-]?[0-9#\.]+)(%|px|pt|em|rem|in|cm|mm|ex|ch|pc|vw|vh|vmin|vmax|deg|rad|turn)?$/.exec(a))return a[2]}function V(a){if(-1=g.currentTime)for(var G=0;G=w||!k)g.began||(g.began=!0,f("begin")),f("run");if(q>n&&q=k&&r!==k||!k)b(k),x||e();f("update");a>=k&&(g.remaining?(t=h,"alternate"===g.direction&&(g.reversed=!g.reversed)):(g.pause(),g.completed||(g.completed=!0,f("complete"),"Promise"in window&&(p(),m=c()))),l=0)}a=void 0===a?{}:a;var h,t,l=0,p=null,m=c(),g=fa(a);g.reset=function(){var a=g.direction,c=g.loop;g.currentTime= -0;g.progress=0;g.paused=!0;g.began=!1;g.completed=!1;g.reversed="reverse"===a;g.remaining="alternate"===a&&1===c?2:c;b(0);for(a=g.children.length;a--;)g.children[a].reset()};g.tick=function(a){h=a;t||(t=h);k((l+h-t)*q.speed)};g.seek=function(a){k(d(a))};g.pause=function(){var a=v.indexOf(g);-1=c&&0<=b&&1>=b){var e=new Float32Array(11);if(c!==d||b!==f)for(var k=0;11>k;++k)e[k]=a(.1*k,c,b);return function(k){if(c===d&&b===f)return k;if(0===k)return 0;if(1===k)return 1;for(var h=0,l=1;10!==l&&e[l]<=k;++l)h+=.1;--l;var l=h+(k-e[l])/(e[l+1]-e[l])*.1,n=3*(1-3*b+3*c)*l*l+2*(3*b-6*c)*l+3*c;if(.001<=n){for(h=0;4>h;++h){n=3*(1-3*b+3*c)*l*l+2*(3*b-6*c)*l+3*c;if(0===n)break;var m=a(l,c,b)-k,l=l-m/n}k=l}else if(0=== -n)k=l;else{var l=h,h=h+.1,g=0;do m=l+(h-l)/2,n=a(m,c,b)-k,0++g);k=m}return a(k,d,f)}}}}(),Q=function(){function a(a,b){return 0===a||1===a?a:-Math.pow(2,10*(a-1))*Math.sin(2*(a-1-b/(2*Math.PI)*Math.asin(1))*Math.PI/b)}var c="Quad Cubic Quart Quint Sine Expo Circ Back Elastic".split(" "),d={In:[[.55,.085,.68,.53],[.55,.055,.675,.19],[.895,.03,.685,.22],[.755,.05,.855,.06],[.47,0,.745,.715],[.95,.05,.795,.035],[.6,.04,.98,.335],[.6,-.28,.735,.045],a],Out:[[.25, -.46,.45,.94],[.215,.61,.355,1],[.165,.84,.44,1],[.23,1,.32,1],[.39,.575,.565,1],[.19,1,.22,1],[.075,.82,.165,1],[.175,.885,.32,1.275],function(b,c){return 1-a(1-b,c)}],InOut:[[.455,.03,.515,.955],[.645,.045,.355,1],[.77,0,.175,1],[.86,0,.07,1],[.445,.05,.55,.95],[1,0,0,1],[.785,.135,.15,.86],[.68,-.55,.265,1.55],function(b,c){return.5>b?a(2*b,c)/2:1-a(-2*b+2,c)/2}]},b={linear:A(.25,.25,.75,.75)},f={},e;for(e in d)f.type=e,d[f.type].forEach(function(a){return function(d,f){b["ease"+a.type+c[f]]=h.fnc(d)? -d:A.apply($jscomp$this,d)}}(f)),f={type:f.type};return b}(),ha={css:function(a,c,d){return a.style[c]=d},attribute:function(a,c,d){return a.setAttribute(c,d)},object:function(a,c,d){return a[c]=d},transform:function(a,c,d,b,f){b[f]||(b[f]=[]);b[f].push(c+"("+d+")")}},v=[],B=0,ia=function(){function a(){B=requestAnimationFrame(c)}function c(c){var b=v.length;if(b){for(var d=0;db&&(c.duration=d.duration);c.children.push(d)});c.seek(0);c.reset();c.autoplay&&c.restart();return c};return c};q.random=function(a,c){return Math.floor(Math.random()*(c-a+1))+a};return q}); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/c980e938.js b/src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/c980e938.js deleted file mode 100644 index d3a23bc910..0000000000 --- a/src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/c980e938.js +++ /dev/null @@ -1,17 +0,0 @@ -app.run(['$rootScope','$route','$location','urlHelper','navigationService','appState','assetsService','eventsService','$cookies','tourService','localStorageService',function($rootScope,$route,$location,urlHelper,navigationService,appState,assetsService,eventsService,$cookies,tourService,localStorageService){$.ajaxSetup({beforeSend:function(xhr){xhr.setRequestHeader("X-UMB-XSRF-TOKEN",$cookies["UMB-XSRF-TOKEN"]);xhr.setRequestHeader("X-Requested-With","XMLHttpRequest");var queryStrings=urlHelper.getQueryStringParams();if(queryStrings.umbDebug==="true"||queryStrings.umbdebug==="true"){xhr.setRequestHeader("X-UMB-DEBUG","true");}}});eventsService.on("app.authenticated",function(evt,data){assetsService._loadInitAssets().then(function(){appReady(data);tourService.registerAllTours().then(function(){tourService.getTourByAlias("umbIntroIntroduction").then(function(introTour){if(introTour&&introTour.disabled!==true&&introTour.completed!==true){tourService.startTour(introTour);localStorageService.set("introTourShown",true);} -else{const introTourShown=localStorageService.get("introTourShown");if(!introTourShown){tourService.getTourByAlias("umbEmailMarketing").then(function(emailMarketingTour){if(emailMarketingTour&&emailMarketingTour.disabled!==true&&emailMarketingTour.completed!==true){const emailMarketingTourShown=localStorageService.get("emailMarketingTourShown");if(!emailMarketingTourShown){tourService.startTour(emailMarketingTour);localStorageService.set("emailMarketingTourShown",true);}}});}}});});});});function appReady(data){appState.setGlobalState("isReady",true);eventsService.emit("app.ready",data);returnToPath=null,returnToSearch=null;} -var currentRouteParams=null;var originalTitle="";$rootScope.$on('$changeTitle',function(event,titlePrefix){if(titlePrefix){$rootScope.locationTitle=titlePrefix+" - "+originalTitle;}else{$rootScope.locationTitle=originalTitle;}});$rootScope.$on('$routeChangeSuccess',function(event,current,previous){var toRetain=currentRouteParams?navigationService.retainQueryStrings(currentRouteParams,current.params):null;if(toRetain){$route.updateParams(toRetain);currentRouteParams=toRetain;} -else{currentRouteParams=Utilities.copy(current.params);} -var deployConfig=Umbraco.Sys.ServerVariables.deploy;var deployEnv,deployEnvTitle;if(deployConfig){deployEnv=Umbraco.Sys.ServerVariables.deploy.CurrentWorkspace;deployEnvTitle="("+deployEnv+") ";} -if(current.params.section){var currentSection=current.params.section.charAt(0).toUpperCase()+current.params.section.slice(1);var baseTitle=currentSection+" - "+$location.$$host;if(deployEnv){$rootScope.locationTitle=deployEnvTitle+baseTitle;} -else{$rootScope.locationTitle=baseTitle;}} -else{if(deployEnv){$rootScope.locationTitle=deployEnvTitle+"Umbraco - "+$location.$$host;} -$rootScope.locationTitle="Umbraco - "+$location.$$host;} -originalTitle=$rootScope.locationTitle;});$rootScope.$on('$routeChangeError',function(event,current,previous,rejection){if(rejection.path){event.preventDefault();var returnPath=null;if(rejection.path=="/login"||rejection.path.startsWith("/login/")){returnPath=encodeURIComponent($location.url());} -$location.path(rejection.path) -if(returnPath){$location.search("returnPath",returnPath);}}});$rootScope.$on('$routeUpdate',function(event,next){if(!currentRouteParams){$route.reload();} -else{var toRetain=navigationService.retainQueryStrings(currentRouteParams,next.params);if(toRetain){$route.updateParams(toRetain);} -if(navigationService.isRouteChangingNavigation(currentRouteParams,next.params)){$route.reload();} -else{if(toRetain){currentRouteParams=toRetain;} -else{currentRouteParams=Utilities.copy(next.params);} -if(currentRouteParams.sr){currentRouteParams.sr=null;$route.updateParams(currentRouteParams);}}}});var touchDevice=/android|webos|iphone|ipad|ipod|blackberry|iemobile|touch/i.test(navigator.userAgent.toLowerCase());appState.setGlobalState("touchDevice",touchDevice);}]);; \ No newline at end of file diff --git a/src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/cb35914a.js b/src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/cb35914a.js deleted file mode 100644 index 72bc2cabd1..0000000000 --- a/src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/cb35914a.js +++ /dev/null @@ -1 +0,0 @@ -!function(){"use strict";var n=tinymce.util.Tools.resolve("tinymce.PluginManager"),t=function(n){n.addCommand("InsertHorizontalRule",function(){n.execCommand("mceInsertContent",!1,"
")})},o=function(n){n.addButton("hr",{icon:"hr",tooltip:"Horizontal line",cmd:"InsertHorizontalRule"}),n.addMenuItem("hr",{icon:"hr",text:"Horizontal line",cmd:"InsertHorizontalRule",context:"insert"})};n.add("hr",function(n){t(n),o(n)})}(); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/cd2e37b0.js b/src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/cd2e37b0.js deleted file mode 100644 index d92fc6df35..0000000000 --- a/src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/cd2e37b0.js +++ /dev/null @@ -1 +0,0 @@ -!function(u){"use strict";var e,n,t,r,o,i,s,a,c,f=tinymce.util.Tools.resolve("tinymce.PluginManager"),d=tinymce.util.Tools.resolve("tinymce.dom.RangeUtils"),l=tinymce.util.Tools.resolve("tinymce.dom.TreeWalker"),m=tinymce.util.Tools.resolve("tinymce.util.VK"),p=tinymce.util.Tools.resolve("tinymce.dom.BookmarkManager"),v=tinymce.util.Tools.resolve("tinymce.util.Tools"),g=tinymce.util.Tools.resolve("tinymce.dom.DOMUtils"),h=function(e){return e&&"BR"===e.nodeName},y=function(e){return e&&3===e.nodeType},N=function(e){return e&&/^(OL|UL|DL)$/.test(e.nodeName)},S=function(e){return e&&/^(OL|UL)$/.test(e.nodeName)},C=function(e){return e&&/^(DT|DD)$/.test(e.nodeName)},O=function(e){return e&&/^(LI|DT|DD)$/.test(e.nodeName)},b=function(e){return e&&/^(TH|TD)$/.test(e.nodeName)},T=h,E=function(e,n){return n&&!!e.schema.getTextBlockElements()[n.nodeName]},L=function(e,n){return e&&e.nodeName in n},D=function(e,n){return!!h(n)&&!(!e.isBlock(n.nextSibling)||h(n.previousSibling))},w=function(e,n,t){var r=e.isEmpty(n);return!(t&&0=e.childNodes.length?t.data.length:0}:t.previousSibling&&y(t.previousSibling)?{container:t.previousSibling,offset:t.previousSibling.data.length}:t.nextSibling&&y(t.nextSibling)?{container:t.nextSibling,offset:0}:{container:e,offset:n}},x=function(e){var n=e.cloneRange(),t=A(e.startContainer,e.startOffset);n.setStart(t.container,t.offset);var r=A(e.endContainer,e.endOffset);return n.setEnd(r.container,r.offset),n},R=g.DOM,I=function(o){var i={},e=function(e){var n,t,r;t=o[e?"startContainer":"endContainer"],r=o[e?"startOffset":"endOffset"],1===t.nodeType&&(n=R.create("span",{"data-mce-type":"bookmark"}),t.hasChildNodes()?(r=Math.min(r,t.childNodes.length-1),e?t.insertBefore(n,t.childNodes[r]):R.insertAfter(n,t.childNodes[r])):t.appendChild(n),t=n,r=0),i[e?"startContainer":"endContainer"]=t,i[e?"startOffset":"endOffset"]=r};return e(!0),o.collapsed||e(),i},_=function(o){function e(e){var n,t,r;n=r=o[e?"startContainer":"endContainer"],t=o[e?"startOffset":"endOffset"],n&&(1===n.nodeType&&(t=function(e){for(var n=e.parentNode.firstChild,t=0;n;){if(n===e)return t;1===n.nodeType&&"bookmark"===n.getAttribute("data-mce-type")||t++,n=n.nextSibling}return-1}(n),n=n.parentNode,R.remove(r),!n.hasChildNodes()&&R.isBlock(n)&&n.appendChild(R.create("br"))),o[e?"startContainer":"endContainer"]=n,o[e?"startOffset":"endOffset"]=t)}e(!0),e();var n=R.createRng();return n.setStart(o.startContainer,o.startOffset),o.endContainer&&n.setEnd(o.endContainer,o.endOffset),x(n)},B=function(){},P=function(e){return function(){return e}},M=function(t){return function(){for(var e=[],n=0;ne.length?Sn(t,e,n):Nn(t,e,n)},[]),oe(o).map(function(e){return e.list})).toArray();var t,r,o},Pn=function(e){var n,t,r=J(ve.getSelectedListItems(e),ye.fromDom);return Ne(te(r,M(On)),te((n=r,(t=Y.call(n,0)).reverse(),t),M(On)),function(e,n){return{start:e,end:n}})},Mn=function(s,e,a){var n,t,r,o=(n=e,t=Pn(s),r=kn(!1),J(n,function(e){return{sourceList:e,entries:xn(0,t,r,e)}}));Z(o,function(e){var n,t,r,o,i,u;n=e.entries,t=a,Z(ee(n,Tn),function(e){return function(e,n){switch(e){case"Indent":n.depth++;break;case"Outdent":n.depth--;break;case"Flatten":n.depth=0}}(t,e)}),r=e.sourceList,i=s,u=e.entries,o=re(function(e,n){if(0===e.length)return[];for(var t=n(e[0]),r=[],o=[],i=0,u=e.length;i0;});if(filtered){return $q.reject(rejection);}} -if(rejection.status===401){var umbRequestHelper=$injector.get('umbRequestHelper');var getCurrentUserPath=umbRequestHelper.getApiUrl('authenticationApiBaseUrl','GetCurrentUser');if(!rejection.config.url.endsWith(getCurrentUserPath)){var userService=$injector.get('userService');return userService.getCurrentUser().then(function(user){var userName=user?user.name:null;return requestRetryQueue.pushRetryFn('unauthorized-server',userName,function retryRequest(){return $injector.get('$http')(rejection.config);});});}}else if(rejection.status===404){var errMsg='The URL returned a 404 (not found):
'+rejection.config.url.split('?')[0]+'';if(rejection.data&&rejection.data.ExceptionMessage){errMsg+='
with error:
'+rejection.data.ExceptionMessage+'';} -notificationsService.error('Request error',errMsg);}else if(rejection.status===403){var msg='Unauthorized access to URL:
'+rejection.config.url.split('?')[0]+'
Contact your administrator for information.';notificationsService.error('Authorization error',msg);} -return $q.reject(rejection);}};} -angular.module('umbraco.interceptors').factory('securityInterceptor',securityInterceptor);}());}());; \ No newline at end of file diff --git a/src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/d1aa3809.js b/src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/d1aa3809.js deleted file mode 100644 index 580a6a2dc2..0000000000 --- a/src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/d1aa3809.js +++ /dev/null @@ -1 +0,0 @@ -!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.moment=t()}(this,function(){"use strict";var e,i;function c(){return e.apply(null,arguments)}function o(e){return e instanceof Array||"[object Array]"===Object.prototype.toString.call(e)}function u(e){return null!=e&&"[object Object]"===Object.prototype.toString.call(e)}function l(e){return void 0===e}function d(e){return"number"==typeof e||"[object Number]"===Object.prototype.toString.call(e)}function h(e){return e instanceof Date||"[object Date]"===Object.prototype.toString.call(e)}function f(e,t){var n,s=[];for(n=0;n>>0,s=0;sDe(e)?(r=e+1,a=o-De(e)):(r=e,a=o),{year:r,dayOfYear:a}}function Ie(e,t,n){var s,i,r=Ve(e.year(),t,n),a=Math.floor((e.dayOfYear()-r-1)/7)+1;return a<1?s=a+Ae(i=e.year()-1,t,n):a>Ae(e.year(),t,n)?(s=a-Ae(e.year(),t,n),i=e.year()+1):(i=e.year(),s=a),{week:s,year:i}}function Ae(e,t,n){var s=Ve(e,t,n),i=Ve(e+1,t,n);return(De(e)-s+i)/7}I("w",["ww",2],"wo","week"),I("W",["WW",2],"Wo","isoWeek"),H("week","w"),H("isoWeek","W"),L("week",5),L("isoWeek",5),ue("w",B),ue("ww",B,z),ue("W",B),ue("WW",B,z),fe(["w","ww","W","WW"],function(e,t,n,s){t[s.substr(0,1)]=k(e)});I("d",0,"do","day"),I("dd",0,0,function(e){return this.localeData().weekdaysMin(this,e)}),I("ddd",0,0,function(e){return this.localeData().weekdaysShort(this,e)}),I("dddd",0,0,function(e){return this.localeData().weekdays(this,e)}),I("e",0,0,"weekday"),I("E",0,0,"isoWeekday"),H("day","d"),H("weekday","e"),H("isoWeekday","E"),L("day",11),L("weekday",11),L("isoWeekday",11),ue("d",B),ue("e",B),ue("E",B),ue("dd",function(e,t){return t.weekdaysMinRegex(e)}),ue("ddd",function(e,t){return t.weekdaysShortRegex(e)}),ue("dddd",function(e,t){return t.weekdaysRegex(e)}),fe(["dd","ddd","dddd"],function(e,t,n,s){var i=n._locale.weekdaysParse(e,s,n._strict);null!=i?t.d=i:g(n).invalidWeekday=e}),fe(["d","e","E"],function(e,t,n,s){t[s]=k(e)});var je="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_");var Ze="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_");var ze="Su_Mo_Tu_We_Th_Fr_Sa".split("_");var $e=ae;var qe=ae;var Je=ae;function Be(){function e(e,t){return t.length-e.length}var t,n,s,i,r,a=[],o=[],u=[],l=[];for(t=0;t<7;t++)n=y([2e3,1]).day(t),s=this.weekdaysMin(n,""),i=this.weekdaysShort(n,""),r=this.weekdays(n,""),a.push(s),o.push(i),u.push(r),l.push(s),l.push(i),l.push(r);for(a.sort(e),o.sort(e),u.sort(e),l.sort(e),t=0;t<7;t++)o[t]=de(o[t]),u[t]=de(u[t]),l[t]=de(l[t]);this._weekdaysRegex=new RegExp("^("+l.join("|")+")","i"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp("^("+u.join("|")+")","i"),this._weekdaysShortStrictRegex=new RegExp("^("+o.join("|")+")","i"),this._weekdaysMinStrictRegex=new RegExp("^("+a.join("|")+")","i")}function Qe(){return this.hours()%12||12}function Xe(e,t){I(e,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),t)})}function Ke(e,t){return t._meridiemParse}I("H",["HH",2],0,"hour"),I("h",["hh",2],0,Qe),I("k",["kk",2],0,function(){return this.hours()||24}),I("hmm",0,0,function(){return""+Qe.apply(this)+U(this.minutes(),2)}),I("hmmss",0,0,function(){return""+Qe.apply(this)+U(this.minutes(),2)+U(this.seconds(),2)}),I("Hmm",0,0,function(){return""+this.hours()+U(this.minutes(),2)}),I("Hmmss",0,0,function(){return""+this.hours()+U(this.minutes(),2)+U(this.seconds(),2)}),Xe("a",!0),Xe("A",!1),H("hour","h"),L("hour",13),ue("a",Ke),ue("A",Ke),ue("H",B),ue("h",B),ue("k",B),ue("HH",B,z),ue("hh",B,z),ue("kk",B,z),ue("hmm",Q),ue("hmmss",X),ue("Hmm",Q),ue("Hmmss",X),ce(["H","HH"],ge),ce(["k","kk"],function(e,t,n){var s=k(e);t[ge]=24===s?0:s}),ce(["a","A"],function(e,t,n){n._isPm=n._locale.isPM(e),n._meridiem=e}),ce(["h","hh"],function(e,t,n){t[ge]=k(e),g(n).bigHour=!0}),ce("hmm",function(e,t,n){var s=e.length-2;t[ge]=k(e.substr(0,s)),t[pe]=k(e.substr(s)),g(n).bigHour=!0}),ce("hmmss",function(e,t,n){var s=e.length-4,i=e.length-2;t[ge]=k(e.substr(0,s)),t[pe]=k(e.substr(s,2)),t[ve]=k(e.substr(i)),g(n).bigHour=!0}),ce("Hmm",function(e,t,n){var s=e.length-2;t[ge]=k(e.substr(0,s)),t[pe]=k(e.substr(s))}),ce("Hmmss",function(e,t,n){var s=e.length-4,i=e.length-2;t[ge]=k(e.substr(0,s)),t[pe]=k(e.substr(s,2)),t[ve]=k(e.substr(i))});var et,tt=Te("Hours",!0),nt={calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},longDateFormat:{LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"},invalidDate:"Invalid date",ordinal:"%d",dayOfMonthOrdinalParse:/\d{1,2}/,relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},months:He,monthsShort:Re,week:{dow:0,doy:6},weekdays:je,weekdaysMin:ze,weekdaysShort:Ze,meridiemParse:/[ap]\.?m?\.?/i},st={},it={};function rt(e){return e?e.toLowerCase().replace("_","-"):e}function at(e){var t=null;if(!st[e]&&"undefined"!=typeof module&&module&&module.exports)try{t=et._abbr,require("./locale/"+e),ot(t)}catch(e){}return st[e]}function ot(e,t){var n;return e&&((n=l(t)?lt(e):ut(e,t))?et=n:"undefined"!=typeof console&&console.warn&&console.warn("Locale "+e+" not found. Did you forget to load it?")),et._abbr}function ut(e,t){if(null!==t){var n,s=nt;if(t.abbr=e,null!=st[e])T("defineLocaleOverride","use moment.updateLocale(localeName, config) to change an existing locale. moment.defineLocale(localeName, config) should only be used for creating a new locale See http://momentjs.com/guides/#/warnings/define-locale/ for more info."),s=st[e]._config;else if(null!=t.parentLocale)if(null!=st[t.parentLocale])s=st[t.parentLocale]._config;else{if(null==(n=at(t.parentLocale)))return it[t.parentLocale]||(it[t.parentLocale]=[]),it[t.parentLocale].push({name:e,config:t}),null;s=n._config}return st[e]=new P(b(s,t)),it[e]&&it[e].forEach(function(e){ut(e.name,e.config)}),ot(e),st[e]}return delete st[e],null}function lt(e){var t;if(e&&e._locale&&e._locale._abbr&&(e=e._locale._abbr),!e)return et;if(!o(e)){if(t=at(e))return t;e=[e]}return function(e){for(var t,n,s,i,r=0;r=t&&a(i,n,!0)>=t-1)break;t--}r++}return et}(e)}function dt(e){var t,n=e._a;return n&&-2===g(e).overflow&&(t=n[_e]<0||11Pe(n[me],n[_e])?ye:n[ge]<0||24Ae(n,r,a)?g(e)._overflowWeeks=!0:null!=u?g(e)._overflowWeekday=!0:(o=Ee(n,s,i,r,a),e._a[me]=o.year,e._dayOfYear=o.dayOfYear)}(e),null!=e._dayOfYear&&(r=ht(e._a[me],s[me]),(e._dayOfYear>De(r)||0===e._dayOfYear)&&(g(e)._overflowDayOfYear=!0),n=Ge(r,0,e._dayOfYear),e._a[_e]=n.getUTCMonth(),e._a[ye]=n.getUTCDate()),t=0;t<3&&null==e._a[t];++t)e._a[t]=a[t]=s[t];for(;t<7;t++)e._a[t]=a[t]=null==e._a[t]?2===t?1:0:e._a[t];24===e._a[ge]&&0===e._a[pe]&&0===e._a[ve]&&0===e._a[we]&&(e._nextDay=!0,e._a[ge]=0),e._d=(e._useUTC?Ge:function(e,t,n,s,i,r,a){var o=new Date(e,t,n,s,i,r,a);return e<100&&0<=e&&isFinite(o.getFullYear())&&o.setFullYear(e),o}).apply(null,a),i=e._useUTC?e._d.getUTCDay():e._d.getDay(),null!=e._tzm&&e._d.setUTCMinutes(e._d.getUTCMinutes()-e._tzm),e._nextDay&&(e._a[ge]=24),e._w&&void 0!==e._w.d&&e._w.d!==i&&(g(e).weekdayMismatch=!0)}}var ft=/^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,mt=/^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,_t=/Z|[+-]\d\d(?::?\d\d)?/,yt=[["YYYYYY-MM-DD",/[+-]\d{6}-\d\d-\d\d/],["YYYY-MM-DD",/\d{4}-\d\d-\d\d/],["GGGG-[W]WW-E",/\d{4}-W\d\d-\d/],["GGGG-[W]WW",/\d{4}-W\d\d/,!1],["YYYY-DDD",/\d{4}-\d{3}/],["YYYY-MM",/\d{4}-\d\d/,!1],["YYYYYYMMDD",/[+-]\d{10}/],["YYYYMMDD",/\d{8}/],["GGGG[W]WWE",/\d{4}W\d{3}/],["GGGG[W]WW",/\d{4}W\d{2}/,!1],["YYYYDDD",/\d{7}/]],gt=[["HH:mm:ss.SSSS",/\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss,SSSS",/\d\d:\d\d:\d\d,\d+/],["HH:mm:ss",/\d\d:\d\d:\d\d/],["HH:mm",/\d\d:\d\d/],["HHmmss.SSSS",/\d\d\d\d\d\d\.\d+/],["HHmmss,SSSS",/\d\d\d\d\d\d,\d+/],["HHmmss",/\d\d\d\d\d\d/],["HHmm",/\d\d\d\d/],["HH",/\d\d/]],pt=/^\/?Date\((\-?\d+)/i;function vt(e){var t,n,s,i,r,a,o=e._i,u=ft.exec(o)||mt.exec(o);if(u){for(g(e).iso=!0,t=0,n=yt.length;tn.valueOf():n.valueOf()this.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()},ln.isLocal=function(){return!!this.isValid()&&!this._isUTC},ln.isUtcOffset=function(){return!!this.isValid()&&this._isUTC},ln.isUtc=Vt,ln.isUTC=Vt,ln.zoneAbbr=function(){return this._isUTC?"UTC":""},ln.zoneName=function(){return this._isUTC?"Coordinated Universal Time":""},ln.dates=n("dates accessor is deprecated. Use date instead.",nn),ln.months=n("months accessor is deprecated. Use month instead",Fe),ln.years=n("years accessor is deprecated. Use year instead",Oe),ln.zone=n("moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/",function(e,t){return null!=e?("string"!=typeof e&&(e=-e),this.utcOffset(e,t),this):-this.utcOffset()}),ln.isDSTShifted=n("isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information",function(){if(!l(this._isDSTShifted))return this._isDSTShifted;var e={};if(w(e,this),(e=Yt(e))._a){var t=e._isUTC?y(e._a):Tt(e._a);this._isDSTShifted=this.isValid()&&0totalX){active=false;if(eventHandlers['cancel']){eventHandlers['cancel'](event);} -return;}else{event.preventDefault();if(eventHandlers['move']){eventHandlers['move'](coords,event);}}});element.on(getEvents(pointerTypes,'end'),function(event){if(!active)return;active=false;if(eventHandlers['end']){eventHandlers['end'](getCoordinates(event),event);}});}};}]);function makeSwipeDirective(directiveName,direction,eventName){ngTouch.directive(directiveName,['$parse','$swipe',function($parse,$swipe){var MAX_VERTICAL_DISTANCE=75;var MAX_VERTICAL_RATIO=0.3;var MIN_HORIZONTAL_DISTANCE=30;return function(scope,element,attr){var swipeHandler=$parse(attr[directiveName]);var startCoords,valid;function validSwipe(coords){if(!startCoords)return false;var deltaY=Math.abs(coords.y-startCoords.y);var deltaX=(coords.x-startCoords.x)*direction;return valid&&deltaY0&&deltaX>MIN_HORIZONTAL_DISTANCE&&deltaY/deltaX1)){a.preventDefault();var c=a.originalEvent.changedTouches[0],d=document.createEvent("MouseEvents");d.initMouseEvent(b,!0,!0,window,1,c.screenX,c.screenY,c.clientX,c.clientY,!1,!1,!1,!1,0,null),a.target.dispatchEvent(d)}}if(a.support.touch="ontouchend"in document,a.support.touch){var e,b=a.ui.mouse.prototype,c=b._mouseInit,d=b._mouseDestroy;b._touchStart=function(a){var b=this;!e&&b._mouseCapture(a.originalEvent.changedTouches[0])&&(e=!0,b._touchMoved=!1,f(a,"mouseover"),f(a,"mousemove"),f(a,"mousedown"))},b._touchMove=function(a){e&&(this._touchMoved=!0,f(a,"mousemove"))},b._touchEnd=function(a){e&&(f(a,"mouseup"),f(a,"mouseout"),this._touchMoved||f(a,"click"),e=!1)},b._mouseInit=function(){var b=this;b.element.bind({touchstart:a.proxy(b,"_touchStart"),touchmove:a.proxy(b,"_touchMove"),touchend:a.proxy(b,"_touchEnd")}),c.call(b)},b._mouseDestroy=function(){var b=this;b.element.unbind({touchstart:a.proxy(b,"_touchStart"),touchmove:a.proxy(b,"_touchMove"),touchend:a.proxy(b,"_touchEnd")}),d.call(b)}}}(jQuery); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/ddf7f64a.js b/src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/ddf7f64a.js deleted file mode 100644 index 8651405932..0000000000 --- a/src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/ddf7f64a.js +++ /dev/null @@ -1,8 +0,0 @@ -(function(window,angular){'use strict';angular.module('ngCookies',['ng']).info({angularVersion:'1.7.5'}).provider('$cookies',[function $CookiesProvider(){var defaults=this.defaults={};function calcOptions(options){return options?angular.extend({},defaults,options):defaults;} -this.$get=['$$cookieReader','$$cookieWriter',function($$cookieReader,$$cookieWriter){return{get:function(key){return $$cookieReader()[key];},getObject:function(key){var value=this.get(key);return value?angular.fromJson(value):value;},getAll:function(){return $$cookieReader();},put:function(key,value,options){$$cookieWriter(key,value,calcOptions(options));},putObject:function(key,value,options){this.put(key,angular.toJson(value),options);},remove:function(key,options){$$cookieWriter(key,undefined,calcOptions(options));}};}];}]);function $$CookieWriter($document,$log,$browser){var cookiePath=$browser.baseHref();var rawDocument=$document[0];function buildCookieString(name,value,options){var path,expires;options=options||{};expires=options.expires;path=angular.isDefined(options.path)?options.path:cookiePath;if(angular.isUndefined(value)){expires='Thu, 01 Jan 1970 00:00:00 GMT';value='';} -if(angular.isString(expires)){expires=new Date(expires);} -var str=encodeURIComponent(name)+'='+encodeURIComponent(value);str+=path?';path='+path:'';str+=options.domain?';domain='+options.domain:'';str+=expires?';expires='+expires.toUTCString():'';str+=options.secure?';secure':'';str+=options.samesite?';samesite='+options.samesite:'';var cookieLength=str.length+1;if(cookieLength>4096){$log.warn('Cookie \''+name+'\' possibly not set or overflowed because it was too large ('+ -cookieLength+' > 4096 bytes)!');} -return str;} -return function(name,value,options){rawDocument.cookie=buildCookieString(name,value,options);};} -$$CookieWriter.$inject=['$document','$log','$browser'];angular.module('ngCookies').provider('$$cookieWriter',function $$CookieWriterProvider(){this.$get=$$CookieWriter;});})(window,window.angular);; \ No newline at end of file diff --git a/src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/de682689.js b/src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/de682689.js deleted file mode 100644 index 7c16b0d128..0000000000 --- a/src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/de682689.js +++ /dev/null @@ -1,7 +0,0 @@ -/*! - * Chart.js v2.9.3 - * https://www.chartjs.org - * (c) 2019 Chart.js Contributors - * Released under the MIT License - */ -!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e(function(){try{return require("moment")}catch(t){}}()):"function"==typeof define&&define.amd?define(["require"],(function(t){return e(function(){try{return t("moment")}catch(t){}}())})):(t=t||self).Chart=e(t.moment)}(this,(function(t){"use strict";t=t&&t.hasOwnProperty("default")?t.default:t;var e={aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],grey:[128,128,128],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],rebeccapurple:[102,51,153],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]},n=function(t,e){return t(e={exports:{}},e.exports),e.exports}((function(t){var n={};for(var i in e)e.hasOwnProperty(i)&&(n[e[i]]=i);var a=t.exports={rgb:{channels:3,labels:"rgb"},hsl:{channels:3,labels:"hsl"},hsv:{channels:3,labels:"hsv"},hwb:{channels:3,labels:"hwb"},cmyk:{channels:4,labels:"cmyk"},xyz:{channels:3,labels:"xyz"},lab:{channels:3,labels:"lab"},lch:{channels:3,labels:"lch"},hex:{channels:1,labels:["hex"]},keyword:{channels:1,labels:["keyword"]},ansi16:{channels:1,labels:["ansi16"]},ansi256:{channels:1,labels:["ansi256"]},hcg:{channels:3,labels:["h","c","g"]},apple:{channels:3,labels:["r16","g16","b16"]},gray:{channels:1,labels:["gray"]}};for(var r in a)if(a.hasOwnProperty(r)){if(!("channels"in a[r]))throw new Error("missing channels property: "+r);if(!("labels"in a[r]))throw new Error("missing channel labels property: "+r);if(a[r].labels.length!==a[r].channels)throw new Error("channel and label counts mismatch: "+r);var o=a[r].channels,s=a[r].labels;delete a[r].channels,delete a[r].labels,Object.defineProperty(a[r],"channels",{value:o}),Object.defineProperty(a[r],"labels",{value:s})}a.rgb.hsl=function(t){var e,n,i=t[0]/255,a=t[1]/255,r=t[2]/255,o=Math.min(i,a,r),s=Math.max(i,a,r),l=s-o;return s===o?e=0:i===s?e=(a-r)/l:a===s?e=2+(r-i)/l:r===s&&(e=4+(i-a)/l),(e=Math.min(60*e,360))<0&&(e+=360),n=(o+s)/2,[e,100*(s===o?0:n<=.5?l/(s+o):l/(2-s-o)),100*n]},a.rgb.hsv=function(t){var e,n,i,a,r,o=t[0]/255,s=t[1]/255,l=t[2]/255,u=Math.max(o,s,l),d=u-Math.min(o,s,l),h=function(t){return(u-t)/6/d+.5};return 0===d?a=r=0:(r=d/u,e=h(o),n=h(s),i=h(l),o===u?a=i-n:s===u?a=1/3+e-i:l===u&&(a=2/3+n-e),a<0?a+=1:a>1&&(a-=1)),[360*a,100*r,100*u]},a.rgb.hwb=function(t){var e=t[0],n=t[1],i=t[2];return[a.rgb.hsl(t)[0],100*(1/255*Math.min(e,Math.min(n,i))),100*(i=1-1/255*Math.max(e,Math.max(n,i)))]},a.rgb.cmyk=function(t){var e,n=t[0]/255,i=t[1]/255,a=t[2]/255;return[100*((1-n-(e=Math.min(1-n,1-i,1-a)))/(1-e)||0),100*((1-i-e)/(1-e)||0),100*((1-a-e)/(1-e)||0),100*e]},a.rgb.keyword=function(t){var i=n[t];if(i)return i;var a,r,o,s=1/0;for(var l in e)if(e.hasOwnProperty(l)){var u=e[l],d=(r=t,o=u,Math.pow(r[0]-o[0],2)+Math.pow(r[1]-o[1],2)+Math.pow(r[2]-o[2],2));d.04045?Math.pow((e+.055)/1.055,2.4):e/12.92)+.3576*(n=n>.04045?Math.pow((n+.055)/1.055,2.4):n/12.92)+.1805*(i=i>.04045?Math.pow((i+.055)/1.055,2.4):i/12.92)),100*(.2126*e+.7152*n+.0722*i),100*(.0193*e+.1192*n+.9505*i)]},a.rgb.lab=function(t){var e=a.rgb.xyz(t),n=e[0],i=e[1],r=e[2];return i/=100,r/=108.883,n=(n/=95.047)>.008856?Math.pow(n,1/3):7.787*n+16/116,[116*(i=i>.008856?Math.pow(i,1/3):7.787*i+16/116)-16,500*(n-i),200*(i-(r=r>.008856?Math.pow(r,1/3):7.787*r+16/116))]},a.hsl.rgb=function(t){var e,n,i,a,r,o=t[0]/360,s=t[1]/100,l=t[2]/100;if(0===s)return[r=255*l,r,r];e=2*l-(n=l<.5?l*(1+s):l+s-l*s),a=[0,0,0];for(var u=0;u<3;u++)(i=o+1/3*-(u-1))<0&&i++,i>1&&i--,r=6*i<1?e+6*(n-e)*i:2*i<1?n:3*i<2?e+(n-e)*(2/3-i)*6:e,a[u]=255*r;return a},a.hsl.hsv=function(t){var e=t[0],n=t[1]/100,i=t[2]/100,a=n,r=Math.max(i,.01);return n*=(i*=2)<=1?i:2-i,a*=r<=1?r:2-r,[e,100*(0===i?2*a/(r+a):2*n/(i+n)),100*((i+n)/2)]},a.hsv.rgb=function(t){var e=t[0]/60,n=t[1]/100,i=t[2]/100,a=Math.floor(e)%6,r=e-Math.floor(e),o=255*i*(1-n),s=255*i*(1-n*r),l=255*i*(1-n*(1-r));switch(i*=255,a){case 0:return[i,l,o];case 1:return[s,i,o];case 2:return[o,i,l];case 3:return[o,s,i];case 4:return[l,o,i];case 5:return[i,o,s]}},a.hsv.hsl=function(t){var e,n,i,a=t[0],r=t[1]/100,o=t[2]/100,s=Math.max(o,.01);return i=(2-r)*o,n=r*s,[a,100*(n=(n/=(e=(2-r)*s)<=1?e:2-e)||0),100*(i/=2)]},a.hwb.rgb=function(t){var e,n,i,a,r,o,s,l=t[0]/360,u=t[1]/100,d=t[2]/100,h=u+d;switch(h>1&&(u/=h,d/=h),i=6*l-(e=Math.floor(6*l)),0!=(1&e)&&(i=1-i),a=u+i*((n=1-d)-u),e){default:case 6:case 0:r=n,o=a,s=u;break;case 1:r=a,o=n,s=u;break;case 2:r=u,o=n,s=a;break;case 3:r=u,o=a,s=n;break;case 4:r=a,o=u,s=n;break;case 5:r=n,o=u,s=a}return[255*r,255*o,255*s]},a.cmyk.rgb=function(t){var e=t[0]/100,n=t[1]/100,i=t[2]/100,a=t[3]/100;return[255*(1-Math.min(1,e*(1-a)+a)),255*(1-Math.min(1,n*(1-a)+a)),255*(1-Math.min(1,i*(1-a)+a))]},a.xyz.rgb=function(t){var e,n,i,a=t[0]/100,r=t[1]/100,o=t[2]/100;return n=-.9689*a+1.8758*r+.0415*o,i=.0557*a+-.204*r+1.057*o,e=(e=3.2406*a+-1.5372*r+-.4986*o)>.0031308?1.055*Math.pow(e,1/2.4)-.055:12.92*e,n=n>.0031308?1.055*Math.pow(n,1/2.4)-.055:12.92*n,i=i>.0031308?1.055*Math.pow(i,1/2.4)-.055:12.92*i,[255*(e=Math.min(Math.max(0,e),1)),255*(n=Math.min(Math.max(0,n),1)),255*(i=Math.min(Math.max(0,i),1))]},a.xyz.lab=function(t){var e=t[0],n=t[1],i=t[2];return n/=100,i/=108.883,e=(e/=95.047)>.008856?Math.pow(e,1/3):7.787*e+16/116,[116*(n=n>.008856?Math.pow(n,1/3):7.787*n+16/116)-16,500*(e-n),200*(n-(i=i>.008856?Math.pow(i,1/3):7.787*i+16/116))]},a.lab.xyz=function(t){var e,n,i,a=t[0];e=t[1]/500+(n=(a+16)/116),i=n-t[2]/200;var r=Math.pow(n,3),o=Math.pow(e,3),s=Math.pow(i,3);return n=r>.008856?r:(n-16/116)/7.787,e=o>.008856?o:(e-16/116)/7.787,i=s>.008856?s:(i-16/116)/7.787,[e*=95.047,n*=100,i*=108.883]},a.lab.lch=function(t){var e,n=t[0],i=t[1],a=t[2];return(e=360*Math.atan2(a,i)/2/Math.PI)<0&&(e+=360),[n,Math.sqrt(i*i+a*a),e]},a.lch.lab=function(t){var e,n=t[0],i=t[1];return e=t[2]/360*2*Math.PI,[n,i*Math.cos(e),i*Math.sin(e)]},a.rgb.ansi16=function(t){var e=t[0],n=t[1],i=t[2],r=1 in arguments?arguments[1]:a.rgb.hsv(t)[2];if(0===(r=Math.round(r/50)))return 30;var o=30+(Math.round(i/255)<<2|Math.round(n/255)<<1|Math.round(e/255));return 2===r&&(o+=60),o},a.hsv.ansi16=function(t){return a.rgb.ansi16(a.hsv.rgb(t),t[2])},a.rgb.ansi256=function(t){var e=t[0],n=t[1],i=t[2];return e===n&&n===i?e<8?16:e>248?231:Math.round((e-8)/247*24)+232:16+36*Math.round(e/255*5)+6*Math.round(n/255*5)+Math.round(i/255*5)},a.ansi16.rgb=function(t){var e=t%10;if(0===e||7===e)return t>50&&(e+=3.5),[e=e/10.5*255,e,e];var n=.5*(1+~~(t>50));return[(1&e)*n*255,(e>>1&1)*n*255,(e>>2&1)*n*255]},a.ansi256.rgb=function(t){if(t>=232){var e=10*(t-232)+8;return[e,e,e]}var n;return t-=16,[Math.floor(t/36)/5*255,Math.floor((n=t%36)/6)/5*255,n%6/5*255]},a.rgb.hex=function(t){var e=(((255&Math.round(t[0]))<<16)+((255&Math.round(t[1]))<<8)+(255&Math.round(t[2]))).toString(16).toUpperCase();return"000000".substring(e.length)+e},a.hex.rgb=function(t){var e=t.toString(16).match(/[a-f0-9]{6}|[a-f0-9]{3}/i);if(!e)return[0,0,0];var n=e[0];3===e[0].length&&(n=n.split("").map((function(t){return t+t})).join(""));var i=parseInt(n,16);return[i>>16&255,i>>8&255,255&i]},a.rgb.hcg=function(t){var e,n=t[0]/255,i=t[1]/255,a=t[2]/255,r=Math.max(Math.max(n,i),a),o=Math.min(Math.min(n,i),a),s=r-o;return e=s<=0?0:r===n?(i-a)/s%6:r===i?2+(a-n)/s:4+(n-i)/s+4,e/=6,[360*(e%=1),100*s,100*(s<1?o/(1-s):0)]},a.hsl.hcg=function(t){var e=t[1]/100,n=t[2]/100,i=1,a=0;return(i=n<.5?2*e*n:2*e*(1-n))<1&&(a=(n-.5*i)/(1-i)),[t[0],100*i,100*a]},a.hsv.hcg=function(t){var e=t[1]/100,n=t[2]/100,i=e*n,a=0;return i<1&&(a=(n-i)/(1-i)),[t[0],100*i,100*a]},a.hcg.rgb=function(t){var e=t[0]/360,n=t[1]/100,i=t[2]/100;if(0===n)return[255*i,255*i,255*i];var a,r=[0,0,0],o=e%1*6,s=o%1,l=1-s;switch(Math.floor(o)){case 0:r[0]=1,r[1]=s,r[2]=0;break;case 1:r[0]=l,r[1]=1,r[2]=0;break;case 2:r[0]=0,r[1]=1,r[2]=s;break;case 3:r[0]=0,r[1]=l,r[2]=1;break;case 4:r[0]=s,r[1]=0,r[2]=1;break;default:r[0]=1,r[1]=0,r[2]=l}return a=(1-n)*i,[255*(n*r[0]+a),255*(n*r[1]+a),255*(n*r[2]+a)]},a.hcg.hsv=function(t){var e=t[1]/100,n=e+t[2]/100*(1-e),i=0;return n>0&&(i=e/n),[t[0],100*i,100*n]},a.hcg.hsl=function(t){var e=t[1]/100,n=t[2]/100*(1-e)+.5*e,i=0;return n>0&&n<.5?i=e/(2*n):n>=.5&&n<1&&(i=e/(2*(1-n))),[t[0],100*i,100*n]},a.hcg.hwb=function(t){var e=t[1]/100,n=e+t[2]/100*(1-e);return[t[0],100*(n-e),100*(1-n)]},a.hwb.hcg=function(t){var e=t[1]/100,n=1-t[2]/100,i=n-e,a=0;return i<1&&(a=(n-i)/(1-i)),[t[0],100*i,100*a]},a.apple.rgb=function(t){return[t[0]/65535*255,t[1]/65535*255,t[2]/65535*255]},a.rgb.apple=function(t){return[t[0]/255*65535,t[1]/255*65535,t[2]/255*65535]},a.gray.rgb=function(t){return[t[0]/100*255,t[0]/100*255,t[0]/100*255]},a.gray.hsl=a.gray.hsv=function(t){return[0,0,t[0]]},a.gray.hwb=function(t){return[0,100,t[0]]},a.gray.cmyk=function(t){return[0,0,0,t[0]]},a.gray.lab=function(t){return[t[0],0,0]},a.gray.hex=function(t){var e=255&Math.round(t[0]/100*255),n=((e<<16)+(e<<8)+e).toString(16).toUpperCase();return"000000".substring(n.length)+n},a.rgb.gray=function(t){return[(t[0]+t[1]+t[2])/3/255*100]}}));n.rgb,n.hsl,n.hsv,n.hwb,n.cmyk,n.xyz,n.lab,n.lch,n.hex,n.keyword,n.ansi16,n.ansi256,n.hcg,n.apple,n.gray;function i(t){var e=function(){for(var t={},e=Object.keys(n),i=e.length,a=0;a1&&(e=Array.prototype.slice.call(arguments));var n=t(e);if("object"==typeof n)for(var i=n.length,a=0;a1&&(e=Array.prototype.slice.call(arguments)),t(e))};return"conversion"in t&&(e.conversion=t.conversion),e}(i)}))}));var s=o,l={aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],grey:[128,128,128],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],rebeccapurple:[102,51,153],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]},u={getRgba:d,getHsla:h,getRgb:function(t){var e=d(t);return e&&e.slice(0,3)},getHsl:function(t){var e=h(t);return e&&e.slice(0,3)},getHwb:c,getAlpha:function(t){var e=d(t);if(e)return e[3];if(e=h(t))return e[3];if(e=c(t))return e[3]},hexString:function(t,e){e=void 0!==e&&3===t.length?e:t[3];return"#"+v(t[0])+v(t[1])+v(t[2])+(e>=0&&e<1?v(Math.round(255*e)):"")},rgbString:function(t,e){if(e<1||t[3]&&t[3]<1)return f(t,e);return"rgb("+t[0]+", "+t[1]+", "+t[2]+")"},rgbaString:f,percentString:function(t,e){if(e<1||t[3]&&t[3]<1)return g(t,e);var n=Math.round(t[0]/255*100),i=Math.round(t[1]/255*100),a=Math.round(t[2]/255*100);return"rgb("+n+"%, "+i+"%, "+a+"%)"},percentaString:g,hslString:function(t,e){if(e<1||t[3]&&t[3]<1)return p(t,e);return"hsl("+t[0]+", "+t[1]+"%, "+t[2]+"%)"},hslaString:p,hwbString:function(t,e){void 0===e&&(e=void 0!==t[3]?t[3]:1);return"hwb("+t[0]+", "+t[1]+"%, "+t[2]+"%"+(void 0!==e&&1!==e?", "+e:"")+")"},keyword:function(t){return b[t.slice(0,3)]}};function d(t){if(t){var e=[0,0,0],n=1,i=t.match(/^#([a-fA-F0-9]{3,4})$/i),a="";if(i){a=(i=i[1])[3];for(var r=0;rn?(e+.05)/(n+.05):(n+.05)/(e+.05)},level:function(t){var e=this.contrast(t);return e>=7.1?"AAA":e>=4.5?"AA":""},dark:function(){var t=this.values.rgb;return(299*t[0]+587*t[1]+114*t[2])/1e3<128},light:function(){return!this.dark()},negate:function(){for(var t=[],e=0;e<3;e++)t[e]=255-this.values.rgb[e];return this.setValues("rgb",t),this},lighten:function(t){var e=this.values.hsl;return e[2]+=e[2]*t,this.setValues("hsl",e),this},darken:function(t){var e=this.values.hsl;return e[2]-=e[2]*t,this.setValues("hsl",e),this},saturate:function(t){var e=this.values.hsl;return e[1]+=e[1]*t,this.setValues("hsl",e),this},desaturate:function(t){var e=this.values.hsl;return e[1]-=e[1]*t,this.setValues("hsl",e),this},whiten:function(t){var e=this.values.hwb;return e[1]+=e[1]*t,this.setValues("hwb",e),this},blacken:function(t){var e=this.values.hwb;return e[2]+=e[2]*t,this.setValues("hwb",e),this},greyscale:function(){var t=this.values.rgb,e=.3*t[0]+.59*t[1]+.11*t[2];return this.setValues("rgb",[e,e,e]),this},clearer:function(t){var e=this.values.alpha;return this.setValues("alpha",e-e*t),this},opaquer:function(t){var e=this.values.alpha;return this.setValues("alpha",e+e*t),this},rotate:function(t){var e=this.values.hsl,n=(e[0]+t)%360;return e[0]=n<0?360+n:n,this.setValues("hsl",e),this},mix:function(t,e){var n=t,i=void 0===e?.5:e,a=2*i-1,r=this.alpha()-n.alpha(),o=((a*r==-1?a:(a+r)/(1+a*r))+1)/2,s=1-o;return this.rgb(o*this.red()+s*n.red(),o*this.green()+s*n.green(),o*this.blue()+s*n.blue()).alpha(this.alpha()*i+n.alpha()*(1-i))},toJSON:function(){return this.rgb()},clone:function(){var t,e,n=new y,i=this.values,a=n.values;for(var r in i)i.hasOwnProperty(r)&&(t=i[r],"[object Array]"===(e={}.toString.call(t))?a[r]=t.slice(0):"[object Number]"===e?a[r]=t:console.error("unexpected color value:",t));return n}},y.prototype.spaces={rgb:["red","green","blue"],hsl:["hue","saturation","lightness"],hsv:["hue","saturation","value"],hwb:["hue","whiteness","blackness"],cmyk:["cyan","magenta","yellow","black"]},y.prototype.maxes={rgb:[255,255,255],hsl:[360,100,100],hsv:[360,100,100],hwb:[360,100,100],cmyk:[100,100,100,100]},y.prototype.getValues=function(t){for(var e=this.values,n={},i=0;i=0;a--)e.call(n,t[a],a);else for(a=0;a=1?t:-(Math.sqrt(1-t*t)-1)},easeOutCirc:function(t){return Math.sqrt(1-(t-=1)*t)},easeInOutCirc:function(t){return(t/=.5)<1?-.5*(Math.sqrt(1-t*t)-1):.5*(Math.sqrt(1-(t-=2)*t)+1)},easeInElastic:function(t){var e=1.70158,n=0,i=1;return 0===t?0:1===t?1:(n||(n=.3),i<1?(i=1,e=n/4):e=n/(2*Math.PI)*Math.asin(1/i),-i*Math.pow(2,10*(t-=1))*Math.sin((t-e)*(2*Math.PI)/n))},easeOutElastic:function(t){var e=1.70158,n=0,i=1;return 0===t?0:1===t?1:(n||(n=.3),i<1?(i=1,e=n/4):e=n/(2*Math.PI)*Math.asin(1/i),i*Math.pow(2,-10*t)*Math.sin((t-e)*(2*Math.PI)/n)+1)},easeInOutElastic:function(t){var e=1.70158,n=0,i=1;return 0===t?0:2==(t/=.5)?1:(n||(n=.45),i<1?(i=1,e=n/4):e=n/(2*Math.PI)*Math.asin(1/i),t<1?i*Math.pow(2,10*(t-=1))*Math.sin((t-e)*(2*Math.PI)/n)*-.5:i*Math.pow(2,-10*(t-=1))*Math.sin((t-e)*(2*Math.PI)/n)*.5+1)},easeInBack:function(t){var e=1.70158;return t*t*((e+1)*t-e)},easeOutBack:function(t){var e=1.70158;return(t-=1)*t*((e+1)*t+e)+1},easeInOutBack:function(t){var e=1.70158;return(t/=.5)<1?t*t*((1+(e*=1.525))*t-e)*.5:.5*((t-=2)*t*((1+(e*=1.525))*t+e)+2)},easeInBounce:function(t){return 1-S.easeOutBounce(1-t)},easeOutBounce:function(t){return t<1/2.75?7.5625*t*t:t<2/2.75?7.5625*(t-=1.5/2.75)*t+.75:t<2.5/2.75?7.5625*(t-=2.25/2.75)*t+.9375:7.5625*(t-=2.625/2.75)*t+.984375},easeInOutBounce:function(t){return t<.5?.5*S.easeInBounce(2*t):.5*S.easeOutBounce(2*t-1)+.5}},C={effects:S};M.easingEffects=S;var P=Math.PI,A=P/180,D=2*P,T=P/2,I=P/4,F=2*P/3,L={clear:function(t){t.ctx.clearRect(0,0,t.width,t.height)},roundedRect:function(t,e,n,i,a,r){if(r){var o=Math.min(r,a/2,i/2),s=e+o,l=n+o,u=e+i-o,d=n+a-o;t.moveTo(e,l),se.left-1e-6&&t.xe.top-1e-6&&t.y0&&this.requestAnimationFrame()},advance:function(){for(var t,e,n,i,a=this.animations,r=0;r=n?(V.callback(t.onAnimationComplete,[t],e),e.animating=!1,a.splice(r,1)):++r}},J=V.options.resolve,Q=["push","pop","shift","splice","unshift"];function tt(t,e){var n=t._chartjs;if(n){var i=n.listeners,a=i.indexOf(e);-1!==a&&i.splice(a,1),i.length>0||(Q.forEach((function(e){delete t[e]})),delete t._chartjs)}}var et=function(t,e){this.initialize(t,e)};V.extend(et.prototype,{datasetElementType:null,dataElementType:null,_datasetElementOptions:["backgroundColor","borderCapStyle","borderColor","borderDash","borderDashOffset","borderJoinStyle","borderWidth"],_dataElementOptions:["backgroundColor","borderColor","borderWidth","pointStyle"],initialize:function(t,e){var n=this;n.chart=t,n.index=e,n.linkScales(),n.addElements(),n._type=n.getMeta().type},updateIndex:function(t){this.index=t},linkScales:function(){var t=this.getMeta(),e=this.chart,n=e.scales,i=this.getDataset(),a=e.options.scales;null!==t.xAxisID&&t.xAxisID in n&&!i.xAxisID||(t.xAxisID=i.xAxisID||a.xAxes[0].id),null!==t.yAxisID&&t.yAxisID in n&&!i.yAxisID||(t.yAxisID=i.yAxisID||a.yAxes[0].id)},getDataset:function(){return this.chart.data.datasets[this.index]},getMeta:function(){return this.chart.getDatasetMeta(this.index)},getScaleForId:function(t){return this.chart.scales[t]},_getValueScaleId:function(){return this.getMeta().yAxisID},_getIndexScaleId:function(){return this.getMeta().xAxisID},_getValueScale:function(){return this.getScaleForId(this._getValueScaleId())},_getIndexScale:function(){return this.getScaleForId(this._getIndexScaleId())},reset:function(){this._update(!0)},destroy:function(){this._data&&tt(this._data,this)},createMetaDataset:function(){var t=this.datasetElementType;return t&&new t({_chart:this.chart,_datasetIndex:this.index})},createMetaData:function(t){var e=this.dataElementType;return e&&new e({_chart:this.chart,_datasetIndex:this.index,_index:t})},addElements:function(){var t,e,n=this.getMeta(),i=this.getDataset().data||[],a=n.data;for(t=0,e=i.length;tn&&this.insertElements(n,i-n)},insertElements:function(t,e){for(var n=0;na?(r=a/e.innerRadius,t.arc(o,s,e.innerRadius-a,i+r,n-r,!0)):t.arc(o,s,a,i+Math.PI/2,n-Math.PI/2),t.closePath(),t.clip()}function rt(t,e,n){var i="inner"===e.borderAlign;i?(t.lineWidth=2*e.borderWidth,t.lineJoin="round"):(t.lineWidth=e.borderWidth,t.lineJoin="bevel"),n.fullCircles&&function(t,e,n,i){var a,r=n.endAngle;for(i&&(n.endAngle=n.startAngle+it,at(t,n),n.endAngle=r,n.endAngle===n.startAngle&&n.fullCircles&&(n.endAngle+=it,n.fullCircles--)),t.beginPath(),t.arc(n.x,n.y,n.innerRadius,n.startAngle+it,n.startAngle,!0),a=0;as;)a-=it;for(;a=o&&a<=s,u=r>=n.innerRadius&&r<=n.outerRadius;return l&&u}return!1},getCenterPoint:function(){var t=this._view,e=(t.startAngle+t.endAngle)/2,n=(t.innerRadius+t.outerRadius)/2;return{x:t.x+Math.cos(e)*n,y:t.y+Math.sin(e)*n}},getArea:function(){var t=this._view;return Math.PI*((t.endAngle-t.startAngle)/(2*Math.PI))*(Math.pow(t.outerRadius,2)-Math.pow(t.innerRadius,2))},tooltipPosition:function(){var t=this._view,e=t.startAngle+(t.endAngle-t.startAngle)/2,n=(t.outerRadius-t.innerRadius)/2+t.innerRadius;return{x:t.x+Math.cos(e)*n,y:t.y+Math.sin(e)*n}},draw:function(){var t,e=this._chart.ctx,n=this._view,i="inner"===n.borderAlign?.33:0,a={x:n.x,y:n.y,innerRadius:n.innerRadius,outerRadius:Math.max(n.outerRadius-i,0),pixelMargin:i,startAngle:n.startAngle,endAngle:n.endAngle,fullCircles:Math.floor(n.circumference/it)};if(e.save(),e.fillStyle=n.backgroundColor,e.strokeStyle=n.borderColor,a.fullCircles){for(a.endAngle=a.startAngle+it,e.beginPath(),e.arc(a.x,a.y,a.outerRadius,a.startAngle,a.endAngle),e.arc(a.x,a.y,a.innerRadius,a.endAngle,a.startAngle,!0),e.closePath(),t=0;tt.x&&(e=vt(e,"left","right")):t.basen?n:i,r:l.right||a<0?0:a>e?e:a,b:l.bottom||r<0?0:r>n?n:r,l:l.left||o<0?0:o>e?e:o}}function xt(t,e,n){var i=null===e,a=null===n,r=!(!t||i&&a)&&mt(t);return r&&(i||e>=r.left&&e<=r.right)&&(a||n>=r.top&&n<=r.bottom)}z._set("global",{elements:{rectangle:{backgroundColor:gt,borderColor:gt,borderSkipped:"bottom",borderWidth:0}}});var yt=X.extend({_type:"rectangle",draw:function(){var t=this._chart.ctx,e=this._view,n=function(t){var e=mt(t),n=e.right-e.left,i=e.bottom-e.top,a=bt(t,n/2,i/2);return{outer:{x:e.left,y:e.top,w:n,h:i},inner:{x:e.left+a.l,y:e.top+a.t,w:n-a.l-a.r,h:i-a.t-a.b}}}(e),i=n.outer,a=n.inner;t.fillStyle=e.backgroundColor,t.fillRect(i.x,i.y,i.w,i.h),i.w===a.w&&i.h===a.h||(t.save(),t.beginPath(),t.rect(i.x,i.y,i.w,i.h),t.clip(),t.fillStyle=e.borderColor,t.rect(a.x,a.y,a.w,a.h),t.fill("evenodd"),t.restore())},height:function(){var t=this._view;return t.base-t.y},inRange:function(t,e){return xt(this._view,t,e)},inLabelRange:function(t,e){var n=this._view;return pt(n)?xt(n,t,null):xt(n,null,e)},inXRange:function(t){return xt(this._view,t,null)},inYRange:function(t){return xt(this._view,null,t)},getCenterPoint:function(){var t,e,n=this._view;return pt(n)?(t=n.x,e=(n.y+n.base)/2):(t=(n.x+n.base)/2,e=n.y),{x:t,y:e}},getArea:function(){var t=this._view;return pt(t)?t.width*Math.abs(t.y-t.base):t.height*Math.abs(t.x-t.base)},tooltipPosition:function(){var t=this._view;return{x:t.x,y:t.y}}}),_t={},kt=ot,wt=ut,Mt=ft,St=yt;_t.Arc=kt,_t.Line=wt,_t.Point=Mt,_t.Rectangle=St;var Ct=V._deprecated,Pt=V.valueOrDefault;function At(t,e,n){var i,a,r=n.barThickness,o=e.stackCount,s=e.pixels[t],l=V.isNullOrUndef(r)?function(t,e){var n,i,a,r,o=t._length;for(a=1,r=e.length;a0?Math.min(o,Math.abs(i-n)):o,n=i;return o}(e.scale,e.pixels):-1;return V.isNullOrUndef(r)?(i=l*n.categoryPercentage,a=n.barPercentage):(i=r*o,a=1),{chunk:i/o,ratio:a,start:s-i/2}}z._set("bar",{hover:{mode:"label"},scales:{xAxes:[{type:"category",offset:!0,gridLines:{offsetGridLines:!0}}],yAxes:[{type:"linear"}]}}),z._set("global",{datasets:{bar:{categoryPercentage:.8,barPercentage:.9}}});var Dt=nt.extend({dataElementType:_t.Rectangle,_dataElementOptions:["backgroundColor","borderColor","borderSkipped","borderWidth","barPercentage","barThickness","categoryPercentage","maxBarThickness","minBarLength"],initialize:function(){var t,e,n=this;nt.prototype.initialize.apply(n,arguments),(t=n.getMeta()).stack=n.getDataset().stack,t.bar=!0,e=n._getIndexScale().options,Ct("bar chart",e.barPercentage,"scales.[x/y]Axes.barPercentage","dataset.barPercentage"),Ct("bar chart",e.barThickness,"scales.[x/y]Axes.barThickness","dataset.barThickness"),Ct("bar chart",e.categoryPercentage,"scales.[x/y]Axes.categoryPercentage","dataset.categoryPercentage"),Ct("bar chart",n._getValueScale().options.minBarLength,"scales.[x/y]Axes.minBarLength","dataset.minBarLength"),Ct("bar chart",e.maxBarThickness,"scales.[x/y]Axes.maxBarThickness","dataset.maxBarThickness")},update:function(t){var e,n,i=this.getMeta().data;for(this._ruler=this.getRuler(),e=0,n=i.length;e=0&&p.min>=0?p.min:p.max,y=void 0===p.start?p.end:p.max>=0&&p.min>=0?p.max-p.min:p.min-p.max,_=g.length;if(v||void 0===v&&void 0!==b)for(i=0;i<_&&(a=g[i]).index!==t;++i)a.stack===b&&(r=void 0===(u=h._parseValue(f[a.index].data[e])).start?u.end:u.min>=0&&u.max>=0?u.max:u.min,(p.min<0&&r<0||p.max>=0&&r>0)&&(x+=r));return o=h.getPixelForValue(x),l=(s=h.getPixelForValue(x+y))-o,void 0!==m&&Math.abs(l)=0&&!c||y<0&&c?o-m:o+m),{size:l,base:o,head:s,center:s+l/2}},calculateBarIndexPixels:function(t,e,n,i){var a="flex"===i.barThickness?function(t,e,n){var i,a=e.pixels,r=a[t],o=t>0?a[t-1]:null,s=t=Ot?-Rt:b<-Ot?Rt:0)+m,y=Math.cos(b),_=Math.sin(b),k=Math.cos(x),w=Math.sin(x),M=b<=0&&x>=0||x>=Rt,S=b<=zt&&x>=zt||x>=Rt+zt,C=b<=-zt&&x>=-zt||x>=Ot+zt,P=b===-Ot||x>=Ot?-1:Math.min(y,y*p,k,k*p),A=C?-1:Math.min(_,_*p,w,w*p),D=M?1:Math.max(y,y*p,k,k*p),T=S?1:Math.max(_,_*p,w,w*p);u=(D-P)/2,d=(T-A)/2,h=-(D+P)/2,c=-(T+A)/2}for(i=0,a=g.length;i0&&!isNaN(t)?Rt*(Math.abs(t)/e):0},getMaxBorderWidth:function(t){var e,n,i,a,r,o,s,l,u=0,d=this.chart;if(!t)for(e=0,n=d.data.datasets.length;e(u=s>u?s:u)?l:u);return u},setHoverStyle:function(t){var e=t._model,n=t._options,i=V.getHoverColor;t.$previousStyle={backgroundColor:e.backgroundColor,borderColor:e.borderColor,borderWidth:e.borderWidth},e.backgroundColor=Lt(n.hoverBackgroundColor,i(n.backgroundColor)),e.borderColor=Lt(n.hoverBorderColor,i(n.borderColor)),e.borderWidth=Lt(n.hoverBorderWidth,n.borderWidth)},_getRingWeightOffset:function(t){for(var e=0,n=0;n0&&Vt(l[t-1]._model,s)&&(n.controlPointPreviousX=u(n.controlPointPreviousX,s.left,s.right),n.controlPointPreviousY=u(n.controlPointPreviousY,s.top,s.bottom)),t0&&(r=t.getDatasetMeta(r[0]._datasetIndex).data),r},"x-axis":function(t,e){return ie(t,e,{intersect:!1})},point:function(t,e){return te(t,Jt(e,t))},nearest:function(t,e,n){var i=Jt(e,t);n.axis=n.axis||"xy";var a=ne(n.axis);return ee(t,i,n.intersect,a)},x:function(t,e,n){var i=Jt(e,t),a=[],r=!1;return Qt(t,(function(t){t.inXRange(i.x)&&a.push(t),t.inRange(i.x,i.y)&&(r=!0)})),n.intersect&&!r&&(a=[]),a},y:function(t,e,n){var i=Jt(e,t),a=[],r=!1;return Qt(t,(function(t){t.inYRange(i.y)&&a.push(t),t.inRange(i.x,i.y)&&(r=!0)})),n.intersect&&!r&&(a=[]),a}}},re=V.extend;function oe(t,e){return V.where(t,(function(t){return t.pos===e}))}function se(t,e){return t.sort((function(t,n){var i=e?n:t,a=e?t:n;return i.weight===a.weight?i.index-a.index:i.weight-a.weight}))}function le(t,e,n,i){return Math.max(t[n],e[n])+Math.max(t[i],e[i])}function ue(t,e,n){var i,a,r=n.box,o=t.maxPadding;if(n.size&&(t[n.pos]-=n.size),n.size=n.horizontal?r.height:r.width,t[n.pos]+=n.size,r.getPadding){var s=r.getPadding();o.top=Math.max(o.top,s.top),o.left=Math.max(o.left,s.left),o.bottom=Math.max(o.bottom,s.bottom),o.right=Math.max(o.right,s.right)}if(i=e.outerWidth-le(o,t,"left","right"),a=e.outerHeight-le(o,t,"top","bottom"),i!==t.w||a!==t.h)return t.w=i,t.h=a,n.horizontal?i!==t.w:a!==t.h}function de(t,e){var n=e.maxPadding;function i(t){var i={left:0,top:0,right:0,bottom:0};return t.forEach((function(t){i[t]=Math.max(e[t],n[t])})),i}return i(t?["left","right"]:["top","bottom"])}function he(t,e,n){var i,a,r,o,s,l,u=[];for(i=0,a=t.length;idiv{position:absolute;width:1000000px;height:1000000px;left:0;top:0}.chartjs-size-monitor-shrink>div{position:absolute;width:200%;height:200%;left:0;top:0}"}))&&fe.default||fe,me="$chartjs",ve="chartjs-size-monitor",be="chartjs-render-monitor",xe="chartjs-render-animation",ye=["animationstart","webkitAnimationStart"],_e={touchstart:"mousedown",touchmove:"mousemove",touchend:"mouseup",pointerenter:"mouseenter",pointerdown:"mousedown",pointermove:"mousemove",pointerup:"mouseup",pointerleave:"mouseout",pointerout:"mouseout"};function ke(t,e){var n=V.getStyle(t,e),i=n&&n.match(/^(\d+)(\.\d+)?px$/);return i?Number(i[1]):void 0}var we=!!function(){var t=!1;try{var e=Object.defineProperty({},"passive",{get:function(){t=!0}});window.addEventListener("e",null,e)}catch(t){}return t}()&&{passive:!0};function Me(t,e,n){t.addEventListener(e,n,we)}function Se(t,e,n){t.removeEventListener(e,n,we)}function Ce(t,e,n,i,a){return{type:t,chart:e,native:a||null,x:void 0!==n?n:null,y:void 0!==i?i:null}}function Pe(t){var e=document.createElement("div");return e.className=t||"",e}function Ae(t,e,n){var i,a,r,o,s=t[me]||(t[me]={}),l=s.resizer=function(t){var e=Pe(ve),n=Pe(ve+"-expand"),i=Pe(ve+"-shrink");n.appendChild(Pe()),i.appendChild(Pe()),e.appendChild(n),e.appendChild(i),e._reset=function(){n.scrollLeft=1e6,n.scrollTop=1e6,i.scrollLeft=1e6,i.scrollTop=1e6};var a=function(){e._reset(),t()};return Me(n,"scroll",a.bind(n,"expand")),Me(i,"scroll",a.bind(i,"shrink")),e}((i=function(){if(s.resizer){var i=n.options.maintainAspectRatio&&t.parentNode,a=i?i.clientWidth:0;e(Ce("resize",n)),i&&i.clientWidth0){var r=t[0];r.label?n=r.label:r.xLabel?n=r.xLabel:a>0&&r.index-1?t.split("\n"):t}function We(t){var e=z.global;return{xPadding:t.xPadding,yPadding:t.yPadding,xAlign:t.xAlign,yAlign:t.yAlign,rtl:t.rtl,textDirection:t.textDirection,bodyFontColor:t.bodyFontColor,_bodyFontFamily:Re(t.bodyFontFamily,e.defaultFontFamily),_bodyFontStyle:Re(t.bodyFontStyle,e.defaultFontStyle),_bodyAlign:t.bodyAlign,bodyFontSize:Re(t.bodyFontSize,e.defaultFontSize),bodySpacing:t.bodySpacing,titleFontColor:t.titleFontColor,_titleFontFamily:Re(t.titleFontFamily,e.defaultFontFamily),_titleFontStyle:Re(t.titleFontStyle,e.defaultFontStyle),titleFontSize:Re(t.titleFontSize,e.defaultFontSize),_titleAlign:t.titleAlign,titleSpacing:t.titleSpacing,titleMarginBottom:t.titleMarginBottom,footerFontColor:t.footerFontColor,_footerFontFamily:Re(t.footerFontFamily,e.defaultFontFamily),_footerFontStyle:Re(t.footerFontStyle,e.defaultFontStyle),footerFontSize:Re(t.footerFontSize,e.defaultFontSize),_footerAlign:t.footerAlign,footerSpacing:t.footerSpacing,footerMarginTop:t.footerMarginTop,caretSize:t.caretSize,cornerRadius:t.cornerRadius,backgroundColor:t.backgroundColor,opacity:0,legendColorBackground:t.multiKeyBackground,displayColors:t.displayColors,borderColor:t.borderColor,borderWidth:t.borderWidth}}function Ve(t,e){return"center"===e?t.x+t.width/2:"right"===e?t.x+t.width-t.xPadding:t.x+t.xPadding}function He(t){return Be([],Ee(t))}var je=X.extend({initialize:function(){this._model=We(this._options),this._lastActive=[]},getTitle:function(){var t=this,e=t._options,n=e.callbacks,i=n.beforeTitle.apply(t,arguments),a=n.title.apply(t,arguments),r=n.afterTitle.apply(t,arguments),o=[];return o=Be(o,Ee(i)),o=Be(o,Ee(a)),o=Be(o,Ee(r))},getBeforeBody:function(){return He(this._options.callbacks.beforeBody.apply(this,arguments))},getBody:function(t,e){var n=this,i=n._options.callbacks,a=[];return V.each(t,(function(t){var r={before:[],lines:[],after:[]};Be(r.before,Ee(i.beforeLabel.call(n,t,e))),Be(r.lines,i.label.call(n,t,e)),Be(r.after,Ee(i.afterLabel.call(n,t,e))),a.push(r)})),a},getAfterBody:function(){return He(this._options.callbacks.afterBody.apply(this,arguments))},getFooter:function(){var t=this,e=t._options.callbacks,n=e.beforeFooter.apply(t,arguments),i=e.footer.apply(t,arguments),a=e.afterFooter.apply(t,arguments),r=[];return r=Be(r,Ee(n)),r=Be(r,Ee(i)),r=Be(r,Ee(a))},update:function(t){var e,n,i,a,r,o,s,l,u,d,h=this,c=h._options,f=h._model,g=h._model=We(c),p=h._active,m=h._data,v={xAlign:f.xAlign,yAlign:f.yAlign},b={x:f.x,y:f.y},x={width:f.width,height:f.height},y={x:f.caretX,y:f.caretY};if(p.length){g.opacity=1;var _=[],k=[];y=Ne[c.position].call(h,p,h._eventPosition);var w=[];for(e=0,n=p.length;ei.width&&(a=i.width-e.width),a<0&&(a=0)),"top"===d?r+=h:r-="bottom"===d?e.height+h:e.height/2,"center"===d?"left"===u?a+=h:"right"===u&&(a-=h):"left"===u?a-=c:"right"===u&&(a+=c),{x:a,y:r}}(g,x,v=function(t,e){var n,i,a,r,o,s=t._model,l=t._chart,u=t._chart.chartArea,d="center",h="center";s.yl.height-e.height&&(h="bottom");var c=(u.left+u.right)/2,f=(u.top+u.bottom)/2;"center"===h?(n=function(t){return t<=c},i=function(t){return t>c}):(n=function(t){return t<=e.width/2},i=function(t){return t>=l.width-e.width/2}),a=function(t){return t+e.width+s.caretSize+s.caretPadding>l.width},r=function(t){return t-e.width-s.caretSize-s.caretPadding<0},o=function(t){return t<=f?"top":"bottom"},n(s.x)?(d="left",a(s.x)&&(d="center",h=o(s.y))):i(s.x)&&(d="right",r(s.x)&&(d="center",h=o(s.y)));var g=t._options;return{xAlign:g.xAlign?g.xAlign:d,yAlign:g.yAlign?g.yAlign:h}}(this,x),h._chart)}else g.opacity=0;return g.xAlign=v.xAlign,g.yAlign=v.yAlign,g.x=b.x,g.y=b.y,g.width=x.width,g.height=x.height,g.caretX=y.x,g.caretY=y.y,h._model=g,t&&c.custom&&c.custom.call(h,g),h},drawCaret:function(t,e){var n=this._chart.ctx,i=this._view,a=this.getCaretPosition(t,e,i);n.lineTo(a.x1,a.y1),n.lineTo(a.x2,a.y2),n.lineTo(a.x3,a.y3)},getCaretPosition:function(t,e,n){var i,a,r,o,s,l,u=n.caretSize,d=n.cornerRadius,h=n.xAlign,c=n.yAlign,f=t.x,g=t.y,p=e.width,m=e.height;if("center"===c)s=g+m/2,"left"===h?(a=(i=f)-u,r=i,o=s+u,l=s-u):(a=(i=f+p)+u,r=i,o=s-u,l=s+u);else if("left"===h?(i=(a=f+d+u)-u,r=a+u):"right"===h?(i=(a=f+p-d-u)-u,r=a+u):(i=(a=n.caretX)-u,r=a+u),"top"===c)s=(o=g)-u,l=o;else{s=(o=g+m)+u,l=o;var v=r;r=i,i=v}return{x1:i,x2:a,x3:r,y1:o,y2:s,y3:l}},drawTitle:function(t,e,n){var i,a,r,o=e.title,s=o.length;if(s){var l=ze(e.rtl,e.x,e.width);for(t.x=Ve(e,e._titleAlign),n.textAlign=l.textAlign(e._titleAlign),n.textBaseline="middle",i=e.titleFontSize,a=e.titleSpacing,n.fillStyle=e.titleFontColor,n.font=V.fontString(i,e._titleFontStyle,e._titleFontFamily),r=0;r0&&n.stroke()},draw:function(){var t=this._chart.ctx,e=this._view;if(0!==e.opacity){var n={width:e.width,height:e.height},i={x:e.x,y:e.y},a=Math.abs(e.opacity<.001)?0:e.opacity,r=e.title.length||e.beforeBody.length||e.body.length||e.afterBody.length||e.footer.length;this._options.enabled&&r&&(t.save(),t.globalAlpha=a,this.drawBackground(i,e,t,n),i.y+=e.yPadding,V.rtl.overrideTextDirection(t,e.textDirection),this.drawTitle(i,e,t),this.drawBody(i,e,t),this.drawFooter(i,e,t),V.rtl.restoreTextDirection(t,e.textDirection),t.restore())}},handleEvent:function(t){var e,n=this,i=n._options;return n._lastActive=n._lastActive||[],"mouseout"===t.type?n._active=[]:(n._active=n._chart.getElementsAtEventForMode(t,i.mode,i),i.reverse&&n._active.reverse()),(e=!V.arrayEquals(n._active,n._lastActive))&&(n._lastActive=n._active,(i.enabled||i.custom)&&(n._eventPosition={x:t.x,y:t.y},n.update(!0),n.pivot())),e}}),qe=Ne,Ue=je;Ue.positioners=qe;var Ye=V.valueOrDefault;function Ge(){return V.merge({},[].slice.call(arguments),{merger:function(t,e,n,i){if("xAxes"===t||"yAxes"===t){var a,r,o,s=n[t].length;for(e[t]||(e[t]=[]),a=0;a=e[t].length&&e[t].push({}),!e[t][a].type||o.type&&o.type!==e[t][a].type?V.merge(e[t][a],[Oe.getScaleDefaults(r),o]):V.merge(e[t][a],o)}else V._merger(t,e,n,i)}})}function Xe(){return V.merge({},[].slice.call(arguments),{merger:function(t,e,n,i){var a=e[t]||{},r=n[t];"scales"===t?e[t]=Ge(a,r):"scale"===t?e[t]=V.merge(a,[Oe.getScaleDefaults(r.type),r]):V._merger(t,e,n,i)}})}function Ke(t){var e=t.options;V.each(t.scales,(function(e){ge.removeBox(t,e)})),e=Xe(z.global,z[t.config.type],e),t.options=t.config.options=e,t.ensureScalesHaveIDs(),t.buildOrUpdateScales(),t.tooltip._options=e.tooltips,t.tooltip.initialize()}function Ze(t,e,n){var i,a=function(t){return t.id===i};do{i=e+n++}while(V.findIndex(t,a)>=0);return i}function $e(t){return"top"===t||"bottom"===t}function Je(t,e){return function(n,i){return n[t]===i[t]?n[e]-i[e]:n[t]-i[t]}}z._set("global",{elements:{},events:["mousemove","mouseout","click","touchstart","touchmove"],hover:{onHover:null,mode:"nearest",intersect:!0,animationDuration:400},onClick:null,maintainAspectRatio:!0,responsive:!0,responsiveAnimationDuration:0});var Qe=function(t,e){return this.construct(t,e),this};V.extend(Qe.prototype,{construct:function(t,e){var n=this;e=function(t){var e=(t=t||{}).data=t.data||{};return e.datasets=e.datasets||[],e.labels=e.labels||[],t.options=Xe(z.global,z[t.type],t.options||{}),t}(e);var i=Fe.acquireContext(t,e),a=i&&i.canvas,r=a&&a.height,o=a&&a.width;n.id=V.uid(),n.ctx=i,n.canvas=a,n.config=e,n.width=o,n.height=r,n.aspectRatio=r?o/r:null,n.options=e.options,n._bufferedRender=!1,n._layers=[],n.chart=n,n.controller=n,Qe.instances[n.id]=n,Object.defineProperty(n,"data",{get:function(){return n.config.data},set:function(t){n.config.data=t}}),i&&a?(n.initialize(),n.update()):console.error("Failed to create chart: can't acquire context from the given item")},initialize:function(){var t=this;return Le.notify(t,"beforeInit"),V.retinaScale(t,t.options.devicePixelRatio),t.bindEvents(),t.options.responsive&&t.resize(!0),t.initToolTip(),Le.notify(t,"afterInit"),t},clear:function(){return V.canvas.clear(this),this},stop:function(){return $.cancelAnimation(this),this},resize:function(t){var e=this,n=e.options,i=e.canvas,a=n.maintainAspectRatio&&e.aspectRatio||null,r=Math.max(0,Math.floor(V.getMaximumWidth(i))),o=Math.max(0,Math.floor(a?r/a:V.getMaximumHeight(i)));if((e.width!==r||e.height!==o)&&(i.width=e.width=r,i.height=e.height=o,i.style.width=r+"px",i.style.height=o+"px",V.retinaScale(e,n.devicePixelRatio),!t)){var s={width:r,height:o};Le.notify(e,"resize",[s]),n.onResize&&n.onResize(e,s),e.stop(),e.update({duration:n.responsiveAnimationDuration})}},ensureScalesHaveIDs:function(){var t=this.options,e=t.scales||{},n=t.scale;V.each(e.xAxes,(function(t,n){t.id||(t.id=Ze(e.xAxes,"x-axis-",n))})),V.each(e.yAxes,(function(t,n){t.id||(t.id=Ze(e.yAxes,"y-axis-",n))})),n&&(n.id=n.id||"scale")},buildOrUpdateScales:function(){var t=this,e=t.options,n=t.scales||{},i=[],a=Object.keys(n).reduce((function(t,e){return t[e]=!1,t}),{});e.scales&&(i=i.concat((e.scales.xAxes||[]).map((function(t){return{options:t,dtype:"category",dposition:"bottom"}})),(e.scales.yAxes||[]).map((function(t){return{options:t,dtype:"linear",dposition:"left"}})))),e.scale&&i.push({options:e.scale,dtype:"radialLinear",isDefault:!0,dposition:"chartArea"}),V.each(i,(function(e){var i=e.options,r=i.id,o=Ye(i.type,e.dtype);$e(i.position)!==$e(e.dposition)&&(i.position=e.dposition),a[r]=!0;var s=null;if(r in n&&n[r].type===o)(s=n[r]).options=i,s.ctx=t.ctx,s.chart=t;else{var l=Oe.getScaleConstructor(o);if(!l)return;s=new l({id:r,type:o,options:i,ctx:t.ctx,chart:t}),n[s.id]=s}s.mergeTicksOptions(),e.isDefault&&(t.scale=s)})),V.each(a,(function(t,e){t||delete n[e]})),t.scales=n,Oe.addScalesToLayout(this)},buildOrUpdateControllers:function(){var t,e,n=this,i=[],a=n.data.datasets;for(t=0,e=a.length;t=0;--n)this.drawDataset(e[n],t);Le.notify(this,"afterDatasetsDraw",[t])}},drawDataset:function(t,e){var n={meta:t,index:t.index,easingValue:e};!1!==Le.notify(this,"beforeDatasetDraw",[n])&&(t.controller.draw(e),Le.notify(this,"afterDatasetDraw",[n]))},_drawTooltip:function(t){var e=this.tooltip,n={tooltip:e,easingValue:t};!1!==Le.notify(this,"beforeTooltipDraw",[n])&&(e.draw(),Le.notify(this,"afterTooltipDraw",[n]))},getElementAtEvent:function(t){return ae.modes.single(this,t)},getElementsAtEvent:function(t){return ae.modes.label(this,t,{intersect:!0})},getElementsAtXAxis:function(t){return ae.modes["x-axis"](this,t,{intersect:!0})},getElementsAtEventForMode:function(t,e,n){var i=ae.modes[e];return"function"==typeof i?i(this,t,n):[]},getDatasetAtEvent:function(t){return ae.modes.dataset(this,t,{intersect:!0})},getDatasetMeta:function(t){var e=this.data.datasets[t];e._meta||(e._meta={});var n=e._meta[this.id];return n||(n=e._meta[this.id]={type:null,data:[],dataset:null,controller:null,hidden:null,xAxisID:null,yAxisID:null,order:e.order||0,index:t}),n},getVisibleDatasetCount:function(){for(var t=0,e=0,n=this.data.datasets.length;e3?n[2]-n[1]:n[1]-n[0];Math.abs(i)>1&&t!==Math.floor(t)&&(i=t-Math.floor(t));var a=V.log10(Math.abs(i)),r="";if(0!==t)if(Math.max(Math.abs(n[0]),Math.abs(n[n.length-1]))<1e-4){var o=V.log10(Math.abs(t)),s=Math.floor(o)-Math.floor(a);s=Math.max(Math.min(s,20),0),r=t.toExponential(s)}else{var l=-1*Math.floor(a);l=Math.max(Math.min(l,20),0),r=t.toFixed(l)}else r="0";return r},logarithmic:function(t,e,n){var i=t/Math.pow(10,Math.floor(V.log10(t)));return 0===t?"0":1===i||2===i||5===i||0===e||e===n.length-1?t.toExponential():""}}},on=V.isArray,sn=V.isNullOrUndef,ln=V.valueOrDefault,un=V.valueAtIndexOrDefault;function dn(t,e,n){var i,a=t.getTicks().length,r=Math.min(e,a-1),o=t.getPixelForTick(r),s=t._startPixel,l=t._endPixel;if(!(n&&(i=1===a?Math.max(o-s,l-o):0===e?(t.getPixelForTick(1)-o)/2:(o-t.getPixelForTick(r-1))/2,(o+=rl+1e-6)))return o}function hn(t,e,n,i){var a,r,o,s,l,u,d,h,c,f,g,p,m,v=n.length,b=[],x=[],y=[];for(a=0;ae){for(n=0;n=c||d<=1||!s.isHorizontal()?s.labelRotation=h:(e=(t=s._getLabelSizes()).widest.width,n=t.highest.height-t.highest.offset,i=Math.min(s.maxWidth,s.chart.width-e),e+6>(a=l.offset?s.maxWidth/d:i/(d-1))&&(a=i/(d-(l.offset?.5:1)),r=s.maxHeight-cn(l.gridLines)-u.padding-fn(l.scaleLabel),o=Math.sqrt(e*e+n*n),f=V.toDegrees(Math.min(Math.asin(Math.min((t.highest.height+6)/a,1)),Math.asin(Math.min(r/o,1))-Math.asin(n/o))),f=Math.max(h,Math.min(c,f))),s.labelRotation=f)},afterCalculateTickRotation:function(){V.callback(this.options.afterCalculateTickRotation,[this])},beforeFit:function(){V.callback(this.options.beforeFit,[this])},fit:function(){var t=this,e=t.minSize={width:0,height:0},n=t.chart,i=t.options,a=i.ticks,r=i.scaleLabel,o=i.gridLines,s=t._isVisible(),l="bottom"===i.position,u=t.isHorizontal();if(u?e.width=t.maxWidth:s&&(e.width=cn(o)+fn(r)),u?s&&(e.height=cn(o)+fn(r)):e.height=t.maxHeight,a.display&&s){var d=pn(a),h=t._getLabelSizes(),c=h.first,f=h.last,g=h.widest,p=h.highest,m=.4*d.minor.lineHeight,v=a.padding;if(u){var b=0!==t.labelRotation,x=V.toRadians(t.labelRotation),y=Math.cos(x),_=Math.sin(x),k=_*g.width+y*(p.height-(b?p.offset:0))+(b?0:m);e.height=Math.min(t.maxHeight,e.height+k+v);var w,M,S=t.getPixelForTick(0)-t.left,C=t.right-t.getPixelForTick(t.getTicks().length-1);b?(w=l?y*c.width+_*c.offset:_*(c.height-c.offset),M=l?_*(f.height-f.offset):y*f.width+_*f.offset):(w=c.width/2,M=f.width/2),t.paddingLeft=Math.max((w-S)*t.width/(t.width-S),0)+3,t.paddingRight=Math.max((M-C)*t.width/(t.width-C),0)+3}else{var P=a.mirror?0:g.width+v+m;e.width=Math.min(t.maxWidth,e.width+P),t.paddingTop=c.height/2,t.paddingBottom=f.height/2}}t.handleMargins(),u?(t.width=t._length=n.width-t.margins.left-t.margins.right,t.height=e.height):(t.width=e.width,t.height=t._length=n.height-t.margins.top-t.margins.bottom)},handleMargins:function(){var t=this;t.margins&&(t.margins.left=Math.max(t.paddingLeft,t.margins.left),t.margins.top=Math.max(t.paddingTop,t.margins.top),t.margins.right=Math.max(t.paddingRight,t.margins.right),t.margins.bottom=Math.max(t.paddingBottom,t.margins.bottom))},afterFit:function(){V.callback(this.options.afterFit,[this])},isHorizontal:function(){var t=this.options.position;return"top"===t||"bottom"===t},isFullWidth:function(){return this.options.fullWidth},getRightValue:function(t){if(sn(t))return NaN;if(("number"==typeof t||t instanceof Number)&&!isFinite(t))return NaN;if(t)if(this.isHorizontal()){if(void 0!==t.x)return this.getRightValue(t.x)}else if(void 0!==t.y)return this.getRightValue(t.y);return t},_convertTicksToLabels:function(t){var e,n,i,a=this;for(a.ticks=t.map((function(t){return t.value})),a.beforeTickToLabelConversion(),e=a.convertTicksToLabels(t)||a.ticks,a.afterTickToLabelConversion(),n=0,i=t.length;nn-1?null:this.getPixelForDecimal(t*i+(e?i/2:0))},getPixelForDecimal:function(t){return this._reversePixels&&(t=1-t),this._startPixel+t*this._length},getDecimalForPixel:function(t){var e=(t-this._startPixel)/this._length;return this._reversePixels?1-e:e},getBasePixel:function(){return this.getPixelForValue(this.getBaseValue())},getBaseValue:function(){var t=this.min,e=this.max;return this.beginAtZero?0:t<0&&e<0?e:t>0&&e>0?t:0},_autoSkip:function(t){var e,n,i,a,r=this.options.ticks,o=this._length,s=r.maxTicksLimit||o/this._tickSize()+1,l=r.major.enabled?function(t){var e,n,i=[];for(e=0,n=t.length;es)return function(t,e,n){var i,a,r=0,o=e[0];for(n=Math.ceil(n),i=0;iu)return r;return Math.max(u,1)}(l,t,0,s),u>0){for(e=0,n=u-1;e1?(h-d)/(u-1):null,vn(t,i,V.isNullOrUndef(a)?0:d-a,d),vn(t,i,h,V.isNullOrUndef(a)?t.length:h+a),mn(t)}return vn(t,i),mn(t)},_tickSize:function(){var t=this.options.ticks,e=V.toRadians(this.labelRotation),n=Math.abs(Math.cos(e)),i=Math.abs(Math.sin(e)),a=this._getLabelSizes(),r=t.autoSkipPadding||0,o=a?a.widest.width+r:0,s=a?a.highest.height+r:0;return this.isHorizontal()?s*n>o*i?o/n:s/i:s*i=0&&(o=t),void 0!==r&&(t=n.indexOf(r))>=0&&(s=t),e.minIndex=o,e.maxIndex=s,e.min=n[o],e.max=n[s]},buildTicks:function(){var t=this._getLabels(),e=this.minIndex,n=this.maxIndex;this.ticks=0===e&&n===t.length-1?t:t.slice(e,n+1)},getLabelForIndex:function(t,e){var n=this.chart;return n.getDatasetMeta(e).controller._getValueScaleId()===this.id?this.getRightValue(n.data.datasets[e].data[t]):this._getLabels()[t]},_configure:function(){var t=this,e=t.options.offset,n=t.ticks;xn.prototype._configure.call(t),t.isHorizontal()||(t._reversePixels=!t._reversePixels),n&&(t._startValue=t.minIndex-(e?.5:0),t._valueRange=Math.max(n.length-(e?0:1),1))},getPixelForValue:function(t,e,n){var i,a,r,o=this;return yn(e)||yn(n)||(t=o.chart.data.datasets[n].data[e]),yn(t)||(i=o.isHorizontal()?t.x:t.y),(void 0!==i||void 0!==t&&isNaN(e))&&(a=o._getLabels(),t=V.valueOrDefault(i,t),e=-1!==(r=a.indexOf(t))?r:e,isNaN(e)&&(e=t)),o.getPixelForDecimal((e-o._startValue)/o._valueRange)},getPixelForTick:function(t){var e=this.ticks;return t<0||t>e.length-1?null:this.getPixelForValue(e[t],t+this.minIndex)},getValueForPixel:function(t){var e=Math.round(this._startValue+this.getDecimalForPixel(t)*this._valueRange);return Math.min(Math.max(e,0),this.ticks.length-1)},getBasePixel:function(){return this.bottom}}),kn={position:"bottom"};_n._defaults=kn;var wn=V.noop,Mn=V.isNullOrUndef;var Sn=xn.extend({getRightValue:function(t){return"string"==typeof t?+t:xn.prototype.getRightValue.call(this,t)},handleTickRangeOptions:function(){var t=this,e=t.options.ticks;if(e.beginAtZero){var n=V.sign(t.min),i=V.sign(t.max);n<0&&i<0?t.max=0:n>0&&i>0&&(t.min=0)}var a=void 0!==e.min||void 0!==e.suggestedMin,r=void 0!==e.max||void 0!==e.suggestedMax;void 0!==e.min?t.min=e.min:void 0!==e.suggestedMin&&(null===t.min?t.min=e.suggestedMin:t.min=Math.min(t.min,e.suggestedMin)),void 0!==e.max?t.max=e.max:void 0!==e.suggestedMax&&(null===t.max?t.max=e.suggestedMax:t.max=Math.max(t.max,e.suggestedMax)),a!==r&&t.min>=t.max&&(a?t.max=t.min+1:t.min=t.max-1),t.min===t.max&&(t.max++,e.beginAtZero||t.min--)},getTickLimit:function(){var t,e=this.options.ticks,n=e.stepSize,i=e.maxTicksLimit;return n?t=Math.ceil(this.max/n)-Math.floor(this.min/n)+1:(t=this._computeTickLimit(),i=i||11),i&&(t=Math.min(i,t)),t},_computeTickLimit:function(){return Number.POSITIVE_INFINITY},handleDirectionalChanges:wn,buildTicks:function(){var t=this,e=t.options.ticks,n=t.getTickLimit(),i={maxTicks:n=Math.max(2,n),min:e.min,max:e.max,precision:e.precision,stepSize:V.valueOrDefault(e.fixedStepSize,e.stepSize)},a=t.ticks=function(t,e){var n,i,a,r,o=[],s=t.stepSize,l=s||1,u=t.maxTicks-1,d=t.min,h=t.max,c=t.precision,f=e.min,g=e.max,p=V.niceNum((g-f)/u/l)*l;if(p<1e-14&&Mn(d)&&Mn(h))return[f,g];(r=Math.ceil(g/p)-Math.floor(f/p))>u&&(p=V.niceNum(r*p/u/l)*l),s||Mn(c)?n=Math.pow(10,V._decimalPlaces(p)):(n=Math.pow(10,c),p=Math.ceil(p*n)/n),i=Math.floor(f/p)*p,a=Math.ceil(g/p)*p,s&&(!Mn(d)&&V.almostWhole(d/p,p/1e3)&&(i=d),!Mn(h)&&V.almostWhole(h/p,p/1e3)&&(a=h)),r=(a-i)/p,r=V.almostEquals(r,Math.round(r),p/1e3)?Math.round(r):Math.ceil(r),i=Math.round(i*n)/n,a=Math.round(a*n)/n,o.push(Mn(d)?i:d);for(var m=1;me.length-1?null:this.getPixelForValue(e[t])}}),Tn=Cn;Dn._defaults=Tn;var In=V.valueOrDefault,Fn=V.math.log10;var Ln={position:"left",ticks:{callback:rn.formatters.logarithmic}};function On(t,e){return V.isFinite(t)&&t>=0?t:e}var Rn=xn.extend({determineDataLimits:function(){var t,e,n,i,a,r,o=this,s=o.options,l=o.chart,u=l.data.datasets,d=o.isHorizontal();function h(t){return d?t.xAxisID===o.id:t.yAxisID===o.id}o.min=Number.POSITIVE_INFINITY,o.max=Number.NEGATIVE_INFINITY,o.minNotZero=Number.POSITIVE_INFINITY;var c=s.stacked;if(void 0===c)for(t=0;t0){var e=V.min(t),n=V.max(t);o.min=Math.min(o.min,e),o.max=Math.max(o.max,n)}}))}else for(t=0;t0?t.minNotZero=t.min:t.max<1?t.minNotZero=Math.pow(10,Math.floor(Fn(t.max))):t.minNotZero=1)},buildTicks:function(){var t=this,e=t.options.ticks,n=!t.isHorizontal(),i={min:On(e.min),max:On(e.max)},a=t.ticks=function(t,e){var n,i,a=[],r=In(t.min,Math.pow(10,Math.floor(Fn(e.min)))),o=Math.floor(Fn(e.max)),s=Math.ceil(e.max/Math.pow(10,o));0===r?(n=Math.floor(Fn(e.minNotZero)),i=Math.floor(e.minNotZero/Math.pow(10,n)),a.push(r),r=i*Math.pow(10,n)):(n=Math.floor(Fn(r)),i=Math.floor(r/Math.pow(10,n)));var l=n<0?Math.pow(10,Math.abs(n)):1;do{a.push(r),10===++i&&(i=1,l=++n>=0?1:l),r=Math.round(i*Math.pow(10,n)*l)/l}while(ne.length-1?null:this.getPixelForValue(e[t])},_getFirstTickValue:function(t){var e=Math.floor(Fn(t));return Math.floor(t/Math.pow(10,e))*Math.pow(10,e)},_configure:function(){var t=this,e=t.min,n=0;xn.prototype._configure.call(t),0===e&&(e=t._getFirstTickValue(t.minNotZero),n=In(t.options.ticks.fontSize,z.global.defaultFontSize)/t._length),t._startValue=Fn(e),t._valueOffset=n,t._valueRange=(Fn(t.max)-Fn(e))/(1-n)},getPixelForValue:function(t){var e=this,n=0;return(t=+e.getRightValue(t))>e.min&&t>0&&(n=(Fn(t)-e._startValue)/e._valueRange+e._valueOffset),e.getPixelForDecimal(n)},getValueForPixel:function(t){var e=this,n=e.getDecimalForPixel(t);return 0===n&&0===e.min?0:Math.pow(10,e._startValue+(n-e._valueOffset)*e._valueRange)}}),zn=Ln;Rn._defaults=zn;var Nn=V.valueOrDefault,Bn=V.valueAtIndexOrDefault,En=V.options.resolve,Wn={display:!0,animate:!0,position:"chartArea",angleLines:{display:!0,color:"rgba(0,0,0,0.1)",lineWidth:1,borderDash:[],borderDashOffset:0},gridLines:{circular:!1},ticks:{showLabelBackdrop:!0,backdropColor:"rgba(255,255,255,0.75)",backdropPaddingY:2,backdropPaddingX:2,callback:rn.formatters.linear},pointLabels:{display:!0,fontSize:10,callback:function(t){return t}}};function Vn(t){var e=t.ticks;return e.display&&t.display?Nn(e.fontSize,z.global.defaultFontSize)+2*e.backdropPaddingY:0}function Hn(t,e,n,i,a){return t===i||t===a?{start:e-n/2,end:e+n/2}:ta?{start:e-n,end:e}:{start:e,end:e+n}}function jn(t){return 0===t||180===t?"center":t<180?"left":"right"}function qn(t,e,n,i){var a,r,o=n.y+i/2;if(V.isArray(e))for(a=0,r=e.length;a270||t<90)&&(n.y-=e.h)}function Yn(t){return V.isNumber(t)?t:0}var Gn=Sn.extend({setDimensions:function(){var t=this;t.width=t.maxWidth,t.height=t.maxHeight,t.paddingTop=Vn(t.options)/2,t.xCenter=Math.floor(t.width/2),t.yCenter=Math.floor((t.height-t.paddingTop)/2),t.drawingArea=Math.min(t.height-t.paddingTop,t.width)/2},determineDataLimits:function(){var t=this,e=t.chart,n=Number.POSITIVE_INFINITY,i=Number.NEGATIVE_INFINITY;V.each(e.data.datasets,(function(a,r){if(e.isDatasetVisible(r)){var o=e.getDatasetMeta(r);V.each(a.data,(function(e,a){var r=+t.getRightValue(e);isNaN(r)||o.data[a].hidden||(n=Math.min(r,n),i=Math.max(r,i))}))}})),t.min=n===Number.POSITIVE_INFINITY?0:n,t.max=i===Number.NEGATIVE_INFINITY?0:i,t.handleTickRangeOptions()},_computeTickLimit:function(){return Math.ceil(this.drawingArea/Vn(this.options))},convertTicksToLabels:function(){var t=this;Sn.prototype.convertTicksToLabels.call(t),t.pointLabels=t.chart.data.labels.map((function(){var e=V.callback(t.options.pointLabels.callback,arguments,t);return e||0===e?e:""}))},getLabelForIndex:function(t,e){return+this.getRightValue(this.chart.data.datasets[e].data[t])},fit:function(){var t=this.options;t.display&&t.pointLabels.display?function(t){var e,n,i,a=V.options._parseFont(t.options.pointLabels),r={l:0,r:t.width,t:0,b:t.height-t.paddingTop},o={};t.ctx.font=a.string,t._pointLabelSizes=[];var s,l,u,d=t.chart.data.labels.length;for(e=0;er.r&&(r.r=f.end,o.r=h),g.startr.b&&(r.b=g.end,o.b=h)}t.setReductions(t.drawingArea,r,o)}(this):this.setCenterPoint(0,0,0,0)},setReductions:function(t,e,n){var i=this,a=e.l/Math.sin(n.l),r=Math.max(e.r-i.width,0)/Math.sin(n.r),o=-e.t/Math.cos(n.t),s=-Math.max(e.b-(i.height-i.paddingTop),0)/Math.cos(n.b);a=Yn(a),r=Yn(r),o=Yn(o),s=Yn(s),i.drawingArea=Math.min(Math.floor(t-(a+r)/2),Math.floor(t-(o+s)/2)),i.setCenterPoint(a,r,o,s)},setCenterPoint:function(t,e,n,i){var a=this,r=a.width-e-a.drawingArea,o=t+a.drawingArea,s=n+a.drawingArea,l=a.height-a.paddingTop-i-a.drawingArea;a.xCenter=Math.floor((o+r)/2+a.left),a.yCenter=Math.floor((s+l)/2+a.top+a.paddingTop)},getIndexAngle:function(t){var e=this.chart,n=(t*(360/e.data.labels.length)+((e.options||{}).startAngle||0))%360;return(n<0?n+360:n)*Math.PI*2/360},getDistanceFromCenterForValue:function(t){var e=this;if(V.isNullOrUndef(t))return NaN;var n=e.drawingArea/(e.max-e.min);return e.options.ticks.reverse?(e.max-t)*n:(t-e.min)*n},getPointPosition:function(t,e){var n=this.getIndexAngle(t)-Math.PI/2;return{x:Math.cos(n)*e+this.xCenter,y:Math.sin(n)*e+this.yCenter}},getPointPositionForValue:function(t,e){return this.getPointPosition(t,this.getDistanceFromCenterForValue(e))},getBasePosition:function(t){var e=this.min,n=this.max;return this.getPointPositionForValue(t||0,this.beginAtZero?0:e<0&&n<0?n:e>0&&n>0?e:0)},_drawGrid:function(){var t,e,n,i=this,a=i.ctx,r=i.options,o=r.gridLines,s=r.angleLines,l=Nn(s.lineWidth,o.lineWidth),u=Nn(s.color,o.color);if(r.pointLabels.display&&function(t){var e=t.ctx,n=t.options,i=n.pointLabels,a=Vn(n),r=t.getDistanceFromCenterForValue(n.ticks.reverse?t.min:t.max),o=V.options._parseFont(i);e.save(),e.font=o.string,e.textBaseline="middle";for(var s=t.chart.data.labels.length-1;s>=0;s--){var l=0===s?a/2:0,u=t.getPointPosition(s,r+l+5),d=Bn(i.fontColor,s,z.global.defaultFontColor);e.fillStyle=d;var h=t.getIndexAngle(s),c=V.toDegrees(h);e.textAlign=jn(c),Un(c,t._pointLabelSizes[s],u),qn(e,t.pointLabels[s],u,o.lineHeight)}e.restore()}(i),o.display&&V.each(i.ticks,(function(t,n){0!==n&&(e=i.getDistanceFromCenterForValue(i.ticksAsNumbers[n]),function(t,e,n,i){var a,r=t.ctx,o=e.circular,s=t.chart.data.labels.length,l=Bn(e.color,i-1),u=Bn(e.lineWidth,i-1);if((o||s)&&l&&u){if(r.save(),r.strokeStyle=l,r.lineWidth=u,r.setLineDash&&(r.setLineDash(e.borderDash||[]),r.lineDashOffset=e.borderDashOffset||0),r.beginPath(),o)r.arc(t.xCenter,t.yCenter,n,0,2*Math.PI);else{a=t.getPointPosition(0,n),r.moveTo(a.x,a.y);for(var d=1;d=0;t--)e=i.getDistanceFromCenterForValue(r.ticks.reverse?i.min:i.max),n=i.getPointPosition(t,e),a.beginPath(),a.moveTo(i.xCenter,i.yCenter),a.lineTo(n.x,n.y),a.stroke();a.restore()}},_drawLabels:function(){var t=this,e=t.ctx,n=t.options.ticks;if(n.display){var i,a,r=t.getIndexAngle(0),o=V.options._parseFont(n),s=Nn(n.fontColor,z.global.defaultFontColor);e.save(),e.font=o.string,e.translate(t.xCenter,t.yCenter),e.rotate(r),e.textAlign="center",e.textBaseline="middle",V.each(t.ticks,(function(r,l){(0!==l||n.reverse)&&(i=t.getDistanceFromCenterForValue(t.ticksAsNumbers[l]),n.showLabelBackdrop&&(a=e.measureText(r).width,e.fillStyle=n.backdropColor,e.fillRect(-a/2-n.backdropPaddingX,-i-o.size/2-n.backdropPaddingY,a+2*n.backdropPaddingX,o.size+2*n.backdropPaddingY)),e.fillStyle=s,e.fillText(r,0,-i))})),e.restore()}},_drawTitle:V.noop}),Xn=Wn;Gn._defaults=Xn;var Kn=V._deprecated,Zn=V.options.resolve,$n=V.valueOrDefault,Jn=Number.MIN_SAFE_INTEGER||-9007199254740991,Qn=Number.MAX_SAFE_INTEGER||9007199254740991,ti={millisecond:{common:!0,size:1,steps:1e3},second:{common:!0,size:1e3,steps:60},minute:{common:!0,size:6e4,steps:60},hour:{common:!0,size:36e5,steps:24},day:{common:!0,size:864e5,steps:30},week:{common:!1,size:6048e5,steps:4},month:{common:!0,size:2628e6,steps:12},quarter:{common:!1,size:7884e6,steps:4},year:{common:!0,size:3154e7}},ei=Object.keys(ti);function ni(t,e){return t-e}function ii(t){return V.valueOrDefault(t.time.min,t.ticks.min)}function ai(t){return V.valueOrDefault(t.time.max,t.ticks.max)}function ri(t,e,n,i){var a=function(t,e,n){for(var i,a,r,o=0,s=t.length-1;o>=0&&o<=s;){if(a=t[(i=o+s>>1)-1]||null,r=t[i],!a)return{lo:null,hi:r};if(r[e]n))return{lo:a,hi:r};s=i-1}}return{lo:r,hi:null}}(t,e,n),r=a.lo?a.hi?a.lo:t[t.length-2]:t[0],o=a.lo?a.hi?a.hi:t[t.length-1]:t[1],s=o[e]-r[e],l=s?(n-r[e])/s:0,u=(o[i]-r[i])*l;return r[i]+u}function oi(t,e){var n=t._adapter,i=t.options.time,a=i.parser,r=a||i.format,o=e;return"function"==typeof a&&(o=a(o)),V.isFinite(o)||(o="string"==typeof r?n.parse(o,r):n.parse(o)),null!==o?+o:(a||"function"!=typeof r||(o=r(e),V.isFinite(o)||(o=n.parse(o))),o)}function si(t,e){if(V.isNullOrUndef(e))return null;var n=t.options.time,i=oi(t,t.getRightValue(e));return null===i?i:(n.round&&(i=+t._adapter.startOf(i,n.round)),i)}function li(t,e,n,i){var a,r,o,s=ei.length;for(a=ei.indexOf(t);a=0&&(e[r].major=!0);return e}(t,r,o,n):r}var di=xn.extend({initialize:function(){this.mergeTicksOptions(),xn.prototype.initialize.call(this)},update:function(){var t=this,e=t.options,n=e.time||(e.time={}),i=t._adapter=new an._date(e.adapters.date);return Kn("time scale",n.format,"time.format","time.parser"),Kn("time scale",n.min,"time.min","ticks.min"),Kn("time scale",n.max,"time.max","ticks.max"),V.mergeIf(n.displayFormats,i.formats()),xn.prototype.update.apply(t,arguments)},getRightValue:function(t){return t&&void 0!==t.t&&(t=t.t),xn.prototype.getRightValue.call(this,t)},determineDataLimits:function(){var t,e,n,i,a,r,o,s=this,l=s.chart,u=s._adapter,d=s.options,h=d.time.unit||"day",c=Qn,f=Jn,g=[],p=[],m=[],v=s._getLabels();for(t=0,n=v.length;t1?function(t){var e,n,i,a={},r=[];for(e=0,n=t.length;e1e5*u)throw e+" and "+n+" are too far apart with stepSize of "+u+" "+l;for(a=h;a=a&&n<=r&&d.push(n);return i.min=a,i.max=r,i._unit=l.unit||(s.autoSkip?li(l.minUnit,i.min,i.max,h):function(t,e,n,i,a){var r,o;for(r=ei.length-1;r>=ei.indexOf(n);r--)if(o=ei[r],ti[o].common&&t._adapter.diff(a,i,o)>=e-1)return o;return ei[n?ei.indexOf(n):0]}(i,d.length,l.minUnit,i.min,i.max)),i._majorUnit=s.major.enabled&&"year"!==i._unit?function(t){for(var e=ei.indexOf(t)+1,n=ei.length;ee&&s=0&&t0?s:1}}),hi={position:"bottom",distribution:"linear",bounds:"data",adapters:{},time:{parser:!1,unit:!1,round:!1,displayFormat:!1,isoWeekday:!1,minUnit:"millisecond",displayFormats:{}},ticks:{autoSkip:!1,source:"auto",major:{enabled:!1}}};di._defaults=hi;var ci={category:_n,linear:Dn,logarithmic:Rn,radialLinear:Gn,time:di},fi={datetime:"MMM D, YYYY, h:mm:ss a",millisecond:"h:mm:ss.SSS a",second:"h:mm:ss a",minute:"h:mm a",hour:"hA",day:"MMM D",week:"ll",month:"MMM YYYY",quarter:"[Q]Q - YYYY",year:"YYYY"};an._date.override("function"==typeof t?{_id:"moment",formats:function(){return fi},parse:function(e,n){return"string"==typeof e&&"string"==typeof n?e=t(e,n):e instanceof t||(e=t(e)),e.isValid()?e.valueOf():null},format:function(e,n){return t(e).format(n)},add:function(e,n,i){return t(e).add(n,i).valueOf()},diff:function(e,n,i){return t(e).diff(t(n),i)},startOf:function(e,n,i){return e=t(e),"isoWeek"===n?e.isoWeekday(i).valueOf():e.startOf(n).valueOf()},endOf:function(e,n){return t(e).endOf(n).valueOf()},_create:function(e){return t(e)}}:{}),z._set("global",{plugins:{filler:{propagate:!0}}});var gi={dataset:function(t){var e=t.fill,n=t.chart,i=n.getDatasetMeta(e),a=i&&n.isDatasetVisible(e)&&i.dataset._children||[],r=a.length||0;return r?function(t,e){return e=n)&&i;switch(r){case"bottom":return"start";case"top":return"end";case"zero":return"origin";case"origin":case"start":case"end":return r;default:return!1}}function mi(t){return(t.el._scale||{}).getPointPositionForValue?function(t){var e,n,i,a,r,o=t.el._scale,s=o.options,l=o.chart.data.labels.length,u=t.fill,d=[];if(!l)return null;for(e=s.ticks.reverse?o.max:o.min,n=s.ticks.reverse?o.min:o.max,i=o.getPointPositionForValue(0,e),a=0;a0;--r)V.canvas.lineTo(t,n[r],n[r-1],!0);else for(o=n[0].cx,s=n[0].cy,l=Math.sqrt(Math.pow(n[0].x-o,2)+Math.pow(n[0].y-s,2)),r=a-1;r>0;--r)t.arc(o,s,l,n[r].angle,n[r-1].angle,!0)}}function _i(t,e,n,i,a,r){var o,s,l,u,d,h,c,f,g=e.length,p=i.spanGaps,m=[],v=[],b=0,x=0;for(t.beginPath(),o=0,s=g;o=0;--n)(e=l[n].$filler)&&e.visible&&(a=(i=e.el)._view,r=i._children||[],o=e.mapper,s=a.backgroundColor||z.global.defaultColor,o&&s&&r.length&&(V.canvas.clipArea(u,t.chartArea),_i(u,r,o,a,s,i._loop),V.canvas.unclipArea(u)))}},wi=V.rtl.getRtlAdapter,Mi=V.noop,Si=V.valueOrDefault;function Ci(t,e){return t.usePointStyle&&t.boxWidth>e?e:t.boxWidth}z._set("global",{legend:{display:!0,position:"top",align:"center",fullWidth:!0,reverse:!1,weight:1e3,onClick:function(t,e){var n=e.datasetIndex,i=this.chart,a=i.getDatasetMeta(n);a.hidden=null===a.hidden?!i.data.datasets[n].hidden:null,i.update()},onHover:null,onLeave:null,labels:{boxWidth:40,padding:10,generateLabels:function(t){var e=t.data.datasets,n=t.options.legend||{},i=n.labels&&n.labels.usePointStyle;return t._getSortedDatasetMetas().map((function(n){var a=n.controller.getStyle(i?0:void 0);return{text:e[n.index].label,fillStyle:a.backgroundColor,hidden:!t.isDatasetVisible(n.index),lineCap:a.borderCapStyle,lineDash:a.borderDash,lineDashOffset:a.borderDashOffset,lineJoin:a.borderJoinStyle,lineWidth:a.borderWidth,strokeStyle:a.borderColor,pointStyle:a.pointStyle,rotation:a.rotation,datasetIndex:n.index}}),this)}}},legendCallback:function(t){var e,n,i,a=document.createElement("ul"),r=t.data.datasets;for(a.setAttribute("class",t.id+"-legend"),e=0,n=r.length;el.width)&&(h+=o+n.padding,d[d.length-(e>0?0:1)]=0),s[e]={left:0,top:0,width:i,height:o},d[d.length-1]+=i+n.padding})),l.height+=h}else{var c=n.padding,f=t.columnWidths=[],g=t.columnHeights=[],p=n.padding,m=0,v=0;V.each(t.legendItems,(function(t,e){var i=Ci(n,o)+o/2+a.measureText(t.text).width;e>0&&v+o+2*c>l.height&&(p+=m+n.padding,f.push(m),g.push(v),m=0,v=0),m=Math.max(m,i),v+=o+c,s[e]={left:0,top:0,width:i,height:o}})),p+=m,f.push(m),g.push(v),l.width+=p}t.width=l.width,t.height=l.height}else t.width=l.width=t.height=l.height=0},afterFit:Mi,isHorizontal:function(){return"top"===this.options.position||"bottom"===this.options.position},draw:function(){var t=this,e=t.options,n=e.labels,i=z.global,a=i.defaultColor,r=i.elements.line,o=t.height,s=t.columnHeights,l=t.width,u=t.lineWidths;if(e.display){var d,h=wi(e.rtl,t.left,t.minSize.width),c=t.ctx,f=Si(n.fontColor,i.defaultFontColor),g=V.options._parseFont(n),p=g.size;c.textAlign=h.textAlign("left"),c.textBaseline="middle",c.lineWidth=.5,c.strokeStyle=f,c.fillStyle=f,c.font=g.string;var m=Ci(n,p),v=t.legendHitBoxes,b=function(t,i){switch(e.align){case"start":return n.padding;case"end":return t-i;default:return(t-i+n.padding)/2}},x=t.isHorizontal();d=x?{x:t.left+b(l,u[0]),y:t.top+n.padding,line:0}:{x:t.left+n.padding,y:t.top+b(o,s[0]),line:0},V.rtl.overrideTextDirection(t.ctx,e.textDirection);var y=p+n.padding;V.each(t.legendItems,(function(e,i){var f=c.measureText(e.text).width,g=m+p/2+f,_=d.x,k=d.y;h.setWidth(t.minSize.width),x?i>0&&_+g+n.padding>t.left+t.minSize.width&&(k=d.y+=y,d.line++,_=d.x=t.left+b(l,u[d.line])):i>0&&k+y>t.top+t.minSize.height&&(_=d.x=_+t.columnWidths[d.line]+n.padding,d.line++,k=d.y=t.top+b(o,s[d.line]));var w=h.x(_);!function(t,e,i){if(!(isNaN(m)||m<=0)){c.save();var o=Si(i.lineWidth,r.borderWidth);if(c.fillStyle=Si(i.fillStyle,a),c.lineCap=Si(i.lineCap,r.borderCapStyle),c.lineDashOffset=Si(i.lineDashOffset,r.borderDashOffset),c.lineJoin=Si(i.lineJoin,r.borderJoinStyle),c.lineWidth=o,c.strokeStyle=Si(i.strokeStyle,a),c.setLineDash&&c.setLineDash(Si(i.lineDash,r.borderDash)),n&&n.usePointStyle){var s=m*Math.SQRT2/2,l=h.xPlus(t,m/2),u=e+p/2;V.canvas.drawPoint(c,i.pointStyle,s,l,u,i.rotation)}else c.fillRect(h.leftForLtr(t,m),e,m,p),0!==o&&c.strokeRect(h.leftForLtr(t,m),e,m,p);c.restore()}}(w,k,e),v[i].left=h.leftForLtr(w,v[i].width),v[i].top=k,function(t,e,n,i){var a=p/2,r=h.xPlus(t,m+a),o=e+a;c.fillText(n.text,r,o),n.hidden&&(c.beginPath(),c.lineWidth=2,c.moveTo(r,o),c.lineTo(h.xPlus(r,i),o),c.stroke())}(w,k,e,f),x?d.x+=g+n.padding:d.y+=y})),V.rtl.restoreTextDirection(t.ctx,e.textDirection)}},_getLegendItemAt:function(t,e){var n,i,a,r=this;if(t>=r.left&&t<=r.right&&e>=r.top&&e<=r.bottom)for(a=r.legendHitBoxes,n=0;n=(i=a[n]).left&&t<=i.left+i.width&&e>=i.top&&e<=i.top+i.height)return r.legendItems[n];return null},handleEvent:function(t){var e,n=this,i=n.options,a="mouseup"===t.type?"click":t.type;if("mousemove"===a){if(!i.onHover&&!i.onLeave)return}else{if("click"!==a)return;if(!i.onClick)return}e=n._getLegendItemAt(t.x,t.y),"click"===a?e&&i.onClick&&i.onClick.call(n,t.native,e):(i.onLeave&&e!==n._hoveredItem&&(n._hoveredItem&&i.onLeave.call(n,t.native,n._hoveredItem),n._hoveredItem=e),i.onHover&&e&&i.onHover.call(n,t.native,e))}});function Ai(t,e){var n=new Pi({ctx:t.ctx,options:e,chart:t});ge.configure(t,n,e),ge.addBox(t,n),t.legend=n}var Di={id:"legend",_element:Pi,beforeInit:function(t){var e=t.options.legend;e&&Ai(t,e)},beforeUpdate:function(t){var e=t.options.legend,n=t.legend;e?(V.mergeIf(e,z.global.legend),n?(ge.configure(t,n,e),n.options=e):Ai(t,e)):n&&(ge.removeBox(t,n),delete t.legend)},afterEvent:function(t,e){var n=t.legend;n&&n.handleEvent(e)}},Ti=V.noop;z._set("global",{title:{display:!1,fontStyle:"bold",fullWidth:!0,padding:10,position:"top",text:"",weight:2e3}});var Ii=X.extend({initialize:function(t){V.extend(this,t),this.legendHitBoxes=[]},beforeUpdate:Ti,update:function(t,e,n){var i=this;return i.beforeUpdate(),i.maxWidth=t,i.maxHeight=e,i.margins=n,i.beforeSetDimensions(),i.setDimensions(),i.afterSetDimensions(),i.beforeBuildLabels(),i.buildLabels(),i.afterBuildLabels(),i.beforeFit(),i.fit(),i.afterFit(),i.afterUpdate(),i.minSize},afterUpdate:Ti,beforeSetDimensions:Ti,setDimensions:function(){var t=this;t.isHorizontal()?(t.width=t.maxWidth,t.left=0,t.right=t.width):(t.height=t.maxHeight,t.top=0,t.bottom=t.height),t.paddingLeft=0,t.paddingTop=0,t.paddingRight=0,t.paddingBottom=0,t.minSize={width:0,height:0}},afterSetDimensions:Ti,beforeBuildLabels:Ti,buildLabels:Ti,afterBuildLabels:Ti,beforeFit:Ti,fit:function(){var t,e=this,n=e.options,i=e.minSize={},a=e.isHorizontal();n.display?(t=(V.isArray(n.text)?n.text.length:1)*V.options._parseFont(n).lineHeight+2*n.padding,e.width=i.width=a?e.maxWidth:t,e.height=i.height=a?t:e.maxHeight):e.width=i.width=e.height=i.height=0},afterFit:Ti,isHorizontal:function(){var t=this.options.position;return"top"===t||"bottom"===t},draw:function(){var t=this,e=t.ctx,n=t.options;if(n.display){var i,a,r,o=V.options._parseFont(n),s=o.lineHeight,l=s/2+n.padding,u=0,d=t.top,h=t.left,c=t.bottom,f=t.right;e.fillStyle=V.valueOrDefault(n.fontColor,z.global.defaultFontColor),e.font=o.string,t.isHorizontal()?(a=h+(f-h)/2,r=d+l,i=f-h):(a="left"===n.position?h+l:f-l,r=d+(c-d)/2,i=c-d,u=Math.PI*("left"===n.position?-.5:.5)),e.save(),e.translate(a,r),e.rotate(u),e.textAlign="center",e.textBaseline="middle";var g=n.text;if(V.isArray(g))for(var p=0,m=0;m=0;i--){var a=t[i];if(e(a))return a}},V.isNumber=function(t){return!isNaN(parseFloat(t))&&isFinite(t)},V.almostEquals=function(t,e,n){return Math.abs(t-e)=t},V.max=function(t){return t.reduce((function(t,e){return isNaN(e)?t:Math.max(t,e)}),Number.NEGATIVE_INFINITY)},V.min=function(t){return t.reduce((function(t,e){return isNaN(e)?t:Math.min(t,e)}),Number.POSITIVE_INFINITY)},V.sign=Math.sign?function(t){return Math.sign(t)}:function(t){return 0===(t=+t)||isNaN(t)?t:t>0?1:-1},V.toRadians=function(t){return t*(Math.PI/180)},V.toDegrees=function(t){return t*(180/Math.PI)},V._decimalPlaces=function(t){if(V.isFinite(t)){for(var e=1,n=0;Math.round(t*e)/e!==t;)e*=10,n++;return n}},V.getAngleFromPoint=function(t,e){var n=e.x-t.x,i=e.y-t.y,a=Math.sqrt(n*n+i*i),r=Math.atan2(i,n);return r<-.5*Math.PI&&(r+=2*Math.PI),{angle:r,distance:a}},V.distanceBetweenPoints=function(t,e){return Math.sqrt(Math.pow(e.x-t.x,2)+Math.pow(e.y-t.y,2))},V.aliasPixel=function(t){return t%2==0?0:.5},V._alignPixel=function(t,e,n){var i=t.currentDevicePixelRatio,a=n/2;return Math.round((e-a)*i)/i+a},V.splineCurve=function(t,e,n,i){var a=t.skip?e:t,r=e,o=n.skip?e:n,s=Math.sqrt(Math.pow(r.x-a.x,2)+Math.pow(r.y-a.y,2)),l=Math.sqrt(Math.pow(o.x-r.x,2)+Math.pow(o.y-r.y,2)),u=s/(s+l),d=l/(s+l),h=i*(u=isNaN(u)?0:u),c=i*(d=isNaN(d)?0:d);return{previous:{x:r.x-h*(o.x-a.x),y:r.y-h*(o.y-a.y)},next:{x:r.x+c*(o.x-a.x),y:r.y+c*(o.y-a.y)}}},V.EPSILON=Number.EPSILON||1e-14,V.splineCurveMonotone=function(t){var e,n,i,a,r,o,s,l,u,d=(t||[]).map((function(t){return{model:t._model,deltaK:0,mK:0}})),h=d.length;for(e=0;e0?d[e-1]:null,(a=e0?d[e-1]:null,a=e=t.length-1?t[0]:t[e+1]:e>=t.length-1?t[t.length-1]:t[e+1]},V.previousItem=function(t,e,n){return n?e<=0?t[t.length-1]:t[e-1]:e<=0?t[0]:t[e-1]},V.niceNum=function(t,e){var n=Math.floor(V.log10(t)),i=t/Math.pow(10,n);return(e?i<1.5?1:i<3?2:i<7?5:10:i<=1?1:i<=2?2:i<=5?5:10)*Math.pow(10,n)},V.requestAnimFrame="undefined"==typeof window?function(t){t()}:window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(t){return window.setTimeout(t,1e3/60)},V.getRelativePosition=function(t,e){var n,i,a=t.originalEvent||t,r=t.target||t.srcElement,o=r.getBoundingClientRect(),s=a.touches;s&&s.length>0?(n=s[0].clientX,i=s[0].clientY):(n=a.clientX,i=a.clientY);var l=parseFloat(V.getStyle(r,"padding-left")),u=parseFloat(V.getStyle(r,"padding-top")),d=parseFloat(V.getStyle(r,"padding-right")),h=parseFloat(V.getStyle(r,"padding-bottom")),c=o.right-o.left-l-d,f=o.bottom-o.top-u-h;return{x:n=Math.round((n-o.left-l)/c*r.width/e.currentDevicePixelRatio),y:i=Math.round((i-o.top-u)/f*r.height/e.currentDevicePixelRatio)}},V.getConstraintWidth=function(t){return n(t,"max-width","clientWidth")},V.getConstraintHeight=function(t){return n(t,"max-height","clientHeight")},V._calculatePadding=function(t,e,n){return(e=V.getStyle(t,e)).indexOf("%")>-1?n*parseInt(e,10)/100:parseInt(e,10)},V._getParentNode=function(t){var e=t.parentNode;return e&&"[object ShadowRoot]"===e.toString()&&(e=e.host),e},V.getMaximumWidth=function(t){var e=V._getParentNode(t);if(!e)return t.clientWidth;var n=e.clientWidth,i=n-V._calculatePadding(e,"padding-left",n)-V._calculatePadding(e,"padding-right",n),a=V.getConstraintWidth(t);return isNaN(a)?i:Math.min(i,a)},V.getMaximumHeight=function(t){var e=V._getParentNode(t);if(!e)return t.clientHeight;var n=e.clientHeight,i=n-V._calculatePadding(e,"padding-top",n)-V._calculatePadding(e,"padding-bottom",n),a=V.getConstraintHeight(t);return isNaN(a)?i:Math.min(i,a)},V.getStyle=function(t,e){return t.currentStyle?t.currentStyle[e]:document.defaultView.getComputedStyle(t,null).getPropertyValue(e)},V.retinaScale=function(t,e){var n=t.currentDevicePixelRatio=e||"undefined"!=typeof window&&window.devicePixelRatio||1;if(1!==n){var i=t.canvas,a=t.height,r=t.width;i.height=a*n,i.width=r*n,t.ctx.scale(n,n),i.style.height||i.style.width||(i.style.height=a+"px",i.style.width=r+"px")}},V.fontString=function(t,e,n){return e+" "+t+"px "+n},V.longestText=function(t,e,n,i){var a=(i=i||{}).data=i.data||{},r=i.garbageCollect=i.garbageCollect||[];i.font!==e&&(a=i.data={},r=i.garbageCollect=[],i.font=e),t.font=e;var o,s,l,u,d,h=0,c=n.length;for(o=0;on.length){for(o=0;oi&&(i=r),i},V.numberOfLabelLines=function(t){var e=1;return V.each(t,(function(t){V.isArray(t)&&t.length>e&&(e=t.length)})),e},V.color=k?function(t){return t instanceof CanvasGradient&&(t=z.global.defaultColor),k(t)}:function(t){return console.error("Color.js not found!"),t},V.getHoverColor=function(t){return t instanceof CanvasPattern||t instanceof CanvasGradient?t:V.color(t).saturate(.5).darken(.1).rgbString()}}(),tn._adapters=an,tn.Animation=Z,tn.animationService=$,tn.controllers=$t,tn.DatasetController=nt,tn.defaults=z,tn.Element=X,tn.elements=_t,tn.Interaction=ae,tn.layouts=ge,tn.platform=Fe,tn.plugins=Le,tn.Scale=xn,tn.scaleService=Oe,tn.Ticks=rn,tn.Tooltip=Ue,tn.helpers.each(ci,(function(t,e){tn.scaleService.registerScaleType(e,t,t._defaults)})),Li)Li.hasOwnProperty(Ni)&&tn.plugins.register(Li[Ni]);tn.platform.initialize();var Bi=tn;return"undefined"!=typeof window&&(window.Chart=tn),tn.Chart=tn,tn.Legend=Li.legend._element,tn.Title=Li.title._element,tn.pluginService=tn.plugins,tn.PluginBase=tn.Element.extend({}),tn.canvasHelpers=tn.helpers.canvas,tn.layoutService=tn.layouts,tn.LinearScaleBase=Sn,tn.helpers.each(["Bar","Bubble","Doughnut","Line","PolarArea","Radar","Scatter"],(function(t){tn[t]=function(e,n){return new tn(e,tn.helpers.merge(n||{},{type:t.charAt(0).toLowerCase()+t.slice(1)}))}})),Bi})); diff --git a/src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/e12dee6b.js b/src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/e12dee6b.js deleted file mode 100644 index 7e017db547..0000000000 --- a/src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/e12dee6b.js +++ /dev/null @@ -1,11 +0,0 @@ -/*! - * angular-chart.js - An angular.js wrapper for Chart.js - * http://jtblin.github.io/angular-chart.js/ - * Version: 1.1.1 - * - * Copyright 2016 Jerome Touffe-Blin - * Released under the BSD-2-Clause license - * https://github.com/jtblin/angular-chart.js/blob/master/LICENSE - */ -!function(t){"use strict";if("object"==typeof exports)module.exports=t("undefined"!=typeof angular?angular:require("angular"),"undefined"!=typeof Chart?Chart:require("chart.js"));else if("function"==typeof define&&define.amd)define(["angular","chart"],t);else{if("undefined"==typeof angular)throw new Error("AngularJS framework needs to be included, see https://angularjs.org/");if("undefined"==typeof Chart)throw new Error("Chart.js library needs to be included, see http://jtblin.github.io/angular-chart.js/");t(angular,Chart)}}(function(t,r){"use strict";function e(){var e={responsive:!0},a={Chart:r,getOptions:function(r){var a=r&&e[r]||{};return t.extend({},e,a)}};this.setOptions=function(r,n){n?e[r]=t.merge(e[r]||{},n):(n=r,e=t.merge(e,n)),t.merge(a.Chart.defaults,e)},this.$get=function(){return a}}function a(e,a){function o(t,r,a){var n=D(t,r);if(C(r)&&k(t,r,a,n)){var o=a[0],c=o.getContext("2d");r.chartGetColor=y(r);var i=b(t,r);F(r),r.chart=new e.Chart(c,{type:t,data:i,options:n}),r.$emit("chart-create",r.chart),A(o,r)}}function c(t,r){return!!(t&&r&&t.length&&r.length)&&(Array.isArray(t[0])?t.length===r.length&&t.every(function(t,e){return t.length===r[e].length}):r.reduce(i,0)>0&&t.length===r.length)}function i(t,r){return t+r}function u(r,e,a){var n={point:void 0,points:void 0};return function(o){var c=r.chart.getElementAtEvent||r.chart.getPointAtEvent,i=r.chart.getElementsAtEvent||r.chart.getPointsAtEvent;if(i){var u=i.call(r.chart,o),l=c?c.call(r.chart,o)[0]:void 0;a!==!1&&(t.equals(n.points,u)||t.equals(n.point,l))||(n.point=l,n.points=u,r[e](u,o,l))}}}function l(a,n){for(var o=t.copy(n.chartColors||e.getOptions(a).chartColors||r.defaults.global.colors),c=o.length>16&255,a=r>>8&255,n=255&r;return[e,a,n]}function v(t){var r=t.match(/^rgba?\(([\d,.]+)\)$/);if(!r)throw new Error("Cannot parse rgb value");return t=r[1].split(","),t.map(Number)}function C(t){return t.chartData&&t.chartData.length}function y(t){return"function"==typeof t.chartGetColor?t.chartGetColor:s}function b(t,r){var e=l(t,r);return Array.isArray(r.chartData[0])?m(r.chartLabels,r.chartData,r.chartSeries||[],e,r.chartDatasetOverride):w(r.chartLabels,r.chartData,e,r.chartDatasetOverride)}function m(r,e,a,n,o){return{labels:r,datasets:e.map(function(r,e){var c=t.extend({},n[e],{label:a[e],data:r});return o&&o.length>=e&&t.merge(c,o[e]),c})}}function w(r,e,a,n){var o={labels:r,datasets:[{data:e,backgroundColor:a.map(function(t){return t.pointBackgroundColor}),hoverBackgroundColor:a.map(function(t){return t.backgroundColor})}]};return n&&t.merge(o.datasets[0],n),o}function D(r,a){return t.extend({},e.getOptions(r),a.chartOptions)}function A(r,e){r.onclick=e.chartClick?u(e,"chartClick",!1):t.noop,r.onmousemove=e.chartHover?u(e,"chartHover",!0):t.noop}function B(t,r){Array.isArray(r.chartData[0])?r.chart.data.datasets.forEach(function(r,e){r.data=t[e]}):r.chart.data.datasets[0].data=t,r.chart.update(),r.$emit("chart-update",r.chart)}function $(t){return!t||Array.isArray(t)&&!t.length||"object"==typeof t&&!Object.keys(t).length}function k(t,r,e,n){return!n.responsive||0!==e[0].clientHeight||(a(function(){o(t,r,e)},50,!1),!1)}function F(t){t.chart&&(t.chart.destroy(),t.$emit("chart-destroy",t.chart))}return function(r){return{restrict:"CA",scope:{chartGetColor:"=?",chartType:"=",chartData:"=?",chartLabels:"=?",chartOptions:"=?",chartSeries:"=?",chartColors:"=?",chartClick:"=?",chartHover:"=?",chartDatasetOverride:"=?"},link:function(e,a){function i(t,n){if(!t||!t.length||Array.isArray(t[0])&&!t[0].length)return void F(e);var i=r||e.chartType;if(i)return e.chart&&c(t,n)?B(t,e):void o(i,e,a)}function u(n,c){if(!$(n)&&!t.equals(n,c)){var i=r||e.chartType;i&&o(i,e,a)}}function l(r,n){$(r)||t.equals(r,n)||o(r,e,a)}n&&window.G_vmlCanvasManager.initElement(a[0]),e.$watch("chartData",i,!0),e.$watch("chartSeries",u,!0),e.$watch("chartLabels",u,!0),e.$watch("chartOptions",u,!0),e.$watch("chartColors",u,!0),e.$watch("chartDatasetOverride",u,!0),e.$watch("chartType",l,!1),e.$on("$destroy",function(){F(e)}),e.$on("$resize",function(){e.chart&&e.chart.resize()})}}}}r.defaults.global.multiTooltipTemplate="<%if (datasetLabel){%><%=datasetLabel%>: <%}%><%= value %>",r.defaults.global.tooltips.mode="label",r.defaults.global.elements.line.borderWidth=2,r.defaults.global.elements.rectangle.borderWidth=2,r.defaults.global.legend.display=!1,r.defaults.global.colors=["#97BBCD","#DCDCDC","#F7464A","#46BFBD","#FDB45C","#949FB1","#4D5360"];var n="object"==typeof window.G_vmlCanvasManager&&null!==window.G_vmlCanvasManager&&"function"==typeof window.G_vmlCanvasManager.initElement;return n&&(r.defaults.global.animation=!1),t.module("chart.js",[]).provider("ChartJs",e).factory("ChartJsFactory",["ChartJs","$timeout",a]).directive("chartBase",["ChartJsFactory",function(t){return new t}]).directive("chartLine",["ChartJsFactory",function(t){return new t("line")}]).directive("chartBar",["ChartJsFactory",function(t){return new t("bar")}]).directive("chartHorizontalBar",["ChartJsFactory",function(t){return new t("horizontalBar")}]).directive("chartRadar",["ChartJsFactory",function(t){return new t("radar")}]).directive("chartDoughnut",["ChartJsFactory",function(t){return new t("doughnut")}]).directive("chartPie",["ChartJsFactory",function(t){return new t("pie")}]).directive("chartPolarArea",["ChartJsFactory",function(t){return new t("polarArea")}]).directive("chartBubble",["ChartJsFactory",function(t){return new t("bubble")}]).name}); -//# sourceMappingURL=angular-chart.min.js.map diff --git a/src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/e1519986.js b/src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/e1519986.js deleted file mode 100644 index ca05c7c803..0000000000 --- a/src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/e1519986.js +++ /dev/null @@ -1,13 +0,0 @@ -(function(window,angular){'use strict';var forEach;var isArray;var isString;var jqLite;angular.module('ngMessages',[],function initAngularHelpers(){forEach=angular.forEach;isArray=angular.isArray;isString=angular.isString;jqLite=angular.element;}).info({angularVersion:'1.7.5'}).directive('ngMessages',['$animate',function($animate){var ACTIVE_CLASS='ng-active';var INACTIVE_CLASS='ng-inactive';return{require:'ngMessages',restrict:'AE',controller:['$element','$scope','$attrs',function NgMessagesCtrl($element,$scope,$attrs){var ctrl=this;var latestKey=0;var nextAttachId=0;this.getAttachId=function getAttachId(){return nextAttachId++;};var messages=this.messages={};var renderLater,cachedCollection;this.render=function(collection){collection=collection||{};renderLater=false;cachedCollection=collection;var multiple=isAttrTruthy($scope,$attrs.ngMessagesMultiple)||isAttrTruthy($scope,$attrs.multiple);var unmatchedMessages=[];var matchedKeys={};var truthyKeys=0;var messageItem=ctrl.head;var messageFound=false;var totalMessages=0;while(messageItem!=null){totalMessages++;var messageCtrl=messageItem.message;var messageUsed=false;if(!messageFound){forEach(collection,function(value,key){if(truthy(value)&&!messageUsed){truthyKeys++;if(messageCtrl.test(key)){if(matchedKeys[key])return;matchedKeys[key]=true;messageUsed=true;messageCtrl.attach();}}});} -if(messageUsed){messageFound=!multiple;}else{unmatchedMessages.push(messageCtrl);} -messageItem=messageItem.next;} -forEach(unmatchedMessages,function(messageCtrl){messageCtrl.detach();});var messageMatched=unmatchedMessages.length!==totalMessages;var attachDefault=ctrl.default&&!messageMatched&&truthyKeys>0;if(attachDefault){ctrl.default.attach();}else if(ctrl.default){ctrl.default.detach();} -if(messageMatched||attachDefault){$animate.setClass($element,ACTIVE_CLASS,INACTIVE_CLASS);}else{$animate.setClass($element,INACTIVE_CLASS,ACTIVE_CLASS);}};$scope.$watchCollection($attrs.ngMessages||$attrs['for'],ctrl.render);this.reRender=function(){if(!renderLater){renderLater=true;$scope.$evalAsync(function(){if(renderLater&&cachedCollection){ctrl.render(cachedCollection);}});}};this.register=function(comment,messageCtrl,isDefault){if(isDefault){ctrl.default=messageCtrl;}else{var nextKey=latestKey.toString();messages[nextKey]={message:messageCtrl};insertMessageNode($element[0],comment,nextKey);comment.$$ngMessageNode=nextKey;latestKey++;} -ctrl.reRender();};this.deregister=function(comment,isDefault){if(isDefault){delete ctrl.default;}else{var key=comment.$$ngMessageNode;delete comment.$$ngMessageNode;removeMessageNode($element[0],comment,key);delete messages[key];} -ctrl.reRender();};function findPreviousMessage(parent,comment){var prevNode=comment;var parentLookup=[];while(prevNode&&prevNode!==parent){var prevKey=prevNode.$$ngMessageNode;if(prevKey&&prevKey.length){return messages[prevKey];} -if(prevNode.childNodes.length&&parentLookup.indexOf(prevNode)===-1){parentLookup.push(prevNode);prevNode=prevNode.childNodes[prevNode.childNodes.length-1];}else if(prevNode.previousSibling){prevNode=prevNode.previousSibling;}else{prevNode=prevNode.parentNode;parentLookup.push(prevNode);}}} -function insertMessageNode(parent,comment,key){var messageNode=messages[key];if(!ctrl.head){ctrl.head=messageNode;}else{var match=findPreviousMessage(parent,comment);if(match){messageNode.next=match.next;match.next=messageNode;}else{messageNode.next=ctrl.head;ctrl.head=messageNode;}}} -function removeMessageNode(parent,comment,key){var messageNode=messages[key];if(!messageNode)return;var match=findPreviousMessage(parent,comment);if(match){match.next=messageNode.next;}else{ctrl.head=messageNode.next;}}}]};function isAttrTruthy(scope,attr){return(isString(attr)&&attr.length===0)||truthy(scope.$eval(attr));} -function truthy(val){return isString(val)?val.length:!!val;}}]).directive('ngMessagesInclude',['$templateRequest','$document','$compile',function($templateRequest,$document,$compile){return{restrict:'AE',require:'^^ngMessages',link:function($scope,element,attrs){var src=attrs.ngMessagesInclude||attrs.src;$templateRequest(src).then(function(html){if($scope.$$destroyed)return;if(isString(html)&&!html.trim()){replaceElementWithMarker(element,src);}else{$compile(html)($scope,function(contents){element.after(contents);replaceElementWithMarker(element,src);});}});}};function replaceElementWithMarker(element,src){var comment=$compile.$$createComment?$compile.$$createComment('ngMessagesInclude',src):$document[0].createComment(' ngMessagesInclude: '+src+' ');var marker=jqLite(comment);element.after(marker);element.remove();}}]).directive('ngMessage',ngMessageDirectiveFactory()).directive('ngMessageExp',ngMessageDirectiveFactory()).directive('ngMessageDefault',ngMessageDirectiveFactory(true));function ngMessageDirectiveFactory(isDefault){return['$animate',function($animate){return{restrict:'AE',transclude:'element',priority:1,terminal:true,require:'^^ngMessages',link:function(scope,element,attrs,ngMessagesCtrl,$transclude){var commentNode,records,staticExp,dynamicExp;if(!isDefault){commentNode=element[0];staticExp=attrs.ngMessage||attrs.when;dynamicExp=attrs.ngMessageExp||attrs.whenExp;var assignRecords=function(items){records=items?(isArray(items)?items:items.split(/[\s,]+/)):null;ngMessagesCtrl.reRender();};if(dynamicExp){assignRecords(scope.$eval(dynamicExp));scope.$watchCollection(dynamicExp,assignRecords);}else{assignRecords(staticExp);}} -var currentElement,messageCtrl;ngMessagesCtrl.register(commentNode,messageCtrl={test:function(name){return contains(records,name);},attach:function(){if(!currentElement){$transclude(function(elm,newScope){$animate.enter(elm,null,element);currentElement=elm;var $$attachId=currentElement.$$attachId=ngMessagesCtrl.getAttachId();currentElement.on('$destroy',function(){if(currentElement&¤tElement.$$attachId===$$attachId){ngMessagesCtrl.deregister(commentNode,isDefault);messageCtrl.detach();} -newScope.$destroy();});});}},detach:function(){if(currentElement){var elm=currentElement;currentElement=null;$animate.leave(elm);}}},isDefault);scope.$on('$destroy',function(){ngMessagesCtrl.deregister(commentNode,isDefault);});}};}];function contains(collection,key){if(collection){return isArray(collection)?collection.indexOf(key)>=0:collection.hasOwnProperty(key);}}}})(window,window.angular);; \ No newline at end of file diff --git a/src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/e3fbab10.js b/src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/e3fbab10.js deleted file mode 100644 index 8c460ecf2c..0000000000 --- a/src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/e3fbab10.js +++ /dev/null @@ -1 +0,0 @@ -!function(c){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),t=tinymce.util.Tools.resolve("tinymce.dom.DOMUtils"),s=tinymce.util.Tools.resolve("tinymce.EditorManager"),a=tinymce.util.Tools.resolve("tinymce.Env"),y=tinymce.util.Tools.resolve("tinymce.util.Delay"),f=tinymce.util.Tools.resolve("tinymce.util.Tools"),d=tinymce.util.Tools.resolve("tinymce.util.VK"),m=function(e){return e.getParam("tab_focus",e.getParam("tabfocus_elements",":prev,:next"))},v=t.DOM,n=function(e){e.keyCode!==d.TAB||e.ctrlKey||e.altKey||e.metaKey||e.preventDefault()},i=function(r){function e(n){var i,o,e,l;if(!(n.keyCode!==d.TAB||n.ctrlKey||n.altKey||n.metaKey||n.isDefaultPrevented())&&(1===(e=f.explode(m(r))).length&&(e[1]=e[0],e[0]=":prev"),o=n.shiftKey?":prev"===e[0]?u(-1):v.get(e[0]):":next"===e[1]?u(1):v.get(e[1]))){var t=s.get(o.id||o.name);o.id&&t?t.focus():y.setTimeout(function(){a.webkit||c.window.focus(),o.focus()},10),n.preventDefault()}function u(e){function t(t){return/INPUT|TEXTAREA|BUTTON/.test(t.tagName)&&s.get(n.id)&&-1!==t.tabIndex&&function e(t){return"BODY"===t.nodeName||"hidden"!==t.type&&"none"!==t.style.display&&"hidden"!==t.style.visibility&&e(t.parentNode)}(t)}if(o=v.select(":input:enabled,*[tabindex]:not(iframe)"),f.each(o,function(e,t){if(e.id===r.id)return i=t,!1}),0":">",'"':""","'":"'","`":"`"},P=h.invert(L),W=function(r){var t=function(n){return r[n]},n="(?:"+h.keys(r).join("|")+")",e=RegExp(n),u=RegExp(n,"g");return function(n){return n=null==n?"":""+n,e.test(n)?n.replace(u,t):n}};h.escape=W(L),h.unescape=W(P),h.result=function(n,r,t){h.isArray(r)||(r=[r]);var e=r.length;if(!e)return h.isFunction(t)?t.call(n):t;for(var u=0;u/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var J=/(.)^/,U={"'":"'","\\":"\\","\r":"r","\n":"n","\u2028":"u2028","\u2029":"u2029"},V=/\\|'|\r|\n|\u2028|\u2029/g,$=function(n){return"\\"+U[n]};h.template=function(i,n,r){!n&&r&&(n=r),n=h.defaults({},n,h.templateSettings);var t,e=RegExp([(n.escape||J).source,(n.interpolate||J).source,(n.evaluate||J).source].join("|")+"|$","g"),o=0,a="__p+='";i.replace(e,function(n,r,t,e,u){return a+=i.slice(o,u).replace(V,$),o=u+n.length,r?a+="'+\n((__t=("+r+"))==null?'':_.escape(__t))+\n'":t?a+="'+\n((__t=("+t+"))==null?'':__t)+\n'":e&&(a+="';\n"+e+"\n__p+='"),n}),a+="';\n",n.variable||(a="with(obj||{}){\n"+a+"}\n"),a="var __t,__p='',__j=Array.prototype.join,"+"print=function(){__p+=__j.call(arguments,'');};\n"+a+"return __p;\n";try{t=new Function(n.variable||"obj","_",a)}catch(n){throw n.source=a,n}var u=function(n){return t.call(this,n,h)},c=n.variable||"obj";return u.source="function("+c+"){\n"+a+"}",u},h.chain=function(n){var r=h(n);return r._chain=!0,r};var G=function(n,r){return n._chain?h(r).chain():r};h.mixin=function(t){return h.each(h.functions(t),function(n){var r=h[n]=t[n];h.prototype[n]=function(){var n=[this._wrapped];return u.apply(n,arguments),G(this,r.apply(h,n))}}),h},h.mixin(h),h.each(["pop","push","reverse","shift","sort","splice","unshift"],function(r){var t=e[r];h.prototype[r]=function(){var n=this._wrapped;return t.apply(n,arguments),"shift"!==r&&"splice"!==r||0!==n.length||delete n[0],G(this,n)}}),h.each(["concat","join","slice"],function(n){var r=e[n];h.prototype[n]=function(){return G(this,r.apply(this._wrapped,arguments))}}),h.prototype.value=function(){return this._wrapped},h.prototype.valueOf=h.prototype.toJSON=h.prototype.value,h.prototype.toString=function(){return String(this._wrapped)},"function"==typeof define&&define.amd&&define("underscore",[],function(){return h})}(); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/f48f9c37.js b/src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/f48f9c37.js deleted file mode 100644 index 6462c82add..0000000000 --- a/src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/f48f9c37.js +++ /dev/null @@ -1,3 +0,0 @@ -var app=angular.module('umbraco',['umbraco.filters','umbraco.directives','umbraco.resources','umbraco.services','umbraco.packages','umbraco.views','ngRoute','ngAnimate','ngCookies','ngSanitize','ngTouch','ngMessages','ngAria','tmh.dynamicLocale','ngFileUpload','LocalStorageModule','chart.js']);app.config(['$compileProvider',function($compileProvider){$compileProvider.debugInfoEnabled(Umbraco.Sys.ServerVariables.isDebuggingEnabled);$compileProvider.commentDirectivesEnabled(false);$compileProvider.cssClassDirectivesEnabled(false);}]);angular.module("umbraco").config(function configureAnimate($animateProvider){$animateProvider.classNameFilter(/\bumb-animated\b/);});var packages=angular.module("umbraco.packages",[]);angular.module("umbraco.views",["umbraco.viewcache"]);angular.module("umbraco.viewcache",[]).run(function($rootScope,$templateCache,localStorageService){if(Umbraco.Sys.ServerVariables.isDebuggingEnabled){$templateCache.removeAll();} -else{var storedVersion=localStorageService.get("umbVersion");if(!storedVersion||storedVersion!==Umbraco.Sys.ServerVariables.application.cacheBuster){$templateCache.removeAll();localStorageService.set("umbVersion",Umbraco.Sys.ServerVariables.application.cacheBuster);}}}).config(["$provide",function($provide){return $provide.decorator("$http",["$delegate",function($delegate){var get=$delegate.get;$delegate.get=function(url,config){if(Umbraco.Sys.ServerVariables.application&&url.startsWith("views/")&&url.endsWith(".html")){var rnd=Umbraco.Sys.ServerVariables.application.cacheBuster;var _op=(url.indexOf("?")>0)?"&":"?";url+=_op+"umb__rnd="+rnd;} -return get(url,config);};return $delegate;}]);}]);if(angular.isFunction(document.angularReady)){document.angularReady.apply(this,[app]);}; \ No newline at end of file diff --git a/src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/faa84de5.js b/src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/faa84de5.js deleted file mode 100644 index bb48bcf941..0000000000 --- a/src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/faa84de5.js +++ /dev/null @@ -1 +0,0 @@ -!function(){"use strict";var t=tinymce.util.Tools.resolve("tinymce.PluginManager"),c=tinymce.util.Tools.resolve("tinymce.util.Tools"),e=function(t,e){var i,n=t.dom,o=t.selection.getSelectedBlocks();o.length&&(i=n.getAttrib(o[0],"dir"),c.each(o,function(t){n.getParent(t.parentNode,'*[dir="'+e+'"]',n.getRoot())||n.setAttrib(t,"dir",i!==e?e:null)}),t.nodeChanged())},i=function(t){t.addCommand("mceDirectionLTR",function(){e(t,"ltr")}),t.addCommand("mceDirectionRTL",function(){e(t,"rtl")})},n=function(e){var i=[];return c.each("h1 h2 h3 h4 h5 h6 div p".split(" "),function(t){i.push(t+"[dir="+e+"]")}),i.join(",")},o=function(t){t.addButton("ltr",{title:"Left to right",cmd:"mceDirectionLTR",stateSelector:n("ltr")}),t.addButton("rtl",{title:"Right to left",cmd:"mceDirectionRTL",stateSelector:n("rtl")})};t.add("directionality",function(t){i(t),o(t)})}(); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/fb8e5b2a.js b/src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/fb8e5b2a.js deleted file mode 100644 index 25398a1674..0000000000 --- a/src/Umbraco.Web.UI.NetCore/App_Data/Smidge/Cache/BERG-DESKTOP/1/fb8e5b2a.js +++ /dev/null @@ -1,13 +0,0 @@ -/*! jQuery UI - v1.12.1 - 2016-09-14 -* http://jqueryui.com -* Includes: widget.js, position.js, data.js, disable-selection.js, effect.js, effects/effect-blind.js, effects/effect-bounce.js, effects/effect-clip.js, effects/effect-drop.js, effects/effect-explode.js, effects/effect-fade.js, effects/effect-fold.js, effects/effect-highlight.js, effects/effect-puff.js, effects/effect-pulsate.js, effects/effect-scale.js, effects/effect-shake.js, effects/effect-size.js, effects/effect-slide.js, effects/effect-transfer.js, focusable.js, form-reset-mixin.js, jquery-1-7.js, keycode.js, labels.js, scroll-parent.js, tabbable.js, unique-id.js, widgets/accordion.js, widgets/autocomplete.js, widgets/button.js, widgets/checkboxradio.js, widgets/controlgroup.js, widgets/datepicker.js, widgets/dialog.js, widgets/draggable.js, widgets/droppable.js, widgets/menu.js, widgets/mouse.js, widgets/progressbar.js, widgets/resizable.js, widgets/selectable.js, widgets/selectmenu.js, widgets/slider.js, widgets/sortable.js, widgets/spinner.js, widgets/tabs.js, widgets/tooltip.js -* Copyright jQuery Foundation and other contributors; Licensed MIT */ - -(function(t){"function"==typeof define&&define.amd?define(["jquery"],t):t(jQuery)})(function(t){function e(t){for(var e=t.css("visibility");"inherit"===e;)t=t.parent(),e=t.css("visibility");return"hidden"!==e}function i(t){for(var e,i;t.length&&t[0]!==document;){if(e=t.css("position"),("absolute"===e||"relative"===e||"fixed"===e)&&(i=parseInt(t.css("zIndex"),10),!isNaN(i)&&0!==i))return i;t=t.parent()}return 0}function s(){this._curInst=null,this._keyEvent=!1,this._disabledInputs=[],this._datepickerShowing=!1,this._inDialog=!1,this._mainDivId="ui-datepicker-div",this._inlineClass="ui-datepicker-inline",this._appendClass="ui-datepicker-append",this._triggerClass="ui-datepicker-trigger",this._dialogClass="ui-datepicker-dialog",this._disableClass="ui-datepicker-disabled",this._unselectableClass="ui-datepicker-unselectable",this._currentClass="ui-datepicker-current-day",this._dayOverClass="ui-datepicker-days-cell-over",this.regional=[],this.regional[""]={closeText:"Done",prevText:"Prev",nextText:"Next",currentText:"Today",monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayNamesShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],dayNamesMin:["Su","Mo","Tu","We","Th","Fr","Sa"],weekHeader:"Wk",dateFormat:"mm/dd/yy",firstDay:0,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""},this._defaults={showOn:"focus",showAnim:"fadeIn",showOptions:{},defaultDate:null,appendText:"",buttonText:"...",buttonImage:"",buttonImageOnly:!1,hideIfNoPrevNext:!1,navigationAsDateFormat:!1,gotoCurrent:!1,changeMonth:!1,changeYear:!1,yearRange:"c-10:c+10",showOtherMonths:!1,selectOtherMonths:!1,showWeek:!1,calculateWeek:this.iso8601Week,shortYearCutoff:"+10",minDate:null,maxDate:null,duration:"fast",beforeShowDay:null,beforeShow:null,onSelect:null,onChangeMonthYear:null,onClose:null,numberOfMonths:1,showCurrentAtPos:0,stepMonths:1,stepBigMonths:12,altField:"",altFormat:"",constrainInput:!0,showButtonPanel:!1,autoSize:!1,disabled:!1},t.extend(this._defaults,this.regional[""]),this.regional.en=t.extend(!0,{},this.regional[""]),this.regional["en-US"]=t.extend(!0,{},this.regional.en),this.dpDiv=n(t("
"))}function n(e){var i="button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";return e.on("mouseout",i,function(){t(this).removeClass("ui-state-hover"),-1!==this.className.indexOf("ui-datepicker-prev")&&t(this).removeClass("ui-datepicker-prev-hover"),-1!==this.className.indexOf("ui-datepicker-next")&&t(this).removeClass("ui-datepicker-next-hover")}).on("mouseover",i,o)}function o(){t.datepicker._isDisabledDatepicker(m.inline?m.dpDiv.parent()[0]:m.input[0])||(t(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover"),t(this).addClass("ui-state-hover"),-1!==this.className.indexOf("ui-datepicker-prev")&&t(this).addClass("ui-datepicker-prev-hover"),-1!==this.className.indexOf("ui-datepicker-next")&&t(this).addClass("ui-datepicker-next-hover"))}function a(e,i){t.extend(e,i);for(var s in i)null==i[s]&&(e[s]=i[s]);return e}function r(t){return function(){var e=this.element.val();t.apply(this,arguments),this._refresh(),e!==this.element.val()&&this._trigger("change")}}t.ui=t.ui||{},t.ui.version="1.12.1";var h=0,l=Array.prototype.slice;t.cleanData=function(e){return function(i){var s,n,o;for(o=0;null!=(n=i[o]);o++)try{s=t._data(n,"events"),s&&s.remove&&t(n).triggerHandler("remove")}catch(a){}e(i)}}(t.cleanData),t.widget=function(e,i,s){var n,o,a,r={},h=e.split(".")[0];e=e.split(".")[1];var l=h+"-"+e;return s||(s=i,i=t.Widget),t.isArray(s)&&(s=t.extend.apply(null,[{}].concat(s))),t.expr[":"][l.toLowerCase()]=function(e){return!!t.data(e,l)},t[h]=t[h]||{},n=t[h][e],o=t[h][e]=function(t,e){return this._createWidget?(arguments.length&&this._createWidget(t,e),void 0):new o(t,e)},t.extend(o,n,{version:s.version,_proto:t.extend({},s),_childConstructors:[]}),a=new i,a.options=t.widget.extend({},a.options),t.each(s,function(e,s){return t.isFunction(s)?(r[e]=function(){function t(){return i.prototype[e].apply(this,arguments)}function n(t){return i.prototype[e].apply(this,t)}return function(){var e,i=this._super,o=this._superApply;return this._super=t,this._superApply=n,e=s.apply(this,arguments),this._super=i,this._superApply=o,e}}(),void 0):(r[e]=s,void 0)}),o.prototype=t.widget.extend(a,{widgetEventPrefix:n?a.widgetEventPrefix||e:e},r,{constructor:o,namespace:h,widgetName:e,widgetFullName:l}),n?(t.each(n._childConstructors,function(e,i){var s=i.prototype;t.widget(s.namespace+"."+s.widgetName,o,i._proto)}),delete n._childConstructors):i._childConstructors.push(o),t.widget.bridge(e,o),o},t.widget.extend=function(e){for(var i,s,n=l.call(arguments,1),o=0,a=n.length;a>o;o++)for(i in n[o])s=n[o][i],n[o].hasOwnProperty(i)&&void 0!==s&&(e[i]=t.isPlainObject(s)?t.isPlainObject(e[i])?t.widget.extend({},e[i],s):t.widget.extend({},s):s);return e},t.widget.bridge=function(e,i){var s=i.prototype.widgetFullName||e;t.fn[e]=function(n){var o="string"==typeof n,a=l.call(arguments,1),r=this;return o?this.length||"instance"!==n?this.each(function(){var i,o=t.data(this,s);return"instance"===n?(r=o,!1):o?t.isFunction(o[n])&&"_"!==n.charAt(0)?(i=o[n].apply(o,a),i!==o&&void 0!==i?(r=i&&i.jquery?r.pushStack(i.get()):i,!1):void 0):t.error("no such method '"+n+"' for "+e+" widget instance"):t.error("cannot call methods on "+e+" prior to initialization; "+"attempted to call method '"+n+"'")}):r=void 0:(a.length&&(n=t.widget.extend.apply(null,[n].concat(a))),this.each(function(){var e=t.data(this,s);e?(e.option(n||{}),e._init&&e._init()):t.data(this,s,new i(n,this))})),r}},t.Widget=function(){},t.Widget._childConstructors=[],t.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"
",options:{classes:{},disabled:!1,create:null},_createWidget:function(e,i){i=t(i||this.defaultElement||this)[0],this.element=t(i),this.uuid=h++,this.eventNamespace="."+this.widgetName+this.uuid,this.bindings=t(),this.hoverable=t(),this.focusable=t(),this.classesElementLookup={},i!==this&&(t.data(i,this.widgetFullName,this),this._on(!0,this.element,{remove:function(t){t.target===i&&this.destroy()}}),this.document=t(i.style?i.ownerDocument:i.document||i),this.window=t(this.document[0].defaultView||this.document[0].parentWindow)),this.options=t.widget.extend({},this.options,this._getCreateOptions(),e),this._create(),this.options.disabled&&this._setOptionDisabled(this.options.disabled),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:function(){return{}},_getCreateEventData:t.noop,_create:t.noop,_init:t.noop,destroy:function(){var e=this;this._destroy(),t.each(this.classesElementLookup,function(t,i){e._removeClass(i,t)}),this.element.off(this.eventNamespace).removeData(this.widgetFullName),this.widget().off(this.eventNamespace).removeAttr("aria-disabled"),this.bindings.off(this.eventNamespace)},_destroy:t.noop,widget:function(){return this.element},option:function(e,i){var s,n,o,a=e;if(0===arguments.length)return t.widget.extend({},this.options);if("string"==typeof e)if(a={},s=e.split("."),e=s.shift(),s.length){for(n=a[e]=t.widget.extend({},this.options[e]),o=0;s.length-1>o;o++)n[s[o]]=n[s[o]]||{},n=n[s[o]];if(e=s.pop(),1===arguments.length)return void 0===n[e]?null:n[e];n[e]=i}else{if(1===arguments.length)return void 0===this.options[e]?null:this.options[e];a[e]=i}return this._setOptions(a),this},_setOptions:function(t){var e;for(e in t)this._setOption(e,t[e]);return this},_setOption:function(t,e){return"classes"===t&&this._setOptionClasses(e),this.options[t]=e,"disabled"===t&&this._setOptionDisabled(e),this},_setOptionClasses:function(e){var i,s,n;for(i in e)n=this.classesElementLookup[i],e[i]!==this.options.classes[i]&&n&&n.length&&(s=t(n.get()),this._removeClass(n,i),s.addClass(this._classes({element:s,keys:i,classes:e,add:!0})))},_setOptionDisabled:function(t){this._toggleClass(this.widget(),this.widgetFullName+"-disabled",null,!!t),t&&(this._removeClass(this.hoverable,null,"ui-state-hover"),this._removeClass(this.focusable,null,"ui-state-focus"))},enable:function(){return this._setOptions({disabled:!1})},disable:function(){return this._setOptions({disabled:!0})},_classes:function(e){function i(i,o){var a,r;for(r=0;i.length>r;r++)a=n.classesElementLookup[i[r]]||t(),a=e.add?t(t.unique(a.get().concat(e.element.get()))):t(a.not(e.element).get()),n.classesElementLookup[i[r]]=a,s.push(i[r]),o&&e.classes[i[r]]&&s.push(e.classes[i[r]])}var s=[],n=this;return e=t.extend({element:this.element,classes:this.options.classes||{}},e),this._on(e.element,{remove:"_untrackClassesElement"}),e.keys&&i(e.keys.match(/\S+/g)||[],!0),e.extra&&i(e.extra.match(/\S+/g)||[]),s.join(" ")},_untrackClassesElement:function(e){var i=this;t.each(i.classesElementLookup,function(s,n){-1!==t.inArray(e.target,n)&&(i.classesElementLookup[s]=t(n.not(e.target).get()))})},_removeClass:function(t,e,i){return this._toggleClass(t,e,i,!1)},_addClass:function(t,e,i){return this._toggleClass(t,e,i,!0)},_toggleClass:function(t,e,i,s){s="boolean"==typeof s?s:i;var n="string"==typeof t||null===t,o={extra:n?e:i,keys:n?t:e,element:n?this.element:t,add:s};return o.element.toggleClass(this._classes(o),s),this},_on:function(e,i,s){var n,o=this;"boolean"!=typeof e&&(s=i,i=e,e=!1),s?(i=n=t(i),this.bindings=this.bindings.add(i)):(s=i,i=this.element,n=this.widget()),t.each(s,function(s,a){function r(){return e||o.options.disabled!==!0&&!t(this).hasClass("ui-state-disabled")?("string"==typeof a?o[a]:a).apply(o,arguments):void 0}"string"!=typeof a&&(r.guid=a.guid=a.guid||r.guid||t.guid++);var h=s.match(/^([\w:-]*)\s*(.*)$/),l=h[1]+o.eventNamespace,c=h[2];c?n.on(l,c,r):i.on(l,r)})},_off:function(e,i){i=(i||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,e.off(i).off(i),this.bindings=t(this.bindings.not(e).get()),this.focusable=t(this.focusable.not(e).get()),this.hoverable=t(this.hoverable.not(e).get())},_delay:function(t,e){function i(){return("string"==typeof t?s[t]:t).apply(s,arguments)}var s=this;return setTimeout(i,e||0)},_hoverable:function(e){this.hoverable=this.hoverable.add(e),this._on(e,{mouseenter:function(e){this._addClass(t(e.currentTarget),null,"ui-state-hover")},mouseleave:function(e){this._removeClass(t(e.currentTarget),null,"ui-state-hover")}})},_focusable:function(e){this.focusable=this.focusable.add(e),this._on(e,{focusin:function(e){this._addClass(t(e.currentTarget),null,"ui-state-focus")},focusout:function(e){this._removeClass(t(e.currentTarget),null,"ui-state-focus")}})},_trigger:function(e,i,s){var n,o,a=this.options[e];if(s=s||{},i=t.Event(i),i.type=(e===this.widgetEventPrefix?e:this.widgetEventPrefix+e).toLowerCase(),i.target=this.element[0],o=i.originalEvent)for(n in o)n in i||(i[n]=o[n]);return this.element.trigger(i,s),!(t.isFunction(a)&&a.apply(this.element[0],[i].concat(s))===!1||i.isDefaultPrevented())}},t.each({show:"fadeIn",hide:"fadeOut"},function(e,i){t.Widget.prototype["_"+e]=function(s,n,o){"string"==typeof n&&(n={effect:n});var a,r=n?n===!0||"number"==typeof n?i:n.effect||i:e;n=n||{},"number"==typeof n&&(n={duration:n}),a=!t.isEmptyObject(n),n.complete=o,n.delay&&s.delay(n.delay),a&&t.effects&&t.effects.effect[r]?s[e](n):r!==e&&s[r]?s[r](n.duration,n.easing,o):s.queue(function(i){t(this)[e](),o&&o.call(s[0]),i()})}}),t.widget,function(){function e(t,e,i){return[parseFloat(t[0])*(u.test(t[0])?e/100:1),parseFloat(t[1])*(u.test(t[1])?i/100:1)]}function i(e,i){return parseInt(t.css(e,i),10)||0}function s(e){var i=e[0];return 9===i.nodeType?{width:e.width(),height:e.height(),offset:{top:0,left:0}}:t.isWindow(i)?{width:e.width(),height:e.height(),offset:{top:e.scrollTop(),left:e.scrollLeft()}}:i.preventDefault?{width:0,height:0,offset:{top:i.pageY,left:i.pageX}}:{width:e.outerWidth(),height:e.outerHeight(),offset:e.offset()}}var n,o=Math.max,a=Math.abs,r=/left|center|right/,h=/top|center|bottom/,l=/[\+\-]\d+(\.[\d]+)?%?/,c=/^\w+/,u=/%$/,d=t.fn.position;t.position={scrollbarWidth:function(){if(void 0!==n)return n;var e,i,s=t("
"),o=s.children()[0];return t("body").append(s),e=o.offsetWidth,s.css("overflow","scroll"),i=o.offsetWidth,e===i&&(i=s[0].clientWidth),s.remove(),n=e-i},getScrollInfo:function(e){var i=e.isWindow||e.isDocument?"":e.element.css("overflow-x"),s=e.isWindow||e.isDocument?"":e.element.css("overflow-y"),n="scroll"===i||"auto"===i&&e.widthi?"left":e>0?"right":"center",vertical:0>r?"top":s>0?"bottom":"middle"};l>p&&p>a(e+i)&&(u.horizontal="center"),c>f&&f>a(s+r)&&(u.vertical="middle"),u.important=o(a(e),a(i))>o(a(s),a(r))?"horizontal":"vertical",n.using.call(this,t,u)}),h.offset(t.extend(D,{using:r}))})},t.ui.position={fit:{left:function(t,e){var i,s=e.within,n=s.isWindow?s.scrollLeft:s.offset.left,a=s.width,r=t.left-e.collisionPosition.marginLeft,h=n-r,l=r+e.collisionWidth-a-n;e.collisionWidth>a?h>0&&0>=l?(i=t.left+h+e.collisionWidth-a-n,t.left+=h-i):t.left=l>0&&0>=h?n:h>l?n+a-e.collisionWidth:n:h>0?t.left+=h:l>0?t.left-=l:t.left=o(t.left-r,t.left)},top:function(t,e){var i,s=e.within,n=s.isWindow?s.scrollTop:s.offset.top,a=e.within.height,r=t.top-e.collisionPosition.marginTop,h=n-r,l=r+e.collisionHeight-a-n;e.collisionHeight>a?h>0&&0>=l?(i=t.top+h+e.collisionHeight-a-n,t.top+=h-i):t.top=l>0&&0>=h?n:h>l?n+a-e.collisionHeight:n:h>0?t.top+=h:l>0?t.top-=l:t.top=o(t.top-r,t.top)}},flip:{left:function(t,e){var i,s,n=e.within,o=n.offset.left+n.scrollLeft,r=n.width,h=n.isWindow?n.scrollLeft:n.offset.left,l=t.left-e.collisionPosition.marginLeft,c=l-h,u=l+e.collisionWidth-r-h,d="left"===e.my[0]?-e.elemWidth:"right"===e.my[0]?e.elemWidth:0,p="left"===e.at[0]?e.targetWidth:"right"===e.at[0]?-e.targetWidth:0,f=-2*e.offset[0];0>c?(i=t.left+d+p+f+e.collisionWidth-r-o,(0>i||a(c)>i)&&(t.left+=d+p+f)):u>0&&(s=t.left-e.collisionPosition.marginLeft+d+p+f-h,(s>0||u>a(s))&&(t.left+=d+p+f))},top:function(t,e){var i,s,n=e.within,o=n.offset.top+n.scrollTop,r=n.height,h=n.isWindow?n.scrollTop:n.offset.top,l=t.top-e.collisionPosition.marginTop,c=l-h,u=l+e.collisionHeight-r-h,d="top"===e.my[1],p=d?-e.elemHeight:"bottom"===e.my[1]?e.elemHeight:0,f="top"===e.at[1]?e.targetHeight:"bottom"===e.at[1]?-e.targetHeight:0,g=-2*e.offset[1];0>c?(s=t.top+p+f+g+e.collisionHeight-r-o,(0>s||a(c)>s)&&(t.top+=p+f+g)):u>0&&(i=t.top-e.collisionPosition.marginTop+p+f+g-h,(i>0||u>a(i))&&(t.top+=p+f+g))}},flipfit:{left:function(){t.ui.position.flip.left.apply(this,arguments),t.ui.position.fit.left.apply(this,arguments)},top:function(){t.ui.position.flip.top.apply(this,arguments),t.ui.position.fit.top.apply(this,arguments)}}}}(),t.ui.position,t.extend(t.expr[":"],{data:t.expr.createPseudo?t.expr.createPseudo(function(e){return function(i){return!!t.data(i,e)}}):function(e,i,s){return!!t.data(e,s[3])}}),t.fn.extend({disableSelection:function(){var t="onselectstart"in document.createElement("div")?"selectstart":"mousedown";return function(){return this.on(t+".ui-disableSelection",function(t){t.preventDefault()})}}(),enableSelection:function(){return this.off(".ui-disableSelection")}});var c="ui-effects-",u="ui-effects-style",d="ui-effects-animated",p=t;t.effects={effect:{}},function(t,e){function i(t,e,i){var s=u[e.type]||{};return null==t?i||!e.def?null:e.def:(t=s.floor?~~t:parseFloat(t),isNaN(t)?e.def:s.mod?(t+s.mod)%s.mod:0>t?0:t>s.max?s.max:t)}function s(i){var s=l(),n=s._rgba=[];return i=i.toLowerCase(),f(h,function(t,o){var a,r=o.re.exec(i),h=r&&o.parse(r),l=o.space||"rgba";return h?(a=s[l](h),s[c[l].cache]=a[c[l].cache],n=s._rgba=a._rgba,!1):e}),n.length?("0,0,0,0"===n.join()&&t.extend(n,o.transparent),s):o[i]}function n(t,e,i){return i=(i+1)%1,1>6*i?t+6*(e-t)*i:1>2*i?e:2>3*i?t+6*(e-t)*(2/3-i):t}var o,a="backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor",r=/^([\-+])=\s*(\d+\.?\d*)/,h=[{re:/rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,parse:function(t){return[t[1],t[2],t[3],t[4]]}},{re:/rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,parse:function(t){return[2.55*t[1],2.55*t[2],2.55*t[3],t[4]]}},{re:/#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/,parse:function(t){return[parseInt(t[1],16),parseInt(t[2],16),parseInt(t[3],16)]}},{re:/#([a-f0-9])([a-f0-9])([a-f0-9])/,parse:function(t){return[parseInt(t[1]+t[1],16),parseInt(t[2]+t[2],16),parseInt(t[3]+t[3],16)]}},{re:/hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,space:"hsla",parse:function(t){return[t[1],t[2]/100,t[3]/100,t[4]]}}],l=t.Color=function(e,i,s,n){return new t.Color.fn.parse(e,i,s,n)},c={rgba:{props:{red:{idx:0,type:"byte"},green:{idx:1,type:"byte"},blue:{idx:2,type:"byte"}}},hsla:{props:{hue:{idx:0,type:"degrees"},saturation:{idx:1,type:"percent"},lightness:{idx:2,type:"percent"}}}},u={"byte":{floor:!0,max:255},percent:{max:1},degrees:{mod:360,floor:!0}},d=l.support={},p=t("

")[0],f=t.each;p.style.cssText="background-color:rgba(1,1,1,.5)",d.rgba=p.style.backgroundColor.indexOf("rgba")>-1,f(c,function(t,e){e.cache="_"+t,e.props.alpha={idx:3,type:"percent",def:1}}),l.fn=t.extend(l.prototype,{parse:function(n,a,r,h){if(n===e)return this._rgba=[null,null,null,null],this;(n.jquery||n.nodeType)&&(n=t(n).css(a),a=e);var u=this,d=t.type(n),p=this._rgba=[];return a!==e&&(n=[n,a,r,h],d="array"),"string"===d?this.parse(s(n)||o._default):"array"===d?(f(c.rgba.props,function(t,e){p[e.idx]=i(n[e.idx],e)}),this):"object"===d?(n instanceof l?f(c,function(t,e){n[e.cache]&&(u[e.cache]=n[e.cache].slice())}):f(c,function(e,s){var o=s.cache;f(s.props,function(t,e){if(!u[o]&&s.to){if("alpha"===t||null==n[t])return;u[o]=s.to(u._rgba)}u[o][e.idx]=i(n[t],e,!0)}),u[o]&&0>t.inArray(null,u[o].slice(0,3))&&(u[o][3]=1,s.from&&(u._rgba=s.from(u[o])))}),this):e},is:function(t){var i=l(t),s=!0,n=this;return f(c,function(t,o){var a,r=i[o.cache];return r&&(a=n[o.cache]||o.to&&o.to(n._rgba)||[],f(o.props,function(t,i){return null!=r[i.idx]?s=r[i.idx]===a[i.idx]:e})),s}),s},_space:function(){var t=[],e=this;return f(c,function(i,s){e[s.cache]&&t.push(i)}),t.pop()},transition:function(t,e){var s=l(t),n=s._space(),o=c[n],a=0===this.alpha()?l("transparent"):this,r=a[o.cache]||o.to(a._rgba),h=r.slice();return s=s[o.cache],f(o.props,function(t,n){var o=n.idx,a=r[o],l=s[o],c=u[n.type]||{};null!==l&&(null===a?h[o]=l:(c.mod&&(l-a>c.mod/2?a+=c.mod:a-l>c.mod/2&&(a-=c.mod)),h[o]=i((l-a)*e+a,n)))}),this[n](h)},blend:function(e){if(1===this._rgba[3])return this;var i=this._rgba.slice(),s=i.pop(),n=l(e)._rgba;return l(t.map(i,function(t,e){return(1-s)*n[e]+s*t}))},toRgbaString:function(){var e="rgba(",i=t.map(this._rgba,function(t,e){return null==t?e>2?1:0:t});return 1===i[3]&&(i.pop(),e="rgb("),e+i.join()+")"},toHslaString:function(){var e="hsla(",i=t.map(this.hsla(),function(t,e){return null==t&&(t=e>2?1:0),e&&3>e&&(t=Math.round(100*t)+"%"),t});return 1===i[3]&&(i.pop(),e="hsl("),e+i.join()+")"},toHexString:function(e){var i=this._rgba.slice(),s=i.pop();return e&&i.push(~~(255*s)),"#"+t.map(i,function(t){return t=(t||0).toString(16),1===t.length?"0"+t:t}).join("")},toString:function(){return 0===this._rgba[3]?"transparent":this.toRgbaString()}}),l.fn.parse.prototype=l.fn,c.hsla.to=function(t){if(null==t[0]||null==t[1]||null==t[2])return[null,null,null,t[3]];var e,i,s=t[0]/255,n=t[1]/255,o=t[2]/255,a=t[3],r=Math.max(s,n,o),h=Math.min(s,n,o),l=r-h,c=r+h,u=.5*c;return e=h===r?0:s===r?60*(n-o)/l+360:n===r?60*(o-s)/l+120:60*(s-n)/l+240,i=0===l?0:.5>=u?l/c:l/(2-c),[Math.round(e)%360,i,u,null==a?1:a]},c.hsla.from=function(t){if(null==t[0]||null==t[1]||null==t[2])return[null,null,null,t[3]];var e=t[0]/360,i=t[1],s=t[2],o=t[3],a=.5>=s?s*(1+i):s+i-s*i,r=2*s-a;return[Math.round(255*n(r,a,e+1/3)),Math.round(255*n(r,a,e)),Math.round(255*n(r,a,e-1/3)),o]},f(c,function(s,n){var o=n.props,a=n.cache,h=n.to,c=n.from;l.fn[s]=function(s){if(h&&!this[a]&&(this[a]=h(this._rgba)),s===e)return this[a].slice();var n,r=t.type(s),u="array"===r||"object"===r?s:arguments,d=this[a].slice();return f(o,function(t,e){var s=u["object"===r?t:e.idx];null==s&&(s=d[e.idx]),d[e.idx]=i(s,e)}),c?(n=l(c(d)),n[a]=d,n):l(d)},f(o,function(e,i){l.fn[e]||(l.fn[e]=function(n){var o,a=t.type(n),h="alpha"===e?this._hsla?"hsla":"rgba":s,l=this[h](),c=l[i.idx];return"undefined"===a?c:("function"===a&&(n=n.call(this,c),a=t.type(n)),null==n&&i.empty?this:("string"===a&&(o=r.exec(n),o&&(n=c+parseFloat(o[2])*("+"===o[1]?1:-1))),l[i.idx]=n,this[h](l)))})})}),l.hook=function(e){var i=e.split(" ");f(i,function(e,i){t.cssHooks[i]={set:function(e,n){var o,a,r="";if("transparent"!==n&&("string"!==t.type(n)||(o=s(n)))){if(n=l(o||n),!d.rgba&&1!==n._rgba[3]){for(a="backgroundColor"===i?e.parentNode:e;(""===r||"transparent"===r)&&a&&a.style;)try{r=t.css(a,"backgroundColor"),a=a.parentNode}catch(h){}n=n.blend(r&&"transparent"!==r?r:"_default")}n=n.toRgbaString()}try{e.style[i]=n}catch(h){}}},t.fx.step[i]=function(e){e.colorInit||(e.start=l(e.elem,i),e.end=l(e.end),e.colorInit=!0),t.cssHooks[i].set(e.elem,e.start.transition(e.end,e.pos))}})},l.hook(a),t.cssHooks.borderColor={expand:function(t){var e={};return f(["Top","Right","Bottom","Left"],function(i,s){e["border"+s+"Color"]=t}),e}},o=t.Color.names={aqua:"#00ffff",black:"#000000",blue:"#0000ff",fuchsia:"#ff00ff",gray:"#808080",green:"#008000",lime:"#00ff00",maroon:"#800000",navy:"#000080",olive:"#808000",purple:"#800080",red:"#ff0000",silver:"#c0c0c0",teal:"#008080",white:"#ffffff",yellow:"#ffff00",transparent:[null,null,null,0],_default:"#ffffff"}}(p),function(){function e(e){var i,s,n=e.ownerDocument.defaultView?e.ownerDocument.defaultView.getComputedStyle(e,null):e.currentStyle,o={};if(n&&n.length&&n[0]&&n[n[0]])for(s=n.length;s--;)i=n[s],"string"==typeof n[i]&&(o[t.camelCase(i)]=n[i]);else for(i in n)"string"==typeof n[i]&&(o[i]=n[i]);return o}function i(e,i){var s,o,a={};for(s in i)o=i[s],e[s]!==o&&(n[s]||(t.fx.step[s]||!isNaN(parseFloat(o)))&&(a[s]=o));return a}var s=["add","remove","toggle"],n={border:1,borderBottom:1,borderColor:1,borderLeft:1,borderRight:1,borderTop:1,borderWidth:1,margin:1,padding:1};t.each(["borderLeftStyle","borderRightStyle","borderBottomStyle","borderTopStyle"],function(e,i){t.fx.step[i]=function(t){("none"!==t.end&&!t.setAttr||1===t.pos&&!t.setAttr)&&(p.style(t.elem,i,t.end),t.setAttr=!0)}}),t.fn.addBack||(t.fn.addBack=function(t){return this.add(null==t?this.prevObject:this.prevObject.filter(t))}),t.effects.animateClass=function(n,o,a,r){var h=t.speed(o,a,r);return this.queue(function(){var o,a=t(this),r=a.attr("class")||"",l=h.children?a.find("*").addBack():a;l=l.map(function(){var i=t(this);return{el:i,start:e(this)}}),o=function(){t.each(s,function(t,e){n[e]&&a[e+"Class"](n[e])})},o(),l=l.map(function(){return this.end=e(this.el[0]),this.diff=i(this.start,this.end),this}),a.attr("class",r),l=l.map(function(){var e=this,i=t.Deferred(),s=t.extend({},h,{queue:!1,complete:function(){i.resolve(e)}});return this.el.animate(this.diff,s),i.promise()}),t.when.apply(t,l.get()).done(function(){o(),t.each(arguments,function(){var e=this.el;t.each(this.diff,function(t){e.css(t,"")})}),h.complete.call(a[0])})})},t.fn.extend({addClass:function(e){return function(i,s,n,o){return s?t.effects.animateClass.call(this,{add:i},s,n,o):e.apply(this,arguments)}}(t.fn.addClass),removeClass:function(e){return function(i,s,n,o){return arguments.length>1?t.effects.animateClass.call(this,{remove:i},s,n,o):e.apply(this,arguments)}}(t.fn.removeClass),toggleClass:function(e){return function(i,s,n,o,a){return"boolean"==typeof s||void 0===s?n?t.effects.animateClass.call(this,s?{add:i}:{remove:i},n,o,a):e.apply(this,arguments):t.effects.animateClass.call(this,{toggle:i},s,n,o)}}(t.fn.toggleClass),switchClass:function(e,i,s,n,o){return t.effects.animateClass.call(this,{add:i,remove:e},s,n,o)}})}(),function(){function e(e,i,s,n){return t.isPlainObject(e)&&(i=e,e=e.effect),e={effect:e},null==i&&(i={}),t.isFunction(i)&&(n=i,s=null,i={}),("number"==typeof i||t.fx.speeds[i])&&(n=s,s=i,i={}),t.isFunction(s)&&(n=s,s=null),i&&t.extend(e,i),s=s||i.duration,e.duration=t.fx.off?0:"number"==typeof s?s:s in t.fx.speeds?t.fx.speeds[s]:t.fx.speeds._default,e.complete=n||i.complete,e}function i(e){return!e||"number"==typeof e||t.fx.speeds[e]?!0:"string"!=typeof e||t.effects.effect[e]?t.isFunction(e)?!0:"object"!=typeof e||e.effect?!1:!0:!0}function s(t,e){var i=e.outerWidth(),s=e.outerHeight(),n=/^rect\((-?\d*\.?\d*px|-?\d+%|auto),?\s*(-?\d*\.?\d*px|-?\d+%|auto),?\s*(-?\d*\.?\d*px|-?\d+%|auto),?\s*(-?\d*\.?\d*px|-?\d+%|auto)\)$/,o=n.exec(t)||["",0,i,s,0];return{top:parseFloat(o[1])||0,right:"auto"===o[2]?i:parseFloat(o[2]),bottom:"auto"===o[3]?s:parseFloat(o[3]),left:parseFloat(o[4])||0}}t.expr&&t.expr.filters&&t.expr.filters.animated&&(t.expr.filters.animated=function(e){return function(i){return!!t(i).data(d)||e(i)}}(t.expr.filters.animated)),t.uiBackCompat!==!1&&t.extend(t.effects,{save:function(t,e){for(var i=0,s=e.length;s>i;i++)null!==e[i]&&t.data(c+e[i],t[0].style[e[i]])},restore:function(t,e){for(var i,s=0,n=e.length;n>s;s++)null!==e[s]&&(i=t.data(c+e[s]),t.css(e[s],i))},setMode:function(t,e){return"toggle"===e&&(e=t.is(":hidden")?"show":"hide"),e},createWrapper:function(e){if(e.parent().is(".ui-effects-wrapper"))return e.parent();var i={width:e.outerWidth(!0),height:e.outerHeight(!0),"float":e.css("float")},s=t("

").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent",border:"none",margin:0,padding:0}),n={width:e.width(),height:e.height()},o=document.activeElement;try{o.id}catch(a){o=document.body}return e.wrap(s),(e[0]===o||t.contains(e[0],o))&&t(o).trigger("focus"),s=e.parent(),"static"===e.css("position")?(s.css({position:"relative"}),e.css({position:"relative"})):(t.extend(i,{position:e.css("position"),zIndex:e.css("z-index")}),t.each(["top","left","bottom","right"],function(t,s){i[s]=e.css(s),isNaN(parseInt(i[s],10))&&(i[s]="auto")}),e.css({position:"relative",top:0,left:0,right:"auto",bottom:"auto"})),e.css(n),s.css(i).show()},removeWrapper:function(e){var i=document.activeElement;return e.parent().is(".ui-effects-wrapper")&&(e.parent().replaceWith(e),(e[0]===i||t.contains(e[0],i))&&t(i).trigger("focus")),e}}),t.extend(t.effects,{version:"1.12.1",define:function(e,i,s){return s||(s=i,i="effect"),t.effects.effect[e]=s,t.effects.effect[e].mode=i,s},scaledDimensions:function(t,e,i){if(0===e)return{height:0,width:0,outerHeight:0,outerWidth:0};var s="horizontal"!==i?(e||100)/100:1,n="vertical"!==i?(e||100)/100:1;return{height:t.height()*n,width:t.width()*s,outerHeight:t.outerHeight()*n,outerWidth:t.outerWidth()*s}},clipToBox:function(t){return{width:t.clip.right-t.clip.left,height:t.clip.bottom-t.clip.top,left:t.clip.left,top:t.clip.top}},unshift:function(t,e,i){var s=t.queue();e>1&&s.splice.apply(s,[1,0].concat(s.splice(e,i))),t.dequeue()},saveStyle:function(t){t.data(u,t[0].style.cssText)},restoreStyle:function(t){t[0].style.cssText=t.data(u)||"",t.removeData(u)},mode:function(t,e){var i=t.is(":hidden");return"toggle"===e&&(e=i?"show":"hide"),(i?"hide"===e:"show"===e)&&(e="none"),e},getBaseline:function(t,e){var i,s;switch(t[0]){case"top":i=0;break;case"middle":i=.5;break;case"bottom":i=1;break;default:i=t[0]/e.height}switch(t[1]){case"left":s=0;break;case"center":s=.5;break;case"right":s=1;break;default:s=t[1]/e.width}return{x:s,y:i}},createPlaceholder:function(e){var i,s=e.css("position"),n=e.position();return e.css({marginTop:e.css("marginTop"),marginBottom:e.css("marginBottom"),marginLeft:e.css("marginLeft"),marginRight:e.css("marginRight")}).outerWidth(e.outerWidth()).outerHeight(e.outerHeight()),/^(static|relative)/.test(s)&&(s="absolute",i=t("<"+e[0].nodeName+">").insertAfter(e).css({display:/^(inline|ruby)/.test(e.css("display"))?"inline-block":"block",visibility:"hidden",marginTop:e.css("marginTop"),marginBottom:e.css("marginBottom"),marginLeft:e.css("marginLeft"),marginRight:e.css("marginRight"),"float":e.css("float")}).outerWidth(e.outerWidth()).outerHeight(e.outerHeight()).addClass("ui-effects-placeholder"),e.data(c+"placeholder",i)),e.css({position:s,left:n.left,top:n.top}),i},removePlaceholder:function(t){var e=c+"placeholder",i=t.data(e);i&&(i.remove(),t.removeData(e))},cleanUp:function(e){t.effects.restoreStyle(e),t.effects.removePlaceholder(e)},setTransition:function(e,i,s,n){return n=n||{},t.each(i,function(t,i){var o=e.cssUnit(i);o[0]>0&&(n[i]=o[0]*s+o[1])}),n}}),t.fn.extend({effect:function(){function i(e){function i(){r.removeData(d),t.effects.cleanUp(r),"hide"===s.mode&&r.hide(),a()}function a(){t.isFunction(h)&&h.call(r[0]),t.isFunction(e)&&e()}var r=t(this);s.mode=c.shift(),t.uiBackCompat===!1||o?"none"===s.mode?(r[l](),a()):n.call(r[0],s,i):(r.is(":hidden")?"hide"===l:"show"===l)?(r[l](),a()):n.call(r[0],s,a)}var s=e.apply(this,arguments),n=t.effects.effect[s.effect],o=n.mode,a=s.queue,r=a||"fx",h=s.complete,l=s.mode,c=[],u=function(e){var i=t(this),s=t.effects.mode(i,l)||o;i.data(d,!0),c.push(s),o&&("show"===s||s===o&&"hide"===s)&&i.show(),o&&"none"===s||t.effects.saveStyle(i),t.isFunction(e)&&e()};return t.fx.off||!n?l?this[l](s.duration,h):this.each(function(){h&&h.call(this)}):a===!1?this.each(u).each(i):this.queue(r,u).queue(r,i)},show:function(t){return function(s){if(i(s))return t.apply(this,arguments);var n=e.apply(this,arguments);return n.mode="show",this.effect.call(this,n) -}}(t.fn.show),hide:function(t){return function(s){if(i(s))return t.apply(this,arguments);var n=e.apply(this,arguments);return n.mode="hide",this.effect.call(this,n)}}(t.fn.hide),toggle:function(t){return function(s){if(i(s)||"boolean"==typeof s)return t.apply(this,arguments);var n=e.apply(this,arguments);return n.mode="toggle",this.effect.call(this,n)}}(t.fn.toggle),cssUnit:function(e){var i=this.css(e),s=[];return t.each(["em","px","%","pt"],function(t,e){i.indexOf(e)>0&&(s=[parseFloat(i),e])}),s},cssClip:function(t){return t?this.css("clip","rect("+t.top+"px "+t.right+"px "+t.bottom+"px "+t.left+"px)"):s(this.css("clip"),this)},transfer:function(e,i){var s=t(this),n=t(e.to),o="fixed"===n.css("position"),a=t("body"),r=o?a.scrollTop():0,h=o?a.scrollLeft():0,l=n.offset(),c={top:l.top-r,left:l.left-h,height:n.innerHeight(),width:n.innerWidth()},u=s.offset(),d=t("
").appendTo("body").addClass(e.className).css({top:u.top-r,left:u.left-h,height:s.innerHeight(),width:s.innerWidth(),position:o?"fixed":"absolute"}).animate(c,e.duration,e.easing,function(){d.remove(),t.isFunction(i)&&i()})}}),t.fx.step.clip=function(e){e.clipInit||(e.start=t(e.elem).cssClip(),"string"==typeof e.end&&(e.end=s(e.end,e.elem)),e.clipInit=!0),t(e.elem).cssClip({top:e.pos*(e.end.top-e.start.top)+e.start.top,right:e.pos*(e.end.right-e.start.right)+e.start.right,bottom:e.pos*(e.end.bottom-e.start.bottom)+e.start.bottom,left:e.pos*(e.end.left-e.start.left)+e.start.left})}}(),function(){var e={};t.each(["Quad","Cubic","Quart","Quint","Expo"],function(t,i){e[i]=function(e){return Math.pow(e,t+2)}}),t.extend(e,{Sine:function(t){return 1-Math.cos(t*Math.PI/2)},Circ:function(t){return 1-Math.sqrt(1-t*t)},Elastic:function(t){return 0===t||1===t?t:-Math.pow(2,8*(t-1))*Math.sin((80*(t-1)-7.5)*Math.PI/15)},Back:function(t){return t*t*(3*t-2)},Bounce:function(t){for(var e,i=4;((e=Math.pow(2,--i))-1)/11>t;);return 1/Math.pow(4,3-i)-7.5625*Math.pow((3*e-2)/22-t,2)}}),t.each(e,function(e,i){t.easing["easeIn"+e]=i,t.easing["easeOut"+e]=function(t){return 1-i(1-t)},t.easing["easeInOut"+e]=function(t){return.5>t?i(2*t)/2:1-i(-2*t+2)/2}})}();var f=t.effects;t.effects.define("blind","hide",function(e,i){var s={up:["bottom","top"],vertical:["bottom","top"],down:["top","bottom"],left:["right","left"],horizontal:["right","left"],right:["left","right"]},n=t(this),o=e.direction||"up",a=n.cssClip(),r={clip:t.extend({},a)},h=t.effects.createPlaceholder(n);r.clip[s[o][0]]=r.clip[s[o][1]],"show"===e.mode&&(n.cssClip(r.clip),h&&h.css(t.effects.clipToBox(r)),r.clip=a),h&&h.animate(t.effects.clipToBox(r),e.duration,e.easing),n.animate(r,{queue:!1,duration:e.duration,easing:e.easing,complete:i})}),t.effects.define("bounce",function(e,i){var s,n,o,a=t(this),r=e.mode,h="hide"===r,l="show"===r,c=e.direction||"up",u=e.distance,d=e.times||5,p=2*d+(l||h?1:0),f=e.duration/p,g=e.easing,m="up"===c||"down"===c?"top":"left",_="up"===c||"left"===c,v=0,b=a.queue().length;for(t.effects.createPlaceholder(a),o=a.css(m),u||(u=a["top"===m?"outerHeight":"outerWidth"]()/3),l&&(n={opacity:1},n[m]=o,a.css("opacity",0).css(m,_?2*-u:2*u).animate(n,f,g)),h&&(u/=Math.pow(2,d-1)),n={},n[m]=o;d>v;v++)s={},s[m]=(_?"-=":"+=")+u,a.animate(s,f,g).animate(n,f,g),u=h?2*u:u/2;h&&(s={opacity:0},s[m]=(_?"-=":"+=")+u,a.animate(s,f,g)),a.queue(i),t.effects.unshift(a,b,p+1)}),t.effects.define("clip","hide",function(e,i){var s,n={},o=t(this),a=e.direction||"vertical",r="both"===a,h=r||"horizontal"===a,l=r||"vertical"===a;s=o.cssClip(),n.clip={top:l?(s.bottom-s.top)/2:s.top,right:h?(s.right-s.left)/2:s.right,bottom:l?(s.bottom-s.top)/2:s.bottom,left:h?(s.right-s.left)/2:s.left},t.effects.createPlaceholder(o),"show"===e.mode&&(o.cssClip(n.clip),n.clip=s),o.animate(n,{queue:!1,duration:e.duration,easing:e.easing,complete:i})}),t.effects.define("drop","hide",function(e,i){var s,n=t(this),o=e.mode,a="show"===o,r=e.direction||"left",h="up"===r||"down"===r?"top":"left",l="up"===r||"left"===r?"-=":"+=",c="+="===l?"-=":"+=",u={opacity:0};t.effects.createPlaceholder(n),s=e.distance||n["top"===h?"outerHeight":"outerWidth"](!0)/2,u[h]=l+s,a&&(n.css(u),u[h]=c+s,u.opacity=1),n.animate(u,{queue:!1,duration:e.duration,easing:e.easing,complete:i})}),t.effects.define("explode","hide",function(e,i){function s(){b.push(this),b.length===u*d&&n()}function n(){p.css({visibility:"visible"}),t(b).remove(),i()}var o,a,r,h,l,c,u=e.pieces?Math.round(Math.sqrt(e.pieces)):3,d=u,p=t(this),f=e.mode,g="show"===f,m=p.show().css("visibility","hidden").offset(),_=Math.ceil(p.outerWidth()/d),v=Math.ceil(p.outerHeight()/u),b=[];for(o=0;u>o;o++)for(h=m.top+o*v,c=o-(u-1)/2,a=0;d>a;a++)r=m.left+a*_,l=a-(d-1)/2,p.clone().appendTo("body").wrap("
").css({position:"absolute",visibility:"visible",left:-a*_,top:-o*v}).parent().addClass("ui-effects-explode").css({position:"absolute",overflow:"hidden",width:_,height:v,left:r+(g?l*_:0),top:h+(g?c*v:0),opacity:g?0:1}).animate({left:r+(g?0:l*_),top:h+(g?0:c*v),opacity:g?1:0},e.duration||500,e.easing,s)}),t.effects.define("fade","toggle",function(e,i){var s="show"===e.mode;t(this).css("opacity",s?0:1).animate({opacity:s?1:0},{queue:!1,duration:e.duration,easing:e.easing,complete:i})}),t.effects.define("fold","hide",function(e,i){var s=t(this),n=e.mode,o="show"===n,a="hide"===n,r=e.size||15,h=/([0-9]+)%/.exec(r),l=!!e.horizFirst,c=l?["right","bottom"]:["bottom","right"],u=e.duration/2,d=t.effects.createPlaceholder(s),p=s.cssClip(),f={clip:t.extend({},p)},g={clip:t.extend({},p)},m=[p[c[0]],p[c[1]]],_=s.queue().length;h&&(r=parseInt(h[1],10)/100*m[a?0:1]),f.clip[c[0]]=r,g.clip[c[0]]=r,g.clip[c[1]]=0,o&&(s.cssClip(g.clip),d&&d.css(t.effects.clipToBox(g)),g.clip=p),s.queue(function(i){d&&d.animate(t.effects.clipToBox(f),u,e.easing).animate(t.effects.clipToBox(g),u,e.easing),i()}).animate(f,u,e.easing).animate(g,u,e.easing).queue(i),t.effects.unshift(s,_,4)}),t.effects.define("highlight","show",function(e,i){var s=t(this),n={backgroundColor:s.css("backgroundColor")};"hide"===e.mode&&(n.opacity=0),t.effects.saveStyle(s),s.css({backgroundImage:"none",backgroundColor:e.color||"#ffff99"}).animate(n,{queue:!1,duration:e.duration,easing:e.easing,complete:i})}),t.effects.define("size",function(e,i){var s,n,o,a=t(this),r=["fontSize"],h=["borderTopWidth","borderBottomWidth","paddingTop","paddingBottom"],l=["borderLeftWidth","borderRightWidth","paddingLeft","paddingRight"],c=e.mode,u="effect"!==c,d=e.scale||"both",p=e.origin||["middle","center"],f=a.css("position"),g=a.position(),m=t.effects.scaledDimensions(a),_=e.from||m,v=e.to||t.effects.scaledDimensions(a,0);t.effects.createPlaceholder(a),"show"===c&&(o=_,_=v,v=o),n={from:{y:_.height/m.height,x:_.width/m.width},to:{y:v.height/m.height,x:v.width/m.width}},("box"===d||"both"===d)&&(n.from.y!==n.to.y&&(_=t.effects.setTransition(a,h,n.from.y,_),v=t.effects.setTransition(a,h,n.to.y,v)),n.from.x!==n.to.x&&(_=t.effects.setTransition(a,l,n.from.x,_),v=t.effects.setTransition(a,l,n.to.x,v))),("content"===d||"both"===d)&&n.from.y!==n.to.y&&(_=t.effects.setTransition(a,r,n.from.y,_),v=t.effects.setTransition(a,r,n.to.y,v)),p&&(s=t.effects.getBaseline(p,m),_.top=(m.outerHeight-_.outerHeight)*s.y+g.top,_.left=(m.outerWidth-_.outerWidth)*s.x+g.left,v.top=(m.outerHeight-v.outerHeight)*s.y+g.top,v.left=(m.outerWidth-v.outerWidth)*s.x+g.left),a.css(_),("content"===d||"both"===d)&&(h=h.concat(["marginTop","marginBottom"]).concat(r),l=l.concat(["marginLeft","marginRight"]),a.find("*[width]").each(function(){var i=t(this),s=t.effects.scaledDimensions(i),o={height:s.height*n.from.y,width:s.width*n.from.x,outerHeight:s.outerHeight*n.from.y,outerWidth:s.outerWidth*n.from.x},a={height:s.height*n.to.y,width:s.width*n.to.x,outerHeight:s.height*n.to.y,outerWidth:s.width*n.to.x};n.from.y!==n.to.y&&(o=t.effects.setTransition(i,h,n.from.y,o),a=t.effects.setTransition(i,h,n.to.y,a)),n.from.x!==n.to.x&&(o=t.effects.setTransition(i,l,n.from.x,o),a=t.effects.setTransition(i,l,n.to.x,a)),u&&t.effects.saveStyle(i),i.css(o),i.animate(a,e.duration,e.easing,function(){u&&t.effects.restoreStyle(i)})})),a.animate(v,{queue:!1,duration:e.duration,easing:e.easing,complete:function(){var e=a.offset();0===v.opacity&&a.css("opacity",_.opacity),u||(a.css("position","static"===f?"relative":f).offset(e),t.effects.saveStyle(a)),i()}})}),t.effects.define("scale",function(e,i){var s=t(this),n=e.mode,o=parseInt(e.percent,10)||(0===parseInt(e.percent,10)?0:"effect"!==n?0:100),a=t.extend(!0,{from:t.effects.scaledDimensions(s),to:t.effects.scaledDimensions(s,o,e.direction||"both"),origin:e.origin||["middle","center"]},e);e.fade&&(a.from.opacity=1,a.to.opacity=0),t.effects.effect.size.call(this,a,i)}),t.effects.define("puff","hide",function(e,i){var s=t.extend(!0,{},e,{fade:!0,percent:parseInt(e.percent,10)||150});t.effects.effect.scale.call(this,s,i)}),t.effects.define("pulsate","show",function(e,i){var s=t(this),n=e.mode,o="show"===n,a="hide"===n,r=o||a,h=2*(e.times||5)+(r?1:0),l=e.duration/h,c=0,u=1,d=s.queue().length;for((o||!s.is(":visible"))&&(s.css("opacity",0).show(),c=1);h>u;u++)s.animate({opacity:c},l,e.easing),c=1-c;s.animate({opacity:c},l,e.easing),s.queue(i),t.effects.unshift(s,d,h+1)}),t.effects.define("shake",function(e,i){var s=1,n=t(this),o=e.direction||"left",a=e.distance||20,r=e.times||3,h=2*r+1,l=Math.round(e.duration/h),c="up"===o||"down"===o?"top":"left",u="up"===o||"left"===o,d={},p={},f={},g=n.queue().length;for(t.effects.createPlaceholder(n),d[c]=(u?"-=":"+=")+a,p[c]=(u?"+=":"-=")+2*a,f[c]=(u?"-=":"+=")+2*a,n.animate(d,l,e.easing);r>s;s++)n.animate(p,l,e.easing).animate(f,l,e.easing);n.animate(p,l,e.easing).animate(d,l/2,e.easing).queue(i),t.effects.unshift(n,g,h+1)}),t.effects.define("slide","show",function(e,i){var s,n,o=t(this),a={up:["bottom","top"],down:["top","bottom"],left:["right","left"],right:["left","right"]},r=e.mode,h=e.direction||"left",l="up"===h||"down"===h?"top":"left",c="up"===h||"left"===h,u=e.distance||o["top"===l?"outerHeight":"outerWidth"](!0),d={};t.effects.createPlaceholder(o),s=o.cssClip(),n=o.position()[l],d[l]=(c?-1:1)*u+n,d.clip=o.cssClip(),d.clip[a[h][1]]=d.clip[a[h][0]],"show"===r&&(o.cssClip(d.clip),o.css(l,d[l]),d.clip=s,d[l]=n),o.animate(d,{queue:!1,duration:e.duration,easing:e.easing,complete:i})});var f;t.uiBackCompat!==!1&&(f=t.effects.define("transfer",function(e,i){t(this).transfer(e,i)})),t.ui.focusable=function(i,s){var n,o,a,r,h,l=i.nodeName.toLowerCase();return"area"===l?(n=i.parentNode,o=n.name,i.href&&o&&"map"===n.nodeName.toLowerCase()?(a=t("img[usemap='#"+o+"']"),a.length>0&&a.is(":visible")):!1):(/^(input|select|textarea|button|object)$/.test(l)?(r=!i.disabled,r&&(h=t(i).closest("fieldset")[0],h&&(r=!h.disabled))):r="a"===l?i.href||s:s,r&&t(i).is(":visible")&&e(t(i)))},t.extend(t.expr[":"],{focusable:function(e){return t.ui.focusable(e,null!=t.attr(e,"tabindex"))}}),t.ui.focusable,t.fn.form=function(){return"string"==typeof this[0].form?this.closest("form"):t(this[0].form)},t.ui.formResetMixin={_formResetHandler:function(){var e=t(this);setTimeout(function(){var i=e.data("ui-form-reset-instances");t.each(i,function(){this.refresh()})})},_bindFormResetHandler:function(){if(this.form=this.element.form(),this.form.length){var t=this.form.data("ui-form-reset-instances")||[];t.length||this.form.on("reset.ui-form-reset",this._formResetHandler),t.push(this),this.form.data("ui-form-reset-instances",t)}},_unbindFormResetHandler:function(){if(this.form.length){var e=this.form.data("ui-form-reset-instances");e.splice(t.inArray(this,e),1),e.length?this.form.data("ui-form-reset-instances",e):this.form.removeData("ui-form-reset-instances").off("reset.ui-form-reset")}}},"1.7"===t.fn.jquery.substring(0,3)&&(t.each(["Width","Height"],function(e,i){function s(e,i,s,o){return t.each(n,function(){i-=parseFloat(t.css(e,"padding"+this))||0,s&&(i-=parseFloat(t.css(e,"border"+this+"Width"))||0),o&&(i-=parseFloat(t.css(e,"margin"+this))||0)}),i}var n="Width"===i?["Left","Right"]:["Top","Bottom"],o=i.toLowerCase(),a={innerWidth:t.fn.innerWidth,innerHeight:t.fn.innerHeight,outerWidth:t.fn.outerWidth,outerHeight:t.fn.outerHeight};t.fn["inner"+i]=function(e){return void 0===e?a["inner"+i].call(this):this.each(function(){t(this).css(o,s(this,e)+"px")})},t.fn["outer"+i]=function(e,n){return"number"!=typeof e?a["outer"+i].call(this,e):this.each(function(){t(this).css(o,s(this,e,!0,n)+"px")})}}),t.fn.addBack=function(t){return this.add(null==t?this.prevObject:this.prevObject.filter(t))}),t.ui.keyCode={BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38},t.ui.escapeSelector=function(){var t=/([!"#$%&'()*+,.\/:;<=>?@[\]^`{|}~])/g;return function(e){return e.replace(t,"\\$1")}}(),t.fn.labels=function(){var e,i,s,n,o;return this[0].labels&&this[0].labels.length?this.pushStack(this[0].labels):(n=this.eq(0).parents("label"),s=this.attr("id"),s&&(e=this.eq(0).parents().last(),o=e.add(e.length?e.siblings():this.siblings()),i="label[for='"+t.ui.escapeSelector(s)+"']",n=n.add(o.find(i).addBack(i))),this.pushStack(n))},t.fn.scrollParent=function(e){var i=this.css("position"),s="absolute"===i,n=e?/(auto|scroll|hidden)/:/(auto|scroll)/,o=this.parents().filter(function(){var e=t(this);return s&&"static"===e.css("position")?!1:n.test(e.css("overflow")+e.css("overflow-y")+e.css("overflow-x"))}).eq(0);return"fixed"!==i&&o.length?o:t(this[0].ownerDocument||document)},t.extend(t.expr[":"],{tabbable:function(e){var i=t.attr(e,"tabindex"),s=null!=i;return(!s||i>=0)&&t.ui.focusable(e,s)}}),t.fn.extend({uniqueId:function(){var t=0;return function(){return this.each(function(){this.id||(this.id="ui-id-"+ ++t)})}}(),removeUniqueId:function(){return this.each(function(){/^ui-id-\d+$/.test(this.id)&&t(this).removeAttr("id")})}}),t.widget("ui.accordion",{version:"1.12.1",options:{active:0,animate:{},classes:{"ui-accordion-header":"ui-corner-top","ui-accordion-header-collapsed":"ui-corner-all","ui-accordion-content":"ui-corner-bottom"},collapsible:!1,event:"click",header:"> li > :first-child, > :not(li):even",heightStyle:"auto",icons:{activeHeader:"ui-icon-triangle-1-s",header:"ui-icon-triangle-1-e"},activate:null,beforeActivate:null},hideProps:{borderTopWidth:"hide",borderBottomWidth:"hide",paddingTop:"hide",paddingBottom:"hide",height:"hide"},showProps:{borderTopWidth:"show",borderBottomWidth:"show",paddingTop:"show",paddingBottom:"show",height:"show"},_create:function(){var e=this.options;this.prevShow=this.prevHide=t(),this._addClass("ui-accordion","ui-widget ui-helper-reset"),this.element.attr("role","tablist"),e.collapsible||e.active!==!1&&null!=e.active||(e.active=0),this._processPanels(),0>e.active&&(e.active+=this.headers.length),this._refresh()},_getCreateEventData:function(){return{header:this.active,panel:this.active.length?this.active.next():t()}},_createIcons:function(){var e,i,s=this.options.icons;s&&(e=t(""),this._addClass(e,"ui-accordion-header-icon","ui-icon "+s.header),e.prependTo(this.headers),i=this.active.children(".ui-accordion-header-icon"),this._removeClass(i,s.header)._addClass(i,null,s.activeHeader)._addClass(this.headers,"ui-accordion-icons"))},_destroyIcons:function(){this._removeClass(this.headers,"ui-accordion-icons"),this.headers.children(".ui-accordion-header-icon").remove()},_destroy:function(){var t;this.element.removeAttr("role"),this.headers.removeAttr("role aria-expanded aria-selected aria-controls tabIndex").removeUniqueId(),this._destroyIcons(),t=this.headers.next().css("display","").removeAttr("role aria-hidden aria-labelledby").removeUniqueId(),"content"!==this.options.heightStyle&&t.css("height","")},_setOption:function(t,e){return"active"===t?(this._activate(e),void 0):("event"===t&&(this.options.event&&this._off(this.headers,this.options.event),this._setupEvents(e)),this._super(t,e),"collapsible"!==t||e||this.options.active!==!1||this._activate(0),"icons"===t&&(this._destroyIcons(),e&&this._createIcons()),void 0)},_setOptionDisabled:function(t){this._super(t),this.element.attr("aria-disabled",t),this._toggleClass(null,"ui-state-disabled",!!t),this._toggleClass(this.headers.add(this.headers.next()),null,"ui-state-disabled",!!t)},_keydown:function(e){if(!e.altKey&&!e.ctrlKey){var i=t.ui.keyCode,s=this.headers.length,n=this.headers.index(e.target),o=!1;switch(e.keyCode){case i.RIGHT:case i.DOWN:o=this.headers[(n+1)%s];break;case i.LEFT:case i.UP:o=this.headers[(n-1+s)%s];break;case i.SPACE:case i.ENTER:this._eventHandler(e);break;case i.HOME:o=this.headers[0];break;case i.END:o=this.headers[s-1]}o&&(t(e.target).attr("tabIndex",-1),t(o).attr("tabIndex",0),t(o).trigger("focus"),e.preventDefault())}},_panelKeyDown:function(e){e.keyCode===t.ui.keyCode.UP&&e.ctrlKey&&t(e.currentTarget).prev().trigger("focus")},refresh:function(){var e=this.options;this._processPanels(),e.active===!1&&e.collapsible===!0||!this.headers.length?(e.active=!1,this.active=t()):e.active===!1?this._activate(0):this.active.length&&!t.contains(this.element[0],this.active[0])?this.headers.length===this.headers.find(".ui-state-disabled").length?(e.active=!1,this.active=t()):this._activate(Math.max(0,e.active-1)):e.active=this.headers.index(this.active),this._destroyIcons(),this._refresh()},_processPanels:function(){var t=this.headers,e=this.panels;this.headers=this.element.find(this.options.header),this._addClass(this.headers,"ui-accordion-header ui-accordion-header-collapsed","ui-state-default"),this.panels=this.headers.next().filter(":not(.ui-accordion-content-active)").hide(),this._addClass(this.panels,"ui-accordion-content","ui-helper-reset ui-widget-content"),e&&(this._off(t.not(this.headers)),this._off(e.not(this.panels)))},_refresh:function(){var e,i=this.options,s=i.heightStyle,n=this.element.parent();this.active=this._findActive(i.active),this._addClass(this.active,"ui-accordion-header-active","ui-state-active")._removeClass(this.active,"ui-accordion-header-collapsed"),this._addClass(this.active.next(),"ui-accordion-content-active"),this.active.next().show(),this.headers.attr("role","tab").each(function(){var e=t(this),i=e.uniqueId().attr("id"),s=e.next(),n=s.uniqueId().attr("id");e.attr("aria-controls",n),s.attr("aria-labelledby",i)}).next().attr("role","tabpanel"),this.headers.not(this.active).attr({"aria-selected":"false","aria-expanded":"false",tabIndex:-1}).next().attr({"aria-hidden":"true"}).hide(),this.active.length?this.active.attr({"aria-selected":"true","aria-expanded":"true",tabIndex:0}).next().attr({"aria-hidden":"false"}):this.headers.eq(0).attr("tabIndex",0),this._createIcons(),this._setupEvents(i.event),"fill"===s?(e=n.height(),this.element.siblings(":visible").each(function(){var i=t(this),s=i.css("position");"absolute"!==s&&"fixed"!==s&&(e-=i.outerHeight(!0))}),this.headers.each(function(){e-=t(this).outerHeight(!0)}),this.headers.next().each(function(){t(this).height(Math.max(0,e-t(this).innerHeight()+t(this).height()))}).css("overflow","auto")):"auto"===s&&(e=0,this.headers.next().each(function(){var i=t(this).is(":visible");i||t(this).show(),e=Math.max(e,t(this).css("height","").height()),i||t(this).hide()}).height(e))},_activate:function(e){var i=this._findActive(e)[0];i!==this.active[0]&&(i=i||this.active[0],this._eventHandler({target:i,currentTarget:i,preventDefault:t.noop}))},_findActive:function(e){return"number"==typeof e?this.headers.eq(e):t()},_setupEvents:function(e){var i={keydown:"_keydown"};e&&t.each(e.split(" "),function(t,e){i[e]="_eventHandler"}),this._off(this.headers.add(this.headers.next())),this._on(this.headers,i),this._on(this.headers.next(),{keydown:"_panelKeyDown"}),this._hoverable(this.headers),this._focusable(this.headers)},_eventHandler:function(e){var i,s,n=this.options,o=this.active,a=t(e.currentTarget),r=a[0]===o[0],h=r&&n.collapsible,l=h?t():a.next(),c=o.next(),u={oldHeader:o,oldPanel:c,newHeader:h?t():a,newPanel:l};e.preventDefault(),r&&!n.collapsible||this._trigger("beforeActivate",e,u)===!1||(n.active=h?!1:this.headers.index(a),this.active=r?t():a,this._toggle(u),this._removeClass(o,"ui-accordion-header-active","ui-state-active"),n.icons&&(i=o.children(".ui-accordion-header-icon"),this._removeClass(i,null,n.icons.activeHeader)._addClass(i,null,n.icons.header)),r||(this._removeClass(a,"ui-accordion-header-collapsed")._addClass(a,"ui-accordion-header-active","ui-state-active"),n.icons&&(s=a.children(".ui-accordion-header-icon"),this._removeClass(s,null,n.icons.header)._addClass(s,null,n.icons.activeHeader)),this._addClass(a.next(),"ui-accordion-content-active")))},_toggle:function(e){var i=e.newPanel,s=this.prevShow.length?this.prevShow:e.oldPanel;this.prevShow.add(this.prevHide).stop(!0,!0),this.prevShow=i,this.prevHide=s,this.options.animate?this._animate(i,s,e):(s.hide(),i.show(),this._toggleComplete(e)),s.attr({"aria-hidden":"true"}),s.prev().attr({"aria-selected":"false","aria-expanded":"false"}),i.length&&s.length?s.prev().attr({tabIndex:-1,"aria-expanded":"false"}):i.length&&this.headers.filter(function(){return 0===parseInt(t(this).attr("tabIndex"),10)}).attr("tabIndex",-1),i.attr("aria-hidden","false").prev().attr({"aria-selected":"true","aria-expanded":"true",tabIndex:0})},_animate:function(t,e,i){var s,n,o,a=this,r=0,h=t.css("box-sizing"),l=t.length&&(!e.length||t.index()",delay:300,options:{icons:{submenu:"ui-icon-caret-1-e"},items:"> *",menus:"ul",position:{my:"left top",at:"right top"},role:"menu",blur:null,focus:null,select:null},_create:function(){this.activeMenu=this.element,this.mouseHandled=!1,this.element.uniqueId().attr({role:this.options.role,tabIndex:0}),this._addClass("ui-menu","ui-widget ui-widget-content"),this._on({"mousedown .ui-menu-item":function(t){t.preventDefault()},"click .ui-menu-item":function(e){var i=t(e.target),s=t(t.ui.safeActiveElement(this.document[0]));!this.mouseHandled&&i.not(".ui-state-disabled").length&&(this.select(e),e.isPropagationStopped()||(this.mouseHandled=!0),i.has(".ui-menu").length?this.expand(e):!this.element.is(":focus")&&s.closest(".ui-menu").length&&(this.element.trigger("focus",[!0]),this.active&&1===this.active.parents(".ui-menu").length&&clearTimeout(this.timer)))},"mouseenter .ui-menu-item":function(e){if(!this.previousFilter){var i=t(e.target).closest(".ui-menu-item"),s=t(e.currentTarget);i[0]===s[0]&&(this._removeClass(s.siblings().children(".ui-state-active"),null,"ui-state-active"),this.focus(e,s))}},mouseleave:"collapseAll","mouseleave .ui-menu":"collapseAll",focus:function(t,e){var i=this.active||this.element.find(this.options.items).eq(0);e||this.focus(t,i)},blur:function(e){this._delay(function(){var i=!t.contains(this.element[0],t.ui.safeActiveElement(this.document[0]));i&&this.collapseAll(e)})},keydown:"_keydown"}),this.refresh(),this._on(this.document,{click:function(t){this._closeOnDocumentClick(t)&&this.collapseAll(t),this.mouseHandled=!1}})},_destroy:function(){var e=this.element.find(".ui-menu-item").removeAttr("role aria-disabled"),i=e.children(".ui-menu-item-wrapper").removeUniqueId().removeAttr("tabIndex role aria-haspopup");this.element.removeAttr("aria-activedescendant").find(".ui-menu").addBack().removeAttr("role aria-labelledby aria-expanded aria-hidden aria-disabled tabIndex").removeUniqueId().show(),i.children().each(function(){var e=t(this);e.data("ui-menu-submenu-caret")&&e.remove()})},_keydown:function(e){var i,s,n,o,a=!0;switch(e.keyCode){case t.ui.keyCode.PAGE_UP:this.previousPage(e);break;case t.ui.keyCode.PAGE_DOWN:this.nextPage(e);break;case t.ui.keyCode.HOME:this._move("first","first",e);break;case t.ui.keyCode.END:this._move("last","last",e);break;case t.ui.keyCode.UP:this.previous(e);break;case t.ui.keyCode.DOWN:this.next(e);break;case t.ui.keyCode.LEFT:this.collapse(e);break;case t.ui.keyCode.RIGHT:this.active&&!this.active.is(".ui-state-disabled")&&this.expand(e);break;case t.ui.keyCode.ENTER:case t.ui.keyCode.SPACE:this._activate(e);break;case t.ui.keyCode.ESCAPE:this.collapse(e);break;default:a=!1,s=this.previousFilter||"",o=!1,n=e.keyCode>=96&&105>=e.keyCode?""+(e.keyCode-96):String.fromCharCode(e.keyCode),clearTimeout(this.filterTimer),n===s?o=!0:n=s+n,i=this._filterMenuItems(n),i=o&&-1!==i.index(this.active.next())?this.active.nextAll(".ui-menu-item"):i,i.length||(n=String.fromCharCode(e.keyCode),i=this._filterMenuItems(n)),i.length?(this.focus(e,i),this.previousFilter=n,this.filterTimer=this._delay(function(){delete this.previousFilter},1e3)):delete this.previousFilter}a&&e.preventDefault()},_activate:function(t){this.active&&!this.active.is(".ui-state-disabled")&&(this.active.children("[aria-haspopup='true']").length?this.expand(t):this.select(t))},refresh:function(){var e,i,s,n,o,a=this,r=this.options.icons.submenu,h=this.element.find(this.options.menus);this._toggleClass("ui-menu-icons",null,!!this.element.find(".ui-icon").length),s=h.filter(":not(.ui-menu)").hide().attr({role:this.options.role,"aria-hidden":"true","aria-expanded":"false"}).each(function(){var e=t(this),i=e.prev(),s=t("").data("ui-menu-submenu-caret",!0);a._addClass(s,"ui-menu-icon","ui-icon "+r),i.attr("aria-haspopup","true").prepend(s),e.attr("aria-labelledby",i.attr("id"))}),this._addClass(s,"ui-menu","ui-widget ui-widget-content ui-front"),e=h.add(this.element),i=e.find(this.options.items),i.not(".ui-menu-item").each(function(){var e=t(this);a._isDivider(e)&&a._addClass(e,"ui-menu-divider","ui-widget-content")}),n=i.not(".ui-menu-item, .ui-menu-divider"),o=n.children().not(".ui-menu").uniqueId().attr({tabIndex:-1,role:this._itemRole()}),this._addClass(n,"ui-menu-item")._addClass(o,"ui-menu-item-wrapper"),i.filter(".ui-state-disabled").attr("aria-disabled","true"),this.active&&!t.contains(this.element[0],this.active[0])&&this.blur()},_itemRole:function(){return{menu:"menuitem",listbox:"option"}[this.options.role]},_setOption:function(t,e){if("icons"===t){var i=this.element.find(".ui-menu-icon");this._removeClass(i,null,this.options.icons.submenu)._addClass(i,null,e.submenu)}this._super(t,e)},_setOptionDisabled:function(t){this._super(t),this.element.attr("aria-disabled",t+""),this._toggleClass(null,"ui-state-disabled",!!t)},focus:function(t,e){var i,s,n;this.blur(t,t&&"focus"===t.type),this._scrollIntoView(e),this.active=e.first(),s=this.active.children(".ui-menu-item-wrapper"),this._addClass(s,null,"ui-state-active"),this.options.role&&this.element.attr("aria-activedescendant",s.attr("id")),n=this.active.parent().closest(".ui-menu-item").children(".ui-menu-item-wrapper"),this._addClass(n,null,"ui-state-active"),t&&"keydown"===t.type?this._close():this.timer=this._delay(function(){this._close()},this.delay),i=e.children(".ui-menu"),i.length&&t&&/^mouse/.test(t.type)&&this._startOpening(i),this.activeMenu=e.parent(),this._trigger("focus",t,{item:e})},_scrollIntoView:function(e){var i,s,n,o,a,r;this._hasScroll()&&(i=parseFloat(t.css(this.activeMenu[0],"borderTopWidth"))||0,s=parseFloat(t.css(this.activeMenu[0],"paddingTop"))||0,n=e.offset().top-this.activeMenu.offset().top-i-s,o=this.activeMenu.scrollTop(),a=this.activeMenu.height(),r=e.outerHeight(),0>n?this.activeMenu.scrollTop(o+n):n+r>a&&this.activeMenu.scrollTop(o+n-a+r))},blur:function(t,e){e||clearTimeout(this.timer),this.active&&(this._removeClass(this.active.children(".ui-menu-item-wrapper"),null,"ui-state-active"),this._trigger("blur",t,{item:this.active}),this.active=null)},_startOpening:function(t){clearTimeout(this.timer),"true"===t.attr("aria-hidden")&&(this.timer=this._delay(function(){this._close(),this._open(t)},this.delay))},_open:function(e){var i=t.extend({of:this.active},this.options.position);clearTimeout(this.timer),this.element.find(".ui-menu").not(e.parents(".ui-menu")).hide().attr("aria-hidden","true"),e.show().removeAttr("aria-hidden").attr("aria-expanded","true").position(i)},collapseAll:function(e,i){clearTimeout(this.timer),this.timer=this._delay(function(){var s=i?this.element:t(e&&e.target).closest(this.element.find(".ui-menu"));s.length||(s=this.element),this._close(s),this.blur(e),this._removeClass(s.find(".ui-state-active"),null,"ui-state-active"),this.activeMenu=s},this.delay)},_close:function(t){t||(t=this.active?this.active.parent():this.element),t.find(".ui-menu").hide().attr("aria-hidden","true").attr("aria-expanded","false")},_closeOnDocumentClick:function(e){return!t(e.target).closest(".ui-menu").length},_isDivider:function(t){return!/[^\-\u2014\u2013\s]/.test(t.text())},collapse:function(t){var e=this.active&&this.active.parent().closest(".ui-menu-item",this.element);e&&e.length&&(this._close(),this.focus(t,e))},expand:function(t){var e=this.active&&this.active.children(".ui-menu ").find(this.options.items).first();e&&e.length&&(this._open(e.parent()),this._delay(function(){this.focus(t,e)}))},next:function(t){this._move("next","first",t)},previous:function(t){this._move("prev","last",t)},isFirstItem:function(){return this.active&&!this.active.prevAll(".ui-menu-item").length},isLastItem:function(){return this.active&&!this.active.nextAll(".ui-menu-item").length},_move:function(t,e,i){var s;this.active&&(s="first"===t||"last"===t?this.active["first"===t?"prevAll":"nextAll"](".ui-menu-item").eq(-1):this.active[t+"All"](".ui-menu-item").eq(0)),s&&s.length&&this.active||(s=this.activeMenu.find(this.options.items)[e]()),this.focus(i,s)},nextPage:function(e){var i,s,n;return this.active?(this.isLastItem()||(this._hasScroll()?(s=this.active.offset().top,n=this.element.height(),this.active.nextAll(".ui-menu-item").each(function(){return i=t(this),0>i.offset().top-s-n}),this.focus(e,i)):this.focus(e,this.activeMenu.find(this.options.items)[this.active?"last":"first"]())),void 0):(this.next(e),void 0)},previousPage:function(e){var i,s,n;return this.active?(this.isFirstItem()||(this._hasScroll()?(s=this.active.offset().top,n=this.element.height(),this.active.prevAll(".ui-menu-item").each(function(){return i=t(this),i.offset().top-s+n>0}),this.focus(e,i)):this.focus(e,this.activeMenu.find(this.options.items).first())),void 0):(this.next(e),void 0)},_hasScroll:function(){return this.element.outerHeight()",options:{appendTo:null,autoFocus:!1,delay:300,minLength:1,position:{my:"left top",at:"left bottom",collision:"none"},source:null,change:null,close:null,focus:null,open:null,response:null,search:null,select:null},requestIndex:0,pending:0,_create:function(){var e,i,s,n=this.element[0].nodeName.toLowerCase(),o="textarea"===n,a="input"===n; -this.isMultiLine=o||!a&&this._isContentEditable(this.element),this.valueMethod=this.element[o||a?"val":"text"],this.isNewMenu=!0,this._addClass("ui-autocomplete-input"),this.element.attr("autocomplete","off"),this._on(this.element,{keydown:function(n){if(this.element.prop("readOnly"))return e=!0,s=!0,i=!0,void 0;e=!1,s=!1,i=!1;var o=t.ui.keyCode;switch(n.keyCode){case o.PAGE_UP:e=!0,this._move("previousPage",n);break;case o.PAGE_DOWN:e=!0,this._move("nextPage",n);break;case o.UP:e=!0,this._keyEvent("previous",n);break;case o.DOWN:e=!0,this._keyEvent("next",n);break;case o.ENTER:this.menu.active&&(e=!0,n.preventDefault(),this.menu.select(n));break;case o.TAB:this.menu.active&&this.menu.select(n);break;case o.ESCAPE:this.menu.element.is(":visible")&&(this.isMultiLine||this._value(this.term),this.close(n),n.preventDefault());break;default:i=!0,this._searchTimeout(n)}},keypress:function(s){if(e)return e=!1,(!this.isMultiLine||this.menu.element.is(":visible"))&&s.preventDefault(),void 0;if(!i){var n=t.ui.keyCode;switch(s.keyCode){case n.PAGE_UP:this._move("previousPage",s);break;case n.PAGE_DOWN:this._move("nextPage",s);break;case n.UP:this._keyEvent("previous",s);break;case n.DOWN:this._keyEvent("next",s)}}},input:function(t){return s?(s=!1,t.preventDefault(),void 0):(this._searchTimeout(t),void 0)},focus:function(){this.selectedItem=null,this.previous=this._value()},blur:function(t){return this.cancelBlur?(delete this.cancelBlur,void 0):(clearTimeout(this.searching),this.close(t),this._change(t),void 0)}}),this._initSource(),this.menu=t("
public class TypeFinderConfig : ITypeFinderConfig { - private readonly ITypeFinderSettings _settings; + private readonly TypeFinderSettings _settings; private IEnumerable _assembliesAcceptingLoadExceptions; - public TypeFinderConfig(ITypeFinderSettings settings) + public TypeFinderConfig(TypeFinderSettings settings) { _settings = settings; } diff --git a/src/Umbraco.Core/ConfigConnectionStringExtensions.cs b/src/Umbraco.Core/ConfigConnectionStringExtensions.cs index 693b8a433e..8047af88c5 100644 --- a/src/Umbraco.Core/ConfigConnectionStringExtensions.cs +++ b/src/Umbraco.Core/ConfigConnectionStringExtensions.cs @@ -5,7 +5,6 @@ using Umbraco.Core.Configuration; namespace Umbraco.Core { - public static class ConfigConnectionStringExtensions { public static bool IsConnectionStringConfigured(this ConfigConnectionString databaseSettings) diff --git a/src/Umbraco.Core/Configuration/GlobalSettingsExtensions.cs b/src/Umbraco.Core/Configuration/GlobalSettingsExtensions.cs index a9a7f578d0..f9b2362e14 100644 --- a/src/Umbraco.Core/Configuration/GlobalSettingsExtensions.cs +++ b/src/Umbraco.Core/Configuration/GlobalSettingsExtensions.cs @@ -1,4 +1,5 @@ using System; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Hosting; namespace Umbraco.Core.Configuration @@ -14,7 +15,7 @@ namespace Umbraco.Core.Configuration /// /// /// - public static string GetBackOfficePath(this IGlobalSettings globalSettings, IHostingEnvironment hostingEnvironment) + public static string GetBackOfficePath(this GlobalSettings globalSettings, IHostingEnvironment hostingEnvironment) { if (_backOfficePath != null) return _backOfficePath; _backOfficePath = hostingEnvironment.ToAbsolute(globalSettings.UmbracoPath); @@ -32,7 +33,7 @@ namespace Umbraco.Core.Configuration /// We also make sure that the virtual directory (SystemDirectories.Root) is stripped off first, otherwise we'd end up with something /// like "MyVirtualDirectory-Umbraco" instead of just "Umbraco". /// - public static string GetUmbracoMvcArea(this IGlobalSettings globalSettings, IHostingEnvironment hostingEnvironment) + public static string GetUmbracoMvcArea(this GlobalSettings globalSettings, IHostingEnvironment hostingEnvironment) { if (_mvcArea != null) return _mvcArea; @@ -41,7 +42,7 @@ namespace Umbraco.Core.Configuration return _mvcArea; } - internal static string GetUmbracoMvcAreaNoCache(this IGlobalSettings globalSettings, IHostingEnvironment hostingEnvironment) + internal static string GetUmbracoMvcAreaNoCache(this GlobalSettings globalSettings, IHostingEnvironment hostingEnvironment) { var path = string.IsNullOrEmpty(globalSettings.UmbracoPath) ? string.Empty diff --git a/src/Umbraco.Configuration/Models/ConnectionStrings.cs b/src/Umbraco.Core/Configuration/Models/ConnectionStrings.cs similarity index 80% rename from src/Umbraco.Configuration/Models/ConnectionStrings.cs rename to src/Umbraco.Core/Configuration/Models/ConnectionStrings.cs index 586765714c..9d038ed17c 100644 --- a/src/Umbraco.Configuration/Models/ConnectionStrings.cs +++ b/src/Umbraco.Core/Configuration/Models/ConnectionStrings.cs @@ -1,25 +1,27 @@ using System; +using System.Collections.Generic; using System.Data.Common; -using Microsoft.Extensions.Configuration; +using System.Text.Json.Serialization; using Umbraco.Core; using Umbraco.Core.Configuration; namespace Umbraco.Configuration.Models { - public class ConnectionStrings : IConnectionStrings + public class ConnectionStrings { - private readonly IConfiguration _configuration; + [JsonPropertyName(Constants.System.UmbracoConnectionName)] + public string UmbracoConnectionString { get; set; } - public ConnectionStrings(IConfiguration configuration) - { - _configuration = configuration; - } + private Dictionary AsDictionary() => new Dictionary + { + { Constants.System.UmbracoConnectionName, UmbracoConnectionString } + }; public ConfigConnectionString this[string key] { get { - var connectionString = _configuration.GetConnectionString(key); + var connectionString = this.AsDictionary()[key]; var provider = ParseProvider(connectionString); return new ConfigConnectionString(connectionString, provider, key); } diff --git a/src/Umbraco.Core/Configuration/ModelsBuilderConfigExtensions.cs b/src/Umbraco.Core/Configuration/ModelsBuilderConfigExtensions.cs index 3e3b116395..4117d904b9 100644 --- a/src/Umbraco.Core/Configuration/ModelsBuilderConfigExtensions.cs +++ b/src/Umbraco.Core/Configuration/ModelsBuilderConfigExtensions.cs @@ -1,5 +1,6 @@ using System.Configuration; using System.IO; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.IO; namespace Umbraco.Core.Configuration @@ -8,9 +9,8 @@ namespace Umbraco.Core.Configuration { private static string _modelsDirectoryAbsolute = null; - public static string ModelsDirectoryAbsolute(this IModelsBuilderConfig modelsBuilderConfig, IIOHelper ioHelper) + public static string ModelsDirectoryAbsolute(this ModelsBuilderConfig modelsBuilderConfig, IIOHelper ioHelper) { - if (_modelsDirectoryAbsolute is null) { var modelsDirectory = modelsBuilderConfig.ModelsDirectory; diff --git a/src/Umbraco.Core/Configuration/UmbracoVersion.cs b/src/Umbraco.Core/Configuration/UmbracoVersion.cs index 0ddac4a8bd..3ae59189fa 100644 --- a/src/Umbraco.Core/Configuration/UmbracoVersion.cs +++ b/src/Umbraco.Core/Configuration/UmbracoVersion.cs @@ -1,7 +1,7 @@ using System; -using System.Configuration; using System.Reflection; using Semver; +using Umbraco.Core.Configuration.Models; namespace Umbraco.Core.Configuration { @@ -10,10 +10,10 @@ namespace Umbraco.Core.Configuration ///
public class UmbracoVersion : IUmbracoVersion { - private readonly IGlobalSettings _globalSettings; + private readonly GlobalSettings _globalSettings; - public UmbracoVersion(IGlobalSettings globalSettings) - : this() + public UmbracoVersion(GlobalSettings globalSettings) + : this() { _globalSettings = globalSettings; } diff --git a/src/Umbraco.Core/IO/IOHelper.cs b/src/Umbraco.Core/IO/IOHelper.cs index a8a34e2e93..3885930031 100644 --- a/src/Umbraco.Core/IO/IOHelper.cs +++ b/src/Umbraco.Core/IO/IOHelper.cs @@ -14,7 +14,7 @@ namespace Umbraco.Core.IO { private readonly IHostingEnvironment _hostingEnvironment; - public IOHelper(IHostingEnvironment hostingEnvironment, IGlobalSettings globalSettings) + public IOHelper(IHostingEnvironment hostingEnvironment) { _hostingEnvironment = hostingEnvironment ?? throw new ArgumentNullException(nameof(hostingEnvironment)); } diff --git a/src/Umbraco.Core/Models/Language.cs b/src/Umbraco.Core/Models/Language.cs index e83c59443d..0ac8526181 100644 --- a/src/Umbraco.Core/Models/Language.cs +++ b/src/Umbraco.Core/Models/Language.cs @@ -3,6 +3,7 @@ using System.Globalization; using System.Runtime.Serialization; using System.Threading; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Models.Entities; namespace Umbraco.Core.Models @@ -14,7 +15,7 @@ namespace Umbraco.Core.Models [DataContract(IsReference = true)] public class Language : EntityBase, ILanguage { - private readonly IGlobalSettings _globalSettings; + private readonly GlobalSettings _globalSettings; private string _isoCode; private string _cultureName; @@ -22,7 +23,7 @@ namespace Umbraco.Core.Models private bool _mandatory; private int? _fallbackLanguageId; - public Language(IGlobalSettings globalSettings, string isoCode) + public Language(GlobalSettings globalSettings, string isoCode) { IsoCode = isoCode; _globalSettings = globalSettings; diff --git a/src/Umbraco.Core/Models/Membership/User.cs b/src/Umbraco.Core/Models/Membership/User.cs index 43cedec951..7599997750 100644 --- a/src/Umbraco.Core/Models/Membership/User.cs +++ b/src/Umbraco.Core/Models/Membership/User.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Runtime.Serialization; using Umbraco.Core.Composing; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Models.Entities; namespace Umbraco.Core.Models.Membership @@ -18,7 +19,7 @@ namespace Umbraco.Core.Models.Membership /// /// Constructor for creating a new/empty user /// - public User(IGlobalSettings globalSettings) + public User(GlobalSettings globalSettings) { SessionTimeout = 60; _userGroups = new HashSet(); @@ -38,7 +39,7 @@ namespace Umbraco.Core.Models.Membership /// /// /// - public User(IGlobalSettings globalSettings, string name, string email, string username, string rawPasswordValue) + public User(GlobalSettings globalSettings, string name, string email, string username, string rawPasswordValue) : this(globalSettings) { if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException("Value cannot be null or whitespace.", nameof(name)); @@ -69,7 +70,7 @@ namespace Umbraco.Core.Models.Membership /// /// /// - public User(IGlobalSettings globalSettings, int id, string name, string email, string username, + public User(GlobalSettings globalSettings, int id, string name, string email, string username, string rawPasswordValue, string passwordConfig, IEnumerable userGroups, int[] startContentIds, int[] startMediaIds) : this(globalSettings) diff --git a/src/Umbraco.Core/Models/UmbracoUserExtensions.cs b/src/Umbraco.Core/Models/UmbracoUserExtensions.cs index 6ed3e6279b..18684f7946 100644 --- a/src/Umbraco.Core/Models/UmbracoUserExtensions.cs +++ b/src/Umbraco.Core/Models/UmbracoUserExtensions.cs @@ -4,6 +4,7 @@ using System.Globalization; using System.Linq; using System.Text; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Models.Membership; using Umbraco.Core.Services; @@ -48,14 +49,14 @@ namespace Umbraco.Core.Models /// /// /// - public static CultureInfo GetUserCulture(this IUser user, ILocalizedTextService textService, IGlobalSettings globalSettings) + public static CultureInfo GetUserCulture(this IUser user, ILocalizedTextService textService, GlobalSettings globalSettings) { if (user == null) throw new ArgumentNullException(nameof(user)); if (textService == null) throw new ArgumentNullException(nameof(textService)); return GetUserCulture(user.Language, textService, globalSettings); } - public static CultureInfo GetUserCulture(string userLanguage, ILocalizedTextService textService, IGlobalSettings globalSettings) + public static CultureInfo GetUserCulture(string userLanguage, ILocalizedTextService textService, GlobalSettings globalSettings) { try { diff --git a/src/Umbraco.Core/Packaging/PackagesRepository.cs b/src/Umbraco.Core/Packaging/PackagesRepository.cs index 0764378b06..b73747fab8 100644 --- a/src/Umbraco.Core/Packaging/PackagesRepository.cs +++ b/src/Umbraco.Core/Packaging/PackagesRepository.cs @@ -5,7 +5,9 @@ using System.IO; using System.IO.Compression; using System.Linq; using System.Xml.Linq; +using Microsoft.Extensions.Options; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Hosting; using Umbraco.Core.IO; using Umbraco.Core.Logging; @@ -61,7 +63,7 @@ namespace Umbraco.Core.Packaging IHostingEnvironment hostingEnvironment, IEntityXmlSerializer serializer, ILogger logger, IUmbracoVersion umbracoVersion, - IGlobalSettings globalSettings, + IOptionsSnapshot globalSettings, string packageRepositoryFileName, string tempFolderPath = null, string packagesFolderPath = null, string mediaFolderPath = null) { @@ -79,7 +81,7 @@ namespace Umbraco.Core.Packaging _tempFolderPath = tempFolderPath ?? Constants.SystemDirectories.TempData.EnsureEndsWith('/') + "PackageFiles"; _packagesFolderPath = packagesFolderPath ?? Constants.SystemDirectories.Packages; - _mediaFolderPath = mediaFolderPath ?? globalSettings.UmbracoMediaPath + "/created-packages"; + _mediaFolderPath = mediaFolderPath ?? globalSettings.Value.UmbracoMediaPath + "/created-packages"; _parser = new PackageDefinitionXmlParser(logger, umbracoVersion); _umbracoVersion = umbracoVersion; diff --git a/src/Umbraco.Core/PublishedContentExtensions.cs b/src/Umbraco.Core/PublishedContentExtensions.cs index 03ce0c066a..62f48917c3 100644 --- a/src/Umbraco.Core/PublishedContentExtensions.cs +++ b/src/Umbraco.Core/PublishedContentExtensions.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using Umbraco.Composing; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Services; @@ -149,7 +150,7 @@ namespace Umbraco.Core } public static bool IsAllowedTemplate(this IPublishedContent content, IContentTypeService contentTypeService, - IWebRoutingSettings webRoutingSettings, int templateId) + WebRoutingSettings webRoutingSettings, int templateId) { return content.IsAllowedTemplate(contentTypeService, webRoutingSettings.DisableAlternativeTemplates, diff --git a/src/Umbraco.Core/Routing/ContentFinderByIdPath.cs b/src/Umbraco.Core/Routing/ContentFinderByIdPath.cs index 4b58832e8e..3d69f8ab46 100644 --- a/src/Umbraco.Core/Routing/ContentFinderByIdPath.cs +++ b/src/Umbraco.Core/Routing/ContentFinderByIdPath.cs @@ -4,6 +4,8 @@ using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Models.PublishedContent; using System.Globalization; +using Umbraco.Core.Configuration.Models; +using Microsoft.Extensions.Options; namespace Umbraco.Web.Routing { @@ -17,11 +19,11 @@ namespace Umbraco.Web.Routing { private readonly ILogger _logger; private readonly IRequestAccessor _requestAccessor; - private readonly IWebRoutingSettings _webRoutingSettings; + private readonly WebRoutingSettings _webRoutingSettings; - public ContentFinderByIdPath(IWebRoutingSettings webRoutingSettings, ILogger logger, IRequestAccessor requestAccessor) + public ContentFinderByIdPath(IOptionsSnapshot webRoutingSettings, ILogger logger, IRequestAccessor requestAccessor) { - _webRoutingSettings = webRoutingSettings ?? throw new System.ArgumentNullException(nameof(webRoutingSettings)); + _webRoutingSettings = webRoutingSettings.Value ?? throw new System.ArgumentNullException(nameof(webRoutingSettings)); _logger = logger ?? throw new System.ArgumentNullException(nameof(logger)); _requestAccessor = requestAccessor; } diff --git a/src/Umbraco.Core/Routing/ContentFinderByUrlAndTemplate.cs b/src/Umbraco.Core/Routing/ContentFinderByUrlAndTemplate.cs index 7bcea4681e..47dc729654 100644 --- a/src/Umbraco.Core/Routing/ContentFinderByUrlAndTemplate.cs +++ b/src/Umbraco.Core/Routing/ContentFinderByUrlAndTemplate.cs @@ -3,6 +3,8 @@ using Umbraco.Core; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Services; +using Umbraco.Core.Configuration.Models; +using Microsoft.Extensions.Options; namespace Umbraco.Web.Routing { @@ -19,14 +21,14 @@ namespace Umbraco.Web.Routing private readonly IFileService _fileService; private readonly IContentTypeService _contentTypeService; - private readonly IWebRoutingSettings _webRoutingSettings; + private readonly WebRoutingSettings _webRoutingSettings; - public ContentFinderByUrlAndTemplate(ILogger logger, IFileService fileService, IContentTypeService contentTypeService, IWebRoutingSettings webRoutingSettings) + public ContentFinderByUrlAndTemplate(ILogger logger, IFileService fileService, IContentTypeService contentTypeService, IOptionsSnapshot webRoutingSettings) : base(logger) { _fileService = fileService; _contentTypeService = contentTypeService; - _webRoutingSettings = webRoutingSettings; + _webRoutingSettings = webRoutingSettings.Value; } /// diff --git a/src/Umbraco.Core/Routing/PublishedRequest.cs b/src/Umbraco.Core/Routing/PublishedRequest.cs index a46eb26e7e..24bad199a5 100644 --- a/src/Umbraco.Core/Routing/PublishedRequest.cs +++ b/src/Umbraco.Core/Routing/PublishedRequest.cs @@ -5,6 +5,8 @@ using System.Threading; using Umbraco.Core.Models; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Configuration.UmbracoSettings; +using Umbraco.Core.Configuration.Models; +using Microsoft.Extensions.Options; namespace Umbraco.Web.Routing { @@ -16,7 +18,7 @@ namespace Umbraco.Web.Routing public class PublishedRequest : IPublishedRequest { private readonly IPublishedRouter _publishedRouter; - private readonly IWebRoutingSettings _webRoutingSettings; + private readonly WebRoutingSettings _webRoutingSettings; private bool _readonly; // after prepared private bool _readonlyUri; // after preparing @@ -33,11 +35,11 @@ namespace Umbraco.Web.Routing /// The published router. /// The Umbraco context. /// The request Uri. - public PublishedRequest(IPublishedRouter publishedRouter, IUmbracoContext umbracoContext, IWebRoutingSettings webRoutingSettings, Uri uri = null) + public PublishedRequest(IPublishedRouter publishedRouter, IUmbracoContext umbracoContext, IOptionsSnapshot webRoutingSettings, Uri uri = null) { UmbracoContext = umbracoContext ?? throw new ArgumentNullException(nameof(umbracoContext)); _publishedRouter = publishedRouter ?? throw new ArgumentNullException(nameof(publishedRouter)); - _webRoutingSettings = webRoutingSettings; + _webRoutingSettings = webRoutingSettings.Value; Uri = uri ?? umbracoContext.CleanedUmbracoUrl; } diff --git a/src/Umbraco.Core/Routing/PublishedRouter.cs b/src/Umbraco.Core/Routing/PublishedRouter.cs index 1a422dea92..d77f64ca5e 100644 --- a/src/Umbraco.Core/Routing/PublishedRouter.cs +++ b/src/Umbraco.Core/Routing/PublishedRouter.cs @@ -10,6 +10,8 @@ using Umbraco.Core.Models; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Services; using Umbraco.Web.Security; +using Umbraco.Core.Configuration.Models; +using Microsoft.Extensions.Options; namespace Umbraco.Web.Routing { @@ -18,7 +20,7 @@ namespace Umbraco.Web.Routing /// public class PublishedRouter : IPublishedRouter { - private readonly IWebRoutingSettings _webRoutingSettings; + private readonly WebRoutingSettings _webRoutingSettings; private readonly ContentFinderCollection _contentFinders; private readonly IContentLastChanceFinder _contentLastChanceFinder; private readonly IProfilingLogger _profilingLogger; @@ -36,7 +38,7 @@ namespace Umbraco.Web.Routing /// Initializes a new instance of the class. ///
public PublishedRouter( - IWebRoutingSettings webRoutingSettings, + IOptionsSnapshot webRoutingSettings, ContentFinderCollection contentFinders, IContentLastChanceFinder contentLastChanceFinder, IVariationContextAccessor variationContextAccessor, @@ -49,7 +51,7 @@ namespace Umbraco.Web.Routing IContentTypeService contentTypeService, IPublicAccessService publicAccessService) { - _webRoutingSettings = webRoutingSettings ?? throw new ArgumentNullException(nameof(webRoutingSettings)); + _webRoutingSettings = webRoutingSettings.Value ?? throw new ArgumentNullException(nameof(webRoutingSettings)); _contentFinders = contentFinders ?? throw new ArgumentNullException(nameof(contentFinders)); _contentLastChanceFinder = contentLastChanceFinder ?? throw new ArgumentNullException(nameof(contentLastChanceFinder)); _profilingLogger = proflog ?? throw new ArgumentNullException(nameof(proflog)); diff --git a/src/Umbraco.Core/Routing/UrlProvider.cs b/src/Umbraco.Core/Routing/UrlProvider.cs index fa764cf7ff..9e1dd9a01d 100644 --- a/src/Umbraco.Core/Routing/UrlProvider.cs +++ b/src/Umbraco.Core/Routing/UrlProvider.cs @@ -4,6 +4,8 @@ using System.Linq; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core; using Umbraco.Core.Models.PublishedContent; +using Umbraco.Core.Configuration.Models; +using Microsoft.Extensions.Options; namespace Umbraco.Web.Routing { @@ -24,7 +26,7 @@ namespace Umbraco.Web.Routing /// The list of media url providers. /// The current variation accessor. /// - public UrlProvider(IUmbracoContextAccessor umbracoContextAccessor, IWebRoutingSettings routingSettings, UrlProviderCollection urlProviders, MediaUrlProviderCollection mediaUrlProviders, IVariationContextAccessor variationContextAccessor) + public UrlProvider(IUmbracoContextAccessor umbracoContextAccessor, IOptionsSnapshot routingSettings, UrlProviderCollection urlProviders, MediaUrlProviderCollection mediaUrlProviders, IVariationContextAccessor variationContextAccessor) { if (routingSettings == null) throw new ArgumentNullException(nameof(routingSettings)); @@ -35,7 +37,7 @@ namespace Umbraco.Web.Routing var provider = UrlMode.Auto; Mode = provider; - if (Enum.TryParse(routingSettings.UrlProviderMode, out provider)) + if (Enum.TryParse(routingSettings.Value.UrlProviderMode, out provider)) { Mode = provider; } diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 3b7ccb1775..067b26e0f0 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -27,6 +27,9 @@ <_Parameter1>Umbraco.Tests + + <_Parameter1>Umbraco.Tests.Common + <_Parameter1>Umbraco.Tests.UnitTests diff --git a/src/Umbraco.Core/UriExtensions.cs b/src/Umbraco.Core/UriExtensions.cs index 13aa6bde46..9a49df7d95 100644 --- a/src/Umbraco.Core/UriExtensions.cs +++ b/src/Umbraco.Core/UriExtensions.cs @@ -3,8 +3,8 @@ using System.IO; using System.Linq; using Umbraco.Composing; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Hosting; -using Umbraco.Core.IO; namespace Umbraco.Core { @@ -38,7 +38,7 @@ namespace Umbraco.Core /// But if we've got this far we'll just have to assume it's front-end anyways. /// /// - public static bool IsBackOfficeRequest(this Uri url, IGlobalSettings globalSettings, IHostingEnvironment hostingEnvironment) + public static bool IsBackOfficeRequest(this Uri url, GlobalSettings globalSettings, IHostingEnvironment hostingEnvironment) { var applicationPath = hostingEnvironment.ApplicationVirtualPath; @@ -128,7 +128,7 @@ namespace Umbraco.Core /// /// /// - internal static bool IsDefaultBackOfficeRequest(this Uri url, IGlobalSettings globalSettings, IHostingEnvironment hostingEnvironment) + internal static bool IsDefaultBackOfficeRequest(this Uri url, GlobalSettings globalSettings, IHostingEnvironment hostingEnvironment) { var backOfficePath = globalSettings.GetBackOfficePath(hostingEnvironment); if (url.AbsolutePath.InvariantEquals(backOfficePath.TrimEnd("/")) diff --git a/src/Umbraco.Examine.Lucene/LuceneIndexCreator.cs b/src/Umbraco.Examine.Lucene/LuceneIndexCreator.cs index 9efcdc4891..6edbb05b85 100644 --- a/src/Umbraco.Examine.Lucene/LuceneIndexCreator.cs +++ b/src/Umbraco.Examine.Lucene/LuceneIndexCreator.cs @@ -4,11 +4,11 @@ using System.IO; using Examine; using Examine.LuceneEngine.Directories; using Lucene.Net.Store; -using Umbraco.Core.Configuration; +using Microsoft.Extensions.Options; using Umbraco.Core; using Umbraco.Core.Composing; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Hosting; -using Umbraco.Core.IO; namespace Umbraco.Examine { @@ -20,13 +20,13 @@ namespace Umbraco.Examine { private readonly ITypeFinder _typeFinder; private readonly IHostingEnvironment _hostingEnvironment; - private readonly IIndexCreatorSettings _settings; + private readonly IndexCreatorSettings _settings; - protected LuceneIndexCreator(ITypeFinder typeFinder, IHostingEnvironment hostingEnvironment, IIndexCreatorSettings settings) + protected LuceneIndexCreator(ITypeFinder typeFinder, IHostingEnvironment hostingEnvironment, IOptionsSnapshot settings) { _typeFinder = typeFinder; _hostingEnvironment = hostingEnvironment; - _settings = settings; + _settings = settings.Value; } public abstract IEnumerable Create(); diff --git a/src/Umbraco.Examine.Lucene/UmbracoIndexesCreator.cs b/src/Umbraco.Examine.Lucene/UmbracoIndexesCreator.cs index 3cf7d6d386..09dc40b32b 100644 --- a/src/Umbraco.Examine.Lucene/UmbracoIndexesCreator.cs +++ b/src/Umbraco.Examine.Lucene/UmbracoIndexesCreator.cs @@ -9,6 +9,8 @@ using Umbraco.Core; using Umbraco.Core.Composing; using Umbraco.Core.Hosting; using Umbraco.Core.IO; +using Umbraco.Core.Configuration.Models; +using Microsoft.Extensions.Options; namespace Umbraco.Examine { @@ -28,7 +30,7 @@ namespace Umbraco.Examine IUmbracoIndexConfig umbracoIndexConfig, IHostingEnvironment hostingEnvironment, IRuntimeState runtimeState, - IIndexCreatorSettings settings) : base(typeFinder, hostingEnvironment, settings) + IOptionsSnapshot settings) : base(typeFinder, hostingEnvironment, settings) { ProfilingLogger = profilingLogger ?? throw new System.ArgumentNullException(nameof(profilingLogger)); LanguageService = languageService ?? throw new System.ArgumentNullException(nameof(languageService)); diff --git a/src/Umbraco.Infrastructure/BackOffice/BackOfficeUserStore.cs b/src/Umbraco.Infrastructure/BackOffice/BackOfficeUserStore.cs index 96b3d8559a..7c2eb1adfd 100644 --- a/src/Umbraco.Infrastructure/BackOffice/BackOfficeUserStore.cs +++ b/src/Umbraco.Infrastructure/BackOffice/BackOfficeUserStore.cs @@ -5,7 +5,9 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Identity; +using Microsoft.Extensions.Options; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Mapping; using Umbraco.Core.Models; using Umbraco.Core.Models.Identity; @@ -32,11 +34,16 @@ namespace Umbraco.Core.BackOffice private readonly IUserService _userService; private readonly IEntityService _entityService; private readonly IExternalLoginService _externalLoginService; - private readonly IGlobalSettings _globalSettings; + private readonly GlobalSettings _globalSettings; private readonly UmbracoMapper _mapper; private bool _disposed = false; - public BackOfficeUserStore(IUserService userService, IEntityService entityService, IExternalLoginService externalLoginService, IGlobalSettings globalSettings, UmbracoMapper mapper) + public BackOfficeUserStore(IUserService userService, IEntityService entityService, IExternalLoginService externalLoginService, IOptionsSnapshot globalSettings, UmbracoMapper mapper) + : this(userService, entityService, externalLoginService, globalSettings.Value, mapper) + { + } + + public BackOfficeUserStore(IUserService userService, IEntityService entityService, IExternalLoginService externalLoginService, GlobalSettings globalSettings, UmbracoMapper mapper) { _userService = userService; _entityService = entityService; diff --git a/src/Umbraco.Infrastructure/Compose/NotificationsComponent.cs b/src/Umbraco.Infrastructure/Compose/NotificationsComponent.cs index 3a4b8a5fac..c725826fd7 100644 --- a/src/Umbraco.Infrastructure/Compose/NotificationsComponent.cs +++ b/src/Umbraco.Infrastructure/Compose/NotificationsComponent.cs @@ -2,9 +2,11 @@ using System.Collections.Generic; using System.Globalization; using System.Linq; +using Microsoft.Extensions.Options; using Umbraco.Core; using Umbraco.Core.Composing; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Logging; using Umbraco.Core.Models; @@ -153,7 +155,7 @@ namespace Umbraco.Web.Compose private readonly INotificationService _notificationService; private readonly IUserService _userService; private readonly ILocalizedTextService _textService; - private readonly IGlobalSettings _globalSettings; + private readonly GlobalSettings _globalSettings; private readonly ILogger _logger; /// @@ -166,14 +168,21 @@ namespace Umbraco.Web.Compose /// /// /// - public Notifier(IUmbracoContextAccessor umbracoContextAccessor, IRequestAccessor requestAccessor, INotificationService notificationService, IUserService userService, ILocalizedTextService textService, IGlobalSettings globalSettings, ILogger logger) + public Notifier( + IUmbracoContextAccessor umbracoContextAccessor, + IRequestAccessor requestAccessor, + INotificationService notificationService, + IUserService userService, + ILocalizedTextService textService, + IOptionsSnapshot globalSettings, + ILogger logger) { _umbracoContextAccessor = umbracoContextAccessor; _requestAccessor = requestAccessor; _notificationService = notificationService; _userService = userService; _textService = textService; - _globalSettings = globalSettings; + _globalSettings = globalSettings.Value; _logger = logger; } diff --git a/src/Umbraco.Infrastructure/Composing/CompositionExtensions/FileSystems.cs b/src/Umbraco.Infrastructure/Composing/CompositionExtensions/FileSystems.cs index 9dc130fcba..fec14bfbd2 100644 --- a/src/Umbraco.Infrastructure/Composing/CompositionExtensions/FileSystems.cs +++ b/src/Umbraco.Infrastructure/Composing/CompositionExtensions/FileSystems.cs @@ -1,4 +1,6 @@ -using Umbraco.Core.Configuration; +using Microsoft.Extensions.Options; +using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Hosting; using Umbraco.Core.IO; using Umbraco.Core.IO.MediaPathSchemes; @@ -97,7 +99,7 @@ namespace Umbraco.Core.Composing.CompositionExtensions var ioHelper = factory.GetInstance(); var hostingEnvironment = factory.GetInstance(); var logger = factory.GetInstance(); - var globalSettings = factory.GetInstance(); + var globalSettings = factory.GetInstance>().Value; var rootPath = hostingEnvironment.MapPathWebRoot(globalSettings.UmbracoMediaPath); var rootUrl = hostingEnvironment.ToAbsolute(globalSettings.UmbracoMediaPath); diff --git a/src/Umbraco.Infrastructure/Composing/CompositionExtensions/Services.cs b/src/Umbraco.Infrastructure/Composing/CompositionExtensions/Services.cs index 980dd1c11e..dd4db120ce 100644 --- a/src/Umbraco.Infrastructure/Composing/CompositionExtensions/Services.cs +++ b/src/Umbraco.Infrastructure/Composing/CompositionExtensions/Services.cs @@ -1,8 +1,10 @@ using System; using System.IO; using System.Linq; +using Microsoft.Extensions.Options; using Umbraco.Core.Cache; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Events; using Umbraco.Core.Hosting; using Umbraco.Core.IO; @@ -94,13 +96,13 @@ namespace Umbraco.Core.Composing.CompositionExtensions factory.GetInstance(), factory.GetInstance(), factory.GetInstance(), - factory.GetInstance(), + factory.GetInstance>(), packageRepoFileName); private static LocalizedTextServiceFileSources SourcesFactory(IFactory container) { var hostingEnvironment = container.GetInstance(); - var globalSettings = container.GetInstance(); + var globalSettings = container.GetInstance>().Value; var mainLangFolder = new DirectoryInfo(hostingEnvironment.MapPathContentRoot(WebPath.Combine(globalSettings.UmbracoPath , "config","lang"))); var appPlugins = new DirectoryInfo(hostingEnvironment.MapPathContentRoot(Constants.SystemDirectories.AppPlugins)); var configLangFolder = new DirectoryInfo(hostingEnvironment.MapPathContentRoot(WebPath.Combine(Constants.SystemDirectories.Config ,"lang"))); diff --git a/src/Umbraco.Infrastructure/Composing/RegisterFactory.cs b/src/Umbraco.Infrastructure/Composing/RegisterFactory.cs index 835bd0b9a8..d6c0e74d75 100644 --- a/src/Umbraco.Infrastructure/Composing/RegisterFactory.cs +++ b/src/Umbraco.Infrastructure/Composing/RegisterFactory.cs @@ -6,6 +6,7 @@ using System; using System.Reflection; using Umbraco.Core.Composing.LightInject; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; namespace Umbraco.Core.Composing { @@ -29,7 +30,7 @@ namespace Umbraco.Core.Composing /// To override the default LightInjectContainer, add an appSetting named 'Umbraco.Core.RegisterType' with /// a fully qualified type name to a class with a static method "Create" returning an IRegister. /// - public static IRegister Create(IGlobalSettings globalSettings) + public static IRegister Create(GlobalSettings globalSettings) { Type type; diff --git a/src/Umbraco.Infrastructure/HealthCheck/NotificationMethods/EmailNotificationMethod.cs b/src/Umbraco.Infrastructure/HealthCheck/NotificationMethods/EmailNotificationMethod.cs index 5ddf9aa288..96eee5f458 100644 --- a/src/Umbraco.Infrastructure/HealthCheck/NotificationMethods/EmailNotificationMethod.cs +++ b/src/Umbraco.Infrastructure/HealthCheck/NotificationMethods/EmailNotificationMethod.cs @@ -17,13 +17,13 @@ namespace Umbraco.Web.HealthCheck.NotificationMethods private readonly ILocalizedTextService _textService; private readonly IRequestAccessor _requestAccessor; - private readonly IGlobalSettings _globalSettings; + private readonly GlobalSettings _globalSettings; private readonly ContentSettings _contentSettings; public EmailNotificationMethod( ILocalizedTextService textService, IRequestAccessor requestAccessor, - IGlobalSettings globalSettings, + IOptionsSnapshot globalSettings, IHealthChecksSettings healthChecksSettings, IOptionsSnapshot contentSettings) : base(healthChecksSettings) @@ -39,7 +39,7 @@ namespace Umbraco.Web.HealthCheck.NotificationMethods _textService = textService ?? throw new ArgumentNullException(nameof(textService)); _requestAccessor = requestAccessor; - _globalSettings = globalSettings; + _globalSettings = globalSettings.Value; _contentSettings = contentSettings.Value ?? throw new ArgumentNullException(nameof(contentSettings)); } diff --git a/src/Umbraco.Infrastructure/Install/FilePermissionHelper.cs b/src/Umbraco.Infrastructure/Install/FilePermissionHelper.cs index 4c3edf0a1b..d5dc5307ab 100644 --- a/src/Umbraco.Infrastructure/Install/FilePermissionHelper.cs +++ b/src/Umbraco.Infrastructure/Install/FilePermissionHelper.cs @@ -8,6 +8,8 @@ using Umbraco.Core.Configuration; using Umbraco.Core.Install; using Umbraco.Core.IO; using Umbraco.Web.PublishedCache; +using Umbraco.Core.Configuration.Models; +using Microsoft.Extensions.Options; namespace Umbraco.Web.Install { @@ -19,13 +21,13 @@ namespace Umbraco.Web.Install // ensure Umbraco can write to these files (the directories must exist) private readonly string[] _permissionFiles = { }; - private readonly IGlobalSettings _globalSettings; + private readonly GlobalSettings _globalSettings; private readonly IIOHelper _ioHelper; private readonly IPublishedSnapshotService _publishedSnapshotService; - public FilePermissionHelper(IGlobalSettings globalSettings, IIOHelper ioHelper, IPublishedSnapshotService publishedSnapshotService) + public FilePermissionHelper(IOptionsSnapshot globalSettings, IIOHelper ioHelper, IPublishedSnapshotService publishedSnapshotService) { - _globalSettings = globalSettings; + _globalSettings = globalSettings.Value; _ioHelper = ioHelper; _publishedSnapshotService = publishedSnapshotService; _permissionDirs = new[] { _globalSettings.UmbracoCssPath, Constants.SystemDirectories.Config, Constants.SystemDirectories.Data, _globalSettings.UmbracoMediaPath, Constants.SystemDirectories.Preview }; diff --git a/src/Umbraco.Infrastructure/Install/InstallHelper.cs b/src/Umbraco.Infrastructure/Install/InstallHelper.cs index 1333363355..b9729f4e1b 100644 --- a/src/Umbraco.Infrastructure/Install/InstallHelper.cs +++ b/src/Umbraco.Infrastructure/Install/InstallHelper.cs @@ -13,6 +13,7 @@ using Umbraco.Core.Persistence; using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Web.Install.Models; +using Microsoft.Extensions.Options; namespace Umbraco.Web.Install { @@ -22,7 +23,7 @@ namespace Umbraco.Web.Install private readonly DatabaseBuilder _databaseBuilder; private readonly ILogger _logger; private readonly IUmbracoVersion _umbracoVersion; - private readonly IConnectionStrings _connectionStrings; + private readonly ConnectionStrings _connectionStrings; private readonly IInstallationService _installationService; private readonly ICookieManager _cookieManager; private readonly IUserAgentProvider _userAgentProvider; @@ -33,7 +34,7 @@ namespace Umbraco.Web.Install public InstallHelper(DatabaseBuilder databaseBuilder, ILogger logger, IUmbracoVersion umbracoVersion, - IConnectionStrings connectionStrings, + IOptionsSnapshot connectionStrings, IInstallationService installationService, ICookieManager cookieManager, IUserAgentProvider userAgentProvider, @@ -43,7 +44,7 @@ namespace Umbraco.Web.Install _logger = logger; _umbracoVersion = umbracoVersion; _databaseBuilder = databaseBuilder; - _connectionStrings = connectionStrings ?? throw new ArgumentNullException(nameof(connectionStrings)); + _connectionStrings = connectionStrings.Value ?? throw new ArgumentNullException(nameof(connectionStrings)); _installationService = installationService; _cookieManager = cookieManager; _userAgentProvider = userAgentProvider; diff --git a/src/Umbraco.Infrastructure/Install/InstallSteps/DatabaseConfigureStep.cs b/src/Umbraco.Infrastructure/Install/InstallSteps/DatabaseConfigureStep.cs index 0c88c7a096..0691f39e80 100644 --- a/src/Umbraco.Infrastructure/Install/InstallSteps/DatabaseConfigureStep.cs +++ b/src/Umbraco.Infrastructure/Install/InstallSteps/DatabaseConfigureStep.cs @@ -6,6 +6,7 @@ using Umbraco.Core.Logging; using Umbraco.Core.Migrations.Install; using Umbraco.Web.Install.Models; using Umbraco.Core.Configuration; +using Microsoft.Extensions.Options; namespace Umbraco.Web.Install.InstallSteps { @@ -16,12 +17,12 @@ namespace Umbraco.Web.Install.InstallSteps { private readonly DatabaseBuilder _databaseBuilder; private readonly ILogger _logger; - private readonly IConnectionStrings _connectionStrings; + private readonly ConnectionStrings _connectionStrings; - public DatabaseConfigureStep(DatabaseBuilder databaseBuilder, IConnectionStrings connectionStrings) + public DatabaseConfigureStep(DatabaseBuilder databaseBuilder, IOptionsSnapshot connectionStrings) { _databaseBuilder = databaseBuilder; - _connectionStrings = connectionStrings ?? throw new ArgumentNullException(nameof(connectionStrings)); + _connectionStrings = connectionStrings.Value ?? throw new ArgumentNullException(nameof(connectionStrings)); } public override Task ExecuteAsync(DatabaseModel database) diff --git a/src/Umbraco.Infrastructure/Install/InstallSteps/DatabaseInstallStep.cs b/src/Umbraco.Infrastructure/Install/InstallSteps/DatabaseInstallStep.cs index b3086672d8..e5f783caba 100644 --- a/src/Umbraco.Infrastructure/Install/InstallSteps/DatabaseInstallStep.cs +++ b/src/Umbraco.Infrastructure/Install/InstallSteps/DatabaseInstallStep.cs @@ -16,19 +16,11 @@ namespace Umbraco.Web.Install.InstallSteps { private readonly DatabaseBuilder _databaseBuilder; private readonly IRuntimeState _runtime; - private readonly ILogger _logger; - private readonly IIOHelper _ioHelper; - private readonly IConnectionStrings _connectionStrings; - private readonly IConfigManipulator _configManipulator; - public DatabaseInstallStep(DatabaseBuilder databaseBuilder, IRuntimeState runtime, ILogger logger, IIOHelper ioHelper, IConnectionStrings connectionStrings, IConfigManipulator configManipulator) + public DatabaseInstallStep(DatabaseBuilder databaseBuilder, IRuntimeState runtime) { _databaseBuilder = databaseBuilder; _runtime = runtime; - _logger = logger; - _ioHelper = ioHelper; - _connectionStrings = connectionStrings; - _configManipulator = configManipulator; } public override Task ExecuteAsync(object model) diff --git a/src/Umbraco.Infrastructure/Install/InstallSteps/DatabaseUpgradeStep.cs b/src/Umbraco.Infrastructure/Install/InstallSteps/DatabaseUpgradeStep.cs index dccf320787..44214d1b73 100644 --- a/src/Umbraco.Infrastructure/Install/InstallSteps/DatabaseUpgradeStep.cs +++ b/src/Umbraco.Infrastructure/Install/InstallSteps/DatabaseUpgradeStep.cs @@ -1,8 +1,10 @@ using System; using System.Linq; using System.Threading.Tasks; +using Microsoft.Extensions.Options; using Umbraco.Core; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Migrations.Install; @@ -20,8 +22,8 @@ namespace Umbraco.Web.Install.InstallSteps private readonly IRuntimeState _runtime; private readonly ILogger _logger; private readonly IUmbracoVersion _umbracoVersion; - private readonly IGlobalSettings _globalSettings; - private readonly IConnectionStrings _connectionStrings; + private readonly GlobalSettings _globalSettings; + private readonly ConnectionStrings _connectionStrings; private readonly IIOHelper _ioHelper; private readonly IConfigManipulator _configManipulator; @@ -30,8 +32,8 @@ namespace Umbraco.Web.Install.InstallSteps IRuntimeState runtime, ILogger logger, IUmbracoVersion umbracoVersion, - IGlobalSettings globalSettings, - IConnectionStrings connectionStrings, + IOptionsSnapshot globalSettings, + IOptionsSnapshot connectionStrings, IIOHelper ioHelper, IConfigManipulator configManipulator) { @@ -39,8 +41,8 @@ namespace Umbraco.Web.Install.InstallSteps _runtime = runtime; _logger = logger; _umbracoVersion = umbracoVersion; - _globalSettings = globalSettings; - _connectionStrings = connectionStrings ?? throw new ArgumentNullException(nameof(connectionStrings)); + _globalSettings = globalSettings.Value; + _connectionStrings = connectionStrings.Value ?? throw new ArgumentNullException(nameof(connectionStrings)); _ioHelper = ioHelper; _configManipulator = configManipulator; } diff --git a/src/Umbraco.Infrastructure/Install/InstallSteps/NewInstallStep.cs b/src/Umbraco.Infrastructure/Install/InstallSteps/NewInstallStep.cs index f3765493d9..a8a516199f 100644 --- a/src/Umbraco.Infrastructure/Install/InstallSteps/NewInstallStep.cs +++ b/src/Umbraco.Infrastructure/Install/InstallSteps/NewInstallStep.cs @@ -30,29 +30,26 @@ namespace Umbraco.Web.Install.InstallSteps private readonly IUserService _userService; private readonly DatabaseBuilder _databaseBuilder; private static HttpClient _httpClient; - private readonly IGlobalSettings _globalSettings; private readonly UserPasswordConfigurationSettings _passwordConfiguration; private readonly SecuritySettings _securitySettings; - private readonly IConnectionStrings _connectionStrings; + private readonly ConnectionStrings _connectionStrings; private readonly ICookieManager _cookieManager; private readonly BackOfficeUserManager _userManager; public NewInstallStep( IUserService userService, DatabaseBuilder databaseBuilder, - IGlobalSettings globalSettings, IOptionsSnapshot passwordConfiguration, IOptionsSnapshot securitySettings, - IConnectionStrings connectionStrings, + IOptionsSnapshot connectionStrings, ICookieManager cookieManager, BackOfficeUserManager userManager) { _userService = userService ?? throw new ArgumentNullException(nameof(userService)); _databaseBuilder = databaseBuilder ?? throw new ArgumentNullException(nameof(databaseBuilder)); - _globalSettings = globalSettings ?? throw new ArgumentNullException(nameof(globalSettings)); _passwordConfiguration = passwordConfiguration.Value ?? throw new ArgumentNullException(nameof(passwordConfiguration)); _securitySettings = securitySettings.Value ?? throw new ArgumentNullException(nameof(securitySettings)); - _connectionStrings = connectionStrings ?? throw new ArgumentNullException(nameof(connectionStrings)); + _connectionStrings = connectionStrings.Value ?? throw new ArgumentNullException(nameof(connectionStrings)); _cookieManager = cookieManager; _userManager = userManager ?? throw new ArgumentNullException(nameof(userManager)); } diff --git a/src/Umbraco.Infrastructure/Migrations/Install/DatabaseBuilder.cs b/src/Umbraco.Infrastructure/Migrations/Install/DatabaseBuilder.cs index 98d50d61b1..8bf8ceb33e 100644 --- a/src/Umbraco.Infrastructure/Migrations/Install/DatabaseBuilder.cs +++ b/src/Umbraco.Infrastructure/Migrations/Install/DatabaseBuilder.cs @@ -2,7 +2,9 @@ using System.IO; using System.Linq; using System.Xml.Linq; +using Microsoft.Extensions.Options; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Hosting; using Umbraco.Core.IO; using Umbraco.Core.Logging; @@ -21,7 +23,7 @@ namespace Umbraco.Core.Migrations.Install { private readonly IUmbracoDatabaseFactory _databaseFactory; private readonly IScopeProvider _scopeProvider; - private readonly IGlobalSettings _globalSettings; + private readonly GlobalSettings _globalSettings; private readonly IRuntimeState _runtime; private readonly IMigrationBuilder _migrationBuilder; private readonly IKeyValueService _keyValueService; @@ -38,7 +40,7 @@ namespace Umbraco.Core.Migrations.Install /// public DatabaseBuilder( IScopeProvider scopeProvider, - IGlobalSettings globalSettings, + IOptionsSnapshot globalSettings, IUmbracoDatabaseFactory databaseFactory, IRuntimeState runtime, ILogger logger, @@ -50,7 +52,7 @@ namespace Umbraco.Core.Migrations.Install IConfigManipulator configManipulator) { _scopeProvider = scopeProvider; - _globalSettings = globalSettings; + _globalSettings = globalSettings.Value; _databaseFactory = databaseFactory; _runtime = runtime; _logger = logger; diff --git a/src/Umbraco.Infrastructure/Migrations/Install/DatabaseDataCreator.cs b/src/Umbraco.Infrastructure/Migrations/Install/DatabaseDataCreator.cs index 36f1a30b20..6f0f32c37d 100644 --- a/src/Umbraco.Infrastructure/Migrations/Install/DatabaseDataCreator.cs +++ b/src/Umbraco.Infrastructure/Migrations/Install/DatabaseDataCreator.cs @@ -1,6 +1,7 @@ using System; using NPoco; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Logging; using Umbraco.Core.Migrations.Upgrade; using Umbraco.Core.Models; @@ -16,9 +17,9 @@ namespace Umbraco.Core.Migrations.Install private readonly IDatabase _database; private readonly ILogger _logger; private readonly IUmbracoVersion _umbracoVersion; - private readonly IGlobalSettings _globalSettings; + private readonly GlobalSettings _globalSettings; - public DatabaseDataCreator(IDatabase database, ILogger logger, IUmbracoVersion umbracoVersion, IGlobalSettings globalSettings) + public DatabaseDataCreator(IDatabase database, ILogger logger, IUmbracoVersion umbracoVersion, GlobalSettings globalSettings) { _database = database; _logger = logger; diff --git a/src/Umbraco.Infrastructure/Migrations/Install/DatabaseSchemaCreator.cs b/src/Umbraco.Infrastructure/Migrations/Install/DatabaseSchemaCreator.cs index 921ba0b3d5..97bd8bc2d6 100644 --- a/src/Umbraco.Infrastructure/Migrations/Install/DatabaseSchemaCreator.cs +++ b/src/Umbraco.Infrastructure/Migrations/Install/DatabaseSchemaCreator.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using NPoco; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Events; using Umbraco.Core.Logging; using Umbraco.Core.Persistence; @@ -20,9 +21,9 @@ namespace Umbraco.Core.Migrations.Install private readonly IUmbracoDatabase _database; private readonly ILogger _logger; private readonly IUmbracoVersion _umbracoVersion; - private readonly IGlobalSettings _globalSettings; + private readonly GlobalSettings _globalSettings; - public DatabaseSchemaCreator(IUmbracoDatabase database, ILogger logger, IUmbracoVersion umbracoVersion, IGlobalSettings globalSettings) + public DatabaseSchemaCreator(IUmbracoDatabase database, ILogger logger, IUmbracoVersion umbracoVersion, GlobalSettings globalSettings) { _database = database; _logger = logger; diff --git a/src/Umbraco.Infrastructure/Migrations/Upgrade/UmbracoPlan.cs b/src/Umbraco.Infrastructure/Migrations/Upgrade/UmbracoPlan.cs index c671b0d236..3b555c89b1 100644 --- a/src/Umbraco.Infrastructure/Migrations/Upgrade/UmbracoPlan.cs +++ b/src/Umbraco.Infrastructure/Migrations/Upgrade/UmbracoPlan.cs @@ -2,6 +2,7 @@ using Semver; using Umbraco.Core.Composing; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Migrations.Upgrade.Common; using Umbraco.Core.Migrations.Upgrade.V_8_0_0; using Umbraco.Core.Migrations.Upgrade.V_8_0_1; @@ -16,13 +17,13 @@ namespace Umbraco.Core.Migrations.Upgrade public class UmbracoPlan : MigrationPlan { private readonly IUmbracoVersion _umbracoVersion; - private readonly IGlobalSettings _globalSettings; + private readonly GlobalSettings _globalSettings; private const string InitPrefix = "{init-"; private const string InitSuffix = "}"; /// /// Initializes a new instance of the class. /// - public UmbracoPlan(IUmbracoVersion umbracoVersion, IGlobalSettings globalSettings) + public UmbracoPlan(IUmbracoVersion umbracoVersion, GlobalSettings globalSettings) : base(Constants.System.UmbracoUpgradePlanName) { _umbracoVersion = umbracoVersion; diff --git a/src/Umbraco.Infrastructure/Models/Mapping/ContentTypeMapDefinition.cs b/src/Umbraco.Infrastructure/Models/Mapping/ContentTypeMapDefinition.cs index 9341b2f756..83da0c306c 100644 --- a/src/Umbraco.Infrastructure/Models/Mapping/ContentTypeMapDefinition.cs +++ b/src/Umbraco.Infrastructure/Models/Mapping/ContentTypeMapDefinition.cs @@ -13,6 +13,8 @@ using Umbraco.Core.Exceptions; using Umbraco.Core.Hosting; using Umbraco.Core.IO; using Umbraco.Core.Strings; +using Umbraco.Core.Configuration.Models; +using Microsoft.Extensions.Options; namespace Umbraco.Web.Models.Mapping { @@ -30,13 +32,12 @@ namespace Umbraco.Web.Models.Mapping private readonly IMemberTypeService _memberTypeService; private readonly ILogger _logger; private readonly IShortStringHelper _shortStringHelper; - private readonly IGlobalSettings _globalSettings; + private readonly GlobalSettings _globalSettings; private readonly IHostingEnvironment _hostingEnvironment; - public ContentTypeMapDefinition(CommonMapper commonMapper, PropertyEditorCollection propertyEditors, IDataTypeService dataTypeService, IFileService fileService, IContentTypeService contentTypeService, IMediaTypeService mediaTypeService, IMemberTypeService memberTypeService, - ILogger logger, IShortStringHelper shortStringHelper, IGlobalSettings globalSettings, IHostingEnvironment hostingEnvironment) + ILogger logger, IShortStringHelper shortStringHelper, IOptionsSnapshot globalSettings, IHostingEnvironment hostingEnvironment) { _commonMapper = commonMapper; _propertyEditors = propertyEditors; @@ -47,7 +48,7 @@ namespace Umbraco.Web.Models.Mapping _memberTypeService = memberTypeService; _logger = logger; _shortStringHelper = shortStringHelper; - _globalSettings = globalSettings; + _globalSettings = globalSettings.Value; _hostingEnvironment = hostingEnvironment; } diff --git a/src/Umbraco.Infrastructure/Models/Mapping/UserMapDefinition.cs b/src/Umbraco.Infrastructure/Models/Mapping/UserMapDefinition.cs index 043b37a654..ca17bffd5d 100644 --- a/src/Umbraco.Infrastructure/Models/Mapping/UserMapDefinition.cs +++ b/src/Umbraco.Infrastructure/Models/Mapping/UserMapDefinition.cs @@ -18,6 +18,8 @@ using Umbraco.Web.Actions; using Umbraco.Web.Services; using Umbraco.Core.Media; using Umbraco.Core.Persistence.Dtos; +using Umbraco.Core.Configuration.Models; +using Microsoft.Extensions.Options; namespace Umbraco.Web.Models.Mapping { @@ -29,13 +31,13 @@ namespace Umbraco.Web.Models.Mapping private readonly ILocalizedTextService _textService; private readonly ActionCollection _actions; private readonly AppCaches _appCaches; - private readonly IGlobalSettings _globalSettings; + private readonly GlobalSettings _globalSettings; private readonly IMediaFileSystem _mediaFileSystem; private readonly IShortStringHelper _shortStringHelper; private readonly IImageUrlGenerator _imageUrlGenerator; public UserMapDefinition(ILocalizedTextService textService, IUserService userService, IEntityService entityService, ISectionService sectionService, - AppCaches appCaches, ActionCollection actions, IGlobalSettings globalSettings, IMediaFileSystem mediaFileSystem, IShortStringHelper shortStringHelper, + AppCaches appCaches, ActionCollection actions, IOptionsSnapshot globalSettings, IMediaFileSystem mediaFileSystem, IShortStringHelper shortStringHelper, IImageUrlGenerator imageUrlGenerator) { _sectionService = sectionService; @@ -44,7 +46,7 @@ namespace Umbraco.Web.Models.Mapping _textService = textService; _actions = actions; _appCaches = appCaches; - _globalSettings = globalSettings; + _globalSettings = globalSettings.Value; _mediaFileSystem = mediaFileSystem; _shortStringHelper = shortStringHelper; _imageUrlGenerator = imageUrlGenerator; diff --git a/src/Umbraco.Infrastructure/Packaging/PackageDataInstallation.cs b/src/Umbraco.Infrastructure/Packaging/PackageDataInstallation.cs index 6b1aa96e69..a868170c5f 100644 --- a/src/Umbraco.Infrastructure/Packaging/PackageDataInstallation.cs +++ b/src/Umbraco.Infrastructure/Packaging/PackageDataInstallation.cs @@ -7,6 +7,7 @@ using System.Xml.Linq; using System.Xml.XPath; using Umbraco.Core.Collections; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.Entities; @@ -29,7 +30,7 @@ namespace Umbraco.Core.Packaging private readonly PropertyEditorCollection _propertyEditors; private readonly IScopeProvider _scopeProvider; private readonly IShortStringHelper _shortStringHelper; - private readonly IGlobalSettings _globalSettings; + private readonly GlobalSettings _globalSettings; private readonly ILocalizedTextService _localizedTextService; private readonly IEntityService _entityService; private readonly IContentTypeService _contentTypeService; @@ -37,7 +38,7 @@ namespace Umbraco.Core.Packaging public PackageDataInstallation(ILogger logger, IFileService fileService, IMacroService macroService, ILocalizationService localizationService, IDataTypeService dataTypeService, IEntityService entityService, IContentTypeService contentTypeService, - IContentService contentService, PropertyEditorCollection propertyEditors, IScopeProvider scopeProvider, IShortStringHelper shortStringHelper, IGlobalSettings globalSettings, + IContentService contentService, PropertyEditorCollection propertyEditors, IScopeProvider scopeProvider, IShortStringHelper shortStringHelper, GlobalSettings globalSettings, ILocalizedTextService localizedTextService) { _logger = logger; diff --git a/src/Umbraco.Infrastructure/Persistence/Factories/LanguageFactory.cs b/src/Umbraco.Infrastructure/Persistence/Factories/LanguageFactory.cs index 1da4a8dfac..0b5937a328 100644 --- a/src/Umbraco.Infrastructure/Persistence/Factories/LanguageFactory.cs +++ b/src/Umbraco.Infrastructure/Persistence/Factories/LanguageFactory.cs @@ -1,5 +1,6 @@ using System.Globalization; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Models; using Umbraco.Core.Persistence.Dtos; @@ -7,7 +8,7 @@ namespace Umbraco.Core.Persistence.Factories { internal static class LanguageFactory { - public static ILanguage BuildEntity(IGlobalSettings globalSettings, LanguageDto dto) + public static ILanguage BuildEntity(GlobalSettings globalSettings, LanguageDto dto) { var lang = new Language(globalSettings, dto.IsoCode) { diff --git a/src/Umbraco.Infrastructure/Persistence/Factories/UserFactory.cs b/src/Umbraco.Infrastructure/Persistence/Factories/UserFactory.cs index b56e822e92..839f7b5ad7 100644 --- a/src/Umbraco.Infrastructure/Persistence/Factories/UserFactory.cs +++ b/src/Umbraco.Infrastructure/Persistence/Factories/UserFactory.cs @@ -1,6 +1,7 @@ using System; using System.Linq; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Models.Membership; using Umbraco.Core.Persistence.Dtos; @@ -8,7 +9,7 @@ namespace Umbraco.Core.Persistence.Factories { internal static class UserFactory { - public static IUser BuildEntity(IGlobalSettings globalSettings, UserDto dto) + public static IUser BuildEntity(GlobalSettings globalSettings, UserDto dto) { var guidId = dto.Id.ToGuid(); diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/LanguageRepository.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/LanguageRepository.cs index 245ff10f7f..80afef181e 100644 --- a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/LanguageRepository.cs +++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/LanguageRepository.cs @@ -1,9 +1,11 @@ using System; using System.Collections.Generic; using System.Linq; +using Microsoft.Extensions.Options; using NPoco; using Umbraco.Core.Cache; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.Entities; @@ -19,14 +21,14 @@ namespace Umbraco.Core.Persistence.Repositories.Implement ///
internal class LanguageRepository : NPocoRepositoryBase, ILanguageRepository { - private readonly IGlobalSettings _globalSettings; + private readonly GlobalSettings _globalSettings; private readonly Dictionary _codeIdMap = new Dictionary(StringComparer.OrdinalIgnoreCase); private readonly Dictionary _idCodeMap = new Dictionary(); - public LanguageRepository(IScopeAccessor scopeAccessor, AppCaches cache, ILogger logger, IGlobalSettings globalSettings) + public LanguageRepository(IScopeAccessor scopeAccessor, AppCaches cache, ILogger logger, IOptionsSnapshot globalSettings) : base(scopeAccessor, cache, logger) { - _globalSettings = globalSettings; + _globalSettings = globalSettings.Value; } protected override IRepositoryCachePolicy CreateCachePolicy() diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/ScriptRepository.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/ScriptRepository.cs index 498cf51432..b137f36bc4 100644 --- a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/ScriptRepository.cs +++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/ScriptRepository.cs @@ -2,7 +2,9 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using Microsoft.Extensions.Options; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.IO; using Umbraco.Core.Models; @@ -14,13 +16,13 @@ namespace Umbraco.Core.Persistence.Repositories.Implement internal class ScriptRepository : FileRepository, IScriptRepository { private readonly IIOHelper _ioHelper; - private readonly IGlobalSettings _globalSettings; + private readonly GlobalSettings _globalSettings; - public ScriptRepository(IFileSystems fileSystems, IIOHelper ioHelper, IGlobalSettings globalSettings) + public ScriptRepository(IFileSystems fileSystems, IIOHelper ioHelper, IOptionsSnapshot globalSettings) : base(fileSystems.ScriptsFileSystem) { _ioHelper = ioHelper ?? throw new ArgumentNullException(nameof(ioHelper)); - _globalSettings = globalSettings; + _globalSettings = globalSettings.Value; } #region Implementation of IRepository diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/StylesheetRepository.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/StylesheetRepository.cs index f432d6959e..4ee18c635c 100644 --- a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/StylesheetRepository.cs +++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/StylesheetRepository.cs @@ -1,7 +1,9 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using Microsoft.Extensions.Options; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.IO; using Umbraco.Core.Models; @@ -13,13 +15,13 @@ namespace Umbraco.Core.Persistence.Repositories.Implement internal class StylesheetRepository : FileRepository, IStylesheetRepository { private readonly IIOHelper _ioHelper; - private readonly IGlobalSettings _globalSettings; + private readonly GlobalSettings _globalSettings; - public StylesheetRepository(IFileSystems fileSystems, IIOHelper ioHelper, IGlobalSettings globalSettings) + public StylesheetRepository(IFileSystems fileSystems, IIOHelper ioHelper, IOptionsSnapshot globalSettings) : base(fileSystems.StylesheetsFileSystem) { _ioHelper = ioHelper; - _globalSettings = globalSettings; + _globalSettings = globalSettings.Value; } #region Overrides of FileRepository diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/UserRepository.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/UserRepository.cs index bd11127296..e054c4423a 100644 --- a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/UserRepository.cs +++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/UserRepository.cs @@ -26,7 +26,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement internal class UserRepository : NPocoRepositoryBase, IUserRepository { private readonly IMapperCollection _mapperCollection; - private readonly IGlobalSettings _globalSettings; + private readonly GlobalSettings _globalSettings; private readonly UserPasswordConfigurationSettings _passwordConfiguration; private readonly IJsonSerializer _jsonSerializer; private string _passwordConfigJson; @@ -47,10 +47,10 @@ namespace Umbraco.Core.Persistence.Repositories.Implement AppCaches appCaches, ILogger logger, IMapperCollection mapperCollection, - IGlobalSettings globalSettings, + IOptionsSnapshot globalSettings, IOptionsSnapshot passwordConfiguration, IJsonSerializer jsonSerializer) - : this(scopeAccessor, appCaches, logger, mapperCollection, globalSettings, passwordConfiguration.Value, jsonSerializer) + : this(scopeAccessor, appCaches, logger, mapperCollection, globalSettings.Value, passwordConfiguration.Value, jsonSerializer) { } @@ -69,7 +69,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement AppCaches appCaches, ILogger logger, IMapperCollection mapperCollection, - IGlobalSettings globalSettings, + GlobalSettings globalSettings, UserPasswordConfigurationSettings passwordConfiguration, IJsonSerializer jsonSerializer) : base(scopeAccessor, appCaches, logger) diff --git a/src/Umbraco.Infrastructure/Persistence/UmbracoDatabaseFactory.cs b/src/Umbraco.Infrastructure/Persistence/UmbracoDatabaseFactory.cs index 837fe6cba3..1b46a6a3cd 100644 --- a/src/Umbraco.Infrastructure/Persistence/UmbracoDatabaseFactory.cs +++ b/src/Umbraco.Infrastructure/Persistence/UmbracoDatabaseFactory.cs @@ -6,6 +6,7 @@ using NPoco; using NPoco.FluentMappings; using Umbraco.Core.Composing; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Logging; using Umbraco.Core.Persistence.FaultHandling; using Umbraco.Core.Persistence.Mappers; @@ -28,7 +29,7 @@ namespace Umbraco.Core.Persistence internal class UmbracoDatabaseFactory : DisposableObjectSlim, IUmbracoDatabaseFactory { private readonly IDbProviderFactoryCreator _dbProviderFactoryCreator; - private readonly IGlobalSettings _globalSettings; + private readonly GlobalSettings _globalSettings; private readonly Lazy _mappers; private readonly ILogger _logger; @@ -70,7 +71,7 @@ namespace Umbraco.Core.Persistence /// Initializes a new instance of the . /// /// Used by core runtime. - public UmbracoDatabaseFactory(ILogger logger, IGlobalSettings globalSettings, IConnectionStrings connectionStrings, Lazy mappers,IDbProviderFactoryCreator dbProviderFactoryCreator) + public UmbracoDatabaseFactory(ILogger logger, GlobalSettings globalSettings, ConnectionStrings connectionStrings, Lazy mappers,IDbProviderFactoryCreator dbProviderFactoryCreator) : this(logger, globalSettings, connectionStrings, Constants.System.UmbracoConnectionName, mappers, dbProviderFactoryCreator) { @@ -80,7 +81,7 @@ namespace Umbraco.Core.Persistence /// Initializes a new instance of the . /// /// Used by the other ctor and in tests. - public UmbracoDatabaseFactory(ILogger logger, IGlobalSettings globalSettings, IConnectionStrings connectionStrings, string connectionStringName, Lazy mappers, IDbProviderFactoryCreator dbProviderFactoryCreator) + public UmbracoDatabaseFactory(ILogger logger, GlobalSettings globalSettings, ConnectionStrings connectionStrings, string connectionStringName, Lazy mappers, IDbProviderFactoryCreator dbProviderFactoryCreator) { if (connectionStringName == null) throw new ArgumentNullException(nameof(connectionStringName)); if (string.IsNullOrWhiteSpace(connectionStringName)) throw new ArgumentException("Value can't be empty or consist only of white-space characters.", nameof(connectionStringName)); diff --git a/src/Umbraco.Infrastructure/Routing/RedirectTrackingComponent.cs b/src/Umbraco.Infrastructure/Routing/RedirectTrackingComponent.cs index f9256b3692..63a6725fb8 100644 --- a/src/Umbraco.Infrastructure/Routing/RedirectTrackingComponent.cs +++ b/src/Umbraco.Infrastructure/Routing/RedirectTrackingComponent.cs @@ -1,8 +1,10 @@ using System; using System.Collections.Generic; using System.Linq; +using Microsoft.Extensions.Options; using Umbraco.Core; using Umbraco.Core.Composing; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Events; using Umbraco.Core.Models; @@ -24,15 +26,14 @@ namespace Umbraco.Web.Routing { private const string _eventStateKey = "Umbraco.Web.Redirects.RedirectTrackingEventHandler"; - - private readonly IWebRoutingSettings _webRoutingSettings; + private readonly WebRoutingSettings _webRoutingSettings; private readonly IPublishedSnapshotAccessor _publishedSnapshotAccessor; private readonly IRedirectUrlService _redirectUrlService; private readonly IVariationContextAccessor _variationContextAccessor; - public RedirectTrackingComponent(IWebRoutingSettings webRoutingSettings, IPublishedSnapshotAccessor publishedSnapshotAccessor, IRedirectUrlService redirectUrlService, IVariationContextAccessor variationContextAccessor) + public RedirectTrackingComponent(IOptionsSnapshot webRoutingSettings, IPublishedSnapshotAccessor publishedSnapshotAccessor, IRedirectUrlService redirectUrlService, IVariationContextAccessor variationContextAccessor) { - _webRoutingSettings = webRoutingSettings; + _webRoutingSettings = webRoutingSettings.Value; _publishedSnapshotAccessor = publishedSnapshotAccessor; _redirectUrlService = redirectUrlService; _variationContextAccessor = variationContextAccessor; diff --git a/src/Umbraco.Infrastructure/Runtime/CoreInitialComponent.cs b/src/Umbraco.Infrastructure/Runtime/CoreInitialComponent.cs index 1432e6b7f2..3a4cd60901 100644 --- a/src/Umbraco.Infrastructure/Runtime/CoreInitialComponent.cs +++ b/src/Umbraco.Infrastructure/Runtime/CoreInitialComponent.cs @@ -1,5 +1,7 @@ -using Umbraco.Core.Composing; +using Microsoft.Extensions.Options; +using Umbraco.Core.Composing; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.IO; namespace Umbraco.Core.Runtime @@ -7,12 +9,12 @@ namespace Umbraco.Core.Runtime public class CoreInitialComponent : IComponent { private readonly IIOHelper _ioHelper; - private readonly IGlobalSettings _globalSettings; + private readonly GlobalSettings _globalSettings; - public CoreInitialComponent(IIOHelper ioHelper, IGlobalSettings globalSettings) + public CoreInitialComponent(IIOHelper ioHelper, IOptionsSnapshot globalSettings) { _ioHelper = ioHelper; - _globalSettings = globalSettings; + _globalSettings = globalSettings.Value; } public void Initialize() diff --git a/src/Umbraco.Infrastructure/Runtime/CoreRuntime.cs b/src/Umbraco.Infrastructure/Runtime/CoreRuntime.cs index 2f9766e5c2..ad036e12eb 100644 --- a/src/Umbraco.Infrastructure/Runtime/CoreRuntime.cs +++ b/src/Umbraco.Infrastructure/Runtime/CoreRuntime.cs @@ -5,6 +5,7 @@ using System.IO; using Umbraco.Core.Cache; using Umbraco.Core.Composing; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Exceptions; using Umbraco.Core.Hosting; using Umbraco.Core.IO; @@ -26,11 +27,12 @@ namespace Umbraco.Core.Runtime private readonly RuntimeState _state; private readonly IUmbracoBootPermissionChecker _umbracoBootPermissionChecker; private readonly IRequestCache _requestCache; - private readonly IGlobalSettings _globalSettings; - private readonly IConnectionStrings _connectionStrings; + private readonly GlobalSettings _globalSettings; + private readonly ConnectionStrings _connectionStrings; public CoreRuntime( - Configs configs, + GlobalSettings globalSettings, + ConnectionStrings connectionStrings, IUmbracoVersion umbracoVersion, IIOHelper ioHelper, ILogger logger, @@ -43,9 +45,11 @@ namespace Umbraco.Core.Runtime ITypeFinder typeFinder, IRequestCache requestCache) { + _globalSettings = globalSettings; + _connectionStrings = connectionStrings; + IOHelper = ioHelper; - Configs = configs; - UmbracoVersion = umbracoVersion ; + UmbracoVersion = umbracoVersion; Profiler = profiler; HostingEnvironment = hostingEnvironment; BackOfficeInfo = backOfficeInfo; @@ -58,14 +62,10 @@ namespace Umbraco.Core.Runtime MainDom = mainDom; TypeFinder = typeFinder; - _globalSettings = Configs.Global(); - _connectionStrings = configs.ConnectionStrings(); - - // runtime state // beware! must use '() => _factory.GetInstance()' and NOT '_factory.GetInstance' // as the second one captures the current value (null) and therefore fails - _state = new RuntimeState(Configs.Global(), UmbracoVersion) + _state = new RuntimeState(_globalSettings, UmbracoVersion) { Level = RuntimeLevel.Boot }; @@ -99,8 +99,8 @@ namespace Umbraco.Core.Runtime /// Gets the /// protected IIOHelper IOHelper { get; } + protected IHostingEnvironment HostingEnvironment { get; } - protected Configs Configs { get; } protected IUmbracoVersion UmbracoVersion { get; } /// @@ -179,7 +179,7 @@ namespace Umbraco.Core.Runtime var typeLoader = new TypeLoader(TypeFinder, appCaches.RuntimeCache, new DirectoryInfo(HostingEnvironment.LocalTempPath), ProfilingLogger); // create the composition - composition = new Composition(register, typeLoader, ProfilingLogger, _state, Configs, IOHelper, appCaches); + composition = new Composition(register, typeLoader, ProfilingLogger, _state, IOHelper, appCaches); composition.RegisterEssentials(Logger, Profiler, ProfilingLogger, MainDom, appCaches, databaseFactory, typeLoader, _state, TypeFinder, IOHelper, UmbracoVersion, DbProviderFactoryCreator, HostingEnvironment, BackOfficeInfo); // register ourselves (TODO: Should we put this in RegisterEssentials?) diff --git a/src/Umbraco.Infrastructure/Runtime/SqlMainDomLock.cs b/src/Umbraco.Infrastructure/Runtime/SqlMainDomLock.cs index d3bb7eefac..723be61283 100644 --- a/src/Umbraco.Infrastructure/Runtime/SqlMainDomLock.cs +++ b/src/Umbraco.Infrastructure/Runtime/SqlMainDomLock.cs @@ -7,6 +7,7 @@ using System.Security.Cryptography; using System.Threading; using System.Threading.Tasks; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Hosting; using Umbraco.Core.Logging; using Umbraco.Core.Persistence; @@ -31,7 +32,7 @@ namespace Umbraco.Core.Runtime private bool _errorDuringAcquiring; private object _locker = new object(); - public SqlMainDomLock(ILogger logger, IGlobalSettings globalSettings, IConnectionStrings connectionStrings, IDbProviderFactoryCreator dbProviderFactoryCreator, IHostingEnvironment hostingEnvironment) + public SqlMainDomLock(ILogger logger, GlobalSettings globalSettings, ConnectionStrings connectionStrings, IDbProviderFactoryCreator dbProviderFactoryCreator, IHostingEnvironment hostingEnvironment) { // unique id for our appdomain, this is more unique than the appdomain id which is just an INT counter to its safer _lockId = Guid.NewGuid().ToString(); diff --git a/src/Umbraco.Infrastructure/RuntimeState.cs b/src/Umbraco.Infrastructure/RuntimeState.cs index 4a33291314..832cdc7605 100644 --- a/src/Umbraco.Infrastructure/RuntimeState.cs +++ b/src/Umbraco.Infrastructure/RuntimeState.cs @@ -3,6 +3,7 @@ using System.Threading; using Semver; using Umbraco.Core.Collections; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Exceptions; using Umbraco.Core.Hosting; using Umbraco.Core.Logging; @@ -16,13 +17,13 @@ namespace Umbraco.Core /// public class RuntimeState : IRuntimeState { - private readonly IGlobalSettings _globalSettings; + private readonly GlobalSettings _globalSettings; private readonly IUmbracoVersion _umbracoVersion; /// /// Initializes a new instance of the class. /// - public RuntimeState(IGlobalSettings globalSettings, IUmbracoVersion umbracoVersion) + public RuntimeState(GlobalSettings globalSettings, IUmbracoVersion umbracoVersion) { _globalSettings = globalSettings; _umbracoVersion = umbracoVersion; diff --git a/src/Umbraco.Infrastructure/Services/Implement/FileService.cs b/src/Umbraco.Infrastructure/Services/Implement/FileService.cs index 188fad4c7b..7d6c0303ce 100644 --- a/src/Umbraco.Infrastructure/Services/Implement/FileService.cs +++ b/src/Umbraco.Infrastructure/Services/Implement/FileService.cs @@ -3,8 +3,10 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Text.RegularExpressions; +using Microsoft.Extensions.Options; using Umbraco.Core.Composing; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Events; using Umbraco.Core.Hosting; using Umbraco.Core.IO; @@ -29,7 +31,7 @@ namespace Umbraco.Core.Services.Implement private readonly IPartialViewMacroRepository _partialViewMacroRepository; private readonly IAuditRepository _auditRepository; private readonly IShortStringHelper _shortStringHelper; - private readonly IGlobalSettings _globalSettings; + private readonly GlobalSettings _globalSettings; private readonly IHostingEnvironment _hostingEnvironment; private const string PartialViewHeader = "@inherits Umbraco.Web.Common.AspNetCore.UmbracoViewPage"; @@ -38,7 +40,7 @@ namespace Umbraco.Core.Services.Implement public FileService(IScopeProvider uowProvider, ILogger logger, IEventMessagesFactory eventMessagesFactory, IStylesheetRepository stylesheetRepository, IScriptRepository scriptRepository, ITemplateRepository templateRepository, IPartialViewRepository partialViewRepository, IPartialViewMacroRepository partialViewMacroRepository, - IAuditRepository auditRepository, IShortStringHelper shortStringHelper, IGlobalSettings globalSettings, IHostingEnvironment hostingEnvironment) + IAuditRepository auditRepository, IShortStringHelper shortStringHelper, IOptionsSnapshot globalSettings, IHostingEnvironment hostingEnvironment) : base(uowProvider, logger, eventMessagesFactory) { _stylesheetRepository = stylesheetRepository; @@ -48,7 +50,7 @@ namespace Umbraco.Core.Services.Implement _partialViewMacroRepository = partialViewMacroRepository; _auditRepository = auditRepository; _shortStringHelper = shortStringHelper; - _globalSettings = globalSettings; + _globalSettings = globalSettings.Value; _hostingEnvironment = hostingEnvironment; } diff --git a/src/Umbraco.Infrastructure/Services/Implement/NotificationService.cs b/src/Umbraco.Infrastructure/Services/Implement/NotificationService.cs index 112ab51bf8..3ad1ea8446 100644 --- a/src/Umbraco.Infrastructure/Services/Implement/NotificationService.cs +++ b/src/Umbraco.Infrastructure/Services/Implement/NotificationService.cs @@ -26,19 +26,19 @@ namespace Umbraco.Core.Services.Implement private readonly IContentService _contentService; private readonly ILocalizationService _localizationService; private readonly INotificationsRepository _notificationsRepository; - private readonly IGlobalSettings _globalSettings; + private readonly GlobalSettings _globalSettings; private readonly ContentSettings _contentSettings; private readonly ILogger _logger; private readonly IIOHelper _ioHelper; public NotificationService(IScopeProvider provider, IUserService userService, IContentService contentService, ILocalizationService localizationService, - ILogger logger, IIOHelper ioHelper, INotificationsRepository notificationsRepository, IGlobalSettings globalSettings, IOptionsSnapshot contentSettings) - : this(provider, userService, contentService, localizationService, logger, ioHelper, notificationsRepository, globalSettings, contentSettings.Value) + ILogger logger, IIOHelper ioHelper, INotificationsRepository notificationsRepository, IOptionsSnapshot globalSettings, IOptionsSnapshot contentSettings) + : this(provider, userService, contentService, localizationService, logger, ioHelper, notificationsRepository, globalSettings.Value, contentSettings.Value) { } public NotificationService(IScopeProvider provider, IUserService userService, IContentService contentService, ILocalizationService localizationService, - ILogger logger, IIOHelper ioHelper, INotificationsRepository notificationsRepository, IGlobalSettings globalSettings, ContentSettings contentSettings) + ILogger logger, IIOHelper ioHelper, INotificationsRepository notificationsRepository, GlobalSettings globalSettings, ContentSettings contentSettings) { _notificationsRepository = notificationsRepository; _globalSettings = globalSettings; diff --git a/src/Umbraco.Infrastructure/Services/Implement/UserService.cs b/src/Umbraco.Infrastructure/Services/Implement/UserService.cs index faf7889fbf..921da6f345 100644 --- a/src/Umbraco.Infrastructure/Services/Implement/UserService.cs +++ b/src/Umbraco.Infrastructure/Services/Implement/UserService.cs @@ -4,7 +4,9 @@ using System.Data.Common; using System.Globalization; using System.Linq; using System.Linq.Expressions; +using Microsoft.Extensions.Options; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Events; using Umbraco.Core.Logging; using Umbraco.Core.Models.Membership; @@ -22,16 +24,16 @@ namespace Umbraco.Core.Services.Implement { private readonly IUserRepository _userRepository; private readonly IUserGroupRepository _userGroupRepository; - private readonly IGlobalSettings _globalSettings; + private readonly GlobalSettings _globalSettings; private readonly bool _isUpgrading; public UserService(IScopeProvider provider, ILogger logger, IEventMessagesFactory eventMessagesFactory, IRuntimeState runtimeState, - IUserRepository userRepository, IUserGroupRepository userGroupRepository, IGlobalSettings globalSettings) + IUserRepository userRepository, IUserGroupRepository userGroupRepository, IOptionsSnapshot globalSettings) : base(provider, logger, eventMessagesFactory) { _userRepository = userRepository; _userGroupRepository = userGroupRepository; - _globalSettings = globalSettings; + _globalSettings = globalSettings.Value; _isUpgrading = runtimeState.Level == RuntimeLevel.Install || runtimeState.Level == RuntimeLevel.Upgrade; } diff --git a/src/Umbraco.Infrastructure/Users/EmailSender.cs b/src/Umbraco.Infrastructure/Users/EmailSender.cs index 9a2f425021..1ca30bb966 100644 --- a/src/Umbraco.Infrastructure/Users/EmailSender.cs +++ b/src/Umbraco.Infrastructure/Users/EmailSender.cs @@ -2,9 +2,11 @@ using System.Linq; using System.Net.Mail; using System.Threading.Tasks; +using Microsoft.Extensions.Options; using MimeKit; using MimeKit.Text; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Events; using SmtpClient = MailKit.Net.Smtp.SmtpClient; @@ -17,14 +19,23 @@ namespace Umbraco.Core { // TODO: This should encapsulate a BackgroundTaskRunner with a queue to send these emails! - private readonly IGlobalSettings _globalSettings; + private readonly GlobalSettings _globalSettings; private readonly bool _enableEvents; - public EmailSender(IGlobalSettings globalSettings) : this(globalSettings, false) + public EmailSender(IOptionsSnapshot globalSettings) : this(globalSettings, false) { } - public EmailSender(IGlobalSettings globalSettings, bool enableEvents) + public EmailSender(IOptionsSnapshot globalSettings, bool enableEvents) + : this(globalSettings.Value, enableEvents) + { + } + + public EmailSender(GlobalSettings globalSettings) : this(globalSettings, false) + { + } + + public EmailSender(GlobalSettings globalSettings, bool enableEvents) { _globalSettings = globalSettings; _enableEvents = enableEvents; @@ -107,7 +118,7 @@ namespace Umbraco.Core /// /// We assume this is possible if either an event handler is registered or an smtp server is configured /// - public static bool CanSendRequiredEmail(IGlobalSettings globalSettings) => EventHandlerRegistered || globalSettings.IsSmtpServerConfigured; + public static bool CanSendRequiredEmail(GlobalSettings globalSettings) => EventHandlerRegistered || globalSettings.IsSmtpServerConfigured; /// /// returns true if an event handler has been registered diff --git a/src/Umbraco.Infrastructure/WebAssets/BackOfficeJavaScriptInitializer.cs b/src/Umbraco.Infrastructure/WebAssets/BackOfficeJavaScriptInitializer.cs index 18279e35ba..77db7bcbfd 100644 --- a/src/Umbraco.Infrastructure/WebAssets/BackOfficeJavaScriptInitializer.cs +++ b/src/Umbraco.Infrastructure/WebAssets/BackOfficeJavaScriptInitializer.cs @@ -2,6 +2,7 @@ using System.Text; using System.Text.RegularExpressions; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Hosting; using Umbraco.Core.IO; @@ -31,7 +32,7 @@ namespace Umbraco.Web.WebAssets /// /// /// - public static string GetJavascriptInitialization(IEnumerable scripts, string angularModule, IGlobalSettings globalSettings, IHostingEnvironment hostingEnvironment) + public static string GetJavascriptInitialization(IEnumerable scripts, string angularModule, GlobalSettings globalSettings, IHostingEnvironment hostingEnvironment) { var jarray = new StringBuilder(); jarray.AppendLine("["); diff --git a/src/Umbraco.Infrastructure/WebAssets/BackOfficeWebAssets.cs b/src/Umbraco.Infrastructure/WebAssets/BackOfficeWebAssets.cs index fcb27f7189..b3d7d485f5 100644 --- a/src/Umbraco.Infrastructure/WebAssets/BackOfficeWebAssets.cs +++ b/src/Umbraco.Infrastructure/WebAssets/BackOfficeWebAssets.cs @@ -1,10 +1,12 @@ using System; using System.Collections.Generic; using System.Linq; +using Microsoft.Extensions.Options; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Umbraco.Core; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Hosting; using Umbraco.Core.IO; using Umbraco.Core.Manifest; @@ -25,7 +27,7 @@ namespace Umbraco.Web.WebAssets private readonly IRuntimeMinifier _runtimeMinifier; private readonly IManifestParser _parser; - private readonly IGlobalSettings _globalSettings; + private readonly GlobalSettings _globalSettings; private readonly IHostingEnvironment _hostingEnvironment; private readonly PropertyEditorCollection _propertyEditorCollection; @@ -34,13 +36,13 @@ namespace Umbraco.Web.WebAssets IManifestParser parser, PropertyEditorCollection propertyEditorCollection, IHostingEnvironment hostingEnvironment, - IGlobalSettings globalSettings) + IOptionsSnapshot globalSettings) { _runtimeMinifier = runtimeMinifier; _parser = parser; _propertyEditorCollection = propertyEditorCollection; _hostingEnvironment = hostingEnvironment; - _globalSettings = globalSettings; + _globalSettings = globalSettings.Value; } public void CreateBundles() diff --git a/src/Umbraco.Infrastructure/WebAssets/RuntimeMinifierExtensions.cs b/src/Umbraco.Infrastructure/WebAssets/RuntimeMinifierExtensions.cs index 072afa5816..929c7c9dd2 100644 --- a/src/Umbraco.Infrastructure/WebAssets/RuntimeMinifierExtensions.cs +++ b/src/Umbraco.Infrastructure/WebAssets/RuntimeMinifierExtensions.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Text; using System.Threading.Tasks; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Hosting; using Umbraco.Core.IO; using Umbraco.Core.WebAssets; @@ -15,7 +16,7 @@ namespace Umbraco.Web.WebAssets /// Returns the JavaScript to load the back office's assets /// /// - public static async Task GetScriptForLoadingBackOfficeAsync(this IRuntimeMinifier minifier, IGlobalSettings globalSettings, IHostingEnvironment hostingEnvironment) + public static async Task GetScriptForLoadingBackOfficeAsync(this IRuntimeMinifier minifier, GlobalSettings globalSettings, IHostingEnvironment hostingEnvironment) { var files = await minifier.GetAssetPathsAsync(BackOfficeWebAssets.UmbracoJsBundleName); var result = BackOfficeJavaScriptInitializer.GetJavascriptInitialization(files, "umbraco", globalSettings, hostingEnvironment); diff --git a/src/Umbraco.ModelsBuilder.Embedded/BackOffice/ContentTypeModelValidator.cs b/src/Umbraco.ModelsBuilder.Embedded/BackOffice/ContentTypeModelValidator.cs index 75affe09e7..1da5e44a77 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/BackOffice/ContentTypeModelValidator.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/BackOffice/ContentTypeModelValidator.cs @@ -1,4 +1,5 @@ -using Umbraco.Core.Configuration; +using Microsoft.Extensions.Options; +using Umbraco.Core.Configuration.Models; using Umbraco.Web.Models.ContentEditing; namespace Umbraco.ModelsBuilder.Embedded.BackOffice @@ -10,7 +11,7 @@ namespace Umbraco.ModelsBuilder.Embedded.BackOffice // ReSharper disable once UnusedMember.Global - This is typed scanned public class ContentTypeModelValidator : ContentTypeModelValidatorBase { - public ContentTypeModelValidator(IModelsBuilderConfig config) : base(config) + public ContentTypeModelValidator(IOptionsSnapshot config) : base(config) { } } diff --git a/src/Umbraco.ModelsBuilder.Embedded/BackOffice/ContentTypeModelValidatorBase.cs b/src/Umbraco.ModelsBuilder.Embedded/BackOffice/ContentTypeModelValidatorBase.cs index 1e96e64df8..dc78b31abd 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/BackOffice/ContentTypeModelValidatorBase.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/BackOffice/ContentTypeModelValidatorBase.cs @@ -1,8 +1,9 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; -using Umbraco.Core.Configuration; +using Microsoft.Extensions.Options; using Umbraco.Core; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Models.PublishedContent; using Umbraco.Web.Editors; using Umbraco.Web.Models.ContentEditing; @@ -13,11 +14,11 @@ namespace Umbraco.ModelsBuilder.Embedded.BackOffice where TModel : ContentTypeSave where TProperty : PropertyTypeBasic { - private readonly IModelsBuilderConfig _config; + private readonly ModelsBuilderConfig _config; - public ContentTypeModelValidatorBase(IModelsBuilderConfig config) + public ContentTypeModelValidatorBase(IOptionsSnapshot config) { - _config = config; + _config = config.Value; } protected override IEnumerable Validate(TModel model) diff --git a/src/Umbraco.ModelsBuilder.Embedded/BackOffice/DashboardReport.cs b/src/Umbraco.ModelsBuilder.Embedded/BackOffice/DashboardReport.cs index 6e22313474..9dc4d8bfb4 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/BackOffice/DashboardReport.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/BackOffice/DashboardReport.cs @@ -1,16 +1,17 @@ using System.Text; using Umbraco.Configuration; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; namespace Umbraco.ModelsBuilder.Embedded.BackOffice { internal class DashboardReport { - private readonly IModelsBuilderConfig _config; + private readonly ModelsBuilderConfig _config; private readonly OutOfDateModelsStatus _outOfDateModels; private readonly ModelsGenerationError _mbErrors; - public DashboardReport(IModelsBuilderConfig config, OutOfDateModelsStatus outOfDateModels, ModelsGenerationError mbErrors) + public DashboardReport(ModelsBuilderConfig config, OutOfDateModelsStatus outOfDateModels, ModelsGenerationError mbErrors) { _config = config; _outOfDateModels = outOfDateModels; diff --git a/src/Umbraco.ModelsBuilder.Embedded/BackOffice/MediaTypeModelValidator.cs b/src/Umbraco.ModelsBuilder.Embedded/BackOffice/MediaTypeModelValidator.cs index fcd42908e7..fc03c24704 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/BackOffice/MediaTypeModelValidator.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/BackOffice/MediaTypeModelValidator.cs @@ -1,4 +1,5 @@ -using Umbraco.Core.Configuration; +using Microsoft.Extensions.Options; +using Umbraco.Core.Configuration.Models; using Umbraco.Web.Models.ContentEditing; namespace Umbraco.ModelsBuilder.Embedded.BackOffice @@ -10,7 +11,7 @@ namespace Umbraco.ModelsBuilder.Embedded.BackOffice // ReSharper disable once UnusedMember.Global - This is typed scanned public class MediaTypeModelValidator : ContentTypeModelValidatorBase { - public MediaTypeModelValidator(IModelsBuilderConfig config) : base(config) + public MediaTypeModelValidator(IOptionsSnapshot config) : base(config) { } } diff --git a/src/Umbraco.ModelsBuilder.Embedded/BackOffice/ModelsBuilderDashboardController.cs b/src/Umbraco.ModelsBuilder.Embedded/BackOffice/ModelsBuilderDashboardController.cs index 17b694de56..92f42121e2 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/BackOffice/ModelsBuilderDashboardController.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/BackOffice/ModelsBuilderDashboardController.cs @@ -3,8 +3,10 @@ using System.Net; using System.Net.Http; using System.Runtime.Serialization; using System.Web.Hosting; +using Microsoft.Extensions.Options; using Umbraco.Configuration; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Exceptions; using Umbraco.ModelsBuilder.Embedded.Building; using Umbraco.Web.Editors; @@ -23,20 +25,20 @@ namespace Umbraco.ModelsBuilder.Embedded.BackOffice [UmbracoApplicationAuthorize(Core.Constants.Applications.Settings)] public class ModelsBuilderDashboardController : UmbracoAuthorizedJsonController { - private readonly IModelsBuilderConfig _config; + private readonly ModelsBuilderConfig _config; private readonly ModelsGenerator _modelGenerator; private readonly OutOfDateModelsStatus _outOfDateModels; private readonly ModelsGenerationError _mbErrors; private readonly DashboardReport _dashboardReport; - public ModelsBuilderDashboardController(IModelsBuilderConfig config, ModelsGenerator modelsGenerator, OutOfDateModelsStatus outOfDateModels, ModelsGenerationError mbErrors) + public ModelsBuilderDashboardController(IOptionsSnapshot config, ModelsGenerator modelsGenerator, OutOfDateModelsStatus outOfDateModels, ModelsGenerationError mbErrors) { //_umbracoServices = umbracoServices; - _config = config; + _config = config.Value; _modelGenerator = modelsGenerator; _outOfDateModels = outOfDateModels; _mbErrors = mbErrors; - _dashboardReport = new DashboardReport(config, outOfDateModels, mbErrors); + _dashboardReport = new DashboardReport(_config, outOfDateModels, mbErrors); } // invoked by the dashboard diff --git a/src/Umbraco.ModelsBuilder.Embedded/Building/Builder.cs b/src/Umbraco.ModelsBuilder.Embedded/Building/Builder.cs index f64e5ed1ce..c053f94649 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/Building/Builder.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/Building/Builder.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using Umbraco.Core; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; namespace Umbraco.ModelsBuilder.Embedded.Building { @@ -70,7 +71,7 @@ namespace Umbraco.ModelsBuilder.Embedded.Building /// /// The list of models to generate. /// The models namespace. - protected Builder(IModelsBuilderConfig config, IList typeModels) + protected Builder(ModelsBuilderConfig config, IList typeModels) { _typeModels = typeModels ?? throw new ArgumentNullException(nameof(typeModels)); diff --git a/src/Umbraco.ModelsBuilder.Embedded/Building/ModelsGenerator.cs b/src/Umbraco.ModelsBuilder.Embedded/Building/ModelsGenerator.cs index 648a2e76fa..29da569102 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/Building/ModelsGenerator.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/Building/ModelsGenerator.cs @@ -1,6 +1,7 @@ using System.IO; using System.Text; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.IO; namespace Umbraco.ModelsBuilder.Embedded.Building @@ -8,11 +9,11 @@ namespace Umbraco.ModelsBuilder.Embedded.Building public class ModelsGenerator { private readonly UmbracoServices _umbracoService; - private readonly IModelsBuilderConfig _config; + private readonly ModelsBuilderConfig _config; private readonly OutOfDateModelsStatus _outOfDateModels; private readonly IIOHelper _ioHelper; - public ModelsGenerator(UmbracoServices umbracoService, IModelsBuilderConfig config, OutOfDateModelsStatus outOfDateModels, IIOHelper ioHelper) + public ModelsGenerator(UmbracoServices umbracoService, ModelsBuilderConfig config, OutOfDateModelsStatus outOfDateModels, IIOHelper ioHelper) { _umbracoService = umbracoService; _config = config; diff --git a/src/Umbraco.ModelsBuilder.Embedded/Building/TextBuilder.cs b/src/Umbraco.ModelsBuilder.Embedded/Building/TextBuilder.cs index 723ee10f35..6caca6c8ab 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/Building/TextBuilder.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/Building/TextBuilder.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Text.RegularExpressions; -using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; namespace Umbraco.ModelsBuilder.Embedded.Building { @@ -17,7 +17,7 @@ namespace Umbraco.ModelsBuilder.Embedded.Building /// and the result of code parsing. /// /// The list of models to generate. - public TextBuilder(IModelsBuilderConfig config, IList typeModels) + public TextBuilder(ModelsBuilderConfig config, IList typeModels) : base(config, typeModels) { } diff --git a/src/Umbraco.ModelsBuilder.Embedded/Compose/ModelsBuilderComponent.cs b/src/Umbraco.ModelsBuilder.Embedded/Compose/ModelsBuilderComponent.cs index 32cfd3057e..a794f45616 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/Compose/ModelsBuilderComponent.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/Compose/ModelsBuilderComponent.cs @@ -15,19 +15,21 @@ using Umbraco.ModelsBuilder.Embedded.BackOffice; using Umbraco.Web; using Umbraco.Web.Mvc; using Umbraco.Web.WebAssets; +using Umbraco.Core.Configuration.Models; +using Microsoft.Extensions.Options; namespace Umbraco.ModelsBuilder.Embedded.Compose { internal class ModelsBuilderComponent : IComponent { - private readonly IModelsBuilderConfig _config; + private readonly ModelsBuilderConfig _config; private readonly IShortStringHelper _shortStringHelper; private readonly LiveModelsProvider _liveModelsProvider; private readonly OutOfDateModelsStatus _outOfDateModels; - public ModelsBuilderComponent(IModelsBuilderConfig config, IShortStringHelper shortStringHelper, LiveModelsProvider liveModelsProvider, OutOfDateModelsStatus outOfDateModels) + public ModelsBuilderComponent(IOptionsSnapshot config, IShortStringHelper shortStringHelper, LiveModelsProvider liveModelsProvider, OutOfDateModelsStatus outOfDateModels) { - _config = config; + _config = config.Value; _shortStringHelper = shortStringHelper; _liveModelsProvider = liveModelsProvider; _outOfDateModels = outOfDateModels; diff --git a/src/Umbraco.ModelsBuilder.Embedded/LiveModelsProvider.cs b/src/Umbraco.ModelsBuilder.Embedded/LiveModelsProvider.cs index 61d39cd373..e1ba236839 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/LiveModelsProvider.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/LiveModelsProvider.cs @@ -6,6 +6,7 @@ using Umbraco.Core.Hosting; using Umbraco.Core.Logging; using Umbraco.ModelsBuilder.Embedded.Building; using Umbraco.Web.Cache; +using Umbraco.Core.Configuration.Models; namespace Umbraco.ModelsBuilder.Embedded { @@ -15,7 +16,7 @@ namespace Umbraco.ModelsBuilder.Embedded private static Mutex _mutex; private static int _req; private readonly ILogger _logger; - private readonly IModelsBuilderConfig _config; + private readonly ModelsBuilderConfig _config; private readonly ModelsGenerator _modelGenerator; private readonly ModelsGenerationError _mbErrors; private readonly IHostingEnvironment _hostingEnvironment; @@ -23,7 +24,7 @@ namespace Umbraco.ModelsBuilder.Embedded // we do not manage pure live here internal bool IsEnabled => _config.ModelsMode.IsLiveNotPure(); - public LiveModelsProvider(ILogger logger, IModelsBuilderConfig config, ModelsGenerator modelGenerator, ModelsGenerationError mbErrors, IHostingEnvironment hostingEnvironment) + public LiveModelsProvider(ILogger logger, ModelsBuilderConfig config, ModelsGenerator modelGenerator, ModelsGenerationError mbErrors, IHostingEnvironment hostingEnvironment) { _logger = logger; _config = config ?? throw new ArgumentNullException(nameof(config)); diff --git a/src/Umbraco.ModelsBuilder.Embedded/ModelsGenerationError.cs b/src/Umbraco.ModelsBuilder.Embedded/ModelsGenerationError.cs index f8f6e8c7bc..0181701f1f 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/ModelsGenerationError.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/ModelsGenerationError.cs @@ -2,16 +2,17 @@ using System.IO; using System.Text; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.IO; namespace Umbraco.ModelsBuilder.Embedded { public sealed class ModelsGenerationError { - private readonly IModelsBuilderConfig _config; + private readonly ModelsBuilderConfig _config; private readonly IIOHelper _ioHelper; - public ModelsGenerationError(IModelsBuilderConfig config, IIOHelper ioHelper) + public ModelsGenerationError(ModelsBuilderConfig config, IIOHelper ioHelper) { _config = config; _ioHelper = ioHelper; diff --git a/src/Umbraco.ModelsBuilder.Embedded/OutOfDateModelsStatus.cs b/src/Umbraco.ModelsBuilder.Embedded/OutOfDateModelsStatus.cs index b8105eeef2..4fb23ad5b3 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/OutOfDateModelsStatus.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/OutOfDateModelsStatus.cs @@ -1,5 +1,6 @@ using System.IO; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.IO; using Umbraco.Web.Cache; @@ -7,10 +8,10 @@ namespace Umbraco.ModelsBuilder.Embedded { public sealed class OutOfDateModelsStatus { - private readonly IModelsBuilderConfig _config; + private readonly ModelsBuilderConfig _config; private readonly IIOHelper _ioHelper; - public OutOfDateModelsStatus(IModelsBuilderConfig config, IIOHelper ioHelper) + public OutOfDateModelsStatus(ModelsBuilderConfig config, IIOHelper ioHelper) { _config = config; _ioHelper = ioHelper; diff --git a/src/Umbraco.ModelsBuilder.Embedded/PureLiveModelFactory.cs b/src/Umbraco.ModelsBuilder.Embedded/PureLiveModelFactory.cs index 7809d2bf48..6e5ba18888 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/PureLiveModelFactory.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/PureLiveModelFactory.cs @@ -19,6 +19,8 @@ using Umbraco.Core.Logging; using Umbraco.Core.Models.PublishedContent; using Umbraco.ModelsBuilder.Embedded.Building; using File = System.IO.File; +using Umbraco.Core.Configuration.Models; +using Microsoft.Extensions.Options; namespace Umbraco.ModelsBuilder.Embedded { @@ -41,7 +43,7 @@ namespace Umbraco.ModelsBuilder.Embedded private const string ProjVirt = "~/App_Data/Models/all.generated.cs"; private static readonly string[] OurFiles = { "models.hash", "models.generated.cs", "all.generated.cs", "all.dll.path", "models.err" }; - private readonly IModelsBuilderConfig _config; + private readonly ModelsBuilderConfig _config; private readonly IApplicationShutdownRegistry _hostingLifetime; private readonly IIOHelper _ioHelper; private readonly ModelsGenerationError _errors; @@ -49,7 +51,7 @@ namespace Umbraco.ModelsBuilder.Embedded public PureLiveModelFactory( Lazy umbracoServices, IProfilingLogger logger, - IModelsBuilderConfig config, + IOptionsSnapshot config, IHostingEnvironment hostingEnvironment, IApplicationShutdownRegistry hostingLifetime, IIOHelper ioHelper) diff --git a/src/Umbraco.PublishedCache.NuCache/ContentCache.cs b/src/Umbraco.PublishedCache.NuCache/ContentCache.cs index 337c61b30f..470a224dc8 100644 --- a/src/Umbraco.PublishedCache.NuCache/ContentCache.cs +++ b/src/Umbraco.PublishedCache.NuCache/ContentCache.cs @@ -3,9 +3,11 @@ using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Xml.XPath; +using Microsoft.Extensions.Options; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Xml; using Umbraco.Core.Xml.XPath; @@ -19,7 +21,7 @@ namespace Umbraco.Web.PublishedCache.NuCache private readonly IAppCache _snapshotCache; private readonly IAppCache _elementsCache; private readonly IDomainCache _domainCache; - private readonly IGlobalSettings _globalSettings; + private readonly GlobalSettings _globalSettings; private readonly IVariationContextAccessor _variationContextAccessor; #region Constructor @@ -29,7 +31,12 @@ namespace Umbraco.Web.PublishedCache.NuCache // it's too late for UmbracoContext which has captured previewDefault and stuff into these ctor vars // but, no, UmbracoContext returns snapshot.Content which comes from elements SO a resync should create a new cache - public ContentCache(bool previewDefault, ContentStore.Snapshot snapshot, IAppCache snapshotCache, IAppCache elementsCache, IDomainCache domainCache, IGlobalSettings globalSettings, IVariationContextAccessor variationContextAccessor) + public ContentCache(bool previewDefault, ContentStore.Snapshot snapshot, IAppCache snapshotCache, IAppCache elementsCache, IDomainCache domainCache, IOptionsSnapshot globalSettings, IVariationContextAccessor variationContextAccessor) + : this(previewDefault, snapshot, snapshotCache, elementsCache, domainCache, globalSettings.Value, variationContextAccessor) + { + } + + public ContentCache(bool previewDefault, ContentStore.Snapshot snapshot, IAppCache snapshotCache, IAppCache elementsCache, IDomainCache domainCache, GlobalSettings globalSettings, IVariationContextAccessor variationContextAccessor) : base(previewDefault) { _snapshot = snapshot; diff --git a/src/Umbraco.PublishedCache.NuCache/DataSource/BTree.cs b/src/Umbraco.PublishedCache.NuCache/DataSource/BTree.cs index 00e7fd34d1..ae7393a91a 100644 --- a/src/Umbraco.PublishedCache.NuCache/DataSource/BTree.cs +++ b/src/Umbraco.PublishedCache.NuCache/DataSource/BTree.cs @@ -2,12 +2,13 @@ using CSharpTest.Net.Collections; using CSharpTest.Net.Serialization; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; namespace Umbraco.Web.PublishedCache.NuCache.DataSource { internal class BTree { - public static BPlusTree GetTree(string filepath, bool exists, INuCacheSettings settings) + public static BPlusTree GetTree(string filepath, bool exists, NuCacheSettings settings) { var keySerializer = new PrimitiveSerializer(); var valueSerializer = new ContentNodeKitSerializer(); @@ -22,7 +23,6 @@ namespace Umbraco.Web.PublishedCache.NuCache.DataSource // default is 4096, min 2^9 = 512, max 2^16 = 64K FileBlockSize = GetBlockSize(settings), - //HACK: Forces FileOptions to be WriteThrough here: https://github.com/mamift/CSharpTest.Net.Collections/blob/9f93733b3af7ee0e2de353e822ff54d908209b0b/src/CSharpTest.Net.Collections/IO/TransactedCompoundFile.cs#L316-L327, // as the reflection uses otherwise will failed in .NET Core as the "_handle" field in FileStream is renamed to "_fileHandle". StoragePerformance = StoragePerformance.CommitToDisk, @@ -40,7 +40,7 @@ namespace Umbraco.Web.PublishedCache.NuCache.DataSource return tree; } - private static int GetBlockSize(INuCacheSettings settings) + private static int GetBlockSize(NuCacheSettings settings) { var blockSize = 4096; diff --git a/src/Umbraco.PublishedCache.NuCache/PublishedSnapshotService.cs b/src/Umbraco.PublishedCache.NuCache/PublishedSnapshotService.cs index 815fe0a168..f603ee25ad 100644 --- a/src/Umbraco.PublishedCache.NuCache/PublishedSnapshotService.cs +++ b/src/Umbraco.PublishedCache.NuCache/PublishedSnapshotService.cs @@ -6,11 +6,13 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; using CSharpTest.Net.Collections; +using Microsoft.Extensions.Options; using Newtonsoft.Json; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Composing; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Hosting; using Umbraco.Core.Install; using Umbraco.Core.IO; @@ -45,7 +47,7 @@ namespace Umbraco.Web.PublishedCache.NuCache private readonly IDocumentRepository _documentRepository; private readonly IMediaRepository _mediaRepository; private readonly IMemberRepository _memberRepository; - private readonly IGlobalSettings _globalSettings; + private readonly GlobalSettings _globalSettings; private readonly IEntityXmlSerializer _entitySerializer; private readonly IPublishedModelFactory _publishedModelFactory; private readonly IDefaultCultureAccessor _defaultCultureAccessor; @@ -53,7 +55,7 @@ namespace Umbraco.Web.PublishedCache.NuCache private readonly IHostingEnvironment _hostingEnvironment; private readonly IShortStringHelper _shortStringHelper; private readonly IIOHelper _ioHelper; - private readonly INuCacheSettings _config; + private readonly NuCacheSettings _config; // volatile because we read it with no lock private volatile bool _isReady; @@ -84,14 +86,15 @@ namespace Umbraco.Web.PublishedCache.NuCache IPublishedSnapshotAccessor publishedSnapshotAccessor, IVariationContextAccessor variationContextAccessor, IProfilingLogger logger, IScopeProvider scopeProvider, IDocumentRepository documentRepository, IMediaRepository mediaRepository, IMemberRepository memberRepository, IDefaultCultureAccessor defaultCultureAccessor, - IDataSource dataSource, IGlobalSettings globalSettings, + IDataSource dataSource, + IOptionsSnapshot globalSettings, IEntityXmlSerializer entitySerializer, IPublishedModelFactory publishedModelFactory, UrlSegmentProviderCollection urlSegmentProviders, IHostingEnvironment hostingEnvironment, IShortStringHelper shortStringHelper, IIOHelper ioHelper, - INuCacheSettings config) + IOptionsSnapshot config) : base(publishedSnapshotAccessor, variationContextAccessor) { //if (Interlocked.Increment(ref _singletonCheck) > 1) @@ -106,12 +109,12 @@ namespace Umbraco.Web.PublishedCache.NuCache _mediaRepository = mediaRepository; _memberRepository = memberRepository; _defaultCultureAccessor = defaultCultureAccessor; - _globalSettings = globalSettings; + _globalSettings = globalSettings.Value; _urlSegmentProviders = urlSegmentProviders; _hostingEnvironment = hostingEnvironment; _shortStringHelper = shortStringHelper; _ioHelper = ioHelper; - _config = config; + _config = config.Value; // we need an Xml serializer here so that the member cache can support XPath, // for members this is done by navigating the serialized-to-xml member diff --git a/src/Umbraco.Tests.Common/SettingsForTests.cs b/src/Umbraco.Tests.Common/SettingsForTests.cs index 1a14dc6bc1..e60f6ad0a4 100644 --- a/src/Umbraco.Tests.Common/SettingsForTests.cs +++ b/src/Umbraco.Tests.Common/SettingsForTests.cs @@ -3,7 +3,7 @@ using Moq; using Semver; using Umbraco.Core; using Umbraco.Core.Configuration; -using Umbraco.Core.Configuration.Legacy; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.IO; using Umbraco.Core.Models.PublishedContent; @@ -16,25 +16,23 @@ namespace Umbraco.Tests.Common { } - public IGlobalSettings GenerateMockGlobalSettings(IUmbracoVersion umbVersion = null) + public GlobalSettings GenerateStubGlobalSettings(IUmbracoVersion umbVersion = null) { var semanticVersion = umbVersion?.SemanticVersion ?? new SemVersion(9); - var config = Mock.Of( - settings => - settings.UseHttps == false && - settings.HideTopLevelNodeFromPath == false && - settings.TimeOutInMinutes == 20 && - settings.DefaultUILanguage == "en" && - settings.ReservedPaths == (GlobalSettings.StaticReservedPaths + "~/umbraco") && - settings.ReservedUrls == GlobalSettings.StaticReservedUrls && - settings.UmbracoPath == "~/umbraco" && - settings.UmbracoMediaPath == "~/media" && - settings.UmbracoCssPath == "~/css" && - settings.UmbracoScriptsPath == "~/scripts" - ); - - + var config = new GlobalSettings + { + UseHttps = false, + HideTopLevelNodeFromPath = false, + TimeOutInMinutes = 20, + DefaultUILanguage = "en", + ReservedPaths = (GlobalSettings.StaticReservedPaths + "~/umbraco"), + ReservedUrls = GlobalSettings.StaticReservedUrls, + UmbracoPath = "~/umbraco", + UmbracoMediaPath = "~/media", + UmbracoCssPath = "~/css", + UmbracoScriptsPath = "~/scripts", + }; return config; } @@ -104,15 +102,15 @@ namespace Umbraco.Tests.Common _defaultHostingSettings = null; } - private readonly Dictionary _defaultGlobalSettings = new Dictionary(); + private readonly Dictionary _defaultGlobalSettings = new Dictionary(); private IHostingSettings _defaultHostingSettings; - public IGlobalSettings GetDefaultGlobalSettings(IUmbracoVersion umbVersion) + public GlobalSettings GetDefaultGlobalSettings(IUmbracoVersion umbVersion) { if (_defaultGlobalSettings.TryGetValue(umbVersion.SemanticVersion, out var settings)) return settings; - settings = GenerateMockGlobalSettings(umbVersion); + settings = GenerateStubGlobalSettings(umbVersion); _defaultGlobalSettings[umbVersion.SemanticVersion] = settings; return settings; } diff --git a/src/Umbraco.Tests.Common/TestHelperBase.cs b/src/Umbraco.Tests.Common/TestHelperBase.cs index 3a6d099e46..461cbf4097 100644 --- a/src/Umbraco.Tests.Common/TestHelperBase.cs +++ b/src/Umbraco.Tests.Common/TestHelperBase.cs @@ -90,7 +90,7 @@ namespace Umbraco.Tests.Common get { if (_ioHelper == null) - _ioHelper = new IOHelper(GetHostingEnvironment(), SettingsForTests.GenerateMockGlobalSettings()); + _ioHelper = new IOHelper(GetHostingEnvironment(), SettingsForTests.GenerateStubGlobalSettings()); return _ioHelper; } } diff --git a/src/Umbraco.Tests.Integration/Implementations/TestHostingEnvironment.cs b/src/Umbraco.Tests.Integration/Implementations/TestHostingEnvironment.cs index 076cecef4a..73076522c8 100644 --- a/src/Umbraco.Tests.Integration/Implementations/TestHostingEnvironment.cs +++ b/src/Umbraco.Tests.Integration/Implementations/TestHostingEnvironment.cs @@ -1,6 +1,6 @@ using Microsoft.AspNetCore.Hosting; -using Umbraco.Core.Configuration; -using Umbraco.Core.Logging; +using Microsoft.Extensions.Options; +using Umbraco.Core.Configuration.Models; using Umbraco.Web.Common.AspNetCore; using IHostingEnvironment = Umbraco.Core.Hosting.IHostingEnvironment; @@ -9,7 +9,7 @@ namespace Umbraco.Tests.Integration.Implementations public class TestHostingEnvironment : AspNetCoreHostingEnvironment, IHostingEnvironment { - public TestHostingEnvironment(IHostingSettings hostingSettings, IWebHostEnvironment webHostEnvironment) + public TestHostingEnvironment(IOptionsSnapshot hostingSettings, IWebHostEnvironment webHostEnvironment) : base(hostingSettings, webHostEnvironment) { } diff --git a/src/Umbraco.Tests.Integration/Umbraco.Web.BackOffice.Security/BackOfficeCookieManagerTests.cs b/src/Umbraco.Tests.Integration/Umbraco.Web.BackOffice.Security/BackOfficeCookieManagerTests.cs index 3464259052..a25a21f27c 100644 --- a/src/Umbraco.Tests.Integration/Umbraco.Web.BackOffice.Security/BackOfficeCookieManagerTests.cs +++ b/src/Umbraco.Tests.Integration/Umbraco.Web.BackOffice.Security/BackOfficeCookieManagerTests.cs @@ -25,7 +25,7 @@ namespace Umbraco.Tests.Security var testHelper = new TestHelper(); var httpContextAccessor = testHelper.GetHttpContextAccessor(); - var globalSettings = testHelper.SettingsForTests.GenerateMockGlobalSettings(); + var globalSettings = testHelper.SettingsForTests.GenerateStubGlobalSettings(); var runtime = Mock.Of(x => x.Level == RuntimeLevel.Install); var mgr = new BackOfficeCookieManager( @@ -50,7 +50,7 @@ namespace Umbraco.Tests.Security //hostingEnvironment.ToAbsolute(globalSettings.UmbracoPath); var httpContextAccessor = testHelper.GetHttpContextAccessor(); - var globalSettings = testHelper.SettingsForTests.GenerateMockGlobalSettings(); + var globalSettings = testHelper.SettingsForTests.GenerateStubGlobalSettings(); var runtime = Mock.Of(x => x.Level == RuntimeLevel.Run); var mgr = new BackOfficeCookieManager( @@ -72,7 +72,7 @@ namespace Umbraco.Tests.Security var testHelper = new TestHelper(); var httpContextAccessor = testHelper.GetHttpContextAccessor(); - var globalSettings = testHelper.SettingsForTests.GenerateMockGlobalSettings(); + var globalSettings = testHelper.SettingsForTests.GenerateStubGlobalSettings(); var runtime = Mock.Of(x => x.Level == RuntimeLevel.Run); @@ -97,7 +97,7 @@ namespace Umbraco.Tests.Security var testHelper = new TestHelper(); var httpContextAccessor = testHelper.GetHttpContextAccessor(); - var globalSettings = testHelper.SettingsForTests.GenerateMockGlobalSettings(); + var globalSettings = testHelper.SettingsForTests.GenerateStubGlobalSettings(); var runtime = Mock.Of(x => x.Level == RuntimeLevel.Run); @@ -119,7 +119,7 @@ namespace Umbraco.Tests.Security var testHelper = new TestHelper(); var httpContextAccessor = testHelper.GetHttpContextAccessor(); - var globalSettings = testHelper.SettingsForTests.GenerateMockGlobalSettings(); + var globalSettings = testHelper.SettingsForTests.GenerateStubGlobalSettings(); var runtime = Mock.Of(x => x.Level == RuntimeLevel.Run); diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Core/Extensions/UriExtensionsTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Extensions/UriExtensionsTests.cs index 4c8903735a..71ef0e1bdb 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Core/Extensions/UriExtensionsTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Extensions/UriExtensionsTests.cs @@ -18,7 +18,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Core.Extensions { _settingsForTests = new SettingsForTests(); _hostEnvironment = Mock.Of(); - _globalSettings = _settingsForTests.GenerateMockGlobalSettings(); + _globalSettings = _settingsForTests.GenerateStubGlobalSettings(); } private SettingsForTests _settingsForTests; diff --git a/src/Umbraco.Tests/TestHelpers/SettingsForTests.cs b/src/Umbraco.Tests/TestHelpers/SettingsForTests.cs index b58301287b..6abe44d0fd 100644 --- a/src/Umbraco.Tests/TestHelpers/SettingsForTests.cs +++ b/src/Umbraco.Tests/TestHelpers/SettingsForTests.cs @@ -1,4 +1,5 @@ using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Configuration.UmbracoSettings; namespace Umbraco.Tests.TestHelpers @@ -7,7 +8,7 @@ namespace Umbraco.Tests.TestHelpers { private static Common.SettingsForTests _settingsForTests = new Common.SettingsForTests(); - public static IGlobalSettings GenerateMockGlobalSettings() => _settingsForTests.GenerateMockGlobalSettings(TestHelper.GetUmbracoVersion()); + public static IGlobalSettings GenerateMockGlobalSettings() => _settingsForTests.GenerateStubGlobalSettings(TestHelper.GetUmbracoVersion()); /// /// Returns generated settings which can be stubbed to return whatever values necessary @@ -45,7 +46,7 @@ namespace Umbraco.Tests.TestHelpers public static void Reset() => _settingsForTests.Reset(); - internal static IGlobalSettings DefaultGlobalSettings => _settingsForTests.GetDefaultGlobalSettings(TestHelper.GetUmbracoVersion()); + internal static GlobalSettings DefaultGlobalSettings => _settingsForTests.GetDefaultGlobalSettings(TestHelper.GetUmbracoVersion()); internal static IHostingSettings DefaultHostingSettings => _settingsForTests.DefaultHostingSettings; diff --git a/src/Umbraco.Tests/TestHelpers/TestHelper.cs b/src/Umbraco.Tests/TestHelpers/TestHelper.cs index e9f05f43fc..08b21dda8d 100644 --- a/src/Umbraco.Tests/TestHelpers/TestHelper.cs +++ b/src/Umbraco.Tests/TestHelpers/TestHelper.cs @@ -58,7 +58,7 @@ namespace Umbraco.Tests.TestHelpers public override IBackOfficeInfo GetBackOfficeInfo() => new AspNetBackOfficeInfo( - SettingsForTests.GenerateMockGlobalSettings(GetUmbracoVersion()), + SettingsForTests.GenerateStubGlobalSettings(GetUmbracoVersion()), TestHelper.IOHelper, Mock.Of(), SettingsForTests.GenerateMockWebRoutingSettings()); public override IHostingEnvironment GetHostingEnvironment() diff --git a/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs b/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs index 1b63bcc98d..24aa171c87 100644 --- a/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs +++ b/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs @@ -8,6 +8,7 @@ using Moq; using Umbraco.Core; using Umbraco.Core.Composing; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Models; @@ -136,10 +137,11 @@ namespace Umbraco.Tests.TestHelpers return umbracoContextFactory.EnsureUmbracoContext().UmbracoContext; } - public IGlobalSettings GetGlobalSettings() + public GlobalSettings GetGlobalSettings() { return SettingsForTests.DefaultGlobalSettings; } + public IFileSystems GetFileSystemsMock() { var fileSystems = Mock.Of(); diff --git a/src/Umbraco.Web.BackOffice/Controllers/AuthenticationController.cs b/src/Umbraco.Web.BackOffice/Controllers/AuthenticationController.cs index a82dda52c7..dc22d24f05 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/AuthenticationController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/AuthenticationController.cs @@ -45,7 +45,7 @@ namespace Umbraco.Web.BackOffice.Controllers private readonly IUserService _userService; private readonly ILocalizedTextService _textService; private readonly UmbracoMapper _umbracoMapper; - private readonly IGlobalSettings _globalSettings; + private readonly GlobalSettings _globalSettings; private readonly SecuritySettings _securitySettings; private readonly ILogger _logger; private readonly IIpResolver _ipResolver; @@ -64,7 +64,7 @@ namespace Umbraco.Web.BackOffice.Controllers IUserService userService, ILocalizedTextService textService, UmbracoMapper umbracoMapper, - IGlobalSettings globalSettings, + IOptionsSnapshot globalSettings, IOptionsSnapshot securitySettings, ILogger logger, IIpResolver ipResolver, @@ -79,7 +79,7 @@ namespace Umbraco.Web.BackOffice.Controllers _userService = userService; _textService = textService; _umbracoMapper = umbracoMapper; - _globalSettings = globalSettings; + _globalSettings = globalSettings.Value; _securitySettings = securitySettings.Value; _logger = logger; _ipResolver = ipResolver; diff --git a/src/Umbraco.Web.BackOffice/Controllers/BackOfficeAssetsController.cs b/src/Umbraco.Web.BackOffice/Controllers/BackOfficeAssetsController.cs index 7cbeb8e86e..916b422b33 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/BackOfficeAssetsController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/BackOfficeAssetsController.cs @@ -3,8 +3,10 @@ using System.Collections.Generic; using System.IO; using System.Linq; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Options; using Umbraco.Core; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Hosting; using Umbraco.Core.IO; using Umbraco.Core.Logging; @@ -17,9 +19,9 @@ namespace Umbraco.Web.BackOffice.Controllers { private readonly IFileSystem _jsLibFileSystem; - public BackOfficeAssetsController(IIOHelper ioHelper, IHostingEnvironment hostingEnvironment, ILogger logger, IGlobalSettings globalSettings) + public BackOfficeAssetsController(IIOHelper ioHelper, IHostingEnvironment hostingEnvironment, ILogger logger, IOptionsSnapshot globalSettings) { - _jsLibFileSystem = new PhysicalFileSystem(ioHelper, hostingEnvironment, logger, globalSettings.UmbracoPath + Path.DirectorySeparatorChar + "lib"); + _jsLibFileSystem = new PhysicalFileSystem(ioHelper, hostingEnvironment, logger, globalSettings.Value.UmbracoPath + Path.DirectorySeparatorChar + "lib"); } [HttpGet] diff --git a/src/Umbraco.Web.BackOffice/Controllers/BackOfficeController.cs b/src/Umbraco.Web.BackOffice/Controllers/BackOfficeController.cs index 1970205ebc..4672d48d88 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/BackOfficeController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/BackOfficeController.cs @@ -5,13 +5,14 @@ using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; -using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Options; using Umbraco.Core; using Umbraco.Core.BackOffice; using Umbraco.Core.Cache; using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.Grid; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Hosting; using Umbraco.Core.Logging; using Umbraco.Core.Services; @@ -35,7 +36,7 @@ namespace Umbraco.Web.BackOffice.Controllers { private readonly BackOfficeUserManager _userManager; private readonly IRuntimeMinifier _runtimeMinifier; - private readonly IGlobalSettings _globalSettings; + private readonly GlobalSettings _globalSettings; private readonly IHostingEnvironment _hostingEnvironment; private readonly IUmbracoContextAccessor _umbracoContextAccessor; private readonly ILocalizedTextService _textService; @@ -49,7 +50,7 @@ namespace Umbraco.Web.BackOffice.Controllers public BackOfficeController( BackOfficeUserManager userManager, IRuntimeMinifier runtimeMinifier, - IGlobalSettings globalSettings, + IOptionsSnapshot globalSettings, IHostingEnvironment hostingEnvironment, IUmbracoContextAccessor umbracoContextAccessor, ILocalizedTextService textService, @@ -59,11 +60,10 @@ namespace Umbraco.Web.BackOffice.Controllers BackOfficeSignInManager signInManager, IWebSecurity webSecurity, ILogger logger) - { _userManager = userManager; _runtimeMinifier = runtimeMinifier; - _globalSettings = globalSettings; + _globalSettings = globalSettings.Value; _hostingEnvironment = hostingEnvironment; _umbracoContextAccessor = umbracoContextAccessor; _textService = textService; diff --git a/src/Umbraco.Web.BackOffice/Controllers/BackOfficeServerVariables.cs b/src/Umbraco.Web.BackOffice/Controllers/BackOfficeServerVariables.cs index 2768770e65..3305a7bbb1 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/BackOfficeServerVariables.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/BackOfficeServerVariables.cs @@ -31,7 +31,7 @@ namespace Umbraco.Web.BackOffice.Controllers private readonly LinkGenerator _linkGenerator; private readonly IRuntimeState _runtimeState; private readonly UmbracoFeatures _features; - private readonly IGlobalSettings _globalSettings; + private readonly GlobalSettings _globalSettings; private readonly IUmbracoVersion _umbracoVersion; private readonly ContentSettings _contentSettings; private readonly TreeCollection _treeCollection; @@ -46,7 +46,7 @@ namespace Umbraco.Web.BackOffice.Controllers LinkGenerator linkGenerator, IRuntimeState runtimeState, UmbracoFeatures features, - IGlobalSettings globalSettings, + IOptionsSnapshot globalSettings, IUmbracoVersion umbracoVersion, IOptionsSnapshot contentSettings, IHttpContextAccessor httpContextAccessor, @@ -60,7 +60,7 @@ namespace Umbraco.Web.BackOffice.Controllers _linkGenerator = linkGenerator; _runtimeState = runtimeState; _features = features; - _globalSettings = globalSettings; + _globalSettings = globalSettings.Value; _umbracoVersion = umbracoVersion; _contentSettings = contentSettings.Value ?? throw new ArgumentNullException(nameof(contentSettings)); _httpContextAccessor = httpContextAccessor; diff --git a/src/Umbraco.Web.BackOffice/Controllers/CodeFileController.cs b/src/Umbraco.Web.BackOffice/Controllers/CodeFileController.cs index 621f3a0e78..7fdfc81cd1 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/CodeFileController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/CodeFileController.cs @@ -3,11 +3,10 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; -using System.Net.Http; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Options; using Umbraco.Core; -using Umbraco.Core.Configuration; -using Umbraco.Core.Configuration.Legacy; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.IO; using Umbraco.Core.Mapping; using Umbraco.Core.Models; @@ -15,15 +14,13 @@ using Umbraco.Core.Services; using Umbraco.Core.Strings; using Umbraco.Core.Strings.Css; using Umbraco.Extensions; -using Umbraco.Web.Models.ContentEditing; -using Stylesheet = Umbraco.Core.Models.Stylesheet; -using StylesheetRule = Umbraco.Web.Models.ContentEditing.StylesheetRule; using Umbraco.Web.BackOffice.Filters; using Umbraco.Web.Common.ActionsResults; using Umbraco.Web.Common.Attributes; using Umbraco.Web.Common.Exceptions; -using Umbraco.Web.Editors; -using Umbraco.Web.BackOffice.Trees; +using Umbraco.Web.Models.ContentEditing; +using Stylesheet = Umbraco.Core.Models.Stylesheet; +using StylesheetRule = Umbraco.Web.Models.ContentEditing.StylesheetRule; namespace Umbraco.Web.BackOffice.Controllers { @@ -41,7 +38,7 @@ namespace Umbraco.Web.BackOffice.Controllers private readonly ILocalizedTextService _localizedTextService; private readonly UmbracoMapper _umbracoMapper; private readonly IShortStringHelper _shortStringHelper; - private readonly IGlobalSettings _globalSettings; + private readonly GlobalSettings _globalSettings; public CodeFileController( IIOHelper ioHelper, @@ -51,9 +48,8 @@ namespace Umbraco.Web.BackOffice.Controllers ILocalizedTextService localizedTextService, UmbracoMapper umbracoMapper, IShortStringHelper shortStringHelper, - IGlobalSettings globalSettings) + IOptionsSnapshot globalSettings) { - _ioHelper = ioHelper; _fileSystems = fileSystems; _fileService = fileService; @@ -61,7 +57,7 @@ namespace Umbraco.Web.BackOffice.Controllers _localizedTextService = localizedTextService; _umbracoMapper = umbracoMapper; _shortStringHelper = shortStringHelper; - _globalSettings = globalSettings; + _globalSettings = globalSettings.Value; } /// diff --git a/src/Umbraco.Web.BackOffice/Controllers/ContentTypeController.cs b/src/Umbraco.Web.BackOffice/Controllers/ContentTypeController.cs index 444667b591..28a09942dd 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/ContentTypeController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/ContentTypeController.cs @@ -39,6 +39,8 @@ using Umbraco.Web.Editors; using Umbraco.Web.Routing; using Umbraco.Web.Security; using ContentType = Umbraco.Core.Models.ContentType; +using Umbraco.Core.Configuration.Models; +using Microsoft.Extensions.Options; namespace Umbraco.Web.BackOffice.Controllers { @@ -55,7 +57,7 @@ namespace Umbraco.Web.BackOffice.Controllers public class ContentTypeController : ContentTypeControllerBase { private readonly IEntityXmlSerializer _serializer; - private readonly IGlobalSettings _globalSettings; + private readonly GlobalSettings _globalSettings; private readonly PropertyEditorCollection _propertyEditors; private readonly IScopeProvider _scopeProvider; private readonly IIOHelper _ioHelper; @@ -74,7 +76,6 @@ namespace Umbraco.Web.BackOffice.Controllers private readonly IEntityService _entityService; private readonly IHostingEnvironment _hostingEnvironment; - public ContentTypeController( ICultureDictionary cultureDictionary, EditorValidatorCollection editorValidatorCollection, @@ -84,7 +85,7 @@ namespace Umbraco.Web.BackOffice.Controllers UmbracoMapper umbracoMapper, ILocalizedTextService localizedTextService, IEntityXmlSerializer serializer, - IGlobalSettings globalSettings, + IOptionsSnapshot globalSettings, PropertyEditorCollection propertyEditors, IScopeProvider scopeProvider, IIOHelper ioHelper, @@ -108,7 +109,7 @@ namespace Umbraco.Web.BackOffice.Controllers localizedTextService) { _serializer = serializer; - _globalSettings = globalSettings; + _globalSettings = globalSettings.Value; _propertyEditors = propertyEditors; _scopeProvider = scopeProvider; _ioHelper = ioHelper; diff --git a/src/Umbraco.Web.BackOffice/Controllers/DashboardController.cs b/src/Umbraco.Web.BackOffice/Controllers/DashboardController.cs index 03bbe132f3..8970a70b34 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/DashboardController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/DashboardController.cs @@ -43,7 +43,6 @@ namespace Umbraco.Web.BackOffice.Controllers /// Initializes a new instance of the with all its dependencies. /// public DashboardController( - IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, diff --git a/src/Umbraco.Web.BackOffice/Controllers/DictionaryController.cs b/src/Umbraco.Web.BackOffice/Controllers/DictionaryController.cs index 7d362e52b6..b0b18c8da3 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/DictionaryController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/DictionaryController.cs @@ -15,6 +15,8 @@ using Umbraco.Web.Common.Exceptions; using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Security; using Constants = Umbraco.Core.Constants; +using Umbraco.Core.Configuration.Models; +using Microsoft.Extensions.Options; namespace Umbraco.Web.BackOffice.Controllers { @@ -33,7 +35,7 @@ namespace Umbraco.Web.BackOffice.Controllers private readonly ILogger _logger; private readonly ILocalizationService _localizationService; private readonly IWebSecurity _webSecurity; - private readonly IGlobalSettings _globalSettings; + private readonly GlobalSettings _globalSettings; private readonly ILocalizedTextService _localizedTextService; private readonly UmbracoMapper _umbracoMapper; @@ -41,7 +43,7 @@ namespace Umbraco.Web.BackOffice.Controllers ILogger logger, ILocalizationService localizationService, IWebSecurity webSecurity, - IGlobalSettings globalSettings, + IOptionsSnapshot globalSettings, ILocalizedTextService localizedTextService, UmbracoMapper umbracoMapper ) @@ -49,7 +51,7 @@ namespace Umbraco.Web.BackOffice.Controllers _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _localizationService = localizationService ?? throw new ArgumentNullException(nameof(localizationService)); _webSecurity = webSecurity ?? throw new ArgumentNullException(nameof(webSecurity)); - _globalSettings = globalSettings ?? throw new ArgumentNullException(nameof(globalSettings)); + _globalSettings = globalSettings.Value ?? throw new ArgumentNullException(nameof(globalSettings)); _localizedTextService = localizedTextService ?? throw new ArgumentNullException(nameof(localizedTextService)); _umbracoMapper = umbracoMapper ?? throw new ArgumentNullException(nameof(umbracoMapper)); } diff --git a/src/Umbraco.Web.BackOffice/Controllers/LanguageController.cs b/src/Umbraco.Web.BackOffice/Controllers/LanguageController.cs index 14667c1fe5..0a58c04443 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/LanguageController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/LanguageController.cs @@ -3,8 +3,10 @@ using System.Collections.Generic; using System.Globalization; using System.Linq; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Options; using Umbraco.Core; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Mapping; using Umbraco.Core.Models; using Umbraco.Core.Services; @@ -25,15 +27,15 @@ namespace Umbraco.Web.BackOffice.Controllers { private readonly ILocalizationService _localizationService; private readonly UmbracoMapper _umbracoMapper; - private readonly IGlobalSettings _globalSettings; + private readonly GlobalSettings _globalSettings; public LanguageController(ILocalizationService localizationService, UmbracoMapper umbracoMapper, - IGlobalSettings globalSettings) + IOptionsSnapshot globalSettings) { _localizationService = localizationService ?? throw new ArgumentNullException(nameof(localizationService)); _umbracoMapper = umbracoMapper ?? throw new ArgumentNullException(nameof(umbracoMapper)); - _globalSettings = globalSettings ?? throw new ArgumentNullException(nameof(globalSettings)); + _globalSettings = globalSettings.Value ?? throw new ArgumentNullException(nameof(globalSettings)); } /// diff --git a/src/Umbraco.Web.BackOffice/Controllers/PreviewController.cs b/src/Umbraco.Web.BackOffice/Controllers/PreviewController.cs index fec9d23f19..eeb73d6d47 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/PreviewController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/PreviewController.cs @@ -1,11 +1,13 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.ViewEngines; +using Microsoft.Extensions.Options; using System; using System.IO; using System.Threading.Tasks; using Umbraco.Core; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Hosting; using Umbraco.Core.Services; @@ -28,7 +30,7 @@ namespace Umbraco.Web.BackOffice.Controllers public class PreviewController : Controller { private readonly UmbracoFeatures _features; - private readonly IGlobalSettings _globalSettings; + private readonly GlobalSettings _globalSettings; private readonly IPublishedSnapshotService _publishedSnapshotService; private readonly IWebSecurity _webSecurity; private readonly ILocalizationService _localizationService; @@ -39,7 +41,7 @@ namespace Umbraco.Web.BackOffice.Controllers public PreviewController( UmbracoFeatures features, - IGlobalSettings globalSettings, + IOptionsSnapshot globalSettings, IPublishedSnapshotService publishedSnapshotService, IWebSecurity webSecurity, ILocalizationService localizationService, @@ -49,7 +51,7 @@ namespace Umbraco.Web.BackOffice.Controllers ICompositeViewEngine viewEngines) { _features = features; - _globalSettings = globalSettings; + _globalSettings = globalSettings.Value; _publishedSnapshotService = publishedSnapshotService; _webSecurity = webSecurity; _localizationService = localizationService; diff --git a/src/Umbraco.Web.BackOffice/Controllers/RedirectUrlManagementController.cs b/src/Umbraco.Web.BackOffice/Controllers/RedirectUrlManagementController.cs index 5086919b83..c5c5ca91ab 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/RedirectUrlManagementController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/RedirectUrlManagementController.cs @@ -12,6 +12,8 @@ using Umbraco.Core.Mapping; using Umbraco.Core.Services; using Umbraco.Web.Common.Attributes; using Umbraco.Web.Security; +using Umbraco.Core.Configuration.Models; +using Microsoft.Extensions.Options; namespace Umbraco.Web.BackOffice.Controllers { @@ -19,21 +21,21 @@ namespace Umbraco.Web.BackOffice.Controllers public class RedirectUrlManagementController : UmbracoAuthorizedApiController { private readonly ILogger _logger; - private readonly IWebRoutingSettings _webRoutingSettings; + private readonly WebRoutingSettings _webRoutingSettings; private readonly IWebSecurity _webSecurity; private readonly IRedirectUrlService _redirectUrlService; private readonly UmbracoMapper _umbracoMapper; private readonly IHostingEnvironment _hostingEnvironment; public RedirectUrlManagementController(ILogger logger, - IWebRoutingSettings webRoutingSettings, + IOptionsSnapshot webRoutingSettings, IWebSecurity webSecurity, IRedirectUrlService redirectUrlService, UmbracoMapper umbracoMapper, IHostingEnvironment hostingEnvironment) { _logger = logger ?? throw new ArgumentNullException(nameof(logger)); - _webRoutingSettings = webRoutingSettings ?? throw new ArgumentNullException(nameof(webRoutingSettings)); + _webRoutingSettings = webRoutingSettings.Value ?? throw new ArgumentNullException(nameof(webRoutingSettings)); _webSecurity = webSecurity ?? throw new ArgumentNullException(nameof(webSecurity)); _redirectUrlService = redirectUrlService ?? throw new ArgumentNullException(nameof(redirectUrlService)); _umbracoMapper = umbracoMapper ?? throw new ArgumentNullException(nameof(umbracoMapper)); diff --git a/src/Umbraco.Web.BackOffice/Controllers/UpdateCheckController.cs b/src/Umbraco.Web.BackOffice/Controllers/UpdateCheckController.cs index 4212bace72..78ac2713c0 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/UpdateCheckController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/UpdateCheckController.cs @@ -3,10 +3,12 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; +using Microsoft.Extensions.Options; using Semver; using Umbraco.Composing; using Umbraco.Core; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Models; using Umbraco.Core.Services; using Umbraco.Web.Common.Attributes; @@ -22,20 +24,20 @@ namespace Umbraco.Web.BackOffice.Controllers private readonly IUmbracoVersion _umbracoVersion; private readonly ICookieManager _cookieManager; private readonly IWebSecurity _webSecurity; - private readonly IGlobalSettings _globalSettings; + private readonly GlobalSettings _globalSettings; public UpdateCheckController( IUpgradeService upgradeService, IUmbracoVersion umbracoVersion, ICookieManager cookieManager, IWebSecurity webSecurity, - IGlobalSettings globalSettings) + IOptionsSnapshot globalSettings) { _upgradeService = upgradeService ?? throw new ArgumentNullException(nameof(upgradeService)); _umbracoVersion = umbracoVersion ?? throw new ArgumentNullException(nameof(umbracoVersion)); _cookieManager = cookieManager ?? throw new ArgumentNullException(nameof(cookieManager)); _webSecurity = webSecurity ?? throw new ArgumentNullException(nameof(webSecurity)); - _globalSettings = globalSettings ?? throw new ArgumentNullException(nameof(globalSettings)); + _globalSettings = globalSettings.Value ?? throw new ArgumentNullException(nameof(globalSettings)); } [UpdateCheckResponseFilter] @@ -77,11 +79,11 @@ namespace Umbraco.Web.BackOffice.Controllers private class UpdateCheckResponseFilter : IActionFilter { - private readonly IGlobalSettings _globalSettings; + private readonly GlobalSettings _globalSettings; - public UpdateCheckResponseFilter(IGlobalSettings globalSettings) + public UpdateCheckResponseFilter(IOptionsSnapshot globalSettings) { - _globalSettings = globalSettings; + _globalSettings = globalSettings.Value; } public void OnActionExecuted(ActionExecutedContext context) diff --git a/src/Umbraco.Web.BackOffice/Controllers/UsersController.cs b/src/Umbraco.Web.BackOffice/Controllers/UsersController.cs index 07c2cab1c7..ab3f48cdad 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/UsersController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/UsersController.cs @@ -66,7 +66,7 @@ namespace Umbraco.Web.BackOffice.Controllers private readonly IEntityService _entityService; private readonly IMediaService _mediaService; private readonly IContentService _contentService; - private readonly IGlobalSettings _globalSettings; + private readonly GlobalSettings _globalSettings; private readonly BackOfficeUserManager _backOfficeUserManager; private readonly ILogger _logger; private readonly LinkGenerator _linkGenerator; @@ -89,7 +89,7 @@ namespace Umbraco.Web.BackOffice.Controllers IEntityService entityService, IMediaService mediaService, IContentService contentService, - IGlobalSettings globalSettings, + IOptionsSnapshot globalSettings, BackOfficeUserManager backOfficeUserManager, ILogger logger, LinkGenerator linkGenerator) @@ -111,7 +111,7 @@ namespace Umbraco.Web.BackOffice.Controllers _entityService = entityService; _mediaService = mediaService; _contentService = contentService; - _globalSettings = globalSettings; + _globalSettings = globalSettings.Value; _backOfficeUserManager = backOfficeUserManager; _logger = logger; _linkGenerator = linkGenerator; diff --git a/src/Umbraco.Web.BackOffice/Filters/SetAngularAntiForgeryTokensAttribute.cs b/src/Umbraco.Web.BackOffice/Filters/SetAngularAntiForgeryTokensAttribute.cs index e52287b57e..761c1110cb 100644 --- a/src/Umbraco.Web.BackOffice/Filters/SetAngularAntiForgeryTokensAttribute.cs +++ b/src/Umbraco.Web.BackOffice/Filters/SetAngularAntiForgeryTokensAttribute.cs @@ -2,8 +2,9 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; +using Microsoft.Extensions.Options; using Umbraco.Core; -using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Web.BackOffice.Security; namespace Umbraco.Extensions @@ -20,12 +21,12 @@ namespace Umbraco.Extensions private class SetAngularAntiForgeryTokensFilter : IAsyncActionFilter { private readonly IBackOfficeAntiforgery _antiforgery; - private readonly IGlobalSettings _globalSettings; + private readonly GlobalSettings _globalSettings; - public SetAngularAntiForgeryTokensFilter(IBackOfficeAntiforgery antiforgery, IGlobalSettings globalSettings) + public SetAngularAntiForgeryTokensFilter(IBackOfficeAntiforgery antiforgery, IOptionsSnapshot globalSettings) { _antiforgery = antiforgery; - _globalSettings = globalSettings; + _globalSettings = globalSettings.Value; } public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) diff --git a/src/Umbraco.Web.BackOffice/Filters/UmbracoWebApiRequireHttpsAttribute.cs b/src/Umbraco.Web.BackOffice/Filters/UmbracoWebApiRequireHttpsAttribute.cs index 7c7652c532..f3fd82bdf6 100644 --- a/src/Umbraco.Web.BackOffice/Filters/UmbracoWebApiRequireHttpsAttribute.cs +++ b/src/Umbraco.Web.BackOffice/Filters/UmbracoWebApiRequireHttpsAttribute.cs @@ -3,7 +3,8 @@ using System.Net; using System.Net.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; -using Umbraco.Core.Configuration; +using Microsoft.Extensions.Options; +using Umbraco.Core.Configuration.Models; namespace Umbraco.Web.BackOffice.Filters { @@ -27,11 +28,11 @@ namespace Umbraco.Web.BackOffice.Filters public class UmbracoWebApiRequireHttpsFilter: IAuthorizationFilter { - private readonly IGlobalSettings _globalSettings; + private readonly GlobalSettings _globalSettings; - public UmbracoWebApiRequireHttpsFilter(IGlobalSettings globalSettings) + public UmbracoWebApiRequireHttpsFilter(IOptionsSnapshot globalSettings) { - _globalSettings = globalSettings; + _globalSettings = globalSettings.Value; } public void OnAuthorization(AuthorizationFilterContext context) diff --git a/src/Umbraco.Web.BackOffice/Routing/BackOfficeAreaRoutes.cs b/src/Umbraco.Web.BackOffice/Routing/BackOfficeAreaRoutes.cs index ec0a75fe11..6d2fe9a9c8 100644 --- a/src/Umbraco.Web.BackOffice/Routing/BackOfficeAreaRoutes.cs +++ b/src/Umbraco.Web.BackOffice/Routing/BackOfficeAreaRoutes.cs @@ -1,6 +1,8 @@ using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.Options; using Umbraco.Core; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Hosting; using Umbraco.Web.BackOffice.Controllers; using Umbraco.Web.Common.Controllers; @@ -14,19 +16,19 @@ namespace Umbraco.Web.BackOffice.Routing /// public class BackOfficeAreaRoutes : IAreaRoutes { - private readonly IGlobalSettings _globalSettings; + private readonly GlobalSettings _globalSettings; private readonly IHostingEnvironment _hostingEnvironment; private readonly IRuntimeState _runtimeState; private readonly UmbracoApiControllerTypeCollection _apiControllers; private readonly string _umbracoPathSegment; public BackOfficeAreaRoutes( - IGlobalSettings globalSettings, + IOptionsSnapshot globalSettings, IHostingEnvironment hostingEnvironment, IRuntimeState runtimeState, UmbracoApiControllerTypeCollection apiControllers) { - _globalSettings = globalSettings; + _globalSettings = globalSettings.Value; _hostingEnvironment = hostingEnvironment; _runtimeState = runtimeState; _apiControllers = apiControllers; diff --git a/src/Umbraco.Web.BackOffice/Security/BackOfficeCookieManager.cs b/src/Umbraco.Web.BackOffice/Security/BackOfficeCookieManager.cs index 75112e9a22..60bdc9c8ff 100644 --- a/src/Umbraco.Web.BackOffice/Security/BackOfficeCookieManager.cs +++ b/src/Umbraco.Web.BackOffice/Security/BackOfficeCookieManager.cs @@ -1,16 +1,15 @@ -using Microsoft.AspNetCore.Authentication.Cookies; +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Extensions; using Microsoft.AspNetCore.Routing; -using System; -using System.Collections.Generic; -using System.Linq; using Umbraco.Core; -using Umbraco.Extensions; using Umbraco.Core.Cache; -using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Hosting; -using Umbraco.Web.BackOffice.Controllers; +using Umbraco.Extensions; namespace Umbraco.Web.BackOffice.Security { @@ -28,7 +27,7 @@ namespace Umbraco.Web.BackOffice.Security private readonly IUmbracoContextAccessor _umbracoContextAccessor; private readonly IRuntimeState _runtime; private readonly IHostingEnvironment _hostingEnvironment; - private readonly IGlobalSettings _globalSettings; + private readonly GlobalSettings _globalSettings; private readonly IRequestCache _requestCache; private readonly string[] _explicitPaths; @@ -36,7 +35,7 @@ namespace Umbraco.Web.BackOffice.Security IUmbracoContextAccessor umbracoContextAccessor, IRuntimeState runtime, IHostingEnvironment hostingEnvironment, - IGlobalSettings globalSettings, + GlobalSettings globalSettings, IRequestCache requestCache, LinkGenerator linkGenerator) : this(umbracoContextAccessor, runtime, hostingEnvironment, globalSettings, requestCache, linkGenerator, null) @@ -46,7 +45,7 @@ namespace Umbraco.Web.BackOffice.Security IUmbracoContextAccessor umbracoContextAccessor, IRuntimeState runtime, IHostingEnvironment hostingEnvironment, - IGlobalSettings globalSettings, + GlobalSettings globalSettings, IRequestCache requestCache, LinkGenerator linkGenerator, IEnumerable explicitPaths) diff --git a/src/Umbraco.Web.BackOffice/Security/ConfigureBackOfficeCookieOptions.cs b/src/Umbraco.Web.BackOffice/Security/ConfigureBackOfficeCookieOptions.cs index 70cdf05dc5..69a5359d4e 100644 --- a/src/Umbraco.Web.BackOffice/Security/ConfigureBackOfficeCookieOptions.cs +++ b/src/Umbraco.Web.BackOffice/Security/ConfigureBackOfficeCookieOptions.cs @@ -29,7 +29,7 @@ namespace Umbraco.Web.BackOffice.Security { private readonly IUmbracoContextAccessor _umbracoContextAccessor; private readonly SecuritySettings _securitySettings; - private readonly IGlobalSettings _globalSettings; + private readonly GlobalSettings _globalSettings; private readonly IHostingEnvironment _hostingEnvironment; private readonly IRuntimeState _runtimeState; private readonly IDataProtectionProvider _dataProtection; @@ -43,7 +43,7 @@ namespace Umbraco.Web.BackOffice.Security public ConfigureBackOfficeCookieOptions( IUmbracoContextAccessor umbracoContextAccessor, IOptionsSnapshot securitySettings, - IGlobalSettings globalSettings, + IOptionsSnapshot globalSettings, IHostingEnvironment hostingEnvironment, IRuntimeState runtimeState, IDataProtectionProvider dataProtection, @@ -56,7 +56,7 @@ namespace Umbraco.Web.BackOffice.Security { _umbracoContextAccessor = umbracoContextAccessor; _securitySettings = securitySettings.Value; - _globalSettings = globalSettings; + _globalSettings = globalSettings.Value; _hostingEnvironment = hostingEnvironment; _runtimeState = runtimeState; _dataProtection = dataProtection; diff --git a/src/Umbraco.Web.Common/AspNetCore/AspNetCoreBackOfficeInfo.cs b/src/Umbraco.Web.Common/AspNetCore/AspNetCoreBackOfficeInfo.cs index 39b1d7ff4e..4dc72bfd95 100644 --- a/src/Umbraco.Web.Common/AspNetCore/AspNetCoreBackOfficeInfo.cs +++ b/src/Umbraco.Web.Common/AspNetCore/AspNetCoreBackOfficeInfo.cs @@ -1,11 +1,17 @@ +using Microsoft.Extensions.Options; using Umbraco.Core; -using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; namespace Umbraco.Web.Common.AspNetCore { public class AspNetCoreBackOfficeInfo : IBackOfficeInfo { - public AspNetCoreBackOfficeInfo(IGlobalSettings globalSettings) + public AspNetCoreBackOfficeInfo(IOptionsSnapshot globalSettings) + : this(globalSettings.Value) + { + } + + public AspNetCoreBackOfficeInfo(GlobalSettings globalSettings) { GetAbsoluteUrl = globalSettings.UmbracoPath; } diff --git a/src/Umbraco.Web.Common/AspNetCore/AspNetCoreHostingEnvironment.cs b/src/Umbraco.Web.Common/AspNetCore/AspNetCoreHostingEnvironment.cs index efa1a52ad4..f35ced66f0 100644 --- a/src/Umbraco.Web.Common/AspNetCore/AspNetCoreHostingEnvironment.cs +++ b/src/Umbraco.Web.Common/AspNetCore/AspNetCoreHostingEnvironment.cs @@ -1,19 +1,26 @@ using System; using System.IO; using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Options; using Umbraco.Core; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; namespace Umbraco.Web.Common.AspNetCore { - public class AspNetCoreHostingEnvironment : Umbraco.Core.Hosting.IHostingEnvironment + public class AspNetCoreHostingEnvironment : Core.Hosting.IHostingEnvironment { - private readonly IHostingSettings _hostingSettings; + private readonly HostingSettings _hostingSettings; private readonly IWebHostEnvironment _webHostEnvironment; private string _localTempPath; - public AspNetCoreHostingEnvironment(IHostingSettings hostingSettings, IWebHostEnvironment webHostEnvironment) + public AspNetCoreHostingEnvironment(IOptionsSnapshot hostingSettings, IWebHostEnvironment webHostEnvironment) + : this(hostingSettings.Value, webHostEnvironment) + { + } + + public AspNetCoreHostingEnvironment(HostingSettings hostingSettings, IWebHostEnvironment webHostEnvironment) { _hostingSettings = hostingSettings ?? throw new ArgumentNullException(nameof(hostingSettings)); _webHostEnvironment = webHostEnvironment ?? throw new ArgumentNullException(nameof(webHostEnvironment)); @@ -27,7 +34,6 @@ namespace Umbraco.Web.Common.AspNetCore ?? "/"; IISVersion = new Version(0, 0); // TODO not necessary IIS - } public bool IsHosted { get; } = true; diff --git a/src/Umbraco.Web.Common/AspNetCore/AspNetCoreRequestAccessor.cs b/src/Umbraco.Web.Common/AspNetCore/AspNetCoreRequestAccessor.cs index d29e58a2bf..2b27e37887 100644 --- a/src/Umbraco.Web.Common/AspNetCore/AspNetCoreRequestAccessor.cs +++ b/src/Umbraco.Web.Common/AspNetCore/AspNetCoreRequestAccessor.cs @@ -2,6 +2,8 @@ using System.Collections.Generic; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Extensions; +using Microsoft.Extensions.Options; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Extensions; using Umbraco.Web.Common.Lifetime; @@ -13,18 +15,18 @@ namespace Umbraco.Web.Common.AspNetCore { private readonly IHttpContextAccessor _httpContextAccessor; private readonly IUmbracoContextAccessor _umbracoContextAccessor; - private readonly IWebRoutingSettings _webRoutingSettings; + private readonly WebRoutingSettings _webRoutingSettings; private readonly ISet _applicationUrls = new HashSet(); private Uri _currentApplicationUrl; public AspNetCoreRequestAccessor(IHttpContextAccessor httpContextAccessor, IUmbracoRequestLifetime umbracoRequestLifetime, IUmbracoContextAccessor umbracoContextAccessor, - IWebRoutingSettings webRoutingSettings) + IOptionsSnapshot webRoutingSettings) { _httpContextAccessor = httpContextAccessor; _umbracoContextAccessor = umbracoContextAccessor; - _webRoutingSettings = webRoutingSettings; + _webRoutingSettings = webRoutingSettings.Value; umbracoRequestLifetime.RequestStart += RequestStart; umbracoRequestLifetime.RequestEnd += RequestEnd; diff --git a/src/Umbraco.Web.Common/AspNetCore/UmbracoViewPage.cs b/src/Umbraco.Web.Common/AspNetCore/UmbracoViewPage.cs index 88e361029f..28bb1dc41c 100644 --- a/src/Umbraco.Web.Common/AspNetCore/UmbracoViewPage.cs +++ b/src/Umbraco.Web.Common/AspNetCore/UmbracoViewPage.cs @@ -25,7 +25,7 @@ namespace Umbraco.Web.Common.AspNetCore private IUmbracoContext _umbracoContext; private IUmbracoContextAccessor UmbracoContextAccessor => Context.RequestServices.GetRequiredService(); - private IGlobalSettings GlobalSettings => Context.RequestServices.GetRequiredService(); + private GlobalSettings GlobalSettings => Context.RequestServices.GetRequiredService>().Value; private ContentSettings ContentSettings => Context.RequestServices.GetRequiredService>().Value; private IProfilerHtml ProfilerHtml => Context.RequestServices.GetRequiredService(); private IIOHelper IOHelper => Context.RequestServices.GetRequiredService(); diff --git a/src/Umbraco.Web.Common/Extensions/HttpRequestExtensions.cs b/src/Umbraco.Web.Common/Extensions/HttpRequestExtensions.cs index 5baedf3ded..0369717b9b 100644 --- a/src/Umbraco.Web.Common/Extensions/HttpRequestExtensions.cs +++ b/src/Umbraco.Web.Common/Extensions/HttpRequestExtensions.cs @@ -7,6 +7,7 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Extensions; using Umbraco.Core; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Hosting; namespace Umbraco.Extensions @@ -24,7 +25,7 @@ namespace Umbraco.Extensions return request.Cookies.TryGetValue(Constants.Web.PreviewCookieName, out var cookieVal) && !cookieVal.IsNullOrWhiteSpace(); } - public static bool IsBackOfficeRequest(this HttpRequest request, IGlobalSettings globalSettings, IHostingEnvironment hostingEnvironment) + public static bool IsBackOfficeRequest(this HttpRequest request, GlobalSettings globalSettings, IHostingEnvironment hostingEnvironment) { return new Uri(request.GetEncodedUrl(), UriKind.RelativeOrAbsolute).IsBackOfficeRequest(globalSettings, hostingEnvironment); } diff --git a/src/Umbraco.Web.Common/Extensions/UmbracoCoreServiceCollectionExtensions.cs b/src/Umbraco.Web.Common/Extensions/UmbracoCoreServiceCollectionExtensions.cs index 7a02b53724..cbdbeac873 100644 --- a/src/Umbraco.Web.Common/Extensions/UmbracoCoreServiceCollectionExtensions.cs +++ b/src/Umbraco.Web.Common/Extensions/UmbracoCoreServiceCollectionExtensions.cs @@ -9,15 +9,16 @@ using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; using Serilog; using Serilog.Extensions.Hosting; using Serilog.Extensions.Logging; using Umbraco.Configuration; -using Umbraco.Configuration.Models; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Composing; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Logging.Serilog; @@ -26,7 +27,7 @@ using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.Runtime; using Umbraco.Web.Common.AspNetCore; using Umbraco.Web.Common.Profiler; -using CoreDebugSettings = Umbraco.Configuration.Models.CoreDebugSettings; +using CoreDebugSettings = Umbraco.Core.Configuration.Models.CoreDebugSettings; namespace Umbraco.Extensions { @@ -101,6 +102,7 @@ namespace Umbraco.Extensions { if (configuration == null) throw new ArgumentNullException(nameof(configuration)); + services.Configure(configuration.GetSection(Constants.Configuration.ConfigPrefix + "ConnectionStrings")); services.Configure(configuration.GetSection(Constants.Configuration.ConfigPrefix + "Tours")); services.Configure(configuration.GetSection(Constants.Configuration.ConfigPrefix + "Core:Debug")); services.Configure(configuration.GetSection(Constants.Configuration.ConfigSecurityPrefix)); @@ -113,12 +115,12 @@ namespace Umbraco.Extensions services.Configure(configuration.GetSection(Constants.Configuration.ConfigPrefix + "ActiveDirectory:")); services.Configure(configuration.GetSection(Constants.Configuration.ConfigPrefix + "Runtime:")); services.Configure(configuration.GetSection(Constants.Configuration.ConfigPrefix + "TypeFinder:")); + services.Configure(configuration.GetSection(Constants.Configuration.ConfigGlobalPrefix)); + services.Configure(configuration.GetSection(Constants.Configuration.ConfigPrefix + "Hosting:")); services.Configure(configuration.GetSection(Constants.Configuration.ConfigPrefix + "NuCache:")); services.Configure(configuration.GetSection(Constants.Configuration.ConfigPrefix + "WebRouting:")); services.Configure(configuration.GetSection(Constants.Configuration.ConfigPrefix + "Examine:")); services.Configure(configuration.GetSection(Constants.Configuration.ConfigModelsBuilderPrefix)); - services.Configure(configuration.GetSection(Constants.Configuration.ConfigPrefix + "Hosting:")); - services.Configure(configuration.GetSection(Constants.Configuration.ConfigGlobalPrefix)); services.Configure(configuration.GetSection(Constants.Configuration.ConfigPrefix + "Imaging:")); var configsFactory = new AspNetCoreConfigsFactory(configuration); @@ -217,21 +219,27 @@ namespace Umbraco.Extensions // into the container. This is not true for `Configs` but we should do that too, see comments in // `RegisterEssentials`. var serviceProvider = services.BuildServiceProvider(); - var configs = serviceProvider.GetService(); + + var globalSettings = serviceProvider.GetService>().Value; + var connectionStrings = serviceProvider.GetService>().Value; + var hostingSettings = serviceProvider.GetService>().Value; + var typeFinderSettings = serviceProvider.GetService>().Value; + var dbProviderFactoryCreator = serviceProvider.GetRequiredService(); CreateCompositionRoot(services, - configs, + globalSettings, + hostingSettings, webHostEnvironment, loggingConfiguration, out var logger, out var ioHelper, out var hostingEnvironment, out var backOfficeInfo, out var profiler); - var globalSettings = configs.Global(); var umbracoVersion = new UmbracoVersion(globalSettings); - var typeFinder = CreateTypeFinder(logger, profiler, webHostEnvironment, entryAssembly, configs.TypeFinder()); + var typeFinder = CreateTypeFinder(logger, profiler, webHostEnvironment, entryAssembly, typeFinderSettings); var coreRuntime = GetCoreRuntime( - configs, + globalSettings, + connectionStrings, umbracoVersion, ioHelper, logger, @@ -247,7 +255,7 @@ namespace Umbraco.Extensions return services; } - private static ITypeFinder CreateTypeFinder(Core.Logging.ILogger logger, IProfiler profiler, IWebHostEnvironment webHostEnvironment, Assembly entryAssembly, ITypeFinderSettings typeFinderSettings) + private static ITypeFinder CreateTypeFinder(Core.Logging.ILogger logger, IProfiler profiler, IWebHostEnvironment webHostEnvironment, Assembly entryAssembly, TypeFinderSettings typeFinderSettings) { var runtimeHashPaths = new RuntimeHashPaths(); runtimeHashPaths.AddFolder(new DirectoryInfo(Path.Combine(webHostEnvironment.ContentRootPath, "bin"))); @@ -256,25 +264,23 @@ namespace Umbraco.Extensions } private static IRuntime GetCoreRuntime( - Configs configs, IUmbracoVersion umbracoVersion, IIOHelper ioHelper, Core.Logging.ILogger logger, + GlobalSettings globalSettings, ConnectionStrings connectionStrings, IUmbracoVersion umbracoVersion, IIOHelper ioHelper, Core.Logging.ILogger logger, IProfiler profiler, Core.Hosting.IHostingEnvironment hostingEnvironment, IBackOfficeInfo backOfficeInfo, ITypeFinder typeFinder, IRequestCache requestCache, IDbProviderFactoryCreator dbProviderFactoryCreator) { - // Determine if we should use the sql main dom or the default - var globalSettings = configs.Global(); - var connStrings = configs.ConnectionStrings(); var appSettingMainDomLock = globalSettings.MainDomLock; var isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); var mainDomLock = appSettingMainDomLock == "SqlMainDomLock" || isWindows == false - ? (IMainDomLock)new SqlMainDomLock(logger, globalSettings, connStrings, dbProviderFactoryCreator, hostingEnvironment) + ? (IMainDomLock)new SqlMainDomLock(logger, globalSettings, connectionStrings, dbProviderFactoryCreator, hostingEnvironment) : new MainDomSemaphoreLock(logger, hostingEnvironment); var mainDom = new MainDom(logger, mainDomLock); var coreRuntime = new CoreRuntime( - configs, + globalSettings, + connectionStrings, umbracoVersion, ioHelper, logger, @@ -292,7 +298,8 @@ namespace Umbraco.Extensions private static IServiceCollection CreateCompositionRoot( IServiceCollection services, - Configs configs, + GlobalSettings globalSettings, + HostingSettings hostingSettings, IWebHostEnvironment webHostEnvironment, ILoggingConfiguration loggingConfiguration, out Core.Logging.ILogger logger, @@ -301,14 +308,12 @@ namespace Umbraco.Extensions out IBackOfficeInfo backOfficeInfo, out IProfiler profiler) { - if (configs == null) - throw new InvalidOperationException($"Could not resolve type {typeof(Configs)} from the container, ensure {nameof(AddUmbracoConfiguration)} is called before calling {nameof(AddUmbracoCore)}"); + if (globalSettings == null) + throw new InvalidOperationException($"Could not resolve type {typeof(GlobalSettings)} from the container, ensure {nameof(AddUmbracoConfiguration)} is called before calling {nameof(AddUmbracoCore)}"); - var hostingSettings = configs.Hosting(); - var globalSettings = configs.Global(); hostingEnvironment = new AspNetCoreHostingEnvironment(hostingSettings, webHostEnvironment); - ioHelper = new IOHelper(hostingEnvironment, globalSettings); + ioHelper = new IOHelper(hostingEnvironment); logger = AddLogger(services, hostingEnvironment, loggingConfiguration); backOfficeInfo = new AspNetCoreBackOfficeInfo(globalSettings); diff --git a/src/Umbraco.Web.Common/Extensions/UmbracoWebServiceCollectionExtensions.cs b/src/Umbraco.Web.Common/Extensions/UmbracoWebServiceCollectionExtensions.cs index a795edf6cf..61120c8ee9 100644 --- a/src/Umbraco.Web.Common/Extensions/UmbracoWebServiceCollectionExtensions.cs +++ b/src/Umbraco.Web.Common/Extensions/UmbracoWebServiceCollectionExtensions.cs @@ -19,6 +19,7 @@ using Smidge; using Smidge.Nuglify; using Umbraco.Core; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Web.Common.ApplicationModels; using Umbraco.Web.Common.Middleware; using Umbraco.Web.Common.ModelBinding; @@ -40,8 +41,7 @@ namespace Umbraco.Extensions // TODO: We need to avoid this, surely there's a way? See ContainerTests.BuildServiceProvider_Before_Host_Is_Configured var serviceProvider = services.BuildServiceProvider(); - var configs = serviceProvider.GetService(); - var imagingSettings = configs.Imaging(); + var imagingSettings = serviceProvider.GetService>().Value; services.AddUmbracoImageSharp(imagingSettings); return services; @@ -53,19 +53,19 @@ namespace Umbraco.Extensions /// /// /// - public static IServiceCollection AddUmbracoImageSharp(this IServiceCollection services, IImagingSettings imagingSettings) + public static IServiceCollection AddUmbracoImageSharp(this IServiceCollection services, ImagingSettings imagingSettings) { services.AddImageSharpCore( options => { options.Configuration = SixLabors.ImageSharp.Configuration.Default; - options.MaxBrowserCacheDays = imagingSettings.MaxBrowserCacheDays; - options.MaxCacheDays = imagingSettings.MaxCacheDays; - options.CachedNameLength = imagingSettings.CachedNameLength; + options.MaxBrowserCacheDays = imagingSettings.Cache.MaxBrowserCacheDays; + options.MaxCacheDays = imagingSettings.Cache.MaxCacheDays; + options.CachedNameLength = imagingSettings.Cache.CachedNameLength; options.OnParseCommands = context => { - RemoveIntParamenterIfValueGreatherThen(context.Commands, ResizeWebProcessor.Width, imagingSettings.MaxResizeWidth); - RemoveIntParamenterIfValueGreatherThen(context.Commands, ResizeWebProcessor.Height, imagingSettings.MaxResizeHeight); + RemoveIntParamenterIfValueGreatherThen(context.Commands, ResizeWebProcessor.Width, imagingSettings.Resize.MaxResizeWidth); + RemoveIntParamenterIfValueGreatherThen(context.Commands, ResizeWebProcessor.Height, imagingSettings.Resize.MaxResizeHeight); }; options.OnBeforeSave = _ => { }; options.OnProcessed = _ => { }; @@ -75,7 +75,7 @@ namespace Umbraco.Extensions .SetMemoryAllocator(provider => ArrayPoolMemoryAllocator.CreateWithMinimalPooling()) .Configure(options => { - options.CacheFolder = imagingSettings.CacheFolder; + options.CacheFolder = imagingSettings.Cache.CacheFolder; }) .SetCache() .SetCacheHash() diff --git a/src/Umbraco.Web.Common/Filters/StatusCodeResultAttribute.cs b/src/Umbraco.Web.Common/Filters/StatusCodeResultAttribute.cs index 8f3fcf3a95..a35628821b 100644 --- a/src/Umbraco.Web.Common/Filters/StatusCodeResultAttribute.cs +++ b/src/Umbraco.Web.Common/Filters/StatusCodeResultAttribute.cs @@ -2,6 +2,8 @@ using Microsoft.AspNetCore.Diagnostics; using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Configuration.UmbracoSettings; namespace Umbraco.Web.Common.Filters @@ -26,7 +28,7 @@ namespace Umbraco.Web.Common.Filters httpContext.Response.StatusCode = (int)_statusCode; - var disableIisCustomErrors = httpContext.RequestServices.GetService().TrySkipIisCustomErrors; + var disableIisCustomErrors = httpContext.RequestServices.GetService>().Value.TrySkipIisCustomErrors; var statusCodePagesFeature = httpContext.Features.Get(); if (statusCodePagesFeature != null) diff --git a/src/Umbraco.Web.Common/Install/InstallController.cs b/src/Umbraco.Web.Common/Install/InstallController.cs index 2b9f716516..d97bb86fed 100644 --- a/src/Umbraco.Web.Common/Install/InstallController.cs +++ b/src/Umbraco.Web.Common/Install/InstallController.cs @@ -12,6 +12,8 @@ using Umbraco.Extensions; using Umbraco.Web.Common.Filters; using Umbraco.Web.Install; using Umbraco.Web.Security; +using Umbraco.Core.Configuration.Models; +using Microsoft.Extensions.Options; namespace Umbraco.Web.Common.Install { @@ -26,7 +28,7 @@ namespace Umbraco.Web.Common.Install private readonly IWebSecurity _webSecurity; private readonly InstallHelper _installHelper; private readonly IRuntimeState _runtime; - private readonly IGlobalSettings _globalSettings; + private readonly GlobalSettings _globalSettings; private readonly IHostingEnvironment _hostingEnvironment; private readonly IUmbracoVersion _umbracoVersion; private readonly ILogger _logger; @@ -37,7 +39,7 @@ namespace Umbraco.Web.Common.Install IWebSecurity webSecurity, InstallHelper installHelper, IRuntimeState runtime, - IGlobalSettings globalSettings, + IOptionsSnapshot globalSettings, IRuntimeMinifier runtimeMinifier, IHostingEnvironment hostingEnvironment, IUmbracoVersion umbracoVersion, @@ -47,7 +49,7 @@ namespace Umbraco.Web.Common.Install _webSecurity = webSecurity; _installHelper = installHelper; _runtime = runtime; - _globalSettings = globalSettings; + _globalSettings = globalSettings.Value; _runtimeMinifier = runtimeMinifier; _hostingEnvironment = hostingEnvironment; _umbracoVersion = umbracoVersion; diff --git a/src/Umbraco.Web.Common/Runtime/AspNetCoreComposer.cs b/src/Umbraco.Web.Common/Runtime/AspNetCoreComposer.cs index a0a84e893f..0cfacbbf13 100644 --- a/src/Umbraco.Web.Common/Runtime/AspNetCoreComposer.cs +++ b/src/Umbraco.Web.Common/Runtime/AspNetCoreComposer.cs @@ -1,33 +1,32 @@ +using System.Linq; using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Options; using Umbraco.Core; using Umbraco.Core.Composing; +using Umbraco.Core.Configuration.Models; +using Umbraco.Core.Diagnostics; using Umbraco.Core.Hosting; -using Umbraco.Net; +using Umbraco.Core.Logging; using Umbraco.Core.Runtime; using Umbraco.Core.Security; +using Umbraco.Extensions; +using Umbraco.Net; using Umbraco.Web.Common.AspNetCore; +using Umbraco.Web.Common.Controllers; using Umbraco.Web.Common.Formatters; +using Umbraco.Web.Common.Install; using Umbraco.Web.Common.Lifetime; using Umbraco.Web.Common.Macros; -using Umbraco.Web.Composing.CompositionExtensions; -using Umbraco.Web.Macros; -using Umbraco.Core.Diagnostics; -using Umbraco.Core.Logging; -using Umbraco.Web.Common.Profiler; -using Umbraco.Web.Common.Install; -using Umbraco.Extensions; -using System.Linq; -using Umbraco.Core.Configuration; -using Umbraco.Web.Common.Controllers; using Umbraco.Web.Common.Middleware; using Umbraco.Web.Common.ModelBinding; +using Umbraco.Web.Common.Profiler; using Umbraco.Web.Common.Routing; -using Umbraco.Web.Common.Templates; using Umbraco.Web.Common.Security; +using Umbraco.Web.Common.Templates; +using Umbraco.Web.Composing.CompositionExtensions; +using Umbraco.Web.Macros; using Umbraco.Web.Security; using Umbraco.Web.Templates; -using Umbraco.Configuration.Models; -using Microsoft.Extensions.Options; namespace Umbraco.Web.Common.Runtime { diff --git a/src/Umbraco.Web.Common/Security/WebSecurity.cs b/src/Umbraco.Web.Common/Security/WebSecurity.cs index c67d5a9b4f..69f5850482 100644 --- a/src/Umbraco.Web.Common/Security/WebSecurity.cs +++ b/src/Umbraco.Web.Common/Security/WebSecurity.cs @@ -1,33 +1,33 @@ using System; using System.Security; using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Options; using Umbraco.Core; -using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Hosting; +using Umbraco.Core.Models; using Umbraco.Core.Models.Membership; using Umbraco.Core.Services; using Umbraco.Extensions; using Umbraco.Web.Security; -using Umbraco.Core.Models; namespace Umbraco.Web.Common.Security { - public class WebSecurity : IWebSecurity { private readonly IUserService _userService; - private readonly IGlobalSettings _globalSettings; + private readonly GlobalSettings _globalSettings; private readonly IHostingEnvironment _hostingEnvironment; private readonly IHttpContextAccessor _httpContextAccessor; public WebSecurity( IUserService userService, - IGlobalSettings globalSettings, + IOptionsSnapshot globalSettings, IHostingEnvironment hostingEnvironment, IHttpContextAccessor httpContextAccessor) { _userService = userService; - _globalSettings = globalSettings; + _globalSettings = globalSettings.Value; _hostingEnvironment = hostingEnvironment; _httpContextAccessor = httpContextAccessor; } @@ -113,7 +113,7 @@ namespace Umbraco.Web.Common.Security return ValidateRequestAttempt.Success; } - private static bool RequestIsInUmbracoApplication(IHttpContextAccessor httpContextAccessor, IGlobalSettings globalSettings, IHostingEnvironment hostingEnvironment) + private static bool RequestIsInUmbracoApplication(IHttpContextAccessor httpContextAccessor, GlobalSettings globalSettings, IHostingEnvironment hostingEnvironment) { return httpContextAccessor.GetRequiredHttpContext().Request.Path.ToString().IndexOf(hostingEnvironment.ToAbsolute(globalSettings.UmbracoPath), StringComparison.InvariantCultureIgnoreCase) > -1; } diff --git a/src/Umbraco.Web.Common/Templates/TemplateRenderer.cs b/src/Umbraco.Web.Common/Templates/TemplateRenderer.cs index d692303df5..81a635a20f 100644 --- a/src/Umbraco.Web.Common/Templates/TemplateRenderer.cs +++ b/src/Umbraco.Web.Common/Templates/TemplateRenderer.cs @@ -11,7 +11,9 @@ using Microsoft.AspNetCore.Mvc.ViewEngines; using Microsoft.AspNetCore.Mvc.ViewFeatures; using Microsoft.AspNetCore.Routing; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; using Umbraco.Core; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Services; using Umbraco.Core.Strings; @@ -34,7 +36,7 @@ namespace Umbraco.Web.Common.Templates private readonly IPublishedRouter _publishedRouter; private readonly IFileService _fileService; private readonly ILocalizationService _languageService; - private readonly IWebRoutingSettings _webRoutingSettings; + private readonly WebRoutingSettings _webRoutingSettings; private readonly IShortStringHelper _shortStringHelper; private readonly IHttpContextAccessor _httpContextAccessor; private readonly ICompositeViewEngine _viewEngine; @@ -43,7 +45,7 @@ namespace Umbraco.Web.Common.Templates IPublishedRouter publishedRouter, IFileService fileService, ILocalizationService textService, - IWebRoutingSettings webRoutingSettings, + IOptionsSnapshot webRoutingSettings, IShortStringHelper shortStringHelper, IHttpContextAccessor httpContextAccessor, ICompositeViewEngine viewEngine) @@ -52,7 +54,7 @@ namespace Umbraco.Web.Common.Templates _publishedRouter = publishedRouter ?? throw new ArgumentNullException(nameof(publishedRouter)); _fileService = fileService ?? throw new ArgumentNullException(nameof(fileService)); _languageService = textService ?? throw new ArgumentNullException(nameof(textService)); - _webRoutingSettings = webRoutingSettings ?? throw new ArgumentNullException(nameof(webRoutingSettings)); + _webRoutingSettings = webRoutingSettings.Value ?? throw new ArgumentNullException(nameof(webRoutingSettings)); _shortStringHelper = shortStringHelper ?? throw new ArgumentNullException(nameof(shortStringHelper)); _httpContextAccessor = httpContextAccessor ?? throw new ArgumentNullException(nameof(httpContextAccessor)); _viewEngine = viewEngine ?? throw new ArgumentNullException(nameof(viewEngine)); diff --git a/src/Umbraco.Web.Common/UmbracoContext/UmbracoContext.cs b/src/Umbraco.Web.Common/UmbracoContext/UmbracoContext.cs index 4419015105..b255013b7f 100644 --- a/src/Umbraco.Web.Common/UmbracoContext/UmbracoContext.cs +++ b/src/Umbraco.Web.Common/UmbracoContext/UmbracoContext.cs @@ -1,7 +1,9 @@ using System; +using Microsoft.Extensions.Options; using Umbraco.Composing; using Umbraco.Core; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Hosting; using Umbraco.Core.Models.PublishedContent; using Umbraco.Web.PublishedCache; @@ -15,7 +17,7 @@ namespace Umbraco.Web /// public class UmbracoContext : DisposableObjectSlim, IDisposeOnRequestEnd, IUmbracoContext { - private readonly IGlobalSettings _globalSettings; + private readonly GlobalSettings _globalSettings; private readonly IHostingEnvironment _hostingEnvironment; private readonly ICookieManager _cookieManager; private readonly IRequestAccessor _requestAccessor; @@ -30,7 +32,7 @@ namespace Umbraco.Web internal UmbracoContext( IPublishedSnapshotService publishedSnapshotService, IWebSecurity webSecurity, - IGlobalSettings globalSettings, + GlobalSettings globalSettings, IHostingEnvironment hostingEnvironment, IVariationContextAccessor variationContextAccessor, UriUtility uriUtility, diff --git a/src/Umbraco.Web.Common/UmbracoContext/UmbracoContextFactory.cs b/src/Umbraco.Web.Common/UmbracoContext/UmbracoContextFactory.cs index 3c771a1668..a3849c532e 100644 --- a/src/Umbraco.Web.Common/UmbracoContext/UmbracoContextFactory.cs +++ b/src/Umbraco.Web.Common/UmbracoContext/UmbracoContextFactory.cs @@ -2,7 +2,9 @@ using System.IO; using System.Text; using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Options; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Hosting; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Services; @@ -22,7 +24,7 @@ namespace Umbraco.Web private readonly IVariationContextAccessor _variationContextAccessor; private readonly IDefaultCultureAccessor _defaultCultureAccessor; - private readonly IGlobalSettings _globalSettings; + private readonly GlobalSettings _globalSettings; private readonly IUserService _userService; private readonly IHostingEnvironment _hostingEnvironment; private readonly IHttpContextAccessor _httpContextAccessor; @@ -39,7 +41,7 @@ namespace Umbraco.Web IPublishedSnapshotService publishedSnapshotService, IVariationContextAccessor variationContextAccessor, IDefaultCultureAccessor defaultCultureAccessor, - IGlobalSettings globalSettings, + IOptionsSnapshot globalSettings, IUserService userService, IHostingEnvironment hostingEnvironment, UriUtility uriUtility, @@ -52,7 +54,7 @@ namespace Umbraco.Web _publishedSnapshotService = publishedSnapshotService ?? throw new ArgumentNullException(nameof(publishedSnapshotService)); _variationContextAccessor = variationContextAccessor ?? throw new ArgumentNullException(nameof(variationContextAccessor)); _defaultCultureAccessor = defaultCultureAccessor ?? throw new ArgumentNullException(nameof(defaultCultureAccessor)); - _globalSettings = globalSettings ?? throw new ArgumentNullException(nameof(globalSettings)); + _globalSettings = globalSettings.Value ?? throw new ArgumentNullException(nameof(globalSettings)); _userService = userService ?? throw new ArgumentNullException(nameof(userService)); _hostingEnvironment = hostingEnvironment ?? throw new ArgumentNullException(nameof(hostingEnvironment)); _uriUtility = uriUtility ?? throw new ArgumentNullException(nameof(uriUtility)); diff --git a/src/Umbraco.Web.UI.NetCore/Umbraco/UmbracoBackOffice/AuthorizeUpgrade.cshtml b/src/Umbraco.Web.UI.NetCore/Umbraco/UmbracoBackOffice/AuthorizeUpgrade.cshtml index d9f39b544c..0a7c95e7fe 100644 --- a/src/Umbraco.Web.UI.NetCore/Umbraco/UmbracoBackOffice/AuthorizeUpgrade.cshtml +++ b/src/Umbraco.Web.UI.NetCore/Umbraco/UmbracoBackOffice/AuthorizeUpgrade.cshtml @@ -1,21 +1,22 @@ -@using Umbraco.Core +@using Microsoft.Extensions.Options; +@using Umbraco.Core @using Umbraco.Web.WebAssets @using Umbraco.Web.Common.Security @using Umbraco.Core.WebAssets @using Umbraco.Core.Configuration +@using Umbraco.Core.Configuration.Models @using Umbraco.Core.Hosting @using Umbraco.Extensions -@using Umbraco.Core.Logging @using Umbraco.Web.BackOffice.Controllers @inject BackOfficeSignInManager signInManager @inject BackOfficeServerVariables backOfficeServerVariables @inject IUmbracoVersion umbracoVersion @inject IHostingEnvironment hostingEnvironment -@inject IGlobalSettings globalSettings +@inject IOptionsSnapshot globalSettings @inject IRuntimeMinifier runtimeMinifier @{ - var backOfficePath = globalSettings.GetBackOfficePath(hostingEnvironment); + var backOfficePath = globalSettings.Value.GetBackOfficePath(hostingEnvironment); } diff --git a/src/Umbraco.Web.UI.NetCore/Umbraco/UmbracoBackOffice/Default.cshtml b/src/Umbraco.Web.UI.NetCore/Umbraco/UmbracoBackOffice/Default.cshtml index 55959c27a8..bce17553d6 100644 --- a/src/Umbraco.Web.UI.NetCore/Umbraco/UmbracoBackOffice/Default.cshtml +++ b/src/Umbraco.Web.UI.NetCore/Umbraco/UmbracoBackOffice/Default.cshtml @@ -1,8 +1,10 @@ -@using Umbraco.Core +@using Microsoft.Extensions.Options; +@using Umbraco.Core @using Umbraco.Web.WebAssets @using Umbraco.Web.Common.Security @using Umbraco.Core.WebAssets @using Umbraco.Core.Configuration +@using Umbraco.Core.Configuration.Models @using Umbraco.Core.Hosting @using Umbraco.Extensions @using Umbraco.Core.Logging @@ -11,7 +13,7 @@ @inject BackOfficeServerVariables backOfficeServerVariables @inject IUmbracoVersion umbracoVersion @inject IHostingEnvironment hostingEnvironment -@inject IGlobalSettings globalSettings +@inject IOptionsSnapshot globalSettings @inject IRuntimeMinifier runtimeMinifier @inject IProfilerHtml profilerHtml @@ -19,7 +21,7 @@ var isDebug = false; var qryDebug = Context.Request.Query["umbDebug"].ToString().TryConvertTo(); isDebug = qryDebug.Success && qryDebug.Result; - var backOfficePath = globalSettings.GetBackOfficePath(hostingEnvironment); + var backOfficePath = globalSettings.Value.GetBackOfficePath(hostingEnvironment); } diff --git a/src/Umbraco.Web.UI.NetCore/umbraco/UmbracoBackOffice/Default.cshtml b/src/Umbraco.Web.UI.NetCore/umbraco/UmbracoBackOffice/Default.cshtml index d399817502..bce17553d6 100644 --- a/src/Umbraco.Web.UI.NetCore/umbraco/UmbracoBackOffice/Default.cshtml +++ b/src/Umbraco.Web.UI.NetCore/umbraco/UmbracoBackOffice/Default.cshtml @@ -1,8 +1,10 @@ -@using Umbraco.Core +@using Microsoft.Extensions.Options; +@using Umbraco.Core @using Umbraco.Web.WebAssets @using Umbraco.Web.Common.Security @using Umbraco.Core.WebAssets @using Umbraco.Core.Configuration +@using Umbraco.Core.Configuration.Models @using Umbraco.Core.Hosting @using Umbraco.Extensions @using Umbraco.Core.Logging @@ -11,15 +13,15 @@ @inject BackOfficeServerVariables backOfficeServerVariables @inject IUmbracoVersion umbracoVersion @inject IHostingEnvironment hostingEnvironment -@inject IGlobalSettings globalSettings +@inject IOptionsSnapshot globalSettings @inject IRuntimeMinifier runtimeMinifier @inject IProfilerHtml profilerHtml @{ var isDebug = false; - var qryDebug = Context.Request.Query["umbDebug"].TryConvertTo(); + var qryDebug = Context.Request.Query["umbDebug"].ToString().TryConvertTo(); isDebug = qryDebug.Success && qryDebug.Result; - var backOfficePath = globalSettings.GetBackOfficePath(hostingEnvironment); + var backOfficePath = globalSettings.Value.GetBackOfficePath(hostingEnvironment); } diff --git a/src/Umbraco.Web.UI.NetCore/umbraco/UmbracoBackOffice/Preview.cshtml b/src/Umbraco.Web.UI.NetCore/umbraco/UmbracoBackOffice/Preview.cshtml index 3bab021741..dd34dab6f4 100644 --- a/src/Umbraco.Web.UI.NetCore/umbraco/UmbracoBackOffice/Preview.cshtml +++ b/src/Umbraco.Web.UI.NetCore/umbraco/UmbracoBackOffice/Preview.cshtml @@ -1,8 +1,9 @@ -@using Umbraco.Core +@using Microsoft.Extensions.Options; @using Umbraco.Web.WebAssets @using Umbraco.Web.Common.Security @using Umbraco.Core.WebAssets @using Umbraco.Core.Configuration +@using Umbraco.Core.Configuration.Models @using Umbraco.Core.Hosting @using Umbraco.Extensions @using Umbraco.Core.Logging @@ -11,7 +12,7 @@ @inject BackOfficeServerVariables backOfficeServerVariables @inject IUmbracoVersion umbracoVersion @inject IHostingEnvironment hostingEnvironment -@inject IGlobalSettings globalSettings +@inject IOptionsSnapshot globalSettings @inject IRuntimeMinifier runtimeMinifier @inject IProfilerHtml profilerHtml diff --git a/src/Umbraco.Web/AppBuilderExtensions.cs b/src/Umbraco.Web/AppBuilderExtensions.cs index c8c6cbdf5c..2c4273b5a1 100644 --- a/src/Umbraco.Web/AppBuilderExtensions.cs +++ b/src/Umbraco.Web/AppBuilderExtensions.cs @@ -3,6 +3,7 @@ using Microsoft.AspNet.SignalR; using Microsoft.Owin.Logging; using Owin; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Hosting; using Umbraco.Core.IO; using Umbraco.Web.Composing; @@ -46,7 +47,7 @@ namespace Umbraco.Web /// The app builder. /// /// - public static IAppBuilder UseSignalR(this IAppBuilder app, IGlobalSettings globalSettings, IHostingEnvironment hostingEnvironment) + public static IAppBuilder UseSignalR(this IAppBuilder app, GlobalSettings globalSettings, IHostingEnvironment hostingEnvironment) { var umbracoPath = globalSettings.GetUmbracoMvcArea(hostingEnvironment); var signalrPath = HttpRuntime.AppDomainAppVirtualPath + umbracoPath + "/BackOffice/signalr"; diff --git a/src/Umbraco.Web/AspNet/AspNetBackOfficeInfo.cs b/src/Umbraco.Web/AspNet/AspNetBackOfficeInfo.cs index 1e60fedeea..ab3f575d36 100644 --- a/src/Umbraco.Web/AspNet/AspNetBackOfficeInfo.cs +++ b/src/Umbraco.Web/AspNet/AspNetBackOfficeInfo.cs @@ -1,6 +1,8 @@ using System.Web; +using Microsoft.Extensions.Options; using Umbraco.Core; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.IO; using Umbraco.Core.Logging; @@ -9,12 +11,17 @@ namespace Umbraco.Web { public class AspNetBackOfficeInfo : IBackOfficeInfo { - private readonly IGlobalSettings _globalSettings; + private readonly GlobalSettings _globalSettings; private readonly IIOHelper _ioHelper; private readonly ILogger _logger; - private readonly IWebRoutingSettings _webRoutingSettings; + private readonly WebRoutingSettings _webRoutingSettings; - public AspNetBackOfficeInfo(IGlobalSettings globalSettings, IIOHelper ioHelper, ILogger logger, IWebRoutingSettings webRoutingSettings) + public AspNetBackOfficeInfo(IOptionsSnapshot globalSettings, IIOHelper ioHelper, ILogger logger, IOptionsSnapshot webRoutingSettings) + : this(globalSettings.Value, ioHelper, logger, webRoutingSettings.Value) + { + } + + public AspNetBackOfficeInfo(GlobalSettings globalSettings, IIOHelper ioHelper, ILogger logger, WebRoutingSettings webRoutingSettings) { _globalSettings = globalSettings; _ioHelper = ioHelper; diff --git a/src/Umbraco.Web/AspNet/AspNetHostingEnvironment.cs b/src/Umbraco.Web/AspNet/AspNetHostingEnvironment.cs index 5e7324236a..2423c7802b 100644 --- a/src/Umbraco.Web/AspNet/AspNetHostingEnvironment.cs +++ b/src/Umbraco.Web/AspNet/AspNetHostingEnvironment.cs @@ -2,27 +2,27 @@ using System; using System.Reflection; using System.Web; using System.Web.Hosting; +using Microsoft.Extensions.Options; using Umbraco.Core; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Hosting; namespace Umbraco.Web.Hosting { public class AspNetHostingEnvironment : IHostingEnvironment { - - private readonly IHostingSettings _hostingSettings; + private readonly HostingSettings _hostingSettings; private string _localTempPath; - - public AspNetHostingEnvironment(IHostingSettings hostingSettings) + public AspNetHostingEnvironment(IOptionsSnapshot hostingSettings) { - _hostingSettings = hostingSettings ?? throw new ArgumentNullException(nameof(hostingSettings)); + _hostingSettings = hostingSettings.Value ?? throw new ArgumentNullException(nameof(hostingSettings)); SiteName = HostingEnvironment.SiteName; ApplicationId = HostingEnvironment.ApplicationID; // when we are not hosted (i.e. unit test or otherwise) we'll need to get the root path from the executing assembly ApplicationPhysicalPath = HostingEnvironment.ApplicationPhysicalPath ?? Assembly.GetExecutingAssembly().GetRootDirectorySafe(); - ApplicationVirtualPath = hostingSettings.ApplicationVirtualPath?.EnsureStartsWith('/') + ApplicationVirtualPath = _hostingSettings.ApplicationVirtualPath?.EnsureStartsWith('/') ?? HostingEnvironment.ApplicationVirtualPath?.EnsureStartsWith("/") ?? "/"; IISVersion = HttpRuntime.IISVersion; diff --git a/src/Umbraco.Web/AspNet/AspNetRequestAccessor.cs b/src/Umbraco.Web/AspNet/AspNetRequestAccessor.cs index aa2cba6949..7e1e853716 100644 --- a/src/Umbraco.Web/AspNet/AspNetRequestAccessor.cs +++ b/src/Umbraco.Web/AspNet/AspNetRequestAccessor.cs @@ -1,5 +1,7 @@ using System; using System.Collections.Generic; +using Microsoft.Extensions.Options; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Web.Routing; @@ -8,20 +10,18 @@ namespace Umbraco.Web.AspNet public class AspNetRequestAccessor : IRequestAccessor { private readonly IHttpContextAccessor _httpContextAccessor; - private readonly IWebRoutingSettings _webRoutingSettings; + private readonly WebRoutingSettings _webRoutingSettings; private readonly ISet _applicationUrls = new HashSet(); private Uri _currentApplicationUrl; - public AspNetRequestAccessor(IHttpContextAccessor httpContextAccessor, IWebRoutingSettings webRoutingSettings) + public AspNetRequestAccessor(IHttpContextAccessor httpContextAccessor, IOptionsSnapshot webRoutingSettings) { _httpContextAccessor = httpContextAccessor; - _webRoutingSettings = webRoutingSettings; + _webRoutingSettings = webRoutingSettings.Value; UmbracoModule.EndRequest += OnEndRequest; UmbracoModule.RouteAttempt += OnRouteAttempt; } - - public string GetRequestValue(string name) { return _httpContextAccessor.GetRequiredHttpContext().Request[name]; diff --git a/src/Umbraco.Web/Compose/AuditEventsComponent.cs b/src/Umbraco.Web/Compose/AuditEventsComponent.cs index 51c47233c7..ef81a35b1c 100644 --- a/src/Umbraco.Web/Compose/AuditEventsComponent.cs +++ b/src/Umbraco.Web/Compose/AuditEventsComponent.cs @@ -11,6 +11,8 @@ using Umbraco.Net; using Umbraco.Core.Services; using Umbraco.Core.Services.Implement; using Umbraco.Extensions; +using Umbraco.Core.Configuration.Models; +using Microsoft.Extensions.Options; namespace Umbraco.Core.Compose { @@ -20,15 +22,15 @@ namespace Umbraco.Core.Compose private readonly IUserService _userService; private readonly IEntityService _entityService; private readonly IIpResolver _ipResolver; - private readonly IGlobalSettings _globalSettings; + private readonly GlobalSettings _globalSettings; - public AuditEventsComponent(IAuditService auditService, IUserService userService, IEntityService entityService, IIpResolver ipResolver, IGlobalSettings globalSettings) + public AuditEventsComponent(IAuditService auditService, IUserService userService, IEntityService entityService, IIpResolver ipResolver, IOptionsSnapshot globalSettings) { _auditService = auditService; _userService = userService; _entityService = entityService; _ipResolver = ipResolver; - _globalSettings = globalSettings; + _globalSettings = globalSettings.Value; } public void Initialize() @@ -49,7 +51,7 @@ namespace Umbraco.Core.Compose public void Terminate() { } - public static IUser UnknownUser(IGlobalSettings globalSettings) => new User(globalSettings) { Id = Constants.Security.UnknownUserId, Name = Constants.Security.UnknownUserName, Email = "" }; + public static IUser UnknownUser(GlobalSettings globalSettings) => new User(globalSettings) { Id = Constants.Security.UnknownUserId, Name = Constants.Security.UnknownUserName, Email = "" }; private IUser CurrentPerformingUser { diff --git a/src/Umbraco.Web/Compose/BackOfficeUserAuditEventsComponent.cs b/src/Umbraco.Web/Compose/BackOfficeUserAuditEventsComponent.cs index dcb5fac32d..2357a62eb8 100644 --- a/src/Umbraco.Web/Compose/BackOfficeUserAuditEventsComponent.cs +++ b/src/Umbraco.Web/Compose/BackOfficeUserAuditEventsComponent.cs @@ -1,8 +1,10 @@ using System; +using Microsoft.Extensions.Options; using Umbraco.Core; using Umbraco.Core.Compose; using Umbraco.Core.Composing; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Models.Membership; using Umbraco.Core.Services; using Umbraco.Web.Security; @@ -13,13 +15,13 @@ namespace Umbraco.Web.Compose { private readonly IAuditService _auditService; private readonly IUserService _userService; - private readonly IGlobalSettings _globalSettings; + private readonly GlobalSettings _globalSettings; - public BackOfficeUserAuditEventsComponent(IAuditService auditService, IUserService userService, IGlobalSettings globalSettings) + public BackOfficeUserAuditEventsComponent(IAuditService auditService, IUserService userService, IOptionsSnapshot globalSettings) { _auditService = auditService; _userService = userService; - _globalSettings = globalSettings; + _globalSettings = globalSettings.Value; } public void Initialize() diff --git a/src/Umbraco.Web/Editors/AuthenticationController.cs b/src/Umbraco.Web/Editors/AuthenticationController.cs index 73fa53f7bc..d919f04077 100644 --- a/src/Umbraco.Web/Editors/AuthenticationController.cs +++ b/src/Umbraco.Web/Editors/AuthenticationController.cs @@ -39,7 +39,7 @@ namespace Umbraco.Web.Editors { private BackOfficeOwinUserManager _userManager; private BackOfficeSignInManager _signInManager; - private readonly IUserPasswordConfiguration _passwordConfiguration; + private readonly UserPasswordConfigurationSettings _passwordConfiguration; private readonly IHostingEnvironment _hostingEnvironment; private readonly IRuntimeState _runtimeState; private readonly SecuritySettings _securitySettings; @@ -47,8 +47,8 @@ namespace Umbraco.Web.Editors private readonly IEmailSender _emailSender; public AuthenticationController( - IUserPasswordConfiguration passwordConfiguration, - IGlobalSettings globalSettings, + IOptionsSnapshot passwordConfiguration, + IOptionsSnapshot globalSettings, IHostingEnvironment hostingEnvironment, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, @@ -63,7 +63,7 @@ namespace Umbraco.Web.Editors IEmailSender emailSender) : base(globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoMapper, publishedUrlProvider) { - _passwordConfiguration = passwordConfiguration ?? throw new ArgumentNullException(nameof(passwordConfiguration)); + _passwordConfiguration = passwordConfiguration.Value ?? throw new ArgumentNullException(nameof(passwordConfiguration)); _hostingEnvironment = hostingEnvironment ?? throw new ArgumentNullException(nameof(hostingEnvironment)); _runtimeState = runtimeState ?? throw new ArgumentNullException(nameof(runtimeState)); _securitySettings = securitySettings.Value ?? throw new ArgumentNullException(nameof(securitySettings)); diff --git a/src/Umbraco.Web/Editors/BackOfficeController.cs b/src/Umbraco.Web/Editors/BackOfficeController.cs index 4258267421..de94f42007 100644 --- a/src/Umbraco.Web/Editors/BackOfficeController.cs +++ b/src/Umbraco.Web/Editors/BackOfficeController.cs @@ -41,7 +41,7 @@ namespace Umbraco.Web.Editors public BackOfficeController( UmbracoFeatures features, - IGlobalSettings globalSettings, + IOptionsSnapshot globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ServiceContext services, AppCaches appCaches, diff --git a/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs b/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs index 0dd232cbfb..4246ffb2ec 100644 --- a/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs +++ b/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs @@ -28,7 +28,7 @@ namespace Umbraco.Web.Editors private readonly UrlHelper _urlHelper; private readonly IRuntimeState _runtimeState; private readonly UmbracoFeatures _features; - private readonly IGlobalSettings _globalSettings; + private readonly GlobalSettings _globalSettings; private readonly IUmbracoVersion _umbracoVersion; private readonly IContentSettings _contentSettings; private readonly TreeCollection _treeCollection; @@ -42,7 +42,7 @@ namespace Umbraco.Web.Editors UrlHelper urlHelper, IRuntimeState runtimeState, UmbracoFeatures features, - IGlobalSettings globalSettings, + IOptionsSnapshot globalSettings, IUmbracoVersion umbracoVersion, IContentSettings contentSettings, TreeCollection treeCollection, @@ -54,7 +54,7 @@ namespace Umbraco.Web.Editors _urlHelper = urlHelper; _runtimeState = runtimeState; _features = features; - _globalSettings = globalSettings; + _globalSettings = globalSettings.Value; _umbracoVersion = umbracoVersion; _contentSettings = contentSettings ?? throw new ArgumentNullException(nameof(contentSettings)); _treeCollection = treeCollection ?? throw new ArgumentNullException(nameof(treeCollection)); diff --git a/src/Umbraco.Web/Editors/UmbracoAuthorizedJsonController.cs b/src/Umbraco.Web/Editors/UmbracoAuthorizedJsonController.cs index 64aba378f4..f0f7e50be5 100644 --- a/src/Umbraco.Web/Editors/UmbracoAuthorizedJsonController.cs +++ b/src/Umbraco.Web/Editors/UmbracoAuthorizedJsonController.cs @@ -1,7 +1,9 @@ using System; +using Microsoft.Extensions.Options; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Logging; using Umbraco.Core.Mapping; using Umbraco.Core.Persistence; @@ -31,7 +33,7 @@ namespace Umbraco.Web.Editors } protected UmbracoAuthorizedJsonController( - IGlobalSettings globalSettings, + IOptionsSnapshot globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, diff --git a/src/Umbraco.Web/HtmlHelperRenderExtensions.cs b/src/Umbraco.Web/HtmlHelperRenderExtensions.cs index 6fe069fc59..d6c4451efb 100644 --- a/src/Umbraco.Web/HtmlHelperRenderExtensions.cs +++ b/src/Umbraco.Web/HtmlHelperRenderExtensions.cs @@ -10,6 +10,7 @@ using System.Web.Mvc.Html; using System.Web.Routing; using Umbraco.Core; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.IO; using Umbraco.Web.Mvc; @@ -60,18 +61,18 @@ namespace Umbraco.Web /// /// See: http://issues.umbraco.org/issue/U4-1614 /// - public static MvcHtmlString PreviewBadge(this HtmlHelper helper, IHttpContextAccessor httpContextAccessor, IGlobalSettings globalSettings, IIOHelper ioHelper, IContentSettings contentSettings) + public static MvcHtmlString PreviewBadge(this HtmlHelper helper, IHttpContextAccessor httpContextAccessor, GlobalSettings globalSettings, IIOHelper ioHelper, IContentSettings contentSettings) { if (Current.UmbracoContext.InPreviewMode) { var htmlBadge = - String.Format(contentSettings.PreviewBadge, + string.Format(contentSettings.PreviewBadge, ioHelper.ResolveUrl(globalSettings.UmbracoPath), WebUtility.UrlEncode(httpContextAccessor.GetRequiredHttpContext().Request.Path), Current.UmbracoContext.PublishedRequest.PublishedContent.Id); return new MvcHtmlString(htmlBadge); } - return new MvcHtmlString(""); + return new MvcHtmlString(string.Empty); } diff --git a/src/Umbraco.Web/Mvc/AreaRegistrationExtensions.cs b/src/Umbraco.Web/Mvc/AreaRegistrationExtensions.cs index 118c53a7f0..e25ab4a69e 100644 --- a/src/Umbraco.Web/Mvc/AreaRegistrationExtensions.cs +++ b/src/Umbraco.Web/Mvc/AreaRegistrationExtensions.cs @@ -6,10 +6,8 @@ using System.Web.Routing; using System.Web.SessionState; using Umbraco.Core; using Umbraco.Core.Configuration; -using Umbraco.Core.Exceptions; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Hosting; -using Umbraco.Core.IO; -using Umbraco.Web.Composing; using Umbraco.Web.WebApi; namespace Umbraco.Web.Mvc @@ -44,7 +42,7 @@ namespace Umbraco.Web.Mvc /// /// internal static Route RouteControllerPlugin(this AreaRegistration area, - IGlobalSettings globalSettings, IHostingEnvironment hostingEnvironment, + GlobalSettings globalSettings, IHostingEnvironment hostingEnvironment, string controllerName, Type controllerType, RouteCollection routes, string controllerSuffixName, string defaultAction, object defaultId, string umbracoTokenValue = "backoffice", diff --git a/src/Umbraco.Web/Mvc/BackOfficeArea.cs b/src/Umbraco.Web/Mvc/BackOfficeArea.cs index 156a896bb5..2037d37914 100644 --- a/src/Umbraco.Web/Mvc/BackOfficeArea.cs +++ b/src/Umbraco.Web/Mvc/BackOfficeArea.cs @@ -1,8 +1,8 @@ using System.Web.Mvc; -using Umbraco.Web.Composing; +using Microsoft.Extensions.Options; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Hosting; -using Umbraco.Core.IO; using Umbraco.Web.Editors; namespace Umbraco.Web.Mvc @@ -10,10 +10,15 @@ namespace Umbraco.Web.Mvc // TODO: This has been ported to netcore, can be removed internal class BackOfficeArea : AreaRegistration { - private readonly IGlobalSettings _globalSettings; + private readonly GlobalSettings _globalSettings; private readonly IHostingEnvironment _hostingEnvironment; - public BackOfficeArea(IGlobalSettings globalSettings, IHostingEnvironment hostingEnvironment) + public BackOfficeArea(IOptionsSnapshot globalSettings, IHostingEnvironment hostingEnvironment) + : this(globalSettings.Value, hostingEnvironment) + { + } + + public BackOfficeArea(GlobalSettings globalSettings, IHostingEnvironment hostingEnvironment) { _globalSettings = globalSettings; _hostingEnvironment = hostingEnvironment; diff --git a/src/Umbraco.Web/Mvc/PluginControllerArea.cs b/src/Umbraco.Web/Mvc/PluginControllerArea.cs index 838e304847..bf2d24086d 100644 --- a/src/Umbraco.Web/Mvc/PluginControllerArea.cs +++ b/src/Umbraco.Web/Mvc/PluginControllerArea.cs @@ -9,6 +9,8 @@ using Umbraco.Core.Composing; using Umbraco.Core.Hosting; using Umbraco.Core.IO; using Umbraco.Web.WebApi; +using Umbraco.Core.Configuration.Models; +using Microsoft.Extensions.Options; namespace Umbraco.Web.Mvc { @@ -17,7 +19,7 @@ namespace Umbraco.Web.Mvc /// internal class PluginControllerArea : AreaRegistration { - private readonly IGlobalSettings _globalSettings; + private readonly GlobalSettings _globalSettings; private readonly IHostingEnvironment _hostingEnvironment; private readonly IEnumerable _surfaceControllers; private readonly IEnumerable _apiControllers; @@ -30,7 +32,12 @@ namespace Umbraco.Web.Mvc /// /// /// - public PluginControllerArea(IGlobalSettings globalSettings, IHostingEnvironment hostingEnvironment, IEnumerable pluginControllers) + public PluginControllerArea(IOptionsSnapshot globalSettings, IHostingEnvironment hostingEnvironment, IEnumerable pluginControllers) + : this(globalSettings.Value, hostingEnvironment, pluginControllers) + { + } + + public PluginControllerArea(GlobalSettings globalSettings, IHostingEnvironment hostingEnvironment, IEnumerable pluginControllers) { _globalSettings = globalSettings; _hostingEnvironment = hostingEnvironment; @@ -41,7 +48,7 @@ namespace Umbraco.Web.Mvc throw new InvalidOperationException("Cannot create a PluginControllerArea unless all plugin controllers assigned have a PluginControllerAttribute assigned"); } _areaName = controllers.First().AreaName; - foreach(var c in controllers) + foreach (var c in controllers) { if (c.AreaName != _areaName) { diff --git a/src/Umbraco.Web/Mvc/RenderMvcController.cs b/src/Umbraco.Web/Mvc/RenderMvcController.cs index 7286f52c64..1e6f5a00c3 100644 --- a/src/Umbraco.Web/Mvc/RenderMvcController.cs +++ b/src/Umbraco.Web/Mvc/RenderMvcController.cs @@ -1,7 +1,8 @@ using System; using System.Web.Mvc; +using Microsoft.Extensions.Options; using Umbraco.Core.Cache; -using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Logging; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Services; @@ -10,7 +11,6 @@ using Umbraco.Web.Routing; namespace Umbraco.Web.Mvc { - /// /// Represents the default front-end rendering controller. /// @@ -25,7 +25,7 @@ namespace Umbraco.Web.Mvc ActionInvoker = new RenderActionInvoker(); } - public RenderMvcController(IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ServiceContext services, AppCaches appCaches, IProfilingLogger profilingLogger) + public RenderMvcController(IOptionsSnapshot globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ServiceContext services, AppCaches appCaches, IProfilingLogger profilingLogger) : base(globalSettings, umbracoContextAccessor, services, appCaches, profilingLogger) { ActionInvoker = new RenderActionInvoker(); diff --git a/src/Umbraco.Web/Mvc/RenderNoContentController.cs b/src/Umbraco.Web/Mvc/RenderNoContentController.cs index 9334591fbb..1f9a24212b 100644 --- a/src/Umbraco.Web/Mvc/RenderNoContentController.cs +++ b/src/Umbraco.Web/Mvc/RenderNoContentController.cs @@ -1,6 +1,8 @@ using System; using System.Web.Mvc; +using Microsoft.Extensions.Options; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.IO; using Umbraco.Web.Models; @@ -10,13 +12,13 @@ namespace Umbraco.Web.Mvc { private readonly IUmbracoContextAccessor _umbracoContextAccessor; private readonly IIOHelper _ioHelper; - private readonly IGlobalSettings _globalSettings; + private readonly GlobalSettings _globalSettings; - public RenderNoContentController(IUmbracoContextAccessor umbracoContextAccessor, IIOHelper ioHelper, IGlobalSettings globalSettings) + public RenderNoContentController(IUmbracoContextAccessor umbracoContextAccessor, IIOHelper ioHelper, IOptionsSnapshot globalSettings) { _umbracoContextAccessor = umbracoContextAccessor ?? throw new ArgumentNullException(nameof(umbracoContextAccessor)); _ioHelper = ioHelper ?? throw new ArgumentNullException(nameof(ioHelper)); - _globalSettings = globalSettings ?? throw new ArgumentNullException(nameof(globalSettings)); + _globalSettings = globalSettings.Value ?? throw new ArgumentNullException(nameof(globalSettings)); } public ActionResult Index() diff --git a/src/Umbraco.Web/Mvc/UmbracoAuthorizedController.cs b/src/Umbraco.Web/Mvc/UmbracoAuthorizedController.cs index 0724cd138d..f774eb8a4e 100644 --- a/src/Umbraco.Web/Mvc/UmbracoAuthorizedController.cs +++ b/src/Umbraco.Web/Mvc/UmbracoAuthorizedController.cs @@ -1,5 +1,7 @@ -using Umbraco.Core.Cache; +using Microsoft.Extensions.Options; +using Umbraco.Core.Cache; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Logging; using Umbraco.Core.Persistence; using Umbraco.Core.Services; @@ -21,7 +23,7 @@ namespace Umbraco.Web.Mvc { } - protected UmbracoAuthorizedController(IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ServiceContext services, AppCaches appCaches, IProfilingLogger profilingLogger) + protected UmbracoAuthorizedController(IOptionsSnapshot globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ServiceContext services, AppCaches appCaches, IProfilingLogger profilingLogger) : base(globalSettings, umbracoContextAccessor, services, appCaches, profilingLogger) { } diff --git a/src/Umbraco.Web/Mvc/UmbracoController.cs b/src/Umbraco.Web/Mvc/UmbracoController.cs index 9cfd93ba9d..ff0ac170fb 100644 --- a/src/Umbraco.Web/Mvc/UmbracoController.cs +++ b/src/Umbraco.Web/Mvc/UmbracoController.cs @@ -1,13 +1,14 @@ using System; using System.Web; using System.Web.Mvc; +using Microsoft.Extensions.Options; using Microsoft.Owin; -using Umbraco.Core.Cache; -using Umbraco.Web.Composing; -using Umbraco.Core.Configuration; -using Umbraco.Core.Logging; using Umbraco.Core; +using Umbraco.Core.Cache; +using Umbraco.Core.Configuration.Models; +using Umbraco.Core.Logging; using Umbraco.Core.Services; +using Umbraco.Web.Composing; using Umbraco.Web.Security; namespace Umbraco.Web.Mvc @@ -21,9 +22,9 @@ namespace Umbraco.Web.Mvc internal Guid InstanceId { get; } = Guid.NewGuid(); /// - /// Gets or sets the Umbraco context. + /// Gets the global settings from configuration. /// - public IGlobalSettings GlobalSettings { get; } + public GlobalSettings GlobalSettings { get; } /// /// Gets the Umbraco context. @@ -69,7 +70,7 @@ namespace Umbraco.Web.Mvc protected UmbracoController() : this( - Current.Factory.GetInstance(), + Current.Factory.GetInstance>(), Current.Factory.GetInstance(), Current.Factory.GetInstance(), Current.Factory.GetInstance(), @@ -78,9 +79,9 @@ namespace Umbraco.Web.Mvc { } - protected UmbracoController(IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ServiceContext services, AppCaches appCaches, IProfilingLogger profilingLogger) + protected UmbracoController(IOptionsSnapshot globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ServiceContext services, AppCaches appCaches, IProfilingLogger profilingLogger) { - GlobalSettings = globalSettings; + GlobalSettings = globalSettings.Value; UmbracoContextAccessor = umbracoContextAccessor; Services = services; AppCaches = appCaches; diff --git a/src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs b/src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs index a687e7c9cd..b9c31388a2 100644 --- a/src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs +++ b/src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs @@ -3,9 +3,11 @@ using System.Text; using System.Web; using System.Web.Mvc; using System.Web.WebPages; +using Microsoft.Extensions.Options; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Services; @@ -22,8 +24,8 @@ namespace Umbraco.Web.Mvc /// public abstract class UmbracoViewPage : WebViewPage { - private readonly IGlobalSettings _globalSettings; - private readonly IContentSettings _contentSettings; + private readonly GlobalSettings _globalSettings; + private readonly ContentSettings _contentSettings; private IUmbracoContext _umbracoContext; private UmbracoHelper _helper; @@ -105,18 +107,18 @@ namespace Umbraco.Web.Mvc : this( Current.Factory.GetInstance(), Current.Factory.GetInstance(), - Current.Factory.GetInstance(), - Current.Factory.GetInstance() + Current.Factory.GetInstance>(), + Current.Factory.GetInstance>() ) { } - protected UmbracoViewPage(ServiceContext services, AppCaches appCaches, IGlobalSettings globalSettings, IContentSettings contentSettings) + protected UmbracoViewPage(ServiceContext services, AppCaches appCaches, IOptionsSnapshot globalSettings, IOptionsSnapshot contentSettings) { Services = services; AppCaches = appCaches; - _globalSettings = globalSettings ?? throw new ArgumentNullException(nameof(globalSettings)); - _contentSettings = contentSettings ?? throw new ArgumentNullException(nameof(contentSettings)); + _globalSettings = globalSettings.Value ?? throw new ArgumentNullException(nameof(globalSettings)); + _contentSettings = contentSettings.Value ?? throw new ArgumentNullException(nameof(contentSettings)); } // view logic below: diff --git a/src/Umbraco.Web/RoutableDocumentFilter.cs b/src/Umbraco.Web/RoutableDocumentFilter.cs index 43e47a39b3..5f5c832d1f 100644 --- a/src/Umbraco.Web/RoutableDocumentFilter.cs +++ b/src/Umbraco.Web/RoutableDocumentFilter.cs @@ -1,16 +1,17 @@ using System; +using System.Collections.Concurrent; +using System.Collections.Generic; using System.IO; +using System.Linq; +using System.Threading; using System.Web; using System.Web.Routing; +using Microsoft.Extensions.Options; using Umbraco.Core; -using Umbraco.Core.Configuration; -using System.Threading; -using System.Collections.Generic; -using System.Linq; -using System.Collections.Concurrent; using Umbraco.Core.Collections; +using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.IO; -using Umbraco.Web.Composing; namespace Umbraco.Web { @@ -22,20 +23,20 @@ namespace Umbraco.Web /// public sealed class RoutableDocumentFilter { - public RoutableDocumentFilter(IGlobalSettings globalSettings, IIOHelper ioHelper) - { - _globalSettings = globalSettings; - _ioHelper = ioHelper; - } - private static readonly ConcurrentDictionary RouteChecks = new ConcurrentDictionary(); - private readonly IGlobalSettings _globalSettings; + private readonly GlobalSettings _globalSettings; private readonly IIOHelper _ioHelper; private object _locker = new object(); private bool _isInit = false; private int? _routeCount; private HashSet _reservedList; + public RoutableDocumentFilter(IOptionsSnapshot globalSettings, IIOHelper ioHelper) + { + _globalSettings = globalSettings.Value; + _ioHelper = ioHelper; + } + /// /// Checks if the request is a document request (i.e. one that the module should handle) /// diff --git a/src/Umbraco.Web/Runtime/WebInitialComponent.cs b/src/Umbraco.Web/Runtime/WebInitialComponent.cs index dbd0a1fb3a..88c08cd937 100644 --- a/src/Umbraco.Web/Runtime/WebInitialComponent.cs +++ b/src/Umbraco.Web/Runtime/WebInitialComponent.cs @@ -17,6 +17,8 @@ using Umbraco.Web.WebApi; using Constants = Umbraco.Core.Constants; using Current = Umbraco.Web.Composing.Current; +using Umbraco.Core.Configuration.Models; +using Microsoft.Extensions.Options; namespace Umbraco.Web.Runtime { @@ -25,7 +27,7 @@ namespace Umbraco.Web.Runtime private readonly IUmbracoContextAccessor _umbracoContextAccessor; private readonly SurfaceControllerTypeCollection _surfaceControllerTypes; private readonly UmbracoApiControllerTypeCollection _apiControllerTypes; - private readonly IGlobalSettings _globalSettings; + private readonly GlobalSettings _globalSettings; private readonly IHostingEnvironment _hostingEnvironment; private readonly IShortStringHelper _shortStringHelper; @@ -33,14 +35,14 @@ namespace Umbraco.Web.Runtime IUmbracoContextAccessor umbracoContextAccessor, SurfaceControllerTypeCollection surfaceControllerTypes, UmbracoApiControllerTypeCollection apiControllerTypes, - IGlobalSettings globalSettings, + IOptionsSnapshot globalSettings, IHostingEnvironment hostingEnvironment, IShortStringHelper shortStringHelper) { _umbracoContextAccessor = umbracoContextAccessor; _surfaceControllerTypes = surfaceControllerTypes; _apiControllerTypes = apiControllerTypes; - _globalSettings = globalSettings; + _globalSettings = globalSettings.Value; _hostingEnvironment = hostingEnvironment; _shortStringHelper = shortStringHelper; } @@ -111,7 +113,7 @@ namespace Umbraco.Web.Runtime // internal for tests internal static void CreateRoutes( IUmbracoContextAccessor umbracoContextAccessor, - IGlobalSettings globalSettings, + GlobalSettings globalSettings, IShortStringHelper shortStringHelper, SurfaceControllerTypeCollection surfaceControllerTypes, UmbracoApiControllerTypeCollection apiControllerTypes, @@ -149,7 +151,7 @@ namespace Umbraco.Web.Runtime } private static void RoutePluginControllers( - IGlobalSettings globalSettings, + GlobalSettings globalSettings, SurfaceControllerTypeCollection surfaceControllerTypes, UmbracoApiControllerTypeCollection apiControllerTypes, IHostingEnvironment hostingEnvironment) diff --git a/src/Umbraco.Web/Security/AppBuilderExtensions.cs b/src/Umbraco.Web/Security/AppBuilderExtensions.cs index ac5434aa4e..885baaab79 100644 --- a/src/Umbraco.Web/Security/AppBuilderExtensions.cs +++ b/src/Umbraco.Web/Security/AppBuilderExtensions.cs @@ -8,6 +8,7 @@ using Owin; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Hosting; using Umbraco.Web.Composing; using Constants = Umbraco.Core.Constants; @@ -34,7 +35,7 @@ namespace Umbraco.Web.Security /// /// By default this will be configured to execute on PipelineStage.Authenticate /// - public static IAppBuilder UseUmbracoBackOfficeExternalCookieAuthentication(this IAppBuilder app, IUmbracoContextAccessor umbracoContextAccessor, IRuntimeState runtimeState,IGlobalSettings globalSettings, IHostingEnvironment hostingEnvironment, IRequestCache requestCache) + public static IAppBuilder UseUmbracoBackOfficeExternalCookieAuthentication(this IAppBuilder app, IUmbracoContextAccessor umbracoContextAccessor, IRuntimeState runtimeState, GlobalSettings globalSettings, IHostingEnvironment hostingEnvironment, IRequestCache requestCache) { return app.UseUmbracoBackOfficeExternalCookieAuthentication(umbracoContextAccessor, runtimeState, globalSettings, hostingEnvironment, requestCache, PipelineStage.Authenticate); } @@ -53,7 +54,7 @@ namespace Umbraco.Web.Security /// public static IAppBuilder UseUmbracoBackOfficeExternalCookieAuthentication(this IAppBuilder app, IUmbracoContextAccessor umbracoContextAccessor, IRuntimeState runtimeState, - IGlobalSettings globalSettings, IHostingEnvironment hostingEnvironment, IRequestCache requestCache, PipelineStage stage) + GlobalSettings globalSettings, IHostingEnvironment hostingEnvironment, IRequestCache requestCache, PipelineStage stage) { if (app == null) throw new ArgumentNullException(nameof(app)); if (runtimeState == null) throw new ArgumentNullException(nameof(runtimeState)); diff --git a/src/Umbraco.Web/Security/BackOfficeCookieAuthenticationProvider.cs b/src/Umbraco.Web/Security/BackOfficeCookieAuthenticationProvider.cs index 8a093f1943..beb79d3e98 100644 --- a/src/Umbraco.Web/Security/BackOfficeCookieAuthenticationProvider.cs +++ b/src/Umbraco.Web/Security/BackOfficeCookieAuthenticationProvider.cs @@ -14,20 +14,20 @@ namespace Umbraco.Web.Security { private readonly IUserService _userService; private readonly IRuntimeState _runtimeState; - private readonly IGlobalSettings _globalSettings; + private readonly GlobalSettings _globalSettings; private readonly IHostingEnvironment _hostingEnvironment; private readonly SecuritySettings _securitySettings; public BackOfficeCookieAuthenticationProvider( IUserService userService, IRuntimeState runtimeState, - IGlobalSettings globalSettings, + IOptionsSnapshot globalSettings, IHostingEnvironment hostingEnvironment, IOptionsSnapshot securitySettings) { _userService = userService; _runtimeState = runtimeState; - _globalSettings = globalSettings; + _globalSettings = globalSettings.Value; _hostingEnvironment = hostingEnvironment; _securitySettings = securitySettings.Value; } diff --git a/src/Umbraco.Web/Security/BackOfficeOwinUserManager.cs b/src/Umbraco.Web/Security/BackOfficeOwinUserManager.cs index da3500fb25..5464902bb3 100644 --- a/src/Umbraco.Web/Security/BackOfficeOwinUserManager.cs +++ b/src/Umbraco.Web/Security/BackOfficeOwinUserManager.cs @@ -46,7 +46,7 @@ namespace Umbraco.Web.Security IUserService userService, IEntityService entityService, IExternalLoginService externalLoginService, - IGlobalSettings globalSettings, + GlobalSettings globalSettings, UmbracoMapper mapper, UserPasswordConfigurationSettings passwordConfiguration, IIpResolver ipResolver, diff --git a/src/Umbraco.Web/Security/BackOfficeSignInManager.cs b/src/Umbraco.Web/Security/BackOfficeSignInManager.cs index 021adaed97..01ed3ae30e 100644 --- a/src/Umbraco.Web/Security/BackOfficeSignInManager.cs +++ b/src/Umbraco.Web/Security/BackOfficeSignInManager.cs @@ -11,6 +11,7 @@ using Umbraco.Core; using Umbraco.Core.BackOffice; using Umbraco.Core.Configuration; using Umbraco.Core.BackOffice; +using Umbraco.Core.Configuration.Models; namespace Umbraco.Web.Security { @@ -25,7 +26,7 @@ namespace Umbraco.Web.Security private readonly IUserClaimsPrincipalFactory _claimsPrincipalFactory; private readonly IAuthenticationManager _authenticationManager; private readonly ILogger _logger; - private readonly IGlobalSettings _globalSettings; + private readonly GlobalSettings _globalSettings; private readonly IOwinRequest _request; public BackOfficeSignInManager( @@ -33,7 +34,18 @@ namespace Umbraco.Web.Security IUserClaimsPrincipalFactory claimsPrincipalFactory, IAuthenticationManager authenticationManager, ILogger logger, - IGlobalSettings globalSettings, + IOptionsSnapshot globalSettings, + IOwinRequest request) + :this(userManager, claimsPrincipalFactory, authenticationManager, logger, globalSettings.Value, request) + { + } + + public BackOfficeSignInManager( + BackOfficeUserManager userManager, + IUserClaimsPrincipalFactory claimsPrincipalFactory, + IAuthenticationManager authenticationManager, + ILogger logger, + GlobalSettings globalSettings, IOwinRequest request) { _userManager = userManager ?? throw new ArgumentNullException(nameof(userManager)); @@ -52,7 +64,7 @@ namespace Umbraco.Web.Security return claimsPrincipal.Identity as ClaimsIdentity; } - public static BackOfficeSignInManager Create(IOwinContext context, IGlobalSettings globalSettings, ILogger logger) + public static BackOfficeSignInManager Create(IOwinContext context, GlobalSettings globalSettings, ILogger logger) { var userManager = context.GetBackOfficeUserManager(); diff --git a/src/Umbraco.Web/Security/GetUserSecondsMiddleWare.cs b/src/Umbraco.Web/Security/GetUserSecondsMiddleWare.cs index 0bf83efd34..e1227a892d 100644 --- a/src/Umbraco.Web/Security/GetUserSecondsMiddleWare.cs +++ b/src/Umbraco.Web/Security/GetUserSecondsMiddleWare.cs @@ -24,7 +24,7 @@ namespace Umbraco.Web.Security internal class GetUserSecondsMiddleWare : OwinMiddleware { private readonly UmbracoBackOfficeCookieAuthOptions _authOptions; - private readonly IGlobalSettings _globalSettings; + private readonly GlobalSettings _globalSettings; private readonly SecuritySettings _securitySettings; private readonly ILogger _logger; private readonly IHostingEnvironment _hostingEnvironment; @@ -32,14 +32,14 @@ namespace Umbraco.Web.Security public GetUserSecondsMiddleWare( OwinMiddleware next, UmbracoBackOfficeCookieAuthOptions authOptions, - IGlobalSettings globalSettings, + IOptionsSnapshot globalSettings, IOptionsSnapshot securitySettings, ILogger logger, IHostingEnvironment hostingEnvironment) : base(next) { _authOptions = authOptions ?? throw new ArgumentNullException(nameof(authOptions)); - _globalSettings = globalSettings; + _globalSettings = globalSettings.Value; _securitySettings = securitySettings.Value; _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _hostingEnvironment = hostingEnvironment; diff --git a/src/Umbraco.Web/UmbracoApplicationBase.cs b/src/Umbraco.Web/UmbracoApplicationBase.cs index 1c447b38aa..7eeea5662c 100644 --- a/src/Umbraco.Web/UmbracoApplicationBase.cs +++ b/src/Umbraco.Web/UmbracoApplicationBase.cs @@ -9,6 +9,7 @@ using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Composing; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Hosting; using Umbraco.Core.IO; using Umbraco.Core.Logging; @@ -44,7 +45,7 @@ namespace Umbraco.Web Path.Combine(hostingEnvironment.ApplicationPhysicalPath, "App_Data\\Logs"), Path.Combine(hostingEnvironment.ApplicationPhysicalPath, "config\\serilog.config"), Path.Combine(hostingEnvironment.ApplicationPhysicalPath, "config\\serilog.user.config")); - var ioHelper = new IOHelper(hostingEnvironment, globalSettings); + var ioHelper = new IOHelper(hostingEnvironment); var logger = SerilogLogger.CreateWithDefaultConfiguration(hostingEnvironment, loggingConfiguration); var configs = configFactory.Create(); @@ -125,7 +126,7 @@ namespace Umbraco.Web /// /// Gets the application register. /// - protected virtual IRegister GetRegister(IGlobalSettings globalSettings) + protected virtual IRegister GetRegister(GlobalSettings globalSettings) { return RegisterFactory.Create(globalSettings); } diff --git a/src/Umbraco.Web/UmbracoContext.cs b/src/Umbraco.Web/UmbracoContext.cs index ae1cf885b3..703f5f9b51 100644 --- a/src/Umbraco.Web/UmbracoContext.cs +++ b/src/Umbraco.Web/UmbracoContext.cs @@ -2,6 +2,7 @@ using System; using System.Web; using Umbraco.Core; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Hosting; using Umbraco.Core.Models.PublishedContent; using Umbraco.Web.Composing; @@ -17,7 +18,7 @@ namespace Umbraco.Web public class UmbracoContext : DisposableObjectSlim, IDisposeOnRequestEnd, IUmbracoContext { private readonly IHttpContextAccessor _httpContextAccessor; - private readonly IGlobalSettings _globalSettings; + private readonly GlobalSettings _globalSettings; private readonly IHostingEnvironment _hostingEnvironment; private readonly ICookieManager _cookieManager; private readonly Lazy _publishedSnapshot; @@ -31,7 +32,7 @@ namespace Umbraco.Web internal UmbracoContext(IHttpContextAccessor httpContextAccessor, IPublishedSnapshotService publishedSnapshotService, IWebSecurity webSecurity, - IGlobalSettings globalSettings, + GlobalSettings globalSettings, IHostingEnvironment hostingEnvironment, IVariationContextAccessor variationContextAccessor, UriUtility uriUtility, diff --git a/src/Umbraco.Web/UmbracoContextFactory.cs b/src/Umbraco.Web/UmbracoContextFactory.cs index bfb4dd627d..a804e4b3be 100644 --- a/src/Umbraco.Web/UmbracoContextFactory.cs +++ b/src/Umbraco.Web/UmbracoContextFactory.cs @@ -1,7 +1,9 @@ using System; using System.IO; using System.Text; +using Microsoft.Extensions.Options; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Hosting; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Services; @@ -20,7 +22,7 @@ namespace Umbraco.Web private readonly IVariationContextAccessor _variationContextAccessor; private readonly IDefaultCultureAccessor _defaultCultureAccessor; - private readonly IGlobalSettings _globalSettings; + private readonly GlobalSettings _globalSettings; private readonly IUserService _userService; private readonly IHostingEnvironment _hostingEnvironment; private readonly IHttpContextAccessor _httpContextAccessor; @@ -35,7 +37,7 @@ namespace Umbraco.Web IPublishedSnapshotService publishedSnapshotService, IVariationContextAccessor variationContextAccessor, IDefaultCultureAccessor defaultCultureAccessor, - IGlobalSettings globalSettings, + IOptionsSnapshot globalSettings, IUserService userService, IHostingEnvironment hostingEnvironment, UriUtility uriUtility, @@ -46,7 +48,7 @@ namespace Umbraco.Web _publishedSnapshotService = publishedSnapshotService ?? throw new ArgumentNullException(nameof(publishedSnapshotService)); _variationContextAccessor = variationContextAccessor ?? throw new ArgumentNullException(nameof(variationContextAccessor)); _defaultCultureAccessor = defaultCultureAccessor ?? throw new ArgumentNullException(nameof(defaultCultureAccessor)); - _globalSettings = globalSettings ?? throw new ArgumentNullException(nameof(globalSettings)); + _globalSettings = globalSettings.Value ?? throw new ArgumentNullException(nameof(globalSettings)); _userService = userService ?? throw new ArgumentNullException(nameof(userService)); _hostingEnvironment = hostingEnvironment; _uriUtility = uriUtility; diff --git a/src/Umbraco.Web/WebApi/UmbracoApiController.cs b/src/Umbraco.Web/WebApi/UmbracoApiController.cs index a832b4e823..36cf0d5c20 100644 --- a/src/Umbraco.Web/WebApi/UmbracoApiController.cs +++ b/src/Umbraco.Web/WebApi/UmbracoApiController.cs @@ -1,8 +1,10 @@ using System; +using Microsoft.Extensions.Options; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Composing; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Logging; using Umbraco.Core.Mapping; using Umbraco.Core.Persistence; @@ -20,7 +22,7 @@ namespace Umbraco.Web.WebApi { } - protected UmbracoApiController(IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoMapper umbracoMapper, IPublishedUrlProvider publishedUrlProvider) + protected UmbracoApiController(IOptionsSnapshot globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoMapper umbracoMapper, IPublishedUrlProvider publishedUrlProvider) : base(globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoMapper, publishedUrlProvider) { } diff --git a/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs b/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs index d009528bc7..323f09316f 100644 --- a/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs +++ b/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs @@ -14,11 +14,11 @@ using Umbraco.Web.Features; using Umbraco.Web.Routing; using Umbraco.Web.Security; using Umbraco.Web.WebApi.Filters; +using Microsoft.Extensions.Options; +using Umbraco.Core.Configuration.Models; namespace Umbraco.Web.WebApi { - - /// /// Provides a base class for Umbraco API controllers. /// @@ -26,7 +26,6 @@ namespace Umbraco.Web.WebApi [FeatureAuthorize] public abstract class UmbracoApiControllerBase : ApiController, IUmbracoFeature { - // note: all Umbraco controllers have two constructors: one with all dependencies, which should be used, // and one with auto dependencies, ie no dependencies - and then dependencies are automatically obtained // here from the Current service locator - this is obviously evil, but it allows us to add new dependencies @@ -38,7 +37,7 @@ namespace Umbraco.Web.WebApi /// Dependencies are obtained from the service locator. protected UmbracoApiControllerBase() : this( - Current.Factory.GetInstance(), + Current.Factory.GetInstance>(), Current.Factory.GetInstance(), Current.Factory.GetInstance(), Current.Factory.GetInstance(), @@ -53,10 +52,10 @@ namespace Umbraco.Web.WebApi /// /// Initializes a new instance of the class with all its dependencies. /// - protected UmbracoApiControllerBase(IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoMapper umbracoMapper, IPublishedUrlProvider publishedUrlProvider) + protected UmbracoApiControllerBase(IOptionsSnapshot globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoMapper umbracoMapper, IPublishedUrlProvider publishedUrlProvider) { UmbracoContextAccessor = umbracoContextAccessor; - GlobalSettings = globalSettings; + GlobalSettings = globalSettings.Value; SqlContext = sqlContext; Services = services; AppCaches = appCaches; @@ -73,9 +72,9 @@ namespace Umbraco.Web.WebApi internal Guid InstanceId { get; } = Guid.NewGuid(); /// - /// Gets the Umbraco context. + /// Gets the global settings from configuration. /// - public virtual IGlobalSettings GlobalSettings { get; } + public virtual GlobalSettings GlobalSettings { get; } /// /// Gets the Umbraco context. diff --git a/src/Umbraco.Web/WebApi/UmbracoAuthorizedApiController.cs b/src/Umbraco.Web/WebApi/UmbracoAuthorizedApiController.cs index 48b3de44fd..1bd9fb8f31 100644 --- a/src/Umbraco.Web/WebApi/UmbracoAuthorizedApiController.cs +++ b/src/Umbraco.Web/WebApi/UmbracoAuthorizedApiController.cs @@ -8,6 +8,8 @@ using Umbraco.Core.Services; using Umbraco.Web.Security; using Umbraco.Core.Mapping; using Umbraco.Web.Routing; +using Microsoft.Extensions.Options; +using Umbraco.Core.Configuration.Models; namespace Umbraco.Web.WebApi { @@ -35,7 +37,7 @@ namespace Umbraco.Web.WebApi { } - protected UmbracoAuthorizedApiController(IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoMapper umbracoMapper, IPublishedUrlProvider publishedUrlProvider) + protected UmbracoAuthorizedApiController(IOptionsSnapshot globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoMapper umbracoMapper, IPublishedUrlProvider publishedUrlProvider) : base(globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoMapper, publishedUrlProvider) { } diff --git a/src/Umbraco.Web/WebAssets/CDF/ClientDependencyComponent.cs b/src/Umbraco.Web/WebAssets/CDF/ClientDependencyComponent.cs index 9a8da5a7eb..b38c775f67 100644 --- a/src/Umbraco.Web/WebAssets/CDF/ClientDependencyComponent.cs +++ b/src/Umbraco.Web/WebAssets/CDF/ClientDependencyComponent.cs @@ -16,16 +16,16 @@ namespace Umbraco.Web.WebAssets.CDF [ComposeAfter(typeof(WebInitialComponent))] public sealed class ClientDependencyComponent : IComponent { - private readonly IHostingSettings _hostingSettings; + private readonly HostingSettings _hostingSettings; private readonly IHostingEnvironment _hostingEnvironment; private readonly RuntimeSettings _runtimeSettings; public ClientDependencyComponent( - IHostingSettings hostingSettings, + IOptionsSnapshot hostingSettings, IHostingEnvironment hostingEnvironment, IOptionsSnapshot runtimeSettings) { - _hostingSettings = hostingSettings; + _hostingSettings = hostingSettings.Value; _hostingEnvironment = hostingEnvironment; _runtimeSettings = runtimeSettings.Value; } From 52a65caf885ed969246ffee043a026032e2a33e6 Mon Sep 17 00:00:00 2001 From: Andy Butland Date: Fri, 21 Aug 2020 15:27:06 +0100 Subject: [PATCH 243/826] Temporarily removed test and non netcore executable projects. --- .../AspNetCoreConfigsFactory.cs | 2 -- .../Umbraco.Configuration.csproj | 10 ++++++++++ .../Configuration/Models/ConnectionStrings.cs | 4 +--- src/Umbraco.Core/Routing/PublishedRequest.cs | 13 ++++++++++++- .../Install/InstallHelper.cs | 1 + .../InstallSteps/DatabaseConfigureStep.cs | 2 +- src/Umbraco.Infrastructure/Trees/TreeNode.cs | 7 ++++++- .../WebAssets/RuntimeMinifierExtensions.cs | 3 --- .../Security/BackOfficeSessionIdValidator.cs | 18 ++++++++---------- .../PreviewAuthenticationMiddleware.cs | 7 ++++--- .../Trees/ContentTreeController.cs | 9 +++++---- .../UmbracoCoreServiceCollectionExtensions.cs | 1 + 12 files changed, 49 insertions(+), 28 deletions(-) diff --git a/src/Umbraco.Configuration/AspNetCoreConfigsFactory.cs b/src/Umbraco.Configuration/AspNetCoreConfigsFactory.cs index ec87be7b3d..d8c36a0046 100644 --- a/src/Umbraco.Configuration/AspNetCoreConfigsFactory.cs +++ b/src/Umbraco.Configuration/AspNetCoreConfigsFactory.cs @@ -3,8 +3,6 @@ using Umbraco.Configuration.Models; using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.HealthChecks; using Umbraco.Core.Configuration.UmbracoSettings; -using ConnectionStrings = Umbraco.Configuration.Models.ConnectionStrings; -using CoreDebugSettings = Umbraco.Core.Configuration.Models.CoreDebugSettings; namespace Umbraco.Configuration { diff --git a/src/Umbraco.Configuration/Umbraco.Configuration.csproj b/src/Umbraco.Configuration/Umbraco.Configuration.csproj index a4dac22386..8d7a0e7f01 100644 --- a/src/Umbraco.Configuration/Umbraco.Configuration.csproj +++ b/src/Umbraco.Configuration/Umbraco.Configuration.csproj @@ -10,15 +10,25 @@ + + + + + + + + + + diff --git a/src/Umbraco.Core/Configuration/Models/ConnectionStrings.cs b/src/Umbraco.Core/Configuration/Models/ConnectionStrings.cs index 9d038ed17c..027adedd09 100644 --- a/src/Umbraco.Core/Configuration/Models/ConnectionStrings.cs +++ b/src/Umbraco.Core/Configuration/Models/ConnectionStrings.cs @@ -2,10 +2,8 @@ using System.Collections.Generic; using System.Data.Common; using System.Text.Json.Serialization; -using Umbraco.Core; -using Umbraco.Core.Configuration; -namespace Umbraco.Configuration.Models +namespace Umbraco.Core.Configuration.Models { public class ConnectionStrings { diff --git a/src/Umbraco.Core/Routing/PublishedRequest.cs b/src/Umbraco.Core/Routing/PublishedRequest.cs index 24bad199a5..7400623a6f 100644 --- a/src/Umbraco.Core/Routing/PublishedRequest.cs +++ b/src/Umbraco.Core/Routing/PublishedRequest.cs @@ -36,10 +36,21 @@ namespace Umbraco.Web.Routing /// The Umbraco context. /// The request Uri. public PublishedRequest(IPublishedRouter publishedRouter, IUmbracoContext umbracoContext, IOptionsSnapshot webRoutingSettings, Uri uri = null) + : this(publishedRouter, umbracoContext, webRoutingSettings.Value, uri) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The published router. + /// The Umbraco context. + /// The request Uri. + public PublishedRequest(IPublishedRouter publishedRouter, IUmbracoContext umbracoContext, WebRoutingSettings webRoutingSettings, Uri uri = null) { UmbracoContext = umbracoContext ?? throw new ArgumentNullException(nameof(umbracoContext)); _publishedRouter = publishedRouter ?? throw new ArgumentNullException(nameof(publishedRouter)); - _webRoutingSettings = webRoutingSettings.Value; + _webRoutingSettings = webRoutingSettings; Uri = uri ?? umbracoContext.CleanedUmbracoUrl; } diff --git a/src/Umbraco.Infrastructure/Install/InstallHelper.cs b/src/Umbraco.Infrastructure/Install/InstallHelper.cs index b9729f4e1b..a0460c93ba 100644 --- a/src/Umbraco.Infrastructure/Install/InstallHelper.cs +++ b/src/Umbraco.Infrastructure/Install/InstallHelper.cs @@ -14,6 +14,7 @@ using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Web.Install.Models; using Microsoft.Extensions.Options; +using Umbraco.Core.Configuration.Models; namespace Umbraco.Web.Install { diff --git a/src/Umbraco.Infrastructure/Install/InstallSteps/DatabaseConfigureStep.cs b/src/Umbraco.Infrastructure/Install/InstallSteps/DatabaseConfigureStep.cs index 0691f39e80..b86c1c2233 100644 --- a/src/Umbraco.Infrastructure/Install/InstallSteps/DatabaseConfigureStep.cs +++ b/src/Umbraco.Infrastructure/Install/InstallSteps/DatabaseConfigureStep.cs @@ -5,7 +5,7 @@ using Umbraco.Core; using Umbraco.Core.Logging; using Umbraco.Core.Migrations.Install; using Umbraco.Web.Install.Models; -using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Microsoft.Extensions.Options; namespace Umbraco.Web.Install.InstallSteps diff --git a/src/Umbraco.Infrastructure/Trees/TreeNode.cs b/src/Umbraco.Infrastructure/Trees/TreeNode.cs index 1b6945bcdd..585929c0e1 100644 --- a/src/Umbraco.Infrastructure/Trees/TreeNode.cs +++ b/src/Umbraco.Infrastructure/Trees/TreeNode.cs @@ -4,6 +4,7 @@ using System.Runtime.Serialization; using Umbraco.Composing; using Umbraco.Core; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Web.Models.ContentEditing; namespace Umbraco.Web.Models.Trees @@ -113,7 +114,11 @@ namespace Umbraco.Web.Models.Trees return Current.IOHelper.ResolveUrl("~" + Icon.TrimStart('~')); //legacy icon path - var backOfficePath = Current.Configs.Global().GetUmbracoMvcArea(Current.HostingEnvironment); + + // TODO: replace this when we have something other than Current.Configs available + //var backOfficePath = Current.Configs.Global().GetUmbracoMvcArea(Current.HostingEnvironment); + var backOfficePath = new GlobalSettings().GetUmbracoMvcArea(Current.HostingEnvironment); + return string.Format("{0}images/umbraco/{1}", backOfficePath.EnsureEndsWith("/"), Icon); } } diff --git a/src/Umbraco.Infrastructure/WebAssets/RuntimeMinifierExtensions.cs b/src/Umbraco.Infrastructure/WebAssets/RuntimeMinifierExtensions.cs index 929c7c9dd2..cc3be4d785 100644 --- a/src/Umbraco.Infrastructure/WebAssets/RuntimeMinifierExtensions.cs +++ b/src/Umbraco.Infrastructure/WebAssets/RuntimeMinifierExtensions.cs @@ -1,11 +1,8 @@ using System; -using System.Collections.Generic; using System.Text; using System.Threading.Tasks; -using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.Models; using Umbraco.Core.Hosting; -using Umbraco.Core.IO; using Umbraco.Core.WebAssets; namespace Umbraco.Web.WebAssets diff --git a/src/Umbraco.Web.BackOffice/Security/BackOfficeSessionIdValidator.cs b/src/Umbraco.Web.BackOffice/Security/BackOfficeSessionIdValidator.cs index fdf630e01c..2b70a1b083 100644 --- a/src/Umbraco.Web.BackOffice/Security/BackOfficeSessionIdValidator.cs +++ b/src/Umbraco.Web.BackOffice/Security/BackOfficeSessionIdValidator.cs @@ -1,16 +1,14 @@  +using System; +using System.Security.Claims; +using System.Threading.Tasks; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Http.Extensions; -using System; -using System.Collections.Generic; -using System.Security.Claims; -using System.Text; -using System.Threading.Tasks; +using Microsoft.Extensions.Options; using Umbraco.Core; using Umbraco.Core.BackOffice; -using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Hosting; using Umbraco.Extensions; @@ -37,14 +35,14 @@ namespace Umbraco.Web.BackOffice.Security { public const string CookieName = "UMB_UCONTEXT_C"; private readonly ISystemClock _systemClock; - private readonly IGlobalSettings _globalSettings; + private readonly GlobalSettings _globalSettings; private readonly IHostingEnvironment _hostingEnvironment; private readonly BackOfficeUserManager _userManager; - public BackOfficeSessionIdValidator(ISystemClock systemClock, IGlobalSettings globalSettings, IHostingEnvironment hostingEnvironment, BackOfficeUserManager userManager) + public BackOfficeSessionIdValidator(ISystemClock systemClock, IOptionsSnapshot globalSettings, IHostingEnvironment hostingEnvironment, BackOfficeUserManager userManager) { _systemClock = systemClock; - _globalSettings = globalSettings; + _globalSettings = globalSettings.Value; _hostingEnvironment = hostingEnvironment; _userManager = userManager; } diff --git a/src/Umbraco.Web.BackOffice/Security/PreviewAuthenticationMiddleware.cs b/src/Umbraco.Web.BackOffice/Security/PreviewAuthenticationMiddleware.cs index ff182b9f7b..f48996332c 100644 --- a/src/Umbraco.Web.BackOffice/Security/PreviewAuthenticationMiddleware.cs +++ b/src/Umbraco.Web.BackOffice/Security/PreviewAuthenticationMiddleware.cs @@ -6,6 +6,7 @@ using System; using System.Threading.Tasks; using Umbraco.Core; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Hosting; using Umbraco.Extensions; @@ -16,14 +17,14 @@ namespace Umbraco.Web.BackOffice.Security /// public class PreviewAuthenticationMiddleware : IMiddleware { - private readonly IGlobalSettings _globalSettings; + private readonly GlobalSettings _globalSettings; private readonly IHostingEnvironment _hostingEnvironment; public PreviewAuthenticationMiddleware( - IGlobalSettings globalSettings, + IOptionsSnapshot globalSettings, IHostingEnvironment hostingEnvironment) { - _globalSettings = globalSettings; + _globalSettings = globalSettings.Value; _hostingEnvironment = hostingEnvironment; } diff --git a/src/Umbraco.Web.BackOffice/Trees/ContentTreeController.cs b/src/Umbraco.Web.BackOffice/Trees/ContentTreeController.cs index 0cc73af315..2f72e1f829 100644 --- a/src/Umbraco.Web.BackOffice/Trees/ContentTreeController.cs +++ b/src/Umbraco.Web.BackOffice/Trees/ContentTreeController.cs @@ -20,6 +20,8 @@ using Umbraco.Web.Common.Attributes; using Umbraco.Web.Common.Exceptions; using Umbraco.Web.Security; using Umbraco.Web.WebApi; +using Umbraco.Core.Configuration.Models; +using Microsoft.Extensions.Options; namespace Umbraco.Web.Trees { @@ -40,7 +42,7 @@ namespace Umbraco.Web.Trees { private readonly UmbracoTreeSearcher _treeSearcher; private readonly ActionCollection _actions; - private readonly IGlobalSettings _globalSettings; + private readonly GlobalSettings _globalSettings; private readonly IMenuItemCollectionFactory _menuItemCollectionFactory; private readonly IWebSecurity _webSecurity; private readonly IContentService _contentService; @@ -49,7 +51,6 @@ namespace Umbraco.Web.Trees private readonly IUserService _userService; private readonly ILocalizationService _localizationService; - public ContentTreeController( ILocalizedTextService localizedTextService, UmbracoApiControllerTypeCollection umbracoApiControllerTypeCollection, @@ -62,7 +63,7 @@ namespace Umbraco.Web.Trees IDataTypeService dataTypeService, UmbracoTreeSearcher treeSearcher, ActionCollection actions, - IGlobalSettings globalSettings, + IOptionsSnapshot globalSettings, IContentService contentService, IPublicAccessService publicAccessService, ILocalizationService localizationService) @@ -70,7 +71,7 @@ namespace Umbraco.Web.Trees { _treeSearcher = treeSearcher; _actions = actions; - _globalSettings = globalSettings; + _globalSettings = globalSettings.Value; _menuItemCollectionFactory = menuItemCollectionFactory; _webSecurity = webSecurity; _contentService = contentService; diff --git a/src/Umbraco.Web.Common/Extensions/UmbracoCoreServiceCollectionExtensions.cs b/src/Umbraco.Web.Common/Extensions/UmbracoCoreServiceCollectionExtensions.cs index cbdbeac873..1c7f8156f4 100644 --- a/src/Umbraco.Web.Common/Extensions/UmbracoCoreServiceCollectionExtensions.cs +++ b/src/Umbraco.Web.Common/Extensions/UmbracoCoreServiceCollectionExtensions.cs @@ -14,6 +14,7 @@ using Serilog; using Serilog.Extensions.Hosting; using Serilog.Extensions.Logging; using Umbraco.Configuration; +using Umbraco.Configuration.Models; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Composing; From 89b725ef28b5c6b4078f1f56646ad6748fff94c2 Mon Sep 17 00:00:00 2001 From: Andy Butland Date: Sun, 23 Aug 2020 13:55:36 +0200 Subject: [PATCH 244/826] Reverted non netcore related project amends in order to limit changes to those necessary for the netcore executable call stack. --- .../AspNetCoreConfigsFactory.cs | 38 +++--- .../Models/ActiveDirectorySettings.cs | 19 +++ .../Models/ConnectionStrings.cs | 69 ++++++++++ .../Models/ContentSettings.cs | 119 ++++++++++++++++++ .../Models/CoreDebugSettings.cs | 23 ++++ .../Models/ExceptionFilterSettings.cs | 19 +++ .../Models/GlobalSettings.cs | 101 +++++++++++++++ .../Models/HostingSettings.cs | 29 +++++ .../Models/ImagingSettings.cs | 26 ++++ .../Models/IndexCreatorSettings.cs | 20 +++ .../Models/KeepAliveSettings.cs | 23 ++++ .../Models/LoggingSettings.cs | 19 +++ .../MemberPasswordConfigurationSettings.cs | 38 ++++++ .../Models/ModelsBuilderConfig.cs | 86 +++++++++++++ .../Models/NuCacheSettings.cs | 19 +++ .../Models/RuntimeSettings.cs | 19 +++ .../Models/SecuritySettings.cs | 33 +++++ .../Models/TourSettings.cs | 21 ++++ .../Models/TypeFinderSettings.cs | 20 +++ .../UserPasswordConfigurationSettings.cs | 36 ++++++ .../Models/WebRoutingSettings.cs | 42 +++++++ .../BackOffice/ContentTypeModelValidator.cs | 5 +- .../ContentTypeModelValidatorBase.cs | 9 +- .../BackOffice/DashboardReport.cs | 5 +- .../BackOffice/MediaTypeModelValidator.cs | 5 +- .../ModelsBuilderDashboardController.cs | 10 +- .../Building/Builder.cs | 3 +- .../Building/ModelsGenerator.cs | 5 +- .../Building/TextBuilder.cs | 4 +- .../Compose/ModelsBuilderComponent.cs | 8 +- .../LiveModelsProvider.cs | 5 +- .../ModelsGenerationError.cs | 5 +- .../OutOfDateModelsStatus.cs | 5 +- .../PureLiveModelFactory.cs | 6 +- src/Umbraco.Tests.Common/SettingsForTests.cs | 38 +++--- src/Umbraco.Tests.Common/TestHelperBase.cs | 5 +- .../Implementations/TestHostingEnvironment.cs | 6 +- .../BackOfficeCookieManagerTests.cs | 10 +- .../Components/ComponentTests.cs | 3 +- src/Umbraco.Tests/Models/MediaXmlTest.cs | 3 +- .../Routing/MediaUrlProviderTests.cs | 7 +- .../BackOfficeOwinUserManagerTests.cs | 10 +- .../TestHelpers/SettingsForTests.cs | 5 +- src/Umbraco.Tests/TestHelpers/TestHelper.cs | 5 +- .../TestHelpers/TestObjects-Mocks.cs | 4 +- src/Umbraco.Tests/TestHelpers/TestObjects.cs | 3 +- src/Umbraco.Web/AppBuilderExtensions.cs | 3 +- .../AspNet/AspNetBackOfficeInfo.cs | 13 +- .../AspNet/AspNetHostingEnvironment.cs | 12 +- .../AspNet/AspNetRequestAccessor.cs | 10 +- .../Compose/AuditEventsComponent.cs | 10 +- .../BackOfficeUserAuditEventsComponent.cs | 8 +- .../Editors/AuthenticationController.cs | 39 +++--- .../Editors/BackOfficeController.cs | 25 ++-- .../Editors/BackOfficeServerVariables.cs | 32 ++--- .../UmbracoAuthorizedJsonController.cs | 4 +- src/Umbraco.Web/HtmlHelperRenderExtensions.cs | 7 +- .../Mvc/AreaRegistrationExtensions.cs | 6 +- src/Umbraco.Web/Mvc/BackOfficeArea.cs | 13 +- src/Umbraco.Web/Mvc/PluginControllerArea.cs | 13 +- src/Umbraco.Web/Mvc/RenderMvcController.cs | 6 +- .../Mvc/RenderNoContentController.cs | 8 +- .../Mvc/UmbracoAuthorizedController.cs | 6 +- src/Umbraco.Web/Mvc/UmbracoController.cs | 19 ++- .../Mvc/UmbracoViewPageOfTModel.cs | 16 ++- src/Umbraco.Web/RoutableDocumentFilter.cs | 27 ++-- .../Runtime/WebInitialComponent.cs | 12 +- .../Security/AppBuilderExtensions.cs | 5 +- .../BackOfficeCookieAuthenticationProvider.cs | 32 ++--- .../Security/BackOfficeOwinUserManager.cs | 13 +- .../Security/BackOfficeSignInManager.cs | 18 +-- .../Security/GetUserSecondsMiddleWare.cs | 21 ++-- src/Umbraco.Web/UmbracoApplicationBase.cs | 5 +- src/Umbraco.Web/UmbracoContext.cs | 5 +- src/Umbraco.Web/UmbracoContextFactory.cs | 8 +- src/Umbraco.Web/UmbracoDefaultOwinStartup.cs | 8 +- .../WebApi/UmbracoApiController.cs | 4 +- .../WebApi/UmbracoApiControllerBase.cs | 15 +-- .../WebApi/UmbracoAuthorizedApiController.cs | 4 +- .../CDF/ClientDependencyComponent.cs | 18 ++- 80 files changed, 1073 insertions(+), 365 deletions(-) create mode 100644 src/Umbraco.Configuration/Models/ActiveDirectorySettings.cs create mode 100644 src/Umbraco.Configuration/Models/ConnectionStrings.cs create mode 100644 src/Umbraco.Configuration/Models/ContentSettings.cs create mode 100644 src/Umbraco.Configuration/Models/CoreDebugSettings.cs create mode 100644 src/Umbraco.Configuration/Models/ExceptionFilterSettings.cs create mode 100644 src/Umbraco.Configuration/Models/GlobalSettings.cs create mode 100644 src/Umbraco.Configuration/Models/HostingSettings.cs create mode 100644 src/Umbraco.Configuration/Models/ImagingSettings.cs create mode 100644 src/Umbraco.Configuration/Models/IndexCreatorSettings.cs create mode 100644 src/Umbraco.Configuration/Models/KeepAliveSettings.cs create mode 100644 src/Umbraco.Configuration/Models/LoggingSettings.cs create mode 100644 src/Umbraco.Configuration/Models/MemberPasswordConfigurationSettings.cs create mode 100644 src/Umbraco.Configuration/Models/ModelsBuilderConfig.cs create mode 100644 src/Umbraco.Configuration/Models/NuCacheSettings.cs create mode 100644 src/Umbraco.Configuration/Models/RuntimeSettings.cs create mode 100644 src/Umbraco.Configuration/Models/SecuritySettings.cs create mode 100644 src/Umbraco.Configuration/Models/TourSettings.cs create mode 100644 src/Umbraco.Configuration/Models/TypeFinderSettings.cs create mode 100644 src/Umbraco.Configuration/Models/UserPasswordConfigurationSettings.cs create mode 100644 src/Umbraco.Configuration/Models/WebRoutingSettings.cs diff --git a/src/Umbraco.Configuration/AspNetCoreConfigsFactory.cs b/src/Umbraco.Configuration/AspNetCoreConfigsFactory.cs index d8c36a0046..d8b5e666b9 100644 --- a/src/Umbraco.Configuration/AspNetCoreConfigsFactory.cs +++ b/src/Umbraco.Configuration/AspNetCoreConfigsFactory.cs @@ -19,27 +19,27 @@ namespace Umbraco.Configuration { var configs = new Configs(); - //configs.Add(() => new TourSettings(_configuration)); - //configs.Add(() => new CoreDebugSettings(_configuration)); + configs.Add(() => new TourSettings(_configuration)); + configs.Add(() => new CoreDebugSettings(_configuration)); configs.Add(() => new RequestHandlerSettings(_configuration)); - //configs.Add(() => new SecuritySettings(_configuration)); - //configs.Add(() => new UserPasswordConfigurationSettings(_configuration)); - //configs.Add(() => new MemberPasswordConfigurationSettings(_configuration)); - //configs.Add(() => new KeepAliveSettings(_configuration)); - //configs.Add(() => new ContentSettings(_configuration)); + configs.Add(() => new SecuritySettings(_configuration)); + configs.Add(() => new UserPasswordConfigurationSettings(_configuration)); + configs.Add(() => new MemberPasswordConfigurationSettings(_configuration)); + configs.Add(() => new KeepAliveSettings(_configuration)); + configs.Add(() => new ContentSettings(_configuration)); configs.Add(() => new HealthChecksSettings(_configuration)); - //configs.Add(() => new LoggingSettings(_configuration)); - //configs.Add(() => new ExceptionFilterSettings(_configuration)); - //configs.Add(() => new ActiveDirectorySettings(_configuration)); - //configs.Add(() => new RuntimeSettings(_configuration)); - //configs.Add(() => new TypeFinderSettings(_configuration)); - //configs.Add(() => new NuCacheSettings(_configuration)); - //configs.Add(() => new WebRoutingSettings(_configuration)); - //configs.Add(() => new IndexCreatorSettings(_configuration)); - //configs.Add(() => new ModelsBuilderConfig(_configuration)); - //configs.Add(() => new HostingSettings(_configuration)); - //configs.Add(() => new GlobalSettings(_configuration)); - //configs.Add(() => new ImagingSettings(_configuration)); + configs.Add(() => new LoggingSettings(_configuration)); + configs.Add(() => new ExceptionFilterSettings(_configuration)); + configs.Add(() => new ActiveDirectorySettings(_configuration)); + configs.Add(() => new RuntimeSettings(_configuration)); + configs.Add(() => new TypeFinderSettings(_configuration)); + configs.Add(() => new NuCacheSettings(_configuration)); + configs.Add(() => new WebRoutingSettings(_configuration)); + configs.Add(() => new IndexCreatorSettings(_configuration)); + configs.Add(() => new ModelsBuilderConfig(_configuration)); + configs.Add(() => new HostingSettings(_configuration)); + configs.Add(() => new GlobalSettings(_configuration)); + configs.Add(() => new ImagingSettings(_configuration)); return configs; } diff --git a/src/Umbraco.Configuration/Models/ActiveDirectorySettings.cs b/src/Umbraco.Configuration/Models/ActiveDirectorySettings.cs new file mode 100644 index 0000000000..015fb17a8e --- /dev/null +++ b/src/Umbraco.Configuration/Models/ActiveDirectorySettings.cs @@ -0,0 +1,19 @@ +using Microsoft.Extensions.Configuration; +using Umbraco.Core; +using Umbraco.Core.Configuration; + +namespace Umbraco.Configuration.Models +{ + internal class ActiveDirectorySettings : IActiveDirectorySettings + { + private const string Prefix = Constants.Configuration.ConfigPrefix + "ActiveDirectory:"; + private readonly IConfiguration _configuration; + + public ActiveDirectorySettings(IConfiguration configuration) + { + _configuration = configuration; + } + + public string ActiveDirectoryDomain => _configuration.GetValue(Prefix+"Domain"); + } +} diff --git a/src/Umbraco.Configuration/Models/ConnectionStrings.cs b/src/Umbraco.Configuration/Models/ConnectionStrings.cs new file mode 100644 index 0000000000..586765714c --- /dev/null +++ b/src/Umbraco.Configuration/Models/ConnectionStrings.cs @@ -0,0 +1,69 @@ +using System; +using System.Data.Common; +using Microsoft.Extensions.Configuration; +using Umbraco.Core; +using Umbraco.Core.Configuration; + +namespace Umbraco.Configuration.Models +{ + public class ConnectionStrings : IConnectionStrings + { + private readonly IConfiguration _configuration; + + public ConnectionStrings(IConfiguration configuration) + { + _configuration = configuration; + } + + public ConfigConnectionString this[string key] + { + get + { + var connectionString = _configuration.GetConnectionString(key); + var provider = ParseProvider(connectionString); + return new ConfigConnectionString(connectionString, provider, key); + } + set => throw new NotImplementedException(); + } + + private string ParseProvider(string connectionString) + { + if (string.IsNullOrEmpty(connectionString)) + { + return null; + } + + var builder = new DbConnectionStringBuilder(); + + builder.ConnectionString = connectionString; + + if (builder.TryGetValue("Data Source", out var ds) && ds is string dataSource) + { + if (dataSource.EndsWith(".sdf")) + { + return Constants.DbProviderNames.SqlCe; + } + } + + if (builder.TryGetValue("Server", out var s) && s is string server && !string.IsNullOrEmpty(server)) + { + if (builder.TryGetValue("Database", out var db) && db is string database && !string.IsNullOrEmpty(database)) + { + return Constants.DbProviderNames.SqlServer; + } + + if (builder.TryGetValue("AttachDbFileName", out var a) && a is string attachDbFileName && !string.IsNullOrEmpty(attachDbFileName)) + { + return Constants.DbProviderNames.SqlServer; + } + + if (builder.TryGetValue("Initial Catalog", out var i) && i is string initialCatalog && !string.IsNullOrEmpty(initialCatalog)) + { + return Constants.DbProviderNames.SqlServer; + } + } + + throw new ArgumentException("Cannot determine provider name from connection string", nameof(connectionString)); + } + } +} diff --git a/src/Umbraco.Configuration/Models/ContentSettings.cs b/src/Umbraco.Configuration/Models/ContentSettings.cs new file mode 100644 index 0000000000..6c9b986dd1 --- /dev/null +++ b/src/Umbraco.Configuration/Models/ContentSettings.cs @@ -0,0 +1,119 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.Extensions.Configuration; +using Umbraco.Core; +using Umbraco.Core.Configuration.UmbracoSettings; +using Umbraco.Core.Macros; + +namespace Umbraco.Configuration.Models +{ + internal class ContentSettings : IContentSettings + { + private const string Prefix = Constants.Configuration.ConfigPrefix + "Content:"; + private const string NotificationsPrefix = Prefix + "Notifications:"; + private const string ImagingPrefix = Prefix + "Imaging:"; + private const string DefaultPreviewBadge = + @"
Preview modeClick to end
"; + + private static readonly ImagingAutoFillUploadField[] DefaultImagingAutoFillUploadField = + { + new ImagingAutoFillUploadField + { + Alias = Constants.Conventions.Media.File, + WidthFieldAlias = Constants.Conventions.Media.Width, + HeightFieldAlias =Constants.Conventions.Media.Height, + ExtensionFieldAlias =Constants.Conventions.Media.Extension, + LengthFieldAlias =Constants.Conventions.Media.Bytes, + } + }; + + private readonly IConfiguration _configuration; + + public ContentSettings(IConfiguration configuration) + { + _configuration = configuration; + } + + public string NotificationEmailAddress => + _configuration.GetValue(NotificationsPrefix+"Email"); + + public bool DisableHtmlEmail => + _configuration.GetValue(NotificationsPrefix+"DisableHtmlEmail", false); + + public IEnumerable ImageFileTypes => _configuration.GetValue( + ImagingPrefix+"ImageFileTypes", new[] { "jpeg", "jpg", "gif", "bmp", "png", "tiff", "tif" }); + + public IEnumerable ImageAutoFillProperties => + _configuration.GetValue(ImagingPrefix+"AutoFillImageProperties", + DefaultImagingAutoFillUploadField); + + + public bool ResolveUrlsFromTextString => + _configuration.GetValue(Prefix+"ResolveUrlsFromTextString", false); + + public IEnumerable Error404Collection => _configuration + .GetSection(Prefix+"Errors:Error404") + .GetChildren() + .Select(x => new ContentErrorPage(x)); + + public string PreviewBadge => _configuration.GetValue(Prefix+"PreviewBadge", DefaultPreviewBadge); + + public MacroErrorBehaviour MacroErrorBehaviour => + _configuration.GetValue(Prefix+"MacroErrors", MacroErrorBehaviour.Inline); + + public IEnumerable DisallowedUploadFiles => _configuration.GetValue( + Prefix+"DisallowedUploadFiles", + new[] { "ashx", "aspx", "ascx", "config", "cshtml", "vbhtml", "asmx", "air", "axd" }); + + public IEnumerable AllowedUploadFiles => + _configuration.GetValue(Prefix+"AllowedUploadFiles", Array.Empty()); + + public bool ShowDeprecatedPropertyEditors => + _configuration.GetValue(Prefix+"ShowDeprecatedPropertyEditors", false); + + public string LoginBackgroundImage => + _configuration.GetValue(Prefix+"LoginBackgroundImage", "assets/img/login.jpg"); + + private class ContentErrorPage : IContentErrorPage + { + public ContentErrorPage(IConfigurationSection configurationSection) + { + Culture = configurationSection.Key; + + var value = configurationSection.Value; + + if (int.TryParse(value, out var contentId)) + { + HasContentId = true; + ContentId = contentId; + } + else if (Guid.TryParse(value, out var contentKey)) + { + HasContentKey = true; + ContentKey = contentKey; + } + else + { + ContentXPath = value; + } + } + + public int ContentId { get; } + public Guid ContentKey { get; } + public string ContentXPath { get; } + public bool HasContentId { get; } + public bool HasContentKey { get; } + public string Culture { get; set; } + } + + private class ImagingAutoFillUploadField : IImagingAutoFillUploadField + { + public string Alias { get; set; } + public string WidthFieldAlias { get; set; } + public string HeightFieldAlias { get; set; } + public string LengthFieldAlias { get; set; } + public string ExtensionFieldAlias { get; set; } + } + } +} diff --git a/src/Umbraco.Configuration/Models/CoreDebugSettings.cs b/src/Umbraco.Configuration/Models/CoreDebugSettings.cs new file mode 100644 index 0000000000..6d6c0eaf0d --- /dev/null +++ b/src/Umbraco.Configuration/Models/CoreDebugSettings.cs @@ -0,0 +1,23 @@ +using Microsoft.Extensions.Configuration; +using Umbraco.Core; +using Umbraco.Core.Configuration; + +namespace Umbraco.Configuration.Models +{ + internal class CoreDebugSettings : ICoreDebugSettings + { + private const string Prefix = Constants.Configuration.ConfigPrefix + "Core:Debug:"; + private readonly IConfiguration _configuration; + + public CoreDebugSettings(IConfiguration configuration) + { + _configuration = configuration; + } + + public bool LogUncompletedScopes => + _configuration.GetValue(Prefix+"LogUncompletedScopes", false); + + public bool DumpOnTimeoutThreadAbort => + _configuration.GetValue(Prefix+"DumpOnTimeoutThreadAbort", false); + } +} diff --git a/src/Umbraco.Configuration/Models/ExceptionFilterSettings.cs b/src/Umbraco.Configuration/Models/ExceptionFilterSettings.cs new file mode 100644 index 0000000000..581daf9f40 --- /dev/null +++ b/src/Umbraco.Configuration/Models/ExceptionFilterSettings.cs @@ -0,0 +1,19 @@ +using Microsoft.Extensions.Configuration; +using Umbraco.Core; +using Umbraco.Core.Configuration; + +namespace Umbraco.Configuration.Models +{ + internal class ExceptionFilterSettings : IExceptionFilterSettings + { + private const string Prefix = Constants.Configuration.ConfigPrefix + "ExceptionFilter:"; + private readonly IConfiguration _configuration; + + public ExceptionFilterSettings(IConfiguration configuration) + { + _configuration = configuration; + } + + public bool Disabled => _configuration.GetValue(Prefix+"Disabled", false); + } +} diff --git a/src/Umbraco.Configuration/Models/GlobalSettings.cs b/src/Umbraco.Configuration/Models/GlobalSettings.cs new file mode 100644 index 0000000000..908ba71590 --- /dev/null +++ b/src/Umbraco.Configuration/Models/GlobalSettings.cs @@ -0,0 +1,101 @@ +using System; +using System.Linq; +using System.Net.Mail; +using Microsoft.Extensions.Configuration; +using Umbraco.Core; +using Umbraco.Core.Configuration; + +namespace Umbraco.Configuration.Models +{ + /// + /// The GlobalSettings Class contains general settings information for the entire Umbraco instance based on information + /// from web.config appsettings + /// + internal class GlobalSettings : IGlobalSettings + { + private const string Prefix = Constants.Configuration.ConfigGlobalPrefix; + + internal const string + StaticReservedPaths = "~/app_plugins/,~/install/,~/mini-profiler-resources/,"; //must end with a comma! + + internal const string + StaticReservedUrls = "~/config/splashes/noNodes.aspx,~/.well-known,"; //must end with a comma! + + private readonly IConfiguration _configuration; + + public GlobalSettings(IConfiguration configuration) + { + _configuration = configuration; + } + + public string ReservedUrls => _configuration.GetValue(Prefix + "ReservedUrls", StaticReservedUrls); + public string ReservedPaths => _configuration.GetValue(Prefix + "ReservedPaths", StaticReservedPaths); + + // TODO: https://github.com/umbraco/Umbraco-CMS/issues/4238 - stop having version in web.config appSettings + public string ConfigurationStatus + { + get => _configuration.GetValue(Prefix + "ConfigurationStatus"); + set => throw new NotImplementedException("We should remove this and only use the value from database"); + } + + public int TimeOutInMinutes => _configuration.GetValue(Prefix + "TimeOutInMinutes", 20); + public string DefaultUILanguage => _configuration.GetValue(Prefix + "DefaultUILanguage", "en-US"); + + public bool HideTopLevelNodeFromPath => + _configuration.GetValue(Prefix + "HideTopLevelNodeFromPath", false); + + public bool UseHttps => _configuration.GetValue(Prefix + "UseHttps", false); + public int VersionCheckPeriod => _configuration.GetValue(Prefix + "VersionCheckPeriod", 7); + public string UmbracoPath => _configuration.GetValue(Prefix + "UmbracoPath", "~/umbraco"); + public string UmbracoCssPath => _configuration.GetValue(Prefix + "UmbracoCssPath", "~/css"); + + public string UmbracoScriptsPath => + _configuration.GetValue(Prefix + "UmbracoScriptsPath", "~/scripts"); + + public string UmbracoMediaPath => _configuration.GetValue(Prefix + "UmbracoMediaPath", "~/media"); + + public bool InstallMissingDatabase => + _configuration.GetValue(Prefix + "InstallMissingDatabase", false); + + public bool InstallEmptyDatabase => _configuration.GetValue(Prefix + "InstallEmptyDatabase", false); + + public bool DisableElectionForSingleServer => + _configuration.GetValue(Prefix + "DisableElectionForSingleServer", false); + + public string RegisterType => _configuration.GetValue(Prefix + "RegisterType", string.Empty); + + public string DatabaseFactoryServerVersion => + _configuration.GetValue(Prefix + "DatabaseFactoryServerVersion", string.Empty); + + public string MainDomLock => _configuration.GetValue(Prefix + "MainDomLock", string.Empty); + + public string NoNodesViewPath => + _configuration.GetValue(Prefix + "NoNodesViewPath", "~/config/splashes/NoNodes.cshtml"); + + public bool IsSmtpServerConfigured => + _configuration.GetSection(Constants.Configuration.ConfigGlobalPrefix + "Smtp")?.GetChildren().Any() ?? false; + + public ISmtpSettings SmtpSettings => + new SmtpSettingsImpl(_configuration.GetSection(Constants.Configuration.ConfigGlobalPrefix + "Smtp")); + + private class SmtpSettingsImpl : ISmtpSettings + { + private readonly IConfigurationSection _configurationSection; + + public SmtpSettingsImpl(IConfigurationSection configurationSection) + { + _configurationSection = configurationSection; + } + + public string From => _configurationSection.GetValue("From"); + public string Host => _configurationSection.GetValue("Host"); + public int Port => _configurationSection.GetValue("Port"); + public string PickupDirectoryLocation => _configurationSection.GetValue("PickupDirectoryLocation"); + public SmtpDeliveryMethod DeliveryMethod => _configurationSection.GetValue("DeliveryMethod"); + + public string Username => _configurationSection.GetValue("Username"); + + public string Password => _configurationSection.GetValue("Password"); + } + } +} diff --git a/src/Umbraco.Configuration/Models/HostingSettings.cs b/src/Umbraco.Configuration/Models/HostingSettings.cs new file mode 100644 index 0000000000..f0fbcf4cab --- /dev/null +++ b/src/Umbraco.Configuration/Models/HostingSettings.cs @@ -0,0 +1,29 @@ +using Microsoft.Extensions.Configuration; +using Umbraco.Core; +using Umbraco.Core.Configuration; + +namespace Umbraco.Configuration.Models +{ + internal class HostingSettings : IHostingSettings + { + private const string Prefix = Constants.Configuration.ConfigPrefix + "Hosting:"; + private readonly IConfiguration _configuration; + + public HostingSettings(IConfiguration configuration) + { + _configuration = configuration; + } + + /// + public LocalTempStorage LocalTempStorageLocation => + _configuration.GetValue(Prefix+"LocalTempStorage", LocalTempStorage.Default); + + public string ApplicationVirtualPath => null; + + /// + /// Gets a value indicating whether umbraco is running in [debug mode]. + /// + /// true if [debug mode]; otherwise, false. + public bool DebugMode => _configuration.GetValue(Prefix+"Debug", false); + } +} diff --git a/src/Umbraco.Configuration/Models/ImagingSettings.cs b/src/Umbraco.Configuration/Models/ImagingSettings.cs new file mode 100644 index 0000000000..4a9501b2ba --- /dev/null +++ b/src/Umbraco.Configuration/Models/ImagingSettings.cs @@ -0,0 +1,26 @@ +using Microsoft.Extensions.Configuration; +using Umbraco.Core; +using Umbraco.Core.Configuration; + +namespace Umbraco.Configuration.Models +{ + internal class ImagingSettings : IImagingSettings + { + private const string Prefix = Constants.Configuration.ConfigPrefix + "Imaging:"; + private const string CachePrefix = Prefix + "Cache:"; + private const string ResizePrefix = Prefix + "Resize:"; + private readonly IConfiguration _configuration; + + public ImagingSettings(IConfiguration configuration) + { + _configuration = configuration; + } + + public int MaxBrowserCacheDays => _configuration.GetValue(CachePrefix + "MaxBrowserCacheDays", 7); + public int MaxCacheDays => _configuration.GetValue(CachePrefix + "MaxCacheDays", 365); + public uint CachedNameLength => _configuration.GetValue(CachePrefix + "CachedNameLength", (uint) 8); + public string CacheFolder => _configuration.GetValue(CachePrefix + "Folder", "../App_Data/Cache"); + public int MaxResizeWidth => _configuration.GetValue(ResizePrefix + "MaxWidth", 5000); + public int MaxResizeHeight => _configuration.GetValue(ResizePrefix + "MaxHeight", 5000); + } +} diff --git a/src/Umbraco.Configuration/Models/IndexCreatorSettings.cs b/src/Umbraco.Configuration/Models/IndexCreatorSettings.cs new file mode 100644 index 0000000000..b4bb000552 --- /dev/null +++ b/src/Umbraco.Configuration/Models/IndexCreatorSettings.cs @@ -0,0 +1,20 @@ +using Microsoft.Extensions.Configuration; +using Umbraco.Core; +using Umbraco.Core.Configuration; + +namespace Umbraco.Configuration.Models +{ + internal class IndexCreatorSettings : IIndexCreatorSettings + { + private const string Prefix = Constants.Configuration.ConfigPrefix + "Examine:"; + private readonly IConfiguration _configuration; + + public IndexCreatorSettings(IConfiguration configuration) + { + _configuration = configuration; + } + + public string LuceneDirectoryFactory => + _configuration.GetValue(Prefix + "LuceneDirectoryFactory"); + } +} diff --git a/src/Umbraco.Configuration/Models/KeepAliveSettings.cs b/src/Umbraco.Configuration/Models/KeepAliveSettings.cs new file mode 100644 index 0000000000..04194e1a3c --- /dev/null +++ b/src/Umbraco.Configuration/Models/KeepAliveSettings.cs @@ -0,0 +1,23 @@ +using Microsoft.Extensions.Configuration; +using Umbraco.Core; +using Umbraco.Core.Configuration.UmbracoSettings; + +namespace Umbraco.Configuration.Models +{ + internal class KeepAliveSettings : IKeepAliveSettings + { + private const string Prefix = Constants.Configuration.ConfigPrefix + "KeepAlive:"; + private readonly IConfiguration _configuration; + + public KeepAliveSettings(IConfiguration configuration) + { + _configuration = configuration; + } + + public bool DisableKeepAliveTask => + _configuration.GetValue(Prefix + "DisableKeepAliveTask", false); + + public string KeepAlivePingUrl => _configuration.GetValue(Prefix + "KeepAlivePingUrl", + "{umbracoApplicationUrl}/api/keepalive/ping"); + } +} diff --git a/src/Umbraco.Configuration/Models/LoggingSettings.cs b/src/Umbraco.Configuration/Models/LoggingSettings.cs new file mode 100644 index 0000000000..b05fe03875 --- /dev/null +++ b/src/Umbraco.Configuration/Models/LoggingSettings.cs @@ -0,0 +1,19 @@ +using Microsoft.Extensions.Configuration; +using Umbraco.Core; +using Umbraco.Core.Configuration.UmbracoSettings; + +namespace Umbraco.Configuration.Models +{ + internal class LoggingSettings : ILoggingSettings + { + private const string Prefix = Constants.Configuration.ConfigPrefix + "Logging:"; + private readonly IConfiguration _configuration; + + public LoggingSettings(IConfiguration configuration) + { + _configuration = configuration; + } + + public int MaxLogAge => _configuration.GetValue(Prefix + "MaxLogAge", -1); + } +} diff --git a/src/Umbraco.Configuration/Models/MemberPasswordConfigurationSettings.cs b/src/Umbraco.Configuration/Models/MemberPasswordConfigurationSettings.cs new file mode 100644 index 0000000000..5a8313a351 --- /dev/null +++ b/src/Umbraco.Configuration/Models/MemberPasswordConfigurationSettings.cs @@ -0,0 +1,38 @@ +using Microsoft.Extensions.Configuration; +using Umbraco.Core; +using Umbraco.Core.Configuration; + +namespace Umbraco.Configuration.Models +{ + internal class MemberPasswordConfigurationSettings : IMemberPasswordConfiguration + { + private const string Prefix = Constants.Configuration.ConfigSecurityPrefix + "MemberPassword:"; + private readonly IConfiguration _configuration; + + public MemberPasswordConfigurationSettings(IConfiguration configuration) + { + _configuration = configuration; + } + + public int RequiredLength => + _configuration.GetValue(Prefix + "RequiredLength", 10); + + public bool RequireNonLetterOrDigit => + _configuration.GetValue(Prefix + "RequireNonLetterOrDigit", false); + + public bool RequireDigit => + _configuration.GetValue(Prefix + "RequireDigit", false); + + public bool RequireLowercase => + _configuration.GetValue(Prefix + "RequireLowercase", false); + + public bool RequireUppercase => + _configuration.GetValue(Prefix + "RequireUppercase", false); + + public string HashAlgorithmType => + _configuration.GetValue(Prefix + "HashAlgorithmType", Constants.Security.AspNetUmbraco8PasswordHashAlgorithmName); // TODO: Need to change to current format when we do members + + public int MaxFailedAccessAttemptsBeforeLockout => + _configuration.GetValue(Prefix + "MaxFailedAccessAttemptsBeforeLockout", 5); + } +} diff --git a/src/Umbraco.Configuration/Models/ModelsBuilderConfig.cs b/src/Umbraco.Configuration/Models/ModelsBuilderConfig.cs new file mode 100644 index 0000000000..d111dbba70 --- /dev/null +++ b/src/Umbraco.Configuration/Models/ModelsBuilderConfig.cs @@ -0,0 +1,86 @@ +using Microsoft.Extensions.Configuration; +using Umbraco.Core; +using Umbraco.Core.Configuration; + +namespace Umbraco.Configuration.Models +{ + /// + /// Represents the models builder configuration. + /// + internal class ModelsBuilderConfig : IModelsBuilderConfig + { + private const string Prefix = Constants.Configuration.ConfigModelsBuilderPrefix; + private readonly IConfiguration _configuration; + + /// + /// Initializes a new instance of the class. + /// + public ModelsBuilderConfig(IConfiguration configuration) + { + _configuration = configuration; + } + + public string DefaultModelsDirectory => "~/App_Data/Models"; + + /// + /// Gets a value indicating whether the whole models experience is enabled. + /// + /// + /// If this is false then absolutely nothing happens. + /// Default value is false which means that unless we have this setting, nothing happens. + /// + public bool Enable => _configuration.GetValue(Prefix+"Enable", false); + + /// + /// Gets the models mode. + /// + public ModelsMode ModelsMode => + _configuration.GetValue(Prefix+"ModelsMode", ModelsMode.Nothing); + + /// + /// Gets the models namespace. + /// + /// That value could be overriden by other (attribute in user's code...). Return default if no value was supplied. + public string ModelsNamespace => _configuration.GetValue(Prefix+"ModelsNamespace"); + + /// + /// Gets a value indicating whether we should enable the models factory. + /// + /// Default value is true because no factory is enabled by default in Umbraco. + public bool EnableFactory => _configuration.GetValue(Prefix+"EnableFactory", true); + + /// + /// Gets a value indicating whether we should flag out-of-date models. + /// + /// + /// Models become out-of-date when data types or content types are updated. When this + /// setting is activated the ~/App_Data/Models/ood.txt file is then created. When models are + /// generated through the dashboard, the files is cleared. Default value is false. + /// + public bool FlagOutOfDateModels => + _configuration.GetValue(Prefix+"FlagOutOfDateModels", false) && !ModelsMode.IsLive(); + + /// + /// Gets the models directory. + /// + /// Default is ~/App_Data/Models but that can be changed. + public string ModelsDirectory => + _configuration.GetValue(Prefix+"ModelsDirectory", "~/App_Data/Models"); + + /// + /// Gets a value indicating whether to accept an unsafe value for ModelsDirectory. + /// + /// + /// An unsafe value is an absolute path, or a relative path pointing outside + /// of the website root. + /// + public bool AcceptUnsafeModelsDirectory => + _configuration.GetValue(Prefix+"AcceptUnsafeModelsDirectory", false); + + /// + /// Gets a value indicating the debug log level. + /// + /// 0 means minimal (safe on live site), anything else means more and more details (maybe not safe). + public int DebugLevel => _configuration.GetValue(Prefix+"DebugLevel", 0); + } +} diff --git a/src/Umbraco.Configuration/Models/NuCacheSettings.cs b/src/Umbraco.Configuration/Models/NuCacheSettings.cs new file mode 100644 index 0000000000..51b8b1fe08 --- /dev/null +++ b/src/Umbraco.Configuration/Models/NuCacheSettings.cs @@ -0,0 +1,19 @@ +using Microsoft.Extensions.Configuration; +using Umbraco.Core; +using Umbraco.Core.Configuration; + +namespace Umbraco.Configuration.Models +{ + internal class NuCacheSettings : INuCacheSettings + { + private const string Prefix = Constants.Configuration.ConfigPrefix + "NuCache:"; + private readonly IConfiguration _configuration; + + public NuCacheSettings(IConfiguration configuration) + { + _configuration = configuration; + } + + public string BTreeBlockSize => _configuration.GetValue(Prefix+"BTreeBlockSize"); + } +} diff --git a/src/Umbraco.Configuration/Models/RuntimeSettings.cs b/src/Umbraco.Configuration/Models/RuntimeSettings.cs new file mode 100644 index 0000000000..ef129030b6 --- /dev/null +++ b/src/Umbraco.Configuration/Models/RuntimeSettings.cs @@ -0,0 +1,19 @@ +using Microsoft.Extensions.Configuration; +using Umbraco.Core; +using Umbraco.Core.Configuration; + +namespace Umbraco.Configuration.Models +{ + internal class RuntimeSettings : IRuntimeSettings + { + private const string Prefix = Constants.Configuration.ConfigPrefix + "Runtime:"; + private readonly IConfiguration _configuration; + public RuntimeSettings(IConfiguration configuration) + { + _configuration = configuration; + } + + public int? MaxQueryStringLength => _configuration.GetValue(Prefix+"MaxRequestLength"); + public int? MaxRequestLength => _configuration.GetValue(Prefix+"MaxRequestLength"); + } +} diff --git a/src/Umbraco.Configuration/Models/SecuritySettings.cs b/src/Umbraco.Configuration/Models/SecuritySettings.cs new file mode 100644 index 0000000000..297c95b1af --- /dev/null +++ b/src/Umbraco.Configuration/Models/SecuritySettings.cs @@ -0,0 +1,33 @@ +using Microsoft.Extensions.Configuration; +using Umbraco.Core; +using Umbraco.Core.Configuration.UmbracoSettings; + +namespace Umbraco.Configuration.Models +{ + internal class SecuritySettings : ISecuritySettings + { + private const string Prefix = Constants.Configuration.ConfigSecurityPrefix; + private readonly IConfiguration _configuration; + + public SecuritySettings(IConfiguration configuration) + { + _configuration = configuration; + } + + public bool KeepUserLoggedIn => _configuration.GetValue(Prefix + "KeepUserLoggedIn", false); + + public bool HideDisabledUsersInBackoffice => + _configuration.GetValue(Prefix + "HideDisabledUsersInBackoffice", false); + + public bool AllowPasswordReset => + _configuration.GetValue(Prefix + "AllowPasswordResetAllowPasswordReset", true); + + public string AuthCookieName => + _configuration.GetValue(Prefix + "AuthCookieName", "UMB_UCONTEXT"); + + public string AuthCookieDomain => + _configuration.GetValue(Prefix + "AuthCookieDomain"); + + public bool UsernameIsEmail => _configuration.GetValue(Prefix + "UsernameIsEmail", true); + } +} diff --git a/src/Umbraco.Configuration/Models/TourSettings.cs b/src/Umbraco.Configuration/Models/TourSettings.cs new file mode 100644 index 0000000000..9fe1814ff5 --- /dev/null +++ b/src/Umbraco.Configuration/Models/TourSettings.cs @@ -0,0 +1,21 @@ +using Microsoft.Extensions.Configuration; +using Umbraco.Core; +using Umbraco.Core.Configuration.UmbracoSettings; + +namespace Umbraco.Configuration.Models +{ + internal class TourSettings : ITourSettings + { + private const string Prefix = Constants.Configuration.ConfigPrefix + "Tours:"; + private readonly IConfiguration _configuration; + + public TourSettings(IConfiguration configuration) + { + _configuration = configuration; + } + + public string Type { get; set; } + + public bool EnableTours => _configuration.GetValue(Prefix+"EnableTours", true); + } +} diff --git a/src/Umbraco.Configuration/Models/TypeFinderSettings.cs b/src/Umbraco.Configuration/Models/TypeFinderSettings.cs new file mode 100644 index 0000000000..8a1f7ac9e0 --- /dev/null +++ b/src/Umbraco.Configuration/Models/TypeFinderSettings.cs @@ -0,0 +1,20 @@ +using Microsoft.Extensions.Configuration; +using Umbraco.Core; +using Umbraco.Core.Configuration; + +namespace Umbraco.Configuration.Models +{ + internal class TypeFinderSettings : ITypeFinderSettings + { + private const string Prefix = Constants.Configuration.ConfigPrefix + "TypeFinder:"; + private readonly IConfiguration _configuration; + + public TypeFinderSettings(IConfiguration configuration) + { + _configuration = configuration; + } + + public string AssembliesAcceptingLoadExceptions => + _configuration.GetValue(Prefix+"AssembliesAcceptingLoadExceptions"); + } +} diff --git a/src/Umbraco.Configuration/Models/UserPasswordConfigurationSettings.cs b/src/Umbraco.Configuration/Models/UserPasswordConfigurationSettings.cs new file mode 100644 index 0000000000..25ce3e3d9a --- /dev/null +++ b/src/Umbraco.Configuration/Models/UserPasswordConfigurationSettings.cs @@ -0,0 +1,36 @@ +using Microsoft.Extensions.Configuration; +using Umbraco.Core; +using Umbraco.Core.Configuration; + +namespace Umbraco.Configuration.Models +{ + internal class UserPasswordConfigurationSettings : IUserPasswordConfiguration + { + private const string Prefix = Constants.Configuration.ConfigSecurityPrefix + "UserPassword:"; + private readonly IConfiguration _configuration; + + public UserPasswordConfigurationSettings(IConfiguration configuration) + { + _configuration = configuration; + } + + public int RequiredLength => _configuration.GetValue(Prefix + "RequiredLength", 10); + + public bool RequireNonLetterOrDigit => + _configuration.GetValue(Prefix + "RequireNonLetterOrDigit", false); + + public bool RequireDigit => _configuration.GetValue(Prefix + "RequireDigit", false); + + public bool RequireLowercase => + _configuration.GetValue(Prefix + "RequireLowercase", false); + + public bool RequireUppercase => + _configuration.GetValue(Prefix + "RequireUppercase", false); + + public string HashAlgorithmType => + _configuration.GetValue(Prefix + "HashAlgorithmType", Constants.Security.AspNetCoreV3PasswordHashAlgorithmName); + + public int MaxFailedAccessAttemptsBeforeLockout => + _configuration.GetValue(Prefix + "MaxFailedAccessAttemptsBeforeLockout", 5); + } +} diff --git a/src/Umbraco.Configuration/Models/WebRoutingSettings.cs b/src/Umbraco.Configuration/Models/WebRoutingSettings.cs new file mode 100644 index 0000000000..9ac856ca9f --- /dev/null +++ b/src/Umbraco.Configuration/Models/WebRoutingSettings.cs @@ -0,0 +1,42 @@ +using Microsoft.Extensions.Configuration; +using Umbraco.Core; +using Umbraco.Core.Configuration.UmbracoSettings; +using Umbraco.Core.Models.PublishedContent; + +namespace Umbraco.Configuration.Models +{ + internal class WebRoutingSettings : IWebRoutingSettings + { + private const string Prefix = Constants.Configuration.ConfigPrefix + "WebRouting:"; + private readonly IConfiguration _configuration; + + public WebRoutingSettings(IConfiguration configuration) + { + _configuration = configuration; + } + + public bool TrySkipIisCustomErrors => + _configuration.GetValue(Prefix + "TrySkipIisCustomErrors", false); + + public bool InternalRedirectPreservesTemplate => + _configuration.GetValue(Prefix + "InternalRedirectPreservesTemplate", false); + + public bool DisableAlternativeTemplates => + _configuration.GetValue(Prefix + "DisableAlternativeTemplates", false); + + public bool ValidateAlternativeTemplates => + _configuration.GetValue(Prefix + "ValidateAlternativeTemplates", false); + + public bool DisableFindContentByIdPath => + _configuration.GetValue(Prefix + "DisableFindContentByIdPath", false); + + public bool DisableRedirectUrlTracking => + _configuration.GetValue(Prefix + "DisableRedirectUrlTracking", false); + + public string UrlProviderMode => + _configuration.GetValue(Prefix + "UrlProviderMode", UrlMode.Auto.ToString()); + + public string UmbracoApplicationUrl => + _configuration.GetValue(Prefix + "UmbracoApplicationUrl"); + } +} diff --git a/src/Umbraco.ModelsBuilder.Embedded/BackOffice/ContentTypeModelValidator.cs b/src/Umbraco.ModelsBuilder.Embedded/BackOffice/ContentTypeModelValidator.cs index 1da5e44a77..75affe09e7 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/BackOffice/ContentTypeModelValidator.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/BackOffice/ContentTypeModelValidator.cs @@ -1,5 +1,4 @@ -using Microsoft.Extensions.Options; -using Umbraco.Core.Configuration.Models; +using Umbraco.Core.Configuration; using Umbraco.Web.Models.ContentEditing; namespace Umbraco.ModelsBuilder.Embedded.BackOffice @@ -11,7 +10,7 @@ namespace Umbraco.ModelsBuilder.Embedded.BackOffice // ReSharper disable once UnusedMember.Global - This is typed scanned public class ContentTypeModelValidator : ContentTypeModelValidatorBase { - public ContentTypeModelValidator(IOptionsSnapshot config) : base(config) + public ContentTypeModelValidator(IModelsBuilderConfig config) : base(config) { } } diff --git a/src/Umbraco.ModelsBuilder.Embedded/BackOffice/ContentTypeModelValidatorBase.cs b/src/Umbraco.ModelsBuilder.Embedded/BackOffice/ContentTypeModelValidatorBase.cs index dc78b31abd..1e96e64df8 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/BackOffice/ContentTypeModelValidatorBase.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/BackOffice/ContentTypeModelValidatorBase.cs @@ -1,9 +1,8 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; -using Microsoft.Extensions.Options; +using Umbraco.Core.Configuration; using Umbraco.Core; -using Umbraco.Core.Configuration.Models; using Umbraco.Core.Models.PublishedContent; using Umbraco.Web.Editors; using Umbraco.Web.Models.ContentEditing; @@ -14,11 +13,11 @@ namespace Umbraco.ModelsBuilder.Embedded.BackOffice where TModel : ContentTypeSave where TProperty : PropertyTypeBasic { - private readonly ModelsBuilderConfig _config; + private readonly IModelsBuilderConfig _config; - public ContentTypeModelValidatorBase(IOptionsSnapshot config) + public ContentTypeModelValidatorBase(IModelsBuilderConfig config) { - _config = config.Value; + _config = config; } protected override IEnumerable Validate(TModel model) diff --git a/src/Umbraco.ModelsBuilder.Embedded/BackOffice/DashboardReport.cs b/src/Umbraco.ModelsBuilder.Embedded/BackOffice/DashboardReport.cs index 9dc4d8bfb4..6e22313474 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/BackOffice/DashboardReport.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/BackOffice/DashboardReport.cs @@ -1,17 +1,16 @@ using System.Text; using Umbraco.Configuration; using Umbraco.Core.Configuration; -using Umbraco.Core.Configuration.Models; namespace Umbraco.ModelsBuilder.Embedded.BackOffice { internal class DashboardReport { - private readonly ModelsBuilderConfig _config; + private readonly IModelsBuilderConfig _config; private readonly OutOfDateModelsStatus _outOfDateModels; private readonly ModelsGenerationError _mbErrors; - public DashboardReport(ModelsBuilderConfig config, OutOfDateModelsStatus outOfDateModels, ModelsGenerationError mbErrors) + public DashboardReport(IModelsBuilderConfig config, OutOfDateModelsStatus outOfDateModels, ModelsGenerationError mbErrors) { _config = config; _outOfDateModels = outOfDateModels; diff --git a/src/Umbraco.ModelsBuilder.Embedded/BackOffice/MediaTypeModelValidator.cs b/src/Umbraco.ModelsBuilder.Embedded/BackOffice/MediaTypeModelValidator.cs index fc03c24704..fcd42908e7 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/BackOffice/MediaTypeModelValidator.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/BackOffice/MediaTypeModelValidator.cs @@ -1,5 +1,4 @@ -using Microsoft.Extensions.Options; -using Umbraco.Core.Configuration.Models; +using Umbraco.Core.Configuration; using Umbraco.Web.Models.ContentEditing; namespace Umbraco.ModelsBuilder.Embedded.BackOffice @@ -11,7 +10,7 @@ namespace Umbraco.ModelsBuilder.Embedded.BackOffice // ReSharper disable once UnusedMember.Global - This is typed scanned public class MediaTypeModelValidator : ContentTypeModelValidatorBase { - public MediaTypeModelValidator(IOptionsSnapshot config) : base(config) + public MediaTypeModelValidator(IModelsBuilderConfig config) : base(config) { } } diff --git a/src/Umbraco.ModelsBuilder.Embedded/BackOffice/ModelsBuilderDashboardController.cs b/src/Umbraco.ModelsBuilder.Embedded/BackOffice/ModelsBuilderDashboardController.cs index 92f42121e2..17b694de56 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/BackOffice/ModelsBuilderDashboardController.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/BackOffice/ModelsBuilderDashboardController.cs @@ -3,10 +3,8 @@ using System.Net; using System.Net.Http; using System.Runtime.Serialization; using System.Web.Hosting; -using Microsoft.Extensions.Options; using Umbraco.Configuration; using Umbraco.Core.Configuration; -using Umbraco.Core.Configuration.Models; using Umbraco.Core.Exceptions; using Umbraco.ModelsBuilder.Embedded.Building; using Umbraco.Web.Editors; @@ -25,20 +23,20 @@ namespace Umbraco.ModelsBuilder.Embedded.BackOffice [UmbracoApplicationAuthorize(Core.Constants.Applications.Settings)] public class ModelsBuilderDashboardController : UmbracoAuthorizedJsonController { - private readonly ModelsBuilderConfig _config; + private readonly IModelsBuilderConfig _config; private readonly ModelsGenerator _modelGenerator; private readonly OutOfDateModelsStatus _outOfDateModels; private readonly ModelsGenerationError _mbErrors; private readonly DashboardReport _dashboardReport; - public ModelsBuilderDashboardController(IOptionsSnapshot config, ModelsGenerator modelsGenerator, OutOfDateModelsStatus outOfDateModels, ModelsGenerationError mbErrors) + public ModelsBuilderDashboardController(IModelsBuilderConfig config, ModelsGenerator modelsGenerator, OutOfDateModelsStatus outOfDateModels, ModelsGenerationError mbErrors) { //_umbracoServices = umbracoServices; - _config = config.Value; + _config = config; _modelGenerator = modelsGenerator; _outOfDateModels = outOfDateModels; _mbErrors = mbErrors; - _dashboardReport = new DashboardReport(_config, outOfDateModels, mbErrors); + _dashboardReport = new DashboardReport(config, outOfDateModels, mbErrors); } // invoked by the dashboard diff --git a/src/Umbraco.ModelsBuilder.Embedded/Building/Builder.cs b/src/Umbraco.ModelsBuilder.Embedded/Building/Builder.cs index c053f94649..f64e5ed1ce 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/Building/Builder.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/Building/Builder.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Linq; using Umbraco.Core; using Umbraco.Core.Configuration; -using Umbraco.Core.Configuration.Models; namespace Umbraco.ModelsBuilder.Embedded.Building { @@ -71,7 +70,7 @@ namespace Umbraco.ModelsBuilder.Embedded.Building /// /// The list of models to generate. /// The models namespace. - protected Builder(ModelsBuilderConfig config, IList typeModels) + protected Builder(IModelsBuilderConfig config, IList typeModels) { _typeModels = typeModels ?? throw new ArgumentNullException(nameof(typeModels)); diff --git a/src/Umbraco.ModelsBuilder.Embedded/Building/ModelsGenerator.cs b/src/Umbraco.ModelsBuilder.Embedded/Building/ModelsGenerator.cs index 29da569102..648a2e76fa 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/Building/ModelsGenerator.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/Building/ModelsGenerator.cs @@ -1,7 +1,6 @@ using System.IO; using System.Text; using Umbraco.Core.Configuration; -using Umbraco.Core.Configuration.Models; using Umbraco.Core.IO; namespace Umbraco.ModelsBuilder.Embedded.Building @@ -9,11 +8,11 @@ namespace Umbraco.ModelsBuilder.Embedded.Building public class ModelsGenerator { private readonly UmbracoServices _umbracoService; - private readonly ModelsBuilderConfig _config; + private readonly IModelsBuilderConfig _config; private readonly OutOfDateModelsStatus _outOfDateModels; private readonly IIOHelper _ioHelper; - public ModelsGenerator(UmbracoServices umbracoService, ModelsBuilderConfig config, OutOfDateModelsStatus outOfDateModels, IIOHelper ioHelper) + public ModelsGenerator(UmbracoServices umbracoService, IModelsBuilderConfig config, OutOfDateModelsStatus outOfDateModels, IIOHelper ioHelper) { _umbracoService = umbracoService; _config = config; diff --git a/src/Umbraco.ModelsBuilder.Embedded/Building/TextBuilder.cs b/src/Umbraco.ModelsBuilder.Embedded/Building/TextBuilder.cs index 6caca6c8ab..723ee10f35 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/Building/TextBuilder.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/Building/TextBuilder.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Text.RegularExpressions; -using Umbraco.Core.Configuration.Models; +using Umbraco.Core.Configuration; namespace Umbraco.ModelsBuilder.Embedded.Building { @@ -17,7 +17,7 @@ namespace Umbraco.ModelsBuilder.Embedded.Building /// and the result of code parsing. /// /// The list of models to generate. - public TextBuilder(ModelsBuilderConfig config, IList typeModels) + public TextBuilder(IModelsBuilderConfig config, IList typeModels) : base(config, typeModels) { } diff --git a/src/Umbraco.ModelsBuilder.Embedded/Compose/ModelsBuilderComponent.cs b/src/Umbraco.ModelsBuilder.Embedded/Compose/ModelsBuilderComponent.cs index a794f45616..32cfd3057e 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/Compose/ModelsBuilderComponent.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/Compose/ModelsBuilderComponent.cs @@ -15,21 +15,19 @@ using Umbraco.ModelsBuilder.Embedded.BackOffice; using Umbraco.Web; using Umbraco.Web.Mvc; using Umbraco.Web.WebAssets; -using Umbraco.Core.Configuration.Models; -using Microsoft.Extensions.Options; namespace Umbraco.ModelsBuilder.Embedded.Compose { internal class ModelsBuilderComponent : IComponent { - private readonly ModelsBuilderConfig _config; + private readonly IModelsBuilderConfig _config; private readonly IShortStringHelper _shortStringHelper; private readonly LiveModelsProvider _liveModelsProvider; private readonly OutOfDateModelsStatus _outOfDateModels; - public ModelsBuilderComponent(IOptionsSnapshot config, IShortStringHelper shortStringHelper, LiveModelsProvider liveModelsProvider, OutOfDateModelsStatus outOfDateModels) + public ModelsBuilderComponent(IModelsBuilderConfig config, IShortStringHelper shortStringHelper, LiveModelsProvider liveModelsProvider, OutOfDateModelsStatus outOfDateModels) { - _config = config.Value; + _config = config; _shortStringHelper = shortStringHelper; _liveModelsProvider = liveModelsProvider; _outOfDateModels = outOfDateModels; diff --git a/src/Umbraco.ModelsBuilder.Embedded/LiveModelsProvider.cs b/src/Umbraco.ModelsBuilder.Embedded/LiveModelsProvider.cs index e1ba236839..61d39cd373 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/LiveModelsProvider.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/LiveModelsProvider.cs @@ -6,7 +6,6 @@ using Umbraco.Core.Hosting; using Umbraco.Core.Logging; using Umbraco.ModelsBuilder.Embedded.Building; using Umbraco.Web.Cache; -using Umbraco.Core.Configuration.Models; namespace Umbraco.ModelsBuilder.Embedded { @@ -16,7 +15,7 @@ namespace Umbraco.ModelsBuilder.Embedded private static Mutex _mutex; private static int _req; private readonly ILogger _logger; - private readonly ModelsBuilderConfig _config; + private readonly IModelsBuilderConfig _config; private readonly ModelsGenerator _modelGenerator; private readonly ModelsGenerationError _mbErrors; private readonly IHostingEnvironment _hostingEnvironment; @@ -24,7 +23,7 @@ namespace Umbraco.ModelsBuilder.Embedded // we do not manage pure live here internal bool IsEnabled => _config.ModelsMode.IsLiveNotPure(); - public LiveModelsProvider(ILogger logger, ModelsBuilderConfig config, ModelsGenerator modelGenerator, ModelsGenerationError mbErrors, IHostingEnvironment hostingEnvironment) + public LiveModelsProvider(ILogger logger, IModelsBuilderConfig config, ModelsGenerator modelGenerator, ModelsGenerationError mbErrors, IHostingEnvironment hostingEnvironment) { _logger = logger; _config = config ?? throw new ArgumentNullException(nameof(config)); diff --git a/src/Umbraco.ModelsBuilder.Embedded/ModelsGenerationError.cs b/src/Umbraco.ModelsBuilder.Embedded/ModelsGenerationError.cs index 0181701f1f..f8f6e8c7bc 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/ModelsGenerationError.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/ModelsGenerationError.cs @@ -2,17 +2,16 @@ using System.IO; using System.Text; using Umbraco.Core.Configuration; -using Umbraco.Core.Configuration.Models; using Umbraco.Core.IO; namespace Umbraco.ModelsBuilder.Embedded { public sealed class ModelsGenerationError { - private readonly ModelsBuilderConfig _config; + private readonly IModelsBuilderConfig _config; private readonly IIOHelper _ioHelper; - public ModelsGenerationError(ModelsBuilderConfig config, IIOHelper ioHelper) + public ModelsGenerationError(IModelsBuilderConfig config, IIOHelper ioHelper) { _config = config; _ioHelper = ioHelper; diff --git a/src/Umbraco.ModelsBuilder.Embedded/OutOfDateModelsStatus.cs b/src/Umbraco.ModelsBuilder.Embedded/OutOfDateModelsStatus.cs index 4fb23ad5b3..b8105eeef2 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/OutOfDateModelsStatus.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/OutOfDateModelsStatus.cs @@ -1,6 +1,5 @@ using System.IO; using Umbraco.Core.Configuration; -using Umbraco.Core.Configuration.Models; using Umbraco.Core.IO; using Umbraco.Web.Cache; @@ -8,10 +7,10 @@ namespace Umbraco.ModelsBuilder.Embedded { public sealed class OutOfDateModelsStatus { - private readonly ModelsBuilderConfig _config; + private readonly IModelsBuilderConfig _config; private readonly IIOHelper _ioHelper; - public OutOfDateModelsStatus(ModelsBuilderConfig config, IIOHelper ioHelper) + public OutOfDateModelsStatus(IModelsBuilderConfig config, IIOHelper ioHelper) { _config = config; _ioHelper = ioHelper; diff --git a/src/Umbraco.ModelsBuilder.Embedded/PureLiveModelFactory.cs b/src/Umbraco.ModelsBuilder.Embedded/PureLiveModelFactory.cs index 6e5ba18888..7809d2bf48 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/PureLiveModelFactory.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/PureLiveModelFactory.cs @@ -19,8 +19,6 @@ using Umbraco.Core.Logging; using Umbraco.Core.Models.PublishedContent; using Umbraco.ModelsBuilder.Embedded.Building; using File = System.IO.File; -using Umbraco.Core.Configuration.Models; -using Microsoft.Extensions.Options; namespace Umbraco.ModelsBuilder.Embedded { @@ -43,7 +41,7 @@ namespace Umbraco.ModelsBuilder.Embedded private const string ProjVirt = "~/App_Data/Models/all.generated.cs"; private static readonly string[] OurFiles = { "models.hash", "models.generated.cs", "all.generated.cs", "all.dll.path", "models.err" }; - private readonly ModelsBuilderConfig _config; + private readonly IModelsBuilderConfig _config; private readonly IApplicationShutdownRegistry _hostingLifetime; private readonly IIOHelper _ioHelper; private readonly ModelsGenerationError _errors; @@ -51,7 +49,7 @@ namespace Umbraco.ModelsBuilder.Embedded public PureLiveModelFactory( Lazy umbracoServices, IProfilingLogger logger, - IOptionsSnapshot config, + IModelsBuilderConfig config, IHostingEnvironment hostingEnvironment, IApplicationShutdownRegistry hostingLifetime, IIOHelper ioHelper) diff --git a/src/Umbraco.Tests.Common/SettingsForTests.cs b/src/Umbraco.Tests.Common/SettingsForTests.cs index e60f6ad0a4..1a14dc6bc1 100644 --- a/src/Umbraco.Tests.Common/SettingsForTests.cs +++ b/src/Umbraco.Tests.Common/SettingsForTests.cs @@ -3,7 +3,7 @@ using Moq; using Semver; using Umbraco.Core; using Umbraco.Core.Configuration; -using Umbraco.Core.Configuration.Models; +using Umbraco.Core.Configuration.Legacy; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.IO; using Umbraco.Core.Models.PublishedContent; @@ -16,23 +16,25 @@ namespace Umbraco.Tests.Common { } - public GlobalSettings GenerateStubGlobalSettings(IUmbracoVersion umbVersion = null) + public IGlobalSettings GenerateMockGlobalSettings(IUmbracoVersion umbVersion = null) { var semanticVersion = umbVersion?.SemanticVersion ?? new SemVersion(9); - var config = new GlobalSettings - { - UseHttps = false, - HideTopLevelNodeFromPath = false, - TimeOutInMinutes = 20, - DefaultUILanguage = "en", - ReservedPaths = (GlobalSettings.StaticReservedPaths + "~/umbraco"), - ReservedUrls = GlobalSettings.StaticReservedUrls, - UmbracoPath = "~/umbraco", - UmbracoMediaPath = "~/media", - UmbracoCssPath = "~/css", - UmbracoScriptsPath = "~/scripts", - }; + var config = Mock.Of( + settings => + settings.UseHttps == false && + settings.HideTopLevelNodeFromPath == false && + settings.TimeOutInMinutes == 20 && + settings.DefaultUILanguage == "en" && + settings.ReservedPaths == (GlobalSettings.StaticReservedPaths + "~/umbraco") && + settings.ReservedUrls == GlobalSettings.StaticReservedUrls && + settings.UmbracoPath == "~/umbraco" && + settings.UmbracoMediaPath == "~/media" && + settings.UmbracoCssPath == "~/css" && + settings.UmbracoScriptsPath == "~/scripts" + ); + + return config; } @@ -102,15 +104,15 @@ namespace Umbraco.Tests.Common _defaultHostingSettings = null; } - private readonly Dictionary _defaultGlobalSettings = new Dictionary(); + private readonly Dictionary _defaultGlobalSettings = new Dictionary(); private IHostingSettings _defaultHostingSettings; - public GlobalSettings GetDefaultGlobalSettings(IUmbracoVersion umbVersion) + public IGlobalSettings GetDefaultGlobalSettings(IUmbracoVersion umbVersion) { if (_defaultGlobalSettings.TryGetValue(umbVersion.SemanticVersion, out var settings)) return settings; - settings = GenerateStubGlobalSettings(umbVersion); + settings = GenerateMockGlobalSettings(umbVersion); _defaultGlobalSettings[umbVersion.SemanticVersion] = settings; return settings; } diff --git a/src/Umbraco.Tests.Common/TestHelperBase.cs b/src/Umbraco.Tests.Common/TestHelperBase.cs index 461cbf4097..85a463ddfa 100644 --- a/src/Umbraco.Tests.Common/TestHelperBase.cs +++ b/src/Umbraco.Tests.Common/TestHelperBase.cs @@ -18,7 +18,6 @@ using Umbraco.Core.Serialization; using Umbraco.Core.Strings; using Umbraco.Web; using Umbraco.Web.Routing; -using CoreDebugSettings = Umbraco.Core.Configuration.Models.CoreDebugSettings; namespace Umbraco.Tests.Common { @@ -83,14 +82,14 @@ namespace Umbraco.Tests.Common public abstract IDbProviderFactoryCreator DbProviderFactoryCreator { get; } public abstract IBulkSqlInsertProvider BulkSqlInsertProvider { get; } public abstract IMarchal Marchal { get; } - public CoreDebugSettings CoreDebugSettings { get; } = new CoreDebugSettings(); + public ICoreDebugSettings CoreDebugSettings { get; } = new CoreDebugSettings(); public IIOHelper IOHelper { get { if (_ioHelper == null) - _ioHelper = new IOHelper(GetHostingEnvironment(), SettingsForTests.GenerateStubGlobalSettings()); + _ioHelper = new IOHelper(GetHostingEnvironment(), SettingsForTests.GenerateMockGlobalSettings()); return _ioHelper; } } diff --git a/src/Umbraco.Tests.Integration/Implementations/TestHostingEnvironment.cs b/src/Umbraco.Tests.Integration/Implementations/TestHostingEnvironment.cs index 73076522c8..076cecef4a 100644 --- a/src/Umbraco.Tests.Integration/Implementations/TestHostingEnvironment.cs +++ b/src/Umbraco.Tests.Integration/Implementations/TestHostingEnvironment.cs @@ -1,6 +1,6 @@ using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.Options; -using Umbraco.Core.Configuration.Models; +using Umbraco.Core.Configuration; +using Umbraco.Core.Logging; using Umbraco.Web.Common.AspNetCore; using IHostingEnvironment = Umbraco.Core.Hosting.IHostingEnvironment; @@ -9,7 +9,7 @@ namespace Umbraco.Tests.Integration.Implementations public class TestHostingEnvironment : AspNetCoreHostingEnvironment, IHostingEnvironment { - public TestHostingEnvironment(IOptionsSnapshot hostingSettings, IWebHostEnvironment webHostEnvironment) + public TestHostingEnvironment(IHostingSettings hostingSettings, IWebHostEnvironment webHostEnvironment) : base(hostingSettings, webHostEnvironment) { } diff --git a/src/Umbraco.Tests.Integration/Umbraco.Web.BackOffice.Security/BackOfficeCookieManagerTests.cs b/src/Umbraco.Tests.Integration/Umbraco.Web.BackOffice.Security/BackOfficeCookieManagerTests.cs index a25a21f27c..3464259052 100644 --- a/src/Umbraco.Tests.Integration/Umbraco.Web.BackOffice.Security/BackOfficeCookieManagerTests.cs +++ b/src/Umbraco.Tests.Integration/Umbraco.Web.BackOffice.Security/BackOfficeCookieManagerTests.cs @@ -25,7 +25,7 @@ namespace Umbraco.Tests.Security var testHelper = new TestHelper(); var httpContextAccessor = testHelper.GetHttpContextAccessor(); - var globalSettings = testHelper.SettingsForTests.GenerateStubGlobalSettings(); + var globalSettings = testHelper.SettingsForTests.GenerateMockGlobalSettings(); var runtime = Mock.Of(x => x.Level == RuntimeLevel.Install); var mgr = new BackOfficeCookieManager( @@ -50,7 +50,7 @@ namespace Umbraco.Tests.Security //hostingEnvironment.ToAbsolute(globalSettings.UmbracoPath); var httpContextAccessor = testHelper.GetHttpContextAccessor(); - var globalSettings = testHelper.SettingsForTests.GenerateStubGlobalSettings(); + var globalSettings = testHelper.SettingsForTests.GenerateMockGlobalSettings(); var runtime = Mock.Of(x => x.Level == RuntimeLevel.Run); var mgr = new BackOfficeCookieManager( @@ -72,7 +72,7 @@ namespace Umbraco.Tests.Security var testHelper = new TestHelper(); var httpContextAccessor = testHelper.GetHttpContextAccessor(); - var globalSettings = testHelper.SettingsForTests.GenerateStubGlobalSettings(); + var globalSettings = testHelper.SettingsForTests.GenerateMockGlobalSettings(); var runtime = Mock.Of(x => x.Level == RuntimeLevel.Run); @@ -97,7 +97,7 @@ namespace Umbraco.Tests.Security var testHelper = new TestHelper(); var httpContextAccessor = testHelper.GetHttpContextAccessor(); - var globalSettings = testHelper.SettingsForTests.GenerateStubGlobalSettings(); + var globalSettings = testHelper.SettingsForTests.GenerateMockGlobalSettings(); var runtime = Mock.Of(x => x.Level == RuntimeLevel.Run); @@ -119,7 +119,7 @@ namespace Umbraco.Tests.Security var testHelper = new TestHelper(); var httpContextAccessor = testHelper.GetHttpContextAccessor(); - var globalSettings = testHelper.SettingsForTests.GenerateStubGlobalSettings(); + var globalSettings = testHelper.SettingsForTests.GenerateMockGlobalSettings(); var runtime = Mock.Of(x => x.Level == RuntimeLevel.Run); diff --git a/src/Umbraco.Tests/Components/ComponentTests.cs b/src/Umbraco.Tests/Components/ComponentTests.cs index 3bd7b0a7cc..a20b220940 100644 --- a/src/Umbraco.Tests/Components/ComponentTests.cs +++ b/src/Umbraco.Tests/Components/ComponentTests.cs @@ -14,7 +14,6 @@ using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.Mappers; using Umbraco.Core.Scoping; using Umbraco.Tests.TestHelpers; -using CoreDebugSettings = Umbraco.Core.Configuration.Models.CoreDebugSettings; namespace Umbraco.Tests.Components { @@ -36,7 +35,7 @@ namespace Umbraco.Tests.Components var typeFinder = TestHelper.GetTypeFinder(); var f = new UmbracoDatabaseFactory(logger, SettingsForTests.DefaultGlobalSettings, Mock.Of(), new Lazy(() => new MapperCollection(Enumerable.Empty())), TestHelper.DbProviderFactoryCreator); var fs = new FileSystems(mock.Object, logger, TestHelper.IOHelper, SettingsForTests.GenerateMockGlobalSettings(), TestHelper.GetHostingEnvironment()); - var coreDebug = new CoreDebugSettings(); + var coreDebug = Mock.Of(); var mediaFileSystem = Mock.Of(); var p = new ScopeProvider(f, fs, coreDebug, mediaFileSystem, logger, typeFinder, NoAppCache.Instance); diff --git a/src/Umbraco.Tests/Models/MediaXmlTest.cs b/src/Umbraco.Tests/Models/MediaXmlTest.cs index 1dd9f3d7cb..632f433c5b 100644 --- a/src/Umbraco.Tests/Models/MediaXmlTest.cs +++ b/src/Umbraco.Tests/Models/MediaXmlTest.cs @@ -3,7 +3,6 @@ using System.Xml.Linq; using Moq; using NUnit.Framework; using Umbraco.Core; -using Umbraco.Core.Configuration.Models; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.IO; using Umbraco.Core.Logging; @@ -32,7 +31,7 @@ namespace Umbraco.Tests.Models // and then, this will reset the width, height... because the file does not exist, of course ;-( var logger = Mock.Of(); var scheme = Mock.Of(); - var config = new ContentSettings(); + var config = Mock.Of(); var mediaFileSystem = new MediaFileSystem(Mock.Of(), scheme, logger, ShortStringHelper); var ignored = new FileUploadPropertyEditor(Mock.Of(), mediaFileSystem, config, DataTypeService, LocalizationService, LocalizedTextService, ShortStringHelper); diff --git a/src/Umbraco.Tests/Routing/MediaUrlProviderTests.cs b/src/Umbraco.Tests/Routing/MediaUrlProviderTests.cs index c191bc1b43..e55a22065b 100644 --- a/src/Umbraco.Tests/Routing/MediaUrlProviderTests.cs +++ b/src/Umbraco.Tests/Routing/MediaUrlProviderTests.cs @@ -4,7 +4,6 @@ using Moq; using Newtonsoft.Json; using NUnit.Framework; using Umbraco.Core; -using Umbraco.Core.Configuration.Models; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.IO; using Umbraco.Core.Logging; @@ -35,12 +34,12 @@ namespace Umbraco.Tests.Routing var logger = Mock.Of(); var mediaFileSystemMock = Mock.Of(); - var contentSettings = new ContentSettings(); + var contentSection = Mock.Of(); var dataTypeService = Mock.Of(); var propertyEditors = new MediaUrlGeneratorCollection(new IMediaUrlGenerator[] { - new FileUploadPropertyEditor(logger, mediaFileSystemMock, contentSettings, dataTypeService, LocalizationService, LocalizedTextService, ShortStringHelper), - new ImageCropperPropertyEditor(logger, mediaFileSystemMock, contentSettings, dataTypeService, LocalizationService, IOHelper, ShortStringHelper, LocalizedTextService), + new FileUploadPropertyEditor(logger, mediaFileSystemMock, contentSection, dataTypeService, LocalizationService, LocalizedTextService, ShortStringHelper), + new ImageCropperPropertyEditor(logger, mediaFileSystemMock, contentSection, dataTypeService, LocalizationService, IOHelper, ShortStringHelper, LocalizedTextService), }); _mediaUrlProvider = new DefaultMediaUrlProvider(propertyEditors, UriUtility); } diff --git a/src/Umbraco.Tests/Security/BackOfficeOwinUserManagerTests.cs b/src/Umbraco.Tests/Security/BackOfficeOwinUserManagerTests.cs index d2a17d1004..8958eabd42 100644 --- a/src/Umbraco.Tests/Security/BackOfficeOwinUserManagerTests.cs +++ b/src/Umbraco.Tests/Security/BackOfficeOwinUserManagerTests.cs @@ -9,7 +9,6 @@ using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.BackOffice; using Umbraco.Core.Configuration; -using Umbraco.Core.Configuration.Models; using Umbraco.Core.Models.Membership; using Umbraco.Net; using Umbraco.Web.Security; @@ -24,19 +23,18 @@ namespace Umbraco.Tests.Security const string v7Hash = "7Uob6fMTTxDIhWGebYiSxg==P+hgvWlXLbDd4cFLADn811KOaVI/9pg1PNvTuG5NklY="; const string plaintext = "4XxzH3s3&J"; - var passwordConfiguration = new UserPasswordConfigurationSettings - { - HashAlgorithmType = Constants.Security.AspNetUmbraco8PasswordHashAlgorithmName - }; + var mockPasswordConfiguration = new Mock(); var mockIpResolver = new Mock(); var mockUserStore = new Mock>(); var mockDataProtectionProvider = new Mock(); mockDataProtectionProvider.Setup(x => x.Create(It.IsAny())) .Returns(new Mock().Object); + mockPasswordConfiguration.Setup(x => x.HashAlgorithmType) + .Returns(Constants.Security.AspNetUmbraco8PasswordHashAlgorithmName); var userManager = BackOfficeOwinUserManager.Create( - passwordConfiguration, + mockPasswordConfiguration.Object, mockIpResolver.Object, mockUserStore.Object, null, diff --git a/src/Umbraco.Tests/TestHelpers/SettingsForTests.cs b/src/Umbraco.Tests/TestHelpers/SettingsForTests.cs index 6abe44d0fd..b58301287b 100644 --- a/src/Umbraco.Tests/TestHelpers/SettingsForTests.cs +++ b/src/Umbraco.Tests/TestHelpers/SettingsForTests.cs @@ -1,5 +1,4 @@ using Umbraco.Core.Configuration; -using Umbraco.Core.Configuration.Models; using Umbraco.Core.Configuration.UmbracoSettings; namespace Umbraco.Tests.TestHelpers @@ -8,7 +7,7 @@ namespace Umbraco.Tests.TestHelpers { private static Common.SettingsForTests _settingsForTests = new Common.SettingsForTests(); - public static IGlobalSettings GenerateMockGlobalSettings() => _settingsForTests.GenerateStubGlobalSettings(TestHelper.GetUmbracoVersion()); + public static IGlobalSettings GenerateMockGlobalSettings() => _settingsForTests.GenerateMockGlobalSettings(TestHelper.GetUmbracoVersion()); /// /// Returns generated settings which can be stubbed to return whatever values necessary @@ -46,7 +45,7 @@ namespace Umbraco.Tests.TestHelpers public static void Reset() => _settingsForTests.Reset(); - internal static GlobalSettings DefaultGlobalSettings => _settingsForTests.GetDefaultGlobalSettings(TestHelper.GetUmbracoVersion()); + internal static IGlobalSettings DefaultGlobalSettings => _settingsForTests.GetDefaultGlobalSettings(TestHelper.GetUmbracoVersion()); internal static IHostingSettings DefaultHostingSettings => _settingsForTests.DefaultHostingSettings; diff --git a/src/Umbraco.Tests/TestHelpers/TestHelper.cs b/src/Umbraco.Tests/TestHelpers/TestHelper.cs index 08b21dda8d..5512f50254 100644 --- a/src/Umbraco.Tests/TestHelpers/TestHelper.cs +++ b/src/Umbraco.Tests/TestHelpers/TestHelper.cs @@ -33,7 +33,6 @@ using Umbraco.Web; using Umbraco.Web.Hosting; using Umbraco.Web.Routing; using File = System.IO.File; -using CoreDebugSettings = Umbraco.Core.Configuration.Models.CoreDebugSettings; namespace Umbraco.Tests.TestHelpers { @@ -58,7 +57,7 @@ namespace Umbraco.Tests.TestHelpers public override IBackOfficeInfo GetBackOfficeInfo() => new AspNetBackOfficeInfo( - SettingsForTests.GenerateStubGlobalSettings(GetUmbracoVersion()), + SettingsForTests.GenerateMockGlobalSettings(GetUmbracoVersion()), TestHelper.IOHelper, Mock.Of(), SettingsForTests.GenerateMockWebRoutingSettings()); public override IHostingEnvironment GetHostingEnvironment() @@ -95,7 +94,7 @@ namespace Umbraco.Tests.TestHelpers public static IDbProviderFactoryCreator DbProviderFactoryCreator => _testHelperInternal.DbProviderFactoryCreator; public static IBulkSqlInsertProvider BulkSqlInsertProvider => _testHelperInternal.BulkSqlInsertProvider; public static IMarchal Marchal => _testHelperInternal.Marchal; - public static CoreDebugSettings CoreDebugSettings => _testHelperInternal.CoreDebugSettings; + public static ICoreDebugSettings CoreDebugSettings => _testHelperInternal.CoreDebugSettings; public static IIOHelper IOHelper => _testHelperInternal.IOHelper; diff --git a/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs b/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs index 24aa171c87..1b63bcc98d 100644 --- a/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs +++ b/src/Umbraco.Tests/TestHelpers/TestObjects-Mocks.cs @@ -8,7 +8,6 @@ using Moq; using Umbraco.Core; using Umbraco.Core.Composing; using Umbraco.Core.Configuration; -using Umbraco.Core.Configuration.Models; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Models; @@ -137,11 +136,10 @@ namespace Umbraco.Tests.TestHelpers return umbracoContextFactory.EnsureUmbracoContext().UmbracoContext; } - public GlobalSettings GetGlobalSettings() + public IGlobalSettings GetGlobalSettings() { return SettingsForTests.DefaultGlobalSettings; } - public IFileSystems GetFileSystemsMock() { var fileSystems = Mock.Of(); diff --git a/src/Umbraco.Tests/TestHelpers/TestObjects.cs b/src/Umbraco.Tests/TestHelpers/TestObjects.cs index 5077563e78..7e8914f78e 100644 --- a/src/Umbraco.Tests/TestHelpers/TestObjects.cs +++ b/src/Umbraco.Tests/TestHelpers/TestObjects.cs @@ -7,7 +7,6 @@ using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Composing; using Umbraco.Core.Configuration; -using Umbraco.Core.Configuration.Models; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Events; using Umbraco.Core.Hosting; @@ -96,7 +95,7 @@ namespace Umbraco.Tests.TestHelpers ILogger logger, IIOHelper ioHelper, IGlobalSettings globalSettings, - ContentSettings contentSettings, + IContentSettings contentSettings, IEventMessagesFactory eventMessagesFactory, UrlSegmentProviderCollection urlSegmentProviders, IUmbracoVersion umbracoVersion, diff --git a/src/Umbraco.Web/AppBuilderExtensions.cs b/src/Umbraco.Web/AppBuilderExtensions.cs index 2c4273b5a1..c8c6cbdf5c 100644 --- a/src/Umbraco.Web/AppBuilderExtensions.cs +++ b/src/Umbraco.Web/AppBuilderExtensions.cs @@ -3,7 +3,6 @@ using Microsoft.AspNet.SignalR; using Microsoft.Owin.Logging; using Owin; using Umbraco.Core.Configuration; -using Umbraco.Core.Configuration.Models; using Umbraco.Core.Hosting; using Umbraco.Core.IO; using Umbraco.Web.Composing; @@ -47,7 +46,7 @@ namespace Umbraco.Web /// The app builder. /// /// - public static IAppBuilder UseSignalR(this IAppBuilder app, GlobalSettings globalSettings, IHostingEnvironment hostingEnvironment) + public static IAppBuilder UseSignalR(this IAppBuilder app, IGlobalSettings globalSettings, IHostingEnvironment hostingEnvironment) { var umbracoPath = globalSettings.GetUmbracoMvcArea(hostingEnvironment); var signalrPath = HttpRuntime.AppDomainAppVirtualPath + umbracoPath + "/BackOffice/signalr"; diff --git a/src/Umbraco.Web/AspNet/AspNetBackOfficeInfo.cs b/src/Umbraco.Web/AspNet/AspNetBackOfficeInfo.cs index ab3f575d36..1e60fedeea 100644 --- a/src/Umbraco.Web/AspNet/AspNetBackOfficeInfo.cs +++ b/src/Umbraco.Web/AspNet/AspNetBackOfficeInfo.cs @@ -1,8 +1,6 @@ using System.Web; -using Microsoft.Extensions.Options; using Umbraco.Core; using Umbraco.Core.Configuration; -using Umbraco.Core.Configuration.Models; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.IO; using Umbraco.Core.Logging; @@ -11,17 +9,12 @@ namespace Umbraco.Web { public class AspNetBackOfficeInfo : IBackOfficeInfo { - private readonly GlobalSettings _globalSettings; + private readonly IGlobalSettings _globalSettings; private readonly IIOHelper _ioHelper; private readonly ILogger _logger; - private readonly WebRoutingSettings _webRoutingSettings; + private readonly IWebRoutingSettings _webRoutingSettings; - public AspNetBackOfficeInfo(IOptionsSnapshot globalSettings, IIOHelper ioHelper, ILogger logger, IOptionsSnapshot webRoutingSettings) - : this(globalSettings.Value, ioHelper, logger, webRoutingSettings.Value) - { - } - - public AspNetBackOfficeInfo(GlobalSettings globalSettings, IIOHelper ioHelper, ILogger logger, WebRoutingSettings webRoutingSettings) + public AspNetBackOfficeInfo(IGlobalSettings globalSettings, IIOHelper ioHelper, ILogger logger, IWebRoutingSettings webRoutingSettings) { _globalSettings = globalSettings; _ioHelper = ioHelper; diff --git a/src/Umbraco.Web/AspNet/AspNetHostingEnvironment.cs b/src/Umbraco.Web/AspNet/AspNetHostingEnvironment.cs index 2423c7802b..5e7324236a 100644 --- a/src/Umbraco.Web/AspNet/AspNetHostingEnvironment.cs +++ b/src/Umbraco.Web/AspNet/AspNetHostingEnvironment.cs @@ -2,27 +2,27 @@ using System; using System.Reflection; using System.Web; using System.Web.Hosting; -using Microsoft.Extensions.Options; using Umbraco.Core; using Umbraco.Core.Configuration; -using Umbraco.Core.Configuration.Models; using Umbraco.Core.Hosting; namespace Umbraco.Web.Hosting { public class AspNetHostingEnvironment : IHostingEnvironment { - private readonly HostingSettings _hostingSettings; + + private readonly IHostingSettings _hostingSettings; private string _localTempPath; - public AspNetHostingEnvironment(IOptionsSnapshot hostingSettings) + + public AspNetHostingEnvironment(IHostingSettings hostingSettings) { - _hostingSettings = hostingSettings.Value ?? throw new ArgumentNullException(nameof(hostingSettings)); + _hostingSettings = hostingSettings ?? throw new ArgumentNullException(nameof(hostingSettings)); SiteName = HostingEnvironment.SiteName; ApplicationId = HostingEnvironment.ApplicationID; // when we are not hosted (i.e. unit test or otherwise) we'll need to get the root path from the executing assembly ApplicationPhysicalPath = HostingEnvironment.ApplicationPhysicalPath ?? Assembly.GetExecutingAssembly().GetRootDirectorySafe(); - ApplicationVirtualPath = _hostingSettings.ApplicationVirtualPath?.EnsureStartsWith('/') + ApplicationVirtualPath = hostingSettings.ApplicationVirtualPath?.EnsureStartsWith('/') ?? HostingEnvironment.ApplicationVirtualPath?.EnsureStartsWith("/") ?? "/"; IISVersion = HttpRuntime.IISVersion; diff --git a/src/Umbraco.Web/AspNet/AspNetRequestAccessor.cs b/src/Umbraco.Web/AspNet/AspNetRequestAccessor.cs index 7e1e853716..aa2cba6949 100644 --- a/src/Umbraco.Web/AspNet/AspNetRequestAccessor.cs +++ b/src/Umbraco.Web/AspNet/AspNetRequestAccessor.cs @@ -1,7 +1,5 @@ using System; using System.Collections.Generic; -using Microsoft.Extensions.Options; -using Umbraco.Core.Configuration.Models; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Web.Routing; @@ -10,18 +8,20 @@ namespace Umbraco.Web.AspNet public class AspNetRequestAccessor : IRequestAccessor { private readonly IHttpContextAccessor _httpContextAccessor; - private readonly WebRoutingSettings _webRoutingSettings; + private readonly IWebRoutingSettings _webRoutingSettings; private readonly ISet _applicationUrls = new HashSet(); private Uri _currentApplicationUrl; - public AspNetRequestAccessor(IHttpContextAccessor httpContextAccessor, IOptionsSnapshot webRoutingSettings) + public AspNetRequestAccessor(IHttpContextAccessor httpContextAccessor, IWebRoutingSettings webRoutingSettings) { _httpContextAccessor = httpContextAccessor; - _webRoutingSettings = webRoutingSettings.Value; + _webRoutingSettings = webRoutingSettings; UmbracoModule.EndRequest += OnEndRequest; UmbracoModule.RouteAttempt += OnRouteAttempt; } + + public string GetRequestValue(string name) { return _httpContextAccessor.GetRequiredHttpContext().Request[name]; diff --git a/src/Umbraco.Web/Compose/AuditEventsComponent.cs b/src/Umbraco.Web/Compose/AuditEventsComponent.cs index ef81a35b1c..51c47233c7 100644 --- a/src/Umbraco.Web/Compose/AuditEventsComponent.cs +++ b/src/Umbraco.Web/Compose/AuditEventsComponent.cs @@ -11,8 +11,6 @@ using Umbraco.Net; using Umbraco.Core.Services; using Umbraco.Core.Services.Implement; using Umbraco.Extensions; -using Umbraco.Core.Configuration.Models; -using Microsoft.Extensions.Options; namespace Umbraco.Core.Compose { @@ -22,15 +20,15 @@ namespace Umbraco.Core.Compose private readonly IUserService _userService; private readonly IEntityService _entityService; private readonly IIpResolver _ipResolver; - private readonly GlobalSettings _globalSettings; + private readonly IGlobalSettings _globalSettings; - public AuditEventsComponent(IAuditService auditService, IUserService userService, IEntityService entityService, IIpResolver ipResolver, IOptionsSnapshot globalSettings) + public AuditEventsComponent(IAuditService auditService, IUserService userService, IEntityService entityService, IIpResolver ipResolver, IGlobalSettings globalSettings) { _auditService = auditService; _userService = userService; _entityService = entityService; _ipResolver = ipResolver; - _globalSettings = globalSettings.Value; + _globalSettings = globalSettings; } public void Initialize() @@ -51,7 +49,7 @@ namespace Umbraco.Core.Compose public void Terminate() { } - public static IUser UnknownUser(GlobalSettings globalSettings) => new User(globalSettings) { Id = Constants.Security.UnknownUserId, Name = Constants.Security.UnknownUserName, Email = "" }; + public static IUser UnknownUser(IGlobalSettings globalSettings) => new User(globalSettings) { Id = Constants.Security.UnknownUserId, Name = Constants.Security.UnknownUserName, Email = "" }; private IUser CurrentPerformingUser { diff --git a/src/Umbraco.Web/Compose/BackOfficeUserAuditEventsComponent.cs b/src/Umbraco.Web/Compose/BackOfficeUserAuditEventsComponent.cs index 2357a62eb8..dcb5fac32d 100644 --- a/src/Umbraco.Web/Compose/BackOfficeUserAuditEventsComponent.cs +++ b/src/Umbraco.Web/Compose/BackOfficeUserAuditEventsComponent.cs @@ -1,10 +1,8 @@ using System; -using Microsoft.Extensions.Options; using Umbraco.Core; using Umbraco.Core.Compose; using Umbraco.Core.Composing; using Umbraco.Core.Configuration; -using Umbraco.Core.Configuration.Models; using Umbraco.Core.Models.Membership; using Umbraco.Core.Services; using Umbraco.Web.Security; @@ -15,13 +13,13 @@ namespace Umbraco.Web.Compose { private readonly IAuditService _auditService; private readonly IUserService _userService; - private readonly GlobalSettings _globalSettings; + private readonly IGlobalSettings _globalSettings; - public BackOfficeUserAuditEventsComponent(IAuditService auditService, IUserService userService, IOptionsSnapshot globalSettings) + public BackOfficeUserAuditEventsComponent(IAuditService auditService, IUserService userService, IGlobalSettings globalSettings) { _auditService = auditService; _userService = userService; - _globalSettings = globalSettings.Value; + _globalSettings = globalSettings; } public void Initialize() diff --git a/src/Umbraco.Web/Editors/AuthenticationController.cs b/src/Umbraco.Web/Editors/AuthenticationController.cs index d919f04077..e4773a85d5 100644 --- a/src/Umbraco.Web/Editors/AuthenticationController.cs +++ b/src/Umbraco.Web/Editors/AuthenticationController.cs @@ -1,30 +1,35 @@ using System; -using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Http; +using System.Collections.Generic; +using System.Net.Mail; using System.Security.Principal; using System.Threading.Tasks; +using System.Web; using System.Web.Http; +using System.Web.Mvc; using Microsoft.AspNetCore.Identity; -using Microsoft.Extensions.Options; using Umbraco.Core; using Umbraco.Core.Cache; -using Umbraco.Core.Configuration; -using Umbraco.Core.Configuration.Models; -using Umbraco.Core.Hosting; -using Umbraco.Core.Logging; -using Umbraco.Core.Mapping; -using Umbraco.Core.Persistence; +using Umbraco.Core.Models; using Umbraco.Core.Services; using Umbraco.Web.Models; +using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Mvc; -using Umbraco.Web.Routing; using Umbraco.Web.Security; using Umbraco.Web.WebApi; using Umbraco.Web.WebApi.Filters; -using Constants = Umbraco.Core.Constants; +using Umbraco.Core.Configuration; +using Umbraco.Core.Logging; +using Umbraco.Core.Persistence; using IUser = Umbraco.Core.Models.Membership.IUser; +using Umbraco.Core.Mapping; +using Umbraco.Core.Configuration.UmbracoSettings; +using Umbraco.Core.Hosting; +using Umbraco.Extensions; +using Umbraco.Web.Routing; +using Constants = Umbraco.Core.Constants; namespace Umbraco.Web.Editors { @@ -39,16 +44,16 @@ namespace Umbraco.Web.Editors { private BackOfficeOwinUserManager _userManager; private BackOfficeSignInManager _signInManager; - private readonly UserPasswordConfigurationSettings _passwordConfiguration; + private readonly IUserPasswordConfiguration _passwordConfiguration; private readonly IHostingEnvironment _hostingEnvironment; private readonly IRuntimeState _runtimeState; - private readonly SecuritySettings _securitySettings; + private readonly ISecuritySettings _securitySettings; private readonly IRequestAccessor _requestAccessor; private readonly IEmailSender _emailSender; public AuthenticationController( - IOptionsSnapshot passwordConfiguration, - IOptionsSnapshot globalSettings, + IUserPasswordConfiguration passwordConfiguration, + IGlobalSettings globalSettings, IHostingEnvironment hostingEnvironment, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, @@ -57,16 +62,16 @@ namespace Umbraco.Web.Editors IProfilingLogger logger, IRuntimeState runtimeState, UmbracoMapper umbracoMapper, - IOptionsSnapshot securitySettings, + ISecuritySettings securitySettings, IPublishedUrlProvider publishedUrlProvider, IRequestAccessor requestAccessor, IEmailSender emailSender) : base(globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoMapper, publishedUrlProvider) { - _passwordConfiguration = passwordConfiguration.Value ?? throw new ArgumentNullException(nameof(passwordConfiguration)); + _passwordConfiguration = passwordConfiguration ?? throw new ArgumentNullException(nameof(passwordConfiguration)); _hostingEnvironment = hostingEnvironment ?? throw new ArgumentNullException(nameof(hostingEnvironment)); _runtimeState = runtimeState ?? throw new ArgumentNullException(nameof(runtimeState)); - _securitySettings = securitySettings.Value ?? throw new ArgumentNullException(nameof(securitySettings)); + _securitySettings = securitySettings ?? throw new ArgumentNullException(nameof(securitySettings)); _requestAccessor = requestAccessor ?? throw new ArgumentNullException(nameof(securitySettings)); _emailSender = emailSender; } diff --git a/src/Umbraco.Web/Editors/BackOfficeController.cs b/src/Umbraco.Web/Editors/BackOfficeController.cs index de94f42007..b963871a58 100644 --- a/src/Umbraco.Web/Editors/BackOfficeController.cs +++ b/src/Umbraco.Web/Editors/BackOfficeController.cs @@ -4,21 +4,19 @@ using System.Threading.Tasks; using System.Web; using System.Web.Mvc; using Microsoft.AspNetCore.Identity; -using Microsoft.Extensions.Options; using Microsoft.Owin.Security; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Configuration; -using Umbraco.Core.Configuration.Models; -using Umbraco.Core.Configuration.UmbracoSettings; -using Umbraco.Core.Hosting; using Umbraco.Core.Logging; +using Umbraco.Web.Mvc; using Umbraco.Core.Services; using Umbraco.Web.Features; -using Umbraco.Web.Mvc; using Umbraco.Web.Security; -using BackOfficeIdentityUser = Umbraco.Core.BackOffice.BackOfficeIdentityUser; using Constants = Umbraco.Core.Constants; +using Umbraco.Core.Configuration.UmbracoSettings; +using Umbraco.Core.Hosting; +using BackOfficeIdentityUser = Umbraco.Core.BackOffice.BackOfficeIdentityUser; namespace Umbraco.Web.Editors { @@ -36,12 +34,12 @@ namespace Umbraco.Web.Editors private readonly IUmbracoVersion _umbracoVersion; private readonly IContentSettings _contentSettings; private readonly IHostingEnvironment _hostingEnvironment; - private readonly RuntimeSettings _runtimeSettings; - private readonly SecuritySettings _securitySettings; + private readonly IRuntimeSettings _runtimeSettings; + private readonly ISecuritySettings _securitySettings; public BackOfficeController( UmbracoFeatures features, - IOptionsSnapshot globalSettings, + IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ServiceContext services, AppCaches appCaches, @@ -49,16 +47,17 @@ namespace Umbraco.Web.Editors IUmbracoVersion umbracoVersion, IContentSettings contentSettings, IHostingEnvironment hostingEnvironment, - IOptionsSnapshot runtimeSettings, - IOptionsSnapshot securitySettings) + IRuntimeSettings settings, + ISecuritySettings securitySettings) : base(globalSettings, umbracoContextAccessor, services, appCaches, profilingLogger) + { _features = features; _umbracoVersion = umbracoVersion; _contentSettings = contentSettings ?? throw new ArgumentNullException(nameof(contentSettings)); _hostingEnvironment = hostingEnvironment; - _runtimeSettings = runtimeSettings.Value; - _securitySettings = securitySettings.Value; + _runtimeSettings = settings; + _securitySettings = securitySettings; } protected BackOfficeSignInManager SignInManager => _signInManager ?? (_signInManager = OwinContext.GetBackOfficeSignInManager()); diff --git a/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs b/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs index 4246ffb2ec..454338112c 100644 --- a/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs +++ b/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs @@ -5,18 +5,18 @@ using System.Linq; using System.Runtime.Serialization; using System.Web; using System.Web.Mvc; -using Microsoft.Extensions.Options; using Umbraco.Core; using Umbraco.Core.Configuration; -using Umbraco.Core.Configuration.Models; +using Umbraco.Web.Features; +using Umbraco.Web.HealthCheck; +using Umbraco.Web.Models.ContentEditing; +using Umbraco.Web.Mvc; +using Umbraco.Web.Trees; +using Constants = Umbraco.Core.Constants; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Hosting; using Umbraco.Core.WebAssets; -using Umbraco.Web.Features; -using Umbraco.Web.Mvc; using Umbraco.Web.Security; -using Umbraco.Web.Trees; -using Constants = Umbraco.Core.Constants; namespace Umbraco.Web.Editors { @@ -28,39 +28,39 @@ namespace Umbraco.Web.Editors private readonly UrlHelper _urlHelper; private readonly IRuntimeState _runtimeState; private readonly UmbracoFeatures _features; - private readonly GlobalSettings _globalSettings; + private readonly IGlobalSettings _globalSettings; private readonly IUmbracoVersion _umbracoVersion; private readonly IContentSettings _contentSettings; private readonly TreeCollection _treeCollection; private readonly IHttpContextAccessor _httpContextAccessor; private readonly IHostingEnvironment _hostingEnvironment; - private readonly RuntimeSettings _runtimeSettings; - private readonly SecuritySettings _securitySettings; + private readonly IRuntimeSettings _settings; + private readonly ISecuritySettings _securitySettings; private readonly IRuntimeMinifier _runtimeMinifier; internal BackOfficeServerVariables( UrlHelper urlHelper, IRuntimeState runtimeState, UmbracoFeatures features, - IOptionsSnapshot globalSettings, + IGlobalSettings globalSettings, IUmbracoVersion umbracoVersion, IContentSettings contentSettings, TreeCollection treeCollection, IHostingEnvironment hostingEnvironment, - IOptionsSnapshot runtimeSettings, - IOptionsSnapshot securitySettings, + IRuntimeSettings settings, + ISecuritySettings securitySettings, IRuntimeMinifier runtimeMinifier) { _urlHelper = urlHelper; _runtimeState = runtimeState; _features = features; - _globalSettings = globalSettings.Value; + _globalSettings = globalSettings; _umbracoVersion = umbracoVersion; _contentSettings = contentSettings ?? throw new ArgumentNullException(nameof(contentSettings)); _treeCollection = treeCollection ?? throw new ArgumentNullException(nameof(treeCollection)); _hostingEnvironment = hostingEnvironment; - _runtimeSettings = runtimeSettings.Value; - _securitySettings = securitySettings.Value; + _settings = settings; + _securitySettings = securitySettings; _runtimeMinifier = runtimeMinifier; } @@ -288,7 +288,7 @@ namespace Umbraco.Web.Editors private string GetMaxRequestLength() { - return _runtimeSettings.MaxRequestLength.HasValue ? _runtimeSettings.MaxRequestLength.Value.ToString() : string.Empty; + return _settings.MaxRequestLength.HasValue ? _settings.MaxRequestLength.Value.ToString() : string.Empty; } } } diff --git a/src/Umbraco.Web/Editors/UmbracoAuthorizedJsonController.cs b/src/Umbraco.Web/Editors/UmbracoAuthorizedJsonController.cs index f0f7e50be5..64aba378f4 100644 --- a/src/Umbraco.Web/Editors/UmbracoAuthorizedJsonController.cs +++ b/src/Umbraco.Web/Editors/UmbracoAuthorizedJsonController.cs @@ -1,9 +1,7 @@ using System; -using Microsoft.Extensions.Options; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Configuration; -using Umbraco.Core.Configuration.Models; using Umbraco.Core.Logging; using Umbraco.Core.Mapping; using Umbraco.Core.Persistence; @@ -33,7 +31,7 @@ namespace Umbraco.Web.Editors } protected UmbracoAuthorizedJsonController( - IOptionsSnapshot globalSettings, + IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, diff --git a/src/Umbraco.Web/HtmlHelperRenderExtensions.cs b/src/Umbraco.Web/HtmlHelperRenderExtensions.cs index d6c4451efb..6fe069fc59 100644 --- a/src/Umbraco.Web/HtmlHelperRenderExtensions.cs +++ b/src/Umbraco.Web/HtmlHelperRenderExtensions.cs @@ -10,7 +10,6 @@ using System.Web.Mvc.Html; using System.Web.Routing; using Umbraco.Core; using Umbraco.Core.Configuration; -using Umbraco.Core.Configuration.Models; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.IO; using Umbraco.Web.Mvc; @@ -61,18 +60,18 @@ namespace Umbraco.Web /// /// See: http://issues.umbraco.org/issue/U4-1614 /// - public static MvcHtmlString PreviewBadge(this HtmlHelper helper, IHttpContextAccessor httpContextAccessor, GlobalSettings globalSettings, IIOHelper ioHelper, IContentSettings contentSettings) + public static MvcHtmlString PreviewBadge(this HtmlHelper helper, IHttpContextAccessor httpContextAccessor, IGlobalSettings globalSettings, IIOHelper ioHelper, IContentSettings contentSettings) { if (Current.UmbracoContext.InPreviewMode) { var htmlBadge = - string.Format(contentSettings.PreviewBadge, + String.Format(contentSettings.PreviewBadge, ioHelper.ResolveUrl(globalSettings.UmbracoPath), WebUtility.UrlEncode(httpContextAccessor.GetRequiredHttpContext().Request.Path), Current.UmbracoContext.PublishedRequest.PublishedContent.Id); return new MvcHtmlString(htmlBadge); } - return new MvcHtmlString(string.Empty); + return new MvcHtmlString(""); } diff --git a/src/Umbraco.Web/Mvc/AreaRegistrationExtensions.cs b/src/Umbraco.Web/Mvc/AreaRegistrationExtensions.cs index e25ab4a69e..118c53a7f0 100644 --- a/src/Umbraco.Web/Mvc/AreaRegistrationExtensions.cs +++ b/src/Umbraco.Web/Mvc/AreaRegistrationExtensions.cs @@ -6,8 +6,10 @@ using System.Web.Routing; using System.Web.SessionState; using Umbraco.Core; using Umbraco.Core.Configuration; -using Umbraco.Core.Configuration.Models; +using Umbraco.Core.Exceptions; using Umbraco.Core.Hosting; +using Umbraco.Core.IO; +using Umbraco.Web.Composing; using Umbraco.Web.WebApi; namespace Umbraco.Web.Mvc @@ -42,7 +44,7 @@ namespace Umbraco.Web.Mvc /// /// internal static Route RouteControllerPlugin(this AreaRegistration area, - GlobalSettings globalSettings, IHostingEnvironment hostingEnvironment, + IGlobalSettings globalSettings, IHostingEnvironment hostingEnvironment, string controllerName, Type controllerType, RouteCollection routes, string controllerSuffixName, string defaultAction, object defaultId, string umbracoTokenValue = "backoffice", diff --git a/src/Umbraco.Web/Mvc/BackOfficeArea.cs b/src/Umbraco.Web/Mvc/BackOfficeArea.cs index 2037d37914..156a896bb5 100644 --- a/src/Umbraco.Web/Mvc/BackOfficeArea.cs +++ b/src/Umbraco.Web/Mvc/BackOfficeArea.cs @@ -1,8 +1,8 @@ using System.Web.Mvc; -using Microsoft.Extensions.Options; +using Umbraco.Web.Composing; using Umbraco.Core.Configuration; -using Umbraco.Core.Configuration.Models; using Umbraco.Core.Hosting; +using Umbraco.Core.IO; using Umbraco.Web.Editors; namespace Umbraco.Web.Mvc @@ -10,15 +10,10 @@ namespace Umbraco.Web.Mvc // TODO: This has been ported to netcore, can be removed internal class BackOfficeArea : AreaRegistration { - private readonly GlobalSettings _globalSettings; + private readonly IGlobalSettings _globalSettings; private readonly IHostingEnvironment _hostingEnvironment; - public BackOfficeArea(IOptionsSnapshot globalSettings, IHostingEnvironment hostingEnvironment) - : this(globalSettings.Value, hostingEnvironment) - { - } - - public BackOfficeArea(GlobalSettings globalSettings, IHostingEnvironment hostingEnvironment) + public BackOfficeArea(IGlobalSettings globalSettings, IHostingEnvironment hostingEnvironment) { _globalSettings = globalSettings; _hostingEnvironment = hostingEnvironment; diff --git a/src/Umbraco.Web/Mvc/PluginControllerArea.cs b/src/Umbraco.Web/Mvc/PluginControllerArea.cs index bf2d24086d..838e304847 100644 --- a/src/Umbraco.Web/Mvc/PluginControllerArea.cs +++ b/src/Umbraco.Web/Mvc/PluginControllerArea.cs @@ -9,8 +9,6 @@ using Umbraco.Core.Composing; using Umbraco.Core.Hosting; using Umbraco.Core.IO; using Umbraco.Web.WebApi; -using Umbraco.Core.Configuration.Models; -using Microsoft.Extensions.Options; namespace Umbraco.Web.Mvc { @@ -19,7 +17,7 @@ namespace Umbraco.Web.Mvc /// internal class PluginControllerArea : AreaRegistration { - private readonly GlobalSettings _globalSettings; + private readonly IGlobalSettings _globalSettings; private readonly IHostingEnvironment _hostingEnvironment; private readonly IEnumerable _surfaceControllers; private readonly IEnumerable _apiControllers; @@ -32,12 +30,7 @@ namespace Umbraco.Web.Mvc /// /// /// - public PluginControllerArea(IOptionsSnapshot globalSettings, IHostingEnvironment hostingEnvironment, IEnumerable pluginControllers) - : this(globalSettings.Value, hostingEnvironment, pluginControllers) - { - } - - public PluginControllerArea(GlobalSettings globalSettings, IHostingEnvironment hostingEnvironment, IEnumerable pluginControllers) + public PluginControllerArea(IGlobalSettings globalSettings, IHostingEnvironment hostingEnvironment, IEnumerable pluginControllers) { _globalSettings = globalSettings; _hostingEnvironment = hostingEnvironment; @@ -48,7 +41,7 @@ namespace Umbraco.Web.Mvc throw new InvalidOperationException("Cannot create a PluginControllerArea unless all plugin controllers assigned have a PluginControllerAttribute assigned"); } _areaName = controllers.First().AreaName; - foreach (var c in controllers) + foreach(var c in controllers) { if (c.AreaName != _areaName) { diff --git a/src/Umbraco.Web/Mvc/RenderMvcController.cs b/src/Umbraco.Web/Mvc/RenderMvcController.cs index 1e6f5a00c3..7286f52c64 100644 --- a/src/Umbraco.Web/Mvc/RenderMvcController.cs +++ b/src/Umbraco.Web/Mvc/RenderMvcController.cs @@ -1,8 +1,7 @@ using System; using System.Web.Mvc; -using Microsoft.Extensions.Options; using Umbraco.Core.Cache; -using Umbraco.Core.Configuration.Models; +using Umbraco.Core.Configuration; using Umbraco.Core.Logging; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Services; @@ -11,6 +10,7 @@ using Umbraco.Web.Routing; namespace Umbraco.Web.Mvc { + /// /// Represents the default front-end rendering controller. /// @@ -25,7 +25,7 @@ namespace Umbraco.Web.Mvc ActionInvoker = new RenderActionInvoker(); } - public RenderMvcController(IOptionsSnapshot globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ServiceContext services, AppCaches appCaches, IProfilingLogger profilingLogger) + public RenderMvcController(IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ServiceContext services, AppCaches appCaches, IProfilingLogger profilingLogger) : base(globalSettings, umbracoContextAccessor, services, appCaches, profilingLogger) { ActionInvoker = new RenderActionInvoker(); diff --git a/src/Umbraco.Web/Mvc/RenderNoContentController.cs b/src/Umbraco.Web/Mvc/RenderNoContentController.cs index 1f9a24212b..9334591fbb 100644 --- a/src/Umbraco.Web/Mvc/RenderNoContentController.cs +++ b/src/Umbraco.Web/Mvc/RenderNoContentController.cs @@ -1,8 +1,6 @@ using System; using System.Web.Mvc; -using Microsoft.Extensions.Options; using Umbraco.Core.Configuration; -using Umbraco.Core.Configuration.Models; using Umbraco.Core.IO; using Umbraco.Web.Models; @@ -12,13 +10,13 @@ namespace Umbraco.Web.Mvc { private readonly IUmbracoContextAccessor _umbracoContextAccessor; private readonly IIOHelper _ioHelper; - private readonly GlobalSettings _globalSettings; + private readonly IGlobalSettings _globalSettings; - public RenderNoContentController(IUmbracoContextAccessor umbracoContextAccessor, IIOHelper ioHelper, IOptionsSnapshot globalSettings) + public RenderNoContentController(IUmbracoContextAccessor umbracoContextAccessor, IIOHelper ioHelper, IGlobalSettings globalSettings) { _umbracoContextAccessor = umbracoContextAccessor ?? throw new ArgumentNullException(nameof(umbracoContextAccessor)); _ioHelper = ioHelper ?? throw new ArgumentNullException(nameof(ioHelper)); - _globalSettings = globalSettings.Value ?? throw new ArgumentNullException(nameof(globalSettings)); + _globalSettings = globalSettings ?? throw new ArgumentNullException(nameof(globalSettings)); } public ActionResult Index() diff --git a/src/Umbraco.Web/Mvc/UmbracoAuthorizedController.cs b/src/Umbraco.Web/Mvc/UmbracoAuthorizedController.cs index f774eb8a4e..0724cd138d 100644 --- a/src/Umbraco.Web/Mvc/UmbracoAuthorizedController.cs +++ b/src/Umbraco.Web/Mvc/UmbracoAuthorizedController.cs @@ -1,7 +1,5 @@ -using Microsoft.Extensions.Options; -using Umbraco.Core.Cache; +using Umbraco.Core.Cache; using Umbraco.Core.Configuration; -using Umbraco.Core.Configuration.Models; using Umbraco.Core.Logging; using Umbraco.Core.Persistence; using Umbraco.Core.Services; @@ -23,7 +21,7 @@ namespace Umbraco.Web.Mvc { } - protected UmbracoAuthorizedController(IOptionsSnapshot globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ServiceContext services, AppCaches appCaches, IProfilingLogger profilingLogger) + protected UmbracoAuthorizedController(IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ServiceContext services, AppCaches appCaches, IProfilingLogger profilingLogger) : base(globalSettings, umbracoContextAccessor, services, appCaches, profilingLogger) { } diff --git a/src/Umbraco.Web/Mvc/UmbracoController.cs b/src/Umbraco.Web/Mvc/UmbracoController.cs index ff0ac170fb..9cfd93ba9d 100644 --- a/src/Umbraco.Web/Mvc/UmbracoController.cs +++ b/src/Umbraco.Web/Mvc/UmbracoController.cs @@ -1,14 +1,13 @@ using System; using System.Web; using System.Web.Mvc; -using Microsoft.Extensions.Options; using Microsoft.Owin; -using Umbraco.Core; using Umbraco.Core.Cache; -using Umbraco.Core.Configuration.Models; -using Umbraco.Core.Logging; -using Umbraco.Core.Services; using Umbraco.Web.Composing; +using Umbraco.Core.Configuration; +using Umbraco.Core.Logging; +using Umbraco.Core; +using Umbraco.Core.Services; using Umbraco.Web.Security; namespace Umbraco.Web.Mvc @@ -22,9 +21,9 @@ namespace Umbraco.Web.Mvc internal Guid InstanceId { get; } = Guid.NewGuid(); /// - /// Gets the global settings from configuration. + /// Gets or sets the Umbraco context. /// - public GlobalSettings GlobalSettings { get; } + public IGlobalSettings GlobalSettings { get; } /// /// Gets the Umbraco context. @@ -70,7 +69,7 @@ namespace Umbraco.Web.Mvc protected UmbracoController() : this( - Current.Factory.GetInstance>(), + Current.Factory.GetInstance(), Current.Factory.GetInstance(), Current.Factory.GetInstance(), Current.Factory.GetInstance(), @@ -79,9 +78,9 @@ namespace Umbraco.Web.Mvc { } - protected UmbracoController(IOptionsSnapshot globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ServiceContext services, AppCaches appCaches, IProfilingLogger profilingLogger) + protected UmbracoController(IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ServiceContext services, AppCaches appCaches, IProfilingLogger profilingLogger) { - GlobalSettings = globalSettings.Value; + GlobalSettings = globalSettings; UmbracoContextAccessor = umbracoContextAccessor; Services = services; AppCaches = appCaches; diff --git a/src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs b/src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs index b9c31388a2..a687e7c9cd 100644 --- a/src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs +++ b/src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs @@ -3,11 +3,9 @@ using System.Text; using System.Web; using System.Web.Mvc; using System.Web.WebPages; -using Microsoft.Extensions.Options; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Configuration; -using Umbraco.Core.Configuration.Models; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Services; @@ -24,8 +22,8 @@ namespace Umbraco.Web.Mvc /// public abstract class UmbracoViewPage : WebViewPage { - private readonly GlobalSettings _globalSettings; - private readonly ContentSettings _contentSettings; + private readonly IGlobalSettings _globalSettings; + private readonly IContentSettings _contentSettings; private IUmbracoContext _umbracoContext; private UmbracoHelper _helper; @@ -107,18 +105,18 @@ namespace Umbraco.Web.Mvc : this( Current.Factory.GetInstance(), Current.Factory.GetInstance(), - Current.Factory.GetInstance>(), - Current.Factory.GetInstance>() + Current.Factory.GetInstance(), + Current.Factory.GetInstance() ) { } - protected UmbracoViewPage(ServiceContext services, AppCaches appCaches, IOptionsSnapshot globalSettings, IOptionsSnapshot contentSettings) + protected UmbracoViewPage(ServiceContext services, AppCaches appCaches, IGlobalSettings globalSettings, IContentSettings contentSettings) { Services = services; AppCaches = appCaches; - _globalSettings = globalSettings.Value ?? throw new ArgumentNullException(nameof(globalSettings)); - _contentSettings = contentSettings.Value ?? throw new ArgumentNullException(nameof(contentSettings)); + _globalSettings = globalSettings ?? throw new ArgumentNullException(nameof(globalSettings)); + _contentSettings = contentSettings ?? throw new ArgumentNullException(nameof(contentSettings)); } // view logic below: diff --git a/src/Umbraco.Web/RoutableDocumentFilter.cs b/src/Umbraco.Web/RoutableDocumentFilter.cs index 5f5c832d1f..43e47a39b3 100644 --- a/src/Umbraco.Web/RoutableDocumentFilter.cs +++ b/src/Umbraco.Web/RoutableDocumentFilter.cs @@ -1,17 +1,16 @@ using System; -using System.Collections.Concurrent; -using System.Collections.Generic; using System.IO; -using System.Linq; -using System.Threading; using System.Web; using System.Web.Routing; -using Microsoft.Extensions.Options; using Umbraco.Core; -using Umbraco.Core.Collections; using Umbraco.Core.Configuration; -using Umbraco.Core.Configuration.Models; +using System.Threading; +using System.Collections.Generic; +using System.Linq; +using System.Collections.Concurrent; +using Umbraco.Core.Collections; using Umbraco.Core.IO; +using Umbraco.Web.Composing; namespace Umbraco.Web { @@ -23,20 +22,20 @@ namespace Umbraco.Web /// public sealed class RoutableDocumentFilter { + public RoutableDocumentFilter(IGlobalSettings globalSettings, IIOHelper ioHelper) + { + _globalSettings = globalSettings; + _ioHelper = ioHelper; + } + private static readonly ConcurrentDictionary RouteChecks = new ConcurrentDictionary(); - private readonly GlobalSettings _globalSettings; + private readonly IGlobalSettings _globalSettings; private readonly IIOHelper _ioHelper; private object _locker = new object(); private bool _isInit = false; private int? _routeCount; private HashSet _reservedList; - public RoutableDocumentFilter(IOptionsSnapshot globalSettings, IIOHelper ioHelper) - { - _globalSettings = globalSettings.Value; - _ioHelper = ioHelper; - } - /// /// Checks if the request is a document request (i.e. one that the module should handle) /// diff --git a/src/Umbraco.Web/Runtime/WebInitialComponent.cs b/src/Umbraco.Web/Runtime/WebInitialComponent.cs index 88c08cd937..dbd0a1fb3a 100644 --- a/src/Umbraco.Web/Runtime/WebInitialComponent.cs +++ b/src/Umbraco.Web/Runtime/WebInitialComponent.cs @@ -17,8 +17,6 @@ using Umbraco.Web.WebApi; using Constants = Umbraco.Core.Constants; using Current = Umbraco.Web.Composing.Current; -using Umbraco.Core.Configuration.Models; -using Microsoft.Extensions.Options; namespace Umbraco.Web.Runtime { @@ -27,7 +25,7 @@ namespace Umbraco.Web.Runtime private readonly IUmbracoContextAccessor _umbracoContextAccessor; private readonly SurfaceControllerTypeCollection _surfaceControllerTypes; private readonly UmbracoApiControllerTypeCollection _apiControllerTypes; - private readonly GlobalSettings _globalSettings; + private readonly IGlobalSettings _globalSettings; private readonly IHostingEnvironment _hostingEnvironment; private readonly IShortStringHelper _shortStringHelper; @@ -35,14 +33,14 @@ namespace Umbraco.Web.Runtime IUmbracoContextAccessor umbracoContextAccessor, SurfaceControllerTypeCollection surfaceControllerTypes, UmbracoApiControllerTypeCollection apiControllerTypes, - IOptionsSnapshot globalSettings, + IGlobalSettings globalSettings, IHostingEnvironment hostingEnvironment, IShortStringHelper shortStringHelper) { _umbracoContextAccessor = umbracoContextAccessor; _surfaceControllerTypes = surfaceControllerTypes; _apiControllerTypes = apiControllerTypes; - _globalSettings = globalSettings.Value; + _globalSettings = globalSettings; _hostingEnvironment = hostingEnvironment; _shortStringHelper = shortStringHelper; } @@ -113,7 +111,7 @@ namespace Umbraco.Web.Runtime // internal for tests internal static void CreateRoutes( IUmbracoContextAccessor umbracoContextAccessor, - GlobalSettings globalSettings, + IGlobalSettings globalSettings, IShortStringHelper shortStringHelper, SurfaceControllerTypeCollection surfaceControllerTypes, UmbracoApiControllerTypeCollection apiControllerTypes, @@ -151,7 +149,7 @@ namespace Umbraco.Web.Runtime } private static void RoutePluginControllers( - GlobalSettings globalSettings, + IGlobalSettings globalSettings, SurfaceControllerTypeCollection surfaceControllerTypes, UmbracoApiControllerTypeCollection apiControllerTypes, IHostingEnvironment hostingEnvironment) diff --git a/src/Umbraco.Web/Security/AppBuilderExtensions.cs b/src/Umbraco.Web/Security/AppBuilderExtensions.cs index 885baaab79..ac5434aa4e 100644 --- a/src/Umbraco.Web/Security/AppBuilderExtensions.cs +++ b/src/Umbraco.Web/Security/AppBuilderExtensions.cs @@ -8,7 +8,6 @@ using Owin; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Configuration; -using Umbraco.Core.Configuration.Models; using Umbraco.Core.Hosting; using Umbraco.Web.Composing; using Constants = Umbraco.Core.Constants; @@ -35,7 +34,7 @@ namespace Umbraco.Web.Security /// /// By default this will be configured to execute on PipelineStage.Authenticate /// - public static IAppBuilder UseUmbracoBackOfficeExternalCookieAuthentication(this IAppBuilder app, IUmbracoContextAccessor umbracoContextAccessor, IRuntimeState runtimeState, GlobalSettings globalSettings, IHostingEnvironment hostingEnvironment, IRequestCache requestCache) + public static IAppBuilder UseUmbracoBackOfficeExternalCookieAuthentication(this IAppBuilder app, IUmbracoContextAccessor umbracoContextAccessor, IRuntimeState runtimeState,IGlobalSettings globalSettings, IHostingEnvironment hostingEnvironment, IRequestCache requestCache) { return app.UseUmbracoBackOfficeExternalCookieAuthentication(umbracoContextAccessor, runtimeState, globalSettings, hostingEnvironment, requestCache, PipelineStage.Authenticate); } @@ -54,7 +53,7 @@ namespace Umbraco.Web.Security /// public static IAppBuilder UseUmbracoBackOfficeExternalCookieAuthentication(this IAppBuilder app, IUmbracoContextAccessor umbracoContextAccessor, IRuntimeState runtimeState, - GlobalSettings globalSettings, IHostingEnvironment hostingEnvironment, IRequestCache requestCache, PipelineStage stage) + IGlobalSettings globalSettings, IHostingEnvironment hostingEnvironment, IRequestCache requestCache, PipelineStage stage) { if (app == null) throw new ArgumentNullException(nameof(app)); if (runtimeState == null) throw new ArgumentNullException(nameof(runtimeState)); diff --git a/src/Umbraco.Web/Security/BackOfficeCookieAuthenticationProvider.cs b/src/Umbraco.Web/Security/BackOfficeCookieAuthenticationProvider.cs index beb79d3e98..26b85d6c39 100644 --- a/src/Umbraco.Web/Security/BackOfficeCookieAuthenticationProvider.cs +++ b/src/Umbraco.Web/Security/BackOfficeCookieAuthenticationProvider.cs @@ -1,10 +1,15 @@ -using Microsoft.Extensions.Options; +using System; +using System.Security.Claims; +using System.Threading.Tasks; +using Microsoft.Owin; using Microsoft.Owin.Security.Cookies; using Umbraco.Core; +using Umbraco.Core.BackOffice; using Umbraco.Core.Configuration; -using Umbraco.Core.Configuration.Models; -using Umbraco.Core.Hosting; using Umbraco.Core.Services; +using Umbraco.Core.Configuration.UmbracoSettings; +using Umbraco.Core.Hosting; +using Umbraco.Core.Security; namespace Umbraco.Web.Security { @@ -14,27 +19,26 @@ namespace Umbraco.Web.Security { private readonly IUserService _userService; private readonly IRuntimeState _runtimeState; - private readonly GlobalSettings _globalSettings; + private readonly IGlobalSettings _globalSettings; private readonly IHostingEnvironment _hostingEnvironment; - private readonly SecuritySettings _securitySettings; + private readonly ISecuritySettings _securitySettings; - public BackOfficeCookieAuthenticationProvider( - IUserService userService, - IRuntimeState runtimeState, - IOptionsSnapshot globalSettings, - IHostingEnvironment hostingEnvironment, - IOptionsSnapshot securitySettings) + public BackOfficeCookieAuthenticationProvider(IUserService userService, IRuntimeState runtimeState, IGlobalSettings globalSettings, IHostingEnvironment hostingEnvironment, ISecuritySettings securitySettings) { _userService = userService; _runtimeState = runtimeState; - _globalSettings = globalSettings.Value; + _globalSettings = globalSettings; _hostingEnvironment = hostingEnvironment; - _securitySettings = securitySettings.Value; + _securitySettings = securitySettings; } public override void ResponseSignOut(CookieResponseSignOutContext context) - { + { + } + + + } } diff --git a/src/Umbraco.Web/Security/BackOfficeOwinUserManager.cs b/src/Umbraco.Web/Security/BackOfficeOwinUserManager.cs index 5464902bb3..771c3239b6 100644 --- a/src/Umbraco.Web/Security/BackOfficeOwinUserManager.cs +++ b/src/Umbraco.Web/Security/BackOfficeOwinUserManager.cs @@ -8,7 +8,6 @@ using Microsoft.Owin.Security.DataProtection; using Umbraco.Core; using Umbraco.Core.BackOffice; using Umbraco.Core.Configuration; -using Umbraco.Core.Configuration.Models; using Umbraco.Core.Mapping; using Umbraco.Core.Security; using Umbraco.Core.Services; @@ -21,7 +20,7 @@ namespace Umbraco.Web.Security public const string OwinMarkerKey = "Umbraco.Web.Security.Identity.BackOfficeUserManagerMarker"; public BackOfficeOwinUserManager( - IOptions passwordConfiguration, + IUserPasswordConfiguration passwordConfiguration, IIpResolver ipResolver, IUserStore store, IOptions optionsAccessor, @@ -33,7 +32,7 @@ namespace Umbraco.Web.Security ILogger> logger) : base(ipResolver, store, optionsAccessor, null, userValidators, passwordValidators, keyNormalizer, errors, null, logger, passwordConfiguration) { - PasswordConfiguration = passwordConfiguration.Value; + PasswordConfiguration = passwordConfiguration; InitUserManager(this, dataProtectionProvider); } @@ -46,9 +45,9 @@ namespace Umbraco.Web.Security IUserService userService, IEntityService entityService, IExternalLoginService externalLoginService, - GlobalSettings globalSettings, + IGlobalSettings globalSettings, UmbracoMapper mapper, - UserPasswordConfigurationSettings passwordConfiguration, + IUserPasswordConfiguration passwordConfiguration, IIpResolver ipResolver, BackOfficeIdentityErrorDescriber errors, IDataProtectionProvider dataProtectionProvider, @@ -69,7 +68,7 @@ namespace Umbraco.Web.Security /// Creates a BackOfficeUserManager instance with all default options and a custom BackOfficeUserManager instance /// public static BackOfficeOwinUserManager Create( - UserPasswordConfigurationSettings passwordConfiguration, + IUserPasswordConfiguration passwordConfiguration, IIpResolver ipResolver, IUserStore customUserStore, BackOfficeIdentityErrorDescriber errors, @@ -104,7 +103,7 @@ namespace Umbraco.Web.Security options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromDays(30); return new BackOfficeOwinUserManager( - new OptionsWrapper(passwordConfiguration), + passwordConfiguration, ipResolver, customUserStore, new OptionsWrapper(options), diff --git a/src/Umbraco.Web/Security/BackOfficeSignInManager.cs b/src/Umbraco.Web/Security/BackOfficeSignInManager.cs index 01ed3ae30e..021adaed97 100644 --- a/src/Umbraco.Web/Security/BackOfficeSignInManager.cs +++ b/src/Umbraco.Web/Security/BackOfficeSignInManager.cs @@ -11,7 +11,6 @@ using Umbraco.Core; using Umbraco.Core.BackOffice; using Umbraco.Core.Configuration; using Umbraco.Core.BackOffice; -using Umbraco.Core.Configuration.Models; namespace Umbraco.Web.Security { @@ -26,7 +25,7 @@ namespace Umbraco.Web.Security private readonly IUserClaimsPrincipalFactory _claimsPrincipalFactory; private readonly IAuthenticationManager _authenticationManager; private readonly ILogger _logger; - private readonly GlobalSettings _globalSettings; + private readonly IGlobalSettings _globalSettings; private readonly IOwinRequest _request; public BackOfficeSignInManager( @@ -34,18 +33,7 @@ namespace Umbraco.Web.Security IUserClaimsPrincipalFactory claimsPrincipalFactory, IAuthenticationManager authenticationManager, ILogger logger, - IOptionsSnapshot globalSettings, - IOwinRequest request) - :this(userManager, claimsPrincipalFactory, authenticationManager, logger, globalSettings.Value, request) - { - } - - public BackOfficeSignInManager( - BackOfficeUserManager userManager, - IUserClaimsPrincipalFactory claimsPrincipalFactory, - IAuthenticationManager authenticationManager, - ILogger logger, - GlobalSettings globalSettings, + IGlobalSettings globalSettings, IOwinRequest request) { _userManager = userManager ?? throw new ArgumentNullException(nameof(userManager)); @@ -64,7 +52,7 @@ namespace Umbraco.Web.Security return claimsPrincipal.Identity as ClaimsIdentity; } - public static BackOfficeSignInManager Create(IOwinContext context, GlobalSettings globalSettings, ILogger logger) + public static BackOfficeSignInManager Create(IOwinContext context, IGlobalSettings globalSettings, ILogger logger) { var userManager = context.GetBackOfficeUserManager(); diff --git a/src/Umbraco.Web/Security/GetUserSecondsMiddleWare.cs b/src/Umbraco.Web/Security/GetUserSecondsMiddleWare.cs index e1227a892d..3ab37f0f70 100644 --- a/src/Umbraco.Web/Security/GetUserSecondsMiddleWare.cs +++ b/src/Umbraco.Web/Security/GetUserSecondsMiddleWare.cs @@ -3,13 +3,14 @@ using System.Diagnostics; using System.Globalization; using System.Threading.Tasks; using System.Web; -using Microsoft.Extensions.Options; using Microsoft.Owin; using Microsoft.Owin.Logging; using Umbraco.Core; using Umbraco.Core.Configuration; -using Umbraco.Core.Configuration.Models; +using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Hosting; +using Umbraco.Core.IO; +using Umbraco.Core.Security; namespace Umbraco.Web.Security { @@ -24,23 +25,23 @@ namespace Umbraco.Web.Security internal class GetUserSecondsMiddleWare : OwinMiddleware { private readonly UmbracoBackOfficeCookieAuthOptions _authOptions; - private readonly GlobalSettings _globalSettings; - private readonly SecuritySettings _securitySettings; + private readonly IGlobalSettings _globalSettings; + private readonly ISecuritySettings _security; private readonly ILogger _logger; private readonly IHostingEnvironment _hostingEnvironment; public GetUserSecondsMiddleWare( OwinMiddleware next, UmbracoBackOfficeCookieAuthOptions authOptions, - IOptionsSnapshot globalSettings, - IOptionsSnapshot securitySettings, + IGlobalSettings globalSettings, + ISecuritySettings security, ILogger logger, IHostingEnvironment hostingEnvironment) : base(next) { _authOptions = authOptions ?? throw new ArgumentNullException(nameof(authOptions)); - _globalSettings = globalSettings.Value; - _securitySettings = securitySettings.Value; + _globalSettings = globalSettings; + _security = security; _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _hostingEnvironment = hostingEnvironment; } @@ -54,7 +55,7 @@ namespace Umbraco.Web.Security && request.Uri.AbsolutePath.InvariantEquals( $"{_globalSettings.GetBackOfficePath(_hostingEnvironment)}/backoffice/UmbracoApi/Authentication/GetRemainingTimeoutSeconds")) { - var cookie = _authOptions.CookieManager.GetRequestCookie(context, _securitySettings.AuthCookieName); + var cookie = _authOptions.CookieManager.GetRequestCookie(context, _security.AuthCookieName); if (cookie.IsNullOrWhiteSpace() == false) { var ticket = _authOptions.TicketDataFormat.Unprotect(cookie); @@ -74,7 +75,7 @@ namespace Umbraco.Web.Security //Ok, so here we need to check if we want to process/renew the auth ticket for each // of these requests. If that is the case, the user will really never be logged out until they // close their browser (there will be edge cases of that, especially when debugging) - if (_securitySettings.KeepUserLoggedIn) + if (_security.KeepUserLoggedIn) { var currentUtc = _authOptions.SystemClock.UtcNow; var issuedUtc = ticket.Properties.IssuedUtc; diff --git a/src/Umbraco.Web/UmbracoApplicationBase.cs b/src/Umbraco.Web/UmbracoApplicationBase.cs index 7eeea5662c..1c447b38aa 100644 --- a/src/Umbraco.Web/UmbracoApplicationBase.cs +++ b/src/Umbraco.Web/UmbracoApplicationBase.cs @@ -9,7 +9,6 @@ using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Composing; using Umbraco.Core.Configuration; -using Umbraco.Core.Configuration.Models; using Umbraco.Core.Hosting; using Umbraco.Core.IO; using Umbraco.Core.Logging; @@ -45,7 +44,7 @@ namespace Umbraco.Web Path.Combine(hostingEnvironment.ApplicationPhysicalPath, "App_Data\\Logs"), Path.Combine(hostingEnvironment.ApplicationPhysicalPath, "config\\serilog.config"), Path.Combine(hostingEnvironment.ApplicationPhysicalPath, "config\\serilog.user.config")); - var ioHelper = new IOHelper(hostingEnvironment); + var ioHelper = new IOHelper(hostingEnvironment, globalSettings); var logger = SerilogLogger.CreateWithDefaultConfiguration(hostingEnvironment, loggingConfiguration); var configs = configFactory.Create(); @@ -126,7 +125,7 @@ namespace Umbraco.Web /// /// Gets the application register. /// - protected virtual IRegister GetRegister(GlobalSettings globalSettings) + protected virtual IRegister GetRegister(IGlobalSettings globalSettings) { return RegisterFactory.Create(globalSettings); } diff --git a/src/Umbraco.Web/UmbracoContext.cs b/src/Umbraco.Web/UmbracoContext.cs index 703f5f9b51..ae1cf885b3 100644 --- a/src/Umbraco.Web/UmbracoContext.cs +++ b/src/Umbraco.Web/UmbracoContext.cs @@ -2,7 +2,6 @@ using System; using System.Web; using Umbraco.Core; using Umbraco.Core.Configuration; -using Umbraco.Core.Configuration.Models; using Umbraco.Core.Hosting; using Umbraco.Core.Models.PublishedContent; using Umbraco.Web.Composing; @@ -18,7 +17,7 @@ namespace Umbraco.Web public class UmbracoContext : DisposableObjectSlim, IDisposeOnRequestEnd, IUmbracoContext { private readonly IHttpContextAccessor _httpContextAccessor; - private readonly GlobalSettings _globalSettings; + private readonly IGlobalSettings _globalSettings; private readonly IHostingEnvironment _hostingEnvironment; private readonly ICookieManager _cookieManager; private readonly Lazy _publishedSnapshot; @@ -32,7 +31,7 @@ namespace Umbraco.Web internal UmbracoContext(IHttpContextAccessor httpContextAccessor, IPublishedSnapshotService publishedSnapshotService, IWebSecurity webSecurity, - GlobalSettings globalSettings, + IGlobalSettings globalSettings, IHostingEnvironment hostingEnvironment, IVariationContextAccessor variationContextAccessor, UriUtility uriUtility, diff --git a/src/Umbraco.Web/UmbracoContextFactory.cs b/src/Umbraco.Web/UmbracoContextFactory.cs index a804e4b3be..bfb4dd627d 100644 --- a/src/Umbraco.Web/UmbracoContextFactory.cs +++ b/src/Umbraco.Web/UmbracoContextFactory.cs @@ -1,9 +1,7 @@ using System; using System.IO; using System.Text; -using Microsoft.Extensions.Options; using Umbraco.Core.Configuration; -using Umbraco.Core.Configuration.Models; using Umbraco.Core.Hosting; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Services; @@ -22,7 +20,7 @@ namespace Umbraco.Web private readonly IVariationContextAccessor _variationContextAccessor; private readonly IDefaultCultureAccessor _defaultCultureAccessor; - private readonly GlobalSettings _globalSettings; + private readonly IGlobalSettings _globalSettings; private readonly IUserService _userService; private readonly IHostingEnvironment _hostingEnvironment; private readonly IHttpContextAccessor _httpContextAccessor; @@ -37,7 +35,7 @@ namespace Umbraco.Web IPublishedSnapshotService publishedSnapshotService, IVariationContextAccessor variationContextAccessor, IDefaultCultureAccessor defaultCultureAccessor, - IOptionsSnapshot globalSettings, + IGlobalSettings globalSettings, IUserService userService, IHostingEnvironment hostingEnvironment, UriUtility uriUtility, @@ -48,7 +46,7 @@ namespace Umbraco.Web _publishedSnapshotService = publishedSnapshotService ?? throw new ArgumentNullException(nameof(publishedSnapshotService)); _variationContextAccessor = variationContextAccessor ?? throw new ArgumentNullException(nameof(variationContextAccessor)); _defaultCultureAccessor = defaultCultureAccessor ?? throw new ArgumentNullException(nameof(defaultCultureAccessor)); - _globalSettings = globalSettings.Value ?? throw new ArgumentNullException(nameof(globalSettings)); + _globalSettings = globalSettings ?? throw new ArgumentNullException(nameof(globalSettings)); _userService = userService ?? throw new ArgumentNullException(nameof(userService)); _hostingEnvironment = hostingEnvironment; _uriUtility = uriUtility; diff --git a/src/Umbraco.Web/UmbracoDefaultOwinStartup.cs b/src/Umbraco.Web/UmbracoDefaultOwinStartup.cs index af10009a0e..600b58cf06 100644 --- a/src/Umbraco.Web/UmbracoDefaultOwinStartup.cs +++ b/src/Umbraco.Web/UmbracoDefaultOwinStartup.cs @@ -1,20 +1,20 @@ using System; -using Microsoft.Extensions.Options; using Microsoft.Owin; using Owin; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Configuration; -using Umbraco.Core.Configuration.Models; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Hosting; +using Umbraco.Core.IO; using Umbraco.Core.Mapping; -using Umbraco.Core.Services; using Umbraco.Net; +using Umbraco.Core.Services; using Umbraco.Web; using Umbraco.Web.Composing; using Umbraco.Web.Security; + [assembly: OwinStartup("UmbracoDefaultOwinStartup", typeof(UmbracoDefaultOwinStartup))] namespace Umbraco.Web @@ -30,7 +30,7 @@ namespace Umbraco.Web protected IUmbracoContextAccessor UmbracoContextAccessor => Current.UmbracoContextAccessor; protected IGlobalSettings GlobalSettings => Current.Factory.GetInstance(); protected IContentSettings ContentSettings => Current.Factory.GetInstance(); - protected SecuritySettings SecuritySettings => Current.Factory.GetInstance>().Value; + protected ISecuritySettings SecuritySettings => Current.Factory.GetInstance(); protected IUserPasswordConfiguration UserPasswordConfig => Current.Factory.GetInstance(); protected IRuntimeState RuntimeState => Current.RuntimeState; protected ServiceContext Services => Current.Services; diff --git a/src/Umbraco.Web/WebApi/UmbracoApiController.cs b/src/Umbraco.Web/WebApi/UmbracoApiController.cs index 36cf0d5c20..a832b4e823 100644 --- a/src/Umbraco.Web/WebApi/UmbracoApiController.cs +++ b/src/Umbraco.Web/WebApi/UmbracoApiController.cs @@ -1,10 +1,8 @@ using System; -using Microsoft.Extensions.Options; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Composing; using Umbraco.Core.Configuration; -using Umbraco.Core.Configuration.Models; using Umbraco.Core.Logging; using Umbraco.Core.Mapping; using Umbraco.Core.Persistence; @@ -22,7 +20,7 @@ namespace Umbraco.Web.WebApi { } - protected UmbracoApiController(IOptionsSnapshot globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoMapper umbracoMapper, IPublishedUrlProvider publishedUrlProvider) + protected UmbracoApiController(IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoMapper umbracoMapper, IPublishedUrlProvider publishedUrlProvider) : base(globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoMapper, publishedUrlProvider) { } diff --git a/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs b/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs index 323f09316f..d009528bc7 100644 --- a/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs +++ b/src/Umbraco.Web/WebApi/UmbracoApiControllerBase.cs @@ -14,11 +14,11 @@ using Umbraco.Web.Features; using Umbraco.Web.Routing; using Umbraco.Web.Security; using Umbraco.Web.WebApi.Filters; -using Microsoft.Extensions.Options; -using Umbraco.Core.Configuration.Models; namespace Umbraco.Web.WebApi { + + /// /// Provides a base class for Umbraco API controllers. /// @@ -26,6 +26,7 @@ namespace Umbraco.Web.WebApi [FeatureAuthorize] public abstract class UmbracoApiControllerBase : ApiController, IUmbracoFeature { + // note: all Umbraco controllers have two constructors: one with all dependencies, which should be used, // and one with auto dependencies, ie no dependencies - and then dependencies are automatically obtained // here from the Current service locator - this is obviously evil, but it allows us to add new dependencies @@ -37,7 +38,7 @@ namespace Umbraco.Web.WebApi /// Dependencies are obtained from the service locator. protected UmbracoApiControllerBase() : this( - Current.Factory.GetInstance>(), + Current.Factory.GetInstance(), Current.Factory.GetInstance(), Current.Factory.GetInstance(), Current.Factory.GetInstance(), @@ -52,10 +53,10 @@ namespace Umbraco.Web.WebApi /// /// Initializes a new instance of the class with all its dependencies. /// - protected UmbracoApiControllerBase(IOptionsSnapshot globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoMapper umbracoMapper, IPublishedUrlProvider publishedUrlProvider) + protected UmbracoApiControllerBase(IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoMapper umbracoMapper, IPublishedUrlProvider publishedUrlProvider) { UmbracoContextAccessor = umbracoContextAccessor; - GlobalSettings = globalSettings.Value; + GlobalSettings = globalSettings; SqlContext = sqlContext; Services = services; AppCaches = appCaches; @@ -72,9 +73,9 @@ namespace Umbraco.Web.WebApi internal Guid InstanceId { get; } = Guid.NewGuid(); /// - /// Gets the global settings from configuration. + /// Gets the Umbraco context. /// - public virtual GlobalSettings GlobalSettings { get; } + public virtual IGlobalSettings GlobalSettings { get; } /// /// Gets the Umbraco context. diff --git a/src/Umbraco.Web/WebApi/UmbracoAuthorizedApiController.cs b/src/Umbraco.Web/WebApi/UmbracoAuthorizedApiController.cs index 1bd9fb8f31..48b3de44fd 100644 --- a/src/Umbraco.Web/WebApi/UmbracoAuthorizedApiController.cs +++ b/src/Umbraco.Web/WebApi/UmbracoAuthorizedApiController.cs @@ -8,8 +8,6 @@ using Umbraco.Core.Services; using Umbraco.Web.Security; using Umbraco.Core.Mapping; using Umbraco.Web.Routing; -using Microsoft.Extensions.Options; -using Umbraco.Core.Configuration.Models; namespace Umbraco.Web.WebApi { @@ -37,7 +35,7 @@ namespace Umbraco.Web.WebApi { } - protected UmbracoAuthorizedApiController(IOptionsSnapshot globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoMapper umbracoMapper, IPublishedUrlProvider publishedUrlProvider) + protected UmbracoAuthorizedApiController(IGlobalSettings globalSettings, IUmbracoContextAccessor umbracoContextAccessor, ISqlContext sqlContext, ServiceContext services, AppCaches appCaches, IProfilingLogger logger, IRuntimeState runtimeState, UmbracoMapper umbracoMapper, IPublishedUrlProvider publishedUrlProvider) : base(globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoMapper, publishedUrlProvider) { } diff --git a/src/Umbraco.Web/WebAssets/CDF/ClientDependencyComponent.cs b/src/Umbraco.Web/WebAssets/CDF/ClientDependencyComponent.cs index b38c775f67..0d8d4b8bf2 100644 --- a/src/Umbraco.Web/WebAssets/CDF/ClientDependencyComponent.cs +++ b/src/Umbraco.Web/WebAssets/CDF/ClientDependencyComponent.cs @@ -3,11 +3,9 @@ using System.Collections.Specialized; using System.IO; using ClientDependency.Core.CompositeFiles.Providers; using ClientDependency.Core.Config; -using Microsoft.Extensions.Options; using Umbraco.Core; using Umbraco.Core.Composing; using Umbraco.Core.Configuration; -using Umbraco.Core.Configuration.Models; using Umbraco.Core.Hosting; using Umbraco.Web.Runtime; @@ -16,18 +14,18 @@ namespace Umbraco.Web.WebAssets.CDF [ComposeAfter(typeof(WebInitialComponent))] public sealed class ClientDependencyComponent : IComponent { - private readonly HostingSettings _hostingSettings; + private readonly IHostingSettings _hostingSettings; private readonly IHostingEnvironment _hostingEnvironment; - private readonly RuntimeSettings _runtimeSettings; + private readonly IRuntimeSettings _settings; public ClientDependencyComponent( - IOptionsSnapshot hostingSettings, + IHostingSettings hostingSettings, IHostingEnvironment hostingEnvironment, - IOptionsSnapshot runtimeSettings) + IRuntimeSettings settings) { - _hostingSettings = hostingSettings.Value; + _hostingSettings = hostingSettings; _hostingEnvironment = hostingEnvironment; - _runtimeSettings = runtimeSettings.Value; + _settings = settings; } public void Initialize() @@ -56,10 +54,10 @@ namespace Umbraco.Web.WebAssets.CDF = Path.Combine(cachePath, "ClientDependency"); } - if (_runtimeSettings.MaxQueryStringLength.HasValue || _runtimeSettings.MaxRequestLength.HasValue) + if (_settings.MaxQueryStringLength.HasValue || _settings.MaxRequestLength.HasValue) { //set the max url length for CDF to be the smallest of the max query length, max request length - ClientDependency.Core.CompositeFiles.CompositeDependencyHandler.MaxHandlerUrlLength = Math.Min(_runtimeSettings.MaxQueryStringLength.GetValueOrDefault(), _runtimeSettings.MaxRequestLength.GetValueOrDefault()); + ClientDependency.Core.CompositeFiles.CompositeDependencyHandler.MaxHandlerUrlLength = Math.Min(_settings.MaxQueryStringLength.GetValueOrDefault(), _settings.MaxRequestLength.GetValueOrDefault()); } //Register a custom renderer - used to process property editor dependencies From 2f22313ceb3a260a2582eb5f24634639d05f7b85 Mon Sep 17 00:00:00 2001 From: Andy Butland Date: Sun, 23 Aug 2020 15:58:37 +0200 Subject: [PATCH 245/826] Restored Umbraco.Web and added temporary methods for converstion between legacy and new configuration models to maintain build. --- .../AspNetCoreConfigsFactory.cs | 1 + .../Umbraco.Configuration.csproj | 10 -- .../MemberPasswordConfigurationSettings.cs | 5 +- .../UserPasswordConfigurationSettings.cs | 5 +- .../Umbraco.Infrastructure.csproj | 1 - .../Building/Builder.cs | 5 +- .../Building/ModelsGenerator.cs | 8 +- .../Building/TextBuilder.cs | 3 +- .../Compose/ModelsBuilderComposer.cs | 15 ++- .../ModelsGenerationError.cs | 8 +- .../OutOfDateModelsStatus.cs | 5 +- .../PureLiveModelFactory.cs | 8 +- .../UmbracoCoreServiceCollectionExtensions.cs | 4 + src/Umbraco.Web/AppBuilderExtensions.cs | 5 +- .../Compose/AuditEventsComponent.cs | 3 +- .../Configuration/ConfigModelConversions.cs | 99 +++++++++++++++++++ .../Editors/BackOfficeController.cs | 5 +- .../Editors/BackOfficeServerVariables.cs | 7 +- .../Mvc/AreaRegistrationExtensions.cs | 3 +- src/Umbraco.Web/Mvc/BackOfficeArea.cs | 3 +- .../Mvc/UmbracoAuthorizeAttribute.cs | 3 +- .../Runtime/WebInitialComponent.cs | 5 +- .../Security/BackOfficeOwinUserManager.cs | 11 ++- .../Security/BackOfficeSignInManager.cs | 3 +- .../Security/GetUserSecondsMiddleWare.cs | 3 +- src/Umbraco.Web/Umbraco.Web.csproj | 1 + src/Umbraco.Web/UmbracoApplication.cs | 7 +- src/Umbraco.Web/UmbracoApplicationBase.cs | 7 +- src/Umbraco.Web/UmbracoContext.cs | 3 +- src/Umbraco.Web/UmbracoInjectedModule.cs | 7 +- .../CheckIfUserTicketDataIsStaleAttribute.cs | 3 +- 31 files changed, 187 insertions(+), 69 deletions(-) create mode 100644 src/Umbraco.Web/Configuration/ConfigModelConversions.cs diff --git a/src/Umbraco.Configuration/AspNetCoreConfigsFactory.cs b/src/Umbraco.Configuration/AspNetCoreConfigsFactory.cs index d8b5e666b9..f957074881 100644 --- a/src/Umbraco.Configuration/AspNetCoreConfigsFactory.cs +++ b/src/Umbraco.Configuration/AspNetCoreConfigsFactory.cs @@ -3,6 +3,7 @@ using Umbraco.Configuration.Models; using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.HealthChecks; using Umbraco.Core.Configuration.UmbracoSettings; +using CoreDebugSettings = Umbraco.Configuration.Models.CoreDebugSettings; namespace Umbraco.Configuration { diff --git a/src/Umbraco.Configuration/Umbraco.Configuration.csproj b/src/Umbraco.Configuration/Umbraco.Configuration.csproj index 8d7a0e7f01..a4dac22386 100644 --- a/src/Umbraco.Configuration/Umbraco.Configuration.csproj +++ b/src/Umbraco.Configuration/Umbraco.Configuration.csproj @@ -10,25 +10,15 @@ - - - - - - - - - - diff --git a/src/Umbraco.Core/Configuration/Models/MemberPasswordConfigurationSettings.cs b/src/Umbraco.Core/Configuration/Models/MemberPasswordConfigurationSettings.cs index 1f2808ef7e..52bba6f4b8 100644 --- a/src/Umbraco.Core/Configuration/Models/MemberPasswordConfigurationSettings.cs +++ b/src/Umbraco.Core/Configuration/Models/MemberPasswordConfigurationSettings.cs @@ -1,7 +1,4 @@ -using Umbraco.Core; -using Umbraco.Core.Configuration; - -namespace Umbraco.Core.Configuration.Models +namespace Umbraco.Core.Configuration.Models { public class MemberPasswordConfigurationSettings : IPasswordConfiguration { diff --git a/src/Umbraco.Core/Configuration/Models/UserPasswordConfigurationSettings.cs b/src/Umbraco.Core/Configuration/Models/UserPasswordConfigurationSettings.cs index a0c26b2410..445a0f545c 100644 --- a/src/Umbraco.Core/Configuration/Models/UserPasswordConfigurationSettings.cs +++ b/src/Umbraco.Core/Configuration/Models/UserPasswordConfigurationSettings.cs @@ -1,7 +1,4 @@ -using Umbraco.Core; -using Umbraco.Core.Configuration; - -namespace Umbraco.Core.Configuration.Models +namespace Umbraco.Core.Configuration.Models { public class UserPasswordConfigurationSettings : IPasswordConfiguration { diff --git a/src/Umbraco.Infrastructure/Umbraco.Infrastructure.csproj b/src/Umbraco.Infrastructure/Umbraco.Infrastructure.csproj index fa0ac89c61..d9cd6bf498 100644 --- a/src/Umbraco.Infrastructure/Umbraco.Infrastructure.csproj +++ b/src/Umbraco.Infrastructure/Umbraco.Infrastructure.csproj @@ -97,7 +97,6 @@ - diff --git a/src/Umbraco.ModelsBuilder.Embedded/Building/Builder.cs b/src/Umbraco.ModelsBuilder.Embedded/Building/Builder.cs index f64e5ed1ce..dc093d3c2d 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/Building/Builder.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/Building/Builder.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using Umbraco.Core; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; namespace Umbraco.ModelsBuilder.Embedded.Building { @@ -70,7 +71,7 @@ namespace Umbraco.ModelsBuilder.Embedded.Building /// /// The list of models to generate. /// The models namespace. - protected Builder(IModelsBuilderConfig config, IList typeModels) + protected Builder(ModelsBuilderConfig config, IList typeModels) { _typeModels = typeModels ?? throw new ArgumentNullException(nameof(typeModels)); @@ -87,7 +88,7 @@ namespace Umbraco.ModelsBuilder.Embedded.Building protected Builder() { } - protected IModelsBuilderConfig Config { get; } + protected ModelsBuilderConfig Config { get; } /// /// Prepares generation by processing the result of code parsing. diff --git a/src/Umbraco.ModelsBuilder.Embedded/Building/ModelsGenerator.cs b/src/Umbraco.ModelsBuilder.Embedded/Building/ModelsGenerator.cs index 648a2e76fa..1572fc9b92 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/Building/ModelsGenerator.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/Building/ModelsGenerator.cs @@ -1,6 +1,8 @@ using System.IO; using System.Text; +using Microsoft.Extensions.Options; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.IO; namespace Umbraco.ModelsBuilder.Embedded.Building @@ -8,14 +10,14 @@ namespace Umbraco.ModelsBuilder.Embedded.Building public class ModelsGenerator { private readonly UmbracoServices _umbracoService; - private readonly IModelsBuilderConfig _config; + private readonly ModelsBuilderConfig _config; private readonly OutOfDateModelsStatus _outOfDateModels; private readonly IIOHelper _ioHelper; - public ModelsGenerator(UmbracoServices umbracoService, IModelsBuilderConfig config, OutOfDateModelsStatus outOfDateModels, IIOHelper ioHelper) + public ModelsGenerator(UmbracoServices umbracoService, IOptionsSnapshot config, OutOfDateModelsStatus outOfDateModels, IIOHelper ioHelper) { _umbracoService = umbracoService; - _config = config; + _config = config.Value; _outOfDateModels = outOfDateModels; _ioHelper = ioHelper; } diff --git a/src/Umbraco.ModelsBuilder.Embedded/Building/TextBuilder.cs b/src/Umbraco.ModelsBuilder.Embedded/Building/TextBuilder.cs index 723ee10f35..9a2ad6f600 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/Building/TextBuilder.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/Building/TextBuilder.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Text; using System.Text.RegularExpressions; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; namespace Umbraco.ModelsBuilder.Embedded.Building { @@ -17,7 +18,7 @@ namespace Umbraco.ModelsBuilder.Embedded.Building /// and the result of code parsing. /// /// The list of models to generate. - public TextBuilder(IModelsBuilderConfig config, IList typeModels) + public TextBuilder(ModelsBuilderConfig config, IList typeModels) : base(config, typeModels) { } diff --git a/src/Umbraco.ModelsBuilder.Embedded/Compose/ModelsBuilderComposer.cs b/src/Umbraco.ModelsBuilder.Embedded/Compose/ModelsBuilderComposer.cs index e582301740..3873080605 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/Compose/ModelsBuilderComposer.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/Compose/ModelsBuilderComposer.cs @@ -6,15 +6,22 @@ using Umbraco.Core.Logging; using Umbraco.Core.Composing; using Umbraco.Core.Models.PublishedContent; using Umbraco.ModelsBuilder.Embedded.Building; +using Umbraco.Core.Configuration.Models; +using Microsoft.Extensions.Options; namespace Umbraco.ModelsBuilder.Embedded.Compose { - - [ComposeBefore(typeof(IPublishedCacheComposer))] [RuntimeLevel(MinLevel = RuntimeLevel.Run)] public sealed class ModelsBuilderComposer : ICoreComposer { + private readonly ModelsBuilderConfig _config; + + public ModelsBuilderComposer(IOptionsSnapshot config) + { + _config = config.Value; + } + public void Compose(Composition composition) { var isLegacyModelsBuilderInstalled = IsLegacyModelsBuilderInstalled(); @@ -32,9 +39,9 @@ namespace Umbraco.ModelsBuilder.Embedded.Compose composition.RegisterUnique(); composition.RegisterUnique(); - if (composition.Configs.ModelsBuilder().ModelsMode == ModelsMode.PureLive) + if (_config.ModelsMode == ModelsMode.PureLive) ComposeForLiveModels(composition); - else if (composition.Configs.ModelsBuilder().EnableFactory) + else if (_config.EnableFactory) ComposeForDefaultModelsFactory(composition); } diff --git a/src/Umbraco.ModelsBuilder.Embedded/ModelsGenerationError.cs b/src/Umbraco.ModelsBuilder.Embedded/ModelsGenerationError.cs index f8f6e8c7bc..92c73e2c6d 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/ModelsGenerationError.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/ModelsGenerationError.cs @@ -1,19 +1,21 @@ using System; using System.IO; using System.Text; +using Microsoft.Extensions.Options; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.IO; namespace Umbraco.ModelsBuilder.Embedded { public sealed class ModelsGenerationError { - private readonly IModelsBuilderConfig _config; + private readonly ModelsBuilderConfig _config; private readonly IIOHelper _ioHelper; - public ModelsGenerationError(IModelsBuilderConfig config, IIOHelper ioHelper) + public ModelsGenerationError(IOptionsSnapshot config, IIOHelper ioHelper) { - _config = config; + _config = config.Value; _ioHelper = ioHelper; } diff --git a/src/Umbraco.ModelsBuilder.Embedded/OutOfDateModelsStatus.cs b/src/Umbraco.ModelsBuilder.Embedded/OutOfDateModelsStatus.cs index b8105eeef2..4fb23ad5b3 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/OutOfDateModelsStatus.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/OutOfDateModelsStatus.cs @@ -1,5 +1,6 @@ using System.IO; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.IO; using Umbraco.Web.Cache; @@ -7,10 +8,10 @@ namespace Umbraco.ModelsBuilder.Embedded { public sealed class OutOfDateModelsStatus { - private readonly IModelsBuilderConfig _config; + private readonly ModelsBuilderConfig _config; private readonly IIOHelper _ioHelper; - public OutOfDateModelsStatus(IModelsBuilderConfig config, IIOHelper ioHelper) + public OutOfDateModelsStatus(ModelsBuilderConfig config, IIOHelper ioHelper) { _config = config; _ioHelper = ioHelper; diff --git a/src/Umbraco.ModelsBuilder.Embedded/PureLiveModelFactory.cs b/src/Umbraco.ModelsBuilder.Embedded/PureLiveModelFactory.cs index 7809d2bf48..da48621c7d 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/PureLiveModelFactory.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/PureLiveModelFactory.cs @@ -19,6 +19,8 @@ using Umbraco.Core.Logging; using Umbraco.Core.Models.PublishedContent; using Umbraco.ModelsBuilder.Embedded.Building; using File = System.IO.File; +using Umbraco.Core.Configuration.Models; +using Microsoft.Extensions.Options; namespace Umbraco.ModelsBuilder.Embedded { @@ -41,7 +43,7 @@ namespace Umbraco.ModelsBuilder.Embedded private const string ProjVirt = "~/App_Data/Models/all.generated.cs"; private static readonly string[] OurFiles = { "models.hash", "models.generated.cs", "all.generated.cs", "all.dll.path", "models.err" }; - private readonly IModelsBuilderConfig _config; + private readonly ModelsBuilderConfig _config; private readonly IApplicationShutdownRegistry _hostingLifetime; private readonly IIOHelper _ioHelper; private readonly ModelsGenerationError _errors; @@ -49,14 +51,14 @@ namespace Umbraco.ModelsBuilder.Embedded public PureLiveModelFactory( Lazy umbracoServices, IProfilingLogger logger, - IModelsBuilderConfig config, + IOptionsSnapshot config, IHostingEnvironment hostingEnvironment, IApplicationShutdownRegistry hostingLifetime, IIOHelper ioHelper) { _umbracoServices = umbracoServices; _logger = logger; - _config = config; + _config = config.Value; _hostingLifetime = hostingLifetime; _ioHelper = ioHelper; _errors = new ModelsGenerationError(config, ioHelper); diff --git a/src/Umbraco.Web.Common/Extensions/UmbracoCoreServiceCollectionExtensions.cs b/src/Umbraco.Web.Common/Extensions/UmbracoCoreServiceCollectionExtensions.cs index 1c7f8156f4..4653bc7bbd 100644 --- a/src/Umbraco.Web.Common/Extensions/UmbracoCoreServiceCollectionExtensions.cs +++ b/src/Umbraco.Web.Common/Extensions/UmbracoCoreServiceCollectionExtensions.cs @@ -28,6 +28,7 @@ using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.Runtime; using Umbraco.Web.Common.AspNetCore; using Umbraco.Web.Common.Profiler; +using ConnectionStrings = Umbraco.Core.Configuration.Models.ConnectionStrings; using CoreDebugSettings = Umbraco.Core.Configuration.Models.CoreDebugSettings; namespace Umbraco.Extensions @@ -124,6 +125,9 @@ namespace Umbraco.Extensions services.Configure(configuration.GetSection(Constants.Configuration.ConfigModelsBuilderPrefix)); services.Configure(configuration.GetSection(Constants.Configuration.ConfigPrefix + "Imaging:")); + // TODO: HealthChecksSettings (+ one other?) + + // TODO: remove this var configsFactory = new AspNetCoreConfigsFactory(configuration); var configs = configsFactory.Create(); services.AddSingleton(configs); diff --git a/src/Umbraco.Web/AppBuilderExtensions.cs b/src/Umbraco.Web/AppBuilderExtensions.cs index c8c6cbdf5c..18eb3a54fe 100644 --- a/src/Umbraco.Web/AppBuilderExtensions.cs +++ b/src/Umbraco.Web/AppBuilderExtensions.cs @@ -4,8 +4,7 @@ using Microsoft.Owin.Logging; using Owin; using Umbraco.Core.Configuration; using Umbraco.Core.Hosting; -using Umbraco.Core.IO; -using Umbraco.Web.Composing; +using Umbraco.Web.Configuration; using Umbraco.Web.Logging; namespace Umbraco.Web @@ -48,7 +47,7 @@ namespace Umbraco.Web /// public static IAppBuilder UseSignalR(this IAppBuilder app, IGlobalSettings globalSettings, IHostingEnvironment hostingEnvironment) { - var umbracoPath = globalSettings.GetUmbracoMvcArea(hostingEnvironment); + var umbracoPath = ConfigModelConversions.ConvertGlobalSettings(globalSettings).GetUmbracoMvcArea(hostingEnvironment); var signalrPath = HttpRuntime.AppDomainAppVirtualPath + umbracoPath + "/BackOffice/signalr"; return app.MapSignalR(signalrPath, new HubConfiguration { EnableDetailedErrors = true }); } diff --git a/src/Umbraco.Web/Compose/AuditEventsComponent.cs b/src/Umbraco.Web/Compose/AuditEventsComponent.cs index 51c47233c7..9b9a1671f3 100644 --- a/src/Umbraco.Web/Compose/AuditEventsComponent.cs +++ b/src/Umbraco.Web/Compose/AuditEventsComponent.cs @@ -11,6 +11,7 @@ using Umbraco.Net; using Umbraco.Core.Services; using Umbraco.Core.Services.Implement; using Umbraco.Extensions; +using Umbraco.Web.Configuration; namespace Umbraco.Core.Compose { @@ -49,7 +50,7 @@ namespace Umbraco.Core.Compose public void Terminate() { } - public static IUser UnknownUser(IGlobalSettings globalSettings) => new User(globalSettings) { Id = Constants.Security.UnknownUserId, Name = Constants.Security.UnknownUserName, Email = "" }; + public static IUser UnknownUser(IGlobalSettings globalSettings) => new User(ConfigModelConversions.ConvertGlobalSettings(globalSettings)) { Id = Constants.Security.UnknownUserId, Name = Constants.Security.UnknownUserName, Email = "" }; private IUser CurrentPerformingUser { diff --git a/src/Umbraco.Web/Configuration/ConfigModelConversions.cs b/src/Umbraco.Web/Configuration/ConfigModelConversions.cs new file mode 100644 index 0000000000..752983c7c9 --- /dev/null +++ b/src/Umbraco.Web/Configuration/ConfigModelConversions.cs @@ -0,0 +1,99 @@ +using Microsoft.AspNetCore.Identity; +using Microsoft.Extensions.Options; +using Umbraco.Core; +using Umbraco.Core.BackOffice; +using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; + +namespace Umbraco.Web.Configuration +{ + /// + /// TEMPORARY: this class has been added just to ensure Umbraco.Web functionality continues to compile, by + /// converting between (used by + /// legacy configuration and (used by Netcore/IOptions configuration). + /// + public static class ConfigModelConversions + { + public static GlobalSettings ConvertGlobalSettings(IGlobalSettings globalSettings) + { + return new GlobalSettings + { + DatabaseFactoryServerVersion = globalSettings.DatabaseFactoryServerVersion, + DefaultUILanguage = globalSettings.DefaultUILanguage, + DisableElectionForSingleServer = globalSettings.DisableElectionForSingleServer, + HideTopLevelNodeFromPath = globalSettings.HideTopLevelNodeFromPath, + InstallEmptyDatabase = globalSettings.InstallEmptyDatabase, + InstallMissingDatabase = globalSettings.InstallMissingDatabase, + MainDomLock = globalSettings.MainDomLock, + NoNodesViewPath = globalSettings.NoNodesViewPath, + RegisterType = globalSettings.RegisterType, + ReservedPaths = globalSettings.ReservedPaths, + ReservedUrls = globalSettings.ReservedUrls, + SmtpSettings = new SmtpSettings + { + DeliveryMethod = globalSettings.SmtpSettings.DeliveryMethod, + From = globalSettings.SmtpSettings.From, + Host = globalSettings.SmtpSettings.Host, + Password = globalSettings.SmtpSettings.Password, + PickupDirectoryLocation = globalSettings.SmtpSettings.PickupDirectoryLocation, + Port = globalSettings.SmtpSettings.Port, + Username = globalSettings.SmtpSettings.Username, + }, + TimeOutInMinutes = globalSettings.TimeOutInMinutes, + UmbracoCssPath = globalSettings.UmbracoCssPath, + UmbracoMediaPath = globalSettings.UmbracoMediaPath, + UmbracoPath = globalSettings.UmbracoPath, + UmbracoScriptsPath = globalSettings.UmbracoScriptsPath, + UseHttps = globalSettings.UseHttps, + VersionCheckPeriod = globalSettings.VersionCheckPeriod, + }; + } + + public static Umbraco.Core.Configuration.Models.ConnectionStrings ConvertConnectionStrings(IConnectionStrings connectionStrings) + { + return new Umbraco.Core.Configuration.Models.ConnectionStrings + { + UmbracoConnectionString = connectionStrings[Constants.System.UmbracoConnectionName].ConnectionString + }; + } + + public static IOptions ConvertToOptionsOfUserPasswordConfigurationSettings(IOptions identityOptions) + { + var passwordOptions = identityOptions.Value.Password; + var lockOutOptions = identityOptions.Value.Lockout; + var passwordConfiguration = new UserPasswordConfigurationSettings + { + MaxFailedAccessAttemptsBeforeLockout = lockOutOptions.MaxFailedAccessAttempts, + HashAlgorithmType = Constants.Security.AspNetCoreV3PasswordHashAlgorithmName, // TODO: not sure where to map this from. + RequireDigit = passwordOptions.RequireDigit, + RequiredLength = passwordOptions.RequiredLength, + RequireLowercase = passwordOptions.RequireLowercase, + RequireNonLetterOrDigit = passwordOptions.RequireNonAlphanumeric, + RequireUppercase = passwordOptions.RequireUppercase, + }; + + return Options.Create(passwordConfiguration); + } + + public static IOptions ConvertToOptionsOfBackOfficeIdentityOptions(IUserPasswordConfiguration passwordConfiguration) + { + var identityOptions = new BackOfficeIdentityOptions + { + Lockout = new LockoutOptions + { + MaxFailedAccessAttempts = passwordConfiguration.MaxFailedAccessAttemptsBeforeLockout, + }, + Password = new PasswordOptions + { + RequireDigit = passwordConfiguration.RequireDigit, + RequiredLength = passwordConfiguration.RequiredLength, + RequireLowercase = passwordConfiguration.RequireLowercase, + RequireNonAlphanumeric = passwordConfiguration.RequireNonLetterOrDigit, + RequireUppercase = passwordConfiguration.RequireUppercase, + } + }; + + return Options.Create(identityOptions); + } + } +} diff --git a/src/Umbraco.Web/Editors/BackOfficeController.cs b/src/Umbraco.Web/Editors/BackOfficeController.cs index b963871a58..3106d02dc8 100644 --- a/src/Umbraco.Web/Editors/BackOfficeController.cs +++ b/src/Umbraco.Web/Editors/BackOfficeController.cs @@ -11,6 +11,7 @@ using Umbraco.Core.Configuration; using Umbraco.Core.Logging; using Umbraco.Web.Mvc; using Umbraco.Core.Services; +using Umbraco.Web.Configuration; using Umbraco.Web.Features; using Umbraco.Web.Security; using Constants = Umbraco.Core.Constants; @@ -139,7 +140,7 @@ namespace Umbraco.Web.Editors if (defaultResponse == null) throw new ArgumentNullException("defaultResponse"); if (externalSignInResponse == null) throw new ArgumentNullException("externalSignInResponse"); - ViewData.SetUmbracoPath(GlobalSettings.GetUmbracoMvcArea(_hostingEnvironment)); + ViewData.SetUmbracoPath(ConfigModelConversions.ConvertGlobalSettings(GlobalSettings).GetUmbracoMvcArea(_hostingEnvironment)); //check if there is the TempData with the any token name specified, if so, assign to view bag and render the view if (ViewData.FromTempData(TempData, ViewDataExtensions.TokenExternalSignInError) || @@ -254,7 +255,7 @@ namespace Umbraco.Web.Editors var groups = Services.UserService.GetUserGroupsByAlias(autoLinkOptions.GetDefaultUserGroups(UmbracoContext, loginInfo)); var autoLinkUser = BackOfficeIdentityUser.CreateNew( - GlobalSettings, + ConfigModelConversions.ConvertGlobalSettings(GlobalSettings), loginInfo.Email, loginInfo.Email, autoLinkOptions.GetDefaultCulture(UmbracoContext, loginInfo)); diff --git a/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs b/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs index 454338112c..ec8d7e5dd5 100644 --- a/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs +++ b/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs @@ -7,6 +7,7 @@ using System.Web; using System.Web.Mvc; using Umbraco.Core; using Umbraco.Core.Configuration; +using Umbraco.Web.Configuration; using Umbraco.Web.Features; using Umbraco.Web.HealthCheck; using Umbraco.Web.Models.ContentEditing; @@ -143,7 +144,7 @@ namespace Umbraco.Web.Editors { "umbracoSettings", new Dictionary { - {"umbracoPath", _globalSettings.GetBackOfficePath(_hostingEnvironment)}, + {"umbracoPath", ConfigModelConversions.ConvertGlobalSettings(_globalSettings).GetBackOfficePath(_hostingEnvironment)}, {"mediaPath", _hostingEnvironment.ToAbsolute(globalSettings.UmbracoMediaPath).TrimEnd('/')}, {"appPluginsPath", _hostingEnvironment.ToAbsolute(Constants.SystemDirectories.AppPlugins).TrimEnd('/')}, { @@ -167,8 +168,8 @@ namespace Umbraco.Web.Editors {"cssPath", _hostingEnvironment.ToAbsolute(globalSettings.UmbracoCssPath).TrimEnd('/')}, {"allowPasswordReset", _securitySettings.AllowPasswordReset}, {"loginBackgroundImage", _contentSettings.LoginBackgroundImage}, - {"showUserInvite", EmailSender.CanSendRequiredEmail(globalSettings)}, - {"canSendRequiredEmail", EmailSender.CanSendRequiredEmail(globalSettings)}, + {"showUserInvite", EmailSender.CanSendRequiredEmail(ConfigModelConversions.ConvertGlobalSettings(globalSettings))}, + {"canSendRequiredEmail", EmailSender.CanSendRequiredEmail(ConfigModelConversions.ConvertGlobalSettings(globalSettings))}, {"showAllowSegmentationForDocumentTypes", false}, } }, diff --git a/src/Umbraco.Web/Mvc/AreaRegistrationExtensions.cs b/src/Umbraco.Web/Mvc/AreaRegistrationExtensions.cs index 118c53a7f0..eee675e9fd 100644 --- a/src/Umbraco.Web/Mvc/AreaRegistrationExtensions.cs +++ b/src/Umbraco.Web/Mvc/AreaRegistrationExtensions.cs @@ -10,6 +10,7 @@ using Umbraco.Core.Exceptions; using Umbraco.Core.Hosting; using Umbraco.Core.IO; using Umbraco.Web.Composing; +using Umbraco.Web.Configuration; using Umbraco.Web.WebApi; namespace Umbraco.Web.Mvc @@ -60,7 +61,7 @@ namespace Umbraco.Web.Mvc if (routes == null) throw new ArgumentNullException(nameof(routes)); if (defaultId == null) throw new ArgumentNullException(nameof(defaultId)); - var umbracoArea = globalSettings.GetUmbracoMvcArea(hostingEnvironment); + var umbracoArea = ConfigModelConversions.ConvertGlobalSettings(globalSettings).GetUmbracoMvcArea(hostingEnvironment); //routes are explicitly named with controller names and IDs var url = umbracoArea + "/" + diff --git a/src/Umbraco.Web/Mvc/BackOfficeArea.cs b/src/Umbraco.Web/Mvc/BackOfficeArea.cs index 156a896bb5..4a4202b42b 100644 --- a/src/Umbraco.Web/Mvc/BackOfficeArea.cs +++ b/src/Umbraco.Web/Mvc/BackOfficeArea.cs @@ -3,6 +3,7 @@ using Umbraco.Web.Composing; using Umbraco.Core.Configuration; using Umbraco.Core.Hosting; using Umbraco.Core.IO; +using Umbraco.Web.Configuration; using Umbraco.Web.Editors; namespace Umbraco.Web.Mvc @@ -50,6 +51,6 @@ namespace Umbraco.Web.Mvc new[] {typeof (BackOfficeController).Namespace}); } - public override string AreaName => _globalSettings.GetUmbracoMvcArea(_hostingEnvironment); + public override string AreaName => ConfigModelConversions.ConvertGlobalSettings(_globalSettings).GetUmbracoMvcArea(_hostingEnvironment); } } diff --git a/src/Umbraco.Web/Mvc/UmbracoAuthorizeAttribute.cs b/src/Umbraco.Web/Mvc/UmbracoAuthorizeAttribute.cs index b5c6185069..9fc58a208f 100644 --- a/src/Umbraco.Web/Mvc/UmbracoAuthorizeAttribute.cs +++ b/src/Umbraco.Web/Mvc/UmbracoAuthorizeAttribute.cs @@ -4,6 +4,7 @@ using System.Web.Mvc; using Umbraco.Core; using Umbraco.Web.Composing; using Umbraco.Core.Configuration; +using Umbraco.Web.Configuration; using Umbraco.Web.Security; namespace Umbraco.Web.Mvc @@ -55,7 +56,7 @@ namespace Umbraco.Web.Mvc { if (redirectToUmbracoLogin) { - _redirectUrl = Current.Configs.Global().GetBackOfficePath(Current.HostingEnvironment).EnsureStartsWith("~"); + _redirectUrl = ConfigModelConversions.ConvertGlobalSettings(Current.Configs.Global()).GetBackOfficePath(Current.HostingEnvironment).EnsureStartsWith("~"); } } diff --git a/src/Umbraco.Web/Runtime/WebInitialComponent.cs b/src/Umbraco.Web/Runtime/WebInitialComponent.cs index dbd0a1fb3a..5ad51acbc0 100644 --- a/src/Umbraco.Web/Runtime/WebInitialComponent.cs +++ b/src/Umbraco.Web/Runtime/WebInitialComponent.cs @@ -11,6 +11,7 @@ using Umbraco.Core.Configuration; using Umbraco.Core.Hosting; using Umbraco.Core.Strings; using Umbraco.Core.IO; +using Umbraco.Web.Configuration; using Umbraco.Web.Install; using Umbraco.Web.Mvc; using Umbraco.Web.WebApi; @@ -117,7 +118,7 @@ namespace Umbraco.Web.Runtime UmbracoApiControllerTypeCollection apiControllerTypes, IHostingEnvironment hostingEnvironment) { - var umbracoPath = globalSettings.GetUmbracoMvcArea(hostingEnvironment); + var umbracoPath = ConfigModelConversions.ConvertGlobalSettings(globalSettings).GetUmbracoMvcArea(hostingEnvironment); // create the front-end route var defaultRoute = RouteTable.Routes.MapRoute( @@ -154,7 +155,7 @@ namespace Umbraco.Web.Runtime UmbracoApiControllerTypeCollection apiControllerTypes, IHostingEnvironment hostingEnvironment) { - var umbracoPath = globalSettings.GetUmbracoMvcArea(hostingEnvironment); + var umbracoPath = ConfigModelConversions.ConvertGlobalSettings(globalSettings).GetUmbracoMvcArea(hostingEnvironment); // need to find the plugin controllers and route them var pluginControllers = surfaceControllerTypes.Concat(apiControllerTypes).ToArray(); diff --git a/src/Umbraco.Web/Security/BackOfficeOwinUserManager.cs b/src/Umbraco.Web/Security/BackOfficeOwinUserManager.cs index 771c3239b6..92e4fca420 100644 --- a/src/Umbraco.Web/Security/BackOfficeOwinUserManager.cs +++ b/src/Umbraco.Web/Security/BackOfficeOwinUserManager.cs @@ -12,6 +12,7 @@ using Umbraco.Core.Mapping; using Umbraco.Core.Security; using Umbraco.Core.Services; using Umbraco.Net; +using Umbraco.Web.Configuration; namespace Umbraco.Web.Security { @@ -20,7 +21,7 @@ namespace Umbraco.Web.Security public const string OwinMarkerKey = "Umbraco.Web.Security.Identity.BackOfficeUserManagerMarker"; public BackOfficeOwinUserManager( - IUserPasswordConfiguration passwordConfiguration, + IOptions passwordConfiguration, IIpResolver ipResolver, IUserStore store, IOptions optionsAccessor, @@ -30,9 +31,9 @@ namespace Umbraco.Web.Security BackOfficeIdentityErrorDescriber errors, IDataProtectionProvider dataProtectionProvider, ILogger> logger) - : base(ipResolver, store, optionsAccessor, null, userValidators, passwordValidators, keyNormalizer, errors, null, logger, passwordConfiguration) + : base(ipResolver, store, optionsAccessor, null, userValidators, passwordValidators, keyNormalizer, errors, null, logger, ConfigModelConversions.ConvertToOptionsOfUserPasswordConfigurationSettings(passwordConfiguration)) { - PasswordConfiguration = passwordConfiguration; + PasswordConfiguration = ConfigModelConversions.ConvertToOptionsOfUserPasswordConfigurationSettings(passwordConfiguration).Value; InitUserManager(this, dataProtectionProvider); } @@ -53,7 +54,7 @@ namespace Umbraco.Web.Security IDataProtectionProvider dataProtectionProvider, ILogger> logger) { - var store = new BackOfficeUserStore(userService, entityService, externalLoginService, globalSettings, mapper); + var store = new BackOfficeUserStore(userService, entityService, externalLoginService, ConfigModelConversions.ConvertGlobalSettings(globalSettings), mapper); return Create( passwordConfiguration, @@ -103,7 +104,7 @@ namespace Umbraco.Web.Security options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromDays(30); return new BackOfficeOwinUserManager( - passwordConfiguration, + ConfigModelConversions.ConvertToOptionsOfBackOfficeIdentityOptions(passwordConfiguration), ipResolver, customUserStore, new OptionsWrapper(options), diff --git a/src/Umbraco.Web/Security/BackOfficeSignInManager.cs b/src/Umbraco.Web/Security/BackOfficeSignInManager.cs index 021adaed97..c998b579a1 100644 --- a/src/Umbraco.Web/Security/BackOfficeSignInManager.cs +++ b/src/Umbraco.Web/Security/BackOfficeSignInManager.cs @@ -11,6 +11,7 @@ using Umbraco.Core; using Umbraco.Core.BackOffice; using Umbraco.Core.Configuration; using Umbraco.Core.BackOffice; +using Umbraco.Web.Configuration; namespace Umbraco.Web.Security { @@ -78,7 +79,7 @@ namespace Umbraco.Web.Security var user = await _userManager.FindByNameAsync(userName); //if the user is null, create an empty one which can be used for auto-linking - if (user == null) user = BackOfficeIdentityUser.CreateNew(_globalSettings, userName, null, _globalSettings.DefaultUILanguage); + if (user == null) user = BackOfficeIdentityUser.CreateNew(ConfigModelConversions.ConvertGlobalSettings(_globalSettings), userName, null, _globalSettings.DefaultUILanguage); //check the password for the user, this will allow a developer to auto-link //an account if they have specified an IBackOfficeUserPasswordChecker diff --git a/src/Umbraco.Web/Security/GetUserSecondsMiddleWare.cs b/src/Umbraco.Web/Security/GetUserSecondsMiddleWare.cs index 3ab37f0f70..f73f25f859 100644 --- a/src/Umbraco.Web/Security/GetUserSecondsMiddleWare.cs +++ b/src/Umbraco.Web/Security/GetUserSecondsMiddleWare.cs @@ -11,6 +11,7 @@ using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Hosting; using Umbraco.Core.IO; using Umbraco.Core.Security; +using Umbraco.Web.Configuration; namespace Umbraco.Web.Security { @@ -53,7 +54,7 @@ namespace Umbraco.Web.Security if (request.Uri.Scheme.InvariantStartsWith("http") && request.Uri.AbsolutePath.InvariantEquals( - $"{_globalSettings.GetBackOfficePath(_hostingEnvironment)}/backoffice/UmbracoApi/Authentication/GetRemainingTimeoutSeconds")) + $"{ConfigModelConversions.ConvertGlobalSettings(_globalSettings).GetBackOfficePath(_hostingEnvironment)}/backoffice/UmbracoApi/Authentication/GetRemainingTimeoutSeconds")) { var cookie = _authOptions.CookieManager.GetRequestCookie(context, _security.AuthCookieName); if (cookie.IsNullOrWhiteSpace() == false) diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 64fc7b5886..82af69a21c 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -148,6 +148,7 @@ + diff --git a/src/Umbraco.Web/UmbracoApplication.cs b/src/Umbraco.Web/UmbracoApplication.cs index 6334f96d4b..4cdcecc1ce 100644 --- a/src/Umbraco.Web/UmbracoApplication.cs +++ b/src/Umbraco.Web/UmbracoApplication.cs @@ -14,6 +14,7 @@ using Umbraco.Core.Hosting; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Web.Runtime; +using Umbraco.Web.Configuration; namespace Umbraco.Web { @@ -29,8 +30,8 @@ namespace Umbraco.Web var dbProviderFactoryCreator = new UmbracoDbProviderFactoryCreator(); - var globalSettings = configs.Global(); - var connectionStrings = configs.ConnectionStrings(); + var globalSettings = ConfigModelConversions.ConvertGlobalSettings(configs.Global()); + var connectionStrings = ConfigModelConversions.ConvertConnectionStrings(configs.ConnectionStrings()); // Determine if we should use the sql main dom or the default var appSettingMainDomLock = globalSettings.MainDomLock; @@ -44,7 +45,7 @@ namespace Umbraco.Web var requestCache = new HttpRequestAppCache(() => HttpContext.Current != null ? HttpContext.Current.Items : null); var umbracoBootPermissionChecker = new AspNetUmbracoBootPermissionChecker(); - return new CoreRuntime(configs, umbracoVersion, ioHelper, logger, profiler, umbracoBootPermissionChecker, hostingEnvironment, backOfficeInfo, dbProviderFactoryCreator, mainDom, + return new CoreRuntime(globalSettings, connectionStrings, umbracoVersion, ioHelper, logger, profiler, umbracoBootPermissionChecker, hostingEnvironment, backOfficeInfo, dbProviderFactoryCreator, mainDom, GetTypeFinder(hostingEnvironment, logger, profiler), requestCache); } diff --git a/src/Umbraco.Web/UmbracoApplicationBase.cs b/src/Umbraco.Web/UmbracoApplicationBase.cs index 1c447b38aa..984f46bd60 100644 --- a/src/Umbraco.Web/UmbracoApplicationBase.cs +++ b/src/Umbraco.Web/UmbracoApplicationBase.cs @@ -16,6 +16,7 @@ using Umbraco.Core.Logging.Serilog; using Umbraco.Core.Logging.Serilog.Enrichers; using Umbraco.Net; using Umbraco.Web.AspNet; +using Umbraco.Web.Configuration; using Umbraco.Web.Hosting; using Umbraco.Web.Logging; using Current = Umbraco.Web.Composing.Current; @@ -44,7 +45,7 @@ namespace Umbraco.Web Path.Combine(hostingEnvironment.ApplicationPhysicalPath, "App_Data\\Logs"), Path.Combine(hostingEnvironment.ApplicationPhysicalPath, "config\\serilog.config"), Path.Combine(hostingEnvironment.ApplicationPhysicalPath, "config\\serilog.user.config")); - var ioHelper = new IOHelper(hostingEnvironment, globalSettings); + var ioHelper = new IOHelper(hostingEnvironment); var logger = SerilogLogger.CreateWithDefaultConfiguration(hostingEnvironment, loggingConfiguration); var configs = configFactory.Create(); @@ -127,7 +128,7 @@ namespace Umbraco.Web /// protected virtual IRegister GetRegister(IGlobalSettings globalSettings) { - return RegisterFactory.Create(globalSettings); + return RegisterFactory.Create(ConfigModelConversions.ConvertGlobalSettings(globalSettings)); } // events - in the order they trigger @@ -160,7 +161,7 @@ namespace Umbraco.Web var globalSettings = Umbraco.Composing.Current.Configs.Global(); - var umbracoVersion = new UmbracoVersion(globalSettings); + var umbracoVersion = new UmbracoVersion(ConfigModelConversions.ConvertGlobalSettings(globalSettings)); // create the register for the application, and boot // the boot manager is responsible for registrations diff --git a/src/Umbraco.Web/UmbracoContext.cs b/src/Umbraco.Web/UmbracoContext.cs index ae1cf885b3..e94e0acc0b 100644 --- a/src/Umbraco.Web/UmbracoContext.cs +++ b/src/Umbraco.Web/UmbracoContext.cs @@ -5,6 +5,7 @@ using Umbraco.Core.Configuration; using Umbraco.Core.Hosting; using Umbraco.Core.Models.PublishedContent; using Umbraco.Web.Composing; +using Umbraco.Web.Configuration; using Umbraco.Web.PublishedCache; using Umbraco.Web.Routing; using Umbraco.Web.Security; @@ -181,7 +182,7 @@ namespace Umbraco.Web { var request = GetRequestFromContext(); if (request?.Url != null - && request.Url.IsBackOfficeRequest(_globalSettings, _hostingEnvironment) == false + && request.Url.IsBackOfficeRequest(ConfigModelConversions.ConvertGlobalSettings(_globalSettings), _hostingEnvironment) == false && Security.CurrentUser != null) { var previewToken = _cookieManager.GetPreviewCookieValue(); // may be null or empty diff --git a/src/Umbraco.Web/UmbracoInjectedModule.cs b/src/Umbraco.Web/UmbracoInjectedModule.cs index ecb67c997d..a610d216a3 100644 --- a/src/Umbraco.Web/UmbracoInjectedModule.cs +++ b/src/Umbraco.Web/UmbracoInjectedModule.cs @@ -13,6 +13,7 @@ using Umbraco.Core.Logging; using Umbraco.Web.Composing; using Umbraco.Web.Routing; using Umbraco.Web.Security; +using Umbraco.Web.Configuration; namespace Umbraco.Web { @@ -113,7 +114,7 @@ namespace Umbraco.Web var umbracoContext = Current.UmbracoContext; // re-write for the default back office path - if (httpContext.Request.Url.IsDefaultBackOfficeRequest(_globalSettings, _hostingEnvironment)) + if (httpContext.Request.Url.IsDefaultBackOfficeRequest(ConfigModelConversions.ConvertGlobalSettings(_globalSettings), _hostingEnvironment)) { if (EnsureRuntime(httpContext, umbracoContext.OriginalRequestUrl)) RewriteToBackOfficeHandler(httpContext); @@ -246,7 +247,7 @@ namespace Umbraco.Web private void RewriteToBackOfficeHandler(HttpContextBase context) { // GlobalSettings.Path has already been through IOHelper.ResolveUrl() so it begins with / and vdir (if any) - var rewritePath = _globalSettings.GetBackOfficePath(_hostingEnvironment).TrimEnd('/') + "/Default"; + var rewritePath = ConfigModelConversions.ConvertGlobalSettings(_globalSettings).GetBackOfficePath(_hostingEnvironment).TrimEnd('/') + "/Default"; // rewrite the path to the path of the handler (i.e. /umbraco/RenderMvc) context.RewritePath(rewritePath, "", "", false); @@ -279,7 +280,7 @@ namespace Umbraco.Web var query = pcr.Uri.Query.TrimStart('?'); // GlobalSettings.Path has already been through IOHelper.ResolveUrl() so it begins with / and vdir (if any) - var rewritePath = _globalSettings.GetBackOfficePath(_hostingEnvironment).TrimEnd('/') + "/RenderMvc"; + var rewritePath = ConfigModelConversions.ConvertGlobalSettings(_globalSettings).GetBackOfficePath(_hostingEnvironment).TrimEnd('/') + "/RenderMvc"; // rewrite the path to the path of the handler (i.e. /umbraco/RenderMvc) context.RewritePath(rewritePath, "", query, false); diff --git a/src/Umbraco.Web/WebApi/Filters/CheckIfUserTicketDataIsStaleAttribute.cs b/src/Umbraco.Web/WebApi/Filters/CheckIfUserTicketDataIsStaleAttribute.cs index 09fd5e080c..bae6d00048 100644 --- a/src/Umbraco.Web/WebApi/Filters/CheckIfUserTicketDataIsStaleAttribute.cs +++ b/src/Umbraco.Web/WebApi/Filters/CheckIfUserTicketDataIsStaleAttribute.cs @@ -12,6 +12,7 @@ using Umbraco.Core.Security; using Umbraco.Web.Security; using Umbraco.Core.Mapping; using Umbraco.Core.Models; +using Umbraco.Web.Configuration; namespace Umbraco.Web.WebApi.Filters { @@ -78,7 +79,7 @@ namespace Umbraco.Web.WebApi.Filters () => user.Username != identity.Username, () => { - var culture = user.GetUserCulture(Current.Services.TextService, Current.Configs.Global()); + var culture = user.GetUserCulture(Current.Services.TextService, ConfigModelConversions.ConvertGlobalSettings(Current.Configs.Global())); return culture != null && culture.ToString() != identity.Culture; }, () => user.AllowedSections.UnsortedSequenceEqual(identity.AllowedApplications) == false, From 2cd91a5a542c7adea172dfec8569f6d8b67e2753 Mon Sep 17 00:00:00 2001 From: Andy Butland Date: Sun, 23 Aug 2020 23:36:48 +0200 Subject: [PATCH 246/826] Converted to IOptions over IOptionsSnapshot due to the latter only working in scoped services. Further amends to return to booting application. --- .../BackOffice/IdentityMapDefinition.cs | 2 +- .../Configuration/Models/ContentSettings.cs | 4 +- .../Configuration/Models/ImagingSettings.cs | 4 +- .../Models/RequestHandlerSettings.cs | 74 +++++++++++++++++++ src/Umbraco.Core/IO/FileSystems.cs | 8 +- .../Packaging/PackagesRepository.cs | 2 +- src/Umbraco.Core/Routing/AliasUrlProvider.cs | 14 ++-- .../Routing/ContentFinderByIdPath.cs | 2 +- .../Routing/ContentFinderByUrlAndTemplate.cs | 2 +- .../Routing/DefaultUrlProvider.cs | 16 ++-- src/Umbraco.Core/Routing/PublishedRequest.cs | 2 +- src/Umbraco.Core/Routing/PublishedRouter.cs | 2 +- src/Umbraco.Core/Routing/UriUtility.cs | 3 +- src/Umbraco.Core/Routing/UrlProvider.cs | 2 +- src/Umbraco.Core/Scheduling/KeepAlive.cs | 2 +- .../Strings/DefaultShortStringHelper.cs | 6 +- .../Strings/DefaultShortStringHelperConfig.cs | 3 +- src/Umbraco.Core/Templates/HtmlUrlParser.cs | 2 +- .../LuceneIndexCreator.cs | 2 +- .../UmbracoIndexesCreator.cs | 2 +- .../BackOffice/BackOfficeUserStore.cs | 2 +- .../Compose/NotificationsComponent.cs | 2 +- .../CompositionExtensions/FileSystems.cs | 2 +- .../CompositionExtensions/Services.cs | 4 +- .../EmailNotificationMethod.cs | 4 +- .../Install/FilePermissionHelper.cs | 2 +- .../Install/InstallHelper.cs | 2 +- .../InstallSteps/DatabaseConfigureStep.cs | 2 +- .../InstallSteps/DatabaseUpgradeStep.cs | 4 +- .../Install/InstallSteps/NewInstallStep.cs | 6 +- .../Enrichers/ThreadAbortExceptionEnricher.cs | 2 +- .../Media/UploadAutoFillProperties.cs | 2 +- .../Migrations/Install/DatabaseBuilder.cs | 2 +- .../Mapping/ContentTypeMapDefinition.cs | 2 +- .../Models/Mapping/DataTypeMapDefinition.cs | 2 +- .../Mapping/MemberTabsAndPropertiesMapper.cs | 2 +- .../Models/Mapping/UserMapDefinition.cs | 2 +- .../Implement/LanguageRepository.cs | 2 +- .../Implement/ScriptRepository.cs | 2 +- .../Implement/StylesheetRepository.cs | 2 +- .../Repositories/Implement/UserRepository.cs | 4 +- .../FileUploadPropertyEditor.cs | 2 +- .../FileUploadPropertyValueEditor.cs | 2 +- .../ImageCropperPropertyEditor.cs | 2 +- .../UploadFileTypeValidator.cs | 2 +- .../Routing/ContentFinderByConfigured404.cs | 2 +- .../Routing/RedirectTrackingComponent.cs | 2 +- .../Runtime/CoreInitialComponent.cs | 3 +- .../Runtime/CoreInitialComposer.cs | 4 +- .../Scheduling/LogScrubber.cs | 2 +- .../Scheduling/SchedulerComponent.cs | 2 +- .../Scoping/ScopeProvider.cs | 2 +- .../Services/Implement/FileService.cs | 2 +- .../Services/Implement/NotificationService.cs | 2 +- .../Services/Implement/UserService.cs | 2 +- .../Users/EmailSender.cs | 4 +- .../WebAssets/BackOfficeWebAssets.cs | 2 +- .../Building/ModelsGenerator.cs | 2 +- .../Compose/ModelsBuilderComposer.cs | 2 +- .../ModelsGenerationError.cs | 2 +- .../PureLiveModelFactory.cs | 2 +- .../ContentCache.cs | 2 +- .../PublishedSnapshotService.cs | 4 +- .../Controllers/AuthenticationController.cs | 6 +- .../Controllers/BackOfficeAssetsController.cs | 2 +- .../Controllers/BackOfficeController.cs | 2 +- .../Controllers/BackOfficeServerVariables.cs | 8 +- .../Controllers/CodeFileController.cs | 2 +- .../Controllers/ContentTypeController.cs | 2 +- .../Controllers/CurrentUserController.cs | 2 +- .../Controllers/DataTypeController.cs | 2 +- .../Controllers/DictionaryController.cs | 2 +- .../Controllers/ImagesController.cs | 2 +- .../Controllers/LanguageController.cs | 2 +- .../Controllers/MediaController.cs | 2 +- .../Controllers/MemberController.cs | 2 +- .../Controllers/PreviewController.cs | 2 +- .../RedirectUrlManagementController.cs | 2 +- .../Controllers/TinyMceController.cs | 2 +- .../Controllers/TourController.cs | 2 +- .../Controllers/UpdateCheckController.cs | 4 +- .../Controllers/UsersController.cs | 6 +- ...coBackOfficeServiceCollectionExtensions.cs | 2 +- .../SetAngularAntiForgeryTokensAttribute.cs | 2 +- .../UmbracoWebApiRequireHttpsAttribute.cs | 2 +- .../Mapping/MediaMapDefinition.cs | 2 +- .../Routing/BackOfficeAreaRoutes.cs | 2 +- .../Security/BackOfficeSessionIdValidator.cs | 2 +- .../ConfigureBackOfficeCookieOptions.cs | 4 +- .../ConfigureBackOfficeIdentityOptions.cs | 2 +- .../PreviewAuthenticationMiddleware.cs | 2 +- .../Trees/ContentTreeController.cs | 2 +- .../AspNetCore/AspNetCoreBackOfficeInfo.cs | 2 +- .../AspNetCoreHostingEnvironment.cs | 2 +- .../AspNetCore/AspNetCoreRequestAccessor.cs | 2 +- .../AspNetCore/UmbracoViewPage.cs | 4 +- .../UmbracoCoreServiceCollectionExtensions.cs | 9 ++- .../UmbracoWebServiceCollectionExtensions.cs | 2 +- .../Filters/ModelBindingExceptionFilter.cs | 2 +- .../Filters/StatusCodeResultAttribute.cs | 2 +- .../Install/InstallController.cs | 2 +- .../Macros/MacroRenderer.cs | 2 +- .../Runtime/AspNetCoreComposer.cs | 2 +- .../Security/WebSecurity.cs | 2 +- .../Templates/TemplateRenderer.cs | 2 +- .../UmbracoContext/UmbracoContextFactory.cs | 2 +- .../umbraco/UmbracoBackOffice/Default.cshtml | 2 +- .../umbraco/UmbracoBackOffice/Preview.cshtml | 2 +- 108 files changed, 230 insertions(+), 146 deletions(-) create mode 100644 src/Umbraco.Core/Configuration/Models/RequestHandlerSettings.cs diff --git a/src/Umbraco.Core/BackOffice/IdentityMapDefinition.cs b/src/Umbraco.Core/BackOffice/IdentityMapDefinition.cs index e002ea1c8d..61fdf82d19 100644 --- a/src/Umbraco.Core/BackOffice/IdentityMapDefinition.cs +++ b/src/Umbraco.Core/BackOffice/IdentityMapDefinition.cs @@ -15,7 +15,7 @@ namespace Umbraco.Core.BackOffice private readonly IEntityService _entityService; private readonly GlobalSettings _globalSettings; - public IdentityMapDefinition(ILocalizedTextService textService, IEntityService entityService, IOptionsSnapshot globalSettings) + public IdentityMapDefinition(ILocalizedTextService textService, IEntityService entityService, IOptions globalSettings) { _textService = textService; _entityService = entityService; diff --git a/src/Umbraco.Core/Configuration/Models/ContentSettings.cs b/src/Umbraco.Core/Configuration/Models/ContentSettings.cs index d1664c2985..4cc74f709a 100644 --- a/src/Umbraco.Core/Configuration/Models/ContentSettings.cs +++ b/src/Umbraco.Core/Configuration/Models/ContentSettings.cs @@ -11,9 +11,9 @@ namespace Umbraco.Core.Configuration.Models private const string DefaultPreviewBadge = @"
Preview modeClick to end
"; - public ContentNotificationSettings Notifications { get; set; } + public ContentNotificationSettings Notifications { get; set; } = new ContentNotificationSettings(); - public ContentImagingSettings Imaging { get; set; } + public ContentImagingSettings Imaging { get; set; } = new ContentImagingSettings(); public bool ResolveUrlsFromTextString { get; set; } = false; diff --git a/src/Umbraco.Core/Configuration/Models/ImagingSettings.cs b/src/Umbraco.Core/Configuration/Models/ImagingSettings.cs index afc55561bb..2f253b151b 100644 --- a/src/Umbraco.Core/Configuration/Models/ImagingSettings.cs +++ b/src/Umbraco.Core/Configuration/Models/ImagingSettings.cs @@ -2,8 +2,8 @@ { public class ImagingSettings { - public ImagingCacheSettings Cache { get; set; } + public ImagingCacheSettings Cache { get; set; } = new ImagingCacheSettings(); - public ImagingResizeSettings Resize { get; set; } + public ImagingResizeSettings Resize { get; set; } = new ImagingResizeSettings(); } } diff --git a/src/Umbraco.Core/Configuration/Models/RequestHandlerSettings.cs b/src/Umbraco.Core/Configuration/Models/RequestHandlerSettings.cs new file mode 100644 index 0000000000..f00658a0be --- /dev/null +++ b/src/Umbraco.Core/Configuration/Models/RequestHandlerSettings.cs @@ -0,0 +1,74 @@ +using System.Collections.Generic; +using Umbraco.Core.Configuration.UmbracoSettings; + +namespace Umbraco.Core.Configuration.Models +{ + public class RequestHandlerSettings + { + private const string Prefix = Constants.Configuration.ConfigPrefix + "RequestHandler:"; + private static readonly CharItem[] DefaultCharCollection = + { + new CharItem { Char = " ", Replacement = "-" }, + new CharItem { Char = "\"", Replacement = "" }, + new CharItem { Char = "'", Replacement = "" }, + new CharItem { Char = "%", Replacement = "" }, + new CharItem { Char = ".", Replacement = "" }, + new CharItem { Char = ";", Replacement = "" }, + new CharItem { Char = "/", Replacement = "" }, + new CharItem { Char = "\\", Replacement = "" }, + new CharItem { Char = ":", Replacement = "" }, + new CharItem { Char = "#", Replacement = "" }, + new CharItem { Char = "+", Replacement = "plus" }, + new CharItem { Char = "*", Replacement = "star" }, + new CharItem { Char = "&", Replacement = "" }, + new CharItem { Char = "?", Replacement = "" }, + new CharItem { Char = "æ", Replacement = "ae" }, + new CharItem { Char = "ä", Replacement = "ae" }, + new CharItem { Char = "ø", Replacement = "oe" }, + new CharItem { Char = "ö", Replacement = "oe" }, + new CharItem { Char = "å", Replacement = "aa" }, + new CharItem { Char = "ü", Replacement = "ue" }, + new CharItem { Char = "ß", Replacement = "ss" }, + new CharItem { Char = "|", Replacement = "-" }, + new CharItem { Char = "<", Replacement = "" }, + new CharItem { Char = ">", Replacement = "" } + }; + + public bool AddTrailingSlash { get; set; } = true; + + public bool ConvertUrlsToAscii { get; set; } = true; + + public bool TryConvertUrlsToAscii { get; set; } = false; + + //We need to special handle ":", as this character is special in keys + public IEnumerable CharCollection + { + get + { + // TODO: implement from configuration + + //var collection = _configuration.GetSection(Prefix + "CharCollection").GetChildren() + // .Select(x => new CharItem() + // { + // Char = x.GetValue("Char"), + // Replacement = x.GetValue("Replacement"), + // }).ToArray(); + + //if (collection.Any() || _configuration.GetSection("Prefix").GetChildren().Any(x => + // x.Key.Equals("CharCollection", StringComparison.OrdinalIgnoreCase))) + //{ + // return collection; + //} + + return DefaultCharCollection; + } + } + + + public class CharItem : IChar + { + public string Char { get; set; } + public string Replacement { get; set; } + } + } +} diff --git a/src/Umbraco.Core/IO/FileSystems.cs b/src/Umbraco.Core/IO/FileSystems.cs index ba5fcb91f3..505f714620 100644 --- a/src/Umbraco.Core/IO/FileSystems.cs +++ b/src/Umbraco.Core/IO/FileSystems.cs @@ -6,6 +6,8 @@ using Umbraco.Core.Logging; using Umbraco.Core.Composing; using Umbraco.Core.Configuration; using Umbraco.Core.Hosting; +using Umbraco.Core.Configuration.Models; +using Microsoft.Extensions.Options; namespace Umbraco.Core.IO { @@ -36,12 +38,12 @@ namespace Umbraco.Core.IO #region Constructor // DI wants a public ctor - public FileSystems(IFactory container, ILogger logger, IIOHelper ioHelper, IGlobalSettings globalSettings, IHostingEnvironment hostingEnvironment) + public FileSystems(IFactory container, ILogger logger, IIOHelper ioHelper, IOptions globalSettings, IHostingEnvironment hostingEnvironment) { _container = container; _logger = logger; _ioHelper = ioHelper; - _globalSettings = globalSettings; + _globalSettings = globalSettings.Value; _hostingEnvironment = hostingEnvironment; } @@ -156,7 +158,7 @@ namespace Umbraco.Core.IO // internal for tests internal IReadOnlyDictionary Paths => _paths; - private IGlobalSettings _globalSettings; + private GlobalSettings _globalSettings; private readonly IHostingEnvironment _hostingEnvironment; /// diff --git a/src/Umbraco.Core/Packaging/PackagesRepository.cs b/src/Umbraco.Core/Packaging/PackagesRepository.cs index b73747fab8..d9c802121d 100644 --- a/src/Umbraco.Core/Packaging/PackagesRepository.cs +++ b/src/Umbraco.Core/Packaging/PackagesRepository.cs @@ -63,7 +63,7 @@ namespace Umbraco.Core.Packaging IHostingEnvironment hostingEnvironment, IEntityXmlSerializer serializer, ILogger logger, IUmbracoVersion umbracoVersion, - IOptionsSnapshot globalSettings, + IOptions globalSettings, string packageRepositoryFileName, string tempFolderPath = null, string packagesFolderPath = null, string mediaFolderPath = null) { diff --git a/src/Umbraco.Core/Routing/AliasUrlProvider.cs b/src/Umbraco.Core/Routing/AliasUrlProvider.cs index e71de2f6c6..0d919614f3 100644 --- a/src/Umbraco.Core/Routing/AliasUrlProvider.cs +++ b/src/Umbraco.Core/Routing/AliasUrlProvider.cs @@ -1,8 +1,10 @@ using System; using System.Collections.Generic; using System.Linq; +using Microsoft.Extensions.Options; using Umbraco.Core; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Models.PublishedContent; @@ -13,17 +15,15 @@ namespace Umbraco.Web.Routing /// public class AliasUrlProvider : IUrlProvider { - private readonly IGlobalSettings _globalSettings; - private readonly IRequestHandlerSettings _requestConfig; + private readonly RequestHandlerSettings _requestConfig; private readonly ISiteDomainHelper _siteDomainHelper; private readonly IUmbracoContextAccessor _umbracoContextAccessor; private readonly UriUtility _uriUtility; private readonly IPublishedValueFallback _publishedValueFallback; - public AliasUrlProvider(IGlobalSettings globalSettings, IRequestHandlerSettings requestConfig, ISiteDomainHelper siteDomainHelper, UriUtility uriUtility, IPublishedValueFallback publishedValueFallback, IUmbracoContextAccessor umbracoContextAccessor) + public AliasUrlProvider(IOptions requestConfig, ISiteDomainHelper siteDomainHelper, UriUtility uriUtility, IPublishedValueFallback publishedValueFallback, IUmbracoContextAccessor umbracoContextAccessor) { - _globalSettings = globalSettings; - _requestConfig = requestConfig; + _requestConfig = requestConfig.Value; _siteDomainHelper = siteDomainHelper; _uriUtility = uriUtility; _publishedValueFallback = publishedValueFallback; @@ -100,7 +100,7 @@ namespace Umbraco.Web.Routing { var path = "/" + alias; var uri = new Uri(path, UriKind.Relative); - yield return UrlInfo.Url(_uriUtility.UriFromUmbraco(uri, _globalSettings, _requestConfig).ToString()); + yield return UrlInfo.Url(_uriUtility.UriFromUmbraco(uri, _requestConfig).ToString()); } } else @@ -127,7 +127,7 @@ namespace Umbraco.Web.Routing { var path = "/" + alias; var uri = new Uri(CombinePaths(domainUri.Uri.GetLeftPart(UriPartial.Path), path)); - yield return UrlInfo.Url(_uriUtility.UriFromUmbraco(uri, _globalSettings, _requestConfig).ToString(), domainUri.Culture.Name); + yield return UrlInfo.Url(_uriUtility.UriFromUmbraco(uri, _requestConfig).ToString(), domainUri.Culture.Name); } } } diff --git a/src/Umbraco.Core/Routing/ContentFinderByIdPath.cs b/src/Umbraco.Core/Routing/ContentFinderByIdPath.cs index 3d69f8ab46..a9d67c24fb 100644 --- a/src/Umbraco.Core/Routing/ContentFinderByIdPath.cs +++ b/src/Umbraco.Core/Routing/ContentFinderByIdPath.cs @@ -21,7 +21,7 @@ namespace Umbraco.Web.Routing private readonly IRequestAccessor _requestAccessor; private readonly WebRoutingSettings _webRoutingSettings; - public ContentFinderByIdPath(IOptionsSnapshot webRoutingSettings, ILogger logger, IRequestAccessor requestAccessor) + public ContentFinderByIdPath(IOptions webRoutingSettings, ILogger logger, IRequestAccessor requestAccessor) { _webRoutingSettings = webRoutingSettings.Value ?? throw new System.ArgumentNullException(nameof(webRoutingSettings)); _logger = logger ?? throw new System.ArgumentNullException(nameof(logger)); diff --git a/src/Umbraco.Core/Routing/ContentFinderByUrlAndTemplate.cs b/src/Umbraco.Core/Routing/ContentFinderByUrlAndTemplate.cs index 47dc729654..b6a01c0c51 100644 --- a/src/Umbraco.Core/Routing/ContentFinderByUrlAndTemplate.cs +++ b/src/Umbraco.Core/Routing/ContentFinderByUrlAndTemplate.cs @@ -23,7 +23,7 @@ namespace Umbraco.Web.Routing private readonly IContentTypeService _contentTypeService; private readonly WebRoutingSettings _webRoutingSettings; - public ContentFinderByUrlAndTemplate(ILogger logger, IFileService fileService, IContentTypeService contentTypeService, IOptionsSnapshot webRoutingSettings) + public ContentFinderByUrlAndTemplate(ILogger logger, IFileService fileService, IContentTypeService contentTypeService, IOptions webRoutingSettings) : base(logger) { _fileService = fileService; diff --git a/src/Umbraco.Core/Routing/DefaultUrlProvider.cs b/src/Umbraco.Core/Routing/DefaultUrlProvider.cs index f56d96b6b3..2af36465dd 100644 --- a/src/Umbraco.Core/Routing/DefaultUrlProvider.cs +++ b/src/Umbraco.Core/Routing/DefaultUrlProvider.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; +using Microsoft.Extensions.Options; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Logging; using Umbraco.Core.Models.PublishedContent; @@ -12,18 +14,18 @@ namespace Umbraco.Web.Routing /// public class DefaultUrlProvider : IUrlProvider { - private readonly IRequestHandlerSettings _requestSettings; + private readonly RequestHandlerSettings _requestSettings; private readonly ILogger _logger; - private readonly IGlobalSettings _globalSettings; + private readonly GlobalSettings _globalSettings; private readonly ISiteDomainHelper _siteDomainHelper; private readonly IUmbracoContextAccessor _umbracoContextAccessor; private readonly UriUtility _uriUtility; - public DefaultUrlProvider(IRequestHandlerSettings requestSettings, ILogger logger, IGlobalSettings globalSettings, ISiteDomainHelper siteDomainHelper, IUmbracoContextAccessor umbracoContextAccessor, UriUtility uriUtility) + public DefaultUrlProvider(IOptions requestSettings, ILogger logger, IOptions globalSettings, ISiteDomainHelper siteDomainHelper, IUmbracoContextAccessor umbracoContextAccessor, UriUtility uriUtility) { - _requestSettings = requestSettings; + _requestSettings = requestSettings.Value; _logger = logger; - _globalSettings = globalSettings; + _globalSettings = globalSettings.Value; _siteDomainHelper = siteDomainHelper; _uriUtility = uriUtility; _umbracoContextAccessor = umbracoContextAccessor; @@ -113,7 +115,7 @@ namespace Umbraco.Web.Routing var path = pos == 0 ? route : route.Substring(pos); var uri = new Uri(CombinePaths(d.Uri.GetLeftPart(UriPartial.Path), path)); - uri = _uriUtility.UriFromUmbraco(uri, _globalSettings, _requestSettings); + uri = _uriUtility.UriFromUmbraco(uri, _requestSettings); yield return UrlInfo.Url(uri.ToString(), culture); } } @@ -172,7 +174,7 @@ namespace Umbraco.Web.Routing // UriFromUmbraco will handle vdir // meaning it will add vdir into domain urls too! - return _uriUtility.UriFromUmbraco(uri, _globalSettings, _requestSettings); + return _uriUtility.UriFromUmbraco(uri, _requestSettings); } string CombinePaths(string path1, string path2) diff --git a/src/Umbraco.Core/Routing/PublishedRequest.cs b/src/Umbraco.Core/Routing/PublishedRequest.cs index 7400623a6f..d1bf6fda0f 100644 --- a/src/Umbraco.Core/Routing/PublishedRequest.cs +++ b/src/Umbraco.Core/Routing/PublishedRequest.cs @@ -35,7 +35,7 @@ namespace Umbraco.Web.Routing /// The published router. /// The Umbraco context. /// The request Uri. - public PublishedRequest(IPublishedRouter publishedRouter, IUmbracoContext umbracoContext, IOptionsSnapshot webRoutingSettings, Uri uri = null) + public PublishedRequest(IPublishedRouter publishedRouter, IUmbracoContext umbracoContext, IOptions webRoutingSettings, Uri uri = null) : this(publishedRouter, umbracoContext, webRoutingSettings.Value, uri) { } diff --git a/src/Umbraco.Core/Routing/PublishedRouter.cs b/src/Umbraco.Core/Routing/PublishedRouter.cs index d77f64ca5e..207e8d7ed4 100644 --- a/src/Umbraco.Core/Routing/PublishedRouter.cs +++ b/src/Umbraco.Core/Routing/PublishedRouter.cs @@ -38,7 +38,7 @@ namespace Umbraco.Web.Routing /// Initializes a new instance of the class. /// public PublishedRouter( - IOptionsSnapshot webRoutingSettings, + IOptions webRoutingSettings, ContentFinderCollection contentFinders, IContentLastChanceFinder contentLastChanceFinder, IVariationContextAccessor variationContextAccessor, diff --git a/src/Umbraco.Core/Routing/UriUtility.cs b/src/Umbraco.Core/Routing/UriUtility.cs index 1ff6ba7436..1bcfab6490 100644 --- a/src/Umbraco.Core/Routing/UriUtility.cs +++ b/src/Umbraco.Core/Routing/UriUtility.cs @@ -2,6 +2,7 @@ using System.Text; using Umbraco.Core; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Hosting; @@ -62,7 +63,7 @@ namespace Umbraco.Web // maps an internal umbraco uri to a public uri // ie with virtual directory, .aspx if required... - public Uri UriFromUmbraco(Uri uri, IGlobalSettings globalSettings, IRequestHandlerSettings requestConfig) + public Uri UriFromUmbraco(Uri uri, RequestHandlerSettings requestConfig) { var path = uri.GetSafeAbsolutePath(); diff --git a/src/Umbraco.Core/Routing/UrlProvider.cs b/src/Umbraco.Core/Routing/UrlProvider.cs index 9e1dd9a01d..6ad44c7716 100644 --- a/src/Umbraco.Core/Routing/UrlProvider.cs +++ b/src/Umbraco.Core/Routing/UrlProvider.cs @@ -26,7 +26,7 @@ namespace Umbraco.Web.Routing /// The list of media url providers. /// The current variation accessor. /// - public UrlProvider(IUmbracoContextAccessor umbracoContextAccessor, IOptionsSnapshot routingSettings, UrlProviderCollection urlProviders, MediaUrlProviderCollection mediaUrlProviders, IVariationContextAccessor variationContextAccessor) + public UrlProvider(IUmbracoContextAccessor umbracoContextAccessor, IOptions routingSettings, UrlProviderCollection urlProviders, MediaUrlProviderCollection mediaUrlProviders, IVariationContextAccessor variationContextAccessor) { if (routingSettings == null) throw new ArgumentNullException(nameof(routingSettings)); diff --git a/src/Umbraco.Core/Scheduling/KeepAlive.cs b/src/Umbraco.Core/Scheduling/KeepAlive.cs index d085569e97..dec9d9daad 100644 --- a/src/Umbraco.Core/Scheduling/KeepAlive.cs +++ b/src/Umbraco.Core/Scheduling/KeepAlive.cs @@ -20,7 +20,7 @@ namespace Umbraco.Web.Scheduling private static HttpClient _httpClient; public KeepAlive(IBackgroundTaskRunner runner, int delayMilliseconds, int periodMilliseconds, - IRequestAccessor requestAccessor, IMainDom mainDom, IOptionsSnapshot keepAliveSettings, IProfilingLogger logger, IServerRegistrar serverRegistrar) + IRequestAccessor requestAccessor, IMainDom mainDom, IOptions keepAliveSettings, IProfilingLogger logger, IServerRegistrar serverRegistrar) : this(runner, delayMilliseconds, periodMilliseconds, requestAccessor, mainDom, keepAliveSettings.Value, logger, serverRegistrar) { } diff --git a/src/Umbraco.Core/Strings/DefaultShortStringHelper.cs b/src/Umbraco.Core/Strings/DefaultShortStringHelper.cs index c3e7fa85c3..3894525d2d 100644 --- a/src/Umbraco.Core/Strings/DefaultShortStringHelper.cs +++ b/src/Umbraco.Core/Strings/DefaultShortStringHelper.cs @@ -4,6 +4,8 @@ using System.IO; using System.Linq; using System.Globalization; using Umbraco.Core.Configuration.UmbracoSettings; +using Umbraco.Core.Configuration.Models; +using Microsoft.Extensions.Options; namespace Umbraco.Core.Strings { @@ -19,9 +21,9 @@ namespace Umbraco.Core.Strings { #region Ctor, consts and vars - public DefaultShortStringHelper(IRequestHandlerSettings settings) + public DefaultShortStringHelper(IOptions settings) { - _config = new DefaultShortStringHelperConfig().WithDefault(settings); + _config = new DefaultShortStringHelperConfig().WithDefault(settings.Value); } // clones the config so it cannot be changed at runtime diff --git a/src/Umbraco.Core/Strings/DefaultShortStringHelperConfig.cs b/src/Umbraco.Core/Strings/DefaultShortStringHelperConfig.cs index 25ee781ae9..32c02c09fb 100644 --- a/src/Umbraco.Core/Strings/DefaultShortStringHelperConfig.cs +++ b/src/Umbraco.Core/Strings/DefaultShortStringHelperConfig.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Configuration.UmbracoSettings; namespace Umbraco.Core.Strings @@ -57,7 +58,7 @@ namespace Umbraco.Core.Strings /// Sets the default configuration. /// /// The short string helper. - public DefaultShortStringHelperConfig WithDefault(IRequestHandlerSettings requestHandlerSettings) + public DefaultShortStringHelperConfig WithDefault(RequestHandlerSettings requestHandlerSettings) { UrlReplaceCharacters = requestHandlerSettings.CharCollection .Where(x => string.IsNullOrEmpty(x.Char) == false) diff --git a/src/Umbraco.Core/Templates/HtmlUrlParser.cs b/src/Umbraco.Core/Templates/HtmlUrlParser.cs index 8a6baa0aa3..60b6f829b0 100644 --- a/src/Umbraco.Core/Templates/HtmlUrlParser.cs +++ b/src/Umbraco.Core/Templates/HtmlUrlParser.cs @@ -15,7 +15,7 @@ namespace Umbraco.Web.Templates private static readonly Regex ResolveUrlPattern = new Regex("(=[\"\']?)(\\W?\\~(?:.(?![\"\']?\\s+(?:\\S+)=|[>\"\']))+.)[\"\']?", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace); - public HtmlUrlParser(IOptionsSnapshot contentSettings, IProfilingLogger logger, IIOHelper ioHelper) + public HtmlUrlParser(IOptions contentSettings, IProfilingLogger logger, IIOHelper ioHelper) { _contentSettings = contentSettings.Value; _ioHelper = ioHelper; diff --git a/src/Umbraco.Examine.Lucene/LuceneIndexCreator.cs b/src/Umbraco.Examine.Lucene/LuceneIndexCreator.cs index 6edbb05b85..5c6b111d87 100644 --- a/src/Umbraco.Examine.Lucene/LuceneIndexCreator.cs +++ b/src/Umbraco.Examine.Lucene/LuceneIndexCreator.cs @@ -22,7 +22,7 @@ namespace Umbraco.Examine private readonly IHostingEnvironment _hostingEnvironment; private readonly IndexCreatorSettings _settings; - protected LuceneIndexCreator(ITypeFinder typeFinder, IHostingEnvironment hostingEnvironment, IOptionsSnapshot settings) + protected LuceneIndexCreator(ITypeFinder typeFinder, IHostingEnvironment hostingEnvironment, IOptions settings) { _typeFinder = typeFinder; _hostingEnvironment = hostingEnvironment; diff --git a/src/Umbraco.Examine.Lucene/UmbracoIndexesCreator.cs b/src/Umbraco.Examine.Lucene/UmbracoIndexesCreator.cs index 09dc40b32b..c4eb2249fa 100644 --- a/src/Umbraco.Examine.Lucene/UmbracoIndexesCreator.cs +++ b/src/Umbraco.Examine.Lucene/UmbracoIndexesCreator.cs @@ -30,7 +30,7 @@ namespace Umbraco.Examine IUmbracoIndexConfig umbracoIndexConfig, IHostingEnvironment hostingEnvironment, IRuntimeState runtimeState, - IOptionsSnapshot settings) : base(typeFinder, hostingEnvironment, settings) + IOptions settings) : base(typeFinder, hostingEnvironment, settings) { ProfilingLogger = profilingLogger ?? throw new System.ArgumentNullException(nameof(profilingLogger)); LanguageService = languageService ?? throw new System.ArgumentNullException(nameof(languageService)); diff --git a/src/Umbraco.Infrastructure/BackOffice/BackOfficeUserStore.cs b/src/Umbraco.Infrastructure/BackOffice/BackOfficeUserStore.cs index 7c2eb1adfd..0c5f5fd6ab 100644 --- a/src/Umbraco.Infrastructure/BackOffice/BackOfficeUserStore.cs +++ b/src/Umbraco.Infrastructure/BackOffice/BackOfficeUserStore.cs @@ -38,7 +38,7 @@ namespace Umbraco.Core.BackOffice private readonly UmbracoMapper _mapper; private bool _disposed = false; - public BackOfficeUserStore(IUserService userService, IEntityService entityService, IExternalLoginService externalLoginService, IOptionsSnapshot globalSettings, UmbracoMapper mapper) + public BackOfficeUserStore(IUserService userService, IEntityService entityService, IExternalLoginService externalLoginService, IOptions globalSettings, UmbracoMapper mapper) : this(userService, entityService, externalLoginService, globalSettings.Value, mapper) { } diff --git a/src/Umbraco.Infrastructure/Compose/NotificationsComponent.cs b/src/Umbraco.Infrastructure/Compose/NotificationsComponent.cs index c725826fd7..15d01bdd12 100644 --- a/src/Umbraco.Infrastructure/Compose/NotificationsComponent.cs +++ b/src/Umbraco.Infrastructure/Compose/NotificationsComponent.cs @@ -174,7 +174,7 @@ namespace Umbraco.Web.Compose INotificationService notificationService, IUserService userService, ILocalizedTextService textService, - IOptionsSnapshot globalSettings, + IOptions globalSettings, ILogger logger) { _umbracoContextAccessor = umbracoContextAccessor; diff --git a/src/Umbraco.Infrastructure/Composing/CompositionExtensions/FileSystems.cs b/src/Umbraco.Infrastructure/Composing/CompositionExtensions/FileSystems.cs index fec14bfbd2..4b941727ca 100644 --- a/src/Umbraco.Infrastructure/Composing/CompositionExtensions/FileSystems.cs +++ b/src/Umbraco.Infrastructure/Composing/CompositionExtensions/FileSystems.cs @@ -99,7 +99,7 @@ namespace Umbraco.Core.Composing.CompositionExtensions var ioHelper = factory.GetInstance(); var hostingEnvironment = factory.GetInstance(); var logger = factory.GetInstance(); - var globalSettings = factory.GetInstance>().Value; + var globalSettings = factory.GetInstance>().Value; var rootPath = hostingEnvironment.MapPathWebRoot(globalSettings.UmbracoMediaPath); var rootUrl = hostingEnvironment.ToAbsolute(globalSettings.UmbracoMediaPath); diff --git a/src/Umbraco.Infrastructure/Composing/CompositionExtensions/Services.cs b/src/Umbraco.Infrastructure/Composing/CompositionExtensions/Services.cs index dd4db120ce..ffd8b880f2 100644 --- a/src/Umbraco.Infrastructure/Composing/CompositionExtensions/Services.cs +++ b/src/Umbraco.Infrastructure/Composing/CompositionExtensions/Services.cs @@ -96,13 +96,13 @@ namespace Umbraco.Core.Composing.CompositionExtensions factory.GetInstance(), factory.GetInstance(), factory.GetInstance(), - factory.GetInstance>(), + factory.GetInstance>(), packageRepoFileName); private static LocalizedTextServiceFileSources SourcesFactory(IFactory container) { var hostingEnvironment = container.GetInstance(); - var globalSettings = container.GetInstance>().Value; + var globalSettings = container.GetInstance>().Value; var mainLangFolder = new DirectoryInfo(hostingEnvironment.MapPathContentRoot(WebPath.Combine(globalSettings.UmbracoPath , "config","lang"))); var appPlugins = new DirectoryInfo(hostingEnvironment.MapPathContentRoot(Constants.SystemDirectories.AppPlugins)); var configLangFolder = new DirectoryInfo(hostingEnvironment.MapPathContentRoot(WebPath.Combine(Constants.SystemDirectories.Config ,"lang"))); diff --git a/src/Umbraco.Infrastructure/HealthCheck/NotificationMethods/EmailNotificationMethod.cs b/src/Umbraco.Infrastructure/HealthCheck/NotificationMethods/EmailNotificationMethod.cs index 96eee5f458..68d72f36fc 100644 --- a/src/Umbraco.Infrastructure/HealthCheck/NotificationMethods/EmailNotificationMethod.cs +++ b/src/Umbraco.Infrastructure/HealthCheck/NotificationMethods/EmailNotificationMethod.cs @@ -23,9 +23,9 @@ namespace Umbraco.Web.HealthCheck.NotificationMethods public EmailNotificationMethod( ILocalizedTextService textService, IRequestAccessor requestAccessor, - IOptionsSnapshot globalSettings, + IOptions globalSettings, IHealthChecksSettings healthChecksSettings, - IOptionsSnapshot contentSettings) + IOptions contentSettings) : base(healthChecksSettings) { var recipientEmail = Settings?["recipientEmail"]?.Value; diff --git a/src/Umbraco.Infrastructure/Install/FilePermissionHelper.cs b/src/Umbraco.Infrastructure/Install/FilePermissionHelper.cs index d5dc5307ab..7a20a1189e 100644 --- a/src/Umbraco.Infrastructure/Install/FilePermissionHelper.cs +++ b/src/Umbraco.Infrastructure/Install/FilePermissionHelper.cs @@ -25,7 +25,7 @@ namespace Umbraco.Web.Install private readonly IIOHelper _ioHelper; private readonly IPublishedSnapshotService _publishedSnapshotService; - public FilePermissionHelper(IOptionsSnapshot globalSettings, IIOHelper ioHelper, IPublishedSnapshotService publishedSnapshotService) + public FilePermissionHelper(IOptions globalSettings, IIOHelper ioHelper, IPublishedSnapshotService publishedSnapshotService) { _globalSettings = globalSettings.Value; _ioHelper = ioHelper; diff --git a/src/Umbraco.Infrastructure/Install/InstallHelper.cs b/src/Umbraco.Infrastructure/Install/InstallHelper.cs index a0460c93ba..af00034983 100644 --- a/src/Umbraco.Infrastructure/Install/InstallHelper.cs +++ b/src/Umbraco.Infrastructure/Install/InstallHelper.cs @@ -35,7 +35,7 @@ namespace Umbraco.Web.Install public InstallHelper(DatabaseBuilder databaseBuilder, ILogger logger, IUmbracoVersion umbracoVersion, - IOptionsSnapshot connectionStrings, + IOptions connectionStrings, IInstallationService installationService, ICookieManager cookieManager, IUserAgentProvider userAgentProvider, diff --git a/src/Umbraco.Infrastructure/Install/InstallSteps/DatabaseConfigureStep.cs b/src/Umbraco.Infrastructure/Install/InstallSteps/DatabaseConfigureStep.cs index b86c1c2233..d995002daa 100644 --- a/src/Umbraco.Infrastructure/Install/InstallSteps/DatabaseConfigureStep.cs +++ b/src/Umbraco.Infrastructure/Install/InstallSteps/DatabaseConfigureStep.cs @@ -19,7 +19,7 @@ namespace Umbraco.Web.Install.InstallSteps private readonly ILogger _logger; private readonly ConnectionStrings _connectionStrings; - public DatabaseConfigureStep(DatabaseBuilder databaseBuilder, IOptionsSnapshot connectionStrings) + public DatabaseConfigureStep(DatabaseBuilder databaseBuilder, IOptions connectionStrings) { _databaseBuilder = databaseBuilder; _connectionStrings = connectionStrings.Value ?? throw new ArgumentNullException(nameof(connectionStrings)); diff --git a/src/Umbraco.Infrastructure/Install/InstallSteps/DatabaseUpgradeStep.cs b/src/Umbraco.Infrastructure/Install/InstallSteps/DatabaseUpgradeStep.cs index 44214d1b73..e19fac4028 100644 --- a/src/Umbraco.Infrastructure/Install/InstallSteps/DatabaseUpgradeStep.cs +++ b/src/Umbraco.Infrastructure/Install/InstallSteps/DatabaseUpgradeStep.cs @@ -32,8 +32,8 @@ namespace Umbraco.Web.Install.InstallSteps IRuntimeState runtime, ILogger logger, IUmbracoVersion umbracoVersion, - IOptionsSnapshot globalSettings, - IOptionsSnapshot connectionStrings, + IOptions globalSettings, + IOptions connectionStrings, IIOHelper ioHelper, IConfigManipulator configManipulator) { diff --git a/src/Umbraco.Infrastructure/Install/InstallSteps/NewInstallStep.cs b/src/Umbraco.Infrastructure/Install/InstallSteps/NewInstallStep.cs index a8a516199f..11f8f916ed 100644 --- a/src/Umbraco.Infrastructure/Install/InstallSteps/NewInstallStep.cs +++ b/src/Umbraco.Infrastructure/Install/InstallSteps/NewInstallStep.cs @@ -39,9 +39,9 @@ namespace Umbraco.Web.Install.InstallSteps public NewInstallStep( IUserService userService, DatabaseBuilder databaseBuilder, - IOptionsSnapshot passwordConfiguration, - IOptionsSnapshot securitySettings, - IOptionsSnapshot connectionStrings, + IOptions passwordConfiguration, + IOptions securitySettings, + IOptions connectionStrings, ICookieManager cookieManager, BackOfficeUserManager userManager) { diff --git a/src/Umbraco.Infrastructure/Logging/Serilog/Enrichers/ThreadAbortExceptionEnricher.cs b/src/Umbraco.Infrastructure/Logging/Serilog/Enrichers/ThreadAbortExceptionEnricher.cs index c9386ea210..8428b60fde 100644 --- a/src/Umbraco.Infrastructure/Logging/Serilog/Enrichers/ThreadAbortExceptionEnricher.cs +++ b/src/Umbraco.Infrastructure/Logging/Serilog/Enrichers/ThreadAbortExceptionEnricher.cs @@ -19,7 +19,7 @@ namespace Umbraco.Infrastructure.Logging.Serilog.Enrichers private readonly IHostingEnvironment _hostingEnvironment; private readonly IMarchal _marchal; - public ThreadAbortExceptionEnricher(IOptionsSnapshot coreDebugSettings, IHostingEnvironment hostingEnvironment, IMarchal marchal) + public ThreadAbortExceptionEnricher(IOptions coreDebugSettings, IHostingEnvironment hostingEnvironment, IMarchal marchal) { _coreDebugSettings = coreDebugSettings.Value; _hostingEnvironment = hostingEnvironment; diff --git a/src/Umbraco.Infrastructure/Media/UploadAutoFillProperties.cs b/src/Umbraco.Infrastructure/Media/UploadAutoFillProperties.cs index 38c77aefb5..3f8c1c217f 100644 --- a/src/Umbraco.Infrastructure/Media/UploadAutoFillProperties.cs +++ b/src/Umbraco.Infrastructure/Media/UploadAutoFillProperties.cs @@ -24,7 +24,7 @@ namespace Umbraco.Web.Media public UploadAutoFillProperties( IMediaFileSystem mediaFileSystem, ILogger logger, - IOptionsSnapshot contentSettings) + IOptions contentSettings) : this(mediaFileSystem, logger, contentSettings.Value) { } diff --git a/src/Umbraco.Infrastructure/Migrations/Install/DatabaseBuilder.cs b/src/Umbraco.Infrastructure/Migrations/Install/DatabaseBuilder.cs index 8bf8ceb33e..c272ebc15b 100644 --- a/src/Umbraco.Infrastructure/Migrations/Install/DatabaseBuilder.cs +++ b/src/Umbraco.Infrastructure/Migrations/Install/DatabaseBuilder.cs @@ -40,7 +40,7 @@ namespace Umbraco.Core.Migrations.Install /// public DatabaseBuilder( IScopeProvider scopeProvider, - IOptionsSnapshot globalSettings, + IOptions globalSettings, IUmbracoDatabaseFactory databaseFactory, IRuntimeState runtime, ILogger logger, diff --git a/src/Umbraco.Infrastructure/Models/Mapping/ContentTypeMapDefinition.cs b/src/Umbraco.Infrastructure/Models/Mapping/ContentTypeMapDefinition.cs index 83da0c306c..82658c5366 100644 --- a/src/Umbraco.Infrastructure/Models/Mapping/ContentTypeMapDefinition.cs +++ b/src/Umbraco.Infrastructure/Models/Mapping/ContentTypeMapDefinition.cs @@ -37,7 +37,7 @@ namespace Umbraco.Web.Models.Mapping public ContentTypeMapDefinition(CommonMapper commonMapper, PropertyEditorCollection propertyEditors, IDataTypeService dataTypeService, IFileService fileService, IContentTypeService contentTypeService, IMediaTypeService mediaTypeService, IMemberTypeService memberTypeService, - ILogger logger, IShortStringHelper shortStringHelper, IOptionsSnapshot globalSettings, IHostingEnvironment hostingEnvironment) + ILogger logger, IShortStringHelper shortStringHelper, IOptions globalSettings, IHostingEnvironment hostingEnvironment) { _commonMapper = commonMapper; _propertyEditors = propertyEditors; diff --git a/src/Umbraco.Infrastructure/Models/Mapping/DataTypeMapDefinition.cs b/src/Umbraco.Infrastructure/Models/Mapping/DataTypeMapDefinition.cs index 069333e55d..b55b18db46 100644 --- a/src/Umbraco.Infrastructure/Models/Mapping/DataTypeMapDefinition.cs +++ b/src/Umbraco.Infrastructure/Models/Mapping/DataTypeMapDefinition.cs @@ -18,7 +18,7 @@ namespace Umbraco.Web.Models.Mapping private readonly ILogger _logger; private readonly ContentSettings _contentSettings; - public DataTypeMapDefinition(PropertyEditorCollection propertyEditors, ILogger logger, IOptionsSnapshot contentSettings) + public DataTypeMapDefinition(PropertyEditorCollection propertyEditors, ILogger logger, IOptions contentSettings) { _propertyEditors = propertyEditors; _logger = logger; diff --git a/src/Umbraco.Infrastructure/Models/Mapping/MemberTabsAndPropertiesMapper.cs b/src/Umbraco.Infrastructure/Models/Mapping/MemberTabsAndPropertiesMapper.cs index b77214fac5..b281e18b73 100644 --- a/src/Umbraco.Infrastructure/Models/Mapping/MemberTabsAndPropertiesMapper.cs +++ b/src/Umbraco.Infrastructure/Models/Mapping/MemberTabsAndPropertiesMapper.cs @@ -38,7 +38,7 @@ namespace Umbraco.Web.Models.Mapping IMemberTypeService memberTypeService, IMemberService memberService, IMemberGroupService memberGroupService, - IOptionsSnapshot memberPasswordConfiguration, + IOptions memberPasswordConfiguration, IContentTypeBaseServiceProvider contentTypeBaseServiceProvider, PropertyEditorCollection propertyEditorCollection) : base(cultureDictionary, localizedTextService, contentTypeBaseServiceProvider) diff --git a/src/Umbraco.Infrastructure/Models/Mapping/UserMapDefinition.cs b/src/Umbraco.Infrastructure/Models/Mapping/UserMapDefinition.cs index ca17bffd5d..58a0d98be1 100644 --- a/src/Umbraco.Infrastructure/Models/Mapping/UserMapDefinition.cs +++ b/src/Umbraco.Infrastructure/Models/Mapping/UserMapDefinition.cs @@ -37,7 +37,7 @@ namespace Umbraco.Web.Models.Mapping private readonly IImageUrlGenerator _imageUrlGenerator; public UserMapDefinition(ILocalizedTextService textService, IUserService userService, IEntityService entityService, ISectionService sectionService, - AppCaches appCaches, ActionCollection actions, IOptionsSnapshot globalSettings, IMediaFileSystem mediaFileSystem, IShortStringHelper shortStringHelper, + AppCaches appCaches, ActionCollection actions, IOptions globalSettings, IMediaFileSystem mediaFileSystem, IShortStringHelper shortStringHelper, IImageUrlGenerator imageUrlGenerator) { _sectionService = sectionService; diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/LanguageRepository.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/LanguageRepository.cs index 80afef181e..6b6ab37001 100644 --- a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/LanguageRepository.cs +++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/LanguageRepository.cs @@ -25,7 +25,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement private readonly Dictionary _codeIdMap = new Dictionary(StringComparer.OrdinalIgnoreCase); private readonly Dictionary _idCodeMap = new Dictionary(); - public LanguageRepository(IScopeAccessor scopeAccessor, AppCaches cache, ILogger logger, IOptionsSnapshot globalSettings) + public LanguageRepository(IScopeAccessor scopeAccessor, AppCaches cache, ILogger logger, IOptions globalSettings) : base(scopeAccessor, cache, logger) { _globalSettings = globalSettings.Value; diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/ScriptRepository.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/ScriptRepository.cs index b137f36bc4..aae888e0c5 100644 --- a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/ScriptRepository.cs +++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/ScriptRepository.cs @@ -18,7 +18,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement private readonly IIOHelper _ioHelper; private readonly GlobalSettings _globalSettings; - public ScriptRepository(IFileSystems fileSystems, IIOHelper ioHelper, IOptionsSnapshot globalSettings) + public ScriptRepository(IFileSystems fileSystems, IIOHelper ioHelper, IOptions globalSettings) : base(fileSystems.ScriptsFileSystem) { _ioHelper = ioHelper ?? throw new ArgumentNullException(nameof(ioHelper)); diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/StylesheetRepository.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/StylesheetRepository.cs index 4ee18c635c..4243d534aa 100644 --- a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/StylesheetRepository.cs +++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/StylesheetRepository.cs @@ -17,7 +17,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement private readonly IIOHelper _ioHelper; private readonly GlobalSettings _globalSettings; - public StylesheetRepository(IFileSystems fileSystems, IIOHelper ioHelper, IOptionsSnapshot globalSettings) + public StylesheetRepository(IFileSystems fileSystems, IIOHelper ioHelper, IOptions globalSettings) : base(fileSystems.StylesheetsFileSystem) { _ioHelper = ioHelper; diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/UserRepository.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/UserRepository.cs index e054c4423a..83bc3730b8 100644 --- a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/UserRepository.cs +++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/UserRepository.cs @@ -47,8 +47,8 @@ namespace Umbraco.Core.Persistence.Repositories.Implement AppCaches appCaches, ILogger logger, IMapperCollection mapperCollection, - IOptionsSnapshot globalSettings, - IOptionsSnapshot passwordConfiguration, + IOptions globalSettings, + IOptions passwordConfiguration, IJsonSerializer jsonSerializer) : this(scopeAccessor, appCaches, logger, mapperCollection, globalSettings.Value, passwordConfiguration.Value, jsonSerializer) { diff --git a/src/Umbraco.Infrastructure/PropertyEditors/FileUploadPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/FileUploadPropertyEditor.cs index 5205cfd15b..1297a0ba2d 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/FileUploadPropertyEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/FileUploadPropertyEditor.cs @@ -33,7 +33,7 @@ namespace Umbraco.Web.PropertyEditors public FileUploadPropertyEditor( ILogger logger, IMediaFileSystem mediaFileSystem, - IOptionsSnapshot contentSettings, + IOptions contentSettings, IDataTypeService dataTypeService, ILocalizationService localizationService, ILocalizedTextService localizedTextService, diff --git a/src/Umbraco.Infrastructure/PropertyEditors/FileUploadPropertyValueEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/FileUploadPropertyValueEditor.cs index e518005526..7425051480 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/FileUploadPropertyValueEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/FileUploadPropertyValueEditor.cs @@ -26,7 +26,7 @@ namespace Umbraco.Web.PropertyEditors ILocalizationService localizationService, ILocalizedTextService localizedTextService, IShortStringHelper shortStringHelper, - IOptionsSnapshot contentSettings) + IOptions contentSettings) : this(attribute, mediaFileSystem, dataTypeService, localizationService, localizedTextService, shortStringHelper, contentSettings.Value) { } diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ImageCropperPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/ImageCropperPropertyEditor.cs index 398b7110e3..2b1efb6d2b 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/ImageCropperPropertyEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/ImageCropperPropertyEditor.cs @@ -43,7 +43,7 @@ namespace Umbraco.Web.PropertyEditors public ImageCropperPropertyEditor( ILogger logger, IMediaFileSystem mediaFileSystem, - IOptionsSnapshot contentSettings, + IOptions contentSettings, IDataTypeService dataTypeService, ILocalizationService localizationService, IIOHelper ioHelper, diff --git a/src/Umbraco.Infrastructure/PropertyEditors/UploadFileTypeValidator.cs b/src/Umbraco.Infrastructure/PropertyEditors/UploadFileTypeValidator.cs index 063ac1cc97..72391c99c0 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/UploadFileTypeValidator.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/UploadFileTypeValidator.cs @@ -23,7 +23,7 @@ namespace Umbraco.Web.PropertyEditors _contentSettings = contentSettings; } - public UploadFileTypeValidator(ILocalizedTextService localizedTextService, IOptionsSnapshot contentSettings) + public UploadFileTypeValidator(ILocalizedTextService localizedTextService, IOptions contentSettings) : this(localizedTextService, contentSettings.Value) { } diff --git a/src/Umbraco.Infrastructure/Routing/ContentFinderByConfigured404.cs b/src/Umbraco.Infrastructure/Routing/ContentFinderByConfigured404.cs index ae47b85365..5b7a720a40 100644 --- a/src/Umbraco.Infrastructure/Routing/ContentFinderByConfigured404.cs +++ b/src/Umbraco.Infrastructure/Routing/ContentFinderByConfigured404.cs @@ -23,7 +23,7 @@ namespace Umbraco.Web.Routing public ContentFinderByConfigured404( ILogger logger, IEntityService entityService, - IOptionsSnapshot contentConfigSettings, + IOptions contentConfigSettings, IExamineManager examineManager) { _logger = logger; diff --git a/src/Umbraco.Infrastructure/Routing/RedirectTrackingComponent.cs b/src/Umbraco.Infrastructure/Routing/RedirectTrackingComponent.cs index 63a6725fb8..cd623b585a 100644 --- a/src/Umbraco.Infrastructure/Routing/RedirectTrackingComponent.cs +++ b/src/Umbraco.Infrastructure/Routing/RedirectTrackingComponent.cs @@ -31,7 +31,7 @@ namespace Umbraco.Web.Routing private readonly IRedirectUrlService _redirectUrlService; private readonly IVariationContextAccessor _variationContextAccessor; - public RedirectTrackingComponent(IOptionsSnapshot webRoutingSettings, IPublishedSnapshotAccessor publishedSnapshotAccessor, IRedirectUrlService redirectUrlService, IVariationContextAccessor variationContextAccessor) + public RedirectTrackingComponent(IOptions webRoutingSettings, IPublishedSnapshotAccessor publishedSnapshotAccessor, IRedirectUrlService redirectUrlService, IVariationContextAccessor variationContextAccessor) { _webRoutingSettings = webRoutingSettings.Value; _publishedSnapshotAccessor = publishedSnapshotAccessor; diff --git a/src/Umbraco.Infrastructure/Runtime/CoreInitialComponent.cs b/src/Umbraco.Infrastructure/Runtime/CoreInitialComponent.cs index 3a4cd60901..a473511e56 100644 --- a/src/Umbraco.Infrastructure/Runtime/CoreInitialComponent.cs +++ b/src/Umbraco.Infrastructure/Runtime/CoreInitialComponent.cs @@ -1,6 +1,5 @@ using Microsoft.Extensions.Options; using Umbraco.Core.Composing; -using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.Models; using Umbraco.Core.IO; @@ -11,7 +10,7 @@ namespace Umbraco.Core.Runtime private readonly IIOHelper _ioHelper; private readonly GlobalSettings _globalSettings; - public CoreInitialComponent(IIOHelper ioHelper, IOptionsSnapshot globalSettings) + public CoreInitialComponent(IIOHelper ioHelper, IOptions globalSettings) { _ioHelper = ioHelper; _globalSettings = globalSettings.Value; diff --git a/src/Umbraco.Infrastructure/Runtime/CoreInitialComposer.cs b/src/Umbraco.Infrastructure/Runtime/CoreInitialComposer.cs index 4f1109a8cb..1d8d8a8f79 100644 --- a/src/Umbraco.Infrastructure/Runtime/CoreInitialComposer.cs +++ b/src/Umbraco.Infrastructure/Runtime/CoreInitialComposer.cs @@ -54,6 +54,8 @@ using Umbraco.Web.Templates; using Umbraco.Web.Trees; using IntegerValidator = Umbraco.Core.PropertyEditors.Validators.IntegerValidator; using TextStringValueConverter = Umbraco.Core.PropertyEditors.ValueConverters.TextStringValueConverter; +using Umbraco.Core.Configuration.Models; +using Microsoft.Extensions.Options; namespace Umbraco.Core.Runtime { @@ -162,7 +164,7 @@ namespace Umbraco.Core.Runtime composition.RegisterUnique(); composition.RegisterUnique(factory - => new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(factory.GetInstance()))); + => new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(factory.GetInstance>().Value))); composition.UrlSegmentProviders() .Append(); diff --git a/src/Umbraco.Infrastructure/Scheduling/LogScrubber.cs b/src/Umbraco.Infrastructure/Scheduling/LogScrubber.cs index 2c5d8afbff..2aff2ce5ab 100644 --- a/src/Umbraco.Infrastructure/Scheduling/LogScrubber.cs +++ b/src/Umbraco.Infrastructure/Scheduling/LogScrubber.cs @@ -20,7 +20,7 @@ namespace Umbraco.Web.Scheduling private readonly IScopeProvider _scopeProvider; public LogScrubber(IBackgroundTaskRunner runner, int delayMilliseconds, int periodMilliseconds, - IMainDom mainDom, IServerRegistrar serverRegistrar, IAuditService auditService, IOptionsSnapshot settings, IScopeProvider scopeProvider, IProfilingLogger logger) + IMainDom mainDom, IServerRegistrar serverRegistrar, IAuditService auditService, IOptions settings, IScopeProvider scopeProvider, IProfilingLogger logger) : this(runner, delayMilliseconds, periodMilliseconds, mainDom, serverRegistrar, auditService, settings.Value, scopeProvider, logger) { } diff --git a/src/Umbraco.Infrastructure/Scheduling/SchedulerComponent.cs b/src/Umbraco.Infrastructure/Scheduling/SchedulerComponent.cs index 982f8470a7..6f014955b8 100644 --- a/src/Umbraco.Infrastructure/Scheduling/SchedulerComponent.cs +++ b/src/Umbraco.Infrastructure/Scheduling/SchedulerComponent.cs @@ -59,7 +59,7 @@ namespace Umbraco.Web.Scheduling IScopeProvider scopeProvider, IUmbracoContextFactory umbracoContextFactory, IProfilingLogger logger, IApplicationShutdownRegistry applicationShutdownRegistry, IHealthChecksSettings healthChecksSettingsConfig, IServerMessenger serverMessenger, IRequestAccessor requestAccessor, - IOptionsSnapshot loggingSettings, IOptionsSnapshot keepAliveSettings, + IOptions loggingSettings, IOptions keepAliveSettings, IHostingEnvironment hostingEnvironment) { _runtime = runtime; diff --git a/src/Umbraco.Infrastructure/Scoping/ScopeProvider.cs b/src/Umbraco.Infrastructure/Scoping/ScopeProvider.cs index 5205a95e8d..947d427995 100644 --- a/src/Umbraco.Infrastructure/Scoping/ScopeProvider.cs +++ b/src/Umbraco.Infrastructure/Scoping/ScopeProvider.cs @@ -28,7 +28,7 @@ namespace Umbraco.Core.Scoping private readonly CoreDebugSettings _coreDebugSettings; private readonly IMediaFileSystem _mediaFileSystem; - public ScopeProvider(IUmbracoDatabaseFactory databaseFactory, FileSystems fileSystems, IOptionsSnapshot coreDebugSettings, IMediaFileSystem mediaFileSystem, ILogger logger, ITypeFinder typeFinder, IRequestCache requestCache) + public ScopeProvider(IUmbracoDatabaseFactory databaseFactory, FileSystems fileSystems, IOptions coreDebugSettings, IMediaFileSystem mediaFileSystem, ILogger logger, ITypeFinder typeFinder, IRequestCache requestCache) :this(databaseFactory, fileSystems, coreDebugSettings.Value, mediaFileSystem, logger, typeFinder, requestCache) { } diff --git a/src/Umbraco.Infrastructure/Services/Implement/FileService.cs b/src/Umbraco.Infrastructure/Services/Implement/FileService.cs index 7d6c0303ce..e82c71d1a5 100644 --- a/src/Umbraco.Infrastructure/Services/Implement/FileService.cs +++ b/src/Umbraco.Infrastructure/Services/Implement/FileService.cs @@ -40,7 +40,7 @@ namespace Umbraco.Core.Services.Implement public FileService(IScopeProvider uowProvider, ILogger logger, IEventMessagesFactory eventMessagesFactory, IStylesheetRepository stylesheetRepository, IScriptRepository scriptRepository, ITemplateRepository templateRepository, IPartialViewRepository partialViewRepository, IPartialViewMacroRepository partialViewMacroRepository, - IAuditRepository auditRepository, IShortStringHelper shortStringHelper, IOptionsSnapshot globalSettings, IHostingEnvironment hostingEnvironment) + IAuditRepository auditRepository, IShortStringHelper shortStringHelper, IOptions globalSettings, IHostingEnvironment hostingEnvironment) : base(uowProvider, logger, eventMessagesFactory) { _stylesheetRepository = stylesheetRepository; diff --git a/src/Umbraco.Infrastructure/Services/Implement/NotificationService.cs b/src/Umbraco.Infrastructure/Services/Implement/NotificationService.cs index 3ad1ea8446..0c1b390592 100644 --- a/src/Umbraco.Infrastructure/Services/Implement/NotificationService.cs +++ b/src/Umbraco.Infrastructure/Services/Implement/NotificationService.cs @@ -32,7 +32,7 @@ namespace Umbraco.Core.Services.Implement private readonly IIOHelper _ioHelper; public NotificationService(IScopeProvider provider, IUserService userService, IContentService contentService, ILocalizationService localizationService, - ILogger logger, IIOHelper ioHelper, INotificationsRepository notificationsRepository, IOptionsSnapshot globalSettings, IOptionsSnapshot contentSettings) + ILogger logger, IIOHelper ioHelper, INotificationsRepository notificationsRepository, IOptions globalSettings, IOptions contentSettings) : this(provider, userService, contentService, localizationService, logger, ioHelper, notificationsRepository, globalSettings.Value, contentSettings.Value) { } diff --git a/src/Umbraco.Infrastructure/Services/Implement/UserService.cs b/src/Umbraco.Infrastructure/Services/Implement/UserService.cs index 921da6f345..fdd79e7264 100644 --- a/src/Umbraco.Infrastructure/Services/Implement/UserService.cs +++ b/src/Umbraco.Infrastructure/Services/Implement/UserService.cs @@ -28,7 +28,7 @@ namespace Umbraco.Core.Services.Implement private readonly bool _isUpgrading; public UserService(IScopeProvider provider, ILogger logger, IEventMessagesFactory eventMessagesFactory, IRuntimeState runtimeState, - IUserRepository userRepository, IUserGroupRepository userGroupRepository, IOptionsSnapshot globalSettings) + IUserRepository userRepository, IUserGroupRepository userGroupRepository, IOptions globalSettings) : base(provider, logger, eventMessagesFactory) { _userRepository = userRepository; diff --git a/src/Umbraco.Infrastructure/Users/EmailSender.cs b/src/Umbraco.Infrastructure/Users/EmailSender.cs index 1ca30bb966..28bbf6471d 100644 --- a/src/Umbraco.Infrastructure/Users/EmailSender.cs +++ b/src/Umbraco.Infrastructure/Users/EmailSender.cs @@ -22,11 +22,11 @@ namespace Umbraco.Core private readonly GlobalSettings _globalSettings; private readonly bool _enableEvents; - public EmailSender(IOptionsSnapshot globalSettings) : this(globalSettings, false) + public EmailSender(IOptions globalSettings) : this(globalSettings, false) { } - public EmailSender(IOptionsSnapshot globalSettings, bool enableEvents) + public EmailSender(IOptions globalSettings, bool enableEvents) : this(globalSettings.Value, enableEvents) { } diff --git a/src/Umbraco.Infrastructure/WebAssets/BackOfficeWebAssets.cs b/src/Umbraco.Infrastructure/WebAssets/BackOfficeWebAssets.cs index b3d7d485f5..5e4a1e2c7a 100644 --- a/src/Umbraco.Infrastructure/WebAssets/BackOfficeWebAssets.cs +++ b/src/Umbraco.Infrastructure/WebAssets/BackOfficeWebAssets.cs @@ -36,7 +36,7 @@ namespace Umbraco.Web.WebAssets IManifestParser parser, PropertyEditorCollection propertyEditorCollection, IHostingEnvironment hostingEnvironment, - IOptionsSnapshot globalSettings) + IOptions globalSettings) { _runtimeMinifier = runtimeMinifier; _parser = parser; diff --git a/src/Umbraco.ModelsBuilder.Embedded/Building/ModelsGenerator.cs b/src/Umbraco.ModelsBuilder.Embedded/Building/ModelsGenerator.cs index 1572fc9b92..c1e2f02031 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/Building/ModelsGenerator.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/Building/ModelsGenerator.cs @@ -14,7 +14,7 @@ namespace Umbraco.ModelsBuilder.Embedded.Building private readonly OutOfDateModelsStatus _outOfDateModels; private readonly IIOHelper _ioHelper; - public ModelsGenerator(UmbracoServices umbracoService, IOptionsSnapshot config, OutOfDateModelsStatus outOfDateModels, IIOHelper ioHelper) + public ModelsGenerator(UmbracoServices umbracoService, IOptions config, OutOfDateModelsStatus outOfDateModels, IIOHelper ioHelper) { _umbracoService = umbracoService; _config = config.Value; diff --git a/src/Umbraco.ModelsBuilder.Embedded/Compose/ModelsBuilderComposer.cs b/src/Umbraco.ModelsBuilder.Embedded/Compose/ModelsBuilderComposer.cs index 3873080605..952fcd453c 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/Compose/ModelsBuilderComposer.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/Compose/ModelsBuilderComposer.cs @@ -17,7 +17,7 @@ namespace Umbraco.ModelsBuilder.Embedded.Compose { private readonly ModelsBuilderConfig _config; - public ModelsBuilderComposer(IOptionsSnapshot config) + public ModelsBuilderComposer(IOptions config) { _config = config.Value; } diff --git a/src/Umbraco.ModelsBuilder.Embedded/ModelsGenerationError.cs b/src/Umbraco.ModelsBuilder.Embedded/ModelsGenerationError.cs index 92c73e2c6d..554e8eda29 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/ModelsGenerationError.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/ModelsGenerationError.cs @@ -13,7 +13,7 @@ namespace Umbraco.ModelsBuilder.Embedded private readonly ModelsBuilderConfig _config; private readonly IIOHelper _ioHelper; - public ModelsGenerationError(IOptionsSnapshot config, IIOHelper ioHelper) + public ModelsGenerationError(IOptions config, IIOHelper ioHelper) { _config = config.Value; _ioHelper = ioHelper; diff --git a/src/Umbraco.ModelsBuilder.Embedded/PureLiveModelFactory.cs b/src/Umbraco.ModelsBuilder.Embedded/PureLiveModelFactory.cs index da48621c7d..c355f651da 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/PureLiveModelFactory.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/PureLiveModelFactory.cs @@ -51,7 +51,7 @@ namespace Umbraco.ModelsBuilder.Embedded public PureLiveModelFactory( Lazy umbracoServices, IProfilingLogger logger, - IOptionsSnapshot config, + IOptions config, IHostingEnvironment hostingEnvironment, IApplicationShutdownRegistry hostingLifetime, IIOHelper ioHelper) diff --git a/src/Umbraco.PublishedCache.NuCache/ContentCache.cs b/src/Umbraco.PublishedCache.NuCache/ContentCache.cs index 470a224dc8..f18018d9f0 100644 --- a/src/Umbraco.PublishedCache.NuCache/ContentCache.cs +++ b/src/Umbraco.PublishedCache.NuCache/ContentCache.cs @@ -31,7 +31,7 @@ namespace Umbraco.Web.PublishedCache.NuCache // it's too late for UmbracoContext which has captured previewDefault and stuff into these ctor vars // but, no, UmbracoContext returns snapshot.Content which comes from elements SO a resync should create a new cache - public ContentCache(bool previewDefault, ContentStore.Snapshot snapshot, IAppCache snapshotCache, IAppCache elementsCache, IDomainCache domainCache, IOptionsSnapshot globalSettings, IVariationContextAccessor variationContextAccessor) + public ContentCache(bool previewDefault, ContentStore.Snapshot snapshot, IAppCache snapshotCache, IAppCache elementsCache, IDomainCache domainCache, IOptions globalSettings, IVariationContextAccessor variationContextAccessor) : this(previewDefault, snapshot, snapshotCache, elementsCache, domainCache, globalSettings.Value, variationContextAccessor) { } diff --git a/src/Umbraco.PublishedCache.NuCache/PublishedSnapshotService.cs b/src/Umbraco.PublishedCache.NuCache/PublishedSnapshotService.cs index f603ee25ad..fabcb0c759 100644 --- a/src/Umbraco.PublishedCache.NuCache/PublishedSnapshotService.cs +++ b/src/Umbraco.PublishedCache.NuCache/PublishedSnapshotService.cs @@ -87,14 +87,14 @@ namespace Umbraco.Web.PublishedCache.NuCache IDocumentRepository documentRepository, IMediaRepository mediaRepository, IMemberRepository memberRepository, IDefaultCultureAccessor defaultCultureAccessor, IDataSource dataSource, - IOptionsSnapshot globalSettings, + IOptions globalSettings, IEntityXmlSerializer entitySerializer, IPublishedModelFactory publishedModelFactory, UrlSegmentProviderCollection urlSegmentProviders, IHostingEnvironment hostingEnvironment, IShortStringHelper shortStringHelper, IIOHelper ioHelper, - IOptionsSnapshot config) + IOptions config) : base(publishedSnapshotAccessor, variationContextAccessor) { //if (Interlocked.Increment(ref _singletonCheck) > 1) diff --git a/src/Umbraco.Web.BackOffice/Controllers/AuthenticationController.cs b/src/Umbraco.Web.BackOffice/Controllers/AuthenticationController.cs index dc22d24f05..619994412b 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/AuthenticationController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/AuthenticationController.cs @@ -64,11 +64,11 @@ namespace Umbraco.Web.BackOffice.Controllers IUserService userService, ILocalizedTextService textService, UmbracoMapper umbracoMapper, - IOptionsSnapshot globalSettings, - IOptionsSnapshot securitySettings, + IOptions globalSettings, + IOptions securitySettings, ILogger logger, IIpResolver ipResolver, - IOptionsSnapshot passwordConfiguration, + IOptions passwordConfiguration, IEmailSender emailSender, Core.Hosting.IHostingEnvironment hostingEnvironment, IRequestAccessor requestAccessor) diff --git a/src/Umbraco.Web.BackOffice/Controllers/BackOfficeAssetsController.cs b/src/Umbraco.Web.BackOffice/Controllers/BackOfficeAssetsController.cs index 916b422b33..5ee7cf31cf 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/BackOfficeAssetsController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/BackOfficeAssetsController.cs @@ -19,7 +19,7 @@ namespace Umbraco.Web.BackOffice.Controllers { private readonly IFileSystem _jsLibFileSystem; - public BackOfficeAssetsController(IIOHelper ioHelper, IHostingEnvironment hostingEnvironment, ILogger logger, IOptionsSnapshot globalSettings) + public BackOfficeAssetsController(IIOHelper ioHelper, IHostingEnvironment hostingEnvironment, ILogger logger, IOptions globalSettings) { _jsLibFileSystem = new PhysicalFileSystem(ioHelper, hostingEnvironment, logger, globalSettings.Value.UmbracoPath + Path.DirectorySeparatorChar + "lib"); } diff --git a/src/Umbraco.Web.BackOffice/Controllers/BackOfficeController.cs b/src/Umbraco.Web.BackOffice/Controllers/BackOfficeController.cs index 4672d48d88..e3480984fd 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/BackOfficeController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/BackOfficeController.cs @@ -50,7 +50,7 @@ namespace Umbraco.Web.BackOffice.Controllers public BackOfficeController( BackOfficeUserManager userManager, IRuntimeMinifier runtimeMinifier, - IOptionsSnapshot globalSettings, + IOptions globalSettings, IHostingEnvironment hostingEnvironment, IUmbracoContextAccessor umbracoContextAccessor, ILocalizedTextService textService, diff --git a/src/Umbraco.Web.BackOffice/Controllers/BackOfficeServerVariables.cs b/src/Umbraco.Web.BackOffice/Controllers/BackOfficeServerVariables.cs index 3305a7bbb1..6976821622 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/BackOfficeServerVariables.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/BackOfficeServerVariables.cs @@ -46,14 +46,14 @@ namespace Umbraco.Web.BackOffice.Controllers LinkGenerator linkGenerator, IRuntimeState runtimeState, UmbracoFeatures features, - IOptionsSnapshot globalSettings, + IOptions globalSettings, IUmbracoVersion umbracoVersion, - IOptionsSnapshot contentSettings, + IOptions contentSettings, IHttpContextAccessor httpContextAccessor, TreeCollection treeCollection, IHostingEnvironment hostingEnvironment, - IOptionsSnapshot runtimeSettings, - IOptionsSnapshot securitySettings, + IOptions runtimeSettings, + IOptions securitySettings, IRuntimeMinifier runtimeMinifier, IAuthenticationSchemeProvider authenticationSchemeProvider) { diff --git a/src/Umbraco.Web.BackOffice/Controllers/CodeFileController.cs b/src/Umbraco.Web.BackOffice/Controllers/CodeFileController.cs index 7fdfc81cd1..4bf76a108a 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/CodeFileController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/CodeFileController.cs @@ -48,7 +48,7 @@ namespace Umbraco.Web.BackOffice.Controllers ILocalizedTextService localizedTextService, UmbracoMapper umbracoMapper, IShortStringHelper shortStringHelper, - IOptionsSnapshot globalSettings) + IOptions globalSettings) { _ioHelper = ioHelper; _fileSystems = fileSystems; diff --git a/src/Umbraco.Web.BackOffice/Controllers/ContentTypeController.cs b/src/Umbraco.Web.BackOffice/Controllers/ContentTypeController.cs index 28a09942dd..659062f4f9 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/ContentTypeController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/ContentTypeController.cs @@ -85,7 +85,7 @@ namespace Umbraco.Web.BackOffice.Controllers UmbracoMapper umbracoMapper, ILocalizedTextService localizedTextService, IEntityXmlSerializer serializer, - IOptionsSnapshot globalSettings, + IOptions globalSettings, PropertyEditorCollection propertyEditors, IScopeProvider scopeProvider, IIOHelper ioHelper, diff --git a/src/Umbraco.Web.BackOffice/Controllers/CurrentUserController.cs b/src/Umbraco.Web.BackOffice/Controllers/CurrentUserController.cs index ff0eacb9bb..eb7cbceef7 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/CurrentUserController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/CurrentUserController.cs @@ -50,7 +50,7 @@ namespace Umbraco.Web.BackOffice.Controllers public CurrentUserController( IMediaFileSystem mediaFileSystem, - IOptionsSnapshot contentSettings, + IOptions contentSettings, IHostingEnvironment hostingEnvironment, IImageUrlGenerator imageUrlGenerator, IWebSecurity webSecurity, diff --git a/src/Umbraco.Web.BackOffice/Controllers/DataTypeController.cs b/src/Umbraco.Web.BackOffice/Controllers/DataTypeController.cs index d049dbebbb..3ffcd5cec3 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/DataTypeController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/DataTypeController.cs @@ -47,7 +47,7 @@ namespace Umbraco.Web.BackOffice.Controllers public DataTypeController( PropertyEditorCollection propertyEditors, IDataTypeService dataTypeService, - IOptionsSnapshot contentSettings, + IOptions contentSettings, UmbracoMapper umbracoMapper, PropertyEditorCollection propertyEditorCollection, IContentTypeService contentTypeService, diff --git a/src/Umbraco.Web.BackOffice/Controllers/DictionaryController.cs b/src/Umbraco.Web.BackOffice/Controllers/DictionaryController.cs index b0b18c8da3..6122c36a53 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/DictionaryController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/DictionaryController.cs @@ -43,7 +43,7 @@ namespace Umbraco.Web.BackOffice.Controllers ILogger logger, ILocalizationService localizationService, IWebSecurity webSecurity, - IOptionsSnapshot globalSettings, + IOptions globalSettings, ILocalizedTextService localizedTextService, UmbracoMapper umbracoMapper ) diff --git a/src/Umbraco.Web.BackOffice/Controllers/ImagesController.cs b/src/Umbraco.Web.BackOffice/Controllers/ImagesController.cs index f909313dff..df834b019c 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/ImagesController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/ImagesController.cs @@ -23,7 +23,7 @@ namespace Umbraco.Web.BackOffice.Controllers private readonly ContentSettings _contentSettings; private readonly IImageUrlGenerator _imageUrlGenerator; - public ImagesController(IMediaFileSystem mediaFileSystem, IOptionsSnapshot contentSettings, IImageUrlGenerator imageUrlGenerator) + public ImagesController(IMediaFileSystem mediaFileSystem, IOptions contentSettings, IImageUrlGenerator imageUrlGenerator) { _mediaFileSystem = mediaFileSystem; _contentSettings = contentSettings.Value; diff --git a/src/Umbraco.Web.BackOffice/Controllers/LanguageController.cs b/src/Umbraco.Web.BackOffice/Controllers/LanguageController.cs index 0a58c04443..66f8b6d7e0 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/LanguageController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/LanguageController.cs @@ -31,7 +31,7 @@ namespace Umbraco.Web.BackOffice.Controllers public LanguageController(ILocalizationService localizationService, UmbracoMapper umbracoMapper, - IOptionsSnapshot globalSettings) + IOptions globalSettings) { _localizationService = localizationService ?? throw new ArgumentNullException(nameof(localizationService)); _umbracoMapper = umbracoMapper ?? throw new ArgumentNullException(nameof(umbracoMapper)); diff --git a/src/Umbraco.Web.BackOffice/Controllers/MediaController.cs b/src/Umbraco.Web.BackOffice/Controllers/MediaController.cs index 9a339a18b8..d075f309c7 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/MediaController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/MediaController.cs @@ -68,7 +68,7 @@ namespace Umbraco.Web.BackOffice.Controllers IShortStringHelper shortStringHelper, IEventMessagesFactory eventMessages, ILocalizedTextService localizedTextService, - IOptionsSnapshot contentSettings, + IOptions contentSettings, IMediaTypeService mediaTypeService, IMediaService mediaService, IEntityService entityService, diff --git a/src/Umbraco.Web.BackOffice/Controllers/MemberController.cs b/src/Umbraco.Web.BackOffice/Controllers/MemberController.cs index 41aa693c0f..6a93bf6437 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/MemberController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/MemberController.cs @@ -63,7 +63,7 @@ namespace Umbraco.Web.BackOffice.Controllers IShortStringHelper shortStringHelper, IEventMessagesFactory eventMessages, ILocalizedTextService localizedTextService, - IOptionsSnapshot passwordConfig, + IOptions passwordConfig, PropertyEditorCollection propertyEditors, LegacyPasswordSecurity passwordSecurity, UmbracoMapper umbracoMapper, diff --git a/src/Umbraco.Web.BackOffice/Controllers/PreviewController.cs b/src/Umbraco.Web.BackOffice/Controllers/PreviewController.cs index eeb73d6d47..3878eb9b14 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/PreviewController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/PreviewController.cs @@ -41,7 +41,7 @@ namespace Umbraco.Web.BackOffice.Controllers public PreviewController( UmbracoFeatures features, - IOptionsSnapshot globalSettings, + IOptions globalSettings, IPublishedSnapshotService publishedSnapshotService, IWebSecurity webSecurity, ILocalizationService localizationService, diff --git a/src/Umbraco.Web.BackOffice/Controllers/RedirectUrlManagementController.cs b/src/Umbraco.Web.BackOffice/Controllers/RedirectUrlManagementController.cs index c5c5ca91ab..9e8358c4b1 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/RedirectUrlManagementController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/RedirectUrlManagementController.cs @@ -28,7 +28,7 @@ namespace Umbraco.Web.BackOffice.Controllers private readonly IHostingEnvironment _hostingEnvironment; public RedirectUrlManagementController(ILogger logger, - IOptionsSnapshot webRoutingSettings, + IOptions webRoutingSettings, IWebSecurity webSecurity, IRedirectUrlService redirectUrlService, UmbracoMapper umbracoMapper, diff --git a/src/Umbraco.Web.BackOffice/Controllers/TinyMceController.cs b/src/Umbraco.Web.BackOffice/Controllers/TinyMceController.cs index 5a28a228f3..b62d6b6080 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/TinyMceController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/TinyMceController.cs @@ -36,7 +36,7 @@ namespace Umbraco.Web.BackOffice.Controllers public TinyMceController( IHostingEnvironment hostingEnvironment, IShortStringHelper shortStringHelper, - IOptionsSnapshot contentSettings, + IOptions contentSettings, IIOHelper ioHelper ) { diff --git a/src/Umbraco.Web.BackOffice/Controllers/TourController.cs b/src/Umbraco.Web.BackOffice/Controllers/TourController.cs index 106d520743..6e7af87a11 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/TourController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/TourController.cs @@ -27,7 +27,7 @@ namespace Umbraco.Web.BackOffice.Controllers public TourController( TourFilterCollection filters, IHostingEnvironment hostingEnvironment, - IOptionsSnapshot tourSettings, + IOptions tourSettings, IWebSecurity webSecurity, IContentTypeService contentTypeService) { diff --git a/src/Umbraco.Web.BackOffice/Controllers/UpdateCheckController.cs b/src/Umbraco.Web.BackOffice/Controllers/UpdateCheckController.cs index 78ac2713c0..16fcb5b38c 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/UpdateCheckController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/UpdateCheckController.cs @@ -31,7 +31,7 @@ namespace Umbraco.Web.BackOffice.Controllers IUmbracoVersion umbracoVersion, ICookieManager cookieManager, IWebSecurity webSecurity, - IOptionsSnapshot globalSettings) + IOptions globalSettings) { _upgradeService = upgradeService ?? throw new ArgumentNullException(nameof(upgradeService)); _umbracoVersion = umbracoVersion ?? throw new ArgumentNullException(nameof(umbracoVersion)); @@ -81,7 +81,7 @@ namespace Umbraco.Web.BackOffice.Controllers { private readonly GlobalSettings _globalSettings; - public UpdateCheckResponseFilter(IOptionsSnapshot globalSettings) + public UpdateCheckResponseFilter(IOptions globalSettings) { _globalSettings = globalSettings.Value; } diff --git a/src/Umbraco.Web.BackOffice/Controllers/UsersController.cs b/src/Umbraco.Web.BackOffice/Controllers/UsersController.cs index ab3f48cdad..b3f752ee49 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/UsersController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/UsersController.cs @@ -73,11 +73,11 @@ namespace Umbraco.Web.BackOffice.Controllers public UsersController( IMediaFileSystem mediaFileSystem, - IOptionsSnapshot contentSettings, + IOptions contentSettings, IHostingEnvironment hostingEnvironment, ISqlContext sqlContext, IImageUrlGenerator imageUrlGenerator, - IOptionsSnapshot securitySettings, + IOptions securitySettings, IRequestAccessor requestAccessor, IEmailSender emailSender, IWebSecurity webSecurity, @@ -89,7 +89,7 @@ namespace Umbraco.Web.BackOffice.Controllers IEntityService entityService, IMediaService mediaService, IContentService contentService, - IOptionsSnapshot globalSettings, + IOptions globalSettings, BackOfficeUserManager backOfficeUserManager, ILogger logger, LinkGenerator linkGenerator) diff --git a/src/Umbraco.Web.BackOffice/Extensions/UmbracoBackOfficeServiceCollectionExtensions.cs b/src/Umbraco.Web.BackOffice/Extensions/UmbracoBackOfficeServiceCollectionExtensions.cs index c9e53b1b82..fbd69acd12 100644 --- a/src/Umbraco.Web.BackOffice/Extensions/UmbracoBackOfficeServiceCollectionExtensions.cs +++ b/src/Umbraco.Web.BackOffice/Extensions/UmbracoBackOfficeServiceCollectionExtensions.cs @@ -74,7 +74,7 @@ namespace Umbraco.Extensions services.TryAddScoped, PasswordValidator>(); services.TryAddScoped>( services => new BackOfficePasswordHasher( - new LegacyPasswordSecurity(services.GetRequiredService>().Value), + new LegacyPasswordSecurity(services.GetRequiredService>().Value), services.GetRequiredService())); services.TryAddScoped, DefaultUserConfirmation>(); services.TryAddScoped, UserClaimsPrincipalFactory>(); diff --git a/src/Umbraco.Web.BackOffice/Filters/SetAngularAntiForgeryTokensAttribute.cs b/src/Umbraco.Web.BackOffice/Filters/SetAngularAntiForgeryTokensAttribute.cs index 761c1110cb..c993766a6b 100644 --- a/src/Umbraco.Web.BackOffice/Filters/SetAngularAntiForgeryTokensAttribute.cs +++ b/src/Umbraco.Web.BackOffice/Filters/SetAngularAntiForgeryTokensAttribute.cs @@ -23,7 +23,7 @@ namespace Umbraco.Extensions private readonly IBackOfficeAntiforgery _antiforgery; private readonly GlobalSettings _globalSettings; - public SetAngularAntiForgeryTokensFilter(IBackOfficeAntiforgery antiforgery, IOptionsSnapshot globalSettings) + public SetAngularAntiForgeryTokensFilter(IBackOfficeAntiforgery antiforgery, IOptions globalSettings) { _antiforgery = antiforgery; _globalSettings = globalSettings.Value; diff --git a/src/Umbraco.Web.BackOffice/Filters/UmbracoWebApiRequireHttpsAttribute.cs b/src/Umbraco.Web.BackOffice/Filters/UmbracoWebApiRequireHttpsAttribute.cs index f3fd82bdf6..e2a1d942d9 100644 --- a/src/Umbraco.Web.BackOffice/Filters/UmbracoWebApiRequireHttpsAttribute.cs +++ b/src/Umbraco.Web.BackOffice/Filters/UmbracoWebApiRequireHttpsAttribute.cs @@ -30,7 +30,7 @@ namespace Umbraco.Web.BackOffice.Filters { private readonly GlobalSettings _globalSettings; - public UmbracoWebApiRequireHttpsFilter(IOptionsSnapshot globalSettings) + public UmbracoWebApiRequireHttpsFilter(IOptions globalSettings) { _globalSettings = globalSettings.Value; } diff --git a/src/Umbraco.Web.BackOffice/Mapping/MediaMapDefinition.cs b/src/Umbraco.Web.BackOffice/Mapping/MediaMapDefinition.cs index b05a05c167..4076f01aab 100644 --- a/src/Umbraco.Web.BackOffice/Mapping/MediaMapDefinition.cs +++ b/src/Umbraco.Web.BackOffice/Mapping/MediaMapDefinition.cs @@ -26,7 +26,7 @@ namespace Umbraco.Web.Models.Mapping private readonly ContentSettings _contentSettings; public MediaMapDefinition(ICultureDictionary cultureDictionary, CommonMapper commonMapper, CommonTreeNodeMapper commonTreeNodeMapper, IMediaService mediaService, IMediaTypeService mediaTypeService, - ILocalizedTextService localizedTextService, MediaUrlGeneratorCollection mediaUrlGenerators, IOptionsSnapshot contentSettings, IContentTypeBaseServiceProvider contentTypeBaseServiceProvider) + ILocalizedTextService localizedTextService, MediaUrlGeneratorCollection mediaUrlGenerators, IOptions contentSettings, IContentTypeBaseServiceProvider contentTypeBaseServiceProvider) { _commonMapper = commonMapper; _commonTreeNodeMapper = commonTreeNodeMapper; diff --git a/src/Umbraco.Web.BackOffice/Routing/BackOfficeAreaRoutes.cs b/src/Umbraco.Web.BackOffice/Routing/BackOfficeAreaRoutes.cs index 6d2fe9a9c8..dd3b3988c9 100644 --- a/src/Umbraco.Web.BackOffice/Routing/BackOfficeAreaRoutes.cs +++ b/src/Umbraco.Web.BackOffice/Routing/BackOfficeAreaRoutes.cs @@ -23,7 +23,7 @@ namespace Umbraco.Web.BackOffice.Routing private readonly string _umbracoPathSegment; public BackOfficeAreaRoutes( - IOptionsSnapshot globalSettings, + IOptions globalSettings, IHostingEnvironment hostingEnvironment, IRuntimeState runtimeState, UmbracoApiControllerTypeCollection apiControllers) diff --git a/src/Umbraco.Web.BackOffice/Security/BackOfficeSessionIdValidator.cs b/src/Umbraco.Web.BackOffice/Security/BackOfficeSessionIdValidator.cs index 2b70a1b083..e91a517496 100644 --- a/src/Umbraco.Web.BackOffice/Security/BackOfficeSessionIdValidator.cs +++ b/src/Umbraco.Web.BackOffice/Security/BackOfficeSessionIdValidator.cs @@ -39,7 +39,7 @@ namespace Umbraco.Web.BackOffice.Security private readonly IHostingEnvironment _hostingEnvironment; private readonly BackOfficeUserManager _userManager; - public BackOfficeSessionIdValidator(ISystemClock systemClock, IOptionsSnapshot globalSettings, IHostingEnvironment hostingEnvironment, BackOfficeUserManager userManager) + public BackOfficeSessionIdValidator(ISystemClock systemClock, IOptions globalSettings, IHostingEnvironment hostingEnvironment, BackOfficeUserManager userManager) { _systemClock = systemClock; _globalSettings = globalSettings.Value; diff --git a/src/Umbraco.Web.BackOffice/Security/ConfigureBackOfficeCookieOptions.cs b/src/Umbraco.Web.BackOffice/Security/ConfigureBackOfficeCookieOptions.cs index 69a5359d4e..3b8421ce6a 100644 --- a/src/Umbraco.Web.BackOffice/Security/ConfigureBackOfficeCookieOptions.cs +++ b/src/Umbraco.Web.BackOffice/Security/ConfigureBackOfficeCookieOptions.cs @@ -42,8 +42,8 @@ namespace Umbraco.Web.BackOffice.Security public ConfigureBackOfficeCookieOptions( IUmbracoContextAccessor umbracoContextAccessor, - IOptionsSnapshot securitySettings, - IOptionsSnapshot globalSettings, + IOptions securitySettings, + IOptions globalSettings, IHostingEnvironment hostingEnvironment, IRuntimeState runtimeState, IDataProtectionProvider dataProtection, diff --git a/src/Umbraco.Web.BackOffice/Security/ConfigureBackOfficeIdentityOptions.cs b/src/Umbraco.Web.BackOffice/Security/ConfigureBackOfficeIdentityOptions.cs index 5dd80411eb..31b5de2e43 100644 --- a/src/Umbraco.Web.BackOffice/Security/ConfigureBackOfficeIdentityOptions.cs +++ b/src/Umbraco.Web.BackOffice/Security/ConfigureBackOfficeIdentityOptions.cs @@ -16,7 +16,7 @@ namespace Umbraco.Web.BackOffice.Security { private readonly UserPasswordConfigurationSettings _userPasswordConfiguration; - public ConfigureBackOfficeIdentityOptions(IOptionsSnapshot userPasswordConfiguration) + public ConfigureBackOfficeIdentityOptions(IOptions userPasswordConfiguration) { _userPasswordConfiguration = userPasswordConfiguration.Value; } diff --git a/src/Umbraco.Web.BackOffice/Security/PreviewAuthenticationMiddleware.cs b/src/Umbraco.Web.BackOffice/Security/PreviewAuthenticationMiddleware.cs index f48996332c..1854187a2a 100644 --- a/src/Umbraco.Web.BackOffice/Security/PreviewAuthenticationMiddleware.cs +++ b/src/Umbraco.Web.BackOffice/Security/PreviewAuthenticationMiddleware.cs @@ -21,7 +21,7 @@ namespace Umbraco.Web.BackOffice.Security private readonly IHostingEnvironment _hostingEnvironment; public PreviewAuthenticationMiddleware( - IOptionsSnapshot globalSettings, + IOptions globalSettings, IHostingEnvironment hostingEnvironment) { _globalSettings = globalSettings.Value; diff --git a/src/Umbraco.Web.BackOffice/Trees/ContentTreeController.cs b/src/Umbraco.Web.BackOffice/Trees/ContentTreeController.cs index 2f72e1f829..44c83e3009 100644 --- a/src/Umbraco.Web.BackOffice/Trees/ContentTreeController.cs +++ b/src/Umbraco.Web.BackOffice/Trees/ContentTreeController.cs @@ -63,7 +63,7 @@ namespace Umbraco.Web.Trees IDataTypeService dataTypeService, UmbracoTreeSearcher treeSearcher, ActionCollection actions, - IOptionsSnapshot globalSettings, + IOptions globalSettings, IContentService contentService, IPublicAccessService publicAccessService, ILocalizationService localizationService) diff --git a/src/Umbraco.Web.Common/AspNetCore/AspNetCoreBackOfficeInfo.cs b/src/Umbraco.Web.Common/AspNetCore/AspNetCoreBackOfficeInfo.cs index 4dc72bfd95..6f40800307 100644 --- a/src/Umbraco.Web.Common/AspNetCore/AspNetCoreBackOfficeInfo.cs +++ b/src/Umbraco.Web.Common/AspNetCore/AspNetCoreBackOfficeInfo.cs @@ -6,7 +6,7 @@ namespace Umbraco.Web.Common.AspNetCore { public class AspNetCoreBackOfficeInfo : IBackOfficeInfo { - public AspNetCoreBackOfficeInfo(IOptionsSnapshot globalSettings) + public AspNetCoreBackOfficeInfo(IOptions globalSettings) : this(globalSettings.Value) { } diff --git a/src/Umbraco.Web.Common/AspNetCore/AspNetCoreHostingEnvironment.cs b/src/Umbraco.Web.Common/AspNetCore/AspNetCoreHostingEnvironment.cs index f35ced66f0..54502fbe29 100644 --- a/src/Umbraco.Web.Common/AspNetCore/AspNetCoreHostingEnvironment.cs +++ b/src/Umbraco.Web.Common/AspNetCore/AspNetCoreHostingEnvironment.cs @@ -15,7 +15,7 @@ namespace Umbraco.Web.Common.AspNetCore private string _localTempPath; - public AspNetCoreHostingEnvironment(IOptionsSnapshot hostingSettings, IWebHostEnvironment webHostEnvironment) + public AspNetCoreHostingEnvironment(IOptions hostingSettings, IWebHostEnvironment webHostEnvironment) : this(hostingSettings.Value, webHostEnvironment) { } diff --git a/src/Umbraco.Web.Common/AspNetCore/AspNetCoreRequestAccessor.cs b/src/Umbraco.Web.Common/AspNetCore/AspNetCoreRequestAccessor.cs index 2b27e37887..985c568a08 100644 --- a/src/Umbraco.Web.Common/AspNetCore/AspNetCoreRequestAccessor.cs +++ b/src/Umbraco.Web.Common/AspNetCore/AspNetCoreRequestAccessor.cs @@ -22,7 +22,7 @@ namespace Umbraco.Web.Common.AspNetCore public AspNetCoreRequestAccessor(IHttpContextAccessor httpContextAccessor, IUmbracoRequestLifetime umbracoRequestLifetime, IUmbracoContextAccessor umbracoContextAccessor, - IOptionsSnapshot webRoutingSettings) + IOptions webRoutingSettings) { _httpContextAccessor = httpContextAccessor; _umbracoContextAccessor = umbracoContextAccessor; diff --git a/src/Umbraco.Web.Common/AspNetCore/UmbracoViewPage.cs b/src/Umbraco.Web.Common/AspNetCore/UmbracoViewPage.cs index 28bb1dc41c..fde3d095fe 100644 --- a/src/Umbraco.Web.Common/AspNetCore/UmbracoViewPage.cs +++ b/src/Umbraco.Web.Common/AspNetCore/UmbracoViewPage.cs @@ -25,8 +25,8 @@ namespace Umbraco.Web.Common.AspNetCore private IUmbracoContext _umbracoContext; private IUmbracoContextAccessor UmbracoContextAccessor => Context.RequestServices.GetRequiredService(); - private GlobalSettings GlobalSettings => Context.RequestServices.GetRequiredService>().Value; - private ContentSettings ContentSettings => Context.RequestServices.GetRequiredService>().Value; + private GlobalSettings GlobalSettings => Context.RequestServices.GetRequiredService>().Value; + private ContentSettings ContentSettings => Context.RequestServices.GetRequiredService>().Value; private IProfilerHtml ProfilerHtml => Context.RequestServices.GetRequiredService(); private IIOHelper IOHelper => Context.RequestServices.GetRequiredService(); diff --git a/src/Umbraco.Web.Common/Extensions/UmbracoCoreServiceCollectionExtensions.cs b/src/Umbraco.Web.Common/Extensions/UmbracoCoreServiceCollectionExtensions.cs index 4653bc7bbd..d03fb183e7 100644 --- a/src/Umbraco.Web.Common/Extensions/UmbracoCoreServiceCollectionExtensions.cs +++ b/src/Umbraco.Web.Common/Extensions/UmbracoCoreServiceCollectionExtensions.cs @@ -124,6 +124,7 @@ namespace Umbraco.Extensions services.Configure(configuration.GetSection(Constants.Configuration.ConfigPrefix + "Examine:")); services.Configure(configuration.GetSection(Constants.Configuration.ConfigModelsBuilderPrefix)); services.Configure(configuration.GetSection(Constants.Configuration.ConfigPrefix + "Imaging:")); + services.Configure(configuration.GetSection(Constants.Configuration.ConfigPrefix + "RequestHandler:")); // TODO: HealthChecksSettings (+ one other?) @@ -225,10 +226,10 @@ namespace Umbraco.Extensions // `RegisterEssentials`. var serviceProvider = services.BuildServiceProvider(); - var globalSettings = serviceProvider.GetService>().Value; - var connectionStrings = serviceProvider.GetService>().Value; - var hostingSettings = serviceProvider.GetService>().Value; - var typeFinderSettings = serviceProvider.GetService>().Value; + var globalSettings = serviceProvider.GetService>().Value; + var connectionStrings = serviceProvider.GetService>().Value; + var hostingSettings = serviceProvider.GetService>().Value; + var typeFinderSettings = serviceProvider.GetService>().Value; var dbProviderFactoryCreator = serviceProvider.GetRequiredService(); diff --git a/src/Umbraco.Web.Common/Extensions/UmbracoWebServiceCollectionExtensions.cs b/src/Umbraco.Web.Common/Extensions/UmbracoWebServiceCollectionExtensions.cs index 61120c8ee9..0b9154b6cf 100644 --- a/src/Umbraco.Web.Common/Extensions/UmbracoWebServiceCollectionExtensions.cs +++ b/src/Umbraco.Web.Common/Extensions/UmbracoWebServiceCollectionExtensions.cs @@ -41,7 +41,7 @@ namespace Umbraco.Extensions // TODO: We need to avoid this, surely there's a way? See ContainerTests.BuildServiceProvider_Before_Host_Is_Configured var serviceProvider = services.BuildServiceProvider(); - var imagingSettings = serviceProvider.GetService>().Value; + var imagingSettings = serviceProvider.GetService>().Value; services.AddUmbracoImageSharp(imagingSettings); return services; diff --git a/src/Umbraco.Web.Common/Filters/ModelBindingExceptionFilter.cs b/src/Umbraco.Web.Common/Filters/ModelBindingExceptionFilter.cs index 76e462843e..3c1de1e138 100644 --- a/src/Umbraco.Web.Common/Filters/ModelBindingExceptionFilter.cs +++ b/src/Umbraco.Web.Common/Filters/ModelBindingExceptionFilter.cs @@ -26,7 +26,7 @@ namespace Umbraco.Web.Common.Filters private readonly ExceptionFilterSettings _exceptionFilterSettings; private readonly IPublishedModelFactory _publishedModelFactory; - public ModelBindingExceptionFilter(IOptionsSnapshot exceptionFilterSettings, IPublishedModelFactory publishedModelFactory) + public ModelBindingExceptionFilter(IOptions exceptionFilterSettings, IPublishedModelFactory publishedModelFactory) { _exceptionFilterSettings = exceptionFilterSettings.Value; _publishedModelFactory = publishedModelFactory ?? throw new ArgumentNullException(nameof(publishedModelFactory)); diff --git a/src/Umbraco.Web.Common/Filters/StatusCodeResultAttribute.cs b/src/Umbraco.Web.Common/Filters/StatusCodeResultAttribute.cs index a35628821b..fe941e89d5 100644 --- a/src/Umbraco.Web.Common/Filters/StatusCodeResultAttribute.cs +++ b/src/Umbraco.Web.Common/Filters/StatusCodeResultAttribute.cs @@ -28,7 +28,7 @@ namespace Umbraco.Web.Common.Filters httpContext.Response.StatusCode = (int)_statusCode; - var disableIisCustomErrors = httpContext.RequestServices.GetService>().Value.TrySkipIisCustomErrors; + var disableIisCustomErrors = httpContext.RequestServices.GetService>().Value.TrySkipIisCustomErrors; var statusCodePagesFeature = httpContext.Features.Get(); if (statusCodePagesFeature != null) diff --git a/src/Umbraco.Web.Common/Install/InstallController.cs b/src/Umbraco.Web.Common/Install/InstallController.cs index d97bb86fed..b5da8eabd4 100644 --- a/src/Umbraco.Web.Common/Install/InstallController.cs +++ b/src/Umbraco.Web.Common/Install/InstallController.cs @@ -39,7 +39,7 @@ namespace Umbraco.Web.Common.Install IWebSecurity webSecurity, InstallHelper installHelper, IRuntimeState runtime, - IOptionsSnapshot globalSettings, + IOptions globalSettings, IRuntimeMinifier runtimeMinifier, IHostingEnvironment hostingEnvironment, IUmbracoVersion umbracoVersion, diff --git a/src/Umbraco.Web.Common/Macros/MacroRenderer.cs b/src/Umbraco.Web.Common/Macros/MacroRenderer.cs index eae771b930..c1fb033d20 100644 --- a/src/Umbraco.Web.Common/Macros/MacroRenderer.cs +++ b/src/Umbraco.Web.Common/Macros/MacroRenderer.cs @@ -37,7 +37,7 @@ namespace Umbraco.Web.Macros public MacroRenderer( IProfilingLogger plogger, IUmbracoContextAccessor umbracoContextAccessor, - IOptionsSnapshot contentSettings, + IOptions contentSettings, ILocalizedTextService textService, AppCaches appCaches, IMacroService macroService, diff --git a/src/Umbraco.Web.Common/Runtime/AspNetCoreComposer.cs b/src/Umbraco.Web.Common/Runtime/AspNetCoreComposer.cs index 0cfacbbf13..67755da5ea 100644 --- a/src/Umbraco.Web.Common/Runtime/AspNetCoreComposer.cs +++ b/src/Umbraco.Web.Common/Runtime/AspNetCoreComposer.cs @@ -97,7 +97,7 @@ namespace Umbraco.Web.Common.Runtime composition.RegisterUnique(); composition.RegisterUnique(); - composition.RegisterUnique(factory => new LegacyPasswordSecurity(factory.GetInstance>().Value)); + composition.RegisterUnique(factory => new LegacyPasswordSecurity(factory.GetInstance>().Value)); } diff --git a/src/Umbraco.Web.Common/Security/WebSecurity.cs b/src/Umbraco.Web.Common/Security/WebSecurity.cs index 69f5850482..b822adf656 100644 --- a/src/Umbraco.Web.Common/Security/WebSecurity.cs +++ b/src/Umbraco.Web.Common/Security/WebSecurity.cs @@ -22,7 +22,7 @@ namespace Umbraco.Web.Common.Security public WebSecurity( IUserService userService, - IOptionsSnapshot globalSettings, + IOptions globalSettings, IHostingEnvironment hostingEnvironment, IHttpContextAccessor httpContextAccessor) { diff --git a/src/Umbraco.Web.Common/Templates/TemplateRenderer.cs b/src/Umbraco.Web.Common/Templates/TemplateRenderer.cs index 81a635a20f..1bec3cf41c 100644 --- a/src/Umbraco.Web.Common/Templates/TemplateRenderer.cs +++ b/src/Umbraco.Web.Common/Templates/TemplateRenderer.cs @@ -45,7 +45,7 @@ namespace Umbraco.Web.Common.Templates IPublishedRouter publishedRouter, IFileService fileService, ILocalizationService textService, - IOptionsSnapshot webRoutingSettings, + IOptions webRoutingSettings, IShortStringHelper shortStringHelper, IHttpContextAccessor httpContextAccessor, ICompositeViewEngine viewEngine) diff --git a/src/Umbraco.Web.Common/UmbracoContext/UmbracoContextFactory.cs b/src/Umbraco.Web.Common/UmbracoContext/UmbracoContextFactory.cs index a3849c532e..d9df11e4a9 100644 --- a/src/Umbraco.Web.Common/UmbracoContext/UmbracoContextFactory.cs +++ b/src/Umbraco.Web.Common/UmbracoContext/UmbracoContextFactory.cs @@ -41,7 +41,7 @@ namespace Umbraco.Web IPublishedSnapshotService publishedSnapshotService, IVariationContextAccessor variationContextAccessor, IDefaultCultureAccessor defaultCultureAccessor, - IOptionsSnapshot globalSettings, + IOptions globalSettings, IUserService userService, IHostingEnvironment hostingEnvironment, UriUtility uriUtility, diff --git a/src/Umbraco.Web.UI.NetCore/umbraco/UmbracoBackOffice/Default.cshtml b/src/Umbraco.Web.UI.NetCore/umbraco/UmbracoBackOffice/Default.cshtml index bce17553d6..b7c654a80d 100644 --- a/src/Umbraco.Web.UI.NetCore/umbraco/UmbracoBackOffice/Default.cshtml +++ b/src/Umbraco.Web.UI.NetCore/umbraco/UmbracoBackOffice/Default.cshtml @@ -13,7 +13,7 @@ @inject BackOfficeServerVariables backOfficeServerVariables @inject IUmbracoVersion umbracoVersion @inject IHostingEnvironment hostingEnvironment -@inject IOptionsSnapshot globalSettings +@inject IOptions globalSettings @inject IRuntimeMinifier runtimeMinifier @inject IProfilerHtml profilerHtml diff --git a/src/Umbraco.Web.UI.NetCore/umbraco/UmbracoBackOffice/Preview.cshtml b/src/Umbraco.Web.UI.NetCore/umbraco/UmbracoBackOffice/Preview.cshtml index dd34dab6f4..212d6bddee 100644 --- a/src/Umbraco.Web.UI.NetCore/umbraco/UmbracoBackOffice/Preview.cshtml +++ b/src/Umbraco.Web.UI.NetCore/umbraco/UmbracoBackOffice/Preview.cshtml @@ -12,7 +12,7 @@ @inject BackOfficeServerVariables backOfficeServerVariables @inject IUmbracoVersion umbracoVersion @inject IHostingEnvironment hostingEnvironment -@inject IOptionsSnapshot globalSettings +@inject IOptions globalSettings @inject IRuntimeMinifier runtimeMinifier @inject IProfilerHtml profilerHtml From b944142905bb818f3c5ac8ddeb2a7e17c3614f47 Mon Sep 17 00:00:00 2001 From: Nikolaj Date: Mon, 24 Aug 2020 08:45:41 +0200 Subject: [PATCH 247/826] Add PreviewViewExists test --- .../AutoFixture/AutoMoqDataAttribute.cs | 1 + .../InstallControllerTest.cs | 20 +++++++++++++++++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Tests.UnitTests/AutoFixture/AutoMoqDataAttribute.cs b/src/Umbraco.Tests.UnitTests/AutoFixture/AutoMoqDataAttribute.cs index dab22fbb62..adb1166cd8 100644 --- a/src/Umbraco.Tests.UnitTests/AutoFixture/AutoMoqDataAttribute.cs +++ b/src/Umbraco.Tests.UnitTests/AutoFixture/AutoMoqDataAttribute.cs @@ -39,6 +39,7 @@ namespace Umbraco.Tests.UnitTests.AutoFixture fixture .Customize(new ConstructorCustomization(typeof(UsersController), new GreedyConstructorQuery())) .Customize(new ConstructorCustomization(typeof(InstallController), new GreedyConstructorQuery())) + .Customize(new ConstructorCustomization(typeof(PreviewController), new GreedyConstructorQuery())) .Customize(new ConstructorCustomization(typeof(BackOfficeUserManager), new GreedyConstructorQuery())) .Customize(new AutoMoqCustomization()); diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Web.Common/InstallControllerTest.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Web.Common/InstallControllerTest.cs index 847d0a900b..484d7e48a6 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Web.Common/InstallControllerTest.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Web.Common/InstallControllerTest.cs @@ -14,16 +14,16 @@ using Umbraco.Core.Hosting; using System.IO; using System.Reflection; using System.Linq; +using Umbraco.Web.BackOffice.Controllers; namespace Umbraco.Tests.UnitTests.Umbraco.Web.Common { [TestFixture] - class InstallControllerTest + class InstallControllerTest // TODO: Is this the right place? { [Test, AutoMoqData] public async Task InstallViewExists( [Frozen] IHostingEnvironment hostingEnvironment, - IHostingEnvironment environment, InstallController sut) { Mock.Get(hostingEnvironment).Setup(x => x.ToAbsolute(It.IsAny())).Returns("/"); @@ -36,5 +36,21 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.Common .Select(f => f.Name).ToArray(); Assert.True(views.Contains(fileName), $"Expected {fileName} to exist, but it didn't"); } + + [Test, AutoMoqData] + public void PrviewViewExists( + [Frozen] IGlobalSettings globalSettings, + PreviewController sut) + { + Mock.Get(globalSettings).Setup(x => x.UmbracoPath).Returns("/"); + + var viewResult = sut.Index() as ViewResult; + var sections = viewResult.ViewName.Split("/"); + var fileName = sections[sections.Length - 1]; + + var views = new DirectoryInfo(@"..\\..\\..\\..\\Umbraco.Web.UI.NetCore\\umbraco\\UmbracoBackOffice").GetFiles() + .Select(f => f.Name).ToArray(); + Assert.True(views.Contains(fileName), $"Expected {fileName} to exist, but it didn't"); + } } } From 31e8acb875b781d3e55648d59d0fadf773d3d705 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Mon, 24 Aug 2020 09:23:37 +0200 Subject: [PATCH 248/826] Renamed nuget pacakges to Umbrac.Cms.* --- build/NuSpecs/UmbracoCms.Core.nuspec | 2 +- build/NuSpecs/UmbracoCms.SqlCe.nuspec | 4 ++-- build/NuSpecs/UmbracoCms.Web.nuspec | 4 ++-- build/NuSpecs/UmbracoCms.nuspec | 4 ++-- build/build.ps1 | 4 ++-- build/templates/UmbracoSolution/UmbracoSolution.csproj | 4 ++-- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/build/NuSpecs/UmbracoCms.Core.nuspec b/build/NuSpecs/UmbracoCms.Core.nuspec index c72e01baa3..bb05e91b96 100644 --- a/build/NuSpecs/UmbracoCms.Core.nuspec +++ b/build/NuSpecs/UmbracoCms.Core.nuspec @@ -1,7 +1,7 @@ - UmbracoCms.Core + Umbraco.Cms.Core 9.0.0 Umbraco Cms Core Binaries Umbraco HQ diff --git a/build/NuSpecs/UmbracoCms.SqlCe.nuspec b/build/NuSpecs/UmbracoCms.SqlCe.nuspec index d64b24cf88..7c7fa2d902 100644 --- a/build/NuSpecs/UmbracoCms.SqlCe.nuspec +++ b/build/NuSpecs/UmbracoCms.SqlCe.nuspec @@ -1,7 +1,7 @@ - UmbracoCms.SqlCe + Umbraco.Cms.SqlCe 9.0.0 Umbraco Cms Sql Ce Add-on Umbraco HQ @@ -23,7 +23,7 @@ the latter would pick anything below 3.0.0 and that includes prereleases such as 3.0.0-alpha, and we do not want this to happen as the alpha of the next major is, really, the next major already. --> - + diff --git a/build/NuSpecs/UmbracoCms.Web.nuspec b/build/NuSpecs/UmbracoCms.Web.nuspec index a35cea9df7..47aab4cdb8 100644 --- a/build/NuSpecs/UmbracoCms.Web.nuspec +++ b/build/NuSpecs/UmbracoCms.Web.nuspec @@ -1,7 +1,7 @@ - UmbracoCms.Web + Umbraco.Cms.Web 9.0.0 Umbraco Cms Core Binaries Umbraco HQ @@ -23,7 +23,7 @@ the latter would pick anything below 3.0.0 and that includes prereleases such as 3.0.0-alpha, and we do not want this to happen as the alpha of the next major is, really, the next major already. --> - + diff --git a/build/NuSpecs/UmbracoCms.nuspec b/build/NuSpecs/UmbracoCms.nuspec index fbcff62bb6..a87d14ed64 100644 --- a/build/NuSpecs/UmbracoCms.nuspec +++ b/build/NuSpecs/UmbracoCms.nuspec @@ -1,7 +1,7 @@ - UmbracoCms + Umbraco.Cms 9.0.0 Umbraco Cms Umbraco HQ @@ -17,7 +17,7 @@ - + - - - - - - - - - 1 - - - - - - - - your@email.here - - - - - - Preview mode - - … - - - Click to end - - - - ]]> - - - - throw - - - ashx,aspx,ascx,config,cshtml,vbhtml,asmx,air,axd,swf,xml,xhtml,html,htm,php,htaccess - - - assets/img/login.jpg - - - - - - false - - - true - - - false - - - - - - - - - - - - - - - - diff --git a/src/Umbraco.Web.UI.NetCore/config/umbracoSettings.config b/src/Umbraco.Web.UI.NetCore/config/umbracoSettings.config deleted file mode 100644 index 5814a82095..0000000000 --- a/src/Umbraco.Web.UI.NetCore/config/umbracoSettings.config +++ /dev/null @@ -1,276 +0,0 @@ - - - - - - - - - - - - - 1 - - - - - - - - your@email.here - - - - - - Preview mode - - … - - - Click to end - - - - ]]> - - - - throw - - - ashx,aspx,ascx,config,cshtml,vbhtml,asmx,air,axd,swf,xml,xhtml,html,htm,php,htaccess - - - assets/img/login.jpg - - - - - - false - - - true - - - false - - - - - - - - - - - - - - - - - - \ No newline at end of file From 892a7e0b3439ccdd048aededfc55703625db1a00 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Mon, 24 Aug 2020 14:16:34 +0200 Subject: [PATCH 259/826] Changed default value of HideTopLevelNodeFromPath to true --- src/Umbraco.Configuration/Models/GlobalSettings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Configuration/Models/GlobalSettings.cs b/src/Umbraco.Configuration/Models/GlobalSettings.cs index 908ba71590..d1f3f12017 100644 --- a/src/Umbraco.Configuration/Models/GlobalSettings.cs +++ b/src/Umbraco.Configuration/Models/GlobalSettings.cs @@ -42,7 +42,7 @@ namespace Umbraco.Configuration.Models public string DefaultUILanguage => _configuration.GetValue(Prefix + "DefaultUILanguage", "en-US"); public bool HideTopLevelNodeFromPath => - _configuration.GetValue(Prefix + "HideTopLevelNodeFromPath", false); + _configuration.GetValue(Prefix + "HideTopLevelNodeFromPath", true); public bool UseHttps => _configuration.GetValue(Prefix + "UseHttps", false); public int VersionCheckPeriod => _configuration.GetValue(Prefix + "VersionCheckPeriod", 7); From b5b492106dc277b1f8b6911ba162f953cfc43c1f Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Mon, 24 Aug 2020 14:23:08 +0200 Subject: [PATCH 260/826] Clean up by moving stuff from Startup.cs into extention methods --- ...oBackOfficeApplicationBuilderExtensions.cs | 21 +++++++ ...coBackOfficeServiceCollectionExtensions.cs | 50 +++++++++++++++- src/Umbraco.Web.UI.NetCore/Startup.cs | 60 ++----------------- 3 files changed, 74 insertions(+), 57 deletions(-) diff --git a/src/Umbraco.Web.BackOffice/Extensions/UmbracoBackOfficeApplicationBuilderExtensions.cs b/src/Umbraco.Web.BackOffice/Extensions/UmbracoBackOfficeApplicationBuilderExtensions.cs index c34d9936bc..282668e4e6 100644 --- a/src/Umbraco.Web.BackOffice/Extensions/UmbracoBackOfficeApplicationBuilderExtensions.cs +++ b/src/Umbraco.Web.BackOffice/Extensions/UmbracoBackOfficeApplicationBuilderExtensions.cs @@ -9,10 +9,31 @@ namespace Umbraco.Extensions { public static class UmbracoBackOfficeApplicationBuilderExtensions { + public static IApplicationBuilder UseUmbraco(this IApplicationBuilder app) + { + if (app == null) throw new ArgumentNullException(nameof(app)); + app.UseStatusCodePages(); + app.UseRouting(); + + app.UseUmbracoCore(); + app.UseUmbracoRouting(); + app.UseRequestLocalization(); + app.UseUmbracoRequestLogging(); + app.UseUmbracoBackOffice(); + app.UseUmbracoInstaller(); + + return app; + } + public static IApplicationBuilder UseUmbracoBackOffice(this IApplicationBuilder app) { if (app == null) throw new ArgumentNullException(nameof(app)); + // Important we handle image manipulations before the static files, otherwise the querystring is just ignored. + // TODO: Since we are dependent on these we need to register them but what happens when we call this multiple times since we are dependent on this for UseUmbracoBackOffice too? + app.UseImageSharp(); + app.UseStaticFiles(); + if (!app.UmbracoCanBoot()) return app; app.UseEndpoints(endpoints => diff --git a/src/Umbraco.Web.BackOffice/Extensions/UmbracoBackOfficeServiceCollectionExtensions.cs b/src/Umbraco.Web.BackOffice/Extensions/UmbracoBackOfficeServiceCollectionExtensions.cs index 2c7db69b84..fc3efab5e0 100644 --- a/src/Umbraco.Web.BackOffice/Extensions/UmbracoBackOfficeServiceCollectionExtensions.cs +++ b/src/Umbraco.Web.BackOffice/Extensions/UmbracoBackOfficeServiceCollectionExtensions.cs @@ -1,5 +1,10 @@ -using Microsoft.AspNetCore.Identity; +using System; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc.Filters; +using Microsoft.AspNetCore.Server.Kestrel.Core; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Umbraco.Core; @@ -17,6 +22,49 @@ namespace Umbraco.Extensions { public static class UmbracoBackOfficeServiceCollectionExtensions { + public static IServiceCollection AddUmbraco(this IServiceCollection services, IWebHostEnvironment webHostEnvironment, IConfiguration config) + { + if (services == null) throw new ArgumentNullException(nameof(services)); + + // TODO: We will need to decide on if we want to use the ServiceBasedControllerActivator to create our controllers + // or use the default IControllerActivator: DefaultControllerActivator (which doesn't directly use the container to resolve controllers) + // This will affect whether we need to explicitly register controllers in the container like we do today in v8. + // What we absolutely must do though is make sure we explicitly opt-in to using one or the other *always* for our controllers instead of + // relying on a global configuration set by a user since if a custom IControllerActivator is used for our own controllers we may not + // guarantee it will work. And then... is that even possible? + + // TODO: we will need to simplify this and prob just have a one or 2 main method that devs call which call all other required methods, + // but for now we'll just be explicit with all of them + services.AddUmbracoConfiguration(config); + services.AddUmbracoCore(webHostEnvironment, out var factory); + services.AddUmbracoWebComponents(); + services.AddUmbracoRuntimeMinifier(config); + services.AddUmbracoBackOffice(); + services.AddUmbracoBackOfficeIdentity(); + services.AddMiniProfiler(options => + { + options.ShouldProfile = request => false; // WebProfiler determine and start profiling. We should not use the MiniProfilerMiddleware to also profile + }); + + //We need to have runtime compilation of views when using umbraco. We could consider having only this when a specific config is set. + //But as far as I can see, there are still precompiled views, even when this is activated, so maybe it is okay. + services.AddControllersWithViews().AddRazorRuntimeCompilation(); + + + // If using Kestrel: https://stackoverflow.com/a/55196057 + services.Configure(options => + { + options.AllowSynchronousIO = true; + }); + + services.Configure(options => + { + options.AllowSynchronousIO = true; + }); + + return services; + } + /// /// Adds the services required for running the Umbraco back office /// diff --git a/src/Umbraco.Web.UI.NetCore/Startup.cs b/src/Umbraco.Web.UI.NetCore/Startup.cs index 21faae22f2..673ac02013 100644 --- a/src/Umbraco.Web.UI.NetCore/Startup.cs +++ b/src/Umbraco.Web.UI.NetCore/Startup.cs @@ -1,7 +1,6 @@ using System; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Server.Kestrel.Core; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; @@ -17,8 +16,8 @@ namespace Umbraco.Web.UI.NetCore /// /// Constructor /// - /// - /// + /// The Web Host Environment + /// The Configuration /// /// Only a few services are possible to be injected here https://github.com/dotnet/aspnetcore/issues/9337 /// @@ -32,69 +31,18 @@ namespace Umbraco.Web.UI.NetCore // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 public void ConfigureServices(IServiceCollection services) { - // TODO: We will need to decide on if we want to use the ServiceBasedControllerActivator to create our controllers - // or use the default IControllerActivator: DefaultControllerActivator (which doesn't directly use the container to resolve controllers) - // This will affect whether we need to explicitly register controllers in the container like we do today in v8. - // What we absolutely must do though is make sure we explicitly opt-in to using one or the other *always* for our controllers instead of - // relying on a global configuration set by a user since if a custom IControllerActivator is used for our own controllers we may not - // guarantee it will work. And then... is that even possible? - - // TODO: we will need to simplify this and prob just have a one or 2 main method that devs call which call all other required methods, - // but for now we'll just be explicit with all of them - services.AddUmbracoConfiguration(_config); - services.AddUmbracoCore(_env, out var factory); - services.AddUmbracoWebComponents(); - services.AddUmbracoRuntimeMinifier(_config); - services.AddUmbracoBackOffice(); - services.AddUmbracoBackOfficeIdentity(); - services.AddMiniProfiler(options => - { - options.ShouldProfile = request => false; // WebProfiler determine and start profiling. We should not use the MiniProfilerMiddleware to also profile - }); - - //We need to have runtime compilation of views when using umbraco. We could consider having only this when a specific config is set. - //But as far as I can see, there are still precompiled views, even when this is activated, so maybe it is okay. - services.AddControllersWithViews().AddRazorRuntimeCompilation(); - - - // If using Kestrel: https://stackoverflow.com/a/55196057 - services.Configure(options => - { - options.AllowSynchronousIO = true; - }); - - services.Configure(options => - { - options.AllowSynchronousIO = true; - }); + services.AddUmbraco(_env, _config); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app) { - //app.UseMiniProfiler(); if (_env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } - app.UseStatusCodePages(); - app.UseRouting(); - - app.UseUmbracoCore(); - app.UseUmbracoRouting(); - app.UseRequestLocalization(); - app.UseUmbracoRequestLogging(); - app.UseUmbracoWebsite(); - app.UseUmbracoBackOffice(); - app.UseUmbracoInstaller(); - - app.UseEndpoints(endpoints => - { - endpoints.MapControllerRoute( - name: "default", - pattern: "{controller}/{action=Index}/{id?}"); - }); + app.UseUmbraco(); } } } From 863a7195b2d13ac3d110558cc55f833510d5af67 Mon Sep 17 00:00:00 2001 From: Andy Butland Date: Mon, 24 Aug 2020 16:06:09 +0200 Subject: [PATCH 261/826] Restored Umbraco.Tests (partially) --- .../Models/RequestHandlerSettings.cs | 36 ++++----- .../Packaging/CompiledPackageXmlParser.cs | 6 +- .../ModelToSqlExpressionHelperBenchmarks.cs | 1 - .../Builders/ModelsBuilderConfigBuilder.cs | 12 +++ .../Builders/RequestHandlerSettingsBuilder.cs | 23 +++++- .../RequestHandlerSettingsBuilderTests.cs | 11 ++- .../Components/ComponentTests.cs | 38 +++++----- .../Composing/CollectionBuildersTests.cs | 2 +- .../Composing/CompositionTests.cs | 2 +- .../Composing/LazyCollectionBuilderTests.cs | 10 +-- .../Composing/PackageActionCollectionTests.cs | 2 +- .../Configurations/GlobalSettingsTests.cs | 9 +-- .../CoreThings/TryConvertToTests.cs | 4 +- src/Umbraco.Tests/IO/FileSystemsTests.cs | 2 +- src/Umbraco.Tests/IO/ShadowFileSystemTests.cs | 11 ++- .../Migrations/AdvancedMigrationTests.cs | 5 +- .../Migrations/MigrationPlanTests.cs | 5 +- src/Umbraco.Tests/Models/MediaXmlTest.cs | 5 +- .../ModelsBuilder/BuilderTests.cs | 10 ++- .../CreatedPackagesRepositoryTests.cs | 7 +- .../Packaging/PackageDataInstallationTests.cs | 6 +- .../Packaging/PackageInstallationTest.cs | 3 +- .../Persistence/DatabaseContextTests.cs | 7 +- .../Repositories/ContentTypeRepositoryTest.cs | 15 +++- .../Repositories/DictionaryRepositoryTest.cs | 7 +- .../Repositories/DocumentRepositoryTest.cs | 5 +- .../Repositories/DomainRepositoryTest.cs | 11 ++- .../Repositories/LanguageRepositoryTest.cs | 31 ++++---- .../Repositories/UserRepositoryTest.cs | 10 ++- .../Persistence/SchemaValidationTest.cs | 4 +- .../Persistence/SqlCeTableByTableTest.cs | 4 +- .../PropertyEditorValueEditorTests.cs | 6 +- .../Published/ConvertersTests.cs | 2 +- .../PublishedContent/NuCacheChildrenTests.cs | 14 ++-- .../PublishedContent/NuCacheTests.cs | 13 ++-- .../PublishedContentLanguageVariantTests.cs | 3 +- .../ContentFinderByUrlAndTemplateTests.cs | 4 +- .../Routing/GetContentUrlsTests.cs | 50 ++++++++----- .../Routing/RenderRouteHandlerTests.cs | 30 ++++---- .../Routing/UmbracoModuleTests.cs | 3 +- src/Umbraco.Tests/Runtimes/StandaloneTests.cs | 19 +++-- .../Scoping/ScopeEventDispatcherTests.cs | 2 +- .../Scoping/ScopedNuCacheTests.cs | 9 ++- .../Scoping/ScopedRepositoryTests.cs | 31 +++++--- .../BackOfficeOwinUserManagerTests.cs | 4 +- .../OwinDataProtectorTokenProviderTests.cs | 4 +- .../Services/ContentServiceEventTests.cs | 11 ++- .../ContentServicePublishBranchTests.cs | 9 ++- .../Services/ContentServiceTagsTests.cs | 15 ++-- .../Services/ContentServiceTests.cs | 74 ++++++++++--------- .../ContentTypeServiceVariantsTests.cs | 24 ++++-- .../Services/EntityServiceTests.cs | 6 +- .../Services/EntityXmlSerializerTests.cs | 18 +++-- .../Services/LocalizationServiceTests.cs | 28 ++++--- .../Services/SectionServiceTests.cs | 4 +- .../Services/UserServiceTests.cs | 5 +- .../Strings/DefaultShortStringHelperTests.cs | 73 +++++++++--------- .../TestHelpers/BaseUsingSqlCeSyntax.cs | 2 +- .../TestHelpers/Entities/MockedUser.cs | 7 +- src/Umbraco.Tests/TestHelpers/TestObjects.cs | 30 +++++--- .../TestHelpers/TestWithDatabaseBase.cs | 4 +- src/Umbraco.Tests/Testing/UmbracoTestBase.cs | 18 +++-- 62 files changed, 507 insertions(+), 319 deletions(-) create mode 100644 src/Umbraco.Tests.Common/Builders/ModelsBuilderConfigBuilder.cs diff --git a/src/Umbraco.Core/Configuration/Models/RequestHandlerSettings.cs b/src/Umbraco.Core/Configuration/Models/RequestHandlerSettings.cs index b52285c42c..e168122738 100644 --- a/src/Umbraco.Core/Configuration/Models/RequestHandlerSettings.cs +++ b/src/Umbraco.Core/Configuration/Models/RequestHandlerSettings.cs @@ -5,7 +5,7 @@ namespace Umbraco.Core.Configuration.Models { public class RequestHandlerSettings { - private static readonly CharItem[] DefaultCharCollection = + internal static readonly CharItem[] DefaultCharCollection = { new CharItem { Char = " ", Replacement = "-" }, new CharItem { Char = "\"", Replacement = "" }, @@ -40,33 +40,29 @@ namespace Umbraco.Core.Configuration.Models public bool TryConvertUrlsToAscii { get; set; } = false; //We need to special handle ":", as this character is special in keys - public IEnumerable CharCollection - { - get - { - // TODO: implement from configuration - //var collection = _configuration.GetSection(Prefix + "CharCollection").GetChildren() - // .Select(x => new CharItem() - // { - // Char = x.GetValue("Char"), - // Replacement = x.GetValue("Replacement"), - // }).ToArray(); + // TODO: implement from configuration - //if (collection.Any() || _configuration.GetSection("Prefix").GetChildren().Any(x => - // x.Key.Equals("CharCollection", StringComparison.OrdinalIgnoreCase))) - //{ - // return collection; - //} + //var collection = _configuration.GetSection(Prefix + "CharCollection").GetChildren() + // .Select(x => new CharItem() + // { + // Char = x.GetValue("Char"), + // Replacement = x.GetValue("Replacement"), + // }).ToArray(); - return DefaultCharCollection; - } - } + //if (collection.Any() || _configuration.GetSection("Prefix").GetChildren().Any(x => + // x.Key.Equals("CharCollection", StringComparison.OrdinalIgnoreCase))) + //{ + // return collection; + //} + // return DefaultCharCollection; + public IEnumerable CharCollection { get; set; } public class CharItem : IChar { public string Char { get; set; } + public string Replacement { get; set; } } } diff --git a/src/Umbraco.Core/Packaging/CompiledPackageXmlParser.cs b/src/Umbraco.Core/Packaging/CompiledPackageXmlParser.cs index 510a4122e9..010e6469bf 100644 --- a/src/Umbraco.Core/Packaging/CompiledPackageXmlParser.cs +++ b/src/Umbraco.Core/Packaging/CompiledPackageXmlParser.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Xml.Linq; -using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Models.Packaging; using File = System.IO.File; @@ -15,9 +15,9 @@ namespace Umbraco.Core.Packaging public class CompiledPackageXmlParser { private readonly ConflictingPackageData _conflictingPackageData; - private readonly IGlobalSettings _globalSettings; + private readonly GlobalSettings _globalSettings; - public CompiledPackageXmlParser(ConflictingPackageData conflictingPackageData, IGlobalSettings globalSettings) + public CompiledPackageXmlParser(ConflictingPackageData conflictingPackageData, GlobalSettings globalSettings) { _conflictingPackageData = conflictingPackageData; _globalSettings = globalSettings; diff --git a/src/Umbraco.Tests.Benchmarks/ModelToSqlExpressionHelperBenchmarks.cs b/src/Umbraco.Tests.Benchmarks/ModelToSqlExpressionHelperBenchmarks.cs index 6eb955ea8f..d200b3e295 100644 --- a/src/Umbraco.Tests.Benchmarks/ModelToSqlExpressionHelperBenchmarks.cs +++ b/src/Umbraco.Tests.Benchmarks/ModelToSqlExpressionHelperBenchmarks.cs @@ -3,7 +3,6 @@ using System.Collections.Concurrent; using System.Linq.Expressions; using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Diagnosers; -using Moq; using Umbraco.Core.Models; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.Mappers; diff --git a/src/Umbraco.Tests.Common/Builders/ModelsBuilderConfigBuilder.cs b/src/Umbraco.Tests.Common/Builders/ModelsBuilderConfigBuilder.cs new file mode 100644 index 0000000000..4b94339dc0 --- /dev/null +++ b/src/Umbraco.Tests.Common/Builders/ModelsBuilderConfigBuilder.cs @@ -0,0 +1,12 @@ +using Umbraco.Core.Configuration.Models; + +namespace Umbraco.Tests.Common.Builders +{ + public class ModelsBuilderConfigBuilder : BuilderBase + { + public override ModelsBuilderConfig Build() + { + return new ModelsBuilderConfig(); + } + } +} diff --git a/src/Umbraco.Tests.Common/Builders/RequestHandlerSettingsBuilder.cs b/src/Umbraco.Tests.Common/Builders/RequestHandlerSettingsBuilder.cs index 43cdacbb9b..33f63c9d16 100644 --- a/src/Umbraco.Tests.Common/Builders/RequestHandlerSettingsBuilder.cs +++ b/src/Umbraco.Tests.Common/Builders/RequestHandlerSettingsBuilder.cs @@ -1,10 +1,14 @@ +using System.Collections.Generic; using Umbraco.Core.Configuration.Models; +using Umbraco.Core.Configuration.UmbracoSettings; namespace Umbraco.Tests.Common.Builders { public class RequestHandlerSettingsBuilder : BuilderBase { private bool? _addTrailingSlash; + private bool? _convertUrlsToAscii; + private IEnumerable _charCollection; public RequestHandlerSettingsBuilder WithAddTrailingSlash(bool addTrailingSlash) { @@ -12,13 +16,30 @@ namespace Umbraco.Tests.Common.Builders return this; } + public RequestHandlerSettingsBuilder WithConvertUrlsToAscii(bool convertUrlsToAscii) + { + _convertUrlsToAscii = convertUrlsToAscii; + return this; + } + + public RequestHandlerSettingsBuilder WithCharCollection(IEnumerable charCollection) + { + _charCollection = charCollection; + return this; + } + + public override RequestHandlerSettings Build() { var addTrailingSlash = _addTrailingSlash ?? false; + var convertUrlsToAscii = _convertUrlsToAscii ?? false; + var charCollection = _charCollection ?? RequestHandlerSettings.DefaultCharCollection; return new RequestHandlerSettings { - AddTrailingSlash = addTrailingSlash, + AddTrailingSlash = addTrailingSlash, + ConvertUrlsToAscii = convertUrlsToAscii, + CharCollection = charCollection, }; } } diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Tests.Common/Builders/RequestHandlerSettingsBuilderTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Tests.Common/Builders/RequestHandlerSettingsBuilderTests.cs index a6dd7f98a4..af6bc0ed6f 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Tests.Common/Builders/RequestHandlerSettingsBuilderTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Tests.Common/Builders/RequestHandlerSettingsBuilderTests.cs @@ -1,5 +1,9 @@ -using NUnit.Framework; +using System.Collections.Generic; +using System.Linq; +using NUnit.Framework; +using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Tests.Common.Builders; +using static Umbraco.Core.Configuration.Models.RequestHandlerSettings; namespace Umbraco.Tests.UnitTests.Umbraco.Tests.Common.Builders { @@ -11,16 +15,21 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Tests.Common.Builders { // Arrange const bool addTrailingSlash = true; + const bool convertUrlsToAscii = true; + var charCollection = new List { new CharItem { Char = "a", Replacement = "b" } }; var builder = new RequestHandlerSettingsBuilder(); // Act var requestHandlerSettings = builder .WithAddTrailingSlash(addTrailingSlash) + .WithConvertUrlsToAscii(convertUrlsToAscii) .Build(); // Assert Assert.AreEqual(addTrailingSlash, requestHandlerSettings.AddTrailingSlash); + Assert.AreEqual(convertUrlsToAscii, requestHandlerSettings.ConvertUrlsToAscii); + Assert.AreEqual("a-b", string.Join(",", requestHandlerSettings.CharCollection.Select(x => $"{x.Char}-{x.Replacement}"))); } } } diff --git a/src/Umbraco.Tests/Components/ComponentTests.cs b/src/Umbraco.Tests/Components/ComponentTests.cs index a20b220940..6f86108edb 100644 --- a/src/Umbraco.Tests/Components/ComponentTests.cs +++ b/src/Umbraco.Tests/Components/ComponentTests.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using Microsoft.Extensions.Options; using Moq; using NUnit.Framework; using Umbraco.Core; @@ -13,6 +14,7 @@ using Umbraco.Core.Logging; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.Mappers; using Umbraco.Core.Scoping; +using Umbraco.Tests.Common.Builders; using Umbraco.Tests.TestHelpers; namespace Umbraco.Tests.Components @@ -33,9 +35,11 @@ namespace Umbraco.Tests.Components var logger = Mock.Of(); var typeFinder = TestHelper.GetTypeFinder(); - var f = new UmbracoDatabaseFactory(logger, SettingsForTests.DefaultGlobalSettings, Mock.Of(), new Lazy(() => new MapperCollection(Enumerable.Empty())), TestHelper.DbProviderFactoryCreator); - var fs = new FileSystems(mock.Object, logger, TestHelper.IOHelper, SettingsForTests.GenerateMockGlobalSettings(), TestHelper.GetHostingEnvironment()); - var coreDebug = Mock.Of(); + var globalSettings = new GlobalSettingsBuilder().Build(); + var connectionStrings = new ConnectionStringsBuilder().Build(); + var f = new UmbracoDatabaseFactory(logger, globalSettings, connectionStrings, new Lazy(() => new MapperCollection(Enumerable.Empty())), TestHelper.DbProviderFactoryCreator); + var fs = new FileSystems(mock.Object, logger, TestHelper.IOHelper, Options.Create(globalSettings), TestHelper.GetHostingEnvironment()); + var coreDebug = new CoreDebugSettingsBuilder().Build(); var mediaFileSystem = Mock.Of(); var p = new ScopeProvider(f, fs, coreDebug, mediaFileSystem, logger, typeFinder, NoAppCache.Instance); @@ -71,7 +75,7 @@ namespace Umbraco.Tests.Components { var register = MockRegister(); var typeLoader = MockTypeLoader(); - var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Unknown), TestHelper.GetConfigs(), TestHelper.IOHelper, AppCaches.NoCache); + var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Unknown), TestHelper.IOHelper, AppCaches.NoCache); var types = TypeArray(); var composers = new Composers(composition, types, Enumerable.Empty(), Mock.Of()); @@ -110,7 +114,7 @@ namespace Umbraco.Tests.Components public void Boot1B() { var register = MockRegister(); - var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Run), TestHelper.GetConfigs(), TestHelper.IOHelper, AppCaches.NoCache); + var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Run), TestHelper.IOHelper, AppCaches.NoCache); var types = TypeArray(); var composers = new Composers(composition, types, Enumerable.Empty(), Mock.Of()); @@ -126,7 +130,7 @@ namespace Umbraco.Tests.Components public void Boot2() { var register = MockRegister(); - var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Unknown), TestHelper.GetConfigs(), TestHelper.IOHelper, AppCaches.NoCache); + var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Unknown), TestHelper.IOHelper, AppCaches.NoCache); var types = TypeArray(); var composers = new Composers(composition, types, Enumerable.Empty(), Mock.Of()); @@ -141,7 +145,7 @@ namespace Umbraco.Tests.Components public void Boot3() { var register = MockRegister(); - var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Unknown), TestHelper.GetConfigs(), TestHelper.IOHelper, AppCaches.NoCache); + var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Unknown), TestHelper.IOHelper, AppCaches.NoCache); var types = TypeArray(); var composers = new Composers(composition, types, Enumerable.Empty(), Mock.Of()); @@ -158,7 +162,7 @@ namespace Umbraco.Tests.Components public void BrokenRequire() { var register = MockRegister(); - var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Unknown), TestHelper.GetConfigs(), TestHelper.IOHelper, AppCaches.NoCache); + var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Unknown), TestHelper.IOHelper, AppCaches.NoCache); var types = TypeArray(); var composers = new Composers(composition, types, Enumerable.Empty(), Mock.Of()); @@ -181,7 +185,7 @@ namespace Umbraco.Tests.Components public void BrokenRequired() { var register = MockRegister(); - var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Unknown), TestHelper.GetConfigs(), TestHelper.IOHelper, AppCaches.NoCache); + var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Unknown), TestHelper.IOHelper, AppCaches.NoCache); var types = TypeArray(); var composers = new Composers(composition, types, Enumerable.Empty(), Mock.Of()); @@ -217,7 +221,7 @@ namespace Umbraco.Tests.Components throw new NotSupportedException(type.FullName); }); }); - var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Unknown), TestHelper.GetConfigs(), TestHelper.IOHelper, AppCaches.NoCache); + var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Unknown), TestHelper.IOHelper, AppCaches.NoCache); var types = new[] { typeof(Composer1), typeof(Composer5), typeof(Composer5a) }; var composers = new Composers(composition, types, Enumerable.Empty(), Mock.Of()); @@ -243,7 +247,7 @@ namespace Umbraco.Tests.Components public void Requires1() { var register = MockRegister(); - var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Unknown), TestHelper.GetConfigs(), TestHelper.IOHelper, AppCaches.NoCache); + var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Unknown), TestHelper.IOHelper, AppCaches.NoCache); var types = new[] { typeof(Composer6), typeof(Composer7), typeof(Composer8) }; var composers = new Composers(composition, types, Enumerable.Empty(), Mock.Of()); @@ -258,7 +262,7 @@ namespace Umbraco.Tests.Components public void Requires2A() { var register = MockRegister(); - var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Unknown), Configs, TestHelper.IOHelper, AppCaches.NoCache); + var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Unknown), TestHelper.IOHelper, AppCaches.NoCache); var types = new[] { typeof(Composer9), typeof(Composer2), typeof(Composer4) }; var composers = new Composers(composition, types, Enumerable.Empty(), Mock.Of()); @@ -276,7 +280,7 @@ namespace Umbraco.Tests.Components var register = MockRegister(); var typeLoader = MockTypeLoader(); var factory = MockFactory(); - var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Run), Configs, TestHelper.IOHelper, AppCaches.NoCache); + var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Run), TestHelper.IOHelper, AppCaches.NoCache); var types = new[] { typeof(Composer9), typeof(Composer2), typeof(Composer4) }; var composers = new Composers(composition, types, Enumerable.Empty(), Mock.Of()); @@ -295,7 +299,7 @@ namespace Umbraco.Tests.Components public void WeakDependencies() { var register = MockRegister(); - var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Unknown), Configs, TestHelper.IOHelper, AppCaches.NoCache); + var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Unknown), TestHelper.IOHelper, AppCaches.NoCache); var types = new[] { typeof(Composer10) }; var composers = new Composers(composition, types, Enumerable.Empty(), Mock.Of()); @@ -334,7 +338,7 @@ namespace Umbraco.Tests.Components public void DisableMissing() { var register = MockRegister(); - var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Unknown), Configs, TestHelper.IOHelper, AppCaches.NoCache); + var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Unknown), TestHelper.IOHelper, AppCaches.NoCache); var types = new[] { typeof(Composer6), typeof(Composer8) }; // 8 disables 7 which is not in the list var composers = new Composers(composition, types, Enumerable.Empty(), Mock.Of()); @@ -349,7 +353,7 @@ namespace Umbraco.Tests.Components public void AttributesPriorities() { var register = MockRegister(); - var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Unknown), Configs, TestHelper.IOHelper, AppCaches.NoCache); + var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Unknown), TestHelper.IOHelper, AppCaches.NoCache); var types = new[] { typeof(Composer26) }; var enableDisableAttributes = new[] { new DisableComposerAttribute(typeof(Composer26)) }; @@ -376,7 +380,7 @@ namespace Umbraco.Tests.Components var register = MockRegister(); var composition = new Composition(register, typeLoader, Mock.Of(), - MockRuntimeState(RuntimeLevel.Run), Configs, TestHelper.IOHelper, AppCaches.NoCache); + MockRuntimeState(RuntimeLevel.Run), TestHelper.IOHelper, AppCaches.NoCache); var allComposers = typeLoader.GetTypes().ToList(); var types = allComposers.Where(x => x.FullName.StartsWith("Umbraco.Core.") || x.FullName.StartsWith("Umbraco.Web")).ToList(); diff --git a/src/Umbraco.Tests/Composing/CollectionBuildersTests.cs b/src/Umbraco.Tests/Composing/CollectionBuildersTests.cs index 2d977e89c7..4416723a55 100644 --- a/src/Umbraco.Tests/Composing/CollectionBuildersTests.cs +++ b/src/Umbraco.Tests/Composing/CollectionBuildersTests.cs @@ -24,7 +24,7 @@ namespace Umbraco.Tests.Composing Current.Reset(); var register = TestHelper.GetRegister(); - _composition = new Composition(register, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.GetConfigs(), TestHelper.IOHelper, AppCaches.NoCache); + _composition = new Composition(register, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.IOHelper, AppCaches.NoCache); } [TearDown] diff --git a/src/Umbraco.Tests/Composing/CompositionTests.cs b/src/Umbraco.Tests/Composing/CompositionTests.cs index 380511eaaa..229ba1102b 100644 --- a/src/Umbraco.Tests/Composing/CompositionTests.cs +++ b/src/Umbraco.Tests/Composing/CompositionTests.cs @@ -41,7 +41,7 @@ namespace Umbraco.Tests.Composing var typeFinder = TestHelper.GetTypeFinder(); var ioHelper = TestHelper.IOHelper; var typeLoader = new TypeLoader(typeFinder, Mock.Of(), new DirectoryInfo(ioHelper.MapPath("~/App_Data/TEMP")), logger); - var composition = new Composition(mockedRegister, typeLoader, logger, Mock.Of(), TestHelper.GetConfigs(), TestHelper.IOHelper, AppCaches.NoCache); + var composition = new Composition(mockedRegister, typeLoader, logger, Mock.Of(), TestHelper.IOHelper, AppCaches.NoCache); // create the factory, ensure it is the mocked factory var factory = composition.CreateFactory(); diff --git a/src/Umbraco.Tests/Composing/LazyCollectionBuilderTests.cs b/src/Umbraco.Tests/Composing/LazyCollectionBuilderTests.cs index 4d0135d6c4..c17e80a34a 100644 --- a/src/Umbraco.Tests/Composing/LazyCollectionBuilderTests.cs +++ b/src/Umbraco.Tests/Composing/LazyCollectionBuilderTests.cs @@ -41,7 +41,7 @@ namespace Umbraco.Tests.Composing public void LazyCollectionBuilderHandlesTypes() { var container = CreateRegister(); - var composition = new Composition(container, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.GetConfigs(), TestHelper.IOHelper, AppCaches.NoCache); + var composition = new Composition(container, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.IOHelper, AppCaches.NoCache); composition.WithCollectionBuilder() .Add() @@ -67,7 +67,7 @@ namespace Umbraco.Tests.Composing public void LazyCollectionBuilderHandlesProducers() { var container = CreateRegister(); - var composition = new Composition(container, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.GetConfigs(), TestHelper.IOHelper, AppCaches.NoCache); + var composition = new Composition(container, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.IOHelper, AppCaches.NoCache); composition.WithCollectionBuilder() .Add(() => new[] { typeof(TransientObject3), typeof(TransientObject2) }) @@ -92,7 +92,7 @@ namespace Umbraco.Tests.Composing public void LazyCollectionBuilderHandlesTypesAndProducers() { var container = CreateRegister(); - var composition = new Composition(container, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.GetConfigs(), TestHelper.IOHelper, AppCaches.NoCache); + var composition = new Composition(container, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.IOHelper, AppCaches.NoCache); composition.WithCollectionBuilder() .Add() @@ -118,7 +118,7 @@ namespace Umbraco.Tests.Composing public void LazyCollectionBuilderThrowsOnIllegalTypes() { var container = CreateRegister(); - var composition = new Composition(container, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.GetConfigs(), TestHelper.IOHelper, AppCaches.NoCache); + var composition = new Composition(container, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.IOHelper, AppCaches.NoCache); composition.WithCollectionBuilder() .Add() @@ -140,7 +140,7 @@ namespace Umbraco.Tests.Composing public void LazyCollectionBuilderCanExcludeTypes() { var container = CreateRegister(); - var composition = new Composition(container, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.GetConfigs(), TestHelper.IOHelper, AppCaches.NoCache); + var composition = new Composition(container, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.IOHelper, AppCaches.NoCache); composition.WithCollectionBuilder() .Add() diff --git a/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs b/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs index 390997173b..118eaab41a 100644 --- a/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs +++ b/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs @@ -22,7 +22,7 @@ namespace Umbraco.Tests.Composing { var container = TestHelper.GetRegister(); - var composition = new Composition(container, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.GetConfigs(), TestHelper.IOHelper, AppCaches.NoCache); + var composition = new Composition(container, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.IOHelper, AppCaches.NoCache); var expectedPackageActions = TypeLoader.GetPackageActions(); composition.WithCollectionBuilder() diff --git a/src/Umbraco.Tests/Configurations/GlobalSettingsTests.cs b/src/Umbraco.Tests/Configurations/GlobalSettingsTests.cs index 56237f562c..fa6949cd09 100644 --- a/src/Umbraco.Tests/Configurations/GlobalSettingsTests.cs +++ b/src/Umbraco.Tests/Configurations/GlobalSettingsTests.cs @@ -2,7 +2,9 @@ using NUnit.Framework; using Umbraco.Core.Configuration; using Umbraco.Core.IO; +using Umbraco.Tests.Common.Builders; using Umbraco.Tests.TestHelpers; +using Umbraco.Web.Configuration; using Umbraco.Web.Hosting; namespace Umbraco.Tests.Configurations @@ -18,17 +20,14 @@ namespace Umbraco.Tests.Configurations [TestCase("~/some-wacky/nestedPath", "/MyVirtualDir/NestedVDir/", "some-wacky-nestedpath")] public void Umbraco_Mvc_Area(string path, string rootPath, string outcome) { - - var globalSettings = SettingsForTests.GenerateMockGlobalSettings(); var mockHostingSettings = Mock.Get(SettingsForTests.GenerateMockHostingSettings()); mockHostingSettings.Setup(x => x.ApplicationVirtualPath).Returns(rootPath); var hostingEnvironment = new AspNetHostingEnvironment(mockHostingSettings.Object); - var globalSettingsMock = Mock.Get(globalSettings); - globalSettingsMock.Setup(x => x.UmbracoPath).Returns(() => path); + var globalSettings = new GlobalSettingsBuilder().WithUmbracoPath(path).Build(); - Assert.AreEqual(outcome, globalSettingsMock.Object.GetUmbracoMvcAreaNoCache(hostingEnvironment)); + Assert.AreEqual(outcome, globalSettings.GetUmbracoMvcAreaNoCache(hostingEnvironment)); } } } diff --git a/src/Umbraco.Tests/CoreThings/TryConvertToTests.cs b/src/Umbraco.Tests/CoreThings/TryConvertToTests.cs index fbb89b1c5d..cd26bf914f 100644 --- a/src/Umbraco.Tests/CoreThings/TryConvertToTests.cs +++ b/src/Umbraco.Tests/CoreThings/TryConvertToTests.cs @@ -1,6 +1,8 @@ using System; +using Microsoft.Extensions.Options; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Strings; using Umbraco.Tests.Testing; @@ -14,7 +16,7 @@ namespace Umbraco.Tests.CoreThings { base.Compose(); - Composition.RegisterUnique(f => new DefaultShortStringHelper(f.GetInstance())); + Composition.RegisterUnique(f => new DefaultShortStringHelper(f.GetInstance>())); } [Test] diff --git a/src/Umbraco.Tests/IO/FileSystemsTests.cs b/src/Umbraco.Tests/IO/FileSystemsTests.cs index c1d3fbb331..71dd954052 100644 --- a/src/Umbraco.Tests/IO/FileSystemsTests.cs +++ b/src/Umbraco.Tests/IO/FileSystemsTests.cs @@ -30,7 +30,7 @@ namespace Umbraco.Tests.IO { _register = TestHelper.GetRegister(); - var composition = new Composition(_register, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.GetConfigs(), TestHelper.IOHelper, AppCaches.NoCache); + var composition = new Composition(_register, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.IOHelper, AppCaches.NoCache); composition.Register(_ => Mock.Of()); composition.Register(_ => Mock.Of()); diff --git a/src/Umbraco.Tests/IO/ShadowFileSystemTests.cs b/src/Umbraco.Tests/IO/ShadowFileSystemTests.cs index 07a04479a4..50ba5a3223 100644 --- a/src/Umbraco.Tests/IO/ShadowFileSystemTests.cs +++ b/src/Umbraco.Tests/IO/ShadowFileSystemTests.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; +using Microsoft.Extensions.Options; using Moq; using NUnit.Framework; using Umbraco.Core; @@ -10,6 +11,7 @@ using Umbraco.Core.Composing; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Scoping; +using Umbraco.Tests.Common.Builders; using Umbraco.Tests.TestHelpers; namespace Umbraco.Tests.IO @@ -436,7 +438,8 @@ namespace Umbraco.Tests.IO var phy = new PhysicalFileSystem(ioHelper, hostingEnvironment, logger, path, "ignore"); var container = Mock.Of(); - var fileSystems = new FileSystems(container, logger, ioHelper, SettingsForTests.GenerateMockGlobalSettings(), TestHelper.GetHostingEnvironment()) { IsScoped = () => scopedFileSystems }; + var globalSettings = Options.Create(new GlobalSettingsBuilder().Build()); + var fileSystems = new FileSystems(container, logger, ioHelper, globalSettings, TestHelper.GetHostingEnvironment()) { IsScoped = () => scopedFileSystems }; var fs = fileSystems.GetFileSystem(phy); var sw = (ShadowWrapper) fs.InnerFileSystem; @@ -532,7 +535,8 @@ namespace Umbraco.Tests.IO var phy = new PhysicalFileSystem(ioHelper, hostingEnvironment, logger, path, "ignore"); var container = Mock.Of(); - var fileSystems = new FileSystems(container, logger, ioHelper, SettingsForTests.GenerateMockGlobalSettings(), TestHelper.GetHostingEnvironment()) { IsScoped = () => scopedFileSystems }; + var globalSettings = Options.Create(new GlobalSettingsBuilder().Build()); + var fileSystems = new FileSystems(container, logger, ioHelper, globalSettings, TestHelper.GetHostingEnvironment()) { IsScoped = () => scopedFileSystems }; var fs = fileSystems.GetFileSystem( phy); var sw = (ShadowWrapper) fs.InnerFileSystem; @@ -587,7 +591,8 @@ namespace Umbraco.Tests.IO var phy = new PhysicalFileSystem(ioHelper, hostingEnvironment, logger, path, "ignore"); var container = Mock.Of(); - var fileSystems = new FileSystems(container, logger, ioHelper, SettingsForTests.GenerateMockGlobalSettings(), TestHelper.GetHostingEnvironment()) { IsScoped = () => scopedFileSystems }; + var globalSettings = Options.Create(new GlobalSettingsBuilder().Build()); + var fileSystems = new FileSystems(container, logger, ioHelper, globalSettings, TestHelper.GetHostingEnvironment()) { IsScoped = () => scopedFileSystems }; var fs = fileSystems.GetFileSystem( phy); var sw = (ShadowWrapper)fs.InnerFileSystem; diff --git a/src/Umbraco.Tests/Migrations/AdvancedMigrationTests.cs b/src/Umbraco.Tests/Migrations/AdvancedMigrationTests.cs index 966c4109c6..dd5fd32971 100644 --- a/src/Umbraco.Tests/Migrations/AdvancedMigrationTests.cs +++ b/src/Umbraco.Tests/Migrations/AdvancedMigrationTests.cs @@ -9,8 +9,10 @@ using Umbraco.Core.Migrations.Upgrade; using Umbraco.Core.Persistence.DatabaseModelDefinitions; using Umbraco.Core.Persistence.Dtos; using Umbraco.Core.Services; +using Umbraco.Tests.Common.Builders; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.Testing; +using Umbraco.Web.Configuration; namespace Umbraco.Tests.Migrations { @@ -42,7 +44,8 @@ namespace Umbraco.Tests.Migrations upgrader.Execute(ScopeProvider, builder, Mock.Of(), logger); - var helper = new DatabaseSchemaCreator(scope.Database, logger, UmbracoVersion, TestObjects.GetGlobalSettings()); + var globalSettings = new GlobalSettingsBuilder().Build(); + var helper = new DatabaseSchemaCreator(scope.Database, logger, UmbracoVersion, globalSettings); var exists = helper.TableExists("umbracoUser"); Assert.IsTrue(exists); diff --git a/src/Umbraco.Tests/Migrations/MigrationPlanTests.cs b/src/Umbraco.Tests/Migrations/MigrationPlanTests.cs index a9785697f4..273255f987 100644 --- a/src/Umbraco.Tests/Migrations/MigrationPlanTests.cs +++ b/src/Umbraco.Tests/Migrations/MigrationPlanTests.cs @@ -13,8 +13,10 @@ using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.Scoping; using Umbraco.Core.Services; using Umbraco.Persistance.SqlCe; +using Umbraco.Tests.Common.Builders; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.Testing; +using Umbraco.Web.Configuration; namespace Umbraco.Tests.Migrations { @@ -139,7 +141,8 @@ namespace Umbraco.Tests.Migrations [Test] public void ValidateUmbracoPlan() { - var plan = new UmbracoPlan(TestHelper.GetUmbracoVersion(), SettingsForTests.GenerateMockGlobalSettings()); + var globalSettings = new GlobalSettingsBuilder().Build(); + var plan = new UmbracoPlan(TestHelper.GetUmbracoVersion(), globalSettings); plan.Validate(); Console.WriteLine(plan.FinalState); Assert.IsFalse(plan.FinalState.IsNullOrWhiteSpace()); diff --git a/src/Umbraco.Tests/Models/MediaXmlTest.cs b/src/Umbraco.Tests/Models/MediaXmlTest.cs index 632f433c5b..b40e56c252 100644 --- a/src/Umbraco.Tests/Models/MediaXmlTest.cs +++ b/src/Umbraco.Tests/Models/MediaXmlTest.cs @@ -8,6 +8,7 @@ using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Services; using Umbraco.Core.Strings; +using Umbraco.Tests.Common.Builders; using Umbraco.Tests.Strings; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.TestHelpers.Entities; @@ -31,10 +32,10 @@ namespace Umbraco.Tests.Models // and then, this will reset the width, height... because the file does not exist, of course ;-( var logger = Mock.Of(); var scheme = Mock.Of(); - var config = Mock.Of(); + var contentSettings = new ContentSettingsBuilder().Build(); var mediaFileSystem = new MediaFileSystem(Mock.Of(), scheme, logger, ShortStringHelper); - var ignored = new FileUploadPropertyEditor(Mock.Of(), mediaFileSystem, config, DataTypeService, LocalizationService, LocalizedTextService, ShortStringHelper); + var ignored = new FileUploadPropertyEditor(Mock.Of(), mediaFileSystem, contentSettings, DataTypeService, LocalizationService, LocalizedTextService, ShortStringHelper); var media = MockedMedia.CreateMediaImage(mediaType, -1); media.WriterId = -1; // else it's zero and that's not a user and it breaks the tests diff --git a/src/Umbraco.Tests/ModelsBuilder/BuilderTests.cs b/src/Umbraco.Tests/ModelsBuilder/BuilderTests.cs index 6065570b13..91bf7406f3 100644 --- a/src/Umbraco.Tests/ModelsBuilder/BuilderTests.cs +++ b/src/Umbraco.Tests/ModelsBuilder/BuilderTests.cs @@ -8,6 +8,7 @@ using Umbraco.Core.Configuration; using Umbraco.Core.Models.PublishedContent; using Umbraco.ModelsBuilder.Embedded; using Umbraco.ModelsBuilder.Embedded.Building; +using Umbraco.Tests.Common.Builders; namespace Umbraco.Tests.ModelsBuilder { @@ -42,7 +43,8 @@ namespace Umbraco.Tests.ModelsBuilder { }; - var builder = new TextBuilder(Mock.Of(), types); + var modelsBuilderConfig = new ModelsBuilderConfigBuilder().Build(); + var builder = new TextBuilder(modelsBuilderConfig, types); var btypes = builder.TypeModels; var sb = new StringBuilder(); @@ -150,7 +152,8 @@ namespace Umbraco.Web.PublishedModels " } }; - var builder = new TextBuilder(Mock.Of(), types); + var modelsBuilderConfig = new ModelsBuilderConfigBuilder().Build(); + var builder = new TextBuilder(modelsBuilderConfig, types); var btypes = builder.TypeModels; builder.ModelsNamespace = "Umbraco.Web.PublishedModels"; @@ -259,7 +262,8 @@ namespace Umbraco.Web.PublishedModels { }; - var builder = new TextBuilder(Mock.Of(), types); + var modelsBuilderConfig = new ModelsBuilderConfigBuilder().Build(); + var builder = new TextBuilder(modelsBuilderConfig, types); builder.ModelsNamespace = "Umbraco.ModelsBuilder.Models"; // forces conflict with Umbraco.ModelsBuilder.Umbraco var btypes = builder.TypeModels; diff --git a/src/Umbraco.Tests/Packaging/CreatedPackagesRepositoryTests.cs b/src/Umbraco.Tests/Packaging/CreatedPackagesRepositoryTests.cs index 6533dd6113..90a352ad39 100644 --- a/src/Umbraco.Tests/Packaging/CreatedPackagesRepositoryTests.cs +++ b/src/Umbraco.Tests/Packaging/CreatedPackagesRepositoryTests.cs @@ -6,13 +6,10 @@ using System.Linq; using System.Xml.Linq; using NUnit.Framework; using Umbraco.Core; -using Umbraco.Core.Composing; -using Umbraco.Core.Configuration; -using Umbraco.Core.IO; using Umbraco.Core.Models.Packaging; using Umbraco.Core.Packaging; using Umbraco.Core.Services; -using Umbraco.Tests.Services; +using Umbraco.Tests.Common.Builders; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.Testing; @@ -44,7 +41,7 @@ namespace Umbraco.Tests.Packaging HostingEnvironment, Factory.GetInstance(), Logger, UmbracoVersion, - Factory.GetInstance(), + Microsoft.Extensions.Options.Options.Create(new GlobalSettingsBuilder().Build()), "createdPackages.config", //temp paths tempFolderPath: "~/" + _testBaseFolder + "/temp", diff --git a/src/Umbraco.Tests/Packaging/PackageDataInstallationTests.cs b/src/Umbraco.Tests/Packaging/PackageDataInstallationTests.cs index d089c4aaa2..ed1cd5424d 100644 --- a/src/Umbraco.Tests/Packaging/PackageDataInstallationTests.cs +++ b/src/Umbraco.Tests/Packaging/PackageDataInstallationTests.cs @@ -18,6 +18,7 @@ using Umbraco.Tests.Services.Importing; using Umbraco.Tests.Testing; using Umbraco.Core.Composing.CompositionExtensions; using Umbraco.Core.Strings; +using Umbraco.Tests.Common.Builders; namespace Umbraco.Tests.Packaging { @@ -712,8 +713,9 @@ namespace Umbraco.Tests.Packaging private void AddLanguages() { - var norwegian = new Core.Models.Language(TestObjects.GetGlobalSettings(), "nb-NO"); - var english = new Core.Models.Language(TestObjects.GetGlobalSettings(), "en-GB"); + var globalSettings = new GlobalSettingsBuilder().Build(); + var norwegian = new Core.Models.Language(globalSettings, "nb-NO"); + var english = new Core.Models.Language(globalSettings, "en-GB"); ServiceContext.LocalizationService.Save(norwegian, 0); ServiceContext.LocalizationService.Save(english, 0); } diff --git a/src/Umbraco.Tests/Packaging/PackageInstallationTest.cs b/src/Umbraco.Tests/Packaging/PackageInstallationTest.cs index 90db389002..1cfb9167ce 100644 --- a/src/Umbraco.Tests/Packaging/PackageInstallationTest.cs +++ b/src/Umbraco.Tests/Packaging/PackageInstallationTest.cs @@ -16,6 +16,7 @@ using Umbraco.Core.PropertyEditors; using Umbraco.Core.Scoping; using Umbraco.Core.Services; using Umbraco.Core.Strings; +using Umbraco.Tests.Common.Builders; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.Testing; using File = System.IO.File; @@ -55,7 +56,7 @@ namespace Umbraco.Tests.Packaging Factory.GetInstance(), Factory.GetInstance(), Factory.GetInstance(), - Factory.GetInstance(), + new GlobalSettingsBuilder().Build(), Factory.GetInstance() ); diff --git a/src/Umbraco.Tests/Persistence/DatabaseContextTests.cs b/src/Umbraco.Tests/Persistence/DatabaseContextTests.cs index ba9bd19db5..8f4947952f 100644 --- a/src/Umbraco.Tests/Persistence/DatabaseContextTests.cs +++ b/src/Umbraco.Tests/Persistence/DatabaseContextTests.cs @@ -15,6 +15,7 @@ using Umbraco.Core.Persistence.Mappers; using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.Services; using Umbraco.Persistance.SqlCe; +using Umbraco.Tests.Common.Builders; using Umbraco.Tests.TestHelpers; using Umbraco.Web.Security; @@ -38,8 +39,8 @@ namespace Umbraco.Tests.Persistence _sqlSyntaxProviders = new[] { (ISqlSyntaxProvider) _sqlCeSyntaxProvider }; _logger = Mock.Of(); _umbracoVersion = TestHelper.GetUmbracoVersion(); - var globalSettings = TestHelper.GetConfigs().Global(); - var connectionStrings = TestHelper.GetConfigs().ConnectionStrings(); + var globalSettings = new GlobalSettingsBuilder().Build(); + var connectionStrings = new ConnectionStringsBuilder().Build(); _databaseFactory = new UmbracoDatabaseFactory(_logger, globalSettings, connectionStrings, new Lazy(() => Mock.Of()), TestHelper.DbProviderFactoryCreator); } @@ -94,7 +95,7 @@ namespace Umbraco.Tests.Persistence using (var database = _databaseFactory.CreateDatabase()) using (var transaction = database.GetTransaction()) { - schemaHelper = new DatabaseSchemaCreator(database, _logger, _umbracoVersion, SettingsForTests.GenerateMockGlobalSettings()); + schemaHelper = new DatabaseSchemaCreator(database, _logger, _umbracoVersion, new GlobalSettingsBuilder().Build()); schemaHelper.InitializeDatabaseSchema(); transaction.Complete(); } diff --git a/src/Umbraco.Tests/Persistence/Repositories/ContentTypeRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/ContentTypeRepositoryTest.cs index 53a632132d..0d6797bd9c 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/ContentTypeRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/ContentTypeRepositoryTest.cs @@ -1,15 +1,18 @@ using System; using System.Collections.Generic; using System.Linq; +using Microsoft.Extensions.Options; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Cache; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Models; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.Dtos; using Umbraco.Core.Persistence.Repositories.Implement; using Umbraco.Core.PropertyEditors; using Umbraco.Core.Scoping; +using Umbraco.Tests.Common.Builders; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.TestHelpers.Entities; using Umbraco.Tests.Testing; @@ -21,21 +24,25 @@ namespace Umbraco.Tests.Persistence.Repositories [UmbracoTest(Mapper = true, Database = UmbracoTestOptions.Database.NewSchemaPerTest)] public class ContentTypeRepositoryTest : TestWithDatabaseBase { + private IOptions _globalSettings; + public override void SetUp() { base.SetUp(); CreateTestData(); + + _globalSettings = Microsoft.Extensions.Options.Options.Create(new GlobalSettingsBuilder().Build()); } private DocumentRepository CreateRepository(IScopeAccessor scopeAccessor, out ContentTypeRepository contentTypeRepository) { - var langRepository = new LanguageRepository(scopeAccessor, AppCaches.Disabled, Logger,TestObjects.GetGlobalSettings()); + var langRepository = new LanguageRepository(scopeAccessor, AppCaches.Disabled, Logger, _globalSettings); var templateRepository = new TemplateRepository(scopeAccessor, AppCaches.Disabled, Logger, TestObjects.GetFileSystemsMock(), IOHelper, ShortStringHelper); var tagRepository = new TagRepository(scopeAccessor, AppCaches.Disabled, Logger); var commonRepository = new ContentTypeCommonRepository(scopeAccessor, templateRepository, AppCaches.Disabled, ShortStringHelper); contentTypeRepository = new ContentTypeRepository(scopeAccessor, AppCaches.Disabled, Logger, commonRepository, langRepository, ShortStringHelper); - var languageRepository = new LanguageRepository(scopeAccessor, AppCaches.Disabled, Logger, TestObjects.GetGlobalSettings()); + var languageRepository = new LanguageRepository(scopeAccessor, AppCaches.Disabled, Logger, _globalSettings); var relationTypeRepository = new RelationTypeRepository(scopeAccessor, AppCaches.Disabled, Logger); var entityRepository = new EntityRepository(scopeAccessor); var relationRepository = new RelationRepository(scopeAccessor, Logger, relationTypeRepository, entityRepository); @@ -47,7 +54,7 @@ namespace Umbraco.Tests.Persistence.Repositories private ContentTypeRepository CreateRepository(IScopeAccessor scopeAccessor) { - var langRepository = new LanguageRepository(scopeAccessor, AppCaches.Disabled, Logger, TestObjects.GetGlobalSettings()); + var langRepository = new LanguageRepository(scopeAccessor, AppCaches.Disabled, Logger, _globalSettings); var templateRepository = new TemplateRepository(scopeAccessor, AppCaches.Disabled, Logger, TestObjects.GetFileSystemsMock(), IOHelper, ShortStringHelper); var commonRepository = new ContentTypeCommonRepository(scopeAccessor, templateRepository, AppCaches.Disabled, ShortStringHelper); var contentTypeRepository = new ContentTypeRepository(scopeAccessor, AppCaches.Disabled, Logger, commonRepository, langRepository, ShortStringHelper); @@ -58,7 +65,7 @@ namespace Umbraco.Tests.Persistence.Repositories { var templateRepository = new TemplateRepository(scopeAccessor, AppCaches.Disabled, Logger, TestObjects.GetFileSystemsMock(), IOHelper, ShortStringHelper); var commonRepository = new ContentTypeCommonRepository(scopeAccessor, templateRepository, AppCaches.Disabled, ShortStringHelper); - var langRepository = new LanguageRepository(scopeAccessor, AppCaches.Disabled, Logger, TestObjects.GetGlobalSettings()); + var langRepository = new LanguageRepository(scopeAccessor, AppCaches.Disabled, Logger, _globalSettings); var contentTypeRepository = new MediaTypeRepository(scopeAccessor, AppCaches.Disabled, Logger, commonRepository, langRepository, ShortStringHelper); return contentTypeRepository; } diff --git a/src/Umbraco.Tests/Persistence/Repositories/DictionaryRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/DictionaryRepositoryTest.cs index e23734acc3..fb9a4d2772 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/DictionaryRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/DictionaryRepositoryTest.cs @@ -8,6 +8,7 @@ using Umbraco.Tests.TestHelpers; using Umbraco.Tests.Testing; using Umbraco.Core; using Umbraco.Core.Composing; +using Umbraco.Tests.Common.Builders; namespace Umbraco.Tests.Persistence.Repositories { @@ -288,7 +289,8 @@ namespace Umbraco.Tests.Persistence.Repositories { var repository = CreateRepository(); - var languageNo = new Language(TestObjects.GetGlobalSettings(), "nb-NO") { CultureName = "nb-NO" }; + var globalSettings = new GlobalSettingsBuilder().Build(); + var languageNo = new Language(globalSettings, "nb-NO") { CultureName = "nb-NO" }; ServiceContext.LocalizationService.Save(languageNo); // Act @@ -373,7 +375,8 @@ namespace Umbraco.Tests.Persistence.Repositories { var language = ServiceContext.LocalizationService.GetLanguageByIsoCode("en-US"); - var languageDK = new Language(TestObjects.GetGlobalSettings(), "da-DK") { CultureName = "da-DK" }; + var globalSettings = new GlobalSettingsBuilder().Build(); + var languageDK = new Language(globalSettings, "da-DK") { CultureName = "da-DK" }; ServiceContext.LocalizationService.Save(languageDK);//Id 2 var readMore = new DictionaryItem("Read More"); diff --git a/src/Umbraco.Tests/Persistence/Repositories/DocumentRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/DocumentRepositoryTest.cs index fe59e431ec..03cfe1af53 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/DocumentRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/DocumentRepositoryTest.cs @@ -20,6 +20,7 @@ using Umbraco.Core.Scoping; using Umbraco.Core.Services; using Umbraco.Tests.Testing; using Umbraco.Web.PropertyEditors; +using Umbraco.Tests.Common.Builders; namespace Umbraco.Tests.Persistence.Repositories { @@ -62,12 +63,14 @@ namespace Umbraco.Tests.Persistence.Repositories private DocumentRepository CreateRepository(IScopeAccessor scopeAccessor, out ContentTypeRepository contentTypeRepository, out TemplateRepository templateRepository, AppCaches appCaches = null) { + var globalSettings = Microsoft.Extensions.Options.Options.Create(new GlobalSettingsBuilder().Build()); + appCaches = appCaches ?? AppCaches; templateRepository = new TemplateRepository(scopeAccessor, appCaches, Logger, TestObjects.GetFileSystemsMock(), IOHelper, ShortStringHelper); var tagRepository = new TagRepository(scopeAccessor, appCaches, Logger); var commonRepository = new ContentTypeCommonRepository(scopeAccessor, templateRepository, appCaches, ShortStringHelper); - var languageRepository = new LanguageRepository(scopeAccessor, appCaches, Logger, TestObjects.GetGlobalSettings()); + var languageRepository = new LanguageRepository(scopeAccessor, appCaches, Logger, globalSettings); contentTypeRepository = new ContentTypeRepository(scopeAccessor, appCaches, Logger, commonRepository, languageRepository, ShortStringHelper); var relationTypeRepository = new RelationTypeRepository(scopeAccessor, AppCaches.Disabled, Logger); var entityRepository = new EntityRepository(scopeAccessor); diff --git a/src/Umbraco.Tests/Persistence/Repositories/DomainRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/DomainRepositoryTest.cs index 91d129aeeb..c3bf9db5de 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/DomainRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/DomainRepositoryTest.cs @@ -9,6 +9,7 @@ using Umbraco.Core.Models; using Umbraco.Core.Persistence.Repositories.Implement; using Umbraco.Core.PropertyEditors; using Umbraco.Core.Scoping; +using Umbraco.Tests.Common.Builders; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.TestHelpers.Entities; using Umbraco.Tests.Testing; @@ -21,11 +22,13 @@ namespace Umbraco.Tests.Persistence.Repositories { private DomainRepository CreateRepository(IScopeProvider provider, out ContentTypeRepository contentTypeRepository, out DocumentRepository documentRepository, out LanguageRepository languageRepository) { + var globalSettings = Microsoft.Extensions.Options.Options.Create(new GlobalSettingsBuilder().Build()); + var accessor = (IScopeAccessor) provider; var templateRepository = new TemplateRepository(accessor, Core.Cache.AppCaches.Disabled, Logger, TestObjects.GetFileSystemsMock(), IOHelper, ShortStringHelper); var tagRepository = new TagRepository(accessor, Core.Cache.AppCaches.Disabled, Logger); var commonRepository = new ContentTypeCommonRepository(accessor, templateRepository, AppCaches, ShortStringHelper); - languageRepository = new LanguageRepository(accessor, Core.Cache.AppCaches.Disabled, Logger, TestObjects.GetGlobalSettings()); + languageRepository = new LanguageRepository(accessor, Core.Cache.AppCaches.Disabled, Logger, globalSettings); contentTypeRepository = new ContentTypeRepository(accessor, Core.Cache.AppCaches.Disabled, Logger, commonRepository, languageRepository, ShortStringHelper); var relationTypeRepository = new RelationTypeRepository(accessor, Core.Cache.AppCaches.Disabled, Logger); var entityRepository = new EntityRepository(accessor); @@ -48,7 +51,8 @@ namespace Umbraco.Tests.Persistence.Repositories var repo = CreateRepository(provider, out contentTypeRepo, out documentRepo, out langRepo); - var lang = new Language(TestObjects.GetGlobalSettings(), isoName); + var globalSettings = new GlobalSettingsBuilder().Build(); + var lang = new Language(globalSettings, isoName); langRepo.Save(lang); ct = MockedContentTypes.CreateBasicContentType("test", "Test"); @@ -203,7 +207,8 @@ namespace Umbraco.Tests.Persistence.Repositories //more test data var lang1 = langRepo.GetByIsoCode("en-AU"); - var lang2 = new Language(TestObjects.GetGlobalSettings(), "es"); + var globalSettings = new GlobalSettingsBuilder().Build(); + var lang2 = new Language(globalSettings, "es"); langRepo.Save(lang2); var content2 = new Content("test", -1, ct) { CreatorId = 0, WriterId = 0 }; documentRepo.Save(content2); diff --git a/src/Umbraco.Tests/Persistence/Repositories/LanguageRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/LanguageRepositoryTest.cs index b1dbe7b6e0..dae0200550 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/LanguageRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/LanguageRepositoryTest.cs @@ -4,12 +4,13 @@ using System.Linq; using Moq; using NUnit.Framework; using Umbraco.Core.Cache; -using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.Repositories.Implement; using Umbraco.Core.Scoping; +using Umbraco.Tests.Common.Builders; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.Testing; @@ -19,16 +20,20 @@ namespace Umbraco.Tests.Persistence.Repositories [UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest)] public class LanguageRepositoryTest : TestWithDatabaseBase { + private GlobalSettings _globalSettings; + public override void SetUp() { base.SetUp(); CreateTestData(); + + _globalSettings = new GlobalSettingsBuilder().Build(); } private LanguageRepository CreateRepository(IScopeProvider provider) { - return new LanguageRepository((IScopeAccessor) provider, AppCaches.Disabled, Mock.Of(), TestObjects.GetGlobalSettings()); + return new LanguageRepository((IScopeAccessor) provider, AppCaches.Disabled, Mock.Of(), Microsoft.Extensions.Options.Options.Create(_globalSettings)); } [Test] @@ -62,7 +67,7 @@ namespace Umbraco.Tests.Persistence.Repositories var repository = CreateRepository(provider); var au = CultureInfo.GetCultureInfo("en-AU"); - var language = (ILanguage)new Language(TestObjects.GetGlobalSettings(), au.Name) + var language = (ILanguage)new Language(_globalSettings, au.Name) { CultureName = au.DisplayName, FallbackLanguageId = 1 @@ -186,7 +191,7 @@ namespace Umbraco.Tests.Persistence.Repositories var repository = CreateRepository(provider); // Act - var languageBR = new Language(TestObjects.GetGlobalSettings(), "pt-BR") { CultureName = "pt-BR" }; + var languageBR = new Language(_globalSettings, "pt-BR") { CultureName = "pt-BR" }; repository.Save(languageBR); // Assert @@ -208,7 +213,7 @@ namespace Umbraco.Tests.Persistence.Repositories var repository = CreateRepository(provider); // Act - var languageBR = new Language(TestObjects.GetGlobalSettings(), "pt-BR") { CultureName = "pt-BR", IsDefault = true, IsMandatory = true }; + var languageBR = new Language(_globalSettings, "pt-BR") { CultureName = "pt-BR", IsDefault = true, IsMandatory = true }; repository.Save(languageBR); // Assert @@ -230,7 +235,7 @@ namespace Umbraco.Tests.Persistence.Repositories var repository = CreateRepository(provider); // Act - var languageBR = new Language(TestObjects.GetGlobalSettings(), "pt-BR") + var languageBR = new Language(_globalSettings, "pt-BR") { CultureName = "pt-BR", FallbackLanguageId = 1 @@ -253,16 +258,16 @@ namespace Umbraco.Tests.Persistence.Repositories { var repository = CreateRepository(provider); - var languageBR = (ILanguage)new Language(TestObjects.GetGlobalSettings(), "pt-BR") { CultureName = "pt-BR", IsDefault = true, IsMandatory = true }; + var languageBR = (ILanguage)new Language(_globalSettings, "pt-BR") { CultureName = "pt-BR", IsDefault = true, IsMandatory = true }; repository.Save(languageBR); - var languageEN = new Language(TestObjects.GetGlobalSettings(), "en-AU") { CultureName = "en-AU" }; + var languageEN = new Language(_globalSettings, "en-AU") { CultureName = "en-AU" }; repository.Save(languageEN); Assert.IsTrue(languageBR.IsDefault); Assert.IsTrue(languageBR.IsMandatory); // Act - var languageNZ = new Language(TestObjects.GetGlobalSettings(), "en-NZ") { CultureName = "en-NZ", IsDefault = true, IsMandatory = true }; + var languageNZ = new Language(_globalSettings, "en-NZ") { CultureName = "en-NZ", IsDefault = true, IsMandatory = true }; repository.Save(languageNZ); languageBR = repository.Get(languageBR.Id); @@ -390,16 +395,16 @@ namespace Umbraco.Tests.Persistence.Repositories { //Id 1 is en-US - when Umbraco is installed - var languageDK = new Language(TestObjects.GetGlobalSettings(), "da-DK") { CultureName = "da-DK" }; + var languageDK = new Language(_globalSettings, "da-DK") { CultureName = "da-DK" }; ServiceContext.LocalizationService.Save(languageDK);//Id 2 - var languageSE = new Language(TestObjects.GetGlobalSettings(), "sv-SE") { CultureName = "sv-SE" }; + var languageSE = new Language(_globalSettings, "sv-SE") { CultureName = "sv-SE" }; ServiceContext.LocalizationService.Save(languageSE);//Id 3 - var languageDE = new Language(TestObjects.GetGlobalSettings(), "de-DE") { CultureName = "de-DE" }; + var languageDE = new Language(_globalSettings, "de-DE") { CultureName = "de-DE" }; ServiceContext.LocalizationService.Save(languageDE);//Id 4 - var languagePT = new Language(TestObjects.GetGlobalSettings(), "pt-PT") { CultureName = "pt-PT" }; + var languagePT = new Language(_globalSettings, "pt-PT") { CultureName = "pt-PT" }; ServiceContext.LocalizationService.Save(languagePT);//Id 5 } } diff --git a/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs index 03fc77572a..e49d6854d2 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs @@ -16,6 +16,7 @@ using System; using Umbraco.Core.Configuration; using Umbraco.Core.Serialization; using Umbraco.Core.Configuration.Models; +using Umbraco.Tests.Common.Builders; namespace Umbraco.Tests.Persistence.Repositories { @@ -28,9 +29,10 @@ namespace Umbraco.Tests.Persistence.Repositories private MediaRepository CreateMediaRepository(IScopeProvider provider, out IMediaTypeRepository mediaTypeRepository) { var accessor = (IScopeAccessor) provider; + var globalSettings = new GlobalSettingsBuilder().Build(); var templateRepository = new TemplateRepository(accessor, AppCaches.Disabled, Logger, TestObjects.GetFileSystemsMock(), IOHelper, ShortStringHelper); var commonRepository = new ContentTypeCommonRepository(accessor, templateRepository, AppCaches, ShortStringHelper); - var languageRepository = new LanguageRepository(accessor, AppCaches, Logger, TestObjects.GetGlobalSettings()); + var languageRepository = new LanguageRepository(accessor, AppCaches, Logger, Microsoft.Extensions.Options.Options.Create(globalSettings)); mediaTypeRepository = new MediaTypeRepository(accessor, AppCaches, Mock.Of(), commonRepository, languageRepository, ShortStringHelper); var tagRepository = new TagRepository(accessor, AppCaches, Mock.Of()); var relationTypeRepository = new RelationTypeRepository(accessor, AppCaches.Disabled, Logger); @@ -52,10 +54,11 @@ namespace Umbraco.Tests.Persistence.Repositories private DocumentRepository CreateContentRepository(IScopeProvider provider, out IContentTypeRepository contentTypeRepository, out ITemplateRepository templateRepository) { var accessor = (IScopeAccessor) provider; + var globalSettings = new GlobalSettingsBuilder().Build(); templateRepository = new TemplateRepository(accessor, AppCaches, Logger, TestObjects.GetFileSystemsMock(), IOHelper, ShortStringHelper); var tagRepository = new TagRepository(accessor, AppCaches, Logger); var commonRepository = new ContentTypeCommonRepository(accessor, templateRepository, AppCaches, ShortStringHelper); - var languageRepository = new LanguageRepository(accessor, AppCaches, Logger, TestObjects.GetGlobalSettings()); + var languageRepository = new LanguageRepository(accessor, AppCaches, Logger, Microsoft.Extensions.Options.Options.Create(globalSettings)); contentTypeRepository = new ContentTypeRepository(accessor, AppCaches, Logger, commonRepository, languageRepository, ShortStringHelper); var relationTypeRepository = new RelationTypeRepository(accessor, AppCaches.Disabled, Logger); var entityRepository = new EntityRepository(accessor); @@ -69,7 +72,8 @@ namespace Umbraco.Tests.Persistence.Repositories private UserRepository CreateRepository(IScopeProvider provider) { var accessor = (IScopeAccessor) provider; - var repository = new UserRepository(accessor, AppCaches.Disabled, Logger, Mappers, TestObjects.GetGlobalSettings(), new UserPasswordConfigurationSettings(), new JsonNetSerializer()); + var globalSettings = new GlobalSettingsBuilder().Build(); + var repository = new UserRepository(accessor, AppCaches.Disabled, Logger, Mappers, globalSettings, new UserPasswordConfigurationSettings(), new JsonNetSerializer()); return repository; } diff --git a/src/Umbraco.Tests/Persistence/SchemaValidationTest.cs b/src/Umbraco.Tests/Persistence/SchemaValidationTest.cs index 0648e3bc21..27bab47968 100644 --- a/src/Umbraco.Tests/Persistence/SchemaValidationTest.cs +++ b/src/Umbraco.Tests/Persistence/SchemaValidationTest.cs @@ -5,6 +5,7 @@ using Umbraco.Core.Configuration; using Umbraco.Core.Logging; using Umbraco.Core.Migrations.Install; using Umbraco.Core.Persistence.SqlSyntax; +using Umbraco.Tests.Common.Builders; using Umbraco.Tests.LegacyXmlPublishedCache; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.Testing; @@ -22,7 +23,8 @@ namespace Umbraco.Tests.Persistence using (var scope = ScopeProvider.CreateScope()) { - var schema = new DatabaseSchemaCreator(scope.Database, Logger, UmbracoVersion, TestObjects.GetGlobalSettings()); + var globalSettings = new GlobalSettingsBuilder().Build(); + var schema = new DatabaseSchemaCreator(scope.Database, Logger, UmbracoVersion, globalSettings); result = schema.ValidateSchema( //TODO: When we remove the xml cache from tests we can remove this too DatabaseSchemaCreator.OrderedTables.Concat(new []{typeof(ContentXmlDto), typeof(PreviewXmlDto)})); diff --git a/src/Umbraco.Tests/Persistence/SqlCeTableByTableTest.cs b/src/Umbraco.Tests/Persistence/SqlCeTableByTableTest.cs index 207e595598..337f1a7289 100644 --- a/src/Umbraco.Tests/Persistence/SqlCeTableByTableTest.cs +++ b/src/Umbraco.Tests/Persistence/SqlCeTableByTableTest.cs @@ -2,10 +2,12 @@ using NPoco; using NUnit.Framework; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Logging; using Umbraco.Core.Migrations.Install; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.Dtos; +using Umbraco.Tests.Common.Builders; using Umbraco.Tests.LegacyXmlPublishedCache; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.Testing; @@ -16,7 +18,7 @@ namespace Umbraco.Tests.Persistence [UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest)] public class SqlCeTableByTableTest : TestWithDatabaseBase { - public IGlobalSettings GlobalSettings => SettingsForTests.GenerateMockGlobalSettings(); + public GlobalSettings GlobalSettings => new GlobalSettingsBuilder().Build(); [Test] public void Can_Create_umbracoNode_Table() diff --git a/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueEditorTests.cs b/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueEditorTests.cs index 6301be051d..439036fa16 100644 --- a/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueEditorTests.cs +++ b/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueEditorTests.cs @@ -9,6 +9,7 @@ using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.PropertyEditors; using Umbraco.Core.Strings; +using Umbraco.Tests.Common.Builders; using Umbraco.Tests.Components; using Umbraco.Tests.TestHelpers; using Current = Umbraco.Web.Composing.Current; @@ -25,10 +26,11 @@ namespace Umbraco.Tests.PropertyEditors Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture; var register = TestHelper.GetRegister(); - var composition = new Composition(register, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.GetConfigs(), TestHelper.IOHelper, AppCaches.NoCache); + var composition = new Composition(register, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.IOHelper, AppCaches.NoCache); + var requestHandlerSettings = new RequestHandlerSettingsBuilder().Build(); register.Register(_ - => new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(SettingsForTests.GenerateMockRequestHandlerSettings()))); + => new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(requestHandlerSettings))); Current.Factory = composition.CreateFactory(); } diff --git a/src/Umbraco.Tests/Published/ConvertersTests.cs b/src/Umbraco.Tests/Published/ConvertersTests.cs index 3ecae51ea8..2ae4c238cc 100644 --- a/src/Umbraco.Tests/Published/ConvertersTests.cs +++ b/src/Umbraco.Tests/Published/ConvertersTests.cs @@ -182,7 +182,7 @@ namespace Umbraco.Tests.Published // Current.Reset(); var register = TestHelper.GetRegister(); - var composition = new Composition(register, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.GetConfigs(), TestHelper.IOHelper, AppCaches.NoCache); + var composition = new Composition(register, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.IOHelper, AppCaches.NoCache); composition.WithCollectionBuilder() .Append() diff --git a/src/Umbraco.Tests/PublishedContent/NuCacheChildrenTests.cs b/src/Umbraco.Tests/PublishedContent/NuCacheChildrenTests.cs index f0aa39fcf8..d224d97467 100644 --- a/src/Umbraco.Tests/PublishedContent/NuCacheChildrenTests.cs +++ b/src/Umbraco.Tests/PublishedContent/NuCacheChildrenTests.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Data; using System.Linq; +using Microsoft.Extensions.Options; using Moq; using NUnit.Framework; using Umbraco.Core; @@ -22,6 +23,7 @@ using Umbraco.Core.Services; using Umbraco.Core.Services.Changes; using Umbraco.Core.Strings; using Umbraco.Tests.Common; +using Umbraco.Tests.Common.Builders; using Umbraco.Tests.Strings; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.Testing.Objects; @@ -60,12 +62,7 @@ namespace Umbraco.Tests.PublishedContent var factory = Mock.Of(); Current.Factory = factory; - var configs = TestHelper.GetConfigs(); - Mock.Get(factory).Setup(x => x.GetInstance(typeof(Configs))).Returns(configs); - var globalSettings = new GlobalSettings(); var hostingEnvironment = Mock.Of(); - configs.Add(TestHelpers.SettingsForTests.GenerateMockContentSettings); - configs.Add(() => globalSettings); Mock.Get(factory).Setup(x => x.GetInstance(typeof(IPublishedModelFactory))).Returns(PublishedModelFactory); @@ -145,8 +142,9 @@ namespace Umbraco.Tests.PublishedContent _source = new TestDataSource(kits()); var typeFinder = TestHelper.GetTypeFinder(); - var settings = Mock.Of(); + var globalSettings = new GlobalSettingsBuilder().Build(); + var nuCacheSettings = new NuCacheSettingsBuilder().Build(); // at last, create the complete NuCache snapshot service! var options = new PublishedSnapshotServiceOptions { IgnoreLocalDb = true }; @@ -164,14 +162,14 @@ namespace Umbraco.Tests.PublishedContent Mock.Of(), new TestDefaultCultureAccessor(), _source, - globalSettings, + Options.Create(globalSettings), Mock.Of(), PublishedModelFactory, new UrlSegmentProviderCollection(new[] { new DefaultUrlSegmentProvider(TestHelper.ShortStringHelper) }), hostingEnvironment, new MockShortStringHelper(), TestHelper.IOHelper, - settings); + Options.Create(nuCacheSettings)); // invariant is the current default _variationAccesor.VariationContext = new VariationContext(); diff --git a/src/Umbraco.Tests/PublishedContent/NuCacheTests.cs b/src/Umbraco.Tests/PublishedContent/NuCacheTests.cs index 8003bdf236..da67a76eb9 100644 --- a/src/Umbraco.Tests/PublishedContent/NuCacheTests.cs +++ b/src/Umbraco.Tests/PublishedContent/NuCacheTests.cs @@ -20,6 +20,7 @@ using Umbraco.Core.Services; using Umbraco.Core.Services.Changes; using Umbraco.Core.Strings; using Umbraco.Tests.Common; +using Umbraco.Tests.Common.Builders; using Umbraco.Tests.Strings; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.Testing.Objects; @@ -53,12 +54,6 @@ namespace Umbraco.Tests.PublishedContent var factory = Mock.Of(); Current.Factory = factory; - var configs = TestHelper.GetConfigs(); - Mock.Get(factory).Setup(x => x.GetInstance(typeof(Configs))).Returns(configs); - var globalSettings = new GlobalSettings(); - configs.Add(TestHelpers.SettingsForTests.GenerateMockContentSettings); - configs.Add(() => globalSettings); - var publishedModelFactory = new NoopPublishedModelFactory(); Mock.Get(factory).Setup(x => x.GetInstance(typeof(IPublishedModelFactory))).Returns(publishedModelFactory); @@ -186,7 +181,9 @@ namespace Umbraco.Tests.PublishedContent _variationAccesor = new TestVariationContextAccessor(); var typeFinder = TestHelper.GetTypeFinder(); - var settings = Mock.Of(); + + var globalSettings = new GlobalSettingsBuilder().Build(); + var nuCacheSettings = new NuCacheSettingsBuilder().Build(); // at last, create the complete NuCache snapshot service! var options = new PublishedSnapshotServiceOptions { IgnoreLocalDb = true }; @@ -211,7 +208,7 @@ namespace Umbraco.Tests.PublishedContent TestHelper.GetHostingEnvironment(), new MockShortStringHelper(), TestHelper.IOHelper, - settings); + nuCacheSettings); // invariant is the current default _variationAccesor.VariationContext = new VariationContext(); diff --git a/src/Umbraco.Tests/PublishedContent/PublishedContentLanguageVariantTests.cs b/src/Umbraco.Tests/PublishedContent/PublishedContentLanguageVariantTests.cs index 8c1024351b..50e82998f9 100644 --- a/src/Umbraco.Tests/PublishedContent/PublishedContentLanguageVariantTests.cs +++ b/src/Umbraco.Tests/PublishedContent/PublishedContentLanguageVariantTests.cs @@ -7,6 +7,7 @@ using NUnit.Framework; using Umbraco.Core.Models; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Services; +using Umbraco.Tests.Common.Builders; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.Testing; using Umbraco.Web; @@ -34,11 +35,11 @@ namespace Umbraco.Tests.PublishedContent private static void MockLocalizationService(ServiceContext serviceContext) { - var globalSettings = SettingsForTests.GenerateMockGlobalSettings(); // Set up languages. // Spanish falls back to English and Italian to Spanish (and then to English). // French has no fall back. // Danish, Swedish and Norweigan create an invalid loop. + var globalSettings = new GlobalSettingsBuilder().Build(); var languages = new List { new Language(globalSettings, "en-US") { Id = 1, CultureName = "English", IsDefault = true }, diff --git a/src/Umbraco.Tests/Routing/ContentFinderByUrlAndTemplateTests.cs b/src/Umbraco.Tests/Routing/ContentFinderByUrlAndTemplateTests.cs index e8b8bab22b..07f0e587e3 100644 --- a/src/Umbraco.Tests/Routing/ContentFinderByUrlAndTemplateTests.cs +++ b/src/Umbraco.Tests/Routing/ContentFinderByUrlAndTemplateTests.cs @@ -8,6 +8,7 @@ using Umbraco.Web.Routing; using Umbraco.Core.Models; using Umbraco.Tests.Testing; using Current = Umbraco.Web.Composing.Current; +using Umbraco.Tests.Common.Builders; namespace Umbraco.Tests.Routing { @@ -38,7 +39,8 @@ namespace Umbraco.Tests.Routing var umbracoContext = GetUmbracoContext(urlAsString, template1.Id, globalSettings:globalSettings.Object); var publishedRouter = CreatePublishedRouter(); var frequest = publishedRouter.CreateRequest(umbracoContext); - var lookup = new ContentFinderByUrlAndTemplate(Logger, ServiceContext.FileService, ServiceContext.ContentTypeService, SettingsForTests.GenerateMockWebRoutingSettings()); + var webRoutingSettings = new WebRoutingSettingsBuilder().Build(); + var lookup = new ContentFinderByUrlAndTemplate(Logger, ServiceContext.FileService, ServiceContext.ContentTypeService, webRoutingSettings); var result = lookup.TryFindContent(frequest); diff --git a/src/Umbraco.Tests/Routing/GetContentUrlsTests.cs b/src/Umbraco.Tests/Routing/GetContentUrlsTests.cs index 4f11802b43..7456d32aa4 100644 --- a/src/Umbraco.Tests/Routing/GetContentUrlsTests.cs +++ b/src/Umbraco.Tests/Routing/GetContentUrlsTests.cs @@ -1,26 +1,35 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Globalization; using System.Linq; using Moq; using NUnit.Framework; -using Umbraco.Core; -using Umbraco.Web.Composing; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Models; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Services; -using Umbraco.Tests.TestHelpers; -using Umbraco.Tests.TestHelpers.Entities; -using Umbraco.Web; -using Umbraco.Web.Routing; using Umbraco.Tests.Common; -using SettingsForTests = Umbraco.Tests.TestHelpers.SettingsForTests; +using Umbraco.Tests.Common.Builders; +using Umbraco.Tests.TestHelpers.Entities; +using Umbraco.Web.Routing; namespace Umbraco.Tests.Routing { [TestFixture] public class GetContentUrlsTests : UrlRoutingTestBase { + private GlobalSettings _globalSettings; + private WebRoutingSettings _webRoutingSettings; + private RequestHandlerSettings _requestHandlerSettings; + + public override void SetUp() + { + base.SetUp(); + + _globalSettings = new GlobalSettingsBuilder().Build(); + _webRoutingSettings = new WebRoutingSettingsBuilder().Build(); + _requestHandlerSettings = new RequestHandlerSettingsBuilder().Build(); + } + private ILocalizedTextService GetTextService() { var textService = Mock.Of( @@ -34,7 +43,7 @@ namespace Umbraco.Tests.Routing { var allLangs = isoCodes .Select(CultureInfo.GetCultureInfo) - .Select(culture => new Language(TestObjects.GetGlobalSettings(), culture.Name) + .Select(culture => new Language(_globalSettings, culture.Name) { CultureName = culture.DisplayName, IsDefault = true, @@ -78,15 +87,17 @@ namespace Umbraco.Tests.Routing content.Path = "-1,1046"; content.Published = true; - var umbracoSettings = SettingsForTests.GenerateMockRequestHandlerSettings(); - var umbContext = GetUmbracoContext("http://localhost:8000"); var umbracoContextAccessor = new TestUmbracoContextAccessor(umbContext); - var urlProvider = new DefaultUrlProvider(umbracoSettings, Logger, TestObjects.GetGlobalSettings(), new SiteDomainHelper(), + var urlProvider = new DefaultUrlProvider( + Microsoft.Extensions.Options.Options.Create(_requestHandlerSettings), + Logger, + Microsoft.Extensions.Options.Options.Create(_globalSettings), + new SiteDomainHelper(), umbracoContextAccessor, UriUtility); var publishedUrlProvider = new UrlProvider( umbracoContextAccessor, - TestHelper.WebRoutingSettings, + Microsoft.Extensions.Options.Options.Create(_webRoutingSettings), new UrlProviderCollection(new []{urlProvider}), new MediaUrlProviderCollection(Enumerable.Empty()), Mock.Of() @@ -123,15 +134,16 @@ namespace Umbraco.Tests.Routing child.Path = "-1,1046,1173"; child.Published = true; - var umbracoSettings = SettingsForTests.GenerateMockRequestHandlerSettings(); - - var umbContext = GetUmbracoContext("http://localhost:8000"); var umbracoContextAccessor = new TestUmbracoContextAccessor(umbContext); - var urlProvider = new DefaultUrlProvider(umbracoSettings, Logger, TestObjects.GetGlobalSettings(), new SiteDomainHelper(), umbracoContextAccessor, UriUtility); + var urlProvider = new DefaultUrlProvider( + Microsoft.Extensions.Options.Options.Create(_requestHandlerSettings), + Logger, + Microsoft.Extensions.Options.Options.Create(_globalSettings), + new SiteDomainHelper(), umbracoContextAccessor, UriUtility); var publishedUrlProvider = new UrlProvider( umbracoContextAccessor, - TestHelper.WebRoutingSettings, + Microsoft.Extensions.Options.Options.Create(_webRoutingSettings), new UrlProviderCollection(new []{urlProvider}), new MediaUrlProviderCollection(Enumerable.Empty()), Mock.Of() diff --git a/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs b/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs index 358a47f09b..dc6caa3ce0 100644 --- a/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs +++ b/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs @@ -6,27 +6,30 @@ using Moq; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Cache; -using Umbraco.Core.Logging; -using Umbraco.Core.Models; -using Umbraco.Tests.TestHelpers; -using Umbraco.Tests.TestHelpers.Stubs; -using Umbraco.Web; -using Umbraco.Web.Models; -using Umbraco.Web.Mvc; -using Umbraco.Web.WebApi; -using Umbraco.Core.Strings; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Hosting; using Umbraco.Core.IO; +using Umbraco.Core.Logging; +using Umbraco.Core.Models; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Runtime; using Umbraco.Core.Services; +using Umbraco.Core.Strings; +using Umbraco.Tests.Common; +using Umbraco.Tests.Common.Builders; using Umbraco.Tests.PublishedContent; +using Umbraco.Tests.TestHelpers; +using Umbraco.Tests.TestHelpers.Stubs; using Umbraco.Tests.Testing; +using Umbraco.Web; +using Umbraco.Web.Models; +using Umbraco.Web.Mvc; using Umbraco.Web.Runtime; +using Umbraco.Web.WebApi; +using ConnectionStrings = Umbraco.Core.Configuration.Models.ConnectionStrings; using Current = Umbraco.Web.Composing.Current; using ILogger = Umbraco.Core.Logging.ILogger; -using Umbraco.Tests.Common; namespace Umbraco.Tests.Routing { @@ -49,8 +52,8 @@ namespace Umbraco.Tests.Routing public class TestRuntime : CoreRuntime { - public TestRuntime(Configs configs, IUmbracoVersion umbracoVersion, IIOHelper ioHelper, ILogger logger, IHostingEnvironment hostingEnvironment, IBackOfficeInfo backOfficeInfo) - : base(configs, umbracoVersion, ioHelper, Mock.Of(), Mock.Of(), new AspNetUmbracoBootPermissionChecker(), hostingEnvironment, backOfficeInfo, TestHelper.DbProviderFactoryCreator, TestHelper.MainDom, TestHelper.GetTypeFinder(), NoAppCache.Instance) + public TestRuntime(GlobalSettings globalSettings, ConnectionStrings connectionStrings, IUmbracoVersion umbracoVersion, IIOHelper ioHelper, ILogger logger, IHostingEnvironment hostingEnvironment, IBackOfficeInfo backOfficeInfo) + : base(globalSettings, connectionStrings, umbracoVersion, ioHelper, Mock.Of(), Mock.Of(), new AspNetUmbracoBootPermissionChecker(), hostingEnvironment, backOfficeInfo, TestHelper.DbProviderFactoryCreator, TestHelper.MainDom, TestHelper.GetTypeFinder(), NoAppCache.Instance) { } @@ -69,7 +72,8 @@ namespace Umbraco.Tests.Routing var umbracoApiControllerTypes = new UmbracoApiControllerTypeCollection(Composition.TypeLoader.GetUmbracoApiControllers()); Composition.RegisterUnique(umbracoApiControllerTypes); - Composition.RegisterUnique(_ => new DefaultShortStringHelper(TestHelpers.SettingsForTests.GenerateMockRequestHandlerSettings())); + var requestHandlerSettings = new RequestHandlerSettingsBuilder().Build(); + Composition.RegisterUnique(_ => new DefaultShortStringHelper(Microsoft.Extensions.Options.Options.Create(requestHandlerSettings))); } public override void TearDown() diff --git a/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs b/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs index 0165e7714f..4dfcd46788 100644 --- a/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs +++ b/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs @@ -15,6 +15,7 @@ using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Services; using Umbraco.Web.PublishedCache; using Umbraco.Web.Routing; +using Umbraco.Web.Configuration; namespace Umbraco.Tests.Routing { @@ -32,7 +33,7 @@ namespace Umbraco.Tests.Routing //create the module var logger = Mock.Of(); var globalSettings = TestObjects.GetGlobalSettings(); - var runtime = new RuntimeState(globalSettings, UmbracoVersion); + var runtime = new RuntimeState(ConfigModelConversions.ConvertGlobalSettings(globalSettings), UmbracoVersion); _module = new UmbracoInjectedModule ( diff --git a/src/Umbraco.Tests/Runtimes/StandaloneTests.cs b/src/Umbraco.Tests/Runtimes/StandaloneTests.cs index ac0ff3f9f9..5984164497 100644 --- a/src/Umbraco.Tests/Runtimes/StandaloneTests.cs +++ b/src/Umbraco.Tests/Runtimes/StandaloneTests.cs @@ -37,6 +37,7 @@ using Current = Umbraco.Web.Composing.Current; using Umbraco.Tests.Common; using Umbraco.Tests.Common.Composing; using Umbraco.Core.Media; +using Umbraco.Tests.Common.Builders; namespace Umbraco.Tests.Runtimes { @@ -63,10 +64,10 @@ namespace Umbraco.Tests.Runtimes var profiler = new LogProfiler(logger); var profilingLogger = new ProfilingLogger(logger, profiler); var appCaches = AppCaches.Disabled; - var globalSettings = TestHelper.GetConfigs().Global(); - var connectionStrings = TestHelper.GetConfigs().ConnectionStrings(); + var globalSettings = new GlobalSettingsBuilder().Build(); + var connectionStrings = new ConnectionStringsBuilder().Build(); var typeFinder = TestHelper.GetTypeFinder(); - var databaseFactory = new UmbracoDatabaseFactory(logger,globalSettings, connectionStrings, new Lazy(() => factory.GetInstance()), TestHelper.DbProviderFactoryCreator); + var databaseFactory = new UmbracoDatabaseFactory(logger, globalSettings, connectionStrings, new Lazy(() => factory.GetInstance()), TestHelper.DbProviderFactoryCreator); var ioHelper = TestHelper.IOHelper; var hostingEnvironment = Mock.Of(); var typeLoader = new TypeLoader(typeFinder, appCaches.RuntimeCache, new DirectoryInfo(ioHelper.MapPath("~/App_Data/TEMP")), profilingLogger); @@ -77,14 +78,13 @@ namespace Umbraco.Tests.Runtimes var configs = TestHelper.GetConfigs(); var variationContextAccessor = TestHelper.VariationContextAccessor; - // create the register and the composition var register = TestHelper.GetRegister(); - var composition = new Composition(register, typeLoader, profilingLogger, runtimeState, configs, ioHelper, appCaches); + var composition = new Composition(register, typeLoader, profilingLogger, runtimeState, ioHelper, appCaches); composition.RegisterEssentials(logger, profiler, profilingLogger, mainDom, appCaches, databaseFactory, typeLoader, runtimeState, typeFinder, ioHelper, umbracoVersion, TestHelper.DbProviderFactoryCreator, hostingEnvironment, backOfficeInfo); // create the core runtime and have it compose itself - var coreRuntime = new CoreRuntime(configs, umbracoVersion, ioHelper, logger, profiler, new AspNetUmbracoBootPermissionChecker(), hostingEnvironment, backOfficeInfo, TestHelper.DbProviderFactoryCreator, TestHelper.MainDom, typeFinder, NoAppCache.Instance); + var coreRuntime = new CoreRuntime(globalSettings, connectionStrings, umbracoVersion, ioHelper, logger, profiler, new AspNetUmbracoBootPermissionChecker(), hostingEnvironment, backOfficeInfo, TestHelper.DbProviderFactoryCreator, TestHelper.MainDom, typeFinder, NoAppCache.Instance); // determine actual runtime level runtimeState.DetermineRuntimeLevel(databaseFactory, logger); @@ -124,8 +124,6 @@ namespace Umbraco.Tests.Runtimes .Append(); // configure - composition.Configs.Add(() => TestHelpers.SettingsForTests.DefaultGlobalSettings); - composition.Configs.Add(TestHelpers.SettingsForTests.GenerateMockContentSettings); // create and register the factory Current.Factory = factory = composition.CreateFactory(); @@ -163,7 +161,8 @@ namespace Umbraco.Tests.Runtimes var scopeProvider = factory.GetInstance(); using (var scope = scopeProvider.CreateScope()) { - var creator = new DatabaseSchemaCreator(scope.Database, logger, umbracoVersion, TestHelpers.SettingsForTests.DefaultGlobalSettings); + var globalSettings = new GlobalSettingsBuilder().Build(); + var creator = new DatabaseSchemaCreator(scope.Database, logger, umbracoVersion, globalSettings); creator.InitializeDatabaseSchema(); scope.Complete(); } @@ -273,7 +272,7 @@ namespace Umbraco.Tests.Runtimes // create the register and the composition var register = TestHelper.GetRegister(); - var composition = new Composition(register, typeLoader, profilingLogger, runtimeState, configs, ioHelper, appCaches); + var composition = new Composition(register, typeLoader, profilingLogger, runtimeState, ioHelper, appCaches); var umbracoVersion = TestHelper.GetUmbracoVersion(); composition.RegisterEssentials(logger, profiler, profilingLogger, mainDom, appCaches, databaseFactory, typeLoader, runtimeState, typeFinder, ioHelper, umbracoVersion, TestHelper.DbProviderFactoryCreator, hostingEnvironment, backOfficeInfo); diff --git a/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs b/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs index be609f9a83..c646bdcf79 100644 --- a/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs @@ -34,7 +34,7 @@ namespace Umbraco.Tests.Scoping var register = TestHelper.GetRegister(); - var composition = new Composition(register, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.GetConfigs(), TestHelper.IOHelper, AppCaches.NoCache); + var composition = new Composition(register, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.IOHelper, AppCaches.NoCache); _testObjects = new TestObjects(register); diff --git a/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs b/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs index 49bca378c7..35f4f421bd 100644 --- a/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopedNuCacheTests.cs @@ -20,6 +20,7 @@ using Umbraco.Core.Services.Implement; using Umbraco.Core.Strings; using Umbraco.Core.Sync; using Umbraco.Tests.Common; +using Umbraco.Tests.Common.Builders; using Umbraco.Tests.Strings; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.Testing; @@ -87,7 +88,9 @@ namespace Umbraco.Tests.Scoping var hostingEnvironment = TestHelper.GetHostingEnvironment(); var typeFinder = TestHelper.GetTypeFinder(); - var settings = Mock.Of(); + + var globalSettings = new GlobalSettingsBuilder().Build(); + var nuCacheSettings = new NuCacheSettingsBuilder().Build(); return new PublishedSnapshotService( options, @@ -102,14 +105,14 @@ namespace Umbraco.Tests.Scoping documentRepository, mediaRepository, memberRepository, DefaultCultureAccessor, new DatabaseDataSource(Mock.Of()), - Factory.GetInstance(), + Microsoft.Extensions.Options.Options.Create(globalSettings), Factory.GetInstance(), new NoopPublishedModelFactory(), new UrlSegmentProviderCollection(new[] { new DefaultUrlSegmentProvider(ShortStringHelper) }), hostingEnvironment, new MockShortStringHelper(), IOHelper, - settings); + Microsoft.Extensions.Options.Options.Create(nuCacheSettings)); } protected IUmbracoContext GetUmbracoContextNu(string url, RouteData routeData = null, bool setSingleton = false) diff --git a/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs b/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs index 4c3bb288e4..da90d7fefa 100644 --- a/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopedRepositoryTests.cs @@ -1,21 +1,23 @@ using System; using System.Collections.Generic; using System.Linq; +using Moq; using NUnit.Framework; +using Umbraco.Core; using Umbraco.Core.Cache; -using Umbraco.Web.Composing; +using Umbraco.Core.Configuration.Models; +using Umbraco.Core.Events; +using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.Membership; using Umbraco.Core.Scoping; +using Umbraco.Core.Sync; +using Umbraco.Tests.Common.Builders; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.Testing; -using Umbraco.Web.Cache; -using Moq; -using Umbraco.Core; -using Umbraco.Core.Events; -using Umbraco.Core.Logging; -using Umbraco.Core.Sync; using Umbraco.Web; +using Umbraco.Web.Cache; +using Umbraco.Web.Composing; namespace Umbraco.Tests.Scoping { @@ -25,6 +27,15 @@ namespace Umbraco.Tests.Scoping { private DistributedCacheBinder _distributedCacheBinder; + private GlobalSettings _globalSettings; + + public override void SetUp() + { + base.SetUp(); + + _globalSettings = new GlobalSettingsBuilder().Build(); + } + protected override void Compose() { base.Compose(); @@ -63,7 +74,7 @@ namespace Umbraco.Tests.Scoping var service = ServiceContext.UserService; var globalCache = Current.AppCaches.IsolatedCaches.GetOrCreate(typeof(IUser)); - var user = (IUser)new User(TestObjects.GetGlobalSettings(), "name", "email", "username", "rawPassword"); + var user = (IUser)new User(_globalSettings, "name", "email", "username", "rawPassword"); service.Save(user); // global cache contains the entity @@ -140,7 +151,7 @@ namespace Umbraco.Tests.Scoping var service = ServiceContext.LocalizationService; var globalCache = Current.AppCaches.IsolatedCaches.GetOrCreate(typeof (ILanguage)); - var lang = (ILanguage) new Language(TestObjects.GetGlobalSettings(), "fr-FR"); + var lang = (ILanguage) new Language(_globalSettings, "fr-FR"); service.Save(lang); // global cache has been flushed, reload @@ -232,7 +243,7 @@ namespace Umbraco.Tests.Scoping var service = ServiceContext.LocalizationService; var globalCache = Current.AppCaches.IsolatedCaches.GetOrCreate(typeof (IDictionaryItem)); - var lang = (ILanguage)new Language(TestObjects.GetGlobalSettings(), "fr-FR"); + var lang = (ILanguage)new Language(_globalSettings, "fr-FR"); service.Save(lang); var item = (IDictionaryItem) new DictionaryItem("item-key"); diff --git a/src/Umbraco.Tests/Security/BackOfficeOwinUserManagerTests.cs b/src/Umbraco.Tests/Security/BackOfficeOwinUserManagerTests.cs index 8958eabd42..b6a8c225e0 100644 --- a/src/Umbraco.Tests/Security/BackOfficeOwinUserManagerTests.cs +++ b/src/Umbraco.Tests/Security/BackOfficeOwinUserManagerTests.cs @@ -11,6 +11,7 @@ using Umbraco.Core.BackOffice; using Umbraco.Core.Configuration; using Umbraco.Core.Models.Membership; using Umbraco.Net; +using Umbraco.Tests.Common.Builders; using Umbraco.Web.Security; namespace Umbraco.Tests.Security @@ -44,7 +45,8 @@ namespace Umbraco.Tests.Security var mockGlobalSettings = new Mock(); mockGlobalSettings.Setup(x => x.DefaultUILanguage).Returns("test"); - var user = new BackOfficeIdentityUser(mockGlobalSettings.Object, 2, new List()) + var globalSettings = new GlobalSettingsBuilder().Build(); + var user = new BackOfficeIdentityUser(globalSettings, 2, new List()) { UserName = "alice", Name = "Alice", diff --git a/src/Umbraco.Tests/Security/OwinDataProtectorTokenProviderTests.cs b/src/Umbraco.Tests/Security/OwinDataProtectorTokenProviderTests.cs index 7b1ca53104..65efdfeb0d 100644 --- a/src/Umbraco.Tests/Security/OwinDataProtectorTokenProviderTests.cs +++ b/src/Umbraco.Tests/Security/OwinDataProtectorTokenProviderTests.cs @@ -9,6 +9,7 @@ using NUnit.Framework; using Umbraco.Core.BackOffice; using Umbraco.Core.Configuration; using Umbraco.Core.Models.Membership; +using Umbraco.Tests.Common.Builders; using Umbraco.Web.Security; namespace Umbraco.Tests.Security @@ -227,6 +228,7 @@ namespace Umbraco.Tests.Security _mockDataProtector.Setup(x => x.Protect(It.IsAny())).Returns((byte[] originalBytes) => originalBytes); _mockDataProtector.Setup(x => x.Unprotect(It.IsAny())).Returns((byte[] originalBytes) => originalBytes); + var globalSettings = new GlobalSettingsBuilder().Build(); var mockGlobalSettings = new Mock(); mockGlobalSettings.Setup(x => x.DefaultUILanguage).Returns("test"); @@ -234,7 +236,7 @@ namespace Umbraco.Tests.Security null, null, null, null, null, null, null, null); _mockUserManager.Setup(x => x.SupportsUserSecurityStamp).Returns(false); - _testUser = new BackOfficeIdentityUser(mockGlobalSettings.Object, 2, new List()) + _testUser = new BackOfficeIdentityUser(globalSettings, 2, new List()) { UserName = "alice", Name = "Alice", diff --git a/src/Umbraco.Tests/Services/ContentServiceEventTests.cs b/src/Umbraco.Tests/Services/ContentServiceEventTests.cs index 26f6d37456..208afe5b4b 100644 --- a/src/Umbraco.Tests/Services/ContentServiceEventTests.cs +++ b/src/Umbraco.Tests/Services/ContentServiceEventTests.cs @@ -1,11 +1,13 @@ using System.Linq; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Events; using Umbraco.Core.Models; using Umbraco.Core.Persistence.Repositories.Implement; using Umbraco.Core.Services; using Umbraco.Core.Services.Implement; +using Umbraco.Tests.Common.Builders; using Umbraco.Tests.TestHelpers.Entities; using Umbraco.Tests.Testing; @@ -18,10 +20,13 @@ namespace Umbraco.Tests.Services Logger = UmbracoTestOptions.Logger.Console)] public class ContentServiceEventTests : TestWithSomeContentBase { + private GlobalSettings _globalSettings; + public override void SetUp() { base.SetUp(); ContentRepositoryBase.ThrowOnWarning = true; + _globalSettings = new GlobalSettingsBuilder().Build(); } public override void TearDown() @@ -35,7 +40,7 @@ namespace Umbraco.Tests.Services { var languageService = ServiceContext.LocalizationService; - languageService.Save(new Language(TestObjects.GetGlobalSettings(), "fr-FR")); + languageService.Save(new Language(_globalSettings, "fr-FR")); var contentTypeService = ServiceContext.ContentTypeService; @@ -146,7 +151,7 @@ namespace Umbraco.Tests.Services { var languageService = ServiceContext.LocalizationService; - languageService.Save(new Language(TestObjects.GetGlobalSettings(), "fr-FR")); + languageService.Save(new Language(_globalSettings, "fr-FR")); var contentTypeService = ServiceContext.ContentTypeService; @@ -312,7 +317,7 @@ namespace Umbraco.Tests.Services { var languageService = ServiceContext.LocalizationService; - languageService.Save(new Language(TestObjects.GetGlobalSettings(), "fr-FR")); + languageService.Save(new Language(_globalSettings, "fr-FR")); var contentTypeService = ServiceContext.ContentTypeService; diff --git a/src/Umbraco.Tests/Services/ContentServicePublishBranchTests.cs b/src/Umbraco.Tests/Services/ContentServicePublishBranchTests.cs index d856f3bd82..35bbaa5f68 100644 --- a/src/Umbraco.Tests/Services/ContentServicePublishBranchTests.cs +++ b/src/Umbraco.Tests/Services/ContentServicePublishBranchTests.cs @@ -5,6 +5,7 @@ using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Models; using Umbraco.Core.Services; +using Umbraco.Tests.Common.Builders; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.Testing; @@ -425,11 +426,13 @@ namespace Umbraco.Tests.Services private void CreateTypes(out IContentType iContentType, out IContentType vContentType) { - var langDe = new Language(TestObjects.GetGlobalSettings(), "de") { IsDefault = true }; + var globalSettings = new GlobalSettingsBuilder().Build(); + + var langDe = new Language(globalSettings, "de") { IsDefault = true }; ServiceContext.LocalizationService.Save(langDe); - var langRu = new Language(TestObjects.GetGlobalSettings(), "ru"); + var langRu = new Language(globalSettings, "ru"); ServiceContext.LocalizationService.Save(langRu); - var langEs = new Language(TestObjects.GetGlobalSettings(), "es"); + var langEs = new Language(globalSettings, "es"); ServiceContext.LocalizationService.Save(langEs); iContentType = new ContentType(ShortStringHelper, -1) diff --git a/src/Umbraco.Tests/Services/ContentServiceTagsTests.cs b/src/Umbraco.Tests/Services/ContentServiceTagsTests.cs index 5e2c3823af..10bd82cbde 100644 --- a/src/Umbraco.Tests/Services/ContentServiceTagsTests.cs +++ b/src/Umbraco.Tests/Services/ContentServiceTagsTests.cs @@ -9,6 +9,8 @@ using Umbraco.Core.PropertyEditors; using Umbraco.Core.Services; using Umbraco.Tests.TestHelpers.Entities; using Umbraco.Tests.Testing; +using Umbraco.Core.Configuration.Models; +using Umbraco.Tests.Common.Builders; namespace Umbraco.Tests.Services { @@ -19,12 +21,15 @@ namespace Umbraco.Tests.Services Logger = UmbracoTestOptions.Logger.Console)] public class ContentServiceTagsTests : TestWithSomeContentBase { + private GlobalSettings _globalSettings; + public PropertyEditorCollection PropertyEditorCollection => Factory.GetInstance(); public override void SetUp() { base.SetUp(); ContentRepositoryBase.ThrowOnWarning = true; + _globalSettings = new GlobalSettingsBuilder().Build(); } public override void TearDown() @@ -81,7 +86,7 @@ namespace Umbraco.Tests.Services public void TagsCanBeVariant() { var languageService = ServiceContext.LocalizationService; - languageService.Save(new Language(TestObjects.GetGlobalSettings(), "fr-FR")); // en-US is already there + languageService.Save(new Language(_globalSettings, "fr-FR")); // en-US is already there var contentService = ServiceContext.ContentService; var contentTypeService = ServiceContext.ContentTypeService; @@ -205,7 +210,7 @@ namespace Umbraco.Tests.Services public void TagsCanBecomeInvariant() { var languageService = ServiceContext.LocalizationService; - languageService.Save(new Language(TestObjects.GetGlobalSettings(), "fr-FR")); // en-US is already there + languageService.Save(new Language(_globalSettings, "fr-FR")); // en-US is already there var enId = ServiceContext.LocalizationService.GetLanguageIdByIsoCode("en-US").Value; @@ -262,7 +267,7 @@ namespace Umbraco.Tests.Services public void TagsCanBecomeInvariant2() { var languageService = ServiceContext.LocalizationService; - languageService.Save(new Language(TestObjects.GetGlobalSettings(), "fr-FR")); // en-US is already there + languageService.Save(new Language(_globalSettings, "fr-FR")); // en-US is already there var enId = ServiceContext.LocalizationService.GetLanguageIdByIsoCode("en-US").Value; @@ -309,7 +314,7 @@ namespace Umbraco.Tests.Services public void TagsCanBecomeInvariantByPropertyType() { var languageService = ServiceContext.LocalizationService; - languageService.Save(new Language(TestObjects.GetGlobalSettings(), "fr-FR")); // en-US is already there + languageService.Save(new Language(_globalSettings, "fr-FR")); // en-US is already there var enId = ServiceContext.LocalizationService.GetLanguageIdByIsoCode("en-US").Value; @@ -366,7 +371,7 @@ namespace Umbraco.Tests.Services public void TagsCanBecomeInvariantByPropertyTypeAndBackToVariant() { var languageService = ServiceContext.LocalizationService; - languageService.Save(new Language(TestObjects.GetGlobalSettings(), "fr-FR")); // en-US is already there + languageService.Save(new Language(_globalSettings, "fr-FR")); // en-US is already there var enId = ServiceContext.LocalizationService.GetLanguageIdByIsoCode("en-US").Value; diff --git a/src/Umbraco.Tests/Services/ContentServiceTests.cs b/src/Umbraco.Tests/Services/ContentServiceTests.cs index c8467b057f..82d7235388 100644 --- a/src/Umbraco.Tests/Services/ContentServiceTests.cs +++ b/src/Umbraco.Tests/Services/ContentServiceTests.cs @@ -6,20 +6,21 @@ using System.Threading; using Moq; using NUnit.Framework; using Umbraco.Core; +using Umbraco.Core.Cache; +using Umbraco.Core.Configuration.Models; +using Umbraco.Core.Events; using Umbraco.Core.Models; using Umbraco.Core.Models.Membership; -using Umbraco.Core.Services; -using Umbraco.Tests.TestHelpers.Entities; -using Umbraco.Core.Events; using Umbraco.Core.Persistence.Dtos; using Umbraco.Core.Persistence.Repositories.Implement; -using Umbraco.Core.Scoping; -using Umbraco.Core.Services.Implement; -using Umbraco.Tests.Testing; -using Umbraco.Core.Persistence.DatabaseModelDefinitions; -using Umbraco.Core.Cache; using Umbraco.Core.PropertyEditors; +using Umbraco.Core.Scoping; +using Umbraco.Core.Services; +using Umbraco.Core.Services.Implement; +using Umbraco.Tests.Common.Builders; using Umbraco.Tests.LegacyXmlPublishedCache; +using Umbraco.Tests.TestHelpers.Entities; +using Umbraco.Tests.Testing; namespace Umbraco.Tests.Services { @@ -39,10 +40,13 @@ namespace Umbraco.Tests.Services // TODO: Add test to verify there is only ONE newest document/content in {Constants.DatabaseSchema.Tables.Document} table after updating. // TODO: Add test to delete specific version (with and without deleting prior versions) and versions by date. + private GlobalSettings _globalSettings; + public override void SetUp() { base.SetUp(); ContentRepositoryBase.ThrowOnWarning = true; + _globalSettings = new GlobalSettingsBuilder().Build(); } public override void TearDown() @@ -172,8 +176,8 @@ namespace Umbraco.Tests.Services [Test] public void Perform_Scheduled_Publishing() { - var langUk = new Language(TestObjects.GetGlobalSettings(), "en-GB") { IsDefault = true }; - var langFr = new Language(TestObjects.GetGlobalSettings(), "fr-FR"); + var langUk = new Language(_globalSettings, "en-GB") { IsDefault = true }; + var langFr = new Language(_globalSettings, "fr-FR"); ServiceContext.LocalizationService.Save(langFr); ServiceContext.LocalizationService.Save(langUk); @@ -507,7 +511,7 @@ namespace Umbraco.Tests.Services [Test] public void Can_Save_New_Content_With_Explicit_User() { - var user = new User(TestObjects.GetGlobalSettings()) + var user = new User(_globalSettings) { Name = "Test", Email = "test@test.com", @@ -876,8 +880,8 @@ namespace Umbraco.Tests.Services [Test] public void Unpublishing_Mandatory_Language_Unpublishes_Document() { - var langUk = new Language(TestObjects.GetGlobalSettings(), "en-GB") { IsDefault = true, IsMandatory = true }; - var langFr = new Language(TestObjects.GetGlobalSettings(), "fr-FR"); + var langUk = new Language(_globalSettings, "en-GB") { IsDefault = true, IsMandatory = true }; + var langFr = new Language(_globalSettings, "fr-FR"); ServiceContext.LocalizationService.Save(langFr); ServiceContext.LocalizationService.Save(langUk); @@ -973,8 +977,8 @@ namespace Umbraco.Tests.Services { // Arrange - var langGB = new Language(TestObjects.GetGlobalSettings(), "en-GB") { IsDefault = true }; - var langFr = new Language(TestObjects.GetGlobalSettings(), "fr-FR"); + var langGB = new Language(_globalSettings, "en-GB") { IsDefault = true }; + var langFr = new Language(_globalSettings, "fr-FR"); ServiceContext.LocalizationService.Save(langFr); ServiceContext.LocalizationService.Save(langGB); @@ -1041,8 +1045,8 @@ namespace Umbraco.Tests.Services { // Arrange - var langGB = new Language(TestObjects.GetGlobalSettings(), "en-GB") { IsDefault = true, IsMandatory = true }; - var langFr = new Language(TestObjects.GetGlobalSettings(), "fr-FR"); + var langGB = new Language(_globalSettings, "en-GB") { IsDefault = true, IsMandatory = true }; + var langFr = new Language(_globalSettings, "fr-FR"); ServiceContext.LocalizationService.Save(langFr); ServiceContext.LocalizationService.Save(langGB); @@ -1220,8 +1224,8 @@ namespace Umbraco.Tests.Services { //TODO: This is using an internal API - we aren't exposing this publicly (at least for now) but we'll keep the test around - var langFr = new Language(TestObjects.GetGlobalSettings(), "fr"); - var langDa = new Language(TestObjects.GetGlobalSettings(), "da"); + var langFr = new Language(_globalSettings, "fr"); + var langDa = new Language(_globalSettings, "da"); ServiceContext.LocalizationService.Save(langFr); ServiceContext.LocalizationService.Save(langDa); @@ -2156,8 +2160,8 @@ namespace Umbraco.Tests.Services [Test] public void Can_Rollback_Version_On_Multilingual() { - var langFr = new Language(TestObjects.GetGlobalSettings(), "fr"); - var langDa = new Language(TestObjects.GetGlobalSettings(), "da"); + var langFr = new Language(_globalSettings, "fr"); + var langDa = new Language(_globalSettings, "da"); ServiceContext.LocalizationService.Save(langFr); ServiceContext.LocalizationService.Save(langDa); @@ -2683,8 +2687,8 @@ namespace Umbraco.Tests.Services { var languageService = ServiceContext.LocalizationService; - var langUk = new Language(TestObjects.GetGlobalSettings(), "en-GB") { IsDefault = true }; - var langFr = new Language(TestObjects.GetGlobalSettings(), "fr-FR"); + var langUk = new Language(_globalSettings, "en-GB") { IsDefault = true }; + var langFr = new Language(_globalSettings, "fr-FR"); languageService.Save(langFr); languageService.Save(langUk); @@ -2718,8 +2722,8 @@ namespace Umbraco.Tests.Services { var languageService = ServiceContext.LocalizationService; - var langUk = new Language(TestObjects.GetGlobalSettings(), "en-GB") { IsDefault = true }; - var langFr = new Language(TestObjects.GetGlobalSettings(), "fr-FR"); + var langUk = new Language(_globalSettings, "en-GB") { IsDefault = true }; + var langFr = new Language(_globalSettings, "fr-FR"); languageService.Save(langFr); languageService.Save(langUk); @@ -2755,9 +2759,9 @@ namespace Umbraco.Tests.Services { var languageService = ServiceContext.LocalizationService; - var langUk = new Language(TestObjects.GetGlobalSettings(), "en-GB") { IsDefault = true }; - var langFr = new Language(TestObjects.GetGlobalSettings(), "fr-FR"); - var langDa = new Language(TestObjects.GetGlobalSettings(), "da-DK"); + var langUk = new Language(_globalSettings, "en-GB") { IsDefault = true }; + var langFr = new Language(_globalSettings, "fr-FR"); + var langDa = new Language(_globalSettings, "da-DK"); languageService.Save(langFr); languageService.Save(langUk); @@ -2857,10 +2861,10 @@ namespace Umbraco.Tests.Services var languageService = ServiceContext.LocalizationService; //var langFr = new Language("fr-FR") { IsDefaultVariantLanguage = true }; - var langXx = new Language(TestObjects.GetGlobalSettings(), "pt-PT") { IsDefault = true }; - var langFr = new Language(TestObjects.GetGlobalSettings(), "fr-FR"); - var langUk = new Language(TestObjects.GetGlobalSettings(), "en-GB"); - var langDe = new Language(TestObjects.GetGlobalSettings(), "de-DE"); + var langXx = new Language(_globalSettings, "pt-PT") { IsDefault = true }; + var langFr = new Language(_globalSettings, "fr-FR"); + var langUk = new Language(_globalSettings, "en-GB"); + var langDe = new Language(_globalSettings, "de-DE"); languageService.Save(langFr); languageService.Save(langUk); @@ -3246,7 +3250,7 @@ namespace Umbraco.Tests.Services var templateRepository = new TemplateRepository(accessor, AppCaches.Disabled, Logger, TestObjects.GetFileSystemsMock(), IOHelper, ShortStringHelper); var tagRepository = new TagRepository(accessor, AppCaches.Disabled, Logger); var commonRepository = new ContentTypeCommonRepository(accessor, templateRepository, AppCaches, ShortStringHelper); - var languageRepository = new LanguageRepository(accessor, AppCaches.Disabled, Logger, TestObjects.GetGlobalSettings()); + var languageRepository = new LanguageRepository(accessor, AppCaches.Disabled, Logger, Microsoft.Extensions.Options.Options.Create(_globalSettings)); contentTypeRepository = new ContentTypeRepository(accessor, AppCaches.Disabled, Logger, commonRepository, languageRepository, ShortStringHelper); var relationTypeRepository = new RelationTypeRepository(accessor, AppCaches.Disabled, Logger); var entityRepository = new EntityRepository(accessor); @@ -3259,8 +3263,8 @@ namespace Umbraco.Tests.Services private void CreateEnglishAndFrenchDocumentType(out Language langUk, out Language langFr, out ContentType contentType) { - langUk = new Language(TestObjects.GetGlobalSettings(), "en-GB") { IsDefault = true }; - langFr = new Language(TestObjects.GetGlobalSettings(), "fr-FR"); + langUk = new Language(_globalSettings, "en-GB") { IsDefault = true }; + langFr = new Language(_globalSettings, "fr-FR"); ServiceContext.LocalizationService.Save(langFr); ServiceContext.LocalizationService.Save(langUk); diff --git a/src/Umbraco.Tests/Services/ContentTypeServiceVariantsTests.cs b/src/Umbraco.Tests/Services/ContentTypeServiceVariantsTests.cs index ab9f85aa3c..5830513fbd 100644 --- a/src/Umbraco.Tests/Services/ContentTypeServiceVariantsTests.cs +++ b/src/Umbraco.Tests/Services/ContentTypeServiceVariantsTests.cs @@ -19,6 +19,7 @@ using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Services; using Umbraco.Core.Strings; using Umbraco.Core.Sync; +using Umbraco.Tests.Common.Builders; using Umbraco.Tests.Strings; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.TestHelpers.Entities; @@ -59,7 +60,9 @@ namespace Umbraco.Tests.Services var hostingEnvironment = Mock.Of(); var typeFinder = TestHelper.GetTypeFinder(); - var settings = Mock.Of(); + + var globalSettings = new GlobalSettingsBuilder().Build(); + var nuCacheSettings = new NuCacheSettingsBuilder().Build(); return new PublishedSnapshotService( options, @@ -74,14 +77,14 @@ namespace Umbraco.Tests.Services documentRepository, mediaRepository, memberRepository, DefaultCultureAccessor, new DatabaseDataSource(Mock.Of()), - Factory.GetInstance(), + Microsoft.Extensions.Options.Options.Create(globalSettings), Factory.GetInstance(), Mock.Of(), new UrlSegmentProviderCollection(new[] { new DefaultUrlSegmentProvider(ShortStringHelper) }), hostingEnvironment, new MockShortStringHelper(), IOHelper, - settings); + Microsoft.Extensions.Options.Options.Create(nuCacheSettings)); } public class LocalServerMessenger : ServerMessengerBase @@ -310,7 +313,9 @@ namespace Umbraco.Tests.Services var nlContentName = "Content nl-NL"; var nlCulture = "nl-NL"; - ServiceContext.LocalizationService.Save(new Language(TestObjects.GetGlobalSettings(), nlCulture)); + var globalSettings = new GlobalSettingsBuilder().Build(); + + ServiceContext.LocalizationService.Save(new Language(globalSettings, nlCulture)); var includeCultureNames = contentType.Variations.HasFlag(ContentVariation.Culture); @@ -666,9 +671,11 @@ namespace Umbraco.Tests.Services // can change it to variant and back // can then switch one property to variant - var languageEn = new Language(TestObjects.GetGlobalSettings(), "en") { IsDefault = true }; + var globalSettings = new GlobalSettingsBuilder().Build(); + + var languageEn = new Language(globalSettings, "en") { IsDefault = true }; ServiceContext.LocalizationService.Save(languageEn); - var languageFr = new Language(TestObjects.GetGlobalSettings(), "fr"); + var languageFr = new Language(globalSettings, "fr"); ServiceContext.LocalizationService.Save(languageFr); var contentType = CreateContentType(ContentVariation.Nothing); @@ -1259,9 +1266,10 @@ namespace Umbraco.Tests.Services private void CreateFrenchAndEnglishLangs() { - var languageEn = new Language(TestObjects.GetGlobalSettings(), "en") { IsDefault = true }; + var globalSettings = new GlobalSettingsBuilder().Build(); + var languageEn = new Language(globalSettings, "en") { IsDefault = true }; ServiceContext.LocalizationService.Save(languageEn); - var languageFr = new Language(TestObjects.GetGlobalSettings(), "fr"); + var languageFr = new Language(globalSettings, "fr"); ServiceContext.LocalizationService.Save(languageFr); } diff --git a/src/Umbraco.Tests/Services/EntityServiceTests.cs b/src/Umbraco.Tests/Services/EntityServiceTests.cs index fb802420d5..8be2dcc962 100644 --- a/src/Umbraco.Tests/Services/EntityServiceTests.cs +++ b/src/Umbraco.Tests/Services/EntityServiceTests.cs @@ -8,6 +8,7 @@ using Umbraco.Core.Models; using Umbraco.Core.Models.Entities; using Umbraco.Core.Persistence.DatabaseModelDefinitions; using Umbraco.Core.Services; +using Umbraco.Tests.Common.Builders; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.TestHelpers.Entities; using Umbraco.Tests.Testing; @@ -31,8 +32,9 @@ namespace Umbraco.Tests.Services if (_langFr == null && _langEs == null) { - _langFr = new Language(SettingsForTests.GenerateMockGlobalSettings(), "fr-FR"); - _langEs = new Language(SettingsForTests.GenerateMockGlobalSettings(), "es-ES"); + var globalSettings = new GlobalSettingsBuilder().Build(); + _langFr = new Language(globalSettings, "fr-FR"); + _langEs = new Language(globalSettings, "es-ES"); ServiceContext.LocalizationService.Save(_langFr); ServiceContext.LocalizationService.Save(_langEs); } diff --git a/src/Umbraco.Tests/Services/EntityXmlSerializerTests.cs b/src/Umbraco.Tests/Services/EntityXmlSerializerTests.cs index e10dd99482..8497208d93 100644 --- a/src/Umbraco.Tests/Services/EntityXmlSerializerTests.cs +++ b/src/Umbraco.Tests/Services/EntityXmlSerializerTests.cs @@ -4,9 +4,10 @@ using System.Linq; using System.Xml.Linq; using NUnit.Framework; using Umbraco.Core; -using Umbraco.Core.Composing; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Models; using Umbraco.Core.Services; +using Umbraco.Tests.Common.Builders; using Umbraco.Tests.Services.Importing; using Umbraco.Tests.Testing; @@ -17,6 +18,13 @@ namespace Umbraco.Tests.Services public class EntityXmlSerializerTests : TestWithSomeContentBase { private IEntityXmlSerializer Serializer => Factory.GetInstance(); + private GlobalSettings _globalSettings; + + public override void SetUp() + { + base.SetUp(); + _globalSettings = new GlobalSettingsBuilder().Build(); + } [Test] public void Can_Export_Macro() @@ -56,10 +64,10 @@ namespace Umbraco.Tests.Services public void Can_Export_Languages() { // Arrange - var languageNbNo = new Language(TestObjects.GetGlobalSettings(), "nb-NO") { CultureName = "Norwegian" }; + var languageNbNo = new Language(_globalSettings, "nb-NO") { CultureName = "Norwegian" }; ServiceContext.LocalizationService.Save(languageNbNo); - var languageEnGb = new Language(TestObjects.GetGlobalSettings(), "en-GB") { CultureName = "English (United Kingdom)" }; + var languageEnGb = new Language(_globalSettings, "en-GB") { CultureName = "English (United Kingdom)" }; ServiceContext.LocalizationService.Save(languageEnGb); var newPackageXml = XElement.Parse(ImportResources.Dictionary_Package); @@ -74,10 +82,10 @@ namespace Umbraco.Tests.Services private void CreateDictionaryData() { - var languageNbNo = new Language(TestObjects.GetGlobalSettings(), "nb-NO") { CultureName = "nb-NO" }; + var languageNbNo = new Language(_globalSettings, "nb-NO") { CultureName = "nb-NO" }; ServiceContext.LocalizationService.Save(languageNbNo); - var languageEnGb = new Language(TestObjects.GetGlobalSettings(), "en-GB") { CultureName = "en-GB" }; + var languageEnGb = new Language(_globalSettings, "en-GB") { CultureName = "en-GB" }; ServiceContext.LocalizationService.Save(languageEnGb); var parentItem = new DictionaryItem("Parent"); diff --git a/src/Umbraco.Tests/Services/LocalizationServiceTests.cs b/src/Umbraco.Tests/Services/LocalizationServiceTests.cs index c5ff549ee3..2785cdea27 100644 --- a/src/Umbraco.Tests/Services/LocalizationServiceTests.cs +++ b/src/Umbraco.Tests/Services/LocalizationServiceTests.cs @@ -9,6 +9,8 @@ using Umbraco.Core.Models; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.Testing; using Umbraco.Core.Persistence; +using Umbraco.Core.Configuration.Models; +using Umbraco.Tests.Common.Builders; namespace Umbraco.Tests.Services { @@ -29,6 +31,14 @@ namespace Umbraco.Tests.Services private int _danishLangId; private int _englishLangId; + private GlobalSettings _globalSettings; + + public override void SetUp() + { + base.SetUp(); + _globalSettings = new GlobalSettingsBuilder().Build(); + } + [Test] public void Can_Get_Root_Dictionary_Items() { @@ -181,7 +191,7 @@ namespace Umbraco.Tests.Services [Test] public void Can_Delete_Language() { - var norwegian = new Language(TestObjects.GetGlobalSettings(), "nb-NO") { CultureName = "Norwegian" }; + var norwegian = new Language(_globalSettings, "nb-NO") { CultureName = "Norwegian" }; ServiceContext.LocalizationService.Save(norwegian, 0); Assert.That(norwegian.HasIdentity, Is.True); var languageId = norwegian.Id; @@ -196,7 +206,7 @@ namespace Umbraco.Tests.Services public void Can_Delete_Language_Used_As_Fallback() { var danish = ServiceContext.LocalizationService.GetLanguageByIsoCode("da-DK"); - var norwegian = new Language(TestObjects.GetGlobalSettings(), "nb-NO") { CultureName = "Norwegian", FallbackLanguageId = danish.Id }; + var norwegian = new Language(_globalSettings, "nb-NO") { CultureName = "Norwegian", FallbackLanguageId = danish.Id }; ServiceContext.LocalizationService.Save(norwegian, 0); var languageId = danish.Id; @@ -346,7 +356,7 @@ namespace Umbraco.Tests.Services // Arrange var localizationService = ServiceContext.LocalizationService; var isoCode = "en-AU"; - var language = new Core.Models.Language(TestObjects.GetGlobalSettings(), isoCode); + var language = new Core.Models.Language(_globalSettings, isoCode); // Act localizationService.Save(language); @@ -361,7 +371,7 @@ namespace Umbraco.Tests.Services { var localizationService = ServiceContext.LocalizationService; var isoCode = "en-AU"; - var language = new Core.Models.Language(TestObjects.GetGlobalSettings(), isoCode); + var language = new Core.Models.Language(_globalSettings, isoCode); // Act localizationService.Save(language); @@ -375,14 +385,14 @@ namespace Umbraco.Tests.Services public void Set_Default_Language() { var localizationService = ServiceContext.LocalizationService; - var language = new Core.Models.Language(TestObjects.GetGlobalSettings(), "en-AU"); + var language = new Core.Models.Language(_globalSettings, "en-AU"); language.IsDefault = true; localizationService.Save(language); var result = localizationService.GetLanguageById(language.Id); Assert.IsTrue(result.IsDefault); - var language2 = new Core.Models.Language(TestObjects.GetGlobalSettings(), "en-NZ"); + var language2 = new Core.Models.Language(_globalSettings, "en-NZ"); language2.IsDefault = true; localizationService.Save(language2); var result2 = localizationService.GetLanguageById(language2.Id); @@ -398,7 +408,7 @@ namespace Umbraco.Tests.Services { var localizationService = ServiceContext.LocalizationService; var isoCode = "en-AU"; - var language = new Core.Models.Language(TestObjects.GetGlobalSettings(), isoCode); + var language = new Core.Models.Language(_globalSettings, isoCode); localizationService.Save(language); // Act @@ -411,8 +421,8 @@ namespace Umbraco.Tests.Services public override void CreateTestData() { - var danish = new Language(TestObjects.GetGlobalSettings(), "da-DK") { CultureName = "Danish" }; - var english = new Language(TestObjects.GetGlobalSettings(), "en-GB") { CultureName = "English" }; + var danish = new Language(_globalSettings, "da-DK") { CultureName = "Danish" }; + var english = new Language(_globalSettings, "en-GB") { CultureName = "English" }; ServiceContext.LocalizationService.Save(danish, 0); ServiceContext.LocalizationService.Save(english, 0); _danishLangId = danish.Id; diff --git a/src/Umbraco.Tests/Services/SectionServiceTests.cs b/src/Umbraco.Tests/Services/SectionServiceTests.cs index 80a4de4bfe..82fda67003 100644 --- a/src/Umbraco.Tests/Services/SectionServiceTests.cs +++ b/src/Umbraco.Tests/Services/SectionServiceTests.cs @@ -4,6 +4,7 @@ using System.Threading; using Umbraco.Core; using Umbraco.Core.Composing; using Umbraco.Core.Models.Membership; +using Umbraco.Tests.Common.Builders; using Umbraco.Tests.Testing; using Umbraco.Web.Services; @@ -34,7 +35,8 @@ namespace Umbraco.Tests.Services private IUser CreateTestUser() { - var user = new User(TestObjects.GetGlobalSettings()) + var globalSettings = new GlobalSettingsBuilder().Build(); + var user = new User(globalSettings) { Name = "Test user", Username = "testUser", diff --git a/src/Umbraco.Tests/Services/UserServiceTests.cs b/src/Umbraco.Tests/Services/UserServiceTests.cs index dbd71870d4..a8a611d524 100644 --- a/src/Umbraco.Tests/Services/UserServiceTests.cs +++ b/src/Umbraco.Tests/Services/UserServiceTests.cs @@ -15,7 +15,7 @@ using Umbraco.Core.Services; using Umbraco.Core.Services.Implement; using Umbraco.Tests.Testing; using Umbraco.Web.Actions; - +using Umbraco.Tests.Common.Builders; namespace Umbraco.Tests.Services { @@ -721,7 +721,8 @@ namespace Umbraco.Tests.Services var hash = new HMACSHA1(); hash.Key = Encoding.Unicode.GetBytes(password); var encodedPassword = Convert.ToBase64String(hash.ComputeHash(Encoding.Unicode.GetBytes(password))); - var membershipUser = new User(TestObjects.GetGlobalSettings(), "JohnDoe", "john@umbraco.io", encodedPassword, encodedPassword); + var globalSettings = new GlobalSettingsBuilder().Build(); + var membershipUser = new User(globalSettings, "JohnDoe", "john@umbraco.io", encodedPassword, encodedPassword); userService.Save(membershipUser); // Assert diff --git a/src/Umbraco.Tests/Strings/DefaultShortStringHelperTests.cs b/src/Umbraco.Tests/Strings/DefaultShortStringHelperTests.cs index 109142f51b..0def86e8d2 100644 --- a/src/Umbraco.Tests/Strings/DefaultShortStringHelperTests.cs +++ b/src/Umbraco.Tests/Strings/DefaultShortStringHelperTests.cs @@ -7,8 +7,10 @@ using Moq; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Composing; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Strings; +using Umbraco.Tests.Common.Builders; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.Testing; @@ -17,6 +19,7 @@ namespace Umbraco.Tests.Strings [TestFixture] public class DefaultShortStringHelperTests : UmbracoTestBase { + private RequestHandlerSettings _requestHandlerSettings; private DefaultShortStringHelper _helper; public override void SetUp() @@ -25,8 +28,8 @@ namespace Umbraco.Tests.Strings // NOTE pre-filters runs _before_ Recode takes place // so there still may be utf8 chars even though you want ascii - - _helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(SettingsForTests.GenerateMockRequestHandlerSettings()) + _requestHandlerSettings = new RequestHandlerSettingsBuilder().Build(); + _helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(_requestHandlerSettings) .WithConfig(CleanStringType.FileName, new DefaultShortStringHelperConfig.Config { //PreFilter = ClearFileChars, // done in IsTerm @@ -94,18 +97,18 @@ namespace Umbraco.Tests.Strings [Test] public void U4_4056() { - var settings = SettingsForTests.GenerateMockRequestHandlerSettings(); - var contentMock = Mock.Get(settings); - contentMock.Setup(x => x.CharCollection).Returns(Enumerable.Empty()); - contentMock.Setup(x => x.ConvertUrlsToAscii).Returns(false); + var requestHandlerSettings = new RequestHandlerSettingsBuilder() + .WithConvertUrlsToAscii(false) + .WithCharCollection(Enumerable.Empty()) + .Build(); const string input = "ÆØÅ and æøå and 中文测试 and אודות האתר and größer БбДдЖж page"; - var helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(settings)); // unicode + var helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(requestHandlerSettings)); // unicode var output = helper.CleanStringForUrlSegment(input); Assert.AreEqual("æøå-and-æøå-and-中文测试-and-אודות-האתר-and-größer-ббдджж-page", output); - helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(settings) + helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(requestHandlerSettings) .WithConfig(CleanStringType.UrlSegment, new DefaultShortStringHelperConfig.Config { IsTerm = (c, leading) => char.IsLetterOrDigit(c) || c == '_', @@ -119,19 +122,19 @@ namespace Umbraco.Tests.Strings [Test] public void U4_4056_TryAscii() { - var settings = SettingsForTests.GenerateMockRequestHandlerSettings(); - var contentMock = Mock.Get(settings); - contentMock.Setup(x => x.CharCollection).Returns(Enumerable.Empty()); - contentMock.Setup(x => x.ConvertUrlsToAscii).Returns(false); + var requestHandlerSettings = new RequestHandlerSettingsBuilder() + .WithConvertUrlsToAscii(false) + .WithCharCollection(Enumerable.Empty()) + .Build(); const string input1 = "ÆØÅ and æøå and 中文测试 and אודות האתר and größer БбДдЖж page"; const string input2 = "ÆØÅ and æøå and größer БбДдЖж page"; - var helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(settings)); // unicode + var helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(requestHandlerSettings)); // unicode Assert.AreEqual("æøå-and-æøå-and-中文测试-and-אודות-האתר-and-größer-ббдджж-page", helper.CleanStringForUrlSegment(input1)); Assert.AreEqual("æøå-and-æøå-and-größer-ббдджж-page", helper.CleanStringForUrlSegment(input2)); - helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(settings) + helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(requestHandlerSettings) .WithConfig(CleanStringType.UrlSegment, new DefaultShortStringHelperConfig.Config { IsTerm = (c, leading) => char.IsLetterOrDigit(c) || c == '_', @@ -145,7 +148,7 @@ namespace Umbraco.Tests.Strings [Test] public void CleanStringUnderscoreInTerm() { - var helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(SettingsForTests.GenerateMockRequestHandlerSettings()) + var helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(_requestHandlerSettings) .WithConfig(CleanStringType.Alias, new DefaultShortStringHelperConfig.Config { // underscore is accepted within terms @@ -155,7 +158,7 @@ namespace Umbraco.Tests.Strings })); Assert.AreEqual("foo_bar*nil", helper.CleanString("foo_bar nil", CleanStringType.Alias)); - helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(SettingsForTests.GenerateMockRequestHandlerSettings()) + helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(_requestHandlerSettings) .WithConfig(CleanStringType.Alias, new DefaultShortStringHelperConfig.Config { // underscore is not accepted within terms @@ -169,7 +172,7 @@ namespace Umbraco.Tests.Strings [Test] public void CleanStringLeadingChars() { - var helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(SettingsForTests.GenerateMockRequestHandlerSettings()) + var helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(_requestHandlerSettings) .WithConfig(CleanStringType.Alias, new DefaultShortStringHelperConfig.Config { // letters and digits are valid leading chars @@ -179,7 +182,7 @@ namespace Umbraco.Tests.Strings })); Assert.AreEqual("0123foo*bar*543*nil*321", helper.CleanString("0123foo_bar 543 nil 321", CleanStringType.Alias)); - helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(SettingsForTests.GenerateMockRequestHandlerSettings()) + helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(_requestHandlerSettings) .WithConfig(CleanStringType.Alias, new DefaultShortStringHelperConfig.Config { // only letters are valid leading chars @@ -190,14 +193,14 @@ namespace Umbraco.Tests.Strings Assert.AreEqual("foo*bar*543*nil*321", helper.CleanString("0123foo_bar 543 nil 321", CleanStringType.Alias)); Assert.AreEqual("foo*bar*543*nil*321", helper.CleanString("0123 foo_bar 543 nil 321", CleanStringType.Alias)); - helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(SettingsForTests.GenerateMockRequestHandlerSettings())); + helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(_requestHandlerSettings)); Assert.AreEqual("child2", helper.CleanStringForSafeAlias("1child2")); } [Test] public void CleanStringTermOnUpper() { - var helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(SettingsForTests.GenerateMockRequestHandlerSettings()) + var helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(_requestHandlerSettings) .WithConfig(CleanStringType.Alias, new DefaultShortStringHelperConfig.Config { StringType = CleanStringType.Utf8 | CleanStringType.Unchanged, @@ -207,7 +210,7 @@ namespace Umbraco.Tests.Strings })); Assert.AreEqual("foo*Bar", helper.CleanString("fooBar", CleanStringType.Alias)); - helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(SettingsForTests.GenerateMockRequestHandlerSettings()) + helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(_requestHandlerSettings) .WithConfig(CleanStringType.Alias, new DefaultShortStringHelperConfig.Config { StringType = CleanStringType.Utf8 | CleanStringType.Unchanged, @@ -221,7 +224,7 @@ namespace Umbraco.Tests.Strings [Test] public void CleanStringAcronymOnNonUpper() { - var helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(SettingsForTests.GenerateMockRequestHandlerSettings()) + var helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(_requestHandlerSettings) .WithConfig(CleanStringType.Alias, new DefaultShortStringHelperConfig.Config { StringType = CleanStringType.Utf8 | CleanStringType.Unchanged, @@ -234,7 +237,7 @@ namespace Umbraco.Tests.Strings Assert.AreEqual("foo*BAnil", helper.CleanString("foo BAnil", CleanStringType.Alias)); Assert.AreEqual("foo*Bnil", helper.CleanString("foo Bnil", CleanStringType.Alias)); - helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(SettingsForTests.GenerateMockRequestHandlerSettings()) + helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(_requestHandlerSettings) .WithConfig(CleanStringType.Alias, new DefaultShortStringHelperConfig.Config { StringType = CleanStringType.Utf8 | CleanStringType.Unchanged, @@ -251,7 +254,7 @@ namespace Umbraco.Tests.Strings [Test] public void CleanStringGreedyAcronyms() { - var helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(SettingsForTests.GenerateMockRequestHandlerSettings()) + var helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(_requestHandlerSettings) .WithConfig(CleanStringType.Alias, new DefaultShortStringHelperConfig.Config { StringType = CleanStringType.Utf8 | CleanStringType.Unchanged, @@ -264,7 +267,7 @@ namespace Umbraco.Tests.Strings Assert.AreEqual("foo*BA*nil", helper.CleanString("foo BAnil", CleanStringType.Alias)); Assert.AreEqual("foo*Bnil", helper.CleanString("foo Bnil", CleanStringType.Alias)); - helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(SettingsForTests.GenerateMockRequestHandlerSettings()) + helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(_requestHandlerSettings) .WithConfig(CleanStringType.Alias, new DefaultShortStringHelperConfig.Config { StringType = CleanStringType.Utf8 | CleanStringType.Unchanged, @@ -281,7 +284,7 @@ namespace Umbraco.Tests.Strings [Test] public void CleanStringWhiteSpace() { - var helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(SettingsForTests.GenerateMockRequestHandlerSettings()) + var helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(_requestHandlerSettings) .WithConfig(CleanStringType.Alias, new DefaultShortStringHelperConfig.Config { StringType = CleanStringType.Utf8 | CleanStringType.Unchanged, @@ -294,7 +297,7 @@ namespace Umbraco.Tests.Strings [Test] public void CleanStringSeparator() { - var helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(SettingsForTests.GenerateMockRequestHandlerSettings()) + var helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(_requestHandlerSettings) .WithConfig(CleanStringType.Alias, new DefaultShortStringHelperConfig.Config { StringType = CleanStringType.Utf8 | CleanStringType.Unchanged, @@ -302,7 +305,7 @@ namespace Umbraco.Tests.Strings })); Assert.AreEqual("foo*bar", helper.CleanString("foo bar", CleanStringType.Alias)); - helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(SettingsForTests.GenerateMockRequestHandlerSettings()) + helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(_requestHandlerSettings) .WithConfig(CleanStringType.Alias, new DefaultShortStringHelperConfig.Config { StringType = CleanStringType.Utf8 | CleanStringType.Unchanged, @@ -310,14 +313,14 @@ namespace Umbraco.Tests.Strings })); Assert.AreEqual("foo bar", helper.CleanString("foo bar", CleanStringType.Alias)); - helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(SettingsForTests.GenerateMockRequestHandlerSettings()) + helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(_requestHandlerSettings) .WithConfig(CleanStringType.Alias, new DefaultShortStringHelperConfig.Config { StringType = CleanStringType.Utf8 | CleanStringType.Unchanged })); Assert.AreEqual("foobar", helper.CleanString("foo bar", CleanStringType.Alias)); - helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(SettingsForTests.GenerateMockRequestHandlerSettings()) + helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(_requestHandlerSettings) .WithConfig(CleanStringType.Alias, new DefaultShortStringHelperConfig.Config { StringType = CleanStringType.Utf8 | CleanStringType.Unchanged, @@ -329,7 +332,7 @@ namespace Umbraco.Tests.Strings [Test] public void CleanStringSymbols() { - var helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(SettingsForTests.GenerateMockRequestHandlerSettings()) + var helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(_requestHandlerSettings) .WithConfig(CleanStringType.Alias, new DefaultShortStringHelperConfig.Config { StringType = CleanStringType.Utf8 | CleanStringType.Unchanged, @@ -383,7 +386,7 @@ namespace Umbraco.Tests.Strings [Test] public void CleanStringEncoding() { - var helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(SettingsForTests.GenerateMockRequestHandlerSettings()) + var helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(_requestHandlerSettings) .WithConfig(CleanStringType.Alias, new DefaultShortStringHelperConfig.Config { StringType = CleanStringType.Utf8 | CleanStringType.Unchanged, @@ -392,7 +395,7 @@ namespace Umbraco.Tests.Strings Assert.AreEqual("中文测试", helper.CleanString("中文测试", CleanStringType.Alias)); Assert.AreEqual("léger*中文测试*ZÔRG", helper.CleanString("léger 中文测试 ZÔRG", CleanStringType.Alias)); - helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(SettingsForTests.GenerateMockRequestHandlerSettings()) + helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(_requestHandlerSettings) .WithConfig(CleanStringType.Alias, new DefaultShortStringHelperConfig.Config { StringType = CleanStringType.Ascii | CleanStringType.Unchanged, @@ -405,7 +408,7 @@ namespace Umbraco.Tests.Strings [Test] public void CleanStringDefaultConfig() { - var settings = SettingsForTests.GenerateMockRequestHandlerSettings(); + var settings = _requestHandlerSettings; var contentMock = Mock.Get(settings); contentMock.Setup(x => x.CharCollection).Returns(Enumerable.Empty()); contentMock.Setup(x => x.ConvertUrlsToAscii).Returns(false); @@ -431,7 +434,7 @@ namespace Umbraco.Tests.Strings [Test] public void CleanStringCasing() { - var helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(SettingsForTests.GenerateMockRequestHandlerSettings()) + var helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(_requestHandlerSettings) .WithConfig(CleanStringType.Alias, new DefaultShortStringHelperConfig.Config { StringType = CleanStringType.Utf8 | CleanStringType.Unchanged, diff --git a/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs b/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs index 6bc228bf83..3faea42f01 100644 --- a/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs +++ b/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs @@ -45,7 +45,7 @@ namespace Umbraco.Tests.TestHelpers logger, false); - var composition = new Composition(container, typeLoader, Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.GetConfigs(), TestHelper.IOHelper, AppCaches.NoCache); + var composition = new Composition(container, typeLoader, Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.IOHelper, AppCaches.NoCache); composition.RegisterUnique(_ => Mock.Of()); composition.RegisterUnique(_ => Mock.Of()); diff --git a/src/Umbraco.Tests/TestHelpers/Entities/MockedUser.cs b/src/Umbraco.Tests/TestHelpers/Entities/MockedUser.cs index 531d87f76f..4977b5d81a 100644 --- a/src/Umbraco.Tests/TestHelpers/Entities/MockedUser.cs +++ b/src/Umbraco.Tests/TestHelpers/Entities/MockedUser.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using Umbraco.Core.Models.Membership; +using Umbraco.Tests.Common.Builders; namespace Umbraco.Tests.TestHelpers.Entities { @@ -23,7 +24,8 @@ namespace Umbraco.Tests.TestHelpers.Entities internal static User CreateUser(string suffix = "") { - var user = new User(SettingsForTests.GenerateMockGlobalSettings()) + var globalSettings = new GlobalSettingsBuilder().Build(); + var user = new User(globalSettings) { Language = "en", IsApproved = true, @@ -41,10 +43,11 @@ namespace Umbraco.Tests.TestHelpers.Entities { var list = new List(); + var globalSettings = new GlobalSettingsBuilder().Build(); for (int i = 0; i < amount; i++) { var name = "Member No-" + i; - var user = new User(SettingsForTests.GenerateMockGlobalSettings(), name, "test" + i + "@test.com", "test" + i, "test" + i); + var user = new User(globalSettings, name, "test" + i + "@test.com", "test" + i, "test" + i); onCreating?.Invoke(i, user); diff --git a/src/Umbraco.Tests/TestHelpers/TestObjects.cs b/src/Umbraco.Tests/TestHelpers/TestObjects.cs index 7e8914f78e..e1c1213e01 100644 --- a/src/Umbraco.Tests/TestHelpers/TestObjects.cs +++ b/src/Umbraco.Tests/TestHelpers/TestObjects.cs @@ -1,12 +1,14 @@ using System; using System.IO; using System.Linq; +using Microsoft.Extensions.Options; using Moq; using NPoco; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Composing; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Events; using Umbraco.Core.Hosting; @@ -23,6 +25,7 @@ using Umbraco.Core.Services; using Umbraco.Core.Services.Implement; using Umbraco.Core.Strings; using Umbraco.Persistance.SqlCe; +using Umbraco.Tests.Common.Builders; using Umbraco.Tests.TestHelpers.Stubs; using Current = Umbraco.Web.Composing.Current; @@ -94,8 +97,8 @@ namespace Umbraco.Tests.TestHelpers AppCaches cache, ILogger logger, IIOHelper ioHelper, - IGlobalSettings globalSettings, - IContentSettings contentSettings, + GlobalSettings globalSettings, + ContentSettings contentSettings, IEventMessagesFactory eventMessagesFactory, UrlSegmentProviderCollection urlSegmentProviders, IUmbracoVersion umbracoVersion, @@ -157,7 +160,7 @@ namespace Umbraco.Tests.TestHelpers var propertyEditorCollection = new PropertyEditorCollection(new DataEditorCollection(Enumerable.Empty())); var localizationService = GetLazyService(factory, c => new LocalizationService(scopeProvider, logger, eventMessagesFactory, GetRepo(c), GetRepo(c), GetRepo(c))); - var userService = GetLazyService(factory, c => new UserService(scopeProvider, logger, eventMessagesFactory, runtimeState, GetRepo(c), GetRepo(c),globalSettings)); + var userService = GetLazyService(factory, c => new UserService(scopeProvider, logger, eventMessagesFactory, runtimeState, GetRepo(c), GetRepo(c), Options.Create(globalSettings))); var dataTypeService = GetLazyService(factory, c => new DataTypeService(scopeProvider, logger, eventMessagesFactory, GetRepo(c), GetRepo(c), GetRepo(c), GetRepo(c), GetRepo(c), ioHelper, localizedTextService.Value, localizationService.Value, TestHelper.ShortStringHelper)); var propertyValidationService = new Lazy(() => new PropertyValidationService(propertyEditorCollection, dataTypeService.Value, localizedTextService.Value)); var contentService = GetLazyService(factory, c => new ContentService(scopeProvider, logger, eventMessagesFactory, GetRepo(c), GetRepo(c), GetRepo(c), GetRepo(c), GetRepo(c), GetRepo(c), propertyValidationService, TestHelper.ShortStringHelper)); @@ -168,7 +171,7 @@ namespace Umbraco.Tests.TestHelpers var mediaService = GetLazyService(factory, c => new MediaService(scopeProvider, mediaFileSystem, logger, eventMessagesFactory, GetRepo(c), GetRepo(c), GetRepo(c), GetRepo(c), TestHelper.ShortStringHelper)); var contentTypeService = GetLazyService(factory, c => new ContentTypeService(scopeProvider, logger, eventMessagesFactory, contentService.Value, GetRepo(c), GetRepo(c), GetRepo(c), GetRepo(c))); var mediaTypeService = GetLazyService(factory, c => new MediaTypeService(scopeProvider, logger, eventMessagesFactory, mediaService.Value, GetRepo(c), GetRepo(c), GetRepo(c), GetRepo(c))); - var fileService = GetLazyService(factory, c => new FileService(scopeProvider, logger, eventMessagesFactory, GetRepo(c), GetRepo(c), GetRepo(c), GetRepo(c), GetRepo(c), GetRepo(c), TestHelper.ShortStringHelper, globalSettings, hostingEnvironment)); + var fileService = GetLazyService(factory, c => new FileService(scopeProvider, logger, eventMessagesFactory, GetRepo(c), GetRepo(c), GetRepo(c), GetRepo(c), GetRepo(c), GetRepo(c), TestHelper.ShortStringHelper, Options.Create(globalSettings), hostingEnvironment)); var memberTypeService = GetLazyService(factory, c => new MemberTypeService(scopeProvider, logger, eventMessagesFactory, memberService.Value, GetRepo(c), GetRepo(c), GetRepo(c))); var entityService = GetLazyService(factory, c => new EntityService(scopeProvider, logger, eventMessagesFactory, idkMap, GetRepo(c))); @@ -180,11 +183,11 @@ namespace Umbraco.Tests.TestHelpers return new PackagingService( auditService.Value, new PackagesRepository(contentService.Value, contentTypeService.Value, dataTypeService.Value, fileService.Value, macroService.Value, localizationService.Value, hostingEnvironment, - new EntityXmlSerializer(contentService.Value, mediaService.Value, dataTypeService.Value, userService.Value, localizationService.Value, contentTypeService.Value, urlSegmentProviders, TestHelper.ShortStringHelper, propertyEditorCollection), logger, umbracoVersion, globalSettings, "createdPackages.config"), + new EntityXmlSerializer(contentService.Value, mediaService.Value, dataTypeService.Value, userService.Value, localizationService.Value, contentTypeService.Value, urlSegmentProviders, TestHelper.ShortStringHelper, propertyEditorCollection), logger, umbracoVersion, Options.Create(globalSettings), "createdPackages.config"), new PackagesRepository(contentService.Value, contentTypeService.Value, dataTypeService.Value, fileService.Value, macroService.Value, localizationService.Value, hostingEnvironment, - new EntityXmlSerializer(contentService.Value, mediaService.Value, dataTypeService.Value, userService.Value, localizationService.Value, contentTypeService.Value, urlSegmentProviders, TestHelper.ShortStringHelper, propertyEditorCollection), logger, umbracoVersion, globalSettings, "installedPackages.config"), + new EntityXmlSerializer(contentService.Value, mediaService.Value, dataTypeService.Value, userService.Value, localizationService.Value, contentTypeService.Value, urlSegmentProviders, TestHelper.ShortStringHelper, propertyEditorCollection), logger, umbracoVersion, Options.Create(globalSettings), "installedPackages.config"), new PackageInstallation( - new PackageDataInstallation(logger, fileService.Value, macroService.Value, localizationService.Value, dataTypeService.Value, entityService.Value, contentTypeService.Value, contentService.Value, propertyEditorCollection, scopeProvider, shortStringHelper, GetGlobalSettings(), localizedTextService.Value), + new PackageDataInstallation(logger, fileService.Value, macroService.Value, localizationService.Value, dataTypeService.Value, entityService.Value, contentTypeService.Value, contentService.Value, propertyEditorCollection, scopeProvider, shortStringHelper, globalSettings, localizedTextService.Value), new PackageFileInstallation(compiledPackageXmlParser, ioHelper, new ProfilingLogger(logger, new TestProfiler())), compiledPackageXmlParser, Mock.Of(), Mock.Of(x => x.ApplicationPhysicalPath == ioHelper.MapPath("~"))), @@ -241,6 +244,10 @@ namespace Umbraco.Tests.TestHelpers public IScopeProvider GetScopeProvider(ILogger logger, ITypeFinder typeFinder = null, FileSystems fileSystems = null, IUmbracoDatabaseFactory databaseFactory = null) { + var globalSettings = new GlobalSettingsBuilder().Build(); + var connectionStrings = new ConnectionStringsBuilder().Build(); + var coreDebugSettings = new CoreDebugSettingsBuilder().Build(); + if (databaseFactory == null) { // var mappersBuilder = new MapperCollectionBuilder(Current.Container); // FIXME: @@ -248,19 +255,18 @@ namespace Umbraco.Tests.TestHelpers // var mappers = mappersBuilder.CreateCollection(); var mappers = Current.Factory.GetInstance(); databaseFactory = new UmbracoDatabaseFactory(logger, - SettingsForTests.DefaultGlobalSettings, - new ConnectionStrings(), + globalSettings, + connectionStrings, Constants.System.UmbracoConnectionName, new Lazy(() => mappers), TestHelper.DbProviderFactoryCreator); } typeFinder ??= new TypeFinder(logger, new DefaultUmbracoAssemblyProvider(GetType().Assembly), new VaryingRuntimeHash()); - fileSystems ??= new FileSystems(Current.Factory, logger, TestHelper.IOHelper, SettingsForTests.GenerateMockGlobalSettings(), TestHelper.GetHostingEnvironment()); + fileSystems ??= new FileSystems(Current.Factory, logger, TestHelper.IOHelper, Options.Create(globalSettings), TestHelper.GetHostingEnvironment()); var coreDebug = TestHelper.CoreDebugSettings; var mediaFileSystem = Mock.Of(); - var scopeProvider = new ScopeProvider(databaseFactory, fileSystems, coreDebug, mediaFileSystem, logger, typeFinder, NoAppCache.Instance); - return scopeProvider; + return new ScopeProvider(databaseFactory, fileSystems, coreDebugSettings, mediaFileSystem, logger, typeFinder, NoAppCache.Instance); } } diff --git a/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs b/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs index cfcdacdadf..ea53d36498 100644 --- a/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs +++ b/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs @@ -33,6 +33,7 @@ using Umbraco.Persistance.SqlCe; using Umbraco.Tests.LegacyXmlPublishedCache; using Umbraco.Web.WebApi; using Umbraco.Tests.Common; +using Umbraco.Tests.Common.Builders; namespace Umbraco.Tests.TestHelpers { @@ -301,7 +302,8 @@ namespace Umbraco.Tests.TestHelpers { using (var scope = ScopeProvider.CreateScope()) { - var schemaHelper = new DatabaseSchemaCreator(scope.Database, Logger, UmbracoVersion, TestObjects.GetGlobalSettings()); + var globalSettings = new GlobalSettingsBuilder().Build(); + var schemaHelper = new DatabaseSchemaCreator(scope.Database, Logger, UmbracoVersion, globalSettings); //Create the umbraco database and its base data schemaHelper.InitializeDatabaseSchema(); diff --git a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs index 94c52e8d96..5d8e047161 100644 --- a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs +++ b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs @@ -60,6 +60,8 @@ using Umbraco.Web.Trees; using Current = Umbraco.Web.Composing.Current; using Umbraco.Tests.Common; using Umbraco.Core.Media; +using Umbraco.Tests.Common.Builders; +using Umbraco.Web.Configuration; namespace Umbraco.Tests.Testing { @@ -177,7 +179,7 @@ namespace Umbraco.Tests.Testing IBackOfficeInfo backOfficeInfo = new AspNetBackOfficeInfo(globalSettings, IOHelper, logger, settings); IIpResolver ipResolver = new AspNetIpResolver(); - UmbracoVersion = new UmbracoVersion(globalSettings); + UmbracoVersion = new UmbracoVersion(ConfigModelConversions.ConvertGlobalSettings(globalSettings)); LocalizedTextService = new LocalizedTextService(new Dictionary>(), logger); @@ -187,7 +189,7 @@ namespace Umbraco.Tests.Testing - Composition = new Composition(register, typeLoader, proflogger, ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.GetConfigs(), TestHelper.IOHelper, AppCaches.NoCache); + Composition = new Composition(register, typeLoader, proflogger, ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.IOHelper, AppCaches.NoCache); @@ -319,15 +321,15 @@ namespace Umbraco.Tests.Testing Composition.RegisterUnique(); Composition.RegisterUnique(); Composition.RegisterUnique(); + + var webRoutingSettings = new WebRoutingSettingsBuilder().Build(); Composition.RegisterUnique(factory => new UrlProvider( factory.GetInstance(), - TestHelpers.SettingsForTests.GenerateMockWebRoutingSettings(), + Microsoft.Extensions.Options.Options.Create(webRoutingSettings), new UrlProviderCollection(Enumerable.Empty()), new MediaUrlProviderCollection(Enumerable.Empty()), - factory.GetInstance() - - )); + factory.GetInstance())); @@ -457,8 +459,8 @@ namespace Umbraco.Tests.Testing Composition.RegisterUnique(_ => new TransientEventMessagesFactory()); - var globalSettings = TestHelper.GetConfigs().Global(); - var connectionStrings = TestHelper.GetConfigs().ConnectionStrings(); + var globalSettings = new GlobalSettingsBuilder().Build(); + var connectionStrings = new ConnectionStringsBuilder().Build(); Composition.RegisterUnique(f => new UmbracoDatabaseFactory(Logger, globalSettings, From 9ceecb21a882ffc3ddeb0206b3dbb94ae37eabb1 Mon Sep 17 00:00:00 2001 From: leekelleher Date: Fri, 31 Jul 2020 17:14:07 +0100 Subject: [PATCH 262/826] Grid cell error - to use "umb-code-snippet" directive --- .../src/views/propertyeditors/grid/editors/error.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/editors/error.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/editors/error.html index 67ef4ea112..5437c2bf85 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/editors/error.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/editors/error.html @@ -1,2 +1,2 @@

Something went wrong with this editor, below is the data stored:

-
{{control | json}}
\ No newline at end of file +{{control | json}} From cdab15af9139e640e0a1f95e976d879d2842ffb2 Mon Sep 17 00:00:00 2001 From: Emma Garland Date: Mon, 24 Aug 2020 16:20:51 +0100 Subject: [PATCH 263/826] Refactoring --- .../integration/Tour/backofficeTour.ts | 31 ++++++++++--------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Tour/backofficeTour.ts b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Tour/backofficeTour.ts index f94205265d..9de589f375 100644 --- a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Tour/backofficeTour.ts +++ b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Tour/backofficeTour.ts @@ -17,21 +17,21 @@ context('Backoffice Tour', () => { //assert cy.get('[data-element="help-tours"]').should("be.visible"); cy.get('[data-element="help-tours"]').click(); - cy.get('[data-element="help-tours"] .umb-progress-circle', { timeout: 60000 }).contains('17%'); + getPercentage(60000, 17); }); it('Backoffice introduction tour should run then rerun', () => { //act cy.umbracoGlobalHelp().should("be.visible"); cy.umbracoGlobalHelp().click(); - runBackOfficeIntroTour(0, 'Start'); - runBackOfficeIntroTour(17, 'Rerun'); + runBackOfficeIntroTour(0, 'Start', 60000); + runBackOfficeIntroTour(17, 'Rerun', 60000); //assert cy.get('[data-element="help-tours"]').should("be.visible"); - cy.get('[data-element="help-tours"] .umb-help-list').first().click(); - cy.get('[data-element="help-tours"] .umb-progress-circle', { timeout: 60000 }).contains('17%'); + cy.get('[data-element="help-tours"] .umb-help-list').click(); cy.umbracoGlobalHelp().should("be.visible"); + getPercentage(60000, 17); }); afterEach(() => { @@ -40,6 +40,10 @@ context('Backoffice Tour', () => { }); }); +function getPercentage(percentage, timeout) { + cy.get('[data-element="help-tours"] .umb-progress-circle', { timeout: timeout }).get('[percentage]').contains(percentage + '%'); +} + function resetTourData() { var tourStatus = { @@ -64,17 +68,16 @@ function resetTourData() { }) } -function runBackOfficeIntroTour(percentageComplete, buttonText) { +function runBackOfficeIntroTour(percentageComplete, buttonText, timeout) { cy.get('[data-element="help-tours"]').should("be.visible"); - cy.get('[data-element="help-tours"]').click(); - cy.get('[data-element="help-tours"] .umb-progress-circle', { timeout: 60000 }).contains(percentageComplete + '%'); - cy.get('[data-element="help-tours"] .umb-progress-circle', { timeout: 60000 }).get('[percentage]').contains(percentageComplete + '%'); + cy.get('[data-element="help-tours"]').click(); + cy.get('[data-element="help-tours"] .umb-progress-circle', { timeout: timeout }).get('[percentage]').contains(percentageComplete + '%'); cy.get('[data-element="help-tours"]').click(); cy.get('[data-element="tour-umbIntroIntroduction"] .umb-button').should("be.visible"); cy.get('[data-element="tour-umbIntroIntroduction"] .umb-button').contains(buttonText); cy.get('[data-element="tour-umbIntroIntroduction"] .umb-button').click(); //act - cy.get('.umb-tour-step', { timeout: 60000 }).should('be.visible'); + cy.get('.umb-tour-step', { timeout: timeout }).should('be.visible'); cy.get('.umb-tour-step__footer').should('be.visible'); cy.get('.umb-tour-step__counter').should('be.visible'); @@ -83,15 +86,15 @@ function runBackOfficeIntroTour(percentageComplete, buttonText) { cy.get('.umb-tour-step__footer .umb-button').should('be.visible').click(); } cy.umbracoGlobalUser().click() - cy.get('.umb-tour-step__counter', { timeout: 10000 }).contains('8/12'); + cy.get('.umb-tour-step__counter', { timeout: timeout }).contains('8/12'); cy.get('.umb-tour-step__footer .umb-button').should('be.visible').click(); - cy.get('.umb-tour-step__counter', { timeout: 10000 }).contains('9/12'); + cy.get('.umb-tour-step__counter', { timeout: timeout }).contains('9/12'); cy.get('.umb-overlay-drawer__align-right .umb-button').should('be.visible').click(); - cy.get('.umb-tour-step__counter', { timeout: 10000 }).contains('10/12'); + cy.get('.umb-tour-step__counter', { timeout: timeout }).contains('10/12'); cy.umbracoGlobalHelp().click() for (let i = 11; i < 13; i++) { - cy.get('.umb-tour-step__counter', { timeout: 10000 }).contains(i + '/12'); + cy.get('.umb-tour-step__counter', { timeout: timeout }).contains(i + '/12'); cy.get('.umb-tour-step__footer .umb-button').should('be.visible').click(); } cy.get('.umb-tour-step__footer .umb-button').should('be.visible').click(); From 27a98dbdaa2a274ac6ab67098a7d315b3af0dcf2 Mon Sep 17 00:00:00 2001 From: Emma Garland Date: Mon, 24 Aug 2020 16:23:18 +0100 Subject: [PATCH 264/826] Tours green - clicked correct element --- .../cypress/integration/Tour/backofficeTour.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Tour/backofficeTour.ts b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Tour/backofficeTour.ts index 9de589f375..0c95faeac0 100644 --- a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Tour/backofficeTour.ts +++ b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Tour/backofficeTour.ts @@ -17,7 +17,7 @@ context('Backoffice Tour', () => { //assert cy.get('[data-element="help-tours"]').should("be.visible"); cy.get('[data-element="help-tours"]').click(); - getPercentage(60000, 17); + getPercentage(17, 60000); }); it('Backoffice introduction tour should run then rerun', () => { @@ -29,9 +29,9 @@ context('Backoffice Tour', () => { //assert cy.get('[data-element="help-tours"]').should("be.visible"); - cy.get('[data-element="help-tours"] .umb-help-list').click(); + cy.get('[data-element="help-tours"]').click(); cy.umbracoGlobalHelp().should("be.visible"); - getPercentage(60000, 17); + getPercentage(17, 60000); }); afterEach(() => { From 6ee13fb0ea64e9f306d4a367a973ae84693f439c Mon Sep 17 00:00:00 2001 From: Emma Garland Date: Mon, 24 Aug 2020 16:27:51 +0100 Subject: [PATCH 265/826] Timeout is a variable --- .../cypress/integration/Tour/backofficeTour.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Tour/backofficeTour.ts b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Tour/backofficeTour.ts index 0c95faeac0..307da2518c 100644 --- a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Tour/backofficeTour.ts +++ b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Tour/backofficeTour.ts @@ -1,7 +1,7 @@ /// context('Backoffice Tour', () => { - + var timeout = 60000; beforeEach(() => { //arrange cy.umbracoLogin(Cypress.env('username'), Cypress.env('password')); @@ -17,21 +17,21 @@ context('Backoffice Tour', () => { //assert cy.get('[data-element="help-tours"]').should("be.visible"); cy.get('[data-element="help-tours"]').click(); - getPercentage(17, 60000); + getPercentage(17, timeout); }); it('Backoffice introduction tour should run then rerun', () => { //act cy.umbracoGlobalHelp().should("be.visible"); cy.umbracoGlobalHelp().click(); - runBackOfficeIntroTour(0, 'Start', 60000); - runBackOfficeIntroTour(17, 'Rerun', 60000); + runBackOfficeIntroTour(0, 'Start', timeout); + runBackOfficeIntroTour(17, 'Rerun', timeout); //assert cy.get('[data-element="help-tours"]').should("be.visible"); cy.get('[data-element="help-tours"]').click(); cy.umbracoGlobalHelp().should("be.visible"); - getPercentage(17, 60000); + getPercentage(17, timeout); }); afterEach(() => { From 0a954d18040fcc7dc98b74d0836f37222f1fd919 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Mon, 24 Aug 2020 18:01:56 +0200 Subject: [PATCH 266/826] Fix issue with build targets after nuget rename --- build/NuSpecs/build/{UmbracoCms.props => Umbraco.Cms.props} | 0 build/NuSpecs/build/{UmbracoCms.targets => Umbraco.Cms.targets} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename build/NuSpecs/build/{UmbracoCms.props => Umbraco.Cms.props} (100%) rename build/NuSpecs/build/{UmbracoCms.targets => Umbraco.Cms.targets} (100%) diff --git a/build/NuSpecs/build/UmbracoCms.props b/build/NuSpecs/build/Umbraco.Cms.props similarity index 100% rename from build/NuSpecs/build/UmbracoCms.props rename to build/NuSpecs/build/Umbraco.Cms.props diff --git a/build/NuSpecs/build/UmbracoCms.targets b/build/NuSpecs/build/Umbraco.Cms.targets similarity index 100% rename from build/NuSpecs/build/UmbracoCms.targets rename to build/NuSpecs/build/Umbraco.Cms.targets From c561b256bf101c36ca2df9a716bc763d4ef5fa47 Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Mon, 24 Aug 2020 18:09:16 +0200 Subject: [PATCH 267/826] Updated solution to include correct filenames --- src/umbraco.sln | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/umbraco.sln b/src/umbraco.sln index 636a5c31c9..b2922abf3e 100644 --- a/src/umbraco.sln +++ b/src/umbraco.sln @@ -62,8 +62,8 @@ Project("{E24C65DC-7377-472B-9ABA-BC803B73C61A}") = "Umbraco.Web.UI.Client", "ht EndProject Project("{E24C65DC-7377-472B-9ABA-BC803B73C61A}") = "Umbraco.Tests.AcceptanceTest", "http://localhost:58896", "{9E4C8A12-FBE0-4673-8CE2-DF99D5D57817}" ProjectSection(WebsiteProperties) = preProject - UseIISExpress = "true" - TargetFrameworkMoniker = ".NETFramework,Version%3Dv4.5" + UseIISExpress = "true" + TargetFrameworkMoniker = ".NETFramework,Version%3Dv4.5" Debug.AspNetCompiler.VirtualPath = "/localhost_58896" Debug.AspNetCompiler.PhysicalPath = "Umbraco.Tests.AcceptanceTest\" Debug.AspNetCompiler.TargetPath = "PrecompiledWeb\localhost_58896\" @@ -84,8 +84,8 @@ Project("{E24C65DC-7377-472B-9ABA-BC803B73C61A}") = "Umbraco.Tests.AcceptanceTes Release.AspNetCompiler.ForceOverwrite = "true" Release.AspNetCompiler.FixedNames = "false" Release.AspNetCompiler.Debug = "False" - DefaultWebSiteLanguage = "Visual C#" - StartServerOnDebug = "false" + DefaultWebSiteLanguage = "Visual C#" + StartServerOnDebug = "false" VWDPort = "58896" VWDPort = "62926" SlnRelativePath = "Umbraco.Tests.AcceptanceTest\" @@ -107,10 +107,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tools", "tools", "{E3F9F378 EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{5B03EF4E-E0AC-4905-861B-8C3EC1A0D458}" - ProjectSection(SolutionItems) = preProject - ..\build\NuSpecs\build\UmbracoCms.props = ..\build\NuSpecs\build\UmbracoCms.props - ..\build\NuSpecs\build\UmbracoCms.targets = ..\build\NuSpecs\build\UmbracoCms.targets - EndProjectSection +ProjectSection(SolutionItems) = preProject + ..\build\NuSpecs\build\Umbraco.Cms.props = ..\build\NuSpecs\build\Umbraco.Cms.props + ..\build\NuSpecs\build\Umbraco.Cms.targets = ..\build\NuSpecs\build\Umbraco.Cms.targets +EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DocTools", "DocTools", "{53594E5B-64A2-4545-8367-E3627D266AE8}" ProjectSection(SolutionItems) = preProject From 056a5548756803cd29661d65809e42025e08c43c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Mon, 24 Aug 2020 21:38:36 +0200 Subject: [PATCH 268/826] use absolute path for thumbnail and dont scale SVGs --- .../components/blockcard/umb-block-card.html | 2 +- .../blockcard/umbBlockCard.component.js | 32 ++++++++++++++++++- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/components/blockcard/umb-block-card.html b/src/Umbraco.Web.UI.Client/src/views/components/blockcard/umb-block-card.html index 486bcbda4a..225362f4d8 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/blockcard/umb-block-card.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/blockcard/umb-block-card.html @@ -1,5 +1,5 @@ -
- - + diff --git a/src/Umbraco.Web.UI.Client/src/views/dictionary/create.html b/src/Umbraco.Web.UI.Client/src/views/dictionary/create.html index 88a67aaf18..9e628464b2 100644 --- a/src/Umbraco.Web.UI.Client/src/views/dictionary/create.html +++ b/src/Umbraco.Web.UI.Client/src/views/dictionary/create.html @@ -1,7 +1,7 @@  diff --git a/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/treepicker.html b/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/treepicker.html index ab1b84db97..2fb2aab352 100644 --- a/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/treepicker.html +++ b/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/treepicker.html @@ -15,12 +15,11 @@ - + diff --git a/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/treesource.html b/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/treesource.html index e693801495..865b59506b 100644 --- a/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/treesource.html +++ b/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/treesource.html @@ -6,7 +6,6 @@ -
- - +
+
- - Query for root node with xpath + +
- +
- +
-
    +
    • - - - Show xpath query help - + + - +

      Use Xpath query to set a root node on the tree, either based on a search from the root of the content tree, or by using a context-aware placeholder.

      - Placeholders finds the nearest published ID and runs its query from there. so for instance: + Placeholders finds the nearest published ID and runs its query from there, so for instance:

      $parent/newsArticle
      @@ -68,14 +63,14 @@ $root: root of the content tree
      $site: Ancestor node at level 1

      -
      +
    • - - Cancel and clear query + +
    - +
diff --git a/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/treesourcetypepicker.html b/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/treesourcetypepicker.html index f679b53093..cdbacfc7f3 100644 --- a/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/treesourcetypepicker.html +++ b/src/Umbraco.Web.UI.Client/src/views/prevalueeditors/treesourcetypepicker.html @@ -12,12 +12,11 @@ on-remove="vm.remove(itemType)">
- + diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/boolean/boolean.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/boolean/boolean.controller.js index df76c2d63a..dab8d2c6f8 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/boolean/boolean.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/boolean/boolean.controller.js @@ -1,6 +1,28 @@ function booleanEditorController($scope, angularHelper) { + // Setup the default config + // This allow to overwrite the configuration when property editor is re-used + // in e.g. third party packages, dashboard or content app. For example when using umb-property-editor. + // At the moment this use "1/0" as default for "truevalue" and "falsevalue", but allow "True/False" as well. + // Maybe sometime later we can make it support "Yes/No" or "On/Off" as well similar to ng-true-value and ng-false-value in Angular. + var config = { + truevalue: "1", + falsevalue: "0", + showLabels: false + }; + + if ($scope.model.config && $scope.model.config.showLabels && Object.toBoolean($scope.model.config.showLabels)) { + config.showLabels = true; + } + + // Map the user config + Utilities.extend(config, $scope.model.config); + + // Map back to the model + $scope.model.config = config; + function setupViewModel() { + $scope.renderModel = { value: false }; @@ -16,12 +38,12 @@ function booleanEditorController($scope, angularHelper) { setupViewModel(); - if( $scope.model && !$scope.model.value ) { - $scope.model.value = ($scope.renderModel.value === true) ? '1' : '0'; + if ($scope.model && !$scope.model.value) { + $scope.model.value = ($scope.renderModel.value === true) ? $scope.model.config.truevalue : $scope.model.config.falsevalue; } - //here we declare a special method which will be called whenever the value has changed from the server - //this is instead of doing a watch on the model.value = faster + // Here we declare a special method which will be called whenever the value has changed from the server + // this is instead of doing a watch on the model.value = faster $scope.model.onValueChanged = function (newVal, oldVal) { //update the display val again if it has changed from the server setupViewModel(); @@ -30,13 +52,13 @@ function booleanEditorController($scope, angularHelper) { // Update the value when the toggle is clicked $scope.toggle = function(){ angularHelper.getCurrentForm($scope).$setDirty(); - if($scope.renderModel.value){ - $scope.model.value = "0"; + if ($scope.renderModel.value){ + $scope.model.value = $scope.model.config.falsevalue; setupViewModel(); return; } - $scope.model.value = "1"; + $scope.model.value = $scope.model.config.truevalue; setupViewModel(); }; diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/boolean/boolean.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/boolean/boolean.html index 21ed753c15..75f3f5452a 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/boolean/boolean.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/boolean/boolean.html @@ -3,9 +3,9 @@ input-id="{{model.alias}}" checked="renderModel.value" on-click="toggle()" - show-labels="{{model.config.labelOn ? 'true': 'false'}}" + show-labels="{{model.config.showLabels}}" label-position="right" label-on="{{model.config.labelOn}}" - label-off="{{model.config.labelOn}}"> + label-off="{{model.config.labelOff}}"> diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js index 238872db40..bd80cdc42c 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js @@ -3,16 +3,19 @@ * The controller that is used for a couple different Property Editors: Multi Node Tree Picker, Content Picker, * since this is used by MNTP and it supports content, media and members, there is code to deal with all 3 of those types * @param {any} $scope + * @param {any} $q + * @param {any} $routeParams + * @param {any} $location * @param {any} entityResource * @param {any} editorState * @param {any} iconHelper - * @param {any} $routeParams * @param {any} angularHelper * @param {any} navigationService - * @param {any} $location * @param {any} localizationService + * @param {any} editorService + * @param {any} userService */ -function contentPickerController($scope, entityResource, editorState, iconHelper, $routeParams, angularHelper, navigationService, $location, localizationService, editorService, $q) { +function contentPickerController($scope, $q, $routeParams, $location, entityResource, editorState, iconHelper, angularHelper, navigationService, localizationService, editorService, userService) { var vm = { labels: { @@ -139,7 +142,8 @@ function contentPickerController($scope, entityResource, editorState, iconHelper : $scope.model.config.startNode.type === "media" ? "Media" : "Document"; - $scope.allowOpenButton = entityType === "Document"; + + $scope.allowOpenButton = false; $scope.allowEditButton = entityType === "Document"; $scope.allowRemoveButton = true; @@ -303,16 +307,24 @@ function contentPickerController($scope, entityResource, editorState, iconHelper $scope.model.value = null; }; - $scope.openContentEditor = function (node) { - var contentEditor = { - id: node.id, + $scope.openEditor = function (item) { + var editor = { + id: entityType === "Member" ? item.key : item.id, submit: function (model) { + + var node = entityType === "Member" ? model.memberNode : + entityType === "Media" ? model.mediaNode : + model.contentNode; + // update the node - node.name = model.contentNode.name; - node.published = model.contentNode.hasPublishedVersion; + item.name = node.name; + if (entityType !== "Member") { - entityResource.getUrl(model.contentNode.id, entityType).then(function (data) { - node.url = data; + if (entityType === "Document") { + item.published = node.hasPublishedVersion; + } + entityResource.getUrl(node.id, entityType).then(function (data) { + item.url = data; }); } editorService.close(); @@ -321,7 +333,18 @@ function contentPickerController($scope, entityResource, editorState, iconHelper editorService.close(); } }; - editorService.contentEditor(contentEditor); + + switch (entityType) { + case "Document": + editorService.contentEditor(editor); + break; + case "Media": + editorService.mediaEditor(editor); + break; + case "Member": + editorService.memberEditor(editor); + break; + } }; //when the scope is destroyed we need to unsubscribe @@ -423,7 +446,7 @@ function contentPickerController($scope, entityResource, editorState, iconHelper if (entityType !== "Member") { entityResource.getUrl(entity.id, entityType).then(function (data) { // update url - angular.forEach($scope.renderModel, function (item) { + $scope.renderModel.forEach(function (item) { if (item.id === entity.id) { if (entity.trashed) { item.url = vm.labels.general_recycleBin; @@ -466,6 +489,7 @@ function contentPickerController($scope, entityResource, editorState, iconHelper "icon": item.icon, "path": item.path, "url": item.url, + "key": item.key, "trashed": item.trashed, "published": (item.metaData && item.metaData.IsPublished === false && entityType === "Document") ? false : true // only content supports published/unpublished content so we set everything else to published so the UI looks correct @@ -484,6 +508,26 @@ function contentPickerController($scope, entityResource, editorState, iconHelper } function init() { + + userService.getCurrentUser().then(function (user) { + switch (entityType) { + case "Document": + var hasAccessToContent = user.allowedSections.indexOf("content") !== -1; + $scope.allowOpenButton = hasAccessToContent; + break; + case "Media": + var hasAccessToMedia = user.allowedSections.indexOf("media") !== -1; + $scope.allowOpenButton = hasAccessToMedia; + break; + case "Member": + var hasAccessToMember = user.allowedSections.indexOf("member") !== -1; + $scope.allowOpenButton = hasAccessToMember; + break; + + default: + } + }); + localizationService.localizeMany(["general_recycleBin", "general_add"]) .then(function(data) { vm.labels.general_recycleBin = data[0]; diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.html index ba22ca9d80..1a17ea2698 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.html @@ -15,7 +15,7 @@ allow-remove="allowRemoveButton" allow-open="model.config.showOpenButton && allowOpenButton && !dialogEditor" on-remove="remove($index)" - on-open="openContentEditor(node)"> + on-open="openEditor(node)"> diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/datepicker/datepicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/datepicker/datepicker.controller.js index 24affc6ac1..30b6fc4c8f 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/datepicker/datepicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/datepicker/datepicker.controller.js @@ -55,7 +55,9 @@ function dateTimePickerController($scope, angularHelper, dateHelper, validationM }; // Don't show calendar if date format has been set to only time - if ($scope.model.config.format === "HH:mm:ss" || $scope.model.config.format === "HH:mm" || $scope.model.config.format === "HH") { + const timeFormat = $scope.model.config.format.toLowerCase(); + const timeFormatPattern = /^h{1,2}:m{1,2}:s{1,2}\s?a?$/gmi; + if (timeFormat.match(timeFormatPattern)) { $scope.datePickerConfig.enableTime = true; $scope.datePickerConfig.noCalendar = true; } diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/datepicker/datepicker.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/datepicker/datepicker.html index b35663c3df..9501a6631b 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/datepicker/datepicker.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/datepicker/datepicker.html @@ -11,21 +11,20 @@ on-change="datePickerChange(dateStr)">
- +
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/dropdownFlexible/dropdownFlexible.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/dropdownFlexible/dropdownFlexible.controller.js index 4064df6a24..69de132715 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/dropdownFlexible/dropdownFlexible.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/dropdownFlexible/dropdownFlexible.controller.js @@ -15,14 +15,14 @@ angular.module("umbraco").controller("Umbraco.PropertyEditors.DropdownFlexibleCo //ensure this is a bool, old data could store zeros/ones or string versions $scope.model.config.multiple = Object.toBoolean($scope.model.config.multiple); - + //ensure when form is saved that we don't store [] or [null] as string values in the database when no items are selected $scope.$on("formSubmitting", function () { - if ($scope.model.value && ($scope.model.value.length === 0 || $scope.model.value[0] === null)) { + if ($scope.model.value !== null && ($scope.model.value.length === 0 || $scope.model.value[0] === null)) { $scope.model.value = null; } }); - + function convertArrayToDictionaryArray(model){ //now we need to format the items in the dictionary because we always want to have an array var newItems = []; @@ -41,7 +41,7 @@ angular.module("umbraco").controller("Umbraco.PropertyEditors.DropdownFlexibleCo var keys = _.keys($scope.model.config.items); for (var i = 0; i < vals.length; i++) { - var label = vals[i].value ? vals[i].value : vals[i]; + var label = vals[i].value ? vals[i].value : vals[i]; newItems.push({ id: keys[i], sortOrder: vals[i].sortOrder, value: label }); } @@ -65,7 +65,7 @@ angular.module("umbraco").controller("Umbraco.PropertyEditors.DropdownFlexibleCo else { throw "The items property must be either an array or a dictionary"; } - + //sort the values $scope.model.config.items.sort(function (a, b) { return (a.sortOrder > b.sortOrder) ? 1 : ((b.sortOrder > a.sortOrder) ? -1 : 0); }); @@ -80,7 +80,7 @@ angular.module("umbraco").controller("Umbraco.PropertyEditors.DropdownFlexibleCo $scope.model.value = ""; } } - + // if we run in single mode we'll store the value in a local variable // so we can pass an array as the model as our PropertyValueEditor expects that $scope.model.singleDropdownValue = ""; diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/editconfig.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/editconfig.controller.js index e56bc67a49..969f675139 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/editconfig.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/editconfig.controller.js @@ -1,10 +1,66 @@ -function EditConfigController($scope) { +function EditConfigController($scope, angularHelper) { var vm = this; - + vm.submit = submit; vm.close = close; + vm.aceOption = { + mode: "json", + theme: "chrome", + showPrintMargin: false, + advanced: { + fontSize: '14px', + enableSnippets: true, + enableBasicAutocompletion: true, + enableLiveAutocompletion: false + }, + onLoad: function (_editor) { + vm.editor = _editor; + + vm.configJson = Utilities.toJson($scope.model.config, true); + + vm.editor.setValue(vm.configJson); + + vm.editor.on("blur", blurAceEditor); + } + }; + + function blurAceEditor(event, _editor) { + const code = _editor.getValue(); + + //var form = angularHelper.getCurrentForm($scope); + var form = vm.gridConfigEditor; + var isValid = isValidJson(code); + + if (isValid) { + $scope.model.config = Utilities.fromJson(code); + + setValid(form); + } + else { + setInvalid(form); + } + } + + function isValidJson(model) { + var flag = true; + try { + Utilities.fromJson(model) + } catch (err) { + flag = false; + } + return flag; + } + + function setValid(form) { + form.$setValidity('json', true); + } + + function setInvalid(form) { + form.$setValidity('json', false); + } + function submit() { if ($scope.model && $scope.model.submit) { $scope.model.submit($scope.model); diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/editconfig.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/editconfig.html index 9fed19d4d9..4470c50274 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/editconfig.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/editconfig.html @@ -16,16 +16,18 @@ - +

{{model.name}}

Settings will only save if the entered json configuration is valid

- -
+
+
+ +
This configuration is not valid json, and will not be saved.
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/layoutconfig.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/layoutconfig.controller.js index 876e4cf8f3..cf201976ad 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/layoutconfig.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/layoutconfig.controller.js @@ -2,17 +2,29 @@ angular.module("umbraco") .controller("Umbraco.PropertyEditors.GridPrevalueEditor.LayoutConfigController", function ($scope, localizationService) { + var vm = this; + + vm.labels = {}; function init() { - setTitle(); + + var labelKeys = [ + "grid_addGridLayout", + "grid_allowAllRowConfigurations" + ]; + + localizationService.localizeMany(labelKeys).then(function (data) { + + vm.labels.title = data[0]; + vm.labels.allowAllRowConfigurations = data[1]; + + setTitle(vm.labels.title); + }); } - function setTitle() { + function setTitle(value) { if (!$scope.model.title) { - localizationService.localize("grid_addGridLayout") - .then(function(data){ - $scope.model.title = data; - }); + $scope.model.title = value; } } @@ -56,13 +68,15 @@ angular.module("umbraco") }; $scope.toggleAllowed = function (section) { + section.allowAll = !section.allowAll; + if (section.allowed) { delete section.allowed; } else { section.allowed = []; } - } + }; $scope.deleteSection = function(section, template) { if ($scope.currentSection === section) { @@ -71,19 +85,32 @@ angular.module("umbraco") var index = template.sections.indexOf(section) template.sections.splice(index, 1); }; - + + $scope.selectRow = function (section, row) { + section.allowed = section.allowed || []; + + var index = section.allowed.indexOf(row.name); + if (row.allowed === true) { + if (index === -1) { + section.allowed.push(row.name); + } + } + else { + section.allowed.splice(index, 1); + } + }; $scope.close = function() { - if($scope.model.close) { + if ($scope.model.close) { $scope.model.close(); } - } + }; $scope.submit = function () { if ($scope.model.submit) { $scope.model.submit($scope.currentLayout); } - } + }; $scope.$watch("currentLayout", function(layout){ if(layout){ diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/layoutconfig.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/layoutconfig.html index 06afaa6b45..49e478a10b 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/layoutconfig.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/layoutconfig.html @@ -1,166 +1,165 @@ -
- - - +
- - + + - - - + + + +
+

+ +

+ + + +
+
+
-
+ + -

+ + + - - - +
+
+
-
+
-
-
+ +
+ + {{currentSection.grid}} + +
+
- - + + + + - - - + -
-
-
+ + -
+
+
- -
- - - - {{currentSection.grid}} - - - -
-
+
+
    - - - - Delete - - +
  • +
    - + + - - +
    -
    -
    +
    +
    +
    -
    -
      +
      +
    +
    +
    -
  • +
    + {{row.name}}
    + {{row.areas.length}} cells +
    +
-
-
-
-
+
+ + +
+
+ +
-
-
-
-
+
-
- {{row.name}}
- {{row.areas.length}} cells
-
- +
+
+
-
- - -
-
- -
- - - - - - -
-
- - - - - - + + + + - - + + - + - + - + diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/rowconfig.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/rowconfig.controller.js index 263e7c0d9a..83a9fd5394 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/rowconfig.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/rowconfig.controller.js @@ -1,22 +1,34 @@ function RowConfigController($scope, localizationService) { + var vm = this; + + vm.labels = {}; + function init() { - setTitle(); + + var labelKeys = [ + "grid_addRowConfiguration", + "grid_allowAllEditors" + ]; + + localizationService.localizeMany(labelKeys).then(function (data) { + + vm.labels.title = data[0]; + vm.labels.allowAllEditors = data[1]; + + setTitle(vm.labels.title); + }); } - function setTitle() { + function setTitle(value) { if (!$scope.model.title) { - localizationService.localize("grid_addRowConfiguration") - .then(function(data){ - $scope.model.title = data; - }); + $scope.model.title = value; } } - $scope.currentRow = $scope.model.currentRow; - $scope.editors = $scope.model.editors; $scope.columns = $scope.model.columns; + $scope.editors = $scope.model.editors; $scope.scaleUp = function(section, max, overflow) { var add = 1; @@ -44,7 +56,7 @@ function RowConfigController($scope, localizationService) { delete $scope.currentCell; } else { - if (cell === undefined) { + if (cell === null) { var available = $scope.availableRowSpace; var space = 4; @@ -58,43 +70,64 @@ function RowConfigController($scope, localizationService) { row.areas.push(cell); } + + cell.allowed = cell.allowed || []; + + $scope.editors.forEach(function (e) { e.allowed = cell.allowed.indexOf(e.alias) !== -1 }); + $scope.currentCell = cell; $scope.currentCell.allowAll = cell.allowAll || !cell.allowed || !cell.allowed.length; } }; $scope.toggleAllowed = function (cell) { + cell.allowAll = !cell.allowAll; + if (cell.allowed) { delete cell.allowed; } else { cell.allowed = []; } - } + }; $scope.deleteArea = function (cell, row) { if ($scope.currentCell === cell) { - $scope.currentCell = undefined; + $scope.currentCell = null; } var index = row.areas.indexOf(cell) row.areas.splice(index, 1); }; $scope.closeArea = function() { - $scope.currentCell = undefined; + $scope.currentCell = null; + }; + + $scope.selectEditor = function (cell, editor) { + cell.allowed = cell.allowed || []; + + var index = cell.allowed.indexOf(editor.alias); + if (editor.allowed === true) { + if (index === -1) { + cell.allowed.push(editor.alias); + } + } + else { + cell.allowed.splice(index, 1); + } }; - $scope.close = function() { - if($scope.model.close) { + $scope.close = function () { + if ($scope.model.close) { $scope.model.close(); } - } + }; $scope.submit = function () { if ($scope.model.submit) { $scope.model.submit($scope.currentRow); } - } + }; $scope.nameChanged = false; var originalName = $scope.currentRow.name; @@ -118,11 +151,8 @@ function RowConfigController($scope, localizationService) { } } }, true); - init(); - - } angular.module("umbraco").controller("Umbraco.PropertyEditors.GridPrevalueEditor.RowConfigController", RowConfigController); diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/rowconfig.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/rowconfig.html index 9e7034688b..b74ef6bf09 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/rowconfig.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/rowconfig.html @@ -1,10 +1,8 @@ -
+
+ - - - -
+ +
+

+
+

Modifying a row configuration name will result in loss of + data for any existing content that is based on this configuration.

+

Modifying only the label will not result in data loss.

+
+ + + + + + -
+
-

+
+
-
-

Modifying a row configuration name will result in loss of - data for any existing content that is based on this configuration.

-

Modifying only the label will not result in data loss.

-
+ + - - - + + + +
+
+
- - - +
-
+ +
+ + {{currentCell.grid}} + +
+
-
-
+ + + - - + + + + - - - -
-
-
+ -
+ + - -
- - - - {{currentCell.grid}} - - - -
-
+
+
+
    +
  • - - - + + {{editor.name}} + ({{editor.alias}}) + + +
  • +
+
+ +
- - - - Delete - - +
- -
    -
  • - -
  • -
+ + + -
-
-
    -
  • - -
  • -
-
-
-
- -
- - - - -
- - - - - + + - - - - - -

Warning!

- -

- You are deleting the row configuration {{model.dialogData.rowName}} -

- -

- - Modifying a row configuration name will result in loss of - data for any existing content that is based on this configuration. - -

- -

- Are you sure? -

- -
-
-
- - - - - - - - - - -
- -
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/editors/media.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/editors/media.controller.js index 7c98fbfc5e..0d558e166c 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/editors/media.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/editors/media.controller.js @@ -20,7 +20,16 @@ angular.module("umbraco") $scope.setImage = function () { var startNodeId = $scope.model.config && $scope.model.config.startNodeId ? $scope.model.config.startNodeId : undefined; var startNodeIsVirtual = startNodeId ? $scope.model.config.startNodeIsVirtual : undefined; - + var value = $scope.control.value; + var target = value + ? { + udi: value.udi, + url: value.image, + image: value.image, + focalPoint: value.focalPoint, + coordinates: value.coordinates + } + : null; var mediaPicker = { startNodeId: startNodeId, startNodeIsVirtual: startNodeIsVirtual, @@ -29,11 +38,13 @@ angular.module("umbraco") disableFolderSelect: true, onlyImages: true, dataTypeKey: $scope.model.dataTypeKey, + currentTarget: target, submit: function (model) { var selectedImage = model.selection[0]; $scope.control.value = { focalPoint: selectedImage.focalPoint, + coordinates: selectedImage.coordinates, id: selectedImage.id, udi: selectedImage.udi, image: selectedImage.image, @@ -69,25 +80,46 @@ angular.module("umbraco") } else { if ($scope.control.editor.config && $scope.control.editor.config.size) { + if ($scope.control.value.coordinates) { + // New way, crop by percent must come before width/height. + imageOptions.crop = $scope.control.value.coordinates; + imageOptions.mode = "percentage" + } else { + // Here in order not to break existing content where focalPoint were used. + // For some reason width/height have to come first when mode=crop. + if ($scope.control.value.focalPoint) { + imageOptions.focalPoint = { + left: $scope.control.value.focalPoint.left, + top: $scope.control.value.focalPoint.top + } + imageOptions.mode = "crop"; + } else { + // Prevent black padding and no crop when focal point not set / changed from default + imageOptions.focalPoint = { + left: 0.5, + top: 0.5 + } + imageOptions.mode = "crop"; + } + } imageOptions.animationprocessmode = "first"; imageOptions.height = $scope.control.editor.config.size.height; imageOptions.width = $scope.control.editor.config.size.width; } - if ($scope.control.value.focalPoint) { - imageOptions.focalPoint = { - left: $scope.control.value.focalPoint.left, - top: $scope.control.value.focalPoint.top - } - imageOptions.mode = "crop"; - } + // set default size if no crop present (moved from the view) + if (url.indexOf('?') == -1) + { + imageOptions.width = 800; + imageOptions.upscale = false; + imageOptions.animationprocessmode = false; } - - mediaHelper.getProcessedImageUrl($scope.control.value.image, imageOptions) - .then(function (url) { - $scope.thumbnailUrl = url; - }); } - }; + mediaHelper.getProcessedImageUrl($scope.control.value.image, imageOptions) + .then(function (url) { + $scope.thumbnailUrl = url; + }); + } + }; - }); + }); diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/editors/media.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/editors/media.html index 184f707ebf..fa32821917 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/editors/media.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/editors/media.html @@ -1,16 +1,16 @@
-
- +
+
Click to insert image
-
+
-
- +
+ -
+
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/grid.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/grid.controller.js index a0826f7a96..6d3383c51e 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/grid.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/grid.controller.js @@ -405,14 +405,16 @@ angular.module("umbraco") eventsService.emit("grid.rowAdded", { scope: $scope, element: $element, row: row }); - // TODO: find a nicer way to do this without relying on setTimeout - setTimeout(function () { - var newRowEl = $element.find("[data-rowid='" + row.$uniqueId + "']"); + if (!isInit) { + // TODO: find a nicer way to do this without relying on setTimeout + setTimeout(function () { + var newRowEl = $element.find("[data-rowid='" + row.$uniqueId + "']"); - if (newRowEl !== null) { - newRowEl.focus(); - } - }, 0); + if (newRowEl !== null) { + newRowEl.focus(); + } + }, 0); + } }; @@ -953,7 +955,7 @@ angular.module("umbraco") $scope.availableEditors = response.data; //Localize the grid editor names - angular.forEach($scope.availableEditors, function (value, key) { + $scope.availableEditors.forEach(function (value) { //If no translation is provided, keep using the editor name from the manifest localizationService.localize("grid_" + value.alias, undefined, value.name).then(function (v) { value.name = v; diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/grid.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/grid.html index 0628766638..afb754a0ef 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/grid.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/grid.html @@ -22,7 +22,7 @@
-

+

Choose a layout

{{row.label || row.name}}
- +

Settings applied

@@ -95,10 +95,10 @@
- @@ -138,24 +138,27 @@
- - + +

This content is not allowed here

- - + +

This content is allowed here

- +

+ Settings applied +

-
- -
+
@@ -163,8 +166,10 @@ @@ -196,13 +201,17 @@
- +
- - @@ -226,7 +235,7 @@
- +
@@ -266,7 +275,7 @@
-

+

Add row

@@ -41,8 +40,7 @@ - @@ -66,14 +64,13 @@
  • -
    +
    + ng-repeat="area in layout.areas | filter: vm.zeroWidthFilter" + ng-style="{width: vm.percentage(area.grid) + '%', 'max-width': '100%'}">

    {{area.maxItems}}

    @@ -84,7 +81,7 @@
    {{layout.label || layout.name}}
    - @@ -93,7 +90,7 @@
  • - @@ -121,7 +118,7 @@
  • - @@ -130,7 +127,7 @@
    • - @@ -149,7 +146,7 @@
    • - @@ -159,7 +156,7 @@
      • - diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/overlays/rowdeleteconfirm.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/overlays/rowdeleteconfirm.html new file mode 100644 index 0000000000..2ba56a5b88 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/overlays/rowdeleteconfirm.html @@ -0,0 +1,16 @@ +
        + +
        + You are deleting the row configuration {{model.layout.name}}. +
        + +

        + + Modifying a row configuration name will result in loss of + data for any existing content that is based on this configuration. + +

        + + ? + +
        diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/icon.prevalues.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/icon.prevalues.html index 2d3d4eeae2..8a11cb516d 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/icon.prevalues.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/icon.prevalues.html @@ -2,7 +2,7 @@
        - +
        diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/includeproperties.prevalues.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/includeproperties.prevalues.html index 0499bea713..42597f0c82 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/includeproperties.prevalues.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/includeproperties.prevalues.html @@ -1,10 +1,12 @@ 
        - + diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/layouts.prevalues.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/layouts.prevalues.controller.js index a02215f452..acfb114307 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/layouts.prevalues.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/layouts.prevalues.controller.js @@ -15,6 +15,8 @@ vm.focusLayoutName = false; vm.layoutsSortableOptions = { + axis: "y", + containment: "parent", distance: 10, tolerance: "pointer", opacity: 0.7, @@ -41,7 +43,6 @@ }; $scope.model.value.push(layout); - } function showPrompt(layout) { diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/layouts.prevalues.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/layouts.prevalues.html index 1240a61fbb..acc3f1d261 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/layouts.prevalues.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/layouts.prevalues.html @@ -1,49 +1,54 @@
        -
        +
        -
        +
        - +
        -
        + - +
        -
        - -
        + -
        +
        + +
        -
        - - {{ layout.name }} - (system layout) -
        +
        -
        - -
        +
        + + {{ layout.name }} + (system layout) +
        -
        - -
        - - - -
        -
        +
        + +
        -
        +
        + - +
        + + +
        +
        -
        +
        + +
        + + + +
        diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/layouts/list/list.listviewlayout.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/layouts/list/list.listviewlayout.controller.js index 4230633e96..fd49d3f706 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/layouts/list/list.listviewlayout.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/layouts/list/list.listviewlayout.controller.js @@ -86,22 +86,20 @@ } function markAsSensitive() { - angular.forEach($scope.options.includeProperties, function (option) { + $scope.options.includeProperties.forEach(function (option) { option.isSensitive = false; - angular.forEach($scope.items, - function (item) { + $scope.items.forEach(function (item) { - angular.forEach(item.properties, - function (property) { + item.properties.forEach(function (property) { - if (option.alias === property.alias) { - option.isSensitive = property.isSensitive; - } + if (option.alias === property.alias) { + option.isSensitive = property.isSensitive; + } - }); + }); - }); + }); }); } diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.controller.js index 9a86dc575a..d98dc92f24 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.controller.js @@ -227,26 +227,21 @@ function listViewController($scope, $interpolate, $routeParams, $injector, $time if (err.status && err.status >= 500) { // Open ysod overlay - $scope.ysodOverlay = { - view: "ysod", - error: err, - show: true - }; + overlayService.ysod(err); } $timeout(function () { $scope.bulkStatus = ""; $scope.actionInProgress = false; - }, - 500); + }, 500); - if (successMsgPromise) { - localizationService.localize("bulk_done") - .then(function (v) { - successMsgPromise.then(function (successMsg) { - notificationsService.success(v, successMsg); - }) - }); + if (successMsgPromise) + { + localizationService.localize("bulk_done").then(function (v) { + successMsgPromise.then(function (successMsg) { + notificationsService.success(v, successMsg); + }) + }); } } @@ -271,7 +266,6 @@ function listViewController($scope, $interpolate, $routeParams, $injector, $time with simple values */ $scope.getContent = function (contentId) { - $scope.reloadView($scope.contentId, true); } @@ -327,8 +321,6 @@ function listViewController($scope, $interpolate, $routeParams, $injector, $time }); }; - - $scope.makeSearch = function() { if ($scope.options.filter !== null && $scope.options.filter !== undefined) { $scope.options.pageNumber = 1; @@ -408,7 +400,6 @@ function listViewController($scope, $interpolate, $routeParams, $injector, $time dialog.title = value; overlayService.open(dialog); }); - }; function performDelete() { @@ -704,8 +695,6 @@ function listViewController($scope, $interpolate, $routeParams, $injector, $time // set what we've got on the result result[alias] = value; }); - - } function isDate(val) { diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.html index ee1847b430..05a294cc1c 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.html @@ -14,29 +14,28 @@
        -
        - - - - @@ -53,13 +52,13 @@ - - @@ -230,11 +229,4 @@
        - - -
        diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/overlays/listviewpublish.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/overlays/listviewpublish.html index 027643eee1..c6f7c85c0b 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/overlays/listviewpublish.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/overlays/listviewpublish.html @@ -29,8 +29,8 @@ + text="{{language.name}}"> +
        diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/overlays/listviewunpublish.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/overlays/listviewunpublish.controller.js index df97d67f5d..650b1b8438 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/overlays/listviewunpublish.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/overlays/listviewunpublish.controller.js @@ -18,7 +18,7 @@ $scope.model.disableSubmitButton = !firstSelected; if (language.isMandatory) { - angular.forEach($scope.model.languages, function (lang) { + $scope.model.languages.forEach(function (lang) { if (lang !== language) { lang.unpublish = true; lang.disabled = language.unpublish; diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/overlays/listviewunpublish.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/overlays/listviewunpublish.html index 254187bdd1..5806bb8f02 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/overlays/listviewunpublish.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/overlays/listviewunpublish.html @@ -30,8 +30,8 @@ model="language.unpublish" on-change="vm.changeSelection(language)" text="{{language.name}}" - disabled="language.disabled" - /> + disabled="language.disabled"> +
        diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.html index 59e6fcd21c..f87c88a467 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.html @@ -31,6 +31,7 @@ diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/membergrouppicker/membergrouppicker.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/membergrouppicker/membergrouppicker.html index 4c53ac5d17..b1cafafb0d 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/membergrouppicker/membergrouppicker.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/membergrouppicker/membergrouppicker.html @@ -10,13 +10,11 @@
        - + diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/membergroups/membergroups.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/membergroups/membergroups.html index 9b59d48ab9..2715e11b15 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/membergroups/membergroups.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/membergroups/membergroups.html @@ -1,11 +1,15 @@ diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/memberpicker/memberpicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/memberpicker/memberpicker.controller.js index 95e595a97a..c3137360e2 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/memberpicker/memberpicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/memberpicker/memberpicker.controller.js @@ -56,10 +56,9 @@ function memberPickerController($scope, entityResource, iconHelper, angularHelpe }; editorService.treePicker(memberPicker); - }; - $scope.remove =function(index){ + $scope.remove = function (index) { $scope.renderModel.splice(index, 1); }; diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/memberpicker/memberpicker.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/memberpicker/memberpicker.html index d968f08d71..99f7fffba8 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/memberpicker/memberpicker.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/memberpicker/memberpicker.html @@ -10,13 +10,12 @@
        - + diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/multipletextbox/multipletextbox.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/multipletextbox/multipletextbox.controller.js index aaf41f3083..42ce10c519 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/multipletextbox/multipletextbox.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/multipletextbox/multipletextbox.controller.js @@ -17,7 +17,7 @@ $scope.model.value = []; } - //add any fields that there isn't values for + // Add any fields that there isn't values for if ($scope.model.config.min > 0) { for (var i = 0; i < $scope.model.config.min; i++) { if ((i + 1) > $scope.model.value.length) { @@ -37,7 +37,7 @@ if ($scope.model.config.max <= 0 && txtBoxValue.value || $scope.model.value.length < $scope.model.config.max && txtBoxValue.value) { var newItemIndex = index + 1; $scope.model.value.splice(newItemIndex, 0, { value: "" }); - //Focus on the newly added value + // Focus on the newly added value $scope.model.value[newItemIndex].hasFocus = true; } break; @@ -47,7 +47,7 @@ var remainder = []; // Used to require an extra hit on backspace for the field to be removed - if(txtBoxValue.value === "") { + if (txtBoxValue.value === "") { backspaceHits++; } else { backspaceHits = 0; @@ -64,11 +64,11 @@ var prevItemIndex = index - 1; - //Set focus back on false as the directive only watches for true - if(prevItemIndex >= 0) { + // Set focus back on false as the directive only watches for true + if (prevItemIndex >= 0) { $scope.model.value[prevItemIndex].hasFocus = false; $timeout(function () { - //Focus on the previous value + // Focus on the previous value $scope.model.value[prevItemIndex].hasFocus = true; }); } @@ -81,12 +81,13 @@ default: } validate(); - } + }; $scope.add = function () { if ($scope.model.config.max <= 0 || $scope.model.value.length < $scope.model.config.max) { $scope.model.value.push({ value: "" }); - // focus new value + + // Focus new value var newItemIndex = $scope.model.value.length - 1; $scope.model.value[newItemIndex].hasFocus = true; } @@ -106,7 +107,7 @@ $scope.model.value = remainder; }; - $scope.showPrompt = function (idx, item){ + $scope.showPrompt = function (idx, item) { var i = $scope.model.value.indexOf(item); @@ -114,11 +115,11 @@ if (i === idx) { $scope.promptIsVisible = i; } - } + }; - $scope.hidePrompt = function(){ + $scope.hidePrompt = function () { $scope.promptIsVisible = "-1"; - } + }; function validate() { if ($scope.multipleTextboxForm) { @@ -126,10 +127,22 @@ $scope.multipleTextboxForm.mandatory.$setValidity("minCount", !invalid); } } + $timeout(function () { validate(); }); - + + // We always need to ensure we dont submit anything broken + var unsubscribe = $scope.$on("formSubmitting", function (ev, args) { + + // Filter to items with values + $scope.model.value = $scope.model.value.filter(el => el.value.trim() !== "") || []; + }); + + // When the scope is destroyed we need to unsubscribe + $scope.$on('$destroy', function () { + unsubscribe(); + }); } angular.module("umbraco").controller("Umbraco.PropertyEditors.MultipleTextBoxController", MultipleTextBoxController); diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/multipletextbox/multipletextbox.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/multipletextbox/multipletextbox.html index 85221c61f7..6a9826ac3c 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/multipletextbox/multipletextbox.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/multipletextbox/multipletextbox.html @@ -2,19 +2,20 @@
        - + +
        - - + +
        - - @@ -22,11 +23,13 @@
        - Add - + +
        diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/multiurlpicker/multiurlpicker.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/multiurlpicker/multiurlpicker.html index ff1969aab8..36c4f8cf84 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/multiurlpicker/multiurlpicker.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/multiurlpicker/multiurlpicker.html @@ -1,6 +1,6 @@ 
        -

        -

        +

        You have picked a content item currently deleted or in the recycle bin

        +

        You have picked content items currently deleted or in the recycle bin

        @@ -17,13 +17,14 @@
        - +
        @@ -40,21 +41,21 @@ Add {{model.config.minNumber - renderModel.length}} item(s) - You can only have {{model.config.maxNumber}} items selected + You can only have {{model.config.maxNumber}} url(s) selected - Add up to {{model.config.maxNumber}} items + Add up to {{model.config.maxNumber}} url(s) - You can only have {{model.config.maxNumber}} items selected + You can only have {{model.config.maxNumber}} url(s) selected - Add at least {{model.config.minNumber}} item(s) + You need to add at least {{model.config.minNumber}} url(s)
        @@ -65,12 +66,12 @@
        - You need to add at least {{model.config.minNumber}} items + You need to add at least {{model.config.minNumber}} url(s)
        - You can only have {{model.config.maxNumber}} items selected + You can only have {{model.config.maxNumber}} url(s) selected
        diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.controller.js index fe9725a7d8..11a3b58c55 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.controller.js @@ -98,6 +98,8 @@ vm.wideMode = Object.toBoolean(model.config.hideLabel); vm.hasContentTypes = model.config.contentTypes.length > 0; + var cultureChanged = eventsService.on('editors.content.cultureChanged', (name, args) => updateModel()); + var labels = {}; vm.labels = labels; localizationService.localizeMany(["grid_addElement", "content_createEmpty", "actions_copy"]).then(function (data) { @@ -167,8 +169,6 @@ isDisabled: true } - - // helper to force the current form into the dirty state function setDirty() { if ($scope.$parent.$parent.propertyForm) { @@ -187,17 +187,29 @@ }; vm.openNodeTypePicker = function ($event) { - if (vm.overlayMenu || vm.nodes.length >= vm.maxItems) { + + if (vm.nodes.length >= vm.maxItems) { return; } - vm.overlayMenu = { - show: false, - style: {}, - filter: vm.scaffolds.length > 12 ? true : false, + var availableItems = []; + _.each(vm.scaffolds, function (scaffold) { + availableItems.push({ + alias: scaffold.contentTypeAlias, + name: scaffold.contentTypeName, + icon: iconHelper.convertFromLegacyIcon(scaffold.icon), + tooltip: scaffold.documentType.description + }); + }); + + const dialog = { + view: "itempicker", orderBy: "$index", view: "itempicker", event: $event, + filter: availableItems.length > 12, + size: availableItems.length > 6 ? "medium" : "small", + availableItems: availableItems, clickPasteItem: function (item) { if (item.type === "elementTypeArray") { _.each(item.data, function (entry) { @@ -206,44 +218,30 @@ } else { pasteFromClipboard(item.data); } - vm.overlayMenu.show = false; - vm.overlayMenu = null; + + overlayService.close(); }, submit: function (model) { if (model && model.selectedItem) { addNode(model.selectedItem.alias); } - vm.overlayMenu.show = false; - vm.overlayMenu = null; + + overlayService.close(); }, close: function () { - vm.overlayMenu.show = false; - vm.overlayMenu = null; + overlayService.close(); } }; - // this could be used for future limiting on node types - vm.overlayMenu.availableItems = []; - _.each(vm.scaffolds, function (scaffold) { - vm.overlayMenu.availableItems.push({ - alias: scaffold.contentTypeAlias, - name: scaffold.contentTypeName, - icon: iconHelper.convertFromLegacyIcon(scaffold.icon), - tooltip: scaffold.documentType.description - }); - }); - - if (vm.overlayMenu.availableItems.length === 0) { + if (dialog.availableItems.length === 0) { return; } - vm.overlayMenu.size = vm.overlayMenu.availableItems.length > 6 ? "medium" : "small"; - - vm.overlayMenu.pasteItems = []; + dialog.pasteItems = []; var singleEntriesForPaste = clipboardService.retriveEntriesOfType("elementType", contentTypeAliases); _.each(singleEntriesForPaste, function (entry) { - vm.overlayMenu.pasteItems.push({ + dialog.pasteItems.push({ type: "elementType", name: entry.label, data: entry.data, @@ -253,7 +251,7 @@ var arrayEntriesForPaste = clipboardService.retriveEntriesOfType("elementTypeArray", contentTypeAliases); _.each(arrayEntriesForPaste, function (entry) { - vm.overlayMenu.pasteItems.push({ + dialog.pasteItems.push({ type: "elementTypeArray", name: entry.label, data: entry.data, @@ -261,26 +259,27 @@ }); }); - vm.overlayMenu.title = labels.grid_addElement; - vm.overlayMenu.hideHeader = vm.overlayMenu.pasteItems.length > 0; + dialog.title = dialog.pasteItems.length > 0 ? labels.grid_addElement : labels.content_createEmpty; - vm.overlayMenu.clickClearPaste = function ($event) { + dialog.clickClearPaste = function ($event) { $event.stopPropagation(); $event.preventDefault(); clipboardService.clearEntriesOfType("elementType", contentTypeAliases); clipboardService.clearEntriesOfType("elementTypeArray", contentTypeAliases); - vm.overlayMenu.pasteItems = [];// This dialog is not connected via the clipboardService events, so we need to update manually. - vm.overlayMenu.hideHeader = false; + dialog.pasteItems = [];// This dialog is not connected via the clipboardService events, so we need to update manually. + dialog.overlayMenu.hideHeader = false; }; - if (vm.overlayMenu.availableItems.length === 1 && vm.overlayMenu.pasteItems.length === 0) { + if (dialog.availableItems.length === 1 && dialog.pasteItems.length === 0) { // only one scaffold type - no need to display the picker addNode(vm.scaffolds[0].contentTypeAlias); - vm.overlayMenu = null; + + dialog.close(); + return; } - vm.overlayMenu.show = true; + overlayService.open(dialog); }; vm.editNode = function (idx) { @@ -507,8 +506,7 @@ if (tab) { scaffold.variants[0].tabs.push(tab); - angular.forEach(tab.properties, - function (property) { + tab.properties.forEach(function (property) { if (_.find(notSupported, function (x) { return x === property.editor; })) { property.notSupported = true; // TODO: Not supported message to be replaced with 'content_nestedContentEditorNotSupported' dictionary key. Currently not possible due to async/timing quirk. @@ -713,6 +711,7 @@ $scope.$on("$destroy", function () { unsubscribe(); + cultureChanged(); watcher(); }); diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.propertyeditor.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.propertyeditor.html index 896f8cf4a4..2f3856b101 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.propertyeditor.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.propertyeditor.html @@ -47,13 +47,17 @@
        - + No content types are configured for this property.
        - @@ -75,12 +79,4 @@ - - -
        diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.prevalues.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.prevalues.controller.js index 33e2b834f3..47d1f401c7 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.prevalues.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.prevalues.controller.js @@ -29,11 +29,15 @@ angular.module("umbraco").controller("Umbraco.PrevalueEditors.RteController", // extend commands with properties for font-icon and if it is a custom command $scope.tinyMceConfig.commands = _.map($scope.tinyMceConfig.commands, function (obj) { var icon = getFontIcon(obj.alias); - return angular.extend(obj, { + + var objCmd = Utilities.extend(obj, { fontIcon: icon.name, isCustom: icon.isCustom, - selected: $scope.model.value.toolbar.indexOf(obj.alias) >= 0 + selected: $scope.model.value.toolbar.indexOf(obj.alias) >= 0, + icon: "mce-ico " + (icon.isCustom ? ' mce-i-custom ' : ' mce-i-') + icon.name }); + + return objCmd; }); }); diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.prevalues.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.prevalues.html index d70f469e6f..96de0cd040 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.prevalues.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.prevalues.html @@ -2,11 +2,12 @@
        - +
        @@ -14,10 +15,12 @@
        - + +
        diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/slider.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/slider.html index ea0c2ef7bc..27c59194c1 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/slider.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/slider.html @@ -1,6 +1,6 @@ -
        +
        -
        +
        + +
        + + +
        + + + + + +
        diff --git a/src/Umbraco.Web.UI.Client/src/views/relationTypes/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/relationTypes/edit.controller.js index a39b48c278..a0b2a6afa1 100644 --- a/src/Umbraco.Web.UI.Client/src/views/relationTypes/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/relationTypes/edit.controller.js @@ -102,7 +102,7 @@ function RelationTypeEditController($scope, $routeParams, relationTypeResource, function formatDates(relations) { if (relations) { userService.getCurrentUser().then(function (currentUser) { - angular.forEach(relations, function (relation) { + relations.forEach(function (relation) { relation.timestampFormatted = dateHelper.getLocalDate(relation.createDate, currentUser.locale, 'LLL'); }); }); diff --git a/src/Umbraco.Web.UI.Client/src/views/stylesheets/infiniteeditors/richtextrule/richtextrule.html b/src/Umbraco.Web.UI.Client/src/views/stylesheets/infiniteeditors/richtextrule/richtextrule.html index cc5487d747..20c62cbd77 100644 --- a/src/Umbraco.Web.UI.Client/src/views/stylesheets/infiniteeditors/richtextrule/richtextrule.html +++ b/src/Umbraco.Web.UI.Client/src/views/stylesheets/infiniteeditors/richtextrule/richtextrule.html @@ -2,7 +2,7 @@ - + - - ' - + + diff --git a/src/Umbraco.Web.UI.Client/src/views/stylesheets/views/rules/rules.controller.js b/src/Umbraco.Web.UI.Client/src/views/stylesheets/views/rules/rules.controller.js index 7a3a51cf2e..de2865d843 100644 --- a/src/Umbraco.Web.UI.Client/src/views/stylesheets/views/rules/rules.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/stylesheets/views/rules/rules.controller.js @@ -59,7 +59,6 @@ angular.module("umbraco").controller("Umbraco.Editors.StyleSheets.RulesControlle }; editorService.open(ruleDialog); - } function setDirty() { diff --git a/src/Umbraco.Web.UI.Client/src/views/stylesheets/views/rules/rules.html b/src/Umbraco.Web.UI.Client/src/views/stylesheets/views/rules/rules.html index 213499740f..8187b88152 100644 --- a/src/Umbraco.Web.UI.Client/src/views/stylesheets/views/rules/rules.html +++ b/src/Umbraco.Web.UI.Client/src/views/stylesheets/views/rules/rules.html @@ -9,13 +9,11 @@
        - -
        - {{rule.name}} -
        + +
        {{rule.name}}
        - Edit - Remove + +
        diff --git a/src/Umbraco.Web.UI.Client/src/views/templates/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/templates/edit.controller.js index 2e3bc6eb80..7b527804f5 100644 --- a/src/Umbraco.Web.UI.Client/src/views/templates/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/templates/edit.controller.js @@ -549,7 +549,7 @@ var availableMasterTemplates = []; // filter out the current template and the selected master template - angular.forEach(vm.templates, function (template) { + vm.templates.forEach(function (template) { if (template.alias !== vm.template.alias && template.alias !== vm.template.masterTemplateAlias) { var templatePathArray = template.path.split(','); // filter descendant templates of current template @@ -602,7 +602,7 @@ function getMasterTemplateName(masterTemplateAlias, templates) { if (masterTemplateAlias) { var templateName = ""; - angular.forEach(templates, function (template) { + templates.forEach(function (template) { if (template.alias === masterTemplateAlias) { templateName = template.name; } diff --git a/src/Umbraco.Web.UI.Client/src/views/templates/edit.html b/src/Umbraco.Web.UI.Client/src/views/templates/edit.html index c5ad1b68d0..255b2c4885 100644 --- a/src/Umbraco.Web.UI.Client/src/views/templates/edit.html +++ b/src/Umbraco.Web.UI.Client/src/views/templates/edit.html @@ -30,12 +30,11 @@
        - - - - +
        - +
        @@ -97,7 +102,7 @@ - + - + diff --git a/src/Umbraco.Web.UI.Client/src/views/users/group.controller.js b/src/Umbraco.Web.UI.Client/src/views/users/group.controller.js index f996e944db..4ca4576755 100644 --- a/src/Umbraco.Web.UI.Client/src/views/users/group.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/users/group.controller.js @@ -185,7 +185,7 @@ * however the list to display the permissions isn't via the dictionary way so we need to format it */ function formatGranularPermissionSelection() { - angular.forEach(vm.userGroup.assignedPermissions, function (node) { + vm.userGroup.assignedPermissions.forEach(function (node) { formatGranularPermissionSelectionForNode(node); }); } @@ -193,8 +193,8 @@ function formatGranularPermissionSelectionForNode(node) { //the dictionary is assigned via node.permissions we will reformat to node.allowedPermissions node.allowedPermissions = []; - angular.forEach(node.permissions, function (permissions, key) { - angular.forEach(permissions, function (p) { + Object.values(node.permissions).forEach(function (permissions) { + permissions.forEach(function (p) { if (p.checked) { node.allowedPermissions.push(p); } @@ -299,7 +299,7 @@ } function setSectionIcon(sections) { - angular.forEach(sections, function (section) { + sections.forEach(function (section) { section.icon = "icon-section"; }); } diff --git a/src/Umbraco.Web.UI.Client/src/views/users/user.controller.js b/src/Umbraco.Web.UI.Client/src/views/users/user.controller.js index 2845c8df68..df2bd997b4 100644 --- a/src/Umbraco.Web.UI.Client/src/views/users/user.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/users/user.controller.js @@ -269,7 +269,7 @@ submit: function (model) { // select items if (model.selection) { - angular.forEach(model.selection, function (item) { + model.selection.forEach(function (item) { if (item.id === "-1") { item.name = vm.labels.contentRoot; item.icon = "icon-folder"; @@ -298,7 +298,7 @@ submit: function (model) { // select items if (model.selection) { - angular.forEach(model.selection, function (item) { + model.selection.forEach(function (item) { if (item.id === "-1") { item.name = vm.labels.mediaRoot; item.icon = "icon-folder"; @@ -321,7 +321,7 @@ var found = false; // check if item is already in the selected list if (selection.length > 0) { - angular.forEach(selection, function (selectedItem) { + selection.forEach(function (selectedItem) { if (selectedItem.udi === item.udi) { found = true; } diff --git a/src/Umbraco.Web.UI.Client/src/views/users/views/groups/groups.controller.js b/src/Umbraco.Web.UI.Client/src/views/users/views/groups/groups.controller.js index 31c52a344b..4b81e7c11c 100644 --- a/src/Umbraco.Web.UI.Client/src/views/users/views/groups/groups.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/users/views/groups/groups.controller.js @@ -123,7 +123,7 @@ } function clearSelection() { - angular.forEach(vm.userGroups, function (userGroup) { + vm.userGroups.forEach(function (userGroup) { userGroup.selected = false; }); vm.selection = []; diff --git a/src/Umbraco.Web.UI.Client/src/views/users/views/users/users.controller.js b/src/Umbraco.Web.UI.Client/src/views/users/views/users/users.controller.js index 2217628872..cb211834b2 100644 --- a/src/Umbraco.Web.UI.Client/src/views/users/views/users/users.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/users/views/users/users.controller.js @@ -274,7 +274,7 @@ } function clearSelection() { - angular.forEach(vm.users, function (user) { + vm.users.forEach(function (user) { user.selected = false; }); vm.selection = []; @@ -305,7 +305,7 @@ vm.disableUserButtonState = "busy"; usersResource.disableUsers(vm.selection).then(function (data) { // update userState - angular.forEach(vm.selection, function (userId) { + vm.selection.forEach(function (userId) { var user = getUserFromArrayById(userId, vm.users); if (user) { user.userState = 1; @@ -326,7 +326,7 @@ vm.enableUserButtonState = "busy"; usersResource.enableUsers(vm.selection).then(function (data) { // update userState - angular.forEach(vm.selection, function (userId) { + vm.selection.forEach(function (userId) { var user = getUserFromArrayById(userId, vm.users); if (user) { user.userState = 0; @@ -345,7 +345,7 @@ vm.unlockUserButtonState = "busy"; usersResource.unlockUsers(vm.selection).then(function (data) { // update userState - angular.forEach(vm.selection, function (userId) { + vm.selection.forEach(function (userId) { var user = getUserFromArrayById(userId, vm.users); if (user) { user.userState = 0; @@ -423,14 +423,14 @@ function selectAll() { if (areAllSelected()) { vm.selection = []; - angular.forEach(vm.users, function (user) { + vm.users.forEach(function (user) { user.selected = false; }); } else { // clear selection so we don't add the same user twice vm.selection = []; // select all users - angular.forEach(vm.users, function (user) { + vm.users.forEach(function (user) { // prevent the current user to be selected if (!user.isCurrentUser) { user.selected = true; @@ -470,7 +470,7 @@ function getFilterName(array) { var name = vm.labels.all; var found = false; - angular.forEach(array, function (item) { + array.forEach(function (item) { if (item.selected) { if (!found) { name = item.name @@ -491,7 +491,7 @@ //If the selection is "ALL" then we need to unselect everything else since this is an 'odd' filter if (userState.key === "All") { - angular.forEach(vm.userStatesFilter, function (i) { + vm.userStatesFilter.forEach(function (i) { i.selected = false; }); //we can't unselect All @@ -500,7 +500,7 @@ vm.usersOptions.userStates = []; } else { - angular.forEach(vm.userStatesFilter, function (i) { + vm.userStatesFilter.forEach(function (i) { if (i.key === "All") { i.selected = false; } @@ -715,13 +715,13 @@ } function setUserDisplayState(users) { - angular.forEach(users, function (user) { + users.forEach(function (user) { user.userDisplayState = usersHelper.getUserStateFromValue(user.userState); }); } function formatDates(users) { - angular.forEach(users, function (user) { + users.forEach(function (user) { if (user.lastLoginDate) { var dateVal; var serverOffset = Umbraco.Sys.ServerVariables.application.serverTimeOffset; @@ -752,7 +752,7 @@ var firstSelectedUserGroups; - angular.forEach(users, function (user) { + users.forEach(function (user) { if (!user.selected) { return; diff --git a/src/Umbraco.Web.UI.Client/test/unit/app/propertyeditors/content-picker-controller.spec.js b/src/Umbraco.Web.UI.Client/test/unit/app/propertyeditors/content-picker-controller.spec.js index 49d8914ac6..c111421d75 100644 --- a/src/Umbraco.Web.UI.Client/test/unit/app/propertyeditors/content-picker-controller.spec.js +++ b/src/Umbraco.Web.UI.Client/test/unit/app/propertyeditors/content-picker-controller.spec.js @@ -5,11 +5,11 @@ describe('Content picker controller tests', function () { beforeEach(module('umbraco')); //inject the contentMocks service - beforeEach(inject(function ($rootScope, $controller, angularHelper, $httpBackend, entityMocks, mocksUtils, localizationMocks) { + beforeEach(inject(function ($rootScope, $controller, angularHelper, $httpBackend, entityMocks, mocksUtils, localizationMocks, userMocks) { //for these tests we don't want any authorization to occur - mocksUtils.disableAuth(); - + mocksUtils.setAuth(); + httpBackend = $httpBackend; scope = $rootScope.$new(); @@ -34,6 +34,7 @@ describe('Content picker controller tests', function () { //see /mocks/content.mocks.js for how its setup entityMocks.register(); localizationMocks.register(); + userMocks.register(); controller = $controller('Umbraco.PropertyEditors.ContentPickerController', { $scope: scope, @@ -42,7 +43,7 @@ describe('Content picker controller tests', function () { //For controller tests its easiest to have the digest and flush happen here //since its intially always the same $http calls made - + //scope.$digest resolves the promise against the httpbackend scope.$digest(); diff --git a/src/Umbraco.Web.UI.NetCore/Umbraco.Web.UI.NetCore.csproj b/src/Umbraco.Web.UI.NetCore/Umbraco.Web.UI.NetCore.csproj index f832deea13..3e1518abdd 100644 --- a/src/Umbraco.Web.UI.NetCore/Umbraco.Web.UI.NetCore.csproj +++ b/src/Umbraco.Web.UI.NetCore/Umbraco.Web.UI.NetCore.csproj @@ -21,6 +21,12 @@ + + + + + + diff --git a/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/cs.xml b/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/cs.xml index fe7e8ac638..4126d1d224 100644 --- a/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/cs.xml +++ b/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/cs.xml @@ -1,8 +1,8 @@ - umbraco - http://umbraco.org + Umbraco komunita + https://our.umbraco.com/documentation/Extending-Umbraco/Language-Files Kultura a názvy hostitelů @@ -11,10 +11,13 @@ Změnit typ dokumentu Kopírovat Vytvořit + Exportovat Vytvořit balíček + Vytvořit skupinu Odstranit Deaktivovat Vyprázdnit koš + Aktivovat Exportovat typ dokumentu Importovat typ dokumentu Importovat balíček @@ -28,17 +31,64 @@ Znovu načíst uzly Znovu publikovat celý web Práva + Přejmenovat + Obnovit + Nastavit oprávnění pro stránku %0% + Kam zkopírovat + Kam přesunout + do struktury stromu pod + Choose where to copy the selected item(s) + Choose where to move the selected item(s) + bylo přesunuto + bylo zkopírováno + bylo smazáno Vrátit starší verzi Odeslat k publikování Odeslat k překladu + Nastavit skupinu Seřadit Přeložit Aktualizovat + Nastavit oprávnění + Odemknout + Vytvořit šablonu obsahu + Přeposlat pozvánku + + + Obsah + Administrace + Struktura + Ostatní + + + Povolit přístup k přiřazování kultury a názvů hostitelů + Povolit přístup k zobrazení protokolu historie uzlu + Povolit přístup k zobrazení uzlu + Povolit přístup ke změně typu dokumentu daného uzlu + Povolit přístup ke kopírování uzlu + Povolit přístup k vytváření uzlů + Povolit přístup k mazání uzlů + Povolit přístup k přesunutí uzlu + Povolit přístup k nastavení a změně veřejného přístupu k uzlu + Povolit přístup k publikování uzlu + Povolit přístup k zrušení publikování uzlu + Povolit přístup ke změně oprávnění pro uzel + Povolit přístup k vrácení uzlu do předchozího stavu + Povolit přístup k odeslání uzlu ke schválení před publikováním + Povolit přístup k odeslání uzlu k překladu + Povolit přístup ke změně pořadí uzlů + Povolit přístup k překladu uzlu + Povolit přístup k uložení uzlu + Povolit přístup k vytvoření šablony obsahu + + + Obsah + Info Přístup zakázán. Přidat novou doménu - odebrat + Odebrat Neplatný uzel. Neplatný tvar domény. Doména už byla přiřazena. @@ -49,16 +99,17 @@ Doména '%0%' už byla přiřazena Doména '%0%' byla aktualizována Editace aktuálních domén + + Dědit Kultura nebo dědění kultury po nadřazeném uzlu. Vztahuje se také
        na aktivní uzel.]]>
        Domény - - Zobrazení pro - + Zrušit výběr Vybrat Dělat něco jiného Tučně @@ -77,15 +128,62 @@ Číslovaný seznam Vložit makro Vložit obrázek + Publikovat a zavřít + Publikovat s potomky Editovat vztahy + Zpět na seznam Uložit + Uložit a zavřít Uložit a publikovat + Uložit a naplánovat Uložit a odeslat ke schválení Náhled + Uložit zobrazení seznamu + Naplánovat + Náhled Náhled je deaktivován, protože není přiřazena žádná šablona Vybrat styl Zobrazit styly Vložit tabulku + Generovat modely a zavřít + Uložit a generovat modely + Zpět + Znovu + Obnovit + Smazat štítek + Zrušit + Potvrdit + Další možnosti publikování + + + Zobrazení pro + Obsah smazán + Obsah nepublikován + Obsah nepublikován pro jazyky: %0% + Obsah publikován + Obsah publikován pro jazyky: %0% + Obsah uložen + Obsah uložen pro jazyky: %0% + Obsah přesunut + Obsah zkopírován + Obsah vrácen zpět + Obsah odeslán k publikování + Obsah odeslán k publikování pro jazyky: %0% + Seřadit podřízené položky prováděné uživatelem + Kopírovat + Publikovat + Publikovat + Přesunout + Uložit + Uložit + Smazat + Nepublikovat + Nepublikovat + Vrátit zpět + Odeslat k publikování + Odeslat k publikování + Seřadit + Historie (všechny jazyky) Abyste změnili typ dokumentu pro zvolený obsah, nejprve jej vyberte ze seznamu typů platných pro tohle umístění. @@ -107,7 +205,14 @@ Nelze dokončit mapování vlastností, neboť nejméně jedna z vlastností má definováno více než jedno mapování. Jsou zobrazeny pouze alternativní typy platné pro aktuální umístění. + + Nepodařilo se vytvořit složku pod rodičem s ID %0% + Nepodařilo se vytvořit složku pod rodičem s názvem %0% + Název složky nesmí obsahovat nepovolené znaky. + Odstranění položky se nezdařilo: %0% + + Is Published O této stránce Alias (jak byste popsali obrázek přes telefon) @@ -124,45 +229,146 @@ Tato položko byla změněna po publikování Tato položka není publikována Naposledy publikováno + There are no items to show + There are no items to show in the list. + No child items have been added + No members have been added Typ média Odkaz na položky medií Skupina členů Role Typ člena + No changes have been made Nevybráno žádné datum Titulek stránky + This media item has no link + No content can be added for this item Vlastnosti Tento dokument je publikován, ale není viditelný, protože jeho rodič '%0%' publikován není + Tato jazyková verze je publikována, ale není viditelná, protože její rodič '%0%' publikován není Jejda: tento dokument je publikován, ale není v mezipaměti (vnitřní chyba) + Could not get the url + This document is published but its url would collide with content %0% + This document is published but its url cannot be routed Publikovat + Published + Published (pending changes)> Stav publikování + Publish with descendants to publish %0% and all content items underneath and thereby making their content publicly available.]]> + Publish with descendants to publish the selected languages and the same languages of content items underneath and thereby making their content publicly available.]]> Datum publikování Datum ukončení publikování Datum odebrání + Set date Třídění je aktualizováno Abyste uzly setřídili, jednoduše je přetáhněte anebo klikněte na jednu z hlaviček sloupce. Podržením "shift" nebo "control" při výběru můžete označit uzlů více. Statistika Titulek (volitelně) + Alternative text (optional) Typ Nepublikovat + Draft + Not created Naposledy změněno Datum/čas poslední změny dokumentu Odebrat soubor(y) + Click here to remove the image from the media item + Click here to remove the file from the media item URL adresa dokumentu Člen skupin(y) Není člen skupin(y) Podřízené položky Cíl + This translates to the following time on the server: + What does this mean?]]> + Are you sure you want to delete this item? + Are you sure you want to delete all items? + Property %0% uses editor %1% which is not supported by Nested Content. + No content types are configured for this property. + Add element type + Select element type + Select the group whose properties should be displayed. If left blank, the first group on the element type will be used. + Enter an angular expression to evaluate against each item for its name. Use + to display the item index + Add another text box + Remove this text box + Content root + Include drafts: also publish unpublished content items. + This value is hidden. If you need access to view this value please contact your website administrator. + This value is hidden. + What languages would you like to publish? All languages with content are saved! + What languages would you like to publish? + What languages would you like to save? + All languages with content are saved on creation! + What languages would you like to send for approval? + What languages would you like to schedule? + Select the languages to unpublish. Unpublishing a mandatory language will unpublish all languages. + Published Languages + Unpublished Languages + Unmodified Languages + These languages haven't been created + Ready to Publish? + Ready to Save? + Send for approval + Select the date and time to publish and/or unpublish the content item. + Create new + Paste from clipboard + This item is in the Recycle Bin + + + Vytvořit novou šablonu obsahu z '%0%' + Prázdná + Vybrat obsahovou šablonu + Šablona obsahu byla vytvořena + Šablona obsahu byla vytvořena z '%0%' + Již existuje jiná šablona obsahu se stejným názvem + Šablona obsahu je předdefinovaný obsah, který si editor může vybrat jako základ pro vytváření nového obsahu Klikněte pro nahrání + nebo kliknutím sem vyberte soubory + Sem můžete přetáhnout a nahrát soubory. + Tento soubor nelze nahrát, nemá povolený typ souboru + Maximální velikost souboru je + Nejvyšší složka médií + Nepodařilo se přesunout média + Nadřazené a cílové složky nemohou být stejné + Médium se nepodařilo zkopírovat + Nepodařilo se vytvořit složku pod nadřazeným id %0% + Nepodařilo se přejmenovat složku s id %0% + Přetáhněte své soubory do oblasti + + + Vytvořit nového člena + Všichni členové + Členské skupiny nemají žádné další vlastnosti pro úpravy. Kde chcete vytvořit nový %0% Vytvořit položku pod + Vyberte typ dokumentu, pro který chcete vytvořit šablonu obsahu + Zadejte název složky Vyberte typ a titulek "typy dokumentů".]]> + Typy dokumentů v části Nastavení.]]> + Vybraná stránka ve stromu obsahu neumožňuje vytváření žádných stránek pod ní. + Oprávnění k úpravám pro tento typ dokumentu + Vytvořit nový typ dokumentu + Typy dokumentů v části Nastavení změnou možnosti Povolit jako root v části Oprávnění.]]> "typy medií".]]> + Vybraná média ve stromu neumožňuje vytváření pod nimi žádná další média. + Upravit oprávnění pro tento typ média + Typ dokumentu bez šablony + Nová složka + Nový datový typ + Nový skript JavaScript + Nová prázdná částečná šablona + Nové makro pro částečnou šablonu + Nová částečná šablona ze snippetu + Nové makro částečné šablony ze snippetu + Nové makro pro částečnou šablonu (bez makra) + Nový soubor stylů - stylopis + Nový soubor stylů Rich Text editoru Prohlédnout svůj web @@ -174,35 +380,42 @@ Vítejte - Stay - Discard changes - You have unsaved changes - Are you sure you want to navigate away from this page? - you have unsaved changes + Zůstat zde + Zahodit změny + Máte neuložené změny + Opravdu chcete opustit tuto stránku? Máte neuložené změny. + Publikování zviditelní vybrané položky na webu. + Zrušení publikování odstraní vybrané položky a všechny jejich potomky z webu. + Zrušení publikování odstraní tuto stránku a všechny její potomky z webu. + Máte neuložené změny. Provedením změn typu dokumentu změny zahodíte. - Done - Deleted %0% item - Deleted %0% items - Deleted %0% out of %1% item - Deleted %0% out of %1% items - Published %0% item - Published %0% items - Published %0% out of %1% item - Published %0% out of %1% items - Unpublished %0% item - Unpublished %0% items - Unpublished %0% out of %1% item - Unpublished %0% out of %1% items - Moved %0% item - Moved %0% items - Moved %0% out of %1% item - Moved %0% out of %1% items - Copied %0% item - Copied %0% items - Copied %0% out of %1% item - Copied %0% out of %1% items + Hotovo + Smazána %0% položka + Smazáno %0% položek + Smazána %0% z %1% položek + Smazáno %0% z %1% položek + Publikována %0% položka + Publikováno %0% položek + Publikována %0% z %1% položek + Publikováno %0% z %1% položek + Zrušeno publikování %0% položky + Zrušeno publikování %0% položek + Zrušeno publikování %0% z %1% položek + Zrušeno publikování %0% z %1% položek + Přesunuta %0% položka + Přesunuto %0% položek + Přesunuta %0% z %1% položek + Přesunuto %0% z %1% položek + Zkopírována %0% položka + Zkopírováno %0% položek + Zkopírována %0% z %1% položek + Zkopírováno %0% z %1% položek + Titulek odkazu + Odkaz + Kotva / dotaz Název Spravovat názvy hostitelů Zavřít toto okno @@ -213,6 +426,7 @@ Vyjmout Editovat položku slovníku Editovat jazyk + Edit selected media Vložit místní odkaz Vložit znak Vložit grafický titulek @@ -220,14 +434,20 @@ Vložit odkaz Kliknout pro přidání makra Vložit tabulku + Tím se odstraní jazyk + Změna kultury jazyka může být náročná operace a bude mít za následek opětovné sestavení mezipaměti obsahu a indexů Naposledy editováno Odkaz Místní odkaz: Při používání místních odkazů vložte znak "#" před odkaz Otevřít v novém okně? + Nastavení makra Toto makro nemá žádné vlastnosti, které by bylo možno editovat Vložit Editovat oprávnění pro + Nastavit oprávnění pro + Nastavit oprávnění pro %0% pro skupinu %1% + Vyberte skupiny uživatelů, pro které chcete nastavit oprávnění Položky koše jsou nyní mazány. Nezavírejte, prosím, toto okno, dokud operace probíhá Koš je nyní prázdný Odebrání položek z koše způsobí jejich trvalé odstranění @@ -243,21 +463,109 @@ Klikněte na obrázek pro zobrazení v plné velikosti Vybrat položku Zobrazit položku mezipaměti + Navázat na originál + Včetně potomků + Nejpřátelštější komunita + Odkaz na stránku + Otevře propojený dokument v novém okně nebo na kartě + Odkaz na média + Vybrat počáteční uzel obsahu + Vybrat média + Vybrat typ média + Vybrat ikonu + Vybrat položku + Vybrat odkaz + Vybrat makro + Vybrat obsah + Vybrat typ obsahu + Vybrat počáteční uzel média + Vybrat člena + Vybrat skupinu členů + Vybrat typ člena + Vybrat uzel + Vybrat sekce + Vybrat uživatele + Nebyly nalezeny žádné ikony + Pro toto makro neexistují žádné parametry + K dispozici nejsou žádná makra + Externí poskytovatelé přihlášení + Podrobnosti o výjimce + Stacktrace + Vnitřní výjimka + Propojit se + Odpojit se + účet + Vybrat editora + Vybrat snippet + Tímto odstraníte uzel a všechny jeho jazyky. Pokud chcete smazat pouze jeden jazyk, měli byste zrušit publikování uzlu v tomto jazyce. + + + Nejsou žádné položky ve slovníku. %0%' níže.
        Můžete přidat další jazyky v nabídce 'jazyky' nalevo.]]>
        Název jazyka + + Přehled slovníku + + + Konfigurovaní vyhledávače + Zobrazuje vlastnosti a nástroje pro libovolný konfigurovaný vyhledávač (např. pro víceindexový vyhledávač) + Hodnoty pole + Stav + Stav indexu a jeho čitelnost + Indexery + Informace o indexu + Uvádí vlastnosti indexu + Spravovat indexy Examine + Umožňuje zobrazit podrobnosti každého indexu a poskytuje některé nástroje pro správu indexů + Znovu vytvořit index + V závislosti na tom, kolik obsahu je na vašem webu, může to chvíli trvat.
        Nedoporučuje se znovu vytvářet index v době vysokého provozu na webu nebo při úpravách obsahu editory. + ]]> +
        + Vyhledávače + Prohledat index a zobrazit výsledky + Nástroje + Nástroje pro správu indexu + pole + Index nelze číst a bude nutné jej znovu sestavit + Proces trvá déle, než se očekávalo, zkontrolujte Umbraco log a zkontrolujte, zda během této operace nedošlo k chybám + Tento index nelze znovu sestavit, protože nemá přiřazen + IIndexPopulator Zadejte Vaše uživatelské jméno Zadejte Vaše heslo + Potvrďte heslo Pojmenujte %0%... Zadejte jméno... + Zadejte e-mail... + Zadejte uživatelské jméno... + Popisek... + Zadejte popis... Pište pro vyhledání... Pište pro filtrování... + Pište pro vložení štítků (po každém stiskněte klávesu Enter)... + Vložte svůj e-mail + Vložte zprávu... + Vaše uživatelské jméno je obvykle váš e-mail + #hodnota or ?klíč=hodnota + Vložte alias... + Generování aliasu... + Vytvořit vlastní zobrazení seznamu + Odebrat vlastní zobrazení seznamu + Typ obsahu, typ média nebo typ člena s tímto aliasem již existuje + + + Přejmenováno + Sem zadejte nový název složky + %0% přejmenováno na %1% Přidat předlohu @@ -271,6 +579,15 @@ Související stylopisy Zobrazit jmenovku Šířka a výška + Všechny typy vlastností a údaje o nich + použití tohoto datového typu bude trvale smazáno, potvrďte, že je chcete odstranit + Ano, smazat + a všechny typy vlastností a data vlastností používající tento typ dat + Vyberte složku, kterou chcete přesunout + do stromové struktury níže + byla přesunuta pod + %0% vymažete vlastnosti a jejich data z následujících položek]]> + Rozumím, že tato akce odstraní vlastnosti a data založená na tomto datovém typu Vaše data byla uložena, ale než budete moci publikovat tuto stránku, je třeba odstranit některé chyby: @@ -286,10 +603,12 @@ %0% není ve správném formátu + Ze serveru byla přijata chyba Použití daného typu souboru bylo zakázáno adminitrátorem UPOZORNĚNÍ! I když CodeMirror je dle konfigurace povolený, je zakázaný v Internet Exploreru, protože není dost stabilní. Vyplňte, prosím, alias i název nového typu vlastností! Vyskytl se problém při čtení/zápisu do určeného souboru nebo adresáře + Chyba při načítání skriptu částečné šablony (soubor: %0%) Uveďte, prosím, titulek Vyberte, prosím, typ Chystáte se obrázek zvětšit více, než je jeho původní rozměr. Opravdu chcete pokračovat? @@ -298,34 +617,43 @@ Žádne aktivní styly nejsou dostupné Umístěte, prosím, kurzor nalevo od těch dvou buňek, které chcete sloučit Nemužete rozdělit buňku, která nebyla sloučená. + Tato vlastnost je neplatná + Volby O... Akce Akce Přidat Alias + Vše Jste si jistí? + Zpět + Zpět na přehled Okraj o Zrušit Okraj buňky Vybrat + Vyčistit Zavřít Zavřít okno Komentovat Potvrdit + Omezit Zachovat proporce + Obsah Pokračovat Kopírovat Vytvořit - Databáse + Databáze Datum Výchozí Odstranit Odstraněno Odstraňování... Vzhled + Slovník Rozměry Dolů Stáhnout @@ -334,55 +662,85 @@ Prvky Email Chyba + Pole Najít + První + Focal point + Obecné + Skupiny + Skupina Výška Nápověda + Skrýt + Historie Ikona + Id Import + Zahrnout podsložky do vyhledávání + Info Vnitřní okraj Vložit Instalovat + Neplatné Vyrovnat + Popisek Jazyk + Poslední Rozvržení + Odkazy Nahrávání Zamčeno Přihlášení Odhlášení Odhlášení Makro + Povinné + Zpráva Přesunout Název Nový Následující Ne z + Vypnuto OK Otevřít + Zapnuto nebo + Seřadit podle Heslo Cesta Moment, prosím... Předchozí Vlastnosti + Obnovit Email pro obdržení formulářových dat Koš + Váš koš je prázdný + Znovu načíst Zbývající + Odebrat Přejmenovat Obnovit Povinné + Načíst Zopakovat Oprávnění + Plánované publikování Hledat + Litujeme, ale nemůžeme najít to, co hledáte. + Nebyly přidány žádné položky Server + Nastavení Zobrazit Zobrazit stránku při odeslání Rozměr Seřadit - Submit - - Typ - Pro hledání pište... + Stav + Potvrdit + Zadejte + Pište pro vyhledávání... + pod Nahoru Aktualizovat Povýšit @@ -397,18 +755,57 @@ Ano Složka Výsledky hledání - Reorder - I am done reordering + Přesunout + Skončil jsem s přesouváním + Náhled + Změnit heslo + na + Seznam + Ukládám... + aktuální + Vložené + vybrané + Další + Články + Videa + Vyčistit + Instalování + + + Modrá + + + Přidat skupinu + Přidat vlastnost + Přidat editor + Přidat šablonu + Přidat vnořený uzel + Přidat potomka + Upravit datový typ + Navigace v sekcích + Klávesové zkratky + zobrazit klávesové zkratky + Přepnout zobrazení seznamu + Přepnout povolení jako root + Okomentovat/Odkomentovat řádky + Odebrat řádek + Kopírovat řádky nahoru + Kopírovat řádky dolů + Přesunout řádky nahoru + Přesunout řádky dolů + Obecný + Editor + Přepnout povolení jazykových verzí - Background color - Bold - Text color + Barva pozadí + Tučně + Barva písma Font Text - Page + Stránka Instalátor se nemůže připojit k databázi. @@ -441,7 +838,7 @@ Heslo výchozího uživatele bylo úspěšně změněno od doby instalace!

        Netřeba nic dalšího dělat. Klikněte na Následující pro pokračování.]]> Heslo je změněno! Mějte skvělý start, sledujte naše uváděcí videa - Kliknutím na tlačítko následující (nebo modifikováním umbracoConfigurationStatus v souboru web.config) přijímáte licenci tohoto software tak, jak je uvedena v poli níže. Upozorňujeme, že tato distribuce umbraca se skládá ze dvou různých licencí, open source MIT licence pro framework a umbraco freeware licence, která pokrývá UI. + Kliknutím na tlačítko následující (nebo modifikováním umbracoConfigurationStatus v souboru web.config) přijímáte licenci tohoto software tak, jak je uvedena v poli níže. Upozorňujeme, že tato distribuce Umbraca se skládá ze dvou různých licencí, open source MIT licence pro framework a umbraco freeware licence, která pokrývá UI. Není nainstalováno. Dotčené soubory a složky Další informace o nastavování oprávnění pro umbraco zde @@ -515,8 +912,8 @@ Stiskněte "následující" pro spuštění průvodce.]]> - Kód kultury - Název kultury + Kód jazyka + Název jazyka Byli jste nečinní a odhlášení proběhne automaticky za @@ -531,8 +928,100 @@ Šťastný bláznivý pátek Šťastnou kočkobotu přihlašte se níže + Přihlásit se pomocí Relace vypršela © 2001 - %0%
        umbraco.org

        ]]>
        + Zapomenuté heslo? + Na uvedenou adresu bude zaslán e-mail s odkazem pro obnovení hesla + Pokud odpovídá našim záznamům, bude na zadanou adresu zaslán e-mail s pokyny k obnovení hesla + Zobrazit heslo + Skrýt heslo + Vrátit se na přihlašovací obrazovku + Zadejte nové heslo + Vaše heslo bylo aktualizováno + Odkaz, na který jste klikli, je neplatný nebo jeho platnost vypršela + Umbraco: Resetování hesla + + + + + + + + + + + +
        + + + + + +
        + +
        + +
        +
        + + + + + + +
        +
        +
        + + + + +
        + + + + +
        +

        + Vyžadováno resetování hesla +

        +

        + Vaše uživatelské jméno pro přihlášení do back-office Umbraco je: %0% +

        +

        + + + + + + +
        + + Kliknutím na tento odkaz obnovíte své heslo + +
        +

        +

        Pokud nemůžete kliknout na odkaz, zkopírujte a vložte tuto adresu URL do okna prohlížeče:

        + + + + +
        + + %1% + +
        +

        +
        +
        +


        +
        +
        + + + ]]>
        Ovládací panel @@ -555,6 +1044,7 @@ Upravte vaše oznámení pro %0% + Nastavení oznámení bylo uloženo pro - Hi %0%

        + Následující jazyky byly změněny %0% + Ahoj %0%

        Toto je automatická zpráva informující Vás, že úloha '%1%' byla provedena na stránce '%2%' @@ -595,14 +1086,68 @@

        Mějte hezký den!

        Zdraví umbraco robot

        ]]>
        + Byly změněny následující jazyky:

        + %0% + ]]>
        [%0%] Upozornění o %1% na %2% Upozornění + Akce + Vytvořeno + Vytvořit balíček a výběrem balíčku. Balíčky umbraco mají obvykle přípony ".umb" nebo ".zip". ]]> + Tím se balíček odstraní + Přetáhněte sem pro nahrání + Zahrnout všechny podřízené uzly + nebo kliknutím sem vyberte soubor balíčku + Nahrát balíček + Nainstalujte místní balíček výběrem ze svého počítače. Instalujte pouze balíčky ze zdrojů, které znáte a kterým důvěřujete + Nahrát další balíček + Zrušit a nahrát další balíček + Přijímám + podmínky použití + Cesta k souboru + Absolutní cesta k souboru (ie: /bin/umbraco.bin) + Nainstalováno + Nainstalované balíčky + Instalovat místní + Dokončit + Tento balíček nemá žádné zobrazení konfigurace + Zatím nebyly vytvořeny žádné balíčky + Nemáte nainstalované žádné balíčky + Balíčky v pravém horním rohu obrazovky.]]> + Akce balíčku + Web autora + Obsah balíčku + Soubory balíčku + URL ikony + Nainstalovat balíček + Licence + URL licence + Vlastnosti balíčku + Hledat balíčky + Výsledky pro + Nemohli jsme nic najít + Zkuste prosím vyhledat jiný balíček nebo procházet jednotlivé kategorie + Oblíbené + Nové + + karma body + Informace + Vlastník + Přispěvatelé + Vytvořeno + Aktuální verze + .NET verze + Počet stažení + Počet lajků + kompatibilita + Tento balíček je kompatibilní s následujícími verzemi Umbraco, jak ohlásili členové komunity. Plnou kompatibilitu nelze zaručit u verzí hlášených pod 100% + Externí zdroje Autor Dokumentace Meta data balíčku @@ -621,6 +1166,17 @@ Upozornění: všechny dokumenty, media atd. závislé na položkách, které odstraníte, přestanou pracovat a mohou vést k nestabilitě systému, takže odinstalovávejte opatrně. Jste-li na pochybách, kontaktujte autora balíčku.]]>
        Verze balíčku + Upgradování z verze + Balíček je již nainstalován + Tento balíček nelze nainstalovat, vyžaduje minimální verzi Umbraco + Odinstalovávám... + Stahuji... + Importuji... + Instaluji... + Restartuji, prosím čekejte... + Vše je hotovo, váš prohlížeč se nyní obnoví, prosím čekejte... + Klepnutím na tlačítko „Dokončit“ dokončete instalaci a znovu načtěte stránku. + Nahrávám balíček... Vložit s úplným formatováním (nedoporučeno) @@ -629,9 +1185,9 @@ Vložit, ale odstranit formátování (doporučeno) - Ochrana prostřednictvím rolí - použijte členské skupiny umbraca.]]> - Musíte vytvořit členskou skupinu před tím, než můžete použít autentizaci prostřednictvím rolí + Ochrana prostřednictvím rolí + použijte členské skupiny umbraca.]]> + Musíte vytvořit členskou skupinu před tím, než můžete použít autentizaci prostřednictvím rolí Chybová stránka Použita, když jsou lidé přihlášení, ale nemají přístup Vyberte, jak omezit přístup k této stránce @@ -640,16 +1196,28 @@ Přihlašovací stránka Vyberte stránku, která obsahuje přihlašovací formulář Odstranit ochranu + %0%?]]> Vyberte stránky, které obsahují přihlašovací formulář a chybová hlášení Vyberte role, které mají přístup k této stránce + %0%]]> + %0%]]> + Ochrana konkrétních členů + Pokud si přejete udělit přístup konkrétním členům Nastavte přihlašovací jmého a heslo pro tuto stránku Jednouživatelská ochrana Jestliže chcete nastavit jenom jednoduchou ochranu prostřednictvím uživatelského jména a hesla + Nedostatečná uživatelská oprávnění k publikování všech potomků + + @@ -659,7 +1227,9 @@ - Zahrnout nepublikované podřízené stránky + + + Ověření se nezdařilo pro požadovaný jazyk '% 0%'. Tento jazyk byl uložen, ale nezveřejněn. Probíhá publikování - počkejte, prosím... %0% ze %1% stránek bylo publikováno... %0% byla publikována @@ -668,23 +1238,49 @@ ok pro publikování %0% a tedy zveřejnění jejího obsahu.

        Můžete publikovat tuto stránku a všechny její podstránky zatrhnutím publikovat všchny podstránky níže. ]]>
        + Zahrnout nepublikované podřízené stránky Nenakonfigurovali jste žádné schválené barvy + + Můžete vybrat pouze položky typu (typů): %0% + Vybrali jste aktuálně odstraněnou položku obsahu nebo položku v koši + Vybrali jste aktuálně odstraněné položky obsahu nebo položky v koši + + + Smazaná položka + Vybrali jste aktuálně odstraněnou položku média nebo položku v koši + Vybrali jste aktuálně odstraněné položky médií nebo položky médií v koši + V koši + + zadejte externí odkaz + zvolte interní stránku + Nadpis + Odkaz + Otevřít v novém okně + zadejte titulek + Zadejte odkaz + Přidat vnější odkaz Přidat vnitřní odkaz Přidat - Nadpis Vnitřní stránka URL Posunout dolů Posunout nahoru - Otevřít v novém okně Odebrat odkaz + + Zrušit oříznutí + Uložit oříznutí + Přidat nové oříznutí + Hotovo + Vrátit změny + + Vyberte verzi, kterou chcete porovnat s aktuální verzí Současná verze Červený text nebude ve vybrané verzi zobrazen, zelený znamená přidaný].]]> Dokument byl vrácen na starší verzi @@ -697,20 +1293,29 @@ Editovat skriptovací soubor - Domovník Obsah + Formuláře + Média + Členové + Balíčky + Nastavení + Překlad + Uživatelé + + Domovník Kurýr Vývojář Průvodce nastavením Umbraca - Media - Členové Zpravodaje - Nastavení Statistiky - Překlad - Uživatelé Nápověda + + Příručky + Nejlepší videopříručky Umbraco + Navštívit our.umbraco.com + Navštívit umbraco.tv + Výchozí šablona Pro importování typu dokumentu vyhledejte soubor ".udt" ve svém počítači tak, že kliknete na tlačítko "Prohledat" a pak kliknete na "Import" (na následující obrazovce budete vyzváni k potvrzení) @@ -726,16 +1331,25 @@ Tento typ obsahu používá jako nadřazený typ obsahu. Záložky z nadřazených typů obsahu nejsou zobrazeny a mohou byt editovány pouze na nadřazených typech obsahu samotných Na této záložce nejsou definovány žádné vlastnosti. Pro vytvoření nové vlastnosti klikněte na odkaz "přidat novou vlastnost" nahoře. + Vytvořit odpovídající šablonu + Přidat ikonu - Sort order - Creation date + Řazení + Datum vytvoření Třídění bylo ukončeno. Abyste nastavili, jak mají být položky seřazeny, přetáhněte jednotlivé z nich nahoru či dolů. Anebo klikněte na hlavičku sloupce pro setřídění celé kolekce + Tato položka nemá vnořené položky k seřazení - Publikování bylo zrušeno doplňkem třetí strany + Validace + Před uložením položky je nutné opravit chyby + Chyba + Uloženo + Nedostatečná uživatelská oprávnění, operace nemohla být dokončena + Zrušeno + Operace byla zrušena doplňkem třetí strany Typ vlastnosti už existuje Typ vlastnosti vytvořen Datový typ: %1%]]> @@ -749,108 +1363,332 @@ Stylopis byl uložen bez chyb Datový typ byl uložen Položka slovníku byla uložena - Publikování se nezdařilo, protože nadřazená stránka není publikována Obsah byl publikován a je viditelný na webu + %0% dokumentů zveřejněných a viditelných na webu + %0% zveřejněných a viditelných na webu + %0% dokumentů zveřejněných pro jazyky %1% a viditelných na webu Obsah byl uložen Nezapomeňte na publikování, aby se změny projevily + Načasování publikování bylo aktualizováno + %0% uloženo Odeslat ke schválení Změny byly odeslány ke schválení - Medium bylo uloženo - Medium bylo uloženo bez chyb + %0% změn bylo odesláno ke schválení + Médium bylo uloženo + Médium bylo uloženo bez chyb Člen byl uložen + Skupina členů byla uložena Vlastnost stylopisu byla uložena Stylopis byl uložen Šablona byla uložena Chyba při ukládání uživatele (zkontrolujte log) Uživatel byl uložen Typ uživatele byl uložen + Skupina uživatelů byla uložena + Jazyky a názvy hostitelů byly uloženy + Při ukládání jazyků a názvů hostitelů došlo k chybě Soubor nebyl uložen soubor nemohl být uložen. Zkontrolujte, prosím, oprávnění k souboru Soubor byl uložen Soubor byl uložen bez chyb Jazyk byl uložen + Typ média byl uložen + Typ člena byl uložen + Skupina členů byla uložena Šablona nebyla uložena Ujistěte se, prosím, že nemáte 2 šablony se stejným aliasem Šablona byla uložena Šablona byla uložena bez chyb! Publikování obsahu bylo zrušeno + Varianta obsahu %0% nebyla publikována + Povinný jazyk '%0%' nebyl publikován. Všechny jazyky pro tuto položku obsahu nejsou nyní publikovány. Částečný pohled byl uložen Částečný pohled byl uložen bez chyb! Částečný pohled nebyl uložen Při ukládání souboru došlo k chybě. + Oprávnění byla uložena pro + Smazáno %0% skupin uživatelů + %0% bylo smazáno + Povoleno %0% uživatelů + Zakázáno %0% uživatelů + %0% je nyní povoleno + %0% je nyní zakázáno + Skupiny uživatelů byly nastaveny + Odemčeno %0% uživatelů + %0% je nyný odemčeno + Člen byl exportován do souboru + Při exportu člena došlo k chybě + Uživatel %0% byl smazán + Pozvat uživatele + Pozvánka byla znovu odeslána na %0% + Dokument nelze publikovat, protože %0% není publikována + Ověření pro jazyk '%0%' se nezdařilo + Typ dokumentu byl exportován do souboru + Při exportu typu dokumentu došlo k chybě + Datum vydání nemůže být v minulosti + Nelze naplánovat publikování dokumentu, protože %0% není publikována + Dokument nelze naplánovat na publikování, protože „%0%“ má datum zveřejnění později než nepovinný jazyk + Datum vypršení platnosti nemůže být v minulosti + Datum vypršení nemůže být před datem vydání + + Publikování bylo zrušeno doplňkem třetí strany + Publikování se nezdařilo, protože nadřazená stránka není publikována - Používá CSS syntaxi např.: h1, .redHeader, .blueTex + Přidat styl + Upravit styl + Styly Rich Text editoru + Definujte styly, které by měly být k dispozici v editoru formátovaného textu pro tuto šablonu stylů Editovat stylopis Editovat vlastnost stylopisu Název, který identifikuje vlastnost stylu v editoru formátovaného textu Náhled + Jak bude text vypadat v Rich Text editoru. + CSS identifikátor nebo třída + Používá syntaxi CSS, např. "h1" nebo ".redHeader" Styly + CSS, který by měl být použit v editoru RTF, např. "color:red;" + Kód + Rich Text editor + + Používá CSS syntaxi např.: h1, .redHeader, .blueTex + Nepodařilo se odstranit šablonu s ID %0% Editovat šablonu + Sekce Vložit obsahovou oblast Vložit zástupce obsahové oblasti + Vložit + Vyberte, co chcete vložit do své šablony Vložit položku slovníku + Položka slovníku je zástupný symbol pro překladatelný text, což usnadňuje vytváření návrhů pro vícejazyčné webové stránky. Vložit makro + + Makro je konfigurovatelná součást, která je skvělá pro opakovaně použitelné části návrhu, kde potřebujete předat parametry, jako jsou galerie, formuláře a seznamy. + Vložit pole stránky umbraco + Zobrazuje hodnotu pojmenovaného pole z aktuální stránky s možnostmi upravit hodnotu nebo alternativní hodnoty. + Částečná šablona + + Částečná šablona je samostatný soubor šablony, který lze vykreslit uvnitř jiné šablony. Je to skvělé pro opakované použití nebo pro oddělení složitých šablon. + Nadřazená šablona - Rychlá příručka k šablonovým značkám umbraca + Žádný master + Vykreslit podřízenou šablonu + @RenderBody(). + ]]> + Definujte pojmenovanou sekci + @section {...}. Ta může být vykreslena v konkrétní oblasti nadřazené šablony pomocí @RenderSection. + ]]> + Vykreslit pojmenovanou sekci + @RenderSection(name). Tím se vykreslí oblast podřízené šablony, která je zabalena do odpovídající definice @section[name] {...}. + ]]> + Název sekce + Sekce je povinná + @section, jinak se zobrazí chyba. + ]]> + Tvůrce dotazů + položky vráceny, do + zkopírovat do schránky + Chci + veškerý obsah + obsah typu "%0%" + z(e) + můj web + kde + a + je + není + před + před (včetně zvoleného datumu) + po + po (včetně zvoleného datumu) + rovná se + nerovná se + obsahuje + neobsahuje + větší než + větší nebo rovno + menší než + menší nebo rovno + Id + Název + Datum vytvoření + Datum poslední aktualizace + řadit podle + vzestupně + sestupně Šablona + + Rychlá příručka k šablonovým značkám umbraca - Image - Macro - Choose type of content - Choose a layout - Add a row - Add content - Drop content - Settings applied - This content is not allowed here - This content is allowed here - Click to embed - Click to insert image - Image caption... - Write here... - Grid Layouts - Layouts are the overall work area for the grid editor, usually you only need one or two different layouts - Add Grid Layout - Adjust the layout by setting column widths and adding additional sections - Row configurations - Rows are predefined cells arranged horizontally - Add row configuration - Adjust the row by setting cell widths and adding additional cells - Columns - Total combined number of columns in the grid layout - Settings - Configure what settings editors can change - Styles - Configure what styling editors can change - Allow all editors - Allow all row configurations + Obrázek + Makro + Vybrat typ obsahu + Vybrat rozvržení + Přidat řádek + Přidat obsah + Zahodit obsah + Nastavení aplikováno + Tento obsah zde není povolen + Tento obsah je zde povolen + Klepněte pro vložení + Klepnutím vložíte obrázek + Titulek obrázku... + Zde pište... + Rozvržení mřížky + Rozvržení je celková pracovní oblast pro editor mřížky, obvykle potřebujete pouze jedno nebo dvě různá rozvržení + Přidat rozvržení mřížky + Upravte rozvržení nastavením šířky sloupců a přidáním dalších sekcí + Konfigurace řádků + Řádky jsou předdefinované buňky uspořádané vodorovně + Přidat konfiguraci řádku + Upravte řádek nastavením šířky buněk a přidáním dalších buněk + Sloupce + Celkový počet sloupců v rozvržení mřížky + Nastavení + Nakonfigurujte, jaká nastavení mohou editoři změnit + Styly + Nakonfigurujte, co mohou editoři stylů změnit + Povolit všechny editory + Povolit všechny konfigurace řádků + Maximální počet položek + Nechte prázdné nebo nastavte na 0 pro neomezené + Nastavit jako výchozí + Vyberat navíc + Zvolit výchozí + jsou přidány + Varování + Odstraňujete konfiguraci řádku + + Odstranění názvu konfigurace řádku povede ke ztrátě dat pro veškerý existující obsah založený na této konfiguraci. + + + + Složení + Skupina + Nepřidali jste žádné skupiny + Přidat skupinu + Zděděno od + Přidat vlastnost + Požadovaný popisek + Povolit zobrazení seznamu + Nakonfiguruje položku obsahu tak, aby zobrazovala seznam svých potomků a seznam potomků, které je možné prohledávat, potomci se nebudou zobrazovat ve stromu + Povolené šablony + Vyberte, kteří editoři šablon mohou používat obsah tohoto typu + Povolit jako root + Povolit editorům vytvářet obsah tohoto typu v kořenovém adresáři stromu obsahu. + Povolené typy podřízených uzlů + Povolit vytváření obsahu zadaných typů pod obsahem tohoto typu. + Vybrat podřízený uzel + Zdědí záložky a vlastnosti z existujícího typu dokumentu. Nové záložky budou přidány do aktuálního typu dokumentu nebo sloučeny, pokud existuje záložka se stejným názvem. + Tento typ obsahu se používá ve složení, a proto jej nelze poskládat. + Nejsou k dispozici žádné typy obsahu, které lze použít jako složení. + Odebráním složení odstraníte všechna související data vlastností. Jakmile uložíte typ dokumentu, již není cesta zpět. + Vytvořit nové + Použít existující + Nastavení editoru + Konfigurace + Ano, smazat + bylo přesunuto pod + bylo zkopírováno pod + Vybrat složku, kterou chcete přesunout + Vybrat složku, kterou chcete kopírovat + ve stromové struktuře níže + Všechny typy dokumentů + Všechny dokumenty + Všechny média + použití tohoto typu dokumentu bude trvale smazáno, prosím potvrďte, že je chcete také odstranit. + použití tohoto typu média bude trvale smazáno, potvrďte, že je chcete také odstranit. + použití tohoto typu člena bude trvale smazáno, potvrďte, že je chcete také odstranit + a všechny dokumenty používající tento typ + a všechny mediální položky používající tento typ + a všichni členové používající tento typ + Člen může upravovat + Povolit editaci této vlastnosti členem na jeho stránce profilu + Obsahuje citlivá data + Skrýt tuto hodnotu vlastnosti před editory obsahu, kteří nemají přístup k prohlížení citlivých informací + Zobrazit v profilu člena + Povolit zobrazení této vlastnosti na stránce profilu člena + záložka nemá žádné řazení + Kde se toto složení používá? + Toto složení se v současnosti používá ve složení následujících typů obsahu: + Povolit různé jazyky + Povolit editorům vytvářet obsah tohoto typu v různých jazycích. + Povolit různé jazyky + Typ prvku + Je typ prvku + Typ prvku je určen k použití například ve vnořeném obsahu, nikoli ve stromu. + Jakmile byl typ dokumentu použit k vytvoření jedné nebo více položek obsahu, nelze jej změnit na typ prvku. + To neplatí pro typ prvku + V této vlastnosti jste provedli změny. Opravdu je chcete zahodit? + + + Přidat jazyk + Povinný jazyk + Před publikováním uzlu je nutné vyplnit vlastnosti v tomto jazyce. + Výchozí jazyk + Web Umbraco může mít nastaven pouze jeden výchozí jazyk. + Přepnutí výchozího jazyka může mít za následek chybějící výchozí obsah. + Nahradit nepřeložený obsah za + Žádné nahrazení nepřeloženého jazyka + Chcete-li povolit automatické zobrazení vícejazyčného obsahu v jiném jazyce, pokud není v požadovaném jazyce přeložen, vyberte jej zde. + Nahrazujicí jazyk + žádný + + + Přidat parametr + Upravit parametr + Zadejte název makra + Parametry + Definujte parametry, které by měly být k dispozici při použití tohoto makra. + Vyberte soubor makra pro částečnou šablonu + + + Stavební modely + to může chvíli trvat, nebojte se + Generované modely + Modely nelze vygenerovat + Generování modelů selhalo, viz výjimka v logu Umbraca + Přidat záložní pole + Náhradní pole + Přidat výchozí hodnotu + Výchozí hodnota Alternativní pole Alternativní text Velká a malá písmena Kódování Vybrat pole - Konvertovat + Konvertovat + Ano, převést konce řádků Nahrazuje nové řádky html tagem &lt;br&gt; Vlastní pole Ano, pouze datum + Formát a kódování Formátovat jako datum + Naformátuje hodnotu jako datum nebo datum s časem podle aktivního jazyka HTML kódování Nahradí speciální znaky jejich HTML ekvivalentem. Bude vloženo za hodnotou pole Bude vloženo před hodnotou pole Malá písmena + Upravit výstup Nic + Ukázka výstupu Vložit za polem Vložit před polem Rekurzivní + Ano, udělej to rekurzivní + Oddělovač Standardní pole Velká písmena Kódování URL @@ -861,7 +1699,7 @@ Podrobnosti překladu - Stáhnout xml DTD + Stáhnout XML DTD Pole Zahrnout podstránky Žádní uživatelé překladatelé nebyli nalezeni. Vytvořte, prosím, překladatele před tím, než začnete posílat obsah k překladu Stránka '%0%' byla poslána k překladu @@ -892,6 +1730,9 @@ Nahrát xml překladu + Obsah + Šablony obsahu + Média Prohlížeč mezipaměti Koš Vytvořené balíčky @@ -909,8 +1750,11 @@ Role Typy členů Typy dokumentů + Typy vztahů/vazeb Balíčky Balíčky + Částečné šablony + Makra částečných šablon Instalovat z úložiště Instalovat Runway Moduly Runway @@ -918,9 +1762,14 @@ Skripty Stylopisy Šablony - Oprávnění Uživatele - Typy Uživatelů + Prohlížeč logu Uživatelé + Nastavení + Šablony + Třetí strana + + Oprávnění uživatele + Typy uživatelů Nová aktualizace je připrvena @@ -929,23 +1778,46 @@ Chyba při kontrole aktualizace. Zkontrolujte, prosím, trasovací zásobník pro další informace + Přístupy + Na základě přiřazených skupin a počátečních uzlů má uživatel přístup k následujícím uzlům + Přiřadit přístup Administrátor Pole kategorie + Uživatel byl vytvořen Změnit heslo + Změnit fotku Změnit heslo + nebyl uzamčen + Heslo nebylo změněno Potvrdit heslo Můžete změnit své heslo pro přístup do administrace Umbraca vyplněním formuláře níže a kliknutím na tlačítko 'Změnit Heslo' Kanál obsahu + Vytvořit dalšího uživatele + Vytvořte nové uživatele a udělte mu přístup do Umbraco. Po vytvoření nového uživatele bude vygenerováno heslo, které s ním můžete sdílet. Popis Deaktivovat uživatele Typ dokumentu Editor Výtah + Neúspěšné pokusy o přihlášení + Přejít na uživatelský profil + Přidáním skupin přidělte přístup a oprávnění + Pozvat dalšího uživatele + Pozvěte nové uživatele, a poskytněte jim přístup do Umbraco. Uživatelům bude zaslán e-mail s pozvánkou a s informacemi o tom, jak se přihlásit do Umbraco. Pozvánky mají platnost 72 hodin. Jazyk + Nastavte jazyk, který uvidíte v nabídkách a dialogových oknech + Poslední datum uzamčení + Poslední přihlášení + Heslo bylo naposledy změněno Přihlašovací jméno Úvodní uzel v knihovně medií + Omezte knihovnu médií na konkrétní počáteční uzel + Úvodní uzly v knihovně medií + Omezte knihovnu médií na konkrétní počáteční uzly Sekce Deaktivovat přistup k Umbracu + se dosud nepřihlásil + Staré heslo Heslo Resetovat heslo Vyše heslo bylo změněno! @@ -959,13 +1831,526 @@ Nahradit oprávnění podřízených uzlů Nyní měníte oprávnění pro stránky: Vyberte stránky, pro které chcete měnit oprávnění + Odebrat fotografii + Výchozí oprávnění + Upřesnění oprávnění + Nastavte oprávnění pro konkrétní uzly + Profil Prohledat všechny podřízené uzly + Přidejte sekce, do kterých mají uživatelé přístup + Vybrat skupiny uživatelů + Nebyl vybrán žádný počáteční uzel + Nebyly vybrány žádné počáteční uzly Úvodní uzel v obsahu + Omezte strom obsahu na konkrétní počáteční uzel + Úvodní uzly obsahu + Omezte strom obsahu na konkrétní počáteční uzly + Uživatel byl naposledy aktualizován + byl vytvořen + Nový uživatel byl úspěšně vytvořen. Pro přihlášení do Umbraco použijte heslo níže. + Správa uživatelů Uživatelské jméno Oprávnění uživatele + Uživatelská skupina + byl pozván + Novému uživateli byla zaslána pozvánka s informacemi, jak se přihlásit do Umbraco. + Dobrý den, vítejte v Umbraco! Za pouhou 1 minutu budete moci používat Umbraco. Jenom od vás potřebujeme, abyste si nastavili heslo a přidali obrázek pro svůj avatar. + Vítejte v Umbraco! Vaše pozvánka bohužel vypršela. Obraťte se na svého správce a požádejte jej, aby jí znovu odeslal. + Nahrání vaší fotografie usnadní ostatním uživatelům, aby vás poznali. Kliknutím na kruh výše nahrajte svou fotku. Spisovatel + Změnit Váš profil Vaše nedávná historie Relace vyprší za + Pozvat uživatele + Vytvořit uživatele + Odeslat pozvánku + Zpět na seznam uživatelů + Umbraco: Pozvánka + + + + + + + + + + + +
        + + + + + +
        + +
        + +
        +
        + + + + + + +
        +
        +
        + + + + +
        + + + + +
        +

        + Zdravím Vás, %0%, +

        +

        + Byli jste pozváni %1% do CMS Umbraco. +

        +

        + Zpráva od %1%: +
        + %2% +

        + + + + + + +
        + + + + + + +
        + + Kliknutím na tento odkaz přijměte pozvání + +
        +
        +

        Pokud nemůžete kliknout na odkaz, zkopírujte a vložte tuto adresu URL do okna prohlížeče:

        + + + + +
        + + %3% + +
        +

        +
        +
        +


        +
        +
        + + ]]>
        + Pozvat + Zasílám pozvání... + Smazat uživatele + Opravdu chcete smazat tento uživatelský účet? + Vše + Aktivní + Zakázané + Uzamčeno + Pozváno + Neaktivní + Jméno (A-Z) + Jméno (Z-A) + Nejnovější + Nejstarší + Poslední přihlášení + Nebyly přidány žádné skupiny uživatelů + + + Validace + Ověřit jako e-mailovou adresu + Ověřit jako číslo + Ověřit jako URL + ...nebo zadat vlastní ověření + Pole je povinné + Zadat chybovou zprávu pro vlastní validaci (volitelné) + Zadat regulární výraz + Zadat chybovou zprávu pro vlastní validaci (volitelné) + Musíte přidat alespoň + Můžete jen mít + položky + vybrané položky + Neplatné datum + Není číslo + Neplatný e-mail + Hodnota nemůže být nulová + Hodnota nemůže být prázdná + Hodnota je neplatná, neodpovídá správnému vzoru + Vlastní ověření + %1% více.]]> + %1% příliš mnoho.]]> + + + + Hodnota je nastavena na doporučenou hodnotu: '%0%'. + Hodnota byla nastavena na '%1%' pro XPath '%2%' v konfiguračním souboru '%3%'. + Očekávaná hodnota '%1%' pro '%2%' v konfiguračním souboru '%3%', ale nalezeno '%0%'. + Nalezena neočekávaná hodnota '%0%' pro '%2%' v konfiguračním souboru '%3%'. + + Vlastní chyby jsou nastaveny na '%0%'. + Vlastní chyby jsou aktuálně nastaveny na '%0%'. Před nasazením se doporučuje nastavit na '%1%'. + Vlastní chyby byly úspěšně nastaveny na '%0%'. + MacroErrors jsou nastaveny na '%0%'. + MakroErrors jsou nastaveny na '%0%', což zabrání úplnému načtení některých nebo všech stránek na vašem webu, pokud dojde k chybám v makrech. Náprava nastaví hodnotu na '%1%'. + MakroErrors jsou nyní nastaveny na '%0%'. + + Try Skip IIS Custom Errors je nastaveno na '%0%' a používáte verzi IIS '%1%'. + Try Skip IIS Custom Errors je aktuálně nastaveno na '%0%'. Doporučuje se nastavit %1% pro vaši verzi služby IIS (%2%). + Try Skip IIS Custom Errors úspěšně nastaveno na '%0%'. + + Soubor neexistuje: '%0%'. + '% 0%' v konfiguračním souboru '% 1%'.]]> + Došlo k chybě, zkontrolujte ji v logu: %0%. + Databáze - Databázové schéma je pro tuto verzi Umbraco správné + Bylo zjištěno %0% problémů se schématem vaší databáze (podrobnosti najdete v logu) + Při ověřování databázového schématu vůči aktuální verzi Umbraco byly zjištěny některé chyby. + Certifikát vašeho webu je platný. + Chyba ověření certifikátu: '%0%' + Platnost SSL certifikátu vašeho webu vypršela. + Platnost certifikátu SSL vašeho webu vyprší za %0% dní. + Chyba při pingování adresy URL %0% - '%1%' + Aktuálně prohlížíte web pomocí schématu HTTPS. + AppSetting 'Umbraco.Core.UseHttps' je v souboru web.config nastaven na 'false'. Jakmile vstoupíte na tento web pomocí schématu HTTPS, mělo by být nastaveno na 'true'. + AppSetting 'Umbraco.Core.UseHttps' je v souboru web.config nastaven na '%0%', vaše cookies %1% jsou označeny jako zabezpečené. + V souboru web.config se nepodařilo aktualizovat nastavení 'Umbraco.Core.UseHttps'. Chyba: %0% + + Povolit HTTPS + Nastaví nastavení umbracoSSL na true v appSettings v souboru web.config. + AppSetting 'Umbraco.Core.UseHttps' je nyní nastaveno na 'true' v souboru web.config, vaše cookies budou označeny jako zabezpečené. + Fix + Nelze opravit kontrolu pro porovnání hodnot pomocí 'ShouldNotEqual'. + Nelze opravit kontrolu pro porovnání hodnot pomocí 'ShouldEqual' s poskytnutou hodnotou. + Hodnota k opravě nebyla poskytnuta. + Režim kompilace ladění je zakázán. + Režim ladění je aktuálně povolen. Před spuštěním webu se doporučuje toto nastavení deaktivovat. + Režim ladění byl úspěšně deaktivován. + Režim sledování je deaktivován. + Režim sledování je aktuálně povolen. Před spuštěním se doporučuje toto nastavení deaktivovat. + Režim sledování byl úspěšně deaktivován. + Všechny složky mají nastavena správná oprávnění. + + %0%.]]> + %0%. Pokud nejsou psány, není třeba podniknout žádné kroky.]]> + Všechny soubory mají nastavena správná oprávnění. + + %0%.]]> + %0%. Pokud nejsou psány, není třeba podniknout žádné kroky.]]> + X-Frame-Options, které určuje, zda může být obsah webu zobrazen na jiném webu pomocí IFRAME.]]> + X-Frame-Options, které určuje, zda může být obsah webu zobrazen na jiném webu pomocí IFRAME.]]> + Nastavit záhlaví v Konfiguraci + Přidá hodnotu do sekce httpProtocol/customHeaders do web.config, aby se zabránilo tomu, že web může být zobrazen na jiném webu pomocí IFRAME. + Do souboru web.config bylo přidáno nastavení pro vytvoření záhlaví, které zabrání jinému webu, zobrazit tento web pomocí IFRAME. + Nelze aktualizovat soubor web.config. Chyba: %0% + X-Content-Type-Options použitá k ochraně před zranitelnostmi čichání MIME.]]> + X-Content-Type-Options použité k ochraně před zranitelnostmi čichání MIME nebyly nalezeny.]]> + Přidá hodnotu do sekce httpProtocol/customHeaders v souboru web.config, která chrání před zranitelnostmi MIME. + Do souboru web.config bylo přidáno nastavení pro vytvoření záhlaví, které chrání před zranitelnostmi MIME. + Strict-Transport-Security, také známo jako HSTS-header, bylo nalezeno.]]> + Strict-Transport-Security nebylo nalezeno.]]> + Do sekce httpProtocol/customHeaders v souboru web.config přidá záhlaví 'Strict-Transport-Security' s hodnotou 'max-age = 10886400'. Tuto opravu použijte pouze v případě, že vaše domény budou spuštěny s https po dobu příštích 18 týdnů (minimálně). + Do vašeho souboru web.config bylo přidáno záhlaví HSTS. + X-XSS-Protection bylo nalezeno.]]> + X-XSS-Protection bylo nalezeno.]]> + Přidá záhlaví 'X-XSS-Protection' s hodnotou '1; mode=block' do sekce httpProtocol/customHeaders v souboru web.config. + Záhlaví X-XSS-Protection bylo přidáno do vašeho souboru web.config. + + %0%.]]> + Nebyly nalezeny žádné hlavičky odhalující informace o technologii webových stránek. + V souboru Web.config nelze najít system.net/mailsettings. + V části system.net/mailsettings v souboru web.config není hostitel nakonfigurován. + Nastavení SMTP jsou správně nakonfigurována a služba funguje jak má. + Server SMTP konfigurovaný s hostitelem '%0%' a portem '%1%' nelze nalézt. Zkontrolujte prosím, zda jsou nastavení SMTP v souboru Web.config a v sekci system.net/mailsettings správná. + %0%.]]> + %0%.]]> +

        Výsledky plánovaných kontrol Umbraco Health Checks provedených na %0% v %1% jsou následující:

        %2%]]>
        + Stav Umbraco Health Check: %0% + Zkontrolovat všechny skupiny + Zkontrolovat skupinu + + Kontrola vyhodnocuje různé oblasti vašeho webu z hlediska nastavení osvědčených postupů, konfigurace, potenciálních problémů atd. Problémy lze snadno vyřešit stisknutím tlačítka. Můžete přidat své vlastní kontroly, podívejte se na dokumentaci pro více informací o vlastních kontrolách.

        + ]]> +
        + + + Zakázat sledování URL + Povolit sledování URL + Jazyk + Originální URL + Přesměrováno na + Správa URL přesměrování + Na tuto položku obsahu přesměrovávají následující adresy URL: + Nebyla provedena žádná přesměrování + Jakmile bude publikovaná stránka přejmenována nebo přesunuta, bude automaticky provedeno přesměrování na novou stránku. + Opravdu chcete odstranit přesměrování z '%0%' na '%1%'? + Přesměrování bylo odstraněno. + Chyba při odebírání URL přesměrování. + Toto odstraní přesměrování + Opravdu chcete zakázat sledování URL adres? + Sledování URL adres je nyní zakázáno. + Při deaktivaci sledování URL adres došlo k chybě, další informace naleznete v logu. + Sledování URL adres je nyní povoleno. + Chyba při povolení sledování URL adres, další informace lze nalézt v logu. + + + Žádné položky ze slovníku na výběr + + + %0% znaků.]]> + %1% je moc.]]> + + + Obsah s ID: {0} v koši souvisí s původním nadřazeným obsahem s ID: {1} + Média s ID: {0} v koši souvisí s původním nadřazeným médiem s ID: {1} + Tuto položku nelze automaticky obnovit + Neexistuje žádné místo, kde lze tuto položku automaticky obnovit. Položku můžete přesunout ručně pomocí stromu níže. + byla obnovena pod + + + Směr + Nadřazený s potomkem + Obousměrný + Nadřazená + Potomek + Počet + Vazby + Vytvořeno + Komentář + Název + Žádné vazby pro tento typ vazby. + Typ vazby + Vazby + + + Začínáme + Správa přesměrování + Obsah + Vítejte + Správa Examine + Stav publikování + Tvůrce modelů + Health Check + Profilování + Začínáme + Instalovat Umbraco formuláře + + + Jít zpět + Aktivní rozvržení: + Skočit do + skupina + prošlo + varování + selhalo + návrh + Kontrola prošla + Kontrola selhala + Otevřít hledání v backoffice + Otevřít/zavřít nápovědu backoffice + Otevřít/zavřít možnosti vašeho profilu + Otevřít kontextové menu pro + Aktuální jazyk + Přepnout jazyk na + Vytvořit novou složku + Částečná šablona + Makro částečné šablony + Člen + Datový typ + Prohledat přesměrování + Prohledat skupiny uživatelů + Prohledat uživatele + Vytvořit položku + Vytvořit + Upravit + Název + + + Závislosti + Tento datový typ nemá žádné závislosti. + Použito v dokumentových typech + Žádné vazby na typy dokumentů. + Použito v typech médií + Žádné vazby na typy médií. + Použito v typech členů + Žádné vazby na typy členů. + Použito v + Použito v dokumentech + Použito ve členech + Použito v médiích + + + Úrovně logování + Uložená vyhledávání + Celkem položek + Časové razítko + Úroveň + Stroj + Zpráva + Výjimka + Vlastnosti + Vyhledat na Googlu + Vyhledat zprávu na Googlu + Vyhledat na Bing + Vyhledat zprávu na Bing + Prohledat naše Umbraco + Vyhledat tuto zprávu na našich fórech a dokumentech Umbraco + Vyhledat Our Umbraco na Googlu + Prohledat Our Umbraco fóra pomocí Googlu + Prohledat Umbraco Source + Vyhledat ve zdrojovém kódu Umbraco na Github + Prohledat Umbraco Issues + Prohledat Umbraco Issues na Github + Smazat toto vyhledávání + Najít logy s ID požadavku + Najít logy se jmenným prostorem + Najít logy s názvem stroje + Otevřít + + + Kopírovat %0% + %0% z %1% + Odebrat všechny položky + + + Otevřít akce vlastností + + + Čekejte + Stav obnovení + Cache paměť + + + + Znovu načíst + Cache databáze + + Znovuvytvoření může být náročné. Použijte jej, když nestačí obnovení stránky, a domníváte se, že mezipaměť databáze nebyla správně vygenerována - což by naznačovalo možný kritický problém Umbraco. + ]]> + + Obnovit + Internals + + nebudete muset používat. + ]]> + + Sběr + Stav publikované mezipaměti + Mezipaměti + + + Profilování výkonu + + Umbraco aktuálně běží v režimu ladění. To znamená, že můžete použít vestavěný profiler výkonu k vyhodnocení výkonu při vykreslování stránek.

        Pokud chcete aktivovat profiler pro konkrétní vykreslení stránky, jednoduše při požadavku na stránku jednoduše přidejte umbDebug=true do URL.

        Pokud chcete, aby byl profiler ve výchozím nastavení aktivován pro všechna vykreslení stránky, můžete použít přepínač níže. Ve vašem prohlížeči nastaví soubor cookie, který automaticky aktivuje profiler. Jinými slovy, profiler bude ve výchozím nastavení aktivní pouze ve vašem prohlížeči, ne v ostatních.

        + ]]> +
        + Ve výchozím stavu aktivovat profiler + Přátelské připomenutí + + + Nikdy byste neměli nechat produkční web běžet v režimu ladění. Režim ladění je vypnut nastavením debug="false" na elementu compilation v souboru web.config. +

        + ]]> +
        + + + Umbraco v současné době neběží v režimu ladění, takže nemůžete použít vestavěný profiler. Takto by to mělo být pro produkční web. +

        +

        + Režim ladění je zapnut nastavením debug="true" na elementu compilation v souboru web.config. +

        + ]]> +
        + + + Hodiny tréninkových videí Umbraco jsou blíž než si myslíte + + Chcete ovládnout Umbraco? Stačí strávit pár minut sledování jednoho z těchto videí o používání Umbraco. Nebo navštivte umbraco.tv , kde najdete ještě více videí o Umbraco

        + ]]> +
        + Chcete-li začít + + + Začněte zde + Tato část obsahuje stavební bloky pro váš web Umbraco. Podle níže uvedených odkazů se dozvíte více o práci s položkami v části Nastavení + Zjistit více + + v sekci Dokumentace v Our Umbraco + ]]> + + + fóru komunity + ]]> + + + výuková videa (některá jsou zdarma, jiná vyžadují předplatné) + ]]> + + + nástrojích zvyšujících produktivitu a komerční podpoře + ]]> + + + školení a certifikace + ]]> + + + + Vítejte v přátelském CMS + Děkujeme, že jste si vybrali Umbraco - myslíme si, že by to mohl být začátek něčeho krásného. I když se to může zpočátku zdát ohromující, udělali jsme hodně pro to, aby byla křivka učení co nejhladší a nejrychlejší. + + + Umbraco formuláře + Vytvářejte formuláře pomocí intuitivního rozhraní drag and drop. Od jednoduchých kontaktních formulářů, které odesílají e-maily, až po pokročilé dotazníky, které se integrují do systémů CRM. Vaši klienti to budou milovat!
        diff --git a/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/da.xml b/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/da.xml index fef9c1cf82..6242d72146 100644 --- a/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/da.xml +++ b/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/da.xml @@ -472,6 +472,7 @@ Vælg medlemstype Vælg node Vælg sektioner + Vælg bruger Vælg brugere Ingen ikoner blev fundet Der er ingen parametre for denne makro @@ -1784,8 +1785,10 @@ Mange hilsner fra Umbraco robotten Brugt af + Slet gemte søgning Log type - Gemte søgninger + Gem søgning + Indtast et navn for din søgebetingelse Samlet resultat Dato Type diff --git a/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/de.xml b/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/de.xml index 529074f24d..86b1d6c130 100644 --- a/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/de.xml +++ b/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/de.xml @@ -4,10 +4,6 @@ The Umbraco community https://our.umbraco.com/documentation/Extending-Umbraco/Language-Files - - - - Kulturen und Hostnamen Protokoll diff --git a/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/en.xml b/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/en.xml index d72179fc75..481d20f777 100644 --- a/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/en.xml +++ b/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/en.xml @@ -499,6 +499,7 @@ Select member type Select node Select sections + Select user Select users No icons were found There are no parameters for this macro @@ -2047,7 +2048,10 @@ To manage your website, simply open the Umbraco back office and start adding con Enter a custom validation error message (optional) You need to add at least You can only have + Add up to items + url(s) + url(s) selected items selected Invalid date Not a number @@ -2265,6 +2269,9 @@ To manage your website, simply open the Umbraco back office and start adding con Name Add new row View more options + Has translation + Missing translation + Dictionary items References @@ -2281,32 +2288,36 @@ To manage your website, simply open the Umbraco back office and start adding con Used in Media - Log Levels - Saved Searches - Total Items - Timestamp - Level - Machine - Message - Exception - Properties - Search With Google - Search this message with Google - Search With Bing - Search this message with Bing - Search Our Umbraco - Search this message on Our Umbraco forums and docs - Search Our Umbraco with Google - Search Our Umbraco forums using Google - Search Umbraco Source - Search within Umbraco source code on Github - Search Umbraco Issues - Search Umbraco Issues on Github - Delete this search - Find Logs with Request ID - Find Logs with Namespace - Find Logs with Machine Name - Open + Delete Saved Search + Log Levels + Saved Searches + Save Search + Enter a friendly name for your search query + Filter Search + Total Items + Timestamp + Level + Machine + Message + Exception + Properties + Search With Google + Search this message with Google + Search With Bing + Search this message with Bing + Search Our Umbraco + Search this message on Our Umbraco forums and docs + Search Our Umbraco with Google + Search Our Umbraco forums using Google + Search Umbraco Source + Search within Umbraco source code on Github + Search Umbraco Issues + Search Umbraco Issues on Github + Delete this search + Find Logs with Request ID + Find Logs with Namespace + Find Logs with Machine Name + Open Copy %0% @@ -2316,6 +2327,7 @@ To manage your website, simply open the Umbraco back office and start adding con Open Property Actions + Close Property Actions Wait diff --git a/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/en_us.xml b/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/en_us.xml index 41efb12f51..9113e94e62 100644 --- a/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/en_us.xml +++ b/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/en_us.xml @@ -503,6 +503,7 @@ Select member type Select node Select sections + Select user Select users No icons were found There are no parameters for this macro @@ -673,6 +674,7 @@ Continue Copy Create + Crop section Database Date Default @@ -2063,7 +2065,10 @@ To manage your website, simply open the Umbraco back office and start adding con Enter a custom validation error message (optional) You need to add at least You can only have + Add up to items + url(s) + url(s) selected items selected Invalid date Not a number @@ -2285,6 +2290,9 @@ To manage your website, simply open the Umbraco back office and start adding con Name Add new row View more options + Has translation + Missing translation + Dictionary items References @@ -2301,8 +2309,12 @@ To manage your website, simply open the Umbraco back office and start adding con Used in Media + Delete Saved Search Log Levels Saved Searches + Save Search + Enter a friendly name for your search query + Filter Search Total Items Timestamp Level @@ -2336,6 +2348,7 @@ To manage your website, simply open the Umbraco back office and start adding con Open Property Actions + Close Property Actions Wait diff --git a/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/fr.xml b/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/fr.xml index b5d1c8feb2..b83ee4f9fe 100644 --- a/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/fr.xml +++ b/src/Umbraco.Web.UI.NetCore/umbraco/config/lang/fr.xml @@ -12,8 +12,8 @@ Copier Créer Exporter - Créer un groupe Créer un package + Créer un groupe Supprimer Désactiver Vider la corbeille @@ -30,17 +30,21 @@ Dépublier Rafraîchir Republier le site tout entier + Renommer Récupérer Spécifiez les permissions pour la page %0% + Choisissez où copier Choisissez où déplacer dans l'arborescence ci-dessous + a été déplacé vers + a été copié vers + a été supprimé Permissions Version antérieure Envoyer pour publication Envoyer pour traduction Spécifier le groupe Trier - Envoyer pour publication Traduire Mettre à jour Spécifier les permissions @@ -65,6 +69,7 @@ Permettre de déplacer un noeud Permettre de définir et modifier l'accès public à un noeud Permettre de publier un noeud + Permettre d'annuler la publication d'un noeud Permettre de modifier les permissions pour un noeud Permettre de revenir à une situation antérieure Permettre d'envoyer un noeud pour approbation avant publication @@ -74,6 +79,10 @@ Permettre de sauvegarder un noeud Permettre la création d'un Modèle de Contenu + + Contenu + Info + Permission refusée. Ajouter un nouveau domaine @@ -88,15 +97,15 @@ Domaine '%0%' déjà assigné Domaine '%0%' mis à jour Editer les domaines actuels + + Hériter Culture ou hériter de la culture des noeuds parents. S'appliquera aussi
        au noeud courant, à moins qu'un domaine ci-dessous soit aussi d'application.]]>
        Domaines - - Aperçu pour - Vider la sélection Choisir @@ -117,25 +126,66 @@ Liste numérique Insérer une macro Insérer une image + Publier et fermer + Publier avec les descendants Editer les relations Retourner à la liste Sauver + Sauver et fermer Sauver et publier Sauver et planifier Sauver et envoyer pour approbation Sauver la mise en page de la liste + Planifier Prévisualiser + Prévisualiser La prévisualisation est désactivée car aucun modèle n'a été assigné. Choisir un style Afficher les styles Insérer un tableau + Générer les modèles et fermer Sauver et générer les modèles Défaire Refaire + Restaurer + Supprimer un tag + Annuler + Confirmer + Options de publication supplémentaires + + + Aperçu pour + Contenu supprimé + Contenu dé-publié + Contenu dé-publié pour les langues : %0% + Contenu publié + Contenu publié pour les langues : %0% + Contenu sauvegardé + Contenu sauvegardé pour les langues : %0% + Contenu déplacé + Contenu copié + Contenu restauré + Contenu envoyé pour publication + Contenu envoyé pour publication pour les langues : %0% + Ordonnancement des sous-éléments réalisé par l'utilisateur + Copier + Publier + Publier + Déplacer + Sauvegarder + Sauvegarder + Supprimer + Annuler publication + Annuler publication + Restaurer + Envoyer pour publication + Envoyer pour publication + Ordonner + Historique (toutes variantes) Pour changer le type de document du contenu séléctionné, faites d'abord un choix dans la liste des types valides à cet endroit. - Puis modifiez si nécessaire la correspondance des propriétés du type actuel vers le nouveau, et cliquez sur Sauver. + Puis confirmez et/ou modifiez la correspondance des propriétés du type actuel vers le nouveau, et cliquez sur Sauver. Le contenu a été republié. Propriété actuelle Type actuel @@ -153,6 +203,12 @@ Impossible de terminer la correspondance des propriétés car une ou plusieurs propriétés ont plus d'une correspondance définie. Seuls les types de documents valides à cet endroit sont affichés. + + Echec de la création d'un dossier sous le parent avec l'ID %0% + Echec de la création d'un dossier sous le parent avec le nom %0% + Le nom du dossier ne peut pas contenir de caractères illégaux. + Echec de la suppression de l'élément : %0% + A été publié A propos de cette page @@ -184,15 +240,20 @@ Aucune date choisie Titre de la page Ce média n'a pas de lien + Aucun contenu ne peut être ajouté pour cet élément Propriétés Ce document est publié mais n'est pas visible car son parent '%0%' n'est pas publié - Oups : ce document est publié mais n'est pas présent dans le cache (erreur interne Umbraco) + Cette culture est publiée mais n'est pas visible car elle n'est pas publiée pour le parent '%0%' + Ce document est publié mais n'est pas présent dans le cache Oups: impossible d'obtenir cet url (erreur interne - voir fichier log) - Oups: ce document est publié mais son url entrerait en collision avec le contenu %0% + Ce document est publié mais son url entrerait en collision avec le contenu %0% + Ce document est publié mais son url ne peut pas être routé Publier Publié Publié (changements en cours) Statut de publication + Publier avec ses descendants pour publier %0% et tous les éléments de contenu en-dessous, rendant de ce fait leur contenu accessible publiquement.]]> + Publier avec ses descendants pour publier les langues sélectionnées et les mêmes langues des éléments de contenu en-dessous, rendant de ce fait leur contenu accessible publiquement.]]> Publié le Dépublié le Supprimer la date @@ -205,6 +266,7 @@ Type Dépublier Dépublié + Non créé Dernière édition Date/heure à laquelle ce document a été édité Supprimer le(s) fichier(s) @@ -215,13 +277,35 @@ Cible Ceci se traduit par l'heure suivante sur le serveur : Qu'est-ce que cela signifie?]]> - Etes-vous certain(e) de vouloir supprimer cet éléménent? + Etes-vous certain(e) de vouloir supprimer cet élément? + Etes-vous certain(e) de vouloir supprimer tous les éléments? La propriété %0% utilise l'éditeur %1% qui n'est pas supporté par Nested Content. + Aucun type de contenu n'est configuré pour cette propriété. + Ajouter un type d'élément + Sélectionner un type d'élément Ajouter un autre champ texte Enlever ce champ texte Racine du contenu + Inclure les brouillons : publier également les éléments de contenu non publiés. Cette valeur est masquée. Si vous avez besoin de pouvoir accéder à cette valeur, veuillez prendre contact avec l'administrateur du site web. Cette valeur est masquée. + Quelles langues souhaitez-vous publier? Toutes les langues ayant du contenu ont été sauvegardées! + Quelles langues souhaitez-vous publier? + Quelles langues souhaitez-vous sauvegarder? + Toutes les langues avec du contenu sont sauvegardées lors de la création! + Quells langues souhaitez-vous envoyer pour approbation? + Quelles langues souhaitez-vous planifier? + Sélectionnez les langues à dépublier. La dépublication d'une langue obligatoire provoquera la dépublication de toutes les langues. + Langues publiées + Langues non publiées + Langues non modifiées + Ces langues n'ont pas été créées + Prêt.e à publier? + Prêt.e à sauvegarder? + Envoyer pour approbation + Sélectionnez la date et l'heure de publication/dépublication de l'élément de contenu. + Créer nouveau + Copier du clipboard Créer un nouveau Modèle de Contenu à partir de '%0%' @@ -235,22 +319,38 @@ Cliquez pour télécharger ou cliquez ici pour choisir un fichier + Vous pouvez faire glisser des fichiers ici pour télécharger. Ce fichier ne peut pas ête chargé, il n'est pas d'un type de fichier autorisé. La taille maximum de fichier est Racine du média + Echec du déplacement du média + Les dossiers parent et destination ne peuvent pas être identiques + Echec de la copie du media + Echec de la création d'un dossier sous le parent avec l'id %0% + Echec du changement de nom du dossier avec l'id %0% + Glissez et déposez vos fichiers dans la zone Créer un nouveau membre Tous les membres + Les groupes de membres n'ont pas de propriétés supplémentaires modifiables. Où voulez-vous créer le nouveau %0% Créer un élément sous Sélectionnez le type de document pour lequel vous souhaitez créer un modèle de contenu + Introduisez un nom de dossier Choisissez un type et un titre - "Types de documents".]]> - "Types de médias".]]> - Type de document sans modèle + Types de documents sous la section Paramètres, en modifiant les Types de noeuds enfants autorisés sous les Permissions.]]> + Types de documents sous la section Paramètres.]]> + La page sélectionnée dans l'arborescence de contenu n'autorise pas la création de pages sous elle. + Modifier les permissions pour ce type de document + Créer un nouveau type de document + Types de documents sous la section Paramètres, en modifiant l'option Autoriser comme racine sous les Permissions.]]> + Types de médias dans la section Paramètres, en modifiant les Types de noeuds enfants autorisés sous les Permissions.]]> + Le media sélectionné dans l'arborescence n'autorise pas la création d'un autre media sous lui. + Modifier les permissions pour ce type de media + Type de document sans modèle Nouveau répertoire Nouveau type de données Nouveau fichier javascript @@ -259,6 +359,8 @@ Nouvelle vue partielle à partir d'un snippet Nouvelle macro pour vue partielle à partir d'un snippet Nouvelle macro pour vue partielle (sans macro) + Nouveau fichier de feuille de style + Nouveau fichier de feuille de style pour l'éditeur de texte Parcourir votre site @@ -274,7 +376,10 @@ Invalider les changements Vous avez des changements en cours Etes-vous certain(e) de vouloir quitter cette page? - vous avez des changements en cours - La dépublication va supprimer du site cette page ainsi que tous ses descendants. + La publication rendra les éléments sélectionnés visibles sur le site. + La suppression de la publication supprimera du site les éléments sélectionnés et tous leurs descendants. + La suppression de la publication supprimera du site cette page ainsi que tous ses descendants. + Vous avez des modifications en cours. Modifier le Type de Document fera disparaître ces modifications. Terminé @@ -302,8 +407,8 @@ Titre du lien Lien + Ancrage / requête Nom - Gérer les noms d'hôtes Fermer cette fenêtre Êtes-vous certain(e) de vouloir supprimer Êtes-vous certain(e) de vouloir désactiver @@ -312,6 +417,7 @@ Couper Editer une entrée du Dictionnaire Modifier la langue + Modifier le media sélectionné Insérer un lien local (ancre) Insérer un caractère Insérer un entête graphique @@ -319,18 +425,21 @@ Insérer un lien Insérer une macro Insérer un tableau + Ceci supprimera la langue + Modifier la culture d'une langue peut être une opération lourde qui aura pour conséquence la réinitialisation de la cache de contenu et des index Dernière modification Lien Lien interne : Si vous utilisez des ancres, insérez # au début du lien Ouvrir dans une nouvelle fenêtre? + Paramètres de la macro Cette macro ne contient aucune propriété éditable Coller Editer les permissions pour Définir les permissions pour Définir les permissions pour %0% pour le groupe d'utilisateurs %1% Sélectionnez les groupes d'utilisateurs pour lesquels vous souhaitez définir les permissions - Les éléments dans la corbeille sont en cours de suppression. Ne fermez pas cette fenêtre avant que cette opération soit terminée. + Les éléments dans la corbeille sont en cours de suppression. Veuillez ne pas fermer cette fenêtre avant que cette opération ne soit terminée. La corbeille est maintenant vide Les éléments supprimés de la corbeille seront supprimés définitivement regexlib.com rencontre actuellement des problèmes sur lesquels nous n'avons aucun contrôle. Nous sommes sincèrement désolés pour le désagrément.]]> @@ -353,14 +462,17 @@ Lier à un media Sélectionner le noeud de base du contenu Sélectionner le media + Sélectionner le type de media Sélectionner l'icône Sélectionner l'élément Sélectionner le lien Sélectionner la macro Sélectionner le contenu + Sélectionner le type de contenu Sélectionner le noeud de base des media Sélectionner le membre Sélectionner le groupe de membres + Sélectionner le type de membre Sélectionner le noeud Sélectionner les sections Sélectionner les utilisateurs @@ -376,10 +488,14 @@ compte Sélectionner un éditeur Selectionner un snippet + Ceci supprimera le noeud et toutes ses langues. Si vous souhaitez supprimer une langue spécifique, vous devriez plutôt supprimer la publication du noeud dans cette langue-là. + + + Il n'y a pas d'éléments dans le dictionnaire. %0%' ci-dessous. + Editez les différentes versions de langues pour l'élément de dictionnaire '%0%' ci-dessous. ]]> Nom de Culture Aperçu du dictionaire + + Recherches configurées + Affiche les propriétés et les outils de chaque Recherche configurée (e.g. une recherche multi-index) + Valeurs du champ + Etat de santé + L'état de santé de l'index et s'il peut être lu + Indexeurs + Info Index + Liste les propriétés de l'index + Gérer les index d'Examine + Vous permet de voir les détails de chaque index et fournit des outils pour gérer les index + Reconstruire l'index + + Cela pourrait prendre un certain temps en fonction de la quantité de contenu présente dans votre site.
        + Il est déconseillé de reconstruire un index pendant les périodes de trafic intense sur le site web ou quand les éditeurs sont en train d'éditer du contenu. + ]]> +
        + Recherches + Rechercher dans l'index et afficher les résultats + Outils + Outils pour gérer l'index + champs + L'index ne peut pas être lu et devra être reconstruit + Le processus dure plus de temps que prévu, vérifiez les logs Umbraco afin de voir s'il y a eu des erreurs pendant cette opératon + Cet index ne peut pas être reconstruit parce qu'on ne lui a pas assigné de + IIndexPopulator + Votre nom d'utilisateur Votre mot de passe @@ -403,10 +547,18 @@ Entrez votre email Entrez un message... Votre nom d'utilisateur est généralement votre adresse email + #value ou ?key=value + Introduisez l'alias... + Génération de l'alias... + Créer un élément + Créer + Modifier + Nom Créer une liste personnalisée Supprimer la liste personnalisée + Il existe déjà un type de contenu, un tye de media ou un type de membre avec cet alias Renommé @@ -432,9 +584,11 @@ Sélectionnez le répertoire où déplacer dans l'arborescence ci-dessous a été déplacé sous + %0% supprimera les propriétés et leurs données des éléments suivants]]> + Je comprends que cette action va supprimer les propriétés et les données basées sur ce Type de Données - Vos données ont été sauvegardées, mais avant de pouvoir publier votre page, il y a des erreurs que vous devez corriger : + Vos données ont été sauvegardées, mais avant de pouvoir publier votre page, il y a des erreurs que vous devez d'abord corriger : Le Membership Provider n'autorise pas le changement des mots de passe (EnablePasswordRetrieval doit être défini à true) %0% existe déjà Des erreurs sont survenues : @@ -459,8 +613,9 @@ Noeud de départ supprimé, contactez votre administrateur Veuillez sélectionner du contenu avant de changer le style Aucun style actif disponible - Veuillez placer le curseur à gauche des deux cellules que vous voulez fusionner + Veuillez placer le curseur à la gauche des deux cellules que vous voulez fusionner Vous ne pouvez pas scinder une cellule qui n'a pas été fusionnée. + Cette propriété n'est pas valide Options @@ -472,6 +627,7 @@ Tout Êtes-vous certain(e)? Retour + Retour à l'aperçu Bord par Annuler @@ -483,6 +639,7 @@ Confirmer Conserver Conserver les proportions + Contenu Continuer Copier Créer @@ -502,16 +659,21 @@ Eléments Email Erreur + Champ Trouver Premier + Point focal Général Groupes + Groupe Hauteur Aide Cacher Historique Icône + Id Importer + Inclure les sous-dossiers dans la recherche Info Marge intérieure Insérer @@ -548,9 +710,11 @@ Un moment s'il vous plaît... Précédent Propriétés + Reconstruire Email de réception des données de formulaire Corbeille Votre corbeille est vide + Rafraîchir Restant Enlever Renommer @@ -564,6 +728,7 @@ Désolé, nous ne pouvons pas trouver ce que vous recherchez Aucun élément n'a été ajouté Serveur + Paramètres Montrer Afficher la page à l'envoi Taille @@ -572,6 +737,7 @@ Envoyer Type Rechercher... + sous Haut Mettre à jour Upgrader @@ -611,8 +777,8 @@ Parcourir les sections Raccourcis afficher les raccourcis - Passer à la vue en liste - Basculer vers l'autorisation comme racine + Activer / Désactiver la vue en liste + Activer / Désactiver l'autorisation comme racine Commenter/Décommenter les lignes Supprimer la ligne Copier les lignes vers le haut @@ -621,6 +787,7 @@ Déplacer les lignes vers le bas Général Editeur + Activer / Désactiver les variantes de culture Couleur de fond @@ -875,6 +1042,7 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à Editez vos notifications pour %0% + Paramètres de notification enregistrés pour + Les langues suivantes ont été modifiées : %0% @@ -966,29 +1135,50 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à ]]> + Les langues suivantes ont été modifiées :

        + %0% + ]]>
        La notification [%0%] à propos de %1% a été executée sur %2% Notifications + Actions + Créé + Créer un package et localisez le package. Les packages Umbraco ont généralement une extension ".umb" ou ".zip". ]]> + Ceci va supprimer le package Déposez pour uploader + Inclure tous les noeuds enfant ou cliquez ici pour choisir les fichiers Uploader un package Installez un package local en le sélectionnant sur votre ordinateur. Installez uniquement des packages de sources fiables que vous connaissez Uploader un autre package Annuler et uploader un autre package - Licence J'accepte les conditions d'utilisation - Installer le package - Terminer + Chemin du fichier + Le chemin absolu du fichier (eg: /bin/umbraco.bin) + Installé Packages installés + Installer localement + Terminer + Ce package n'a pas de vue de configuration + Aucun package n'a encore été créé Vous n'avez aucun package installé 'Packages' en haut à droite de votre écran]]> - Chercher des packages + Actions du package + URL de l'auteur + Contenu du package + Fichiers du package + URL de l'icone + Installer le package + Licence + URL de la licence + Propriétés du package + Chercher des packages Résultats pour Nous n'avons rien pu trouver pour Veuillez essayer de chercher un autre package ou naviguez à travers les catégories @@ -1025,6 +1215,7 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à Remarque : tous les documents, media etc. dépendant des éléments que vous supprimez vont cesser de fonctionner, ce qui peut provoquer une instabilité du système, désinstallez donc avec prudence. En cas de doute, contactez l'auteur du package.]]> Version du package + Mise à jour à partir de la version Package déjà installé Ce package ne peut pas être installé, il nécessite au minimum la version Umbraco %0% Désinstallation... @@ -1043,24 +1234,29 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à Coller, mais supprimer le formatage (recommandé) - Protection basée sur les rôles - via les groupes de membres Umbraco.]]> - Vous devez créer un groupe avant de pouvoir utiliser l'authentification basée sur les rôles + Protection basée sur les groupes + Si vous souhaitez donner accès à tous les utilisateurs de groupes de membres spécifiques + Vous devez créer un groupe de membres avant de pouvoir utiliser la protection basée sur les groupes Page d'erreur Utilisé pour les personnes connectées, mais qui n'ont pas accès - Choisissez comment restreindre l'accès à cette page - %0% est maintenant protégée - Protection supprimée de %0% + %0%]]> + %0% est maintenant protégée]]> + %0% supprimée]]> Page de connexion Choisissez la page qui contient le formulaire de connexion - Supprimer la protection + Supprimer la protection... + %0%?]]> Choisissez les pages qui contiennent le formulaire de connexion et les messages d'erreur - Choisissez les rôles qui ont accès à cette page - Définissez l'identifiant et le mot de passe pour cette page - Protection utilisateur unique - Si vous souhaitez mettre en place une protection simple utilisant un identifiant et un mot de passe uniques + %0%]]> + %0%]]> + Protection pour des membres spécifiques + Si vous souhaitez donner accès à des membres spécifiques + Permissions utilisateur insuffisantes pour publier tous les documents enfants. + @@ -1076,7 +1272,8 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à - Inclure les pages enfant non publiées + + La validation a échoué pour la langue obligatoire '%0%'. Cette langue a été sauvegardée mais pas publiée. Publication en cours - veuillez patienter... %0% pages sur %1% ont été publiées... %0% a été publié @@ -1090,12 +1287,15 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à Vous n'avez configuré aucune couleur approuvée + Vous pouvez uniquement sélectionner des éléments du(des) type(s) : %0% Vous avez choisi un élément de contenu actuellement supprimé ou dans la corbeille Vous avez choisi des éléments de contenu actuellement supprimés ou dans la corbeille + Elément supprimé Vous avez choisi un élément media actuellement supprimé ou dans la corbeille Vous avez choisi des éléments media actuellement supprimés ou dans la corbeille + Mis dans la corbeille introduire un lien externe @@ -1108,11 +1308,13 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à Réinitialiser - Définir le recadrage Sauvegarder le recadrage Ajouter un nouveau recadrage + Terminé + Annuler les modifications + Sélectionnez une version à comparer avec la version actuelle Version actuelle Le texte en Rouge signifie qu'il a été supprimé de la version choisie, vert signifie ajouté]]> Le document a été restauré à une version antérieure @@ -1125,20 +1327,14 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à Editer le fichier de script - Concierge Contenu - Courier - Développeur - Assistant de configuration Umbraco + Formulaires Medias Membres - Newsletters + Packages Configuration - Statistiques Traduction Utilisateurs - Aide - Formulaires Les meilleurs tutoriels vidéo Umbraco @@ -1158,14 +1354,16 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à Ce type de contenu utilise en tant que type de contenu de base. Les onglets du type de contenu de base ne sont pas affichés et peuvent seulement être modifiés à partir du type de contenu de base lui-même. Aucune propriété définie dans cet onglet. Cliquez sur le lien "Ajouter une nouvelle propriété" en-haut pour créer une nouvelle propriété. + Créer le template correspondant Ajouter une icône Ordre de tri Date de création Tri achevé. - Faites glisser les différents éléments vers le haut ou vers le bas pour définir la manière dont ils doivent être organisés. Ou cliquez sur les entêtes de colonnes pour trier la collection complète d'éléments + Faites glisser les différents éléments vers le haut ou vers le bas pour définir la manière dont ils doivent être organisés. Ou cliquez sur les en-têtes de colonnes pour trier la collection complète d'éléments + Ce noeud n'a aucun noeud enfant à trier Validation @@ -1175,7 +1373,6 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à Permissions utilisateur insuffisantes, l'opération n'a pas pu être complétée Annulation L'opération a été annulée par une extension tierce - La publication a été annulée par une extension tierce. Le type de propriété existe déjà Type de propriété créé Type de données : %1%]]> @@ -1189,16 +1386,22 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à Feuille de style sauvegardée sans erreurs Type de données sauvegardé Elément de dictionnaire sauvegardé - La publication a échoué car la page parent n'est pas publiée Contenu publié et visible sur le site + %0% documents publiés et visibles sur le site web + %0% publié et visible sur le site web + %0% documents publiés pour la langue %1% et visibles sur le site web Contenu sauvegardé N'oubliez pas de publier pour rendre les modifications visibles + Un planning de publication a été mis à jour + %0% sauvegardé Envoyer pour approbation Les modifications ont été envoyées pour approbation + %0% modifications ont été envoyées pour approbation Media sauvegardé Media sauvegardé sans erreurs Membre sauvegardé + Groupe de membres sauvegardé Propriété de feuille de style sauvegardée Feuille de style sauvegardée Modèle sauvegardé @@ -1213,11 +1416,14 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à Langue sauvegardée Type de média sauvegardé Type de membre sauvegardé + Groupe de membres sauvegardé Modèle non sauvegardé Assurez-vous de ne pas avoir 2 modèles avec le même alias. Modèle sauvegardé Modèle sauvegardé sans aucune erreurs ! Contenu publié + Variation de contenu %0% dépubliée + La langue obligatoire '%0%' a été dépubliée. Toutes les langues pour cet éléménent de contenu sont maintenant dépubliées. Vue partielle sauvegardée Vue partielle sauvegardée sans erreurs ! Vue partielle non sauvegardée @@ -1237,16 +1443,35 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à L'utilisateur %0% a été supprimé Inviter l'utilisateur L'invitation a été envoyée à nouveau à %0% + Impossible de publier le document car la langue obligatoire '%0%' n'est pas publiée + La validation a échoué pour la langue '%0%' + Le Type de Document a été exporté dans le fichier + Une erreur est survenue durant l'export du type de document + La date de publication ne peut pas être dans le passé + Impossible de planifier la publication du document car la langue obligatoire '%0%' n'est pas publiée + Impossible de planifier la publication du document car la langue obligatoire '%0%' a une date de publication postérieure à celle d'une langue non obligatoire + La date d'expiration ne peut pas être dans le passé + La date d'expiration ne peut pas être antérieure à la date de publication - Utilise la syntaxe CSS. Ex : h1, .redHeader, .blueTex + Ajouter un style + Modifier un style + Styles pour l'éditeur de texte + Definir les styles qui doivent êtres disponibles dans l'éditeur de texte pour cette feuille de style Editer la feuille de style Editer la propriété de feuille de style Donner un nom pour identifier la propriété dans le Rich Text Editor Prévisualiser + L'apparence qu'aura le text dans l'éditeur de texte. + Sélecteur + Utilise la syntaxe CSS. Ex : "h1" ou ".redHeader" Styles + Le CSS qui devrait être appliqué dans l'éditeur de texte, e.g. "color:red;" + Code + Editeur de Texte + Echec de la suppression du modèle avec l'ID %0% Editer le modèle Sections Insérer une zone de contenu @@ -1293,6 +1518,7 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à Générateur de requêtes éléments trouvés, en + copier dans le clipboard Je veux tout le contenu le contenu du type "%0%" @@ -1363,7 +1589,9 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à Compositions - Vous n'avez pas ajouté d'onglet + Groupe + Vous n'avez pas ajouté de groupe + Ajouter un groupe Hérité de Ajouter une propriété Label requis @@ -1371,7 +1599,7 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à Configure l'élément de contenu de manière à afficher ses éléments enfants sous forme d'une liste que l'on peut trier et filtrer, les enfants ne seront pas affichés dans l'arborescence Modèles autorisés Sélectionnez les modèles que les éditeurs sont autorisés à utiliser pour du contenu de ce type. - Autorisé comme racine + Autoriser comme racine Autorisez les éditeurs à créer du contenu de ce type à la racine de l'arborescence de contenu. Types de noeuds enfants autorisés Autorisez la création de contenu des types spécifiés sous le contenu de ce type-ci @@ -1379,6 +1607,7 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à Hériter des onglets et propriétés d'un type de document existant. De nouveaux onglets seront ajoutés au type de document actuel, ou fusionnés s'il existe un onglet avec un nom sililaire. Ce type de contenu est utilisé dans une composition, et ne peut donc pas être lui-même un composé. Il n'y a pas de type de contenu disponible à utiliser dans une composition. + La suppression d'une composition supprimera les données de toutes les propriétés associées. Une fois que vous sauvegardez le type de document, il n'y a plus moyen de faire marche arrière. Editeurs disponibles Réutiliser Configuration de l'éditeur @@ -1407,6 +1636,35 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à l'onglet n'a pas d'ordre de tri Où cette composition est-elle utilisée? Cette composition est actuellement utilisée dans la composition des types de contenu suivants : + Permettre une variation par culture + Permettre aux éditeurs de créer du contenu de ce type dans différentes langues. + Permettre une variation par culture + Type de l'Elément + Est un Type d'Elément + Un Type d'Elément est destiné à être utilisé par exemple dans Nested Content, et pas dans l'arborescence. + Ceci n'est pas d'application pour un Type d'Elément + Vous avez apporté des modifications à cette propriété. Etes-vous certain.e de vouloir les annuler? + + + Ajouter une langue + Langue obligatoire + Les propriétés doivent être remplies dans cette langue avant que le noeud ne puisse être publié. + Langue par défaut + Un site Umbraco ne peut avoir qu'une seule langue par défaut définie. + Changer la langue par défaut peut amener à ce que du contenu par défaut soit manquant. + Retombe sur + Pas de langue alternative + Pour permettre à un site multi-langue de retomber sur une autre langue dans le cas où il n'existe pas dans la langue demandée, sélectionnez-là ici. + Langue alternative + aucune + + + Ajouter un paramètre + Modifier le paramètre + Introduire le nom de la macro + Paramètres + Définir les paramètres qui devraient être disponibles lorsque l'on utilise cette macro. + Sélectionner le fichier de vue partielle de la macro Fabrication des modèles @@ -1427,7 +1685,7 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à Choisir un champ Convertir les sauts de ligne Oui, convertir les sauts de ligne - Remplace les sauts de ligne avec des balises &lt;br&gt; + Remplace les sauts de ligne avec des balises 'br' Champs particuliers Oui, la date seulement Format et encodage @@ -1449,7 +1707,7 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à Champs standards Majuscules Encode pour URL - Formatera les caractères spéciaux de manière à ce qu'ils soient reconnus dans une URL + Formatera les caractères spéciaux dans les URL Sera seulement utilisé si toutes les valeurs des champs ci-dessus sont vides Ce champ sera utilisé seulement si le champ initial est vide Oui, avec l'heure. Séparateur: @@ -1519,14 +1777,17 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à Scripts Feuilles de style Modèles + Visualisation des Log Utilisateurs - Analytique + Configuration + Modélisation + Parties Tierces Nouvelle mise à jour disponible %0% est disponible, cliquez ici pour télécharger Aucune connexion au serveur - Erreur lors de la recherche de mises à jour. Veuillez vérifier le stack trace pour obtenir plus d'informations sur l'erreur. + Erreur lors de la recherche de mises à jour. Veuillez vérifier le stack trace pour obtenir plus d'informations. Accès @@ -1554,7 +1815,7 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à Voir le profil de l'utilisateur Ajouter des groupes pour donner les accès et permissions Inviter un autre utilisateur - Inviter de nouveaux utilisateurs pour leur donner accès à Umbraco. Un email d'invitation sera envoyé à chaque utilisateur avec des informations concernant la connexion à Umbraco. + Inviter de nouveaux utilisateurs pour leur donner accès à Umbraco. Un email d'invitation sera envoyé à chaque utilisateur avec des informations concernant la connexion à Umbraco. Les invitations sont valables pendant 72 heures. Langue Spécifiez la langue dans laquelle vous souhaitez voir les menus et dialogues Date du dernier bloquage @@ -1606,7 +1867,8 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à a été invité Une invitation a été envoyée au nouvel utilisateur avec les détails concernant la connexion à Umbraco. Bien le bonjour et bienvenue dans Umbraco! Vous serez prêt.e dans moins d'1 minute, vous devez encore simplement configurer votre mot de passe et ajouter une photo pour votre avatar. - Chargez une photo afin que les autres utilisateurs puissent vous reconnaître facilement. + Bienvenue dans Umbraco! Malheureusement, votre invitation a expiré. Veuillez contacter votre administrateur et demandez-lui de vous l'envoyer à nouveau. + Chargez une photo afin que les autres utilisateurs puissent vous reconnaître facilement. Cliquez sur le cercle ci-dessus pour charger votre photo. Rédacteur Modifier Votre profil @@ -1712,6 +1974,17 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à Nouvel envoi de l'invitation en cours... Supprimer l'Utilisateur Etes-vous certain(e) de vouloir supprimer le compte de cet utilisateur? + Tous + Actif + Désactivé + Bloqué + Invité + Inactif + Nom (A-Z) + Nom (Z-A) + Plus récent + Plus ancien + Dernière connexion Validation @@ -1720,7 +1993,9 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à Valider comme Url ...ou introduisez une validation spécifique Champ obligatoire + Introduisez un message d'erreur de validation personnalisé (optionnel) Introduisez une expression régulière + Introduisez un message d'erreur de validation personnalisé (optionnel) Vous devez ajouter au moins Vous ne pouvez avoir que éléments @@ -1728,6 +2003,12 @@ Pour gérer votre site, ouvrez simplement le backoffice Umbraco et commencez à Date non valide Pas un nombre Email non valide + La valeur ne peut pas être null + La valeur ne peut pas être vide + Valeur non valide, elle ne correspond pas au modèle correct + Validation personnalisée + %1% supplémentaires.]]> + %1% en trop.]]> -
        - - - -
        +
        + + +
        + + + +
        - -
        -
        -
        + +
        + + +
        +
  • diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml index 44cdcc41f0..7fa1249828 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/en.xml @@ -1599,10 +1599,12 @@ To manage your website, simply open the Umbraco back office and start adding con Grid Layouts Layouts are the overall work area for the grid editor, usually you only need one or two different layouts Add Grid Layout + Edit Grid Layout Adjust the layout by setting column widths and adding additional sections Row configurations Rows are predefined cells arranged horizontally Add row configuration + Edit row configuration Adjust the row by setting cell widths and adding additional cells Columns Total combined number of columns in the grid layout diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml index 5e2a11c24c..464e8bbb02 100644 --- a/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml +++ b/src/Umbraco.Web.UI/Umbraco/config/lang/en_us.xml @@ -1616,10 +1616,12 @@ To manage your website, simply open the Umbraco back office and start adding con Grid Layouts Layouts are the overall work area for the grid editor, usually you only need one or two different layouts Add Grid Layout + Edit Grid Layout Adjust the layout by setting column widths and adding additional sections Row configurations Rows are predefined cells arranged horizontally Add row configuration + Edit row configuration Adjust the row by setting cell widths and adding additional cells Columns Total combined number of columns in the grid layout From e6ac534069bd9fdfe0ee3278d769ba7dc9e2d190 Mon Sep 17 00:00:00 2001 From: Andy Butland Date: Thu, 27 Aug 2020 09:27:11 +0200 Subject: [PATCH 333/826] Resolved post-merge issues. --- src/Umbraco.Core/Configuration/Models/GlobalSettings.cs | 2 ++ .../Configuration/ConfigModelConversionsFromLegacy.cs | 1 + .../Configuration/ConfigModelConversionsToLegacy.cs | 5 +++++ 3 files changed, 8 insertions(+) diff --git a/src/Umbraco.Core/Configuration/Models/GlobalSettings.cs b/src/Umbraco.Core/Configuration/Models/GlobalSettings.cs index ac659b6d05..e71d29412d 100644 --- a/src/Umbraco.Core/Configuration/Models/GlobalSettings.cs +++ b/src/Umbraco.Core/Configuration/Models/GlobalSettings.cs @@ -32,6 +32,8 @@ public string Path { get; set; } = "~/umbraco"; + public string IconsPath { get; set; } = $"~/umbraco/assets/icons"; + public string UmbracoCssPath { get; set; } = "~/css"; public string UmbracoScriptsPath { get; set; } = "~/scripts"; diff --git a/src/Umbraco.Infrastructure/Configuration/ConfigModelConversionsFromLegacy.cs b/src/Umbraco.Infrastructure/Configuration/ConfigModelConversionsFromLegacy.cs index 6ce73a9f6c..406e3a115f 100644 --- a/src/Umbraco.Infrastructure/Configuration/ConfigModelConversionsFromLegacy.cs +++ b/src/Umbraco.Infrastructure/Configuration/ConfigModelConversionsFromLegacy.cs @@ -43,6 +43,7 @@ namespace Umbraco.Infrastructure.Configuration UmbracoMediaPath = globalSettings.UmbracoMediaPath, Path = globalSettings.UmbracoPath, UmbracoScriptsPath = globalSettings.UmbracoScriptsPath, + IconsPath = globalSettings.IconsPath, UseHttps = globalSettings.UseHttps, VersionCheckPeriod = globalSettings.VersionCheckPeriod, }; diff --git a/src/Umbraco.Infrastructure/Configuration/ConfigModelConversionsToLegacy.cs b/src/Umbraco.Infrastructure/Configuration/ConfigModelConversionsToLegacy.cs index 5c2d8c090f..355326b082 100644 --- a/src/Umbraco.Infrastructure/Configuration/ConfigModelConversionsToLegacy.cs +++ b/src/Umbraco.Infrastructure/Configuration/ConfigModelConversionsToLegacy.cs @@ -43,6 +43,7 @@ namespace Umbraco.Infrastructure.Configuration UmbracoMediaPath = globalSettings.UmbracoMediaPath, UmbracoPath = globalSettings.Path, UmbracoScriptsPath = globalSettings.UmbracoScriptsPath, + IconsPath = globalSettings.IconsPath, UseHttps = globalSettings.UseHttps, VersionCheckPeriod = globalSettings.VersionCheckPeriod, }; @@ -109,6 +110,10 @@ namespace Umbraco.Infrastructure.Configuration public string MainDomLock { get; set; } public string NoNodesViewPath { get; set; } + + public string IconsPath { get; set; } + + public string ConfigurationStatus { get; set; } } private class TestSmtpSettings : ISmtpSettings From 3b93b6d108471d597b6967a0df27c2e9154a9cd6 Mon Sep 17 00:00:00 2001 From: Sebastiaan Janssen Date: Thu, 27 Aug 2020 09:45:13 +0200 Subject: [PATCH 334/826] Adds .NET Core issue template --- .github/ISSUE_TEMPLATE/3_BugNetCore.md | 65 +++++++++++++++++++ ...port_question.md => 4_Support_question.md} | 0 ...tion_issue.md => 5_Documentation_issue.md} | 0 ..._Security_issue.md => 6_Security_issue.md} | 0 4 files changed, 65 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/3_BugNetCore.md rename .github/ISSUE_TEMPLATE/{3_Support_question.md => 4_Support_question.md} (100%) rename .github/ISSUE_TEMPLATE/{4_Documentation_issue.md => 5_Documentation_issue.md} (100%) rename .github/ISSUE_TEMPLATE/{5_Security_issue.md => 6_Security_issue.md} (100%) diff --git a/.github/ISSUE_TEMPLATE/3_BugNetCore.md b/.github/ISSUE_TEMPLATE/3_BugNetCore.md new file mode 100644 index 0000000000..a6f0187769 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/3_BugNetCore.md @@ -0,0 +1,65 @@ +--- +name: 🌟 .Net Core Bug Report +about: For bugs specifically for the **upcoming** .NET Core release of Umbraco, don't use this if you're working with Umbraco version 7 or 8 +labels: project/net-core +--- + +ℹ️ If this bug **also** appears on the current version 8 of Umbraco then please [report it as a regular bug](https://github.com/umbraco/Umbraco-CMS/issues/new?template=1_Bug.md), fixes in version 8 will be merged to the .NET Core version. + +A brief description of the issue goes here. + + + + +Reproduction +------------ + +If you're filing a bug, please describe how to reproduce it. Include as much +relevant information as possible, such as: + +### Bug summary + + + +### Specifics + + + +### Steps to reproduce + + + +### Expected result + + + +### Actual result + + diff --git a/.github/ISSUE_TEMPLATE/3_Support_question.md b/.github/ISSUE_TEMPLATE/4_Support_question.md similarity index 100% rename from .github/ISSUE_TEMPLATE/3_Support_question.md rename to .github/ISSUE_TEMPLATE/4_Support_question.md diff --git a/.github/ISSUE_TEMPLATE/4_Documentation_issue.md b/.github/ISSUE_TEMPLATE/5_Documentation_issue.md similarity index 100% rename from .github/ISSUE_TEMPLATE/4_Documentation_issue.md rename to .github/ISSUE_TEMPLATE/5_Documentation_issue.md diff --git a/.github/ISSUE_TEMPLATE/5_Security_issue.md b/.github/ISSUE_TEMPLATE/6_Security_issue.md similarity index 100% rename from .github/ISSUE_TEMPLATE/5_Security_issue.md rename to .github/ISSUE_TEMPLATE/6_Security_issue.md From dae94bd9574d2fb5eb69a5a6d96b84e3239ed6d5 Mon Sep 17 00:00:00 2001 From: Sebastiaan Janssen Date: Thu, 27 Aug 2020 09:46:06 +0200 Subject: [PATCH 335/826] Update issue template --- .github/ISSUE_TEMPLATE/3_BugNetCore.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/3_BugNetCore.md b/.github/ISSUE_TEMPLATE/3_BugNetCore.md index a6f0187769..989904d4d8 100644 --- a/.github/ISSUE_TEMPLATE/3_BugNetCore.md +++ b/.github/ISSUE_TEMPLATE/3_BugNetCore.md @@ -1,6 +1,6 @@ --- name: 🌟 .Net Core Bug Report -about: For bugs specifically for the **upcoming** .NET Core release of Umbraco, don't use this if you're working with Umbraco version 7 or 8 +about: For bugs specifically for the upcoming .NET Core release of Umbraco, don't use this if you're working with Umbraco version 7 or 8 labels: project/net-core --- From df4677e97000b3f8ace4974160e71c464689f03f Mon Sep 17 00:00:00 2001 From: Mole Date: Thu, 27 Aug 2020 11:31:46 +0200 Subject: [PATCH 336/826] Update src/Umbraco.Tests.UnitTests/Umbraco.Web.Common/FileNameTests.cs Co-authored-by: Bjarke Berg --- .../Umbraco.Web.Common/FileNameTests.cs | 60 +++++++++---------- 1 file changed, 28 insertions(+), 32 deletions(-) diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Web.Common/FileNameTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Web.Common/FileNameTests.cs index 772becf2e4..c1c331903e 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Web.Common/FileNameTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Web.Common/FileNameTests.cs @@ -1,40 +1,34 @@ -using System; using System.Collections.Generic; -using System.Text; +using System.IO; +using System.Linq; using System.Threading.Tasks; +using AutoFixture.NUnit3; using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.ViewFeatures; using Moq; using NUnit.Framework; using Umbraco.Core.Configuration; -using Umbraco.Tests.UnitTests.AutoFixture; -using Umbraco.Web.Common.Install; -using Umbraco.Core; -using AutoFixture.NUnit3; using Umbraco.Core.Hosting; -using System.IO; -using System.Reflection; -using System.Linq; +using Umbraco.Tests.UnitTests.AutoFixture; using Umbraco.Web.BackOffice.Controllers; -using Microsoft.AspNetCore.Mvc.ViewFeatures; -using AutoFixture; -using Microsoft.AspNetCore.Http; +using Umbraco.Web.Common.Install; namespace Umbraco.Tests.UnitTests.Umbraco.Web.Common { [TestFixture] - class FileNameTests + internal class FileNameTests { - private string getViewName(ViewResult viewResult, string seperator = "/") + private string GetViewName(ViewResult viewResult, string separator = "/") { - var sections = viewResult.ViewName.Split(seperator); - return sections[sections.Length - 1]; + var sections = viewResult.ViewName.Split(separator); + return sections[^1]; } - private string[] getUiFiles(IEnumerable pathFromNetCore) + private IEnumerable GetUiFiles(IEnumerable pathFromNetCore) { var sourceRoot = TestContext.CurrentContext.TestDirectory.Split("Umbraco.Tests.UnitTests")[0]; var pathToFiles = Path.Combine(sourceRoot, "Umbraco.Web.UI.NetCore"); - foreach(var pathSection in pathFromNetCore) + foreach (var pathSection in pathFromNetCore) { pathToFiles = Path.Combine(pathToFiles, pathSection); } @@ -42,35 +36,38 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.Common return new DirectoryInfo(pathToFiles).GetFiles().Select(f => f.Name).ToArray(); } - [Test, AutoMoqData] + [Test] + [AutoMoqData] public async Task InstallViewExists( [Frozen] IHostingEnvironment hostingEnvironment, InstallController sut) { Mock.Get(hostingEnvironment).Setup(x => x.ToAbsolute(It.IsAny())).Returns("http://localhost/"); var viewResult = await sut.Index() as ViewResult; - var fileName = getViewName(viewResult, Path.DirectorySeparatorChar.ToString()); + var fileName = GetViewName(viewResult, Path.DirectorySeparatorChar.ToString()); - var views = getUiFiles(new string[] { "Umbraco", "UmbracoInstall" }); + var views = GetUiFiles(new[] { "Umbraco", "UmbracoInstall" }); Assert.True(views.Contains(fileName), $"Expected {fileName} to exist, but it didn't"); } - [Test, AutoMoqData] - public void PrviewViewExists( + [Test] + [AutoMoqData] + public void PreviewViewExists( [Frozen] IGlobalSettings globalSettings, PreviewController sut) { Mock.Get(globalSettings).Setup(x => x.UmbracoPath).Returns("/"); var viewResult = sut.Index() as ViewResult; - var fileName = getViewName(viewResult); + var fileName = GetViewName(viewResult); - var views = getUiFiles(new string[] {"Umbraco", "UmbracoBackOffice" }); + var views = GetUiFiles(new[] { "Umbraco", "UmbracoBackOffice" }); Assert.True(views.Contains(fileName), $"Expected {fileName} to exist, but it didn't"); } - [Test, AutoMoqData] + [Test] + [AutoMoqData] public async Task BackOfficeDefaultExists( [Frozen] IGlobalSettings globalSettings, [Frozen] IHostingEnvironment hostingEnvironment, @@ -85,8 +82,8 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.Common sut.TempData = tempDataDictionary; var viewResult = await sut.Default() as ViewResult; - var fileName = getViewName(viewResult); - var views = getUiFiles(new string[] { "Umbraco", "UmbracoBackOffice" }); + var fileName = GetViewName(viewResult); + var views = GetUiFiles(new[] { "Umbraco", "UmbracoBackOffice" }); Assert.True(views.Contains(fileName), $"Expected {fileName} to exist, but it didn't"); } @@ -95,13 +92,12 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.Common [Test] public void LanguageFilesAreLowercase() { - - var files = getUiFiles(new string[] { "Umbraco", "config", "lang" }); + var files = GetUiFiles(new[] { "Umbraco", "config", "lang" }); foreach (var fileName in files) { - Assert.AreEqual(fileName.ToLower(), fileName, $"Language files must be all lowercase but {fileName} is not lowercase."); + Assert.AreEqual(fileName.ToLower(), fileName, + $"Language files must be all lowercase but {fileName} is not lowercase."); } - } } } From ecfc520d44ebfeaf7465ef73011406bb04ce2594 Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Thu, 27 Aug 2020 10:38:27 +0100 Subject: [PATCH 337/826] Make the selector less specific to fix the doctype tour The child element no longer contains an but is a
    +
    diff --git a/src/Umbraco.Web.UI.Client/src/views/components/blockcard/umbBlockCard.component.js b/src/Umbraco.Web.UI.Client/src/views/components/blockcard/umbBlockCard.component.js index c0758aa2df..454d264a89 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/blockcard/umbBlockCard.component.js +++ b/src/Umbraco.Web.UI.Client/src/views/components/blockcard/umbBlockCard.component.js @@ -14,9 +14,39 @@ } }); - function BlockCardController() { + function BlockCardController($scope, umbRequestHelper) { var vm = this; + vm.styleBackgroundImage = "transparent"; + + var unwatch = $scope.$watch("vm.blockConfigModel.thumbnail", (newValue, oldValue) => { + console.log("updateThumbnail") + if(newValue !== oldValue) { + vm.updateThumbnail(); + } + }); + + vm.$onInit = function () { + + vm.updateThumbnail(); + + } + vm.$onDestroy = function () { + unwatch(); + } + + vm.updateThumbnail = function () { + if (vm.blockConfigModel.thumbnail == null || vm.blockConfigModel.thumbnail === "") { + vm.styleBackgroundImage = "transparent"; + return; + } + + var path = umbRequestHelper.convertVirtualToAbsolutePath(vm.blockConfigModel.thumbnail); + if (path.toLowerCase().endsWith(".svg") === false) { + path += "?upscale=false&width=400)"; + } + vm.styleBackgroundImage = 'url(\''+path+'\')'; + } } From 1c09ee7dcec9f61de2ff50c500d5b1e84f8c5bfc Mon Sep 17 00:00:00 2001 From: Chriztian Steinmeier Date: Mon, 24 Aug 2020 21:58:21 +0200 Subject: [PATCH 269/826] Add `!important' to the color in the style attribute (#8710) Turns out `!important` doesn't work with the `ng-style` attribute, so have stwitched to use `ng-attr-style` instead, which works. --- .../src/views/components/blockcard/umb-block-card.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/components/blockcard/umb-block-card.html b/src/Umbraco.Web.UI.Client/src/views/components/blockcard/umb-block-card.html index 486bcbda4a..f8ccccd166 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/blockcard/umb-block-card.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/blockcard/umb-block-card.html @@ -1,6 +1,6 @@
    - +
    From 7e32de7bb651a5c106f490fa7aad5a8c9fe7ab49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Mon, 24 Aug 2020 21:59:34 +0200 Subject: [PATCH 270/826] important fix --- .../src/views/components/blockcard/umb-block-card.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/components/blockcard/umb-block-card.html b/src/Umbraco.Web.UI.Client/src/views/components/blockcard/umb-block-card.html index 486bcbda4a..f8ccccd166 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/blockcard/umb-block-card.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/blockcard/umb-block-card.html @@ -1,6 +1,6 @@
    - +
    From aedd7563a4acf05884c8bb19468a9e9261cc1ac4 Mon Sep 17 00:00:00 2001 From: Andy Butland Date: Mon, 24 Aug 2020 22:58:23 +0200 Subject: [PATCH 271/826] Restored Umbraco.Tests (further) --- .../Packaging/PackageInstallationTest.cs | 9 +- .../Repositories/MediaRepositoryTest.cs | 5 +- .../Repositories/MediaTypeRepositoryTest.cs | 4 +- .../Repositories/MemberRepositoryTest.cs | 4 +- .../Repositories/MemberTypeRepositoryTest.cs | 4 +- .../PublicAccessRepositoryTest.cs | 4 +- .../Repositories/ScriptRepositoryTest.cs | 4 +- .../Repositories/StylesheetRepositoryTest.cs | 4 +- .../Repositories/TagRepositoryTest.cs | 7 +- .../Repositories/TemplateRepositoryTest.cs | 5 +- .../PublishedContent/NuCacheTests.cs | 4 +- .../Routing/ContentFinderByIdTests.cs | 4 +- .../ContentFinderByUrlAndTemplateTests.cs | 2 +- .../Routing/MediaUrlProviderTests.cs | 10 +- .../Routing/UmbracoModuleTests.cs | 10 +- src/Umbraco.Tests/Routing/UrlProviderTests.cs | 107 +++++++++-------- .../Routing/UrlsProviderWithDomainsTests.cs | 86 ++++++++------ .../Routing/UrlsWithNestedDomains.cs | 17 +-- src/Umbraco.Tests/Runtimes/StandaloneTests.cs | 5 +- .../Scoping/ScopeEventDispatcherTests.cs | 4 +- .../Services/ContentServicePerformanceTest.cs | 4 +- .../Strings/CmsHelperCasingTests.cs | 4 +- .../Templates/HtmlImageSourceParserTests.cs | 5 +- .../Templates/HtmlLocalLinkParserTests.cs | 4 +- src/Umbraco.Tests/TestHelpers/BaseWebTest.cs | 9 +- .../TestHelpers/ConfigModelConversions.cs | 109 ++++++++++++++++++ .../Testing/TestingTests/MockTests.cs | 4 +- src/Umbraco.Tests/Testing/UmbracoTestBase.cs | 45 ++++---- src/Umbraco.Tests/Umbraco.Tests.csproj | 4 +- .../UmbracoExamine/ExamineBaseTest.cs | 5 +- .../Web/Mvc/SurfaceControllerTests.cs | 5 +- .../Web/Mvc/UmbracoViewPageTests.cs | 4 +- .../Configuration/ConfigModelConversions.cs | 2 +- 33 files changed, 341 insertions(+), 162 deletions(-) create mode 100644 src/Umbraco.Tests/TestHelpers/ConfigModelConversions.cs diff --git a/src/Umbraco.Tests/Packaging/PackageInstallationTest.cs b/src/Umbraco.Tests/Packaging/PackageInstallationTest.cs index 1cfb9167ce..04c51029c7 100644 --- a/src/Umbraco.Tests/Packaging/PackageInstallationTest.cs +++ b/src/Umbraco.Tests/Packaging/PackageInstallationTest.cs @@ -47,7 +47,11 @@ namespace Umbraco.Tests.Packaging _testBaseFolder.Delete(true); } - private CompiledPackageXmlParser Parser => new CompiledPackageXmlParser(new ConflictingPackageData(ServiceContext.MacroService, ServiceContext.FileService),Factory.GetInstance()); + private CompiledPackageXmlParser Parser => new CompiledPackageXmlParser( + new ConflictingPackageData( + ServiceContext.MacroService, + ServiceContext.FileService), + new GlobalSettingsBuilder().Build()); private PackageDataInstallation PackageDataInstallation => new PackageDataInstallation( Logger, ServiceContext.FileService, ServiceContext.MacroService, ServiceContext.LocalizationService, @@ -57,8 +61,7 @@ namespace Umbraco.Tests.Packaging Factory.GetInstance(), Factory.GetInstance(), new GlobalSettingsBuilder().Build(), - Factory.GetInstance() - ); + Factory.GetInstance() ); private IPackageInstallation PackageInstallation => new PackageInstallation( PackageDataInstallation, diff --git a/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs index 83572180af..119a207cb9 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs @@ -16,6 +16,7 @@ using Umbraco.Tests.Testing; using Umbraco.Core.Services; using Umbraco.Core; using Umbraco.Core.PropertyEditors; +using Umbraco.Tests.Common.Builders; namespace Umbraco.Tests.Persistence.Repositories { @@ -34,10 +35,10 @@ namespace Umbraco.Tests.Persistence.Repositories { appCaches = appCaches ?? AppCaches; var scopeAccessor = (IScopeAccessor) provider; - + var globalSettings = new GlobalSettingsBuilder().Build(); var templateRepository = new TemplateRepository(scopeAccessor, appCaches, Logger, TestObjects.GetFileSystemsMock(), IOHelper, ShortStringHelper); var commonRepository = new ContentTypeCommonRepository(scopeAccessor, templateRepository, appCaches, ShortStringHelper); - var languageRepository = new LanguageRepository(scopeAccessor, appCaches, Logger, TestObjects.GetGlobalSettings()); + var languageRepository = new LanguageRepository(scopeAccessor, appCaches, Logger, Microsoft.Extensions.Options.Options.Create(globalSettings)); mediaTypeRepository = new MediaTypeRepository(scopeAccessor, appCaches, Logger, commonRepository, languageRepository, ShortStringHelper); var tagRepository = new TagRepository(scopeAccessor, appCaches, Logger); var relationTypeRepository = new RelationTypeRepository(scopeAccessor, AppCaches.Disabled, Logger); diff --git a/src/Umbraco.Tests/Persistence/Repositories/MediaTypeRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/MediaTypeRepositoryTest.cs index 6ffbdaca10..fac2a6665a 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/MediaTypeRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/MediaTypeRepositoryTest.cs @@ -8,6 +8,7 @@ using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.Dtos; using Umbraco.Core.Persistence.Repositories.Implement; using Umbraco.Core.Scoping; +using Umbraco.Tests.Common.Builders; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.TestHelpers.Entities; using Umbraco.Tests.Testing; @@ -21,9 +22,10 @@ namespace Umbraco.Tests.Persistence.Repositories private MediaTypeRepository CreateRepository(IScopeProvider provider) { var cacheHelper = AppCaches.Disabled; + var globalSettings = new GlobalSettingsBuilder().Build(); var templateRepository = new TemplateRepository((IScopeAccessor)provider, cacheHelper, Logger, TestObjects.GetFileSystemsMock(), IOHelper, ShortStringHelper); var commonRepository = new ContentTypeCommonRepository((IScopeAccessor)provider, templateRepository, AppCaches, ShortStringHelper); - var languageRepository = new LanguageRepository((IScopeAccessor)provider, AppCaches, Logger, TestObjects.GetGlobalSettings()); + var languageRepository = new LanguageRepository((IScopeAccessor)provider, AppCaches, Logger, Microsoft.Extensions.Options.Options.Create(globalSettings)); return new MediaTypeRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger, commonRepository, languageRepository, ShortStringHelper); } diff --git a/src/Umbraco.Tests/Persistence/Repositories/MemberRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/MemberRepositoryTest.cs index b8c823f59e..37d5260dc0 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/MemberRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/MemberRepositoryTest.cs @@ -17,6 +17,7 @@ using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.Repositories.Implement; using Umbraco.Core.PropertyEditors; using Umbraco.Core.Scoping; +using Umbraco.Tests.Common.Builders; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.TestHelpers.Entities; using Umbraco.Tests.Testing; @@ -30,9 +31,10 @@ namespace Umbraco.Tests.Persistence.Repositories private MemberRepository CreateRepository(IScopeProvider provider, out MemberTypeRepository memberTypeRepository, out MemberGroupRepository memberGroupRepository) { var accessor = (IScopeAccessor) provider; + var globalSettings = new GlobalSettingsBuilder().Build(); var templateRepository = Mock.Of(); var commonRepository = new ContentTypeCommonRepository(accessor, templateRepository, AppCaches, ShortStringHelper); - var languageRepository = new LanguageRepository(accessor, AppCaches.Disabled, Logger, TestObjects.GetGlobalSettings()); + var languageRepository = new LanguageRepository(accessor, AppCaches.Disabled, Logger, Microsoft.Extensions.Options.Options.Create(globalSettings)); memberTypeRepository = new MemberTypeRepository(accessor, AppCaches.Disabled, Logger, commonRepository, languageRepository, ShortStringHelper); memberGroupRepository = new MemberGroupRepository(accessor, AppCaches.Disabled, Logger); var tagRepo = new TagRepository(accessor, AppCaches.Disabled, Logger); diff --git a/src/Umbraco.Tests/Persistence/Repositories/MemberTypeRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/MemberTypeRepositoryTest.cs index b8c60f97fe..be32305cfc 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/MemberTypeRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/MemberTypeRepositoryTest.cs @@ -10,6 +10,7 @@ using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.Repositories.Implement; using Umbraco.Core.Scoping; +using Umbraco.Tests.Common.Builders; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.TestHelpers.Entities; using Umbraco.Tests.Testing; @@ -23,8 +24,9 @@ namespace Umbraco.Tests.Persistence.Repositories private MemberTypeRepository CreateRepository(IScopeProvider provider) { var templateRepository = Mock.Of(); + var globalSettings = new GlobalSettingsBuilder().Build(); var commonRepository = new ContentTypeCommonRepository((IScopeAccessor)provider, templateRepository, AppCaches, ShortStringHelper); - var languageRepository = new LanguageRepository((IScopeAccessor)provider, AppCaches.Disabled, Mock.Of(), TestObjects.GetGlobalSettings()); + var languageRepository = new LanguageRepository((IScopeAccessor)provider, AppCaches.Disabled, Mock.Of(), Microsoft.Extensions.Options.Options.Create(globalSettings)); return new MemberTypeRepository((IScopeAccessor) provider, AppCaches.Disabled, Mock.Of(), commonRepository, languageRepository, ShortStringHelper); } diff --git a/src/Umbraco.Tests/Persistence/Repositories/PublicAccessRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/PublicAccessRepositoryTest.cs index 4ba2c3eab6..b31d490578 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/PublicAccessRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/PublicAccessRepositoryTest.cs @@ -9,6 +9,7 @@ using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.Repositories.Implement; using Umbraco.Core.PropertyEditors; using Umbraco.Core.Scoping; +using Umbraco.Tests.Common.Builders; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.TestHelpers.Entities; using Umbraco.Tests.Testing; @@ -306,10 +307,11 @@ namespace Umbraco.Tests.Persistence.Repositories private DocumentRepository CreateRepository(IScopeProvider provider, out ContentTypeRepository contentTypeRepository) { var accessor = (IScopeAccessor) provider; + var globalSettings = new GlobalSettingsBuilder().Build(); var templateRepository = new TemplateRepository(accessor, AppCaches, Logger, TestObjects.GetFileSystemsMock(), IOHelper, ShortStringHelper); var tagRepository = new TagRepository(accessor, AppCaches, Logger); var commonRepository = new ContentTypeCommonRepository(accessor, templateRepository, AppCaches, ShortStringHelper); - var languageRepository = new LanguageRepository(accessor, AppCaches, Logger, TestObjects.GetGlobalSettings()); + var languageRepository = new LanguageRepository(accessor, AppCaches, Logger, Microsoft.Extensions.Options.Options.Create(globalSettings)); contentTypeRepository = new ContentTypeRepository(accessor, AppCaches, Logger, commonRepository, languageRepository, ShortStringHelper); var relationTypeRepository = new RelationTypeRepository(accessor, AppCaches, Logger); var entityRepository = new EntityRepository(accessor); diff --git a/src/Umbraco.Tests/Persistence/Repositories/ScriptRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/ScriptRepositoryTest.cs index 7922af99b0..2ef8d2d30f 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/ScriptRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/ScriptRepositoryTest.cs @@ -13,6 +13,7 @@ using Umbraco.Core.Models; using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.Repositories.Implement; using Umbraco.Core.PropertyEditors; +using Umbraco.Tests.Common.Builders; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.Testing; @@ -40,7 +41,8 @@ namespace Umbraco.Tests.Persistence.Repositories private IScriptRepository CreateRepository() { - return new ScriptRepository(_fileSystems, IOHelper, TestObjects.GetGlobalSettings()); + var globalSettings = new GlobalSettingsBuilder().Build(); + return new ScriptRepository(_fileSystems, IOHelper, Microsoft.Extensions.Options.Options.Create(globalSettings)); } protected override void Compose() diff --git a/src/Umbraco.Tests/Persistence/Repositories/StylesheetRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/StylesheetRepositoryTest.cs index f4558dca2d..5b6f77ac7e 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/StylesheetRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/StylesheetRepositoryTest.cs @@ -12,6 +12,7 @@ using Umbraco.Core.IO; using Umbraco.Core.Models; using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.Repositories.Implement; +using Umbraco.Tests.Common.Builders; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.Testing; @@ -37,7 +38,8 @@ namespace Umbraco.Tests.Persistence.Repositories private IStylesheetRepository CreateRepository() { - return new StylesheetRepository(_fileSystems, IOHelper, TestObjects.GetGlobalSettings()); + var globalSettings = new GlobalSettingsBuilder().Build(); + return new StylesheetRepository(_fileSystems, IOHelper, Microsoft.Extensions.Options.Options.Create(globalSettings)); } [Test] diff --git a/src/Umbraco.Tests/Persistence/Repositories/TagRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/TagRepositoryTest.cs index d4341cd128..913fc876fe 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/TagRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/TagRepositoryTest.cs @@ -10,6 +10,7 @@ using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.Repositories.Implement; using Umbraco.Core.PropertyEditors; using Umbraco.Core.Scoping; +using Umbraco.Tests.Common.Builders; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.TestHelpers.Entities; using Umbraco.Tests.Testing; @@ -955,10 +956,11 @@ namespace Umbraco.Tests.Persistence.Repositories private DocumentRepository CreateDocumentRepository(IScopeProvider provider, out ContentTypeRepository contentTypeRepository) { var accessor = (IScopeAccessor) provider; + var globalSettings = new GlobalSettingsBuilder().Build(); var templateRepository = new TemplateRepository(accessor, AppCaches.Disabled, Logger, TestObjects.GetFileSystemsMock(), IOHelper, ShortStringHelper); var tagRepository = new TagRepository(accessor, AppCaches.Disabled, Logger); var commonRepository = new ContentTypeCommonRepository(accessor, templateRepository, AppCaches.Disabled, ShortStringHelper); - var languageRepository = new LanguageRepository(accessor, AppCaches.Disabled, Logger, TestObjects.GetGlobalSettings()); + var languageRepository = new LanguageRepository(accessor, AppCaches.Disabled, Logger, Microsoft.Extensions.Options.Options.Create(globalSettings)); contentTypeRepository = new ContentTypeRepository(accessor, AppCaches.Disabled, Logger, commonRepository, languageRepository, ShortStringHelper); var relationTypeRepository = new RelationTypeRepository(accessor, AppCaches.Disabled, Logger); var entityRepository = new EntityRepository(accessor); @@ -972,10 +974,11 @@ namespace Umbraco.Tests.Persistence.Repositories private MediaRepository CreateMediaRepository(IScopeProvider provider, out MediaTypeRepository mediaTypeRepository) { var accessor = (IScopeAccessor) provider; + var globalSettings = new GlobalSettingsBuilder().Build(); var templateRepository = new TemplateRepository(accessor, AppCaches.Disabled, Logger, TestObjects.GetFileSystemsMock(), IOHelper, ShortStringHelper); var tagRepository = new TagRepository(accessor, AppCaches.Disabled, Logger); var commonRepository = new ContentTypeCommonRepository(accessor, templateRepository, AppCaches.Disabled, ShortStringHelper); - var languageRepository = new LanguageRepository(accessor, AppCaches.Disabled, Logger, TestObjects.GetGlobalSettings()); + var languageRepository = new LanguageRepository(accessor, AppCaches.Disabled, Logger, Microsoft.Extensions.Options.Options.Create(globalSettings)); mediaTypeRepository = new MediaTypeRepository(accessor, AppCaches.Disabled, Logger, commonRepository, languageRepository, ShortStringHelper); var relationTypeRepository = new RelationTypeRepository(accessor, AppCaches.Disabled, Logger); var entityRepository = new EntityRepository(accessor); diff --git a/src/Umbraco.Tests/Persistence/Repositories/TemplateRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/TemplateRepositoryTest.cs index b7c1f6a2a8..fdf7b48a4a 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/TemplateRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/TemplateRepositoryTest.cs @@ -15,6 +15,7 @@ using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.Repositories.Implement; using Umbraco.Core.PropertyEditors; using Umbraco.Core.Scoping; +using Umbraco.Tests.Common.Builders; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.TestHelpers.Entities; using Umbraco.Tests.Testing; @@ -238,10 +239,10 @@ namespace Umbraco.Tests.Persistence.Repositories using (ScopeProvider.CreateScope()) { var templateRepository = CreateRepository(ScopeProvider); - + var globalSettings = new GlobalSettingsBuilder().Build(); var tagRepository = new TagRepository(ScopeProvider, AppCaches.Disabled, Logger); var commonRepository = new ContentTypeCommonRepository(ScopeProvider, templateRepository, AppCaches, ShortStringHelper); - var languageRepository = new LanguageRepository(ScopeProvider, AppCaches.Disabled, Logger, TestObjects.GetGlobalSettings()); + var languageRepository = new LanguageRepository(ScopeProvider, AppCaches.Disabled, Logger, Microsoft.Extensions.Options.Options.Create(globalSettings)); var contentTypeRepository = new ContentTypeRepository(ScopeProvider, AppCaches.Disabled, Logger, commonRepository, languageRepository, ShortStringHelper); var relationTypeRepository = new RelationTypeRepository(ScopeProvider, AppCaches.Disabled, Logger); var entityRepository = new EntityRepository(ScopeProvider); diff --git a/src/Umbraco.Tests/PublishedContent/NuCacheTests.cs b/src/Umbraco.Tests/PublishedContent/NuCacheTests.cs index da67a76eb9..d65d89a363 100644 --- a/src/Umbraco.Tests/PublishedContent/NuCacheTests.cs +++ b/src/Umbraco.Tests/PublishedContent/NuCacheTests.cs @@ -201,14 +201,14 @@ namespace Umbraco.Tests.PublishedContent Mock.Of(), new TestDefaultCultureAccessor(), dataSource, - globalSettings, + Microsoft.Extensions.Options.Options.Create(globalSettings), Mock.Of(), publishedModelFactory, new UrlSegmentProviderCollection(new[] { new DefaultUrlSegmentProvider(TestHelper.ShortStringHelper) }), TestHelper.GetHostingEnvironment(), new MockShortStringHelper(), TestHelper.IOHelper, - nuCacheSettings); + Microsoft.Extensions.Options.Options.Create(nuCacheSettings)); // invariant is the current default _variationAccesor.VariationContext = new VariationContext(); diff --git a/src/Umbraco.Tests/Routing/ContentFinderByIdTests.cs b/src/Umbraco.Tests/Routing/ContentFinderByIdTests.cs index d3c820d239..069aead6b3 100644 --- a/src/Umbraco.Tests/Routing/ContentFinderByIdTests.cs +++ b/src/Umbraco.Tests/Routing/ContentFinderByIdTests.cs @@ -1,5 +1,6 @@ using NUnit.Framework; using Umbraco.Core; +using Umbraco.Tests.Common.Builders; using Umbraco.Tests.TestHelpers; using Umbraco.Web; using Umbraco.Web.Routing; @@ -17,7 +18,8 @@ namespace Umbraco.Tests.Routing var umbracoContext = GetUmbracoContext(urlAsString); var publishedRouter = CreatePublishedRouter(); var frequest = publishedRouter.CreateRequest(umbracoContext); - var lookup = new ContentFinderByIdPath(SettingsForTests.GenerateMockWebRoutingSettings(), Logger, Factory.GetInstance()); + var webRoutingSettings = new WebRoutingSettingsBuilder().Build(); + var lookup = new ContentFinderByIdPath(Microsoft.Extensions.Options.Options.Create(webRoutingSettings), Logger, Factory.GetInstance()); var result = lookup.TryFindContent(frequest); diff --git a/src/Umbraco.Tests/Routing/ContentFinderByUrlAndTemplateTests.cs b/src/Umbraco.Tests/Routing/ContentFinderByUrlAndTemplateTests.cs index 07f0e587e3..2c991ce455 100644 --- a/src/Umbraco.Tests/Routing/ContentFinderByUrlAndTemplateTests.cs +++ b/src/Umbraco.Tests/Routing/ContentFinderByUrlAndTemplateTests.cs @@ -40,7 +40,7 @@ namespace Umbraco.Tests.Routing var publishedRouter = CreatePublishedRouter(); var frequest = publishedRouter.CreateRequest(umbracoContext); var webRoutingSettings = new WebRoutingSettingsBuilder().Build(); - var lookup = new ContentFinderByUrlAndTemplate(Logger, ServiceContext.FileService, ServiceContext.ContentTypeService, webRoutingSettings); + var lookup = new ContentFinderByUrlAndTemplate(Logger, ServiceContext.FileService, ServiceContext.ContentTypeService, Microsoft.Extensions.Options.Options.Create(webRoutingSettings)); var result = lookup.TryFindContent(frequest); diff --git a/src/Umbraco.Tests/Routing/MediaUrlProviderTests.cs b/src/Umbraco.Tests/Routing/MediaUrlProviderTests.cs index e55a22065b..4545dc5a0e 100644 --- a/src/Umbraco.Tests/Routing/MediaUrlProviderTests.cs +++ b/src/Umbraco.Tests/Routing/MediaUrlProviderTests.cs @@ -13,6 +13,7 @@ using Umbraco.Core.PropertyEditors; using Umbraco.Core.PropertyEditors.ValueConverters; using Umbraco.Core.Services; using Umbraco.Tests.Common; +using Umbraco.Tests.Common.Builders; using Umbraco.Tests.PublishedContent; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.Testing; @@ -34,12 +35,12 @@ namespace Umbraco.Tests.Routing var logger = Mock.Of(); var mediaFileSystemMock = Mock.Of(); - var contentSection = Mock.Of(); + var contentSettings = new ContentSettingsBuilder().Build(); var dataTypeService = Mock.Of(); var propertyEditors = new MediaUrlGeneratorCollection(new IMediaUrlGenerator[] { - new FileUploadPropertyEditor(logger, mediaFileSystemMock, contentSection, dataTypeService, LocalizationService, LocalizedTextService, ShortStringHelper), - new ImageCropperPropertyEditor(logger, mediaFileSystemMock, contentSection, dataTypeService, LocalizationService, IOHelper, ShortStringHelper, LocalizedTextService), + new FileUploadPropertyEditor(logger, mediaFileSystemMock, contentSettings, dataTypeService, LocalizationService, LocalizedTextService, ShortStringHelper), + new ImageCropperPropertyEditor(logger, mediaFileSystemMock, contentSettings, dataTypeService, LocalizationService, IOHelper, ShortStringHelper, LocalizedTextService), }); _mediaUrlProvider = new DefaultMediaUrlProvider(propertyEditors, UriUtility); } @@ -149,9 +150,10 @@ namespace Umbraco.Tests.Routing private IPublishedUrlProvider GetPublishedUrlProvider(IUmbracoContext umbracoContext) { + var webRoutingSettings = new WebRoutingSettingsBuilder().Build(); return new UrlProvider( new TestUmbracoContextAccessor(umbracoContext), - TestHelper.WebRoutingSettings, + Microsoft.Extensions.Options.Options.Create(webRoutingSettings), new UrlProviderCollection(Enumerable.Empty()), new MediaUrlProviderCollection(new []{_mediaUrlProvider}), Mock.Of() diff --git a/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs b/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs index 4dfcd46788..252e03f4c0 100644 --- a/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs +++ b/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs @@ -16,6 +16,8 @@ using Umbraco.Core.Services; using Umbraco.Web.PublishedCache; using Umbraco.Web.Routing; using Umbraco.Web.Configuration; +using ConfigModelConversions = Umbraco.Tests.TestHelpers.ConfigModelConversions; +using Umbraco.Tests.Common.Builders; namespace Umbraco.Tests.Routing { @@ -32,8 +34,8 @@ namespace Umbraco.Tests.Routing // FIXME: be able to get the UmbracoModule from the container. any reason settings were from testobjects? //create the module var logger = Mock.Of(); - var globalSettings = TestObjects.GetGlobalSettings(); - var runtime = new RuntimeState(ConfigModelConversions.ConvertGlobalSettings(globalSettings), UmbracoVersion); + var globalSettings = new GlobalSettingsBuilder().Build(); + var runtime = new RuntimeState(globalSettings, UmbracoVersion); _module = new UmbracoInjectedModule ( @@ -41,10 +43,10 @@ namespace Umbraco.Tests.Routing logger, null, // FIXME: PublishedRouter complexities... Mock.Of(), - new RoutableDocumentFilter(globalSettings, IOHelper), + new RoutableDocumentFilter(ConfigModelConversions.ConvertGlobalSettings(globalSettings), IOHelper), UriUtility, AppCaches.RequestCache, - globalSettings, + ConfigModelConversions.ConvertGlobalSettings(globalSettings), HostingEnvironment ); diff --git a/src/Umbraco.Tests/Routing/UrlProviderTests.cs b/src/Umbraco.Tests/Routing/UrlProviderTests.cs index 1ff0a2b33d..d7a6cc701a 100644 --- a/src/Umbraco.Tests/Routing/UrlProviderTests.cs +++ b/src/Umbraco.Tests/Routing/UrlProviderTests.cs @@ -17,6 +17,7 @@ using Umbraco.Web; using Umbraco.Web.PublishedCache; using Umbraco.Web.Routing; using Umbraco.Tests.Common; +using Umbraco.Tests.Common.Builders; namespace Umbraco.Tests.Routing { @@ -45,14 +46,16 @@ namespace Umbraco.Tests.Routing [Test] public void Ensure_Cache_Is_Correct() { - var globalSettings = Mock.Get(Factory.GetInstance()); //this will modify the IGlobalSettings instance stored in the container - globalSettings.Setup(x => x.HideTopLevelNodeFromPath).Returns(false); + var globalSettings = new GlobalSettingsBuilder().WithHideTopLevelNodeFromPath(false).Build(); - var requestHandlerSettings = TestHelpers.SettingsForTests.GenerateMockRequestHandlerSettings(); + var requestHandlerSettings = new RequestHandlerSettingsBuilder().Build(); - var umbracoContext = GetUmbracoContext("/test", 1111, globalSettings: globalSettings.Object); + var umbracoContext = GetUmbracoContext("/test", 1111, globalSettings: ConfigModelConversions.ConvertGlobalSettings(globalSettings)); var umbracoContextAccessor = new TestUmbracoContextAccessor(umbracoContext); - var urlProvider = new DefaultUrlProvider(requestHandlerSettings, Logger, globalSettings.Object, + var urlProvider = new DefaultUrlProvider( + Microsoft.Extensions.Options.Options.Create(requestHandlerSettings), + Logger, + Microsoft.Extensions.Options.Options.Create(globalSettings), new SiteDomainHelper(), umbracoContextAccessor, UriUtility); var publishedUrlProvider = GetPublishedUrlProvider(umbracoContext, urlProvider); @@ -100,13 +103,13 @@ namespace Umbraco.Tests.Routing private IPublishedUrlProvider GetPublishedUrlProvider(IUmbracoContext umbracoContext, DefaultUrlProvider urlProvider) { + var webRoutingSettings = new WebRoutingSettingsBuilder().Build(); return new UrlProvider( new TestUmbracoContextAccessor(umbracoContext), - TestHelper.WebRoutingSettings, + Microsoft.Extensions.Options.Options.Create(webRoutingSettings), new UrlProviderCollection(new []{urlProvider}), new MediaUrlProviderCollection(Enumerable.Empty()), - Mock.Of() - ); + Mock.Of()); } // test hideTopLevelNodeFromPath false @@ -120,15 +123,16 @@ namespace Umbraco.Tests.Routing [TestCase(1172, "/test-page/")] public void Get_Url_Not_Hiding_Top_Level(int nodeId, string niceUrlMatch) { - var globalSettings = Mock.Get(Factory.GetInstance()); //this will modify the IGlobalSettings instance stored in the container - globalSettings.Setup(x => x.HideTopLevelNodeFromPath).Returns(false); + var globalSettings = new GlobalSettingsBuilder().WithHideTopLevelNodeFromPath(false).Build(); - var requestHandlerSettings = TestHelpers.SettingsForTests.GenerateMockRequestHandlerSettings(); + var requestHandlerSettings = new RequestHandlerSettingsBuilder().Build(); - - var umbracoContext = GetUmbracoContext("/test", 1111, globalSettings: globalSettings.Object); + var umbracoContext = GetUmbracoContext("/test", 1111, globalSettings: ConfigModelConversions.ConvertGlobalSettings(globalSettings)); var umbracoContextAccessor = new TestUmbracoContextAccessor(umbracoContext); - var urlProvider = new DefaultUrlProvider(requestHandlerSettings, Logger, globalSettings.Object, + var urlProvider = new DefaultUrlProvider( + Microsoft.Extensions.Options.Options.Create(requestHandlerSettings), + Logger, + Microsoft.Extensions.Options.Options.Create(globalSettings), new SiteDomainHelper(), umbracoContextAccessor, UriUtility); var publishedUrlProvider = GetPublishedUrlProvider(umbracoContext, urlProvider); @@ -149,13 +153,15 @@ namespace Umbraco.Tests.Routing [TestCase(1172, "/test-page/")] // not hidden because not first root public void Get_Url_Hiding_Top_Level(int nodeId, string niceUrlMatch) { - var globalSettings = Mock.Get(Factory.GetInstance()); //this will modify the IGlobalSettings instance stored in the container - globalSettings.Setup(x => x.HideTopLevelNodeFromPath).Returns(true); + var globalSettings = new GlobalSettingsBuilder().WithHideTopLevelNodeFromPath(true).Build(); - var requestHandlerSettings = TestHelpers.SettingsForTests.GenerateMockRequestHandlerSettings(); - var umbracoContext = GetUmbracoContext("/test", 1111, globalSettings: globalSettings.Object); + var requestHandlerSettings = new RequestHandlerSettingsBuilder().Build(); + var umbracoContext = GetUmbracoContext("/test", 1111, globalSettings: ConfigModelConversions.ConvertGlobalSettings(globalSettings)); var umbracoContextAccessor = new TestUmbracoContextAccessor(umbracoContext); - var urlProvider = new DefaultUrlProvider(requestHandlerSettings, Logger, globalSettings.Object, + var urlProvider = new DefaultUrlProvider( + Microsoft.Extensions.Options.Options.Create(requestHandlerSettings), + Logger, + Microsoft.Extensions.Options.Options.Create(globalSettings), new SiteDomainHelper(), umbracoContextAccessor, UriUtility); var publishedUrlProvider = GetPublishedUrlProvider(umbracoContext, urlProvider); @@ -168,11 +174,9 @@ namespace Umbraco.Tests.Routing { const string currentUri = "http://example.us/test"; - var globalSettings = Mock.Get(Factory.GetInstance()); //this will modify the IGlobalSettings instance stored in the container - globalSettings.Setup(x => x.HideTopLevelNodeFromPath).Returns(false); - - var requestHandlerSettings = TestHelpers.SettingsForTests.GenerateMockRequestHandlerSettings(); + var globalSettings = new GlobalSettingsBuilder().WithHideTopLevelNodeFromPath(false).Build(); + var requestHandlerSettings = new RequestHandlerSettingsBuilder().Build(); var contentType = new PublishedContentType(Guid.NewGuid(), 666, "alias", PublishedItemType.Content, Enumerable.Empty(), Enumerable.Empty(), ContentVariation.Culture); var publishedContent = new SolidPublishedContent(contentType) { Id = 1234 }; @@ -193,12 +197,14 @@ namespace Umbraco.Tests.Routing snapshotService.Setup(x => x.CreatePublishedSnapshot(It.IsAny())) .Returns(snapshot); - var umbracoContext = GetUmbracoContext(currentUri, - globalSettings: globalSettings.Object, + globalSettings: ConfigModelConversions.ConvertGlobalSettings(globalSettings), snapshotService: snapshotService.Object); var umbracoContextAccessor = new TestUmbracoContextAccessor(umbracoContext); - var urlProvider = new DefaultUrlProvider(requestHandlerSettings, Logger, globalSettings.Object, + var urlProvider = new DefaultUrlProvider( + Microsoft.Extensions.Options.Options.Create(requestHandlerSettings), + Logger, + Microsoft.Extensions.Options.Options.Create(globalSettings), new SiteDomainHelper(), umbracoContextAccessor, UriUtility); var publishedUrlProvider = GetPublishedUrlProvider(umbracoContext, urlProvider); @@ -216,10 +222,9 @@ namespace Umbraco.Tests.Routing { const string currentUri = "http://example.fr/test"; - var globalSettings = Mock.Get(Factory.GetInstance()); //this will modify the IGlobalSettings instance stored in the container - globalSettings.Setup(x => x.HideTopLevelNodeFromPath).Returns(false); + var globalSettings = new GlobalSettingsBuilder().WithHideTopLevelNodeFromPath(false).Build(); - var requestHandlerSettings = TestHelpers.SettingsForTests.GenerateMockRequestHandlerSettings(); + var requestHandlerSettings = new RequestHandlerSettingsBuilder().Build(); var contentType = new PublishedContentType(Guid.NewGuid(), 666, "alias", PublishedItemType.Content, Enumerable.Empty(), Enumerable.Empty(), ContentVariation.Culture); var publishedContent = new SolidPublishedContent(contentType) { Id = 1234 }; @@ -249,12 +254,14 @@ namespace Umbraco.Tests.Routing snapshotService.Setup(x => x.CreatePublishedSnapshot(It.IsAny())) .Returns(snapshot); - var umbracoContext = GetUmbracoContext(currentUri, - globalSettings: globalSettings.Object, + globalSettings: ConfigModelConversions.ConvertGlobalSettings(globalSettings), snapshotService: snapshotService.Object); var umbracoContextAccessor = new TestUmbracoContextAccessor(umbracoContext); - var urlProvider = new DefaultUrlProvider(requestHandlerSettings, Logger, globalSettings.Object, + var urlProvider = new DefaultUrlProvider( + Microsoft.Extensions.Options.Options.Create(requestHandlerSettings), + Logger, + Microsoft.Extensions.Options.Options.Create(globalSettings), new SiteDomainHelper(), umbracoContextAccessor, UriUtility); var publishedUrlProvider = GetPublishedUrlProvider(umbracoContext, urlProvider); @@ -272,10 +279,9 @@ namespace Umbraco.Tests.Routing { const string currentUri = "http://example.us/test"; - var globalSettings = Mock.Get(Factory.GetInstance()); //this will modify the IGlobalSettings instance stored in the container - globalSettings.Setup(x => x.HideTopLevelNodeFromPath).Returns(false); + var globalSettings = new GlobalSettingsBuilder().WithHideTopLevelNodeFromPath(false).Build(); - var requestHandlerSettings = TestHelpers.SettingsForTests.GenerateMockRequestHandlerSettings(); + var requestHandlerSettings = new RequestHandlerSettingsBuilder().Build(); var contentType = new PublishedContentType(Guid.NewGuid(), 666, "alias", PublishedItemType.Content, Enumerable.Empty(), Enumerable.Empty(), ContentVariation.Culture); var publishedContent = new SolidPublishedContent(contentType) { Id = 1234 }; @@ -306,10 +312,13 @@ namespace Umbraco.Tests.Routing .Returns(snapshot); var umbracoContext = GetUmbracoContext(currentUri, - globalSettings: globalSettings.Object, + globalSettings: ConfigModelConversions.ConvertGlobalSettings(globalSettings), snapshotService: snapshotService.Object); var umbracoContextAccessor = new TestUmbracoContextAccessor(umbracoContext); - var urlProvider = new DefaultUrlProvider(requestHandlerSettings, Logger, globalSettings.Object, + var urlProvider = new DefaultUrlProvider( + Microsoft.Extensions.Options.Options.Create(requestHandlerSettings), + Logger, + Microsoft.Extensions.Options.Options.Create(globalSettings), new SiteDomainHelper(), umbracoContextAccessor, UriUtility); @@ -323,15 +332,16 @@ namespace Umbraco.Tests.Routing [Test] public void Get_Url_Relative_Or_Absolute() { - var globalSettings = Mock.Get(Factory.GetInstance()); //this will modify the IGlobalSettings instance stored in the container - globalSettings.Setup(x => x.HideTopLevelNodeFromPath).Returns(false); + var globalSettings = new GlobalSettingsBuilder().WithHideTopLevelNodeFromPath(false).Build(); - var requestHandlerSettings = TestHelpers.SettingsForTests.GenerateMockRequestHandlerSettings(); + var requestHandlerSettings = new RequestHandlerSettingsBuilder().Build(); - - var umbracoContext = GetUmbracoContext("http://example.com/test", 1111, globalSettings: globalSettings.Object); + var umbracoContext = GetUmbracoContext("http://example.com/test", 1111, globalSettings: ConfigModelConversions.ConvertGlobalSettings(globalSettings)); var umbracoContextAccessor = new TestUmbracoContextAccessor(umbracoContext); - var urlProvider = new DefaultUrlProvider(requestHandlerSettings, Logger, globalSettings.Object, + var urlProvider = new DefaultUrlProvider( + Microsoft.Extensions.Options.Options.Create(requestHandlerSettings), + Logger, + Microsoft.Extensions.Options.Options.Create(globalSettings), new SiteDomainHelper(), umbracoContextAccessor, UriUtility); var publishedUrlProvider = GetPublishedUrlProvider(umbracoContext, urlProvider); @@ -344,14 +354,15 @@ namespace Umbraco.Tests.Routing [Test] public void Get_Url_Unpublished() { - var globalSettings = Mock.Get(Factory.GetInstance()); //this will modify the IGlobalSettings instance stored in the container - globalSettings.Setup(x => x.HideTopLevelNodeFromPath).Returns(false); + var globalSettings = new GlobalSettingsBuilder().WithHideTopLevelNodeFromPath(false).Build(); - var requestHandlerSettings = TestHelpers.SettingsForTests.GenerateMockRequestHandlerSettings(); + var requestHandlerSettings = new RequestHandlerSettingsBuilder().Build(); - var urlProvider = new DefaultUrlProvider(requestHandlerSettings, Logger, globalSettings.Object, + var urlProvider = new DefaultUrlProvider(Microsoft.Extensions.Options.Options.Create(requestHandlerSettings), + Logger, + Microsoft.Extensions.Options.Options.Create(globalSettings), new SiteDomainHelper(), UmbracoContextAccessor, UriUtility); - var umbracoContext = GetUmbracoContext("http://example.com/test", 1111, globalSettings: globalSettings.Object); + var umbracoContext = GetUmbracoContext("http://example.com/test", 1111, globalSettings: ConfigModelConversions.ConvertGlobalSettings(globalSettings)); var publishedUrlProvider = GetPublishedUrlProvider(umbracoContext, urlProvider); //mock the Umbraco settings that we need diff --git a/src/Umbraco.Tests/Routing/UrlsProviderWithDomainsTests.cs b/src/Umbraco.Tests/Routing/UrlsProviderWithDomainsTests.cs index d8e373b428..79813e662c 100644 --- a/src/Umbraco.Tests/Routing/UrlsProviderWithDomainsTests.cs +++ b/src/Umbraco.Tests/Routing/UrlsProviderWithDomainsTests.cs @@ -9,6 +9,7 @@ using Umbraco.Core.Models; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Services; using Umbraco.Tests.Common; +using Umbraco.Tests.Common.Builders; using Umbraco.Tests.LegacyXmlPublishedCache; using Umbraco.Tests.TestHelpers; using Umbraco.Web; @@ -178,14 +179,15 @@ namespace Umbraco.Tests.Routing [TestCase(10011, "https://domain1.com", false, "/1001-1/")] public void Get_Url_SimpleDomain(int nodeId, string currentUrl, bool absolute, string expected) { - var settings = TestHelpers.SettingsForTests.GenerateMockRequestHandlerSettings(); + var requestHandlerSettings = new RequestHandlerSettingsBuilder().Build(); - var globalSettings = Mock.Get(Factory.GetInstance()); //this will modify the IGlobalSettings instance stored in the container - globalSettings.Setup(x => x.HideTopLevelNodeFromPath).Returns(false); // ignored w/domains + var globalSettings = new GlobalSettingsBuilder().WithHideTopLevelNodeFromPath(false).Build(); - var umbracoContext = GetUmbracoContext("/test", 1111, globalSettings:globalSettings.Object); + var umbracoContext = GetUmbracoContext("/test", 1111, globalSettings: ConfigModelConversions.ConvertGlobalSettings(globalSettings)); var umbracoContextAccessor = new TestUmbracoContextAccessor(umbracoContext); - var urlProvider = new DefaultUrlProvider(settings, Logger, globalSettings.Object, + var urlProvider = new DefaultUrlProvider(Microsoft.Extensions.Options.Options.Create(requestHandlerSettings), + Logger, + Microsoft.Extensions.Options.Options.Create(globalSettings), new SiteDomainHelper(), umbracoContextAccessor, UriUtility); var publishedUrlProvider = GetPublishedUrlProvider(umbracoContext, urlProvider); @@ -212,14 +214,14 @@ namespace Umbraco.Tests.Routing [TestCase(10011, "https://domain1.com", false, "http://domain1.com/foo/1001-1/")] public void Get_Url_SimpleWithSchemeAndPath(int nodeId, string currentUrl, bool absolute, string expected) { - var settings = TestHelpers.SettingsForTests.GenerateMockRequestHandlerSettings(); + var requestHandlerSettings = new RequestHandlerSettingsBuilder().Build(); + var globalSettings = new GlobalSettingsBuilder().WithHideTopLevelNodeFromPath(false).Build(); - var globalSettings = Mock.Get(Factory.GetInstance()); //this will modify the IGlobalSettings instance stored in the container - globalSettings.Setup(x => x.HideTopLevelNodeFromPath).Returns(false); // ignored w/domains - - var umbracoContext = GetUmbracoContext("/test", 1111, globalSettings:globalSettings.Object); + var umbracoContext = GetUmbracoContext("/test", 1111, globalSettings: ConfigModelConversions.ConvertGlobalSettings(globalSettings)); var umbracoContextAccessor = new TestUmbracoContextAccessor(umbracoContext); - var urlProvider = new DefaultUrlProvider(settings, Logger, globalSettings.Object, + var urlProvider = new DefaultUrlProvider(Microsoft.Extensions.Options.Options.Create(requestHandlerSettings), + Logger, + Microsoft.Extensions.Options.Options.Create(globalSettings), new SiteDomainHelper(), umbracoContextAccessor, UriUtility); var publishedUrlProvider = GetPublishedUrlProvider(umbracoContext, urlProvider); @@ -238,14 +240,15 @@ namespace Umbraco.Tests.Routing [TestCase(1002, "http://domain1.com", false, "/1002/")] public void Get_Url_DeepDomain(int nodeId, string currentUrl, bool absolute, string expected) { - var settings = TestHelpers.SettingsForTests.GenerateMockRequestHandlerSettings(); + var requestHandlerSettings = new RequestHandlerSettingsBuilder().Build(); - var globalSettings = Mock.Get(Factory.GetInstance()); //this will modify the IGlobalSettings instance stored in the container - globalSettings.Setup(x => x.HideTopLevelNodeFromPath).Returns(false); // ignored w/domains + var globalSettings = new GlobalSettingsBuilder().WithHideTopLevelNodeFromPath(false).Build(); - var umbracoContext = GetUmbracoContext("/test", 1111, globalSettings:globalSettings.Object); + var umbracoContext = GetUmbracoContext("/test", 1111, globalSettings: ConfigModelConversions.ConvertGlobalSettings(globalSettings)); var umbracoContextAccessor = new TestUmbracoContextAccessor(umbracoContext); - var urlProvider = new DefaultUrlProvider(settings, Logger, globalSettings.Object, + var urlProvider = new DefaultUrlProvider(Microsoft.Extensions.Options.Options.Create(requestHandlerSettings), + Logger, + Microsoft.Extensions.Options.Options.Create(globalSettings), new SiteDomainHelper(), umbracoContextAccessor, UriUtility); var publishedUrlProvider = GetPublishedUrlProvider(umbracoContext, urlProvider); @@ -270,14 +273,16 @@ namespace Umbraco.Tests.Routing [TestCase(100321, "http://domain3.com", false, "/fr/1003-2-1/")] public void Get_Url_NestedDomains(int nodeId, string currentUrl, bool absolute, string expected) { - var settings = TestHelpers.SettingsForTests.GenerateMockRequestHandlerSettings(); + var requestHandlerSettings = new RequestHandlerSettingsBuilder().Build(); - var globalSettings = Mock.Get(Factory.GetInstance()); //this will modify the IGlobalSettings instance stored in the container - globalSettings.Setup(x => x.HideTopLevelNodeFromPath).Returns(false); // ignored w/domains + var globalSettings = new GlobalSettingsBuilder().WithHideTopLevelNodeFromPath(false).Build(); - var umbracoContext = GetUmbracoContext("/test", 1111, globalSettings:globalSettings.Object); + var umbracoContext = GetUmbracoContext("/test", 1111, globalSettings: ConfigModelConversions.ConvertGlobalSettings(globalSettings)); var umbracoContextAccessor = new TestUmbracoContextAccessor(umbracoContext); - var urlProvider = new DefaultUrlProvider(settings, Logger, globalSettings.Object, + var urlProvider = new DefaultUrlProvider( + Microsoft.Extensions.Options.Options.Create(requestHandlerSettings), + Logger, + Microsoft.Extensions.Options.Options.Create(globalSettings), new SiteDomainHelper(), umbracoContextAccessor, UriUtility); var publishedUrlProvider = GetPublishedUrlProvider(umbracoContext, urlProvider); @@ -292,14 +297,16 @@ namespace Umbraco.Tests.Routing [Test] public void Get_Url_DomainsAndCache() { - var settings = TestHelpers.SettingsForTests.GenerateMockRequestHandlerSettings(); + var requestHandlerSettings = new RequestHandlerSettingsBuilder().Build(); - var globalSettings = Mock.Get(Factory.GetInstance()); //this will modify the IGlobalSettings instance stored in the container - globalSettings.Setup(x => x.HideTopLevelNodeFromPath).Returns(false); // ignored w/domains + var globalSettings = new GlobalSettingsBuilder().WithHideTopLevelNodeFromPath(false).Build(); - var umbracoContext = GetUmbracoContext("/test", 1111, globalSettings:globalSettings.Object); + var umbracoContext = GetUmbracoContext("/test", 1111, globalSettings: ConfigModelConversions.ConvertGlobalSettings(globalSettings)); var umbracoContextAccessor = new TestUmbracoContextAccessor(umbracoContext); - var urlProvider = new DefaultUrlProvider(settings, Logger, globalSettings.Object, + var urlProvider = new DefaultUrlProvider( + Microsoft.Extensions.Options.Options.Create(requestHandlerSettings), + Logger, + Microsoft.Extensions.Options.Options.Create(globalSettings), new SiteDomainHelper(), umbracoContextAccessor, UriUtility); var publishedUrlProvider = GetPublishedUrlProvider(umbracoContext, urlProvider); @@ -356,14 +363,16 @@ namespace Umbraco.Tests.Routing [Test] public void Get_Url_Relative_Or_Absolute() { - var settings = TestHelpers.SettingsForTests.GenerateMockRequestHandlerSettings(); + var requestHandlerSettings = new RequestHandlerSettingsBuilder().Build(); - var globalSettings = Mock.Get(Factory.GetInstance()); //this will modify the IGlobalSettings instance stored in the container - globalSettings.Setup(x => x.HideTopLevelNodeFromPath).Returns(false); // ignored w/domains + var globalSettings = new GlobalSettingsBuilder().WithHideTopLevelNodeFromPath(false).Build(); - var umbracoContext = GetUmbracoContext("http://domain1.com/test", 1111, globalSettings:globalSettings.Object); + var umbracoContext = GetUmbracoContext("http://domain1.com/test", 1111, globalSettings: ConfigModelConversions.ConvertGlobalSettings(globalSettings)); var umbracoContextAccessor = new TestUmbracoContextAccessor(umbracoContext); - var urlProvider = new DefaultUrlProvider(settings, Logger, globalSettings.Object, + var urlProvider = new DefaultUrlProvider( + Microsoft.Extensions.Options.Options.Create(requestHandlerSettings), + Logger, + Microsoft.Extensions.Options.Options.Create(globalSettings), new SiteDomainHelper(), umbracoContextAccessor, UriUtility); var publishedUrlProvider = GetPublishedUrlProvider(umbracoContext, urlProvider); @@ -381,14 +390,16 @@ namespace Umbraco.Tests.Routing [Test] public void Get_Url_Alternate() { - var settings = TestHelpers.SettingsForTests.GenerateMockRequestHandlerSettings(); + var requestHandlerSettings = new RequestHandlerSettingsBuilder().Build(); - var globalSettings = Mock.Get(Factory.GetInstance()); //this will modify the IGlobalSettings instance stored in the container - globalSettings.Setup(x => x.HideTopLevelNodeFromPath).Returns(false); // ignored w/domains + var globalSettings = new GlobalSettingsBuilder().WithHideTopLevelNodeFromPath(false).Build(); - var umbracoContext = GetUmbracoContext("http://domain1.com/en/test", 1111, globalSettings:globalSettings.Object); + var umbracoContext = GetUmbracoContext("http://domain1.com/en/test", 1111, globalSettings: ConfigModelConversions.ConvertGlobalSettings(globalSettings)); var umbracoContextAccessor = new TestUmbracoContextAccessor(umbracoContext); - var urlProvider = new DefaultUrlProvider(settings, Logger, globalSettings.Object, + var urlProvider = new DefaultUrlProvider( + Microsoft.Extensions.Options.Options.Create(requestHandlerSettings), + Logger, + Microsoft.Extensions.Options.Options.Create(globalSettings), new SiteDomainHelper(), umbracoContextAccessor, UriUtility); var publishedUrlProvider = GetPublishedUrlProvider(umbracoContext, urlProvider); @@ -408,9 +419,10 @@ namespace Umbraco.Tests.Routing private IPublishedUrlProvider GetPublishedUrlProvider(IUmbracoContext umbracoContext, DefaultUrlProvider urlProvider) { + var webRoutingSettings = new WebRoutingSettingsBuilder().Build(); return new UrlProvider( new TestUmbracoContextAccessor(umbracoContext), - TestHelper.WebRoutingSettings, + Microsoft.Extensions.Options.Options.Create(webRoutingSettings), new UrlProviderCollection(new []{urlProvider}), new MediaUrlProviderCollection(Enumerable.Empty()), Mock.Of() diff --git a/src/Umbraco.Tests/Routing/UrlsWithNestedDomains.cs b/src/Umbraco.Tests/Routing/UrlsWithNestedDomains.cs index 13ee5afa3e..085cf7f274 100644 --- a/src/Umbraco.Tests/Routing/UrlsWithNestedDomains.cs +++ b/src/Umbraco.Tests/Routing/UrlsWithNestedDomains.cs @@ -12,6 +12,7 @@ using Umbraco.Core.Services; using Umbraco.Tests.LegacyXmlPublishedCache; using Umbraco.Web; using Umbraco.Tests.Common; +using Umbraco.Tests.Common.Builders; namespace Umbraco.Tests.Routing { @@ -33,19 +34,20 @@ namespace Umbraco.Tests.Routing [Test] public void DoNotPolluteCache() { - var globalSettings = Mock.Get(Factory.GetInstance()); //this will modify the IGlobalSettings instance stored in the container - globalSettings.Setup(x => x.HideTopLevelNodeFromPath).Returns(false); - - var settings = TestHelpers.SettingsForTests.GenerateMockRequestHandlerSettings(); + var globalSettings = new GlobalSettingsBuilder().WithHideTopLevelNodeFromPath(false).Build(); + var requestHandlerSettings = new RequestHandlerSettingsBuilder().Build(); SetDomains1(); const string url = "http://domain1.com/1001-1/1001-1-1"; // get the nice url for 100111 - var umbracoContext = GetUmbracoContext(url, 9999, globalSettings:globalSettings.Object); + var umbracoContext = GetUmbracoContext(url, 9999, globalSettings: ConfigModelConversions.ConvertGlobalSettings(globalSettings)); var umbracoContextAccessor = new TestUmbracoContextAccessor(umbracoContext); - var urlProvider = new DefaultUrlProvider(settings, Logger, globalSettings.Object, + var urlProvider = new DefaultUrlProvider( + Microsoft.Extensions.Options.Options.Create(requestHandlerSettings), + Logger, + Microsoft.Extensions.Options.Options.Create(globalSettings), new SiteDomainHelper(), umbracoContextAccessor, UriUtility); var publishedUrlProvider = GetPublishedUrlProvider(umbracoContext, urlProvider); @@ -97,9 +99,10 @@ namespace Umbraco.Tests.Routing private IPublishedUrlProvider GetPublishedUrlProvider(IUmbracoContext umbracoContext, DefaultUrlProvider urlProvider) { + var webRoutingSettings = new WebRoutingSettingsBuilder().Build(); return new UrlProvider( new TestUmbracoContextAccessor(umbracoContext), - TestHelper.WebRoutingSettings, + Microsoft.Extensions.Options.Options.Create(webRoutingSettings), new UrlProviderCollection(new []{urlProvider}), new MediaUrlProviderCollection(Enumerable.Empty()), Mock.Of() diff --git a/src/Umbraco.Tests/Runtimes/StandaloneTests.cs b/src/Umbraco.Tests/Runtimes/StandaloneTests.cs index 5984164497..394ed902f8 100644 --- a/src/Umbraco.Tests/Runtimes/StandaloneTests.cs +++ b/src/Umbraco.Tests/Runtimes/StandaloneTests.cs @@ -161,7 +161,6 @@ namespace Umbraco.Tests.Runtimes var scopeProvider = factory.GetInstance(); using (var scope = scopeProvider.CreateScope()) { - var globalSettings = new GlobalSettingsBuilder().Build(); var creator = new DatabaseSchemaCreator(scope.Database, logger, umbracoVersion, globalSettings); creator.InitializeDatabaseSchema(); scope.Complete(); @@ -277,7 +276,9 @@ namespace Umbraco.Tests.Runtimes composition.RegisterEssentials(logger, profiler, profilingLogger, mainDom, appCaches, databaseFactory, typeLoader, runtimeState, typeFinder, ioHelper, umbracoVersion, TestHelper.DbProviderFactoryCreator, hostingEnvironment, backOfficeInfo); // create the core runtime and have it compose itself - var coreRuntime = new CoreRuntime(configs, umbracoVersion, ioHelper, logger, profiler, new AspNetUmbracoBootPermissionChecker(), hostingEnvironment, backOfficeInfo, TestHelper.DbProviderFactoryCreator, TestHelper.MainDom, typeFinder, NoAppCache.Instance); + var globalSettings = new GlobalSettingsBuilder().Build(); + var connectionStrings = new ConnectionStringsBuilder().Build(); + var coreRuntime = new CoreRuntime(globalSettings, connectionStrings, umbracoVersion, ioHelper, logger, profiler, new AspNetUmbracoBootPermissionChecker(), hostingEnvironment, backOfficeInfo, TestHelper.DbProviderFactoryCreator, TestHelper.MainDom, typeFinder, NoAppCache.Instance); // get the components // all of them? diff --git a/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs b/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs index c646bdcf79..e47e9692bd 100644 --- a/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs @@ -16,6 +16,7 @@ using Umbraco.Core.Persistence.Mappers; using Umbraco.Core.Services; using Umbraco.Tests.Components; using Current = Umbraco.Web.Composing.Current; +using Umbraco.Tests.Common.Builders; namespace Umbraco.Tests.Scoping { @@ -38,7 +39,8 @@ namespace Umbraco.Tests.Scoping _testObjects = new TestObjects(register); - composition.RegisterUnique(factory => new FileSystems(factory, factory.TryGetInstance(), TestHelper.IOHelper, SettingsForTests.GenerateMockGlobalSettings(), TestHelper.GetHostingEnvironment())); + var globalSettings = new GlobalSettingsBuilder().Build(); + composition.RegisterUnique(factory => new FileSystems(factory, factory.TryGetInstance(), TestHelper.IOHelper, Microsoft.Extensions.Options.Options.Create(globalSettings), TestHelper.GetHostingEnvironment())); composition.WithCollectionBuilder(); composition.Configs.Add(() => SettingsForTests.DefaultGlobalSettings); diff --git a/src/Umbraco.Tests/Services/ContentServicePerformanceTest.cs b/src/Umbraco.Tests/Services/ContentServicePerformanceTest.cs index d5afde6477..02f6ad330f 100644 --- a/src/Umbraco.Tests/Services/ContentServicePerformanceTest.cs +++ b/src/Umbraco.Tests/Services/ContentServicePerformanceTest.cs @@ -16,6 +16,7 @@ using Umbraco.Core.Persistence.Repositories; using Umbraco.Core.Persistence.Repositories.Implement; using Umbraco.Core.PropertyEditors; using Umbraco.Core.Scoping; +using Umbraco.Tests.Common.Builders; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.TestHelpers.Entities; using Umbraco.Tests.TestHelpers.Stubs; @@ -43,10 +44,11 @@ namespace Umbraco.Tests.Services private DocumentRepository CreateDocumentRepository(IScopeProvider provider) { var accessor = (IScopeAccessor)provider; + var globalSettings = new GlobalSettingsBuilder().Build(); var tRepository = new TemplateRepository((IScopeAccessor) provider, AppCaches.Disabled, Logger, TestObjects.GetFileSystemsMock(), IOHelper, ShortStringHelper); var tagRepo = new TagRepository(accessor, AppCaches.Disabled, Logger); var commonRepository = new ContentTypeCommonRepository(accessor, tRepository, AppCaches, ShortStringHelper); - var languageRepository = new LanguageRepository(accessor, AppCaches.Disabled, Logger, TestObjects.GetGlobalSettings()); + var languageRepository = new LanguageRepository(accessor, AppCaches.Disabled, Logger, Microsoft.Extensions.Options.Options.Create(globalSettings)); var ctRepository = new ContentTypeRepository(accessor, AppCaches.Disabled, Logger, commonRepository, languageRepository, ShortStringHelper); var relationTypeRepository = new RelationTypeRepository(accessor, AppCaches.Disabled, Logger); var entityRepository = new EntityRepository(accessor); diff --git a/src/Umbraco.Tests/Strings/CmsHelperCasingTests.cs b/src/Umbraco.Tests/Strings/CmsHelperCasingTests.cs index 84ffa3b696..71d789eddb 100644 --- a/src/Umbraco.Tests/Strings/CmsHelperCasingTests.cs +++ b/src/Umbraco.Tests/Strings/CmsHelperCasingTests.cs @@ -1,6 +1,7 @@ using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Strings; +using Umbraco.Tests.Common.Builders; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.Testing; @@ -30,7 +31,8 @@ namespace Umbraco.Tests.Strings [TestCase("WhoIsNumber6InTheVillage", "Who Is Number6 In The Village")] // issue is fixed public void CompatibleDefaultReplacement(string input, string expected) { - var helper = new DefaultShortStringHelper(SettingsForTests.GenerateMockRequestHandlerSettings()); + var requestHandlerSettings = new RequestHandlerSettingsBuilder().Build(); + var helper = new DefaultShortStringHelper(Microsoft.Extensions.Options.Options.Create(requestHandlerSettings)); var output = input.Length < 2 ? input : helper.SplitPascalCasing(input, ' ').ToFirstUpperInvariant(); Assert.AreEqual(expected, output); } diff --git a/src/Umbraco.Tests/Templates/HtmlImageSourceParserTests.cs b/src/Umbraco.Tests/Templates/HtmlImageSourceParserTests.cs index 14e45d976c..4dc7ad0278 100644 --- a/src/Umbraco.Tests/Templates/HtmlImageSourceParserTests.cs +++ b/src/Umbraco.Tests/Templates/HtmlImageSourceParserTests.cs @@ -14,6 +14,7 @@ using Umbraco.Core; using System.Diagnostics; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.Common; +using Umbraco.Tests.Common.Builders; namespace Umbraco.Tests.Templates { @@ -76,9 +77,9 @@ namespace Umbraco.Tests.Templates var umbracoContextFactory = TestUmbracoContextFactory.Create( umbracoContextAccessor: umbracoContextAccessor); - + var webRoutingSettings = new WebRoutingSettingsBuilder().Build(); var publishedUrlProvider = new UrlProvider(umbracoContextAccessor, - TestHelper.WebRoutingSettings, + Microsoft.Extensions.Options.Options.Create(webRoutingSettings), new UrlProviderCollection(Enumerable.Empty()), new MediaUrlProviderCollection(new []{mediaUrlProvider.Object}), Mock.Of() diff --git a/src/Umbraco.Tests/Templates/HtmlLocalLinkParserTests.cs b/src/Umbraco.Tests/Templates/HtmlLocalLinkParserTests.cs index 20677468c6..375dc91d19 100644 --- a/src/Umbraco.Tests/Templates/HtmlLocalLinkParserTests.cs +++ b/src/Umbraco.Tests/Templates/HtmlLocalLinkParserTests.cs @@ -7,6 +7,7 @@ using Umbraco.Core; using Umbraco.Core.Models; using Umbraco.Core.Models.PublishedContent; using Umbraco.Tests.Common; +using Umbraco.Tests.Common.Builders; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.Testing.Objects; using Umbraco.Web; @@ -72,8 +73,9 @@ namespace Umbraco.Tests.Templates var umbracoContextFactory = TestUmbracoContextFactory.Create( umbracoContextAccessor: umbracoContextAccessor); + var webRoutingSettings = new WebRoutingSettingsBuilder().Build(); var publishedUrlProvider = new UrlProvider(umbracoContextAccessor, - TestHelper.WebRoutingSettings, + Microsoft.Extensions.Options.Options.Create(webRoutingSettings), new UrlProviderCollection(new []{contentUrlProvider.Object}), new MediaUrlProviderCollection(new []{mediaUrlProvider.Object}), Mock.Of() diff --git a/src/Umbraco.Tests/TestHelpers/BaseWebTest.cs b/src/Umbraco.Tests/TestHelpers/BaseWebTest.cs index 8926c02182..e51a10da50 100644 --- a/src/Umbraco.Tests/TestHelpers/BaseWebTest.cs +++ b/src/Umbraco.Tests/TestHelpers/BaseWebTest.cs @@ -5,6 +5,7 @@ using Moq; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Composing; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Logging; using Umbraco.Core.Models; @@ -13,6 +14,7 @@ using Umbraco.Core.PropertyEditors; using Umbraco.Core.Services; using Umbraco.Core.Strings; using Umbraco.Tests.Common; +using Umbraco.Tests.Common.Builders; using Umbraco.Tests.PublishedContent; using Umbraco.Tests.TestHelpers.Stubs; using Umbraco.Web; @@ -91,13 +93,14 @@ namespace Umbraco.Tests.TestHelpers internal PublishedRouter CreatePublishedRouter(IFactory container = null, ContentFinderCollection contentFinders = null) { - return CreatePublishedRouter(SettingsForTests.GenerateMockWebRoutingSettings(), container ?? Factory, contentFinders); + var webRoutingSettings = new WebRoutingSettingsBuilder().Build(); + return CreatePublishedRouter(webRoutingSettings, container ?? Factory, contentFinders); } - internal static PublishedRouter CreatePublishedRouter(IWebRoutingSettings webRoutingSettings, IFactory container = null, ContentFinderCollection contentFinders = null) + internal static PublishedRouter CreatePublishedRouter(WebRoutingSettings webRoutingSettings, IFactory container = null, ContentFinderCollection contentFinders = null) { return new PublishedRouter( - webRoutingSettings, + Microsoft.Extensions.Options.Options.Create(webRoutingSettings), contentFinders ?? new ContentFinderCollection(Enumerable.Empty()), new TestLastChanceFinder(), new TestVariationContextAccessor(), diff --git a/src/Umbraco.Tests/TestHelpers/ConfigModelConversions.cs b/src/Umbraco.Tests/TestHelpers/ConfigModelConversions.cs new file mode 100644 index 0000000000..800374c690 --- /dev/null +++ b/src/Umbraco.Tests/TestHelpers/ConfigModelConversions.cs @@ -0,0 +1,109 @@ +using System.Net.Mail; +using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; + +namespace Umbraco.Tests.TestHelpers +{ + /// + /// TEMPORARY: this class has been added just to ensure tests on Umbraco.Web functionality, that still use the interface + /// based configuration, by converting between e.g (used by + /// legacy configuration and (used by Netcore/IOptions configuration). + /// + public static class ConfigModelConversions + { + public static IGlobalSettings ConvertGlobalSettings(GlobalSettings globalSettings) + { + return new TestGlobalSettings + { + DatabaseFactoryServerVersion = globalSettings.DatabaseFactoryServerVersion, + DefaultUILanguage = globalSettings.DefaultUILanguage, + DisableElectionForSingleServer = globalSettings.DisableElectionForSingleServer, + HideTopLevelNodeFromPath = globalSettings.HideTopLevelNodeFromPath, + InstallEmptyDatabase = globalSettings.InstallEmptyDatabase, + InstallMissingDatabase = globalSettings.InstallMissingDatabase, + MainDomLock = globalSettings.MainDomLock, + NoNodesViewPath = globalSettings.NoNodesViewPath, + RegisterType = globalSettings.RegisterType, + ReservedPaths = globalSettings.ReservedPaths, + ReservedUrls = globalSettings.ReservedUrls, + SmtpSettings = new TestSmtpSettings + { + DeliveryMethod = globalSettings.Smtp.DeliveryMethod, + From = globalSettings.Smtp.From, + Host = globalSettings.Smtp.Host, + Password = globalSettings.Smtp.Password, + PickupDirectoryLocation = globalSettings.Smtp.PickupDirectoryLocation, + Port = globalSettings.Smtp.Port, + Username = globalSettings.Smtp.Username, + }, + TimeOutInMinutes = globalSettings.TimeOutInMinutes, + UmbracoCssPath = globalSettings.UmbracoCssPath, + UmbracoMediaPath = globalSettings.UmbracoMediaPath, + UmbracoPath = globalSettings.UmbracoPath, + UmbracoScriptsPath = globalSettings.UmbracoScriptsPath, + UseHttps = globalSettings.UseHttps, + VersionCheckPeriod = globalSettings.VersionCheckPeriod, + }; + } + + private class TestGlobalSettings : IGlobalSettings + { + public string ReservedUrls { get; set; } + + public string ReservedPaths { get; set; } + + public int TimeOutInMinutes { get; set; } + + public string DefaultUILanguage { get; set; } + + public bool HideTopLevelNodeFromPath { get; set; } + + public bool UseHttps { get; set; } + + public int VersionCheckPeriod { get; set; } + + public string UmbracoPath { get; set; } + + public string UmbracoCssPath { get; set; } + + public string UmbracoScriptsPath { get; set; } + + public string UmbracoMediaPath { get; set; } + + public bool IsSmtpServerConfigured { get; set; } + + public ISmtpSettings SmtpSettings { get; set; } + + public bool InstallMissingDatabase { get; set; } + + public bool InstallEmptyDatabase { get; set; } + + public bool DisableElectionForSingleServer { get; set; } + + public string RegisterType { get; set; } + + public string DatabaseFactoryServerVersion { get; set; } + + public string MainDomLock { get; set; } + + public string NoNodesViewPath { get; set; } + } + + private class TestSmtpSettings : ISmtpSettings + { + public string From { get; set; } + + public string Host { get; set; } + + public int Port { get; set; } + + public string PickupDirectoryLocation { get; set; } + + public SmtpDeliveryMethod DeliveryMethod { get; set; } + + public string Username { get; set; } + + public string Password { get; set; } + } + } +} diff --git a/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs b/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs index 6f5739eb02..0232cafb1c 100644 --- a/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs +++ b/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs @@ -27,6 +27,7 @@ using Umbraco.Web.Security; using Umbraco.Web.Security.Providers; using Umbraco.Web.WebApi; using Current = Umbraco.Web.Composing.Current; +using Umbraco.Tests.Common.Builders; namespace Umbraco.Tests.Testing.TestingTests { @@ -84,9 +85,10 @@ namespace Umbraco.Tests.Testing.TestingTests .Returns(UrlInfo.Url("/hello/world/1234")); var urlProvider = urlProviderMock.Object; + var webRoutingSettings = new WebRoutingSettingsBuilder().Build(); var theUrlProvider = new UrlProvider( new TestUmbracoContextAccessor(umbracoContext), - TestHelper.WebRoutingSettings, + Microsoft.Extensions.Options.Options.Create(webRoutingSettings), new UrlProviderCollection(new [] { urlProvider }), new MediaUrlProviderCollection( Enumerable.Empty()) , umbracoContext.VariationContextAccessor); diff --git a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs index 5d8e047161..d339143c61 100644 --- a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs +++ b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs @@ -13,13 +13,18 @@ using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Composing; +using Umbraco.Core.Composing.CompositionExtensions; using Umbraco.Core.Configuration; +using Umbraco.Core.Dictionary; using Umbraco.Core.Events; +using Umbraco.Core.Hosting; using Umbraco.Core.IO; using Umbraco.Core.IO.MediaPathSchemes; using Umbraco.Core.Logging; using Umbraco.Core.Logging.Serilog; using Umbraco.Core.Manifest; +using Umbraco.Core.Mapping; +using Umbraco.Core.Media; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.Mappers; @@ -27,41 +32,35 @@ using Umbraco.Core.Persistence.Repositories.Implement; using Umbraco.Core.Persistence.SqlSyntax; using Umbraco.Core.PropertyEditors; using Umbraco.Core.Scoping; +using Umbraco.Core.Security; +using Umbraco.Core.Serialization; +using Umbraco.Core.Services; using Umbraco.Core.Services.Implement; using Umbraco.Core.Strings; +using Umbraco.Net; +using Umbraco.Tests.Common; +using Umbraco.Tests.Common.Builders; using Umbraco.Tests.Components; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.TestHelpers.Stubs; using Umbraco.Web; -using Umbraco.Web.Services; using Umbraco.Web.Actions; +using Umbraco.Web.AspNet; using Umbraco.Web.ContentApps; +using Umbraco.Web.Hosting; +using Umbraco.Web.Install; +using Umbraco.Web.PropertyEditors; using Umbraco.Web.PublishedCache; using Umbraco.Web.Routing; -using Umbraco.Core.Composing.CompositionExtensions; -using Umbraco.Core.Hosting; -using Umbraco.Core.Mapping; -using Umbraco.Core.Serialization; -using Umbraco.Web.Composing.CompositionExtensions; -using Umbraco.Web.Hosting; using Umbraco.Web.Sections; -using FileSystems = Umbraco.Core.IO.FileSystems; -using Umbraco.Web.Templates; -using Umbraco.Web.PropertyEditors; -using Umbraco.Core.Dictionary; -using Umbraco.Net; -using Umbraco.Core.Security; -using Umbraco.Core.Services; -using Umbraco.Web.AspNet; -using Umbraco.Web.Install; using Umbraco.Web.Security; using Umbraco.Web.Security.Providers; +using Umbraco.Web.Services; +using Umbraco.Web.Templates; using Umbraco.Web.Trees; +using ConfigModelConversions = Umbraco.Tests.TestHelpers.ConfigModelConversions; using Current = Umbraco.Web.Composing.Current; -using Umbraco.Tests.Common; -using Umbraco.Core.Media; -using Umbraco.Tests.Common.Builders; -using Umbraco.Web.Configuration; +using FileSystems = Umbraco.Core.IO.FileSystems; namespace Umbraco.Tests.Testing { @@ -174,12 +173,12 @@ namespace Umbraco.Tests.Testing TypeFinder = new TypeFinder(logger, new DefaultUmbracoAssemblyProvider(GetType().Assembly), new VaryingRuntimeHash()); var appCaches = GetAppCaches(); - var globalSettings = TestHelpers.SettingsForTests.DefaultGlobalSettings; + var globalSettings = new GlobalSettingsBuilder().Build(); var settings = TestHelpers.SettingsForTests.GenerateMockWebRoutingSettings(); - IBackOfficeInfo backOfficeInfo = new AspNetBackOfficeInfo(globalSettings, IOHelper, logger, settings); + IBackOfficeInfo backOfficeInfo = new AspNetBackOfficeInfo(ConfigModelConversions.ConvertGlobalSettings(globalSettings), IOHelper, logger, settings); IIpResolver ipResolver = new AspNetIpResolver(); - UmbracoVersion = new UmbracoVersion(ConfigModelConversions.ConvertGlobalSettings(globalSettings)); + UmbracoVersion = new UmbracoVersion(globalSettings); LocalizedTextService = new LocalizedTextService(new Dictionary>(), logger); diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj index 9a552d04d8..b21814cab7 100644 --- a/src/Umbraco.Tests/Umbraco.Tests.csproj +++ b/src/Umbraco.Tests/Umbraco.Tests.csproj @@ -145,6 +145,7 @@ + @@ -558,8 +559,7 @@ - - + diff --git a/src/Umbraco.Tests/UmbracoExamine/ExamineBaseTest.cs b/src/Umbraco.Tests/UmbracoExamine/ExamineBaseTest.cs index 0d55fd99d7..eac16e457f 100644 --- a/src/Umbraco.Tests/UmbracoExamine/ExamineBaseTest.cs +++ b/src/Umbraco.Tests/UmbracoExamine/ExamineBaseTest.cs @@ -6,6 +6,7 @@ using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Logging; using Umbraco.Core.Logging.Serilog; using Umbraco.Core.Strings; +using Umbraco.Tests.Common.Builders; using Umbraco.Tests.Components; using Umbraco.Tests.TestHelpers; @@ -33,8 +34,8 @@ namespace Umbraco.Tests.UmbracoExamine protected override void Compose() { base.Compose(); - - Composition.RegisterUnique(_ => new DefaultShortStringHelper(SettingsForTests.GenerateMockRequestHandlerSettings())); + var requestHandlerSettings = new RequestHandlerSettingsBuilder().Build(); + Composition.RegisterUnique(_ => new DefaultShortStringHelper(Microsoft.Extensions.Options.Options.Create(requestHandlerSettings))); } } } diff --git a/src/Umbraco.Tests/Web/Mvc/SurfaceControllerTests.cs b/src/Umbraco.Tests/Web/Mvc/SurfaceControllerTests.cs index 4c222b9116..8e0c534550 100644 --- a/src/Umbraco.Tests/Web/Mvc/SurfaceControllerTests.cs +++ b/src/Umbraco.Tests/Web/Mvc/SurfaceControllerTests.cs @@ -12,6 +12,7 @@ using Umbraco.Core.Logging; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Services; using Umbraco.Tests.Common; +using Umbraco.Tests.Common.Builders; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.Testing; using Umbraco.Web; @@ -155,8 +156,8 @@ namespace Umbraco.Tests.Web.Mvc var content = Mock.Of(publishedContent => publishedContent.Id == 12345); - - var publishedRouter = BaseWebTest.CreatePublishedRouter(TestHelpers.SettingsForTests.GenerateMockWebRoutingSettings()); + var webRoutingSettings = new WebRoutingSettingsBuilder().Build(); + var publishedRouter = BaseWebTest.CreatePublishedRouter(webRoutingSettings); var frequest = publishedRouter.CreateRequest(umbracoContext, new Uri("http://localhost/test")); frequest.PublishedContent = content; diff --git a/src/Umbraco.Tests/Web/Mvc/UmbracoViewPageTests.cs b/src/Umbraco.Tests/Web/Mvc/UmbracoViewPageTests.cs index 6f1a073eca..5e89f29496 100644 --- a/src/Umbraco.Tests/Web/Mvc/UmbracoViewPageTests.cs +++ b/src/Umbraco.Tests/Web/Mvc/UmbracoViewPageTests.cs @@ -22,6 +22,7 @@ using Umbraco.Web.Models; using Umbraco.Web.Mvc; using Umbraco.Web.Routing; using Umbraco.Web.Security; +using Umbraco.Tests.Common.Builders; namespace Umbraco.Tests.Web.Mvc { @@ -387,7 +388,8 @@ namespace Umbraco.Tests.Web.Mvc { var umbracoContext = GetUmbracoContext("/dang", 0); - var publishedRouter = BaseWebTest.CreatePublishedRouter(TestHelpers.SettingsForTests.GenerateMockWebRoutingSettings()); + var webRoutingSettings = new WebRoutingSettingsBuilder().Build(); + var publishedRouter = BaseWebTest.CreatePublishedRouter(webRoutingSettings); var frequest = publishedRouter.CreateRequest(umbracoContext, new Uri("http://localhost/dang")); frequest.Culture = CultureInfo.InvariantCulture; diff --git a/src/Umbraco.Web/Configuration/ConfigModelConversions.cs b/src/Umbraco.Web/Configuration/ConfigModelConversions.cs index c6ded26ce2..b34ffb4def 100644 --- a/src/Umbraco.Web/Configuration/ConfigModelConversions.cs +++ b/src/Umbraco.Web/Configuration/ConfigModelConversions.cs @@ -9,7 +9,7 @@ namespace Umbraco.Web.Configuration { /// /// TEMPORARY: this class has been added just to ensure Umbraco.Web functionality continues to compile, by - /// converting between (used by + /// converting between e.g. (used by /// legacy configuration and (used by Netcore/IOptions configuration). /// public static class ConfigModelConversions From 2ed3568295d54b6bb3e8404d356180348a3ec8b8 Mon Sep 17 00:00:00 2001 From: Andy Butland Date: Tue, 25 Aug 2020 10:11:19 +0200 Subject: [PATCH 272/826] Fix after merge. --- .../Services/Implement/NotificationService.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Infrastructure/Services/Implement/NotificationService.cs b/src/Umbraco.Infrastructure/Services/Implement/NotificationService.cs index 467338455b..411babe247 100644 --- a/src/Umbraco.Infrastructure/Services/Implement/NotificationService.cs +++ b/src/Umbraco.Infrastructure/Services/Implement/NotificationService.cs @@ -411,9 +411,9 @@ namespace Umbraco.Core.Services.Implement string.Concat(siteUri.Authority, _ioHelper.ResolveUrl(_globalSettings.UmbracoPath)), summary.ToString()); - var fromMail = _contentSettings.Notifications.NotificationEmailAddress ?? _globalSettings.SmtpSettings.From; + var fromMail = _contentSettings.Notifications.NotificationEmailAddress ?? _globalSettings.Smtp.From; // create the mail message - var mail = new MailMessage(fromMail, mailingUser.Email); + var mail = new MailMessage(fromMail, fromMail); // populate the message From ae6fdede767734f9a9cf79ccf8a822f9e40fe504 Mon Sep 17 00:00:00 2001 From: Andy Butland Date: Tue, 25 Aug 2020 10:23:50 +0200 Subject: [PATCH 273/826] Restored Umbraco.Tests to compiling state. --- src/Umbraco.Core/Composing/Composition.cs | 5 +++++ src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs | 2 +- src/Umbraco.Tests/TestHelpers/TestHelper.cs | 3 ++- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Core/Composing/Composition.cs b/src/Umbraco.Core/Composing/Composition.cs index 72d45605a6..6989d4d0a2 100644 --- a/src/Umbraco.Core/Composing/Composition.cs +++ b/src/Umbraco.Core/Composing/Composition.cs @@ -60,6 +60,11 @@ namespace Umbraco.Core.Composing /// public IRuntimeState RuntimeState { get; } + /// + /// Gets the configurations. + /// + public Configs Configs { get; } + #endregion #region IRegister diff --git a/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs b/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs index f63c56b64e..26322aa801 100644 --- a/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs +++ b/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs @@ -118,7 +118,7 @@ namespace Umbraco.Tests.Runtimes public class TestRuntime : CoreRuntime { public TestRuntime(Configs configs, IUmbracoVersion umbracoVersion, IIOHelper ioHelper, ILogger logger, IProfiler profiler, IHostingEnvironment hostingEnvironment, IBackOfficeInfo backOfficeInfo) - :base(configs, umbracoVersion, ioHelper, logger, profiler, new AspNetUmbracoBootPermissionChecker(), hostingEnvironment, backOfficeInfo, TestHelper.DbProviderFactoryCreator, TestHelper.MainDom, TestHelper.GetTypeFinder(), NoAppCache.Instance) + : base(Umbraco.Web.Configuration.ConfigModelConversions.ConvertGlobalSettings(configs.Global()), Umbraco.Web.Configuration.ConfigModelConversions.ConvertConnectionStrings(configs.ConnectionStrings()), umbracoVersion, ioHelper, logger, profiler, new AspNetUmbracoBootPermissionChecker(), hostingEnvironment, backOfficeInfo, TestHelper.DbProviderFactoryCreator, TestHelper.MainDom, TestHelper.GetTypeFinder(), NoAppCache.Instance) { } diff --git a/src/Umbraco.Tests/TestHelpers/TestHelper.cs b/src/Umbraco.Tests/TestHelpers/TestHelper.cs index 9aeb668518..1675d75fc1 100644 --- a/src/Umbraco.Tests/TestHelpers/TestHelper.cs +++ b/src/Umbraco.Tests/TestHelpers/TestHelper.cs @@ -33,6 +33,7 @@ using Umbraco.Web; using Umbraco.Web.Hosting; using Umbraco.Web.Routing; using File = System.IO.File; +using Umbraco.Tests.Common.Builders; namespace Umbraco.Tests.TestHelpers { @@ -105,7 +106,7 @@ namespace Umbraco.Tests.TestHelpers public static IWebRoutingSettings WebRoutingSettings => _testHelperInternal.WebRoutingSettings; - public static IEmailSender EmailSender { get; } = new EmailSender(SettingsForTests.GenerateMockGlobalSettings()); + public static IEmailSender EmailSender { get; } = new EmailSender(new GlobalSettingsBuilder().Build()); /// From 2c05718689033eec24be76f10a6fb64587665c85 Mon Sep 17 00:00:00 2001 From: Andy Butland Date: Tue, 25 Aug 2020 10:25:30 +0200 Subject: [PATCH 274/826] Restored Umbraco.Tests.Benchmarks. --- .../ModelToSqlExpressionHelperBenchmarks.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Umbraco.Tests.Benchmarks/ModelToSqlExpressionHelperBenchmarks.cs b/src/Umbraco.Tests.Benchmarks/ModelToSqlExpressionHelperBenchmarks.cs index d200b3e295..6eb955ea8f 100644 --- a/src/Umbraco.Tests.Benchmarks/ModelToSqlExpressionHelperBenchmarks.cs +++ b/src/Umbraco.Tests.Benchmarks/ModelToSqlExpressionHelperBenchmarks.cs @@ -3,6 +3,7 @@ using System.Collections.Concurrent; using System.Linq.Expressions; using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Diagnosers; +using Moq; using Umbraco.Core.Models; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.Mappers; From 967f0be705a8272c1760b7dcaddb0b45119eb1c9 Mon Sep 17 00:00:00 2001 From: Andy Butland Date: Tue, 25 Aug 2020 10:45:54 +0200 Subject: [PATCH 275/826] Aligned property names in code with those in configuration. --- .../Configuration/GlobalSettingsExtensions.cs | 6 +-- .../Models/ContentNotificationSettings.cs | 2 +- .../Configuration/Models/ContentSettings.cs | 2 +- .../Configuration/Models/GlobalSettings.cs | 2 +- .../Configuration/Models/HostingSettings.cs | 2 +- .../Models/RequestHandlerSettings.cs | 6 ++- .../Configuration/Models/SecuritySettings.cs | 4 ++ .../FolderAndFilePermissionsCheck.cs | 2 +- .../Packaging/CompiledPackageXmlParser.cs | 2 +- .../Strings/DefaultShortStringHelperConfig.cs | 4 +- .../CompositionExtensions/Services.cs | 2 +- .../EmailNotificationMethod.cs | 2 +- .../Install/FilePermissionHelper.cs | 2 +- .../Services/Implement/FileService.cs | 4 +- .../Services/Implement/NotificationService.cs | 6 +-- .../BackOfficeJavaScriptInitializer.cs | 2 +- .../Builders/GlobalSettingsBuilder.cs | 18 +-------- .../Builders/HostingSettingsBuilder.cs | 10 ++--- .../BackOfficeCookieManagerTests.cs | 8 ++-- .../Builders/HostingSettingsBuilderTests.cs | 4 +- .../TestHelpers/ConfigModelConversions.cs | 2 +- .../Controllers/BackOfficeAssetsController.cs | 2 +- .../Controllers/BackOfficeController.cs | 4 +- .../Controllers/PreviewController.cs | 2 +- .../AspNetCore/AspNetCoreBackOfficeInfo.cs | 2 +- .../AspNetCoreHostingEnvironment.cs | 2 +- .../AspNetCore/UmbracoViewPage.cs | 2 +- .../UmbracoCoreServiceCollectionExtensions.cs | 38 +++++++++---------- .../Install/InstallController.cs | 4 +- .../Macros/MacroRenderer.cs | 2 +- .../Security/WebSecurity.cs | 2 +- .../Configuration/ConfigModelConversions.cs | 2 +- 32 files changed, 73 insertions(+), 81 deletions(-) diff --git a/src/Umbraco.Core/Configuration/GlobalSettingsExtensions.cs b/src/Umbraco.Core/Configuration/GlobalSettingsExtensions.cs index f9b2362e14..dc52c8dcd6 100644 --- a/src/Umbraco.Core/Configuration/GlobalSettingsExtensions.cs +++ b/src/Umbraco.Core/Configuration/GlobalSettingsExtensions.cs @@ -18,7 +18,7 @@ namespace Umbraco.Core.Configuration public static string GetBackOfficePath(this GlobalSettings globalSettings, IHostingEnvironment hostingEnvironment) { if (_backOfficePath != null) return _backOfficePath; - _backOfficePath = hostingEnvironment.ToAbsolute(globalSettings.UmbracoPath); + _backOfficePath = hostingEnvironment.ToAbsolute(globalSettings.Path); return _backOfficePath; } @@ -44,9 +44,9 @@ namespace Umbraco.Core.Configuration internal static string GetUmbracoMvcAreaNoCache(this GlobalSettings globalSettings, IHostingEnvironment hostingEnvironment) { - var path = string.IsNullOrEmpty(globalSettings.UmbracoPath) + var path = string.IsNullOrEmpty(globalSettings.Path) ? string.Empty - : hostingEnvironment.ToAbsolute(globalSettings.UmbracoPath); + : hostingEnvironment.ToAbsolute(globalSettings.Path); if (path.IsNullOrWhiteSpace()) throw new InvalidOperationException("Cannot create an MVC Area path without the umbracoPath specified"); diff --git a/src/Umbraco.Core/Configuration/Models/ContentNotificationSettings.cs b/src/Umbraco.Core/Configuration/Models/ContentNotificationSettings.cs index 0ae1ffd991..ab1c10ff77 100644 --- a/src/Umbraco.Core/Configuration/Models/ContentNotificationSettings.cs +++ b/src/Umbraco.Core/Configuration/Models/ContentNotificationSettings.cs @@ -2,7 +2,7 @@ { public class ContentNotificationSettings { - public string NotificationEmailAddress { get; set; } + public string Email { get; set; } public bool DisableHtmlEmail { get; set; } = false; } diff --git a/src/Umbraco.Core/Configuration/Models/ContentSettings.cs b/src/Umbraco.Core/Configuration/Models/ContentSettings.cs index 0a405d7db3..31a97e6615 100644 --- a/src/Umbraco.Core/Configuration/Models/ContentSettings.cs +++ b/src/Umbraco.Core/Configuration/Models/ContentSettings.cs @@ -28,7 +28,7 @@ namespace Umbraco.Core.Configuration.Models public string PreviewBadge { get; set; } = DefaultPreviewBadge; - public MacroErrorBehaviour MacroErrorBehaviour { get; set; } = MacroErrorBehaviour.Inline; + public MacroErrorBehaviour MacroErrors { get; set; } = MacroErrorBehaviour.Inline; public IEnumerable DisallowedUploadFiles { get; set; } = new[] { "ashx", "aspx", "ascx", "config", "cshtml", "vbhtml", "asmx", "air", "axd" }; diff --git a/src/Umbraco.Core/Configuration/Models/GlobalSettings.cs b/src/Umbraco.Core/Configuration/Models/GlobalSettings.cs index 8f5f64ffbc..ac659b6d05 100644 --- a/src/Umbraco.Core/Configuration/Models/GlobalSettings.cs +++ b/src/Umbraco.Core/Configuration/Models/GlobalSettings.cs @@ -30,7 +30,7 @@ public int VersionCheckPeriod { get; set; } = 7; - public string UmbracoPath { get; set; } = "~/umbraco"; + public string Path { get; set; } = "~/umbraco"; public string UmbracoCssPath { get; set; } = "~/css"; diff --git a/src/Umbraco.Core/Configuration/Models/HostingSettings.cs b/src/Umbraco.Core/Configuration/Models/HostingSettings.cs index ea389efde4..0863181922 100644 --- a/src/Umbraco.Core/Configuration/Models/HostingSettings.cs +++ b/src/Umbraco.Core/Configuration/Models/HostingSettings.cs @@ -13,6 +13,6 @@ /// Gets a value indicating whether umbraco is running in [debug mode]. /// /// true if [debug mode]; otherwise, false. - public bool DebugMode { get; set; } = false; + public bool Debug { get; set; } = false; } } diff --git a/src/Umbraco.Core/Configuration/Models/RequestHandlerSettings.cs b/src/Umbraco.Core/Configuration/Models/RequestHandlerSettings.cs index e168122738..a2422fc899 100644 --- a/src/Umbraco.Core/Configuration/Models/RequestHandlerSettings.cs +++ b/src/Umbraco.Core/Configuration/Models/RequestHandlerSettings.cs @@ -35,9 +35,11 @@ namespace Umbraco.Core.Configuration.Models public bool AddTrailingSlash { get; set; } = true; - public bool ConvertUrlsToAscii { get; set; } = true; + public string ConvertUrlsToAscii { get; set; } = "try"; - public bool TryConvertUrlsToAscii { get; set; } = false; + public bool ShouldConvertUrlsToAscii => ConvertUrlsToAscii.InvariantEquals("true"); + + public bool ShouldTryConvertUrlsToAscii => ConvertUrlsToAscii.InvariantEquals("try"); //We need to special handle ":", as this character is special in keys diff --git a/src/Umbraco.Core/Configuration/Models/SecuritySettings.cs b/src/Umbraco.Core/Configuration/Models/SecuritySettings.cs index 5295abb368..f40160d69b 100644 --- a/src/Umbraco.Core/Configuration/Models/SecuritySettings.cs +++ b/src/Umbraco.Core/Configuration/Models/SecuritySettings.cs @@ -13,5 +13,9 @@ public string AuthCookieDomain { get; set; } public bool UsernameIsEmail { get; set; } = true; + + public UserPasswordConfigurationSettings UserPassword { get; set; } + + public MemberPasswordConfigurationSettings MemberPassword { get; set; } } } diff --git a/src/Umbraco.Core/HealthCheck/Checks/Permissions/FolderAndFilePermissionsCheck.cs b/src/Umbraco.Core/HealthCheck/Checks/Permissions/FolderAndFilePermissionsCheck.cs index d6fbfae813..8cd0d3a575 100644 --- a/src/Umbraco.Core/HealthCheck/Checks/Permissions/FolderAndFilePermissionsCheck.cs +++ b/src/Umbraco.Core/HealthCheck/Checks/Permissions/FolderAndFilePermissionsCheck.cs @@ -77,7 +77,7 @@ namespace Umbraco.Web.HealthCheck.Checks.Permissions { _globalSettings.UmbracoCssPath, PermissionCheckRequirement.Optional }, { _globalSettings.UmbracoMediaPath, PermissionCheckRequirement.Optional }, { _globalSettings.UmbracoScriptsPath, PermissionCheckRequirement.Optional }, - { _globalSettings.UmbracoPath, PermissionCheckRequirement.Optional }, + { _globalSettings.Path, PermissionCheckRequirement.Optional }, { Constants.SystemDirectories.MvcViews, PermissionCheckRequirement.Optional } }; diff --git a/src/Umbraco.Core/Packaging/CompiledPackageXmlParser.cs b/src/Umbraco.Core/Packaging/CompiledPackageXmlParser.cs index 010e6469bf..2013fd9904 100644 --- a/src/Umbraco.Core/Packaging/CompiledPackageXmlParser.cs +++ b/src/Umbraco.Core/Packaging/CompiledPackageXmlParser.cs @@ -138,7 +138,7 @@ namespace Umbraco.Core.Packaging if (path.Contains("[$")) { //this is experimental and undocumented... - path = path.Replace("[$UMBRACO]", _globalSettings.UmbracoPath); + path = path.Replace("[$UMBRACO]", _globalSettings.Path); path = path.Replace("[$CONFIG]", Constants.SystemDirectories.Config); path = path.Replace("[$DATA]", Constants.SystemDirectories.Data); } diff --git a/src/Umbraco.Core/Strings/DefaultShortStringHelperConfig.cs b/src/Umbraco.Core/Strings/DefaultShortStringHelperConfig.cs index 32c02c09fb..d6adf5b221 100644 --- a/src/Umbraco.Core/Strings/DefaultShortStringHelperConfig.cs +++ b/src/Umbraco.Core/Strings/DefaultShortStringHelperConfig.cs @@ -65,9 +65,9 @@ namespace Umbraco.Core.Strings .ToDictionary(x => x.Char, x => x.Replacement); var urlSegmentConvertTo = CleanStringType.Utf8; - if (requestHandlerSettings.ConvertUrlsToAscii) + if (requestHandlerSettings.ShouldConvertUrlsToAscii) urlSegmentConvertTo = CleanStringType.Ascii; - if (requestHandlerSettings.TryConvertUrlsToAscii) + if (requestHandlerSettings.ShouldTryConvertUrlsToAscii) urlSegmentConvertTo = CleanStringType.TryAscii; return WithConfig(CleanStringType.UrlSegment, new Config diff --git a/src/Umbraco.Infrastructure/Composing/CompositionExtensions/Services.cs b/src/Umbraco.Infrastructure/Composing/CompositionExtensions/Services.cs index ffd8b880f2..105ef00f73 100644 --- a/src/Umbraco.Infrastructure/Composing/CompositionExtensions/Services.cs +++ b/src/Umbraco.Infrastructure/Composing/CompositionExtensions/Services.cs @@ -103,7 +103,7 @@ namespace Umbraco.Core.Composing.CompositionExtensions { var hostingEnvironment = container.GetInstance(); var globalSettings = container.GetInstance>().Value; - var mainLangFolder = new DirectoryInfo(hostingEnvironment.MapPathContentRoot(WebPath.Combine(globalSettings.UmbracoPath , "config","lang"))); + var mainLangFolder = new DirectoryInfo(hostingEnvironment.MapPathContentRoot(WebPath.Combine(globalSettings.Path , "config","lang"))); var appPlugins = new DirectoryInfo(hostingEnvironment.MapPathContentRoot(Constants.SystemDirectories.AppPlugins)); var configLangFolder = new DirectoryInfo(hostingEnvironment.MapPathContentRoot(WebPath.Combine(Constants.SystemDirectories.Config ,"lang"))); diff --git a/src/Umbraco.Infrastructure/HealthCheck/NotificationMethods/EmailNotificationMethod.cs b/src/Umbraco.Infrastructure/HealthCheck/NotificationMethods/EmailNotificationMethod.cs index dd2f27320e..19d63d7d6a 100644 --- a/src/Umbraco.Infrastructure/HealthCheck/NotificationMethods/EmailNotificationMethod.cs +++ b/src/Umbraco.Infrastructure/HealthCheck/NotificationMethods/EmailNotificationMethod.cs @@ -79,7 +79,7 @@ namespace Umbraco.Web.HealthCheck.NotificationMethods private MailMessage CreateMailMessage(string subject, string message) { - var to = _contentSettings.Notifications.NotificationEmailAddress; + var to = _contentSettings.Notifications.Email; if (string.IsNullOrWhiteSpace(subject)) subject = "Umbraco Health Check Status"; diff --git a/src/Umbraco.Infrastructure/Install/FilePermissionHelper.cs b/src/Umbraco.Infrastructure/Install/FilePermissionHelper.cs index 7a20a1189e..07d78444c1 100644 --- a/src/Umbraco.Infrastructure/Install/FilePermissionHelper.cs +++ b/src/Umbraco.Infrastructure/Install/FilePermissionHelper.cs @@ -31,7 +31,7 @@ namespace Umbraco.Web.Install _ioHelper = ioHelper; _publishedSnapshotService = publishedSnapshotService; _permissionDirs = new[] { _globalSettings.UmbracoCssPath, Constants.SystemDirectories.Config, Constants.SystemDirectories.Data, _globalSettings.UmbracoMediaPath, Constants.SystemDirectories.Preview }; - _packagesPermissionsDirs = new[] { Constants.SystemDirectories.Bin, _globalSettings.UmbracoPath, Constants.SystemDirectories.Packages }; + _packagesPermissionsDirs = new[] { Constants.SystemDirectories.Bin, _globalSettings.Path, Constants.SystemDirectories.Packages }; } public bool RunFilePermissionTestSuite(out Dictionary> report) diff --git a/src/Umbraco.Infrastructure/Services/Implement/FileService.cs b/src/Umbraco.Infrastructure/Services/Implement/FileService.cs index e82c71d1a5..086092597f 100644 --- a/src/Umbraco.Infrastructure/Services/Implement/FileService.cs +++ b/src/Umbraco.Infrastructure/Services/Implement/FileService.cs @@ -675,7 +675,7 @@ namespace Umbraco.Core.Services.Implement public IEnumerable GetPartialViewSnippetNames(params string[] filterNames) { - var snippetPath = _hostingEnvironment.MapPathContentRoot($"{_globalSettings.UmbracoPath}/PartialViewMacros/Templates/"); + var snippetPath = _hostingEnvironment.MapPathContentRoot($"{_globalSettings.Path}/PartialViewMacros/Templates/"); var files = Directory.GetFiles(snippetPath, "*.cshtml") .Select(Path.GetFileNameWithoutExtension) .Except(filterNames, StringComparer.InvariantCultureIgnoreCase) @@ -909,7 +909,7 @@ namespace Umbraco.Core.Services.Implement fileName += ".cshtml"; } - var snippetPath = _hostingEnvironment.MapPathContentRoot($"{_globalSettings.UmbracoPath}/PartialViewMacros/Templates/{fileName}"); + var snippetPath = _hostingEnvironment.MapPathContentRoot($"{_globalSettings.Path}/PartialViewMacros/Templates/{fileName}"); return System.IO.File.Exists(snippetPath) ? Attempt.Succeed(snippetPath) : Attempt.Fail(); diff --git a/src/Umbraco.Infrastructure/Services/Implement/NotificationService.cs b/src/Umbraco.Infrastructure/Services/Implement/NotificationService.cs index 411babe247..9b0045da7b 100644 --- a/src/Umbraco.Infrastructure/Services/Implement/NotificationService.cs +++ b/src/Umbraco.Infrastructure/Services/Implement/NotificationService.cs @@ -392,7 +392,7 @@ namespace Umbraco.Core.Services.Implement var protocol = _globalSettings.UseHttps ? "https" : "http"; var subjectVars = new NotificationEmailSubjectParams( - string.Concat(siteUri.Authority, _ioHelper.ResolveUrl(_globalSettings.UmbracoPath)), + string.Concat(siteUri.Authority, _ioHelper.ResolveUrl(_globalSettings.Path)), actionName, content.Name); @@ -408,10 +408,10 @@ namespace Umbraco.Core.Services.Implement string.Concat(content.Id, ".aspx"), protocol), performingUser.Name, - string.Concat(siteUri.Authority, _ioHelper.ResolveUrl(_globalSettings.UmbracoPath)), + string.Concat(siteUri.Authority, _ioHelper.ResolveUrl(_globalSettings.Path)), summary.ToString()); - var fromMail = _contentSettings.Notifications.NotificationEmailAddress ?? _globalSettings.Smtp.From; + var fromMail = _contentSettings.Notifications.Email ?? _globalSettings.Smtp.From; // create the mail message var mail = new MailMessage(fromMail, fromMail); diff --git a/src/Umbraco.Infrastructure/WebAssets/BackOfficeJavaScriptInitializer.cs b/src/Umbraco.Infrastructure/WebAssets/BackOfficeJavaScriptInitializer.cs index 77db7bcbfd..8908978e4b 100644 --- a/src/Umbraco.Infrastructure/WebAssets/BackOfficeJavaScriptInitializer.cs +++ b/src/Umbraco.Infrastructure/WebAssets/BackOfficeJavaScriptInitializer.cs @@ -48,7 +48,7 @@ namespace Umbraco.Web.WebAssets } jarray.Append("]"); - return WriteScript(jarray.ToString(), hostingEnvironment.ToAbsolute(globalSettings.UmbracoPath), angularModule); + return WriteScript(jarray.ToString(), hostingEnvironment.ToAbsolute(globalSettings.Path), angularModule); } /// diff --git a/src/Umbraco.Tests.Common/Builders/GlobalSettingsBuilder.cs b/src/Umbraco.Tests.Common/Builders/GlobalSettingsBuilder.cs index 72cc6de9a1..ab07331108 100644 --- a/src/Umbraco.Tests.Common/Builders/GlobalSettingsBuilder.cs +++ b/src/Umbraco.Tests.Common/Builders/GlobalSettingsBuilder.cs @@ -18,7 +18,6 @@ namespace Umbraco.Tests.Common.Builders private bool? _hideTopLevelNodeFromPath; private bool? _installEmptyDatabase; private bool? _installMissingDatabase; - private bool? _isSmtpServerConfigured; private string _path; private string _registerType; private string _reservedPaths; @@ -26,7 +25,6 @@ namespace Umbraco.Tests.Common.Builders private int? _timeOutInMinutes; private string _umbracoCssPath; private string _umbracoMediaPath; - private string _umbracoPath; private string _umbracoScriptsPath; private string _mainDomLock; private string _noNodesViewPath; @@ -83,12 +81,6 @@ namespace Umbraco.Tests.Common.Builders return this; } - public GlobalSettingsBuilder WithIsSmtpServerConfigured(bool isSmtpServerConfigured) - { - _isSmtpServerConfigured = isSmtpServerConfigured; - return this; - } - public GlobalSettingsBuilder WithPath(string path) { _path = path; @@ -113,12 +105,6 @@ namespace Umbraco.Tests.Common.Builders return this; } - public GlobalSettingsBuilder WithUmbracoPath(string umbracoPath) - { - _umbracoPath = umbracoPath; - return this; - } - public GlobalSettingsBuilder WithUseHttps(bool useHttps) { _useHttps = useHttps; @@ -178,7 +164,7 @@ namespace Umbraco.Tests.Common.Builders var registerType = _registerType ?? null; var reservedPaths = _reservedPaths ?? "~/app_plugins/,~/install/,~/mini-profiler-resources/,"; var reservedUrls = _reservedUrls ?? "~/config/splashes/noNodes.aspx,~/.well-known,"; - var umbracoPath = _umbracoPath ?? "~/umbraco"; + var path = _path ?? "~/umbraco"; var useHttps = _useHttps ?? false; var umbracoCssPath = _umbracoCssPath ?? "~/css"; var umbracoMediaPath = _umbracoMediaPath ?? "~/media"; @@ -201,7 +187,7 @@ namespace Umbraco.Tests.Common.Builders RegisterType = registerType, ReservedPaths = reservedPaths, ReservedUrls = reservedUrls, - UmbracoPath = umbracoPath, + Path = path, UseHttps = useHttps, UmbracoCssPath = umbracoCssPath, UmbracoMediaPath = umbracoMediaPath, diff --git a/src/Umbraco.Tests.Common/Builders/HostingSettingsBuilder.cs b/src/Umbraco.Tests.Common/Builders/HostingSettingsBuilder.cs index 11e622d4d4..3e5e1db391 100644 --- a/src/Umbraco.Tests.Common/Builders/HostingSettingsBuilder.cs +++ b/src/Umbraco.Tests.Common/Builders/HostingSettingsBuilder.cs @@ -6,7 +6,7 @@ namespace Umbraco.Tests.Common.Builders public class HostingSettingsBuilder : BuilderBase { private string _applicationVirtualPath; - private bool? _debugMode; + private bool? _debug; private LocalTempStorage? _localTempStorageLocation; public HostingSettingsBuilder WithApplicationVirtualPath(string applicationVirtualPath) @@ -15,9 +15,9 @@ namespace Umbraco.Tests.Common.Builders return this; } - public HostingSettingsBuilder WithDebugMode(bool debugMode) + public HostingSettingsBuilder WithDebug(bool debug) { - _debugMode = debugMode; + _debug = debug; return this; } @@ -29,14 +29,14 @@ namespace Umbraco.Tests.Common.Builders public override HostingSettings Build() { - var debugMode = _debugMode ?? false; + var debug = _debug ?? false; var localTempStorageLocation = _localTempStorageLocation ?? LocalTempStorage.Default; var applicationVirtualPath = _applicationVirtualPath ?? null; return new HostingSettings { ApplicationVirtualPath = applicationVirtualPath, - DebugMode = debugMode, + Debug = debug, LocalTempStorageLocation = localTempStorageLocation, }; } diff --git a/src/Umbraco.Tests.Integration/Umbraco.Web.BackOffice.Security/BackOfficeCookieManagerTests.cs b/src/Umbraco.Tests.Integration/Umbraco.Web.BackOffice.Security/BackOfficeCookieManagerTests.cs index 6fd5672085..d03d4386f0 100644 --- a/src/Umbraco.Tests.Integration/Umbraco.Web.BackOffice.Security/BackOfficeCookieManagerTests.cs +++ b/src/Umbraco.Tests.Integration/Umbraco.Web.BackOffice.Security/BackOfficeCookieManagerTests.cs @@ -57,7 +57,7 @@ namespace Umbraco.Tests.Security var mgr = new BackOfficeCookieManager( Mock.Of(), runtime, - Mock.Of(x => x.ApplicationVirtualPath == "/" && x.ToAbsolute(globalSettings.UmbracoPath) == "/umbraco"), + Mock.Of(x => x.ApplicationVirtualPath == "/" && x.ToAbsolute(globalSettings.Path) == "/umbraco"), globalSettings, Mock.Of(), Mock.Of()); @@ -80,7 +80,7 @@ namespace Umbraco.Tests.Security var mgr = new BackOfficeCookieManager( Mock.Of(), runtime, - Mock.Of(x => x.ApplicationVirtualPath == "/" && x.ToAbsolute(globalSettings.UmbracoPath) == "/umbraco" && x.ToAbsolute(Constants.SystemDirectories.Install) == "/install"), + Mock.Of(x => x.ApplicationVirtualPath == "/" && x.ToAbsolute(globalSettings.Path) == "/umbraco" && x.ToAbsolute(Constants.SystemDirectories.Install) == "/install"), globalSettings, Mock.Of(), GetMockLinkGenerator(out var remainingTimeoutSecondsPath, out var isAuthPath)); @@ -105,7 +105,7 @@ namespace Umbraco.Tests.Security var mgr = new BackOfficeCookieManager( Mock.Of(), runtime, - Mock.Of(x => x.ApplicationVirtualPath == "/" && x.ToAbsolute(globalSettings.UmbracoPath) == "/umbraco" && x.ToAbsolute(Constants.SystemDirectories.Install) == "/install"), + Mock.Of(x => x.ApplicationVirtualPath == "/" && x.ToAbsolute(globalSettings.Path) == "/umbraco" && x.ToAbsolute(Constants.SystemDirectories.Install) == "/install"), globalSettings, Mock.Of(x => x.IsAvailable == true && x.Get(Constants.Security.ForceReAuthFlag) == "not null"), GetMockLinkGenerator(out var remainingTimeoutSecondsPath, out var isAuthPath)); @@ -127,7 +127,7 @@ namespace Umbraco.Tests.Security var mgr = new BackOfficeCookieManager( Mock.Of(), runtime, - Mock.Of(x => x.ApplicationVirtualPath == "/" && x.ToAbsolute(globalSettings.UmbracoPath) == "/umbraco" && x.ToAbsolute(Constants.SystemDirectories.Install) == "/install"), + Mock.Of(x => x.ApplicationVirtualPath == "/" && x.ToAbsolute(globalSettings.Path) == "/umbraco" && x.ToAbsolute(Constants.SystemDirectories.Install) == "/install"), globalSettings, Mock.Of(), GetMockLinkGenerator(out var remainingTimeoutSecondsPath, out var isAuthPath)); diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Tests.Common/Builders/HostingSettingsBuilderTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Tests.Common/Builders/HostingSettingsBuilderTests.cs index 81ab0a7183..377e143b97 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Tests.Common/Builders/HostingSettingsBuilderTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Tests.Common/Builders/HostingSettingsBuilderTests.cs @@ -18,12 +18,12 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Tests.Common.Builders // Act var hostingSettings = builder - .WithDebugMode(debugMode) + .WithDebug(debugMode) .WithLocalTempStorageLocation(localTempStorageLocation) .Build(); // Assert - Assert.AreEqual(debugMode, hostingSettings.DebugMode); + Assert.AreEqual(debugMode, hostingSettings.Debug); Assert.AreEqual(localTempStorageLocation, hostingSettings.LocalTempStorageLocation); } } diff --git a/src/Umbraco.Tests/TestHelpers/ConfigModelConversions.cs b/src/Umbraco.Tests/TestHelpers/ConfigModelConversions.cs index 800374c690..5417116713 100644 --- a/src/Umbraco.Tests/TestHelpers/ConfigModelConversions.cs +++ b/src/Umbraco.Tests/TestHelpers/ConfigModelConversions.cs @@ -39,7 +39,7 @@ namespace Umbraco.Tests.TestHelpers TimeOutInMinutes = globalSettings.TimeOutInMinutes, UmbracoCssPath = globalSettings.UmbracoCssPath, UmbracoMediaPath = globalSettings.UmbracoMediaPath, - UmbracoPath = globalSettings.UmbracoPath, + UmbracoPath = globalSettings.Path, UmbracoScriptsPath = globalSettings.UmbracoScriptsPath, UseHttps = globalSettings.UseHttps, VersionCheckPeriod = globalSettings.VersionCheckPeriod, diff --git a/src/Umbraco.Web.BackOffice/Controllers/BackOfficeAssetsController.cs b/src/Umbraco.Web.BackOffice/Controllers/BackOfficeAssetsController.cs index 5ee7cf31cf..92df3b0fad 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/BackOfficeAssetsController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/BackOfficeAssetsController.cs @@ -21,7 +21,7 @@ namespace Umbraco.Web.BackOffice.Controllers public BackOfficeAssetsController(IIOHelper ioHelper, IHostingEnvironment hostingEnvironment, ILogger logger, IOptions globalSettings) { - _jsLibFileSystem = new PhysicalFileSystem(ioHelper, hostingEnvironment, logger, globalSettings.Value.UmbracoPath + Path.DirectorySeparatorChar + "lib"); + _jsLibFileSystem = new PhysicalFileSystem(ioHelper, hostingEnvironment, logger, globalSettings.Value.Path + Path.DirectorySeparatorChar + "lib"); } [HttpGet] diff --git a/src/Umbraco.Web.BackOffice/Controllers/BackOfficeController.cs b/src/Umbraco.Web.BackOffice/Controllers/BackOfficeController.cs index e3480984fd..6cf92d9100 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/BackOfficeController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/BackOfficeController.cs @@ -78,7 +78,7 @@ namespace Umbraco.Web.BackOffice.Controllers [HttpGet] public async Task Default() { - var viewPath = Path.Combine(_globalSettings.UmbracoPath , Constants.Web.Mvc.BackOfficeArea, nameof(Default) + ".cshtml") + var viewPath = Path.Combine(_globalSettings.Path , Constants.Web.Mvc.BackOfficeArea, nameof(Default) + ".cshtml") .Replace("\\", "/"); // convert to forward slashes since it's a virtual path return await RenderDefaultOrProcessExternalLoginAsync( @@ -156,7 +156,7 @@ namespace Umbraco.Web.BackOffice.Controllers [StatusCodeResult(System.Net.HttpStatusCode.ServiceUnavailable)] public async Task AuthorizeUpgrade() { - var viewPath = Path.Combine(_globalSettings.UmbracoPath, Umbraco.Core.Constants.Web.Mvc.BackOfficeArea, nameof(AuthorizeUpgrade) + ".cshtml"); + var viewPath = Path.Combine(_globalSettings.Path, Umbraco.Core.Constants.Web.Mvc.BackOfficeArea, nameof(AuthorizeUpgrade) + ".cshtml"); return await RenderDefaultOrProcessExternalLoginAsync( //The default view to render when there is no external login info or errors () => View(viewPath), diff --git a/src/Umbraco.Web.BackOffice/Controllers/PreviewController.cs b/src/Umbraco.Web.BackOffice/Controllers/PreviewController.cs index 3878eb9b14..7b370b1824 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/PreviewController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/PreviewController.cs @@ -77,7 +77,7 @@ namespace Umbraco.Web.BackOffice.Controllers } var viewPath = Path.Combine( - _globalSettings.UmbracoPath, + _globalSettings.Path, Constants.Web.Mvc.BackOfficeArea, ControllerExtensions.GetControllerName() + ".cshtml") .Replace("\\", "/"); // convert to forward slashes since it's a virtual path diff --git a/src/Umbraco.Web.Common/AspNetCore/AspNetCoreBackOfficeInfo.cs b/src/Umbraco.Web.Common/AspNetCore/AspNetCoreBackOfficeInfo.cs index 6f40800307..6c83bc5747 100644 --- a/src/Umbraco.Web.Common/AspNetCore/AspNetCoreBackOfficeInfo.cs +++ b/src/Umbraco.Web.Common/AspNetCore/AspNetCoreBackOfficeInfo.cs @@ -13,7 +13,7 @@ namespace Umbraco.Web.Common.AspNetCore public AspNetCoreBackOfficeInfo(GlobalSettings globalSettings) { - GetAbsoluteUrl = globalSettings.UmbracoPath; + GetAbsoluteUrl = globalSettings.Path; } public string GetAbsoluteUrl { get; } // TODO make absolute diff --git a/src/Umbraco.Web.Common/AspNetCore/AspNetCoreHostingEnvironment.cs b/src/Umbraco.Web.Common/AspNetCore/AspNetCoreHostingEnvironment.cs index 54502fbe29..32c291bbce 100644 --- a/src/Umbraco.Web.Common/AspNetCore/AspNetCoreHostingEnvironment.cs +++ b/src/Umbraco.Web.Common/AspNetCore/AspNetCoreHostingEnvironment.cs @@ -43,7 +43,7 @@ namespace Umbraco.Web.Common.AspNetCore public string ApplicationServerAddress { get; } public string ApplicationVirtualPath { get; } - public bool IsDebugMode => _hostingSettings.DebugMode; + public bool IsDebugMode => _hostingSettings.Debug; public Version IISVersion { get; } public string LocalTempPath diff --git a/src/Umbraco.Web.Common/AspNetCore/UmbracoViewPage.cs b/src/Umbraco.Web.Common/AspNetCore/UmbracoViewPage.cs index fde3d095fe..776f22eea1 100644 --- a/src/Umbraco.Web.Common/AspNetCore/UmbracoViewPage.cs +++ b/src/Umbraco.Web.Common/AspNetCore/UmbracoViewPage.cs @@ -64,7 +64,7 @@ namespace Umbraco.Web.Common.AspNetCore // creating previewBadge markup markupToInject = string.Format(ContentSettings.PreviewBadge, - IOHelper.ResolveUrl(GlobalSettings.UmbracoPath), + IOHelper.ResolveUrl(GlobalSettings.Path), Context.Request.GetEncodedUrl(), UmbracoContext.PublishedRequest.PublishedContent.Id); } diff --git a/src/Umbraco.Web.Common/Extensions/UmbracoCoreServiceCollectionExtensions.cs b/src/Umbraco.Web.Common/Extensions/UmbracoCoreServiceCollectionExtensions.cs index 46d035d76b..b5583f0b7e 100644 --- a/src/Umbraco.Web.Common/Extensions/UmbracoCoreServiceCollectionExtensions.cs +++ b/src/Umbraco.Web.Common/Extensions/UmbracoCoreServiceCollectionExtensions.cs @@ -104,28 +104,28 @@ namespace Umbraco.Extensions { if (configuration == null) throw new ArgumentNullException(nameof(configuration)); - services.Configure(configuration.GetSection("ConnectionStrings"), o => o.BindNonPublicProperties = true); - services.Configure(configuration.GetSection(Constants.Configuration.ConfigPrefix + "Tours")); - services.Configure(configuration.GetSection(Constants.Configuration.ConfigPrefix + "Core:Debug")); - services.Configure(configuration.GetSection(Constants.Configuration.ConfigSecurityPrefix)); - services.Configure(configuration.GetSection(Constants.Configuration.ConfigSecurityPrefix + "UserPassword")); - services.Configure(configuration.GetSection(Constants.Configuration.ConfigSecurityPrefix + "MemberPassword")); - services.Configure(configuration.GetSection(Constants.Configuration.ConfigPrefix + "KeepAlive")); - services.Configure(configuration.GetSection(Constants.Configuration.ConfigPrefix + "Content")); - services.Configure(configuration.GetSection(Constants.Configuration.ConfigPrefix + "Logging")); - services.Configure(configuration.GetSection(Constants.Configuration.ConfigPrefix + "ExceptionFilter")); services.Configure(configuration.GetSection(Constants.Configuration.ConfigPrefix + "ActiveDirectory")); - services.Configure(configuration.GetSection(Constants.Configuration.ConfigPrefix + "Runtime")); - services.Configure(configuration.GetSection(Constants.Configuration.ConfigPrefix + "TypeFinder")); + services.Configure(configuration.GetSection("ConnectionStrings"), o => o.BindNonPublicProperties = true); + services.Configure(configuration.GetSection(Constants.Configuration.ConfigPrefix + "Content")); + services.Configure(configuration.GetSection(Constants.Configuration.ConfigPrefix + "Core:Debug")); + services.Configure(configuration.GetSection(Constants.Configuration.ConfigPrefix + "ExceptionFilter")); services.Configure(configuration.GetSection(Constants.Configuration.ConfigPrefix + "Global")); - services.Configure(configuration.GetSection(Constants.Configuration.ConfigPrefix + "Hosting")); - services.Configure(configuration.GetSection(Constants.Configuration.ConfigPrefix + "NuCache")); - services.Configure(configuration.GetSection(Constants.Configuration.ConfigPrefix + "WebRouting")); - services.Configure(configuration.GetSection(Constants.Configuration.ConfigPrefix + "Examine")); - services.Configure(configuration.GetSection(Constants.Configuration.ConfigGlobalPrefix + "ModelsBuilder")); - services.Configure(configuration.GetSection(Constants.Configuration.ConfigPrefix + "Imaging")); - services.Configure(configuration.GetSection(Constants.Configuration.ConfigPrefix + "RequestHandler")); services.Configure(configuration.GetSection(Constants.Configuration.ConfigPrefix + "HealthChecks")); + services.Configure(configuration.GetSection(Constants.Configuration.ConfigPrefix + "Hosting")); + services.Configure(configuration.GetSection(Constants.Configuration.ConfigPrefix + "Imaging")); + services.Configure(configuration.GetSection(Constants.Configuration.ConfigPrefix + "Examine")); + services.Configure(configuration.GetSection(Constants.Configuration.ConfigPrefix + "KeepAlive")); + services.Configure(configuration.GetSection(Constants.Configuration.ConfigPrefix + "Logging")); + services.Configure(configuration.GetSection(Constants.Configuration.ConfigSecurityPrefix + "MemberPassword")); + services.Configure(configuration.GetSection(Constants.Configuration.ConfigGlobalPrefix + "ModelsBuilder")); + services.Configure(configuration.GetSection(Constants.Configuration.ConfigPrefix + "NuCache")); + services.Configure(configuration.GetSection(Constants.Configuration.ConfigPrefix + "RequestHandler")); + services.Configure(configuration.GetSection(Constants.Configuration.ConfigPrefix + "Runtime")); + services.Configure(configuration.GetSection(Constants.Configuration.ConfigSecurityPrefix)); + services.Configure(configuration.GetSection(Constants.Configuration.ConfigPrefix + "Tours")); + services.Configure(configuration.GetSection(Constants.Configuration.ConfigPrefix + "TypeFinder")); + services.Configure(configuration.GetSection(Constants.Configuration.ConfigSecurityPrefix + "UserPassword")); + services.Configure(configuration.GetSection(Constants.Configuration.ConfigPrefix + "WebRouting")); // TODO: remove this var configsFactory = new AspNetCoreConfigsFactory(configuration); diff --git a/src/Umbraco.Web.Common/Install/InstallController.cs b/src/Umbraco.Web.Common/Install/InstallController.cs index b5da8eabd4..d3c0e5e0f3 100644 --- a/src/Umbraco.Web.Common/Install/InstallController.cs +++ b/src/Umbraco.Web.Common/Install/InstallController.cs @@ -78,7 +78,7 @@ namespace Umbraco.Web.Common.Install { case ValidateRequestAttempt.FailedNoPrivileges: case ValidateRequestAttempt.FailedNoContextId: - return Redirect(_globalSettings.UmbracoPath + "/AuthorizeUpgrade?redir=" + Request.GetEncodedUrl()); + return Redirect(_globalSettings.Path + "/AuthorizeUpgrade?redir=" + Request.GetEncodedUrl()); } } @@ -86,7 +86,7 @@ namespace Umbraco.Web.Common.Install ViewData.SetInstallApiBaseUrl(Url.GetInstallerApiUrl()); // get the base umbraco folder - var baseFolder = _hostingEnvironment.ToAbsolute(_globalSettings.UmbracoPath); + var baseFolder = _hostingEnvironment.ToAbsolute(_globalSettings.Path); ViewData.SetUmbracoBaseFolder(baseFolder); ViewData.SetUmbracoVersion(_umbracoVersion.SemanticVersion); diff --git a/src/Umbraco.Web.Common/Macros/MacroRenderer.cs b/src/Umbraco.Web.Common/Macros/MacroRenderer.cs index c1fb033d20..58c1e59338 100644 --- a/src/Umbraco.Web.Common/Macros/MacroRenderer.cs +++ b/src/Umbraco.Web.Common/Macros/MacroRenderer.cs @@ -290,7 +290,7 @@ namespace Umbraco.Web.Macros Alias = macro.Alias, MacroSource = macro.MacroSource, Exception = e, - Behaviour = _contentSettings.MacroErrorBehaviour + Behaviour = _contentSettings.MacroErrors }; switch (macroErrorEventArgs.Behaviour) diff --git a/src/Umbraco.Web.Common/Security/WebSecurity.cs b/src/Umbraco.Web.Common/Security/WebSecurity.cs index b822adf656..0f3831b94c 100644 --- a/src/Umbraco.Web.Common/Security/WebSecurity.cs +++ b/src/Umbraco.Web.Common/Security/WebSecurity.cs @@ -115,7 +115,7 @@ namespace Umbraco.Web.Common.Security private static bool RequestIsInUmbracoApplication(IHttpContextAccessor httpContextAccessor, GlobalSettings globalSettings, IHostingEnvironment hostingEnvironment) { - return httpContextAccessor.GetRequiredHttpContext().Request.Path.ToString().IndexOf(hostingEnvironment.ToAbsolute(globalSettings.UmbracoPath), StringComparison.InvariantCultureIgnoreCase) > -1; + return httpContextAccessor.GetRequiredHttpContext().Request.Path.ToString().IndexOf(hostingEnvironment.ToAbsolute(globalSettings.Path), StringComparison.InvariantCultureIgnoreCase) > -1; } } } diff --git a/src/Umbraco.Web/Configuration/ConfigModelConversions.cs b/src/Umbraco.Web/Configuration/ConfigModelConversions.cs index b34ffb4def..7225c1c058 100644 --- a/src/Umbraco.Web/Configuration/ConfigModelConversions.cs +++ b/src/Umbraco.Web/Configuration/ConfigModelConversions.cs @@ -42,7 +42,7 @@ namespace Umbraco.Web.Configuration TimeOutInMinutes = globalSettings.TimeOutInMinutes, UmbracoCssPath = globalSettings.UmbracoCssPath, UmbracoMediaPath = globalSettings.UmbracoMediaPath, - UmbracoPath = globalSettings.UmbracoPath, + Path = globalSettings.UmbracoPath, UmbracoScriptsPath = globalSettings.UmbracoScriptsPath, UseHttps = globalSettings.UseHttps, VersionCheckPeriod = globalSettings.VersionCheckPeriod, From b4e01392d9bf3bb1c44da26fb9127230abc85f49 Mon Sep 17 00:00:00 2001 From: Andy Butland Date: Tue, 25 Aug 2020 11:00:11 +0200 Subject: [PATCH 276/826] Removed registration of old-style configuration in Netcore executable. --- .../Builders/RequestHandlerSettingsBuilder.cs | 9 ++++----- .../Builders/RequestHandlerSettingsBuilderTests.cs | 2 +- src/Umbraco.Tests/Configurations/GlobalSettingsTests.cs | 2 +- .../Strings/DefaultShortStringHelperTests.cs | 6 +++--- .../Extensions/UmbracoCoreServiceCollectionExtensions.cs | 5 ----- 5 files changed, 9 insertions(+), 15 deletions(-) diff --git a/src/Umbraco.Tests.Common/Builders/RequestHandlerSettingsBuilder.cs b/src/Umbraco.Tests.Common/Builders/RequestHandlerSettingsBuilder.cs index 33f63c9d16..3c6f652014 100644 --- a/src/Umbraco.Tests.Common/Builders/RequestHandlerSettingsBuilder.cs +++ b/src/Umbraco.Tests.Common/Builders/RequestHandlerSettingsBuilder.cs @@ -7,7 +7,7 @@ namespace Umbraco.Tests.Common.Builders public class RequestHandlerSettingsBuilder : BuilderBase { private bool? _addTrailingSlash; - private bool? _convertUrlsToAscii; + private string _convertUrlsToAscii; private IEnumerable _charCollection; public RequestHandlerSettingsBuilder WithAddTrailingSlash(bool addTrailingSlash) @@ -16,7 +16,7 @@ namespace Umbraco.Tests.Common.Builders return this; } - public RequestHandlerSettingsBuilder WithConvertUrlsToAscii(bool convertUrlsToAscii) + public RequestHandlerSettingsBuilder WithConvertUrlsToAscii(string convertUrlsToAscii) { _convertUrlsToAscii = convertUrlsToAscii; return this; @@ -26,13 +26,12 @@ namespace Umbraco.Tests.Common.Builders { _charCollection = charCollection; return this; - } - + } public override RequestHandlerSettings Build() { var addTrailingSlash = _addTrailingSlash ?? false; - var convertUrlsToAscii = _convertUrlsToAscii ?? false; + var convertUrlsToAscii = _convertUrlsToAscii ?? "false"; var charCollection = _charCollection ?? RequestHandlerSettings.DefaultCharCollection; return new RequestHandlerSettings diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Tests.Common/Builders/RequestHandlerSettingsBuilderTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Tests.Common/Builders/RequestHandlerSettingsBuilderTests.cs index af6bc0ed6f..8d84a6d4c6 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Tests.Common/Builders/RequestHandlerSettingsBuilderTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Tests.Common/Builders/RequestHandlerSettingsBuilderTests.cs @@ -15,7 +15,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Tests.Common.Builders { // Arrange const bool addTrailingSlash = true; - const bool convertUrlsToAscii = true; + const string convertUrlsToAscii = "try"; var charCollection = new List { new CharItem { Char = "a", Replacement = "b" } }; var builder = new RequestHandlerSettingsBuilder(); diff --git a/src/Umbraco.Tests/Configurations/GlobalSettingsTests.cs b/src/Umbraco.Tests/Configurations/GlobalSettingsTests.cs index fa6949cd09..cae2919621 100644 --- a/src/Umbraco.Tests/Configurations/GlobalSettingsTests.cs +++ b/src/Umbraco.Tests/Configurations/GlobalSettingsTests.cs @@ -25,7 +25,7 @@ namespace Umbraco.Tests.Configurations var hostingEnvironment = new AspNetHostingEnvironment(mockHostingSettings.Object); - var globalSettings = new GlobalSettingsBuilder().WithUmbracoPath(path).Build(); + var globalSettings = new GlobalSettingsBuilder().WithPath(path).Build(); Assert.AreEqual(outcome, globalSettings.GetUmbracoMvcAreaNoCache(hostingEnvironment)); } diff --git a/src/Umbraco.Tests/Strings/DefaultShortStringHelperTests.cs b/src/Umbraco.Tests/Strings/DefaultShortStringHelperTests.cs index 0def86e8d2..28d7d90f7e 100644 --- a/src/Umbraco.Tests/Strings/DefaultShortStringHelperTests.cs +++ b/src/Umbraco.Tests/Strings/DefaultShortStringHelperTests.cs @@ -98,7 +98,7 @@ namespace Umbraco.Tests.Strings public void U4_4056() { var requestHandlerSettings = new RequestHandlerSettingsBuilder() - .WithConvertUrlsToAscii(false) + .WithConvertUrlsToAscii("false") .WithCharCollection(Enumerable.Empty()) .Build(); @@ -123,7 +123,7 @@ namespace Umbraco.Tests.Strings public void U4_4056_TryAscii() { var requestHandlerSettings = new RequestHandlerSettingsBuilder() - .WithConvertUrlsToAscii(false) + .WithConvertUrlsToAscii("false") .WithCharCollection(Enumerable.Empty()) .Build(); @@ -411,7 +411,7 @@ namespace Umbraco.Tests.Strings var settings = _requestHandlerSettings; var contentMock = Mock.Get(settings); contentMock.Setup(x => x.CharCollection).Returns(Enumerable.Empty()); - contentMock.Setup(x => x.ConvertUrlsToAscii).Returns(false); + contentMock.Setup(x => x.ConvertUrlsToAscii).Returns("false"); var helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(settings)); diff --git a/src/Umbraco.Web.Common/Extensions/UmbracoCoreServiceCollectionExtensions.cs b/src/Umbraco.Web.Common/Extensions/UmbracoCoreServiceCollectionExtensions.cs index b5583f0b7e..b4911d6b59 100644 --- a/src/Umbraco.Web.Common/Extensions/UmbracoCoreServiceCollectionExtensions.cs +++ b/src/Umbraco.Web.Common/Extensions/UmbracoCoreServiceCollectionExtensions.cs @@ -127,11 +127,6 @@ namespace Umbraco.Extensions services.Configure(configuration.GetSection(Constants.Configuration.ConfigSecurityPrefix + "UserPassword")); services.Configure(configuration.GetSection(Constants.Configuration.ConfigPrefix + "WebRouting")); - // TODO: remove this - var configsFactory = new AspNetCoreConfigsFactory(configuration); - var configs = configsFactory.Create(); - services.AddSingleton(configs); - return services; } From 82416431834fef4a7a38c816b31ad070812402cb Mon Sep 17 00:00:00 2001 From: Andy Butland Date: Tue, 25 Aug 2020 12:30:43 +0200 Subject: [PATCH 277/826] Resolved various failing tests. --- src/Umbraco.Core/Composing/Composition.cs | 8 ++- .../Models/RequestHandlerSettings.cs | 2 +- .../ConfigModelConversionsFromLegacy.cs | 57 +++++++++++++++++++ .../ConfigModelConversionsToLegacy.cs} | 27 ++++++++- .../Models/ContentEditing/UserInvite.cs | 1 + .../Runtime/CoreRuntime.cs | 7 ++- .../ContainerTests.cs | 2 +- .../RequestHandlerSettingsBuilderTests.cs | 1 + .../Components/ComponentTests.cs | 28 ++++----- .../Composing/CollectionBuildersTests.cs | 2 +- .../Composing/CompositionTests.cs | 2 +- .../Composing/LazyCollectionBuilderTests.cs | 10 ++-- .../Composing/PackageActionCollectionTests.cs | 2 +- src/Umbraco.Tests/IO/FileSystemsTests.cs | 2 +- .../PropertyEditorValueEditorTests.cs | 2 +- .../Published/ConvertersTests.cs | 2 +- .../Routing/UmbracoModuleTests.cs | 20 ++----- src/Umbraco.Tests/Routing/UrlProviderTests.cs | 23 ++++---- .../Routing/UrlsProviderWithDomainsTests.cs | 17 +++--- .../Routing/UrlsWithNestedDomains.cs | 3 +- .../Runtimes/CoreRuntimeTests.cs | 6 +- src/Umbraco.Tests/Runtimes/StandaloneTests.cs | 4 +- .../Scoping/ScopeEventDispatcherTests.cs | 2 +- .../TestHelpers/BaseUsingSqlCeSyntax.cs | 2 +- src/Umbraco.Tests/Testing/UmbracoTestBase.cs | 25 ++++++-- src/Umbraco.Tests/Umbraco.Tests.csproj | 1 - .../UmbracoCoreServiceCollectionExtensions.cs | 5 ++ src/Umbraco.Web/AppBuilderExtensions.cs | 4 +- .../Compose/AuditEventsComponent.cs | 6 +- .../Configuration/ConfigModelConversions.cs | 47 +-------------- .../Editors/BackOfficeController.cs | 6 +- .../Editors/BackOfficeServerVariables.cs | 18 +++--- .../Mvc/AreaRegistrationExtensions.cs | 7 +-- src/Umbraco.Web/Mvc/BackOfficeArea.cs | 6 +- .../Mvc/UmbracoAuthorizeAttribute.cs | 6 +- .../Runtime/WebInitialComponent.cs | 9 +-- .../Security/BackOfficeOwinUserManager.cs | 3 +- .../Security/BackOfficeSignInManager.cs | 5 +- .../Security/GetUserSecondsMiddleWare.cs | 6 +- src/Umbraco.Web/UmbracoApplication.cs | 16 ++---- src/Umbraco.Web/UmbracoApplicationBase.cs | 11 ++-- src/Umbraco.Web/UmbracoContext.cs | 4 +- src/Umbraco.Web/UmbracoInjectedModule.cs | 13 ++--- .../CheckIfUserTicketDataIsStaleAttribute.cs | 11 ++-- 44 files changed, 234 insertions(+), 207 deletions(-) create mode 100644 src/Umbraco.Infrastructure/Configuration/ConfigModelConversionsFromLegacy.cs rename src/{Umbraco.Tests/TestHelpers/ConfigModelConversions.cs => Umbraco.Infrastructure/Configuration/ConfigModelConversionsToLegacy.cs} (80%) diff --git a/src/Umbraco.Core/Composing/Composition.cs b/src/Umbraco.Core/Composing/Composition.cs index 6989d4d0a2..e248d9eaf3 100644 --- a/src/Umbraco.Core/Composing/Composition.cs +++ b/src/Umbraco.Core/Composing/Composition.cs @@ -28,14 +28,16 @@ namespace Umbraco.Core.Composing /// A type loader. /// A logger. /// The runtime state. + /// Optional configs. /// An IOHelper /// - public Composition(IRegister register, TypeLoader typeLoader, IProfilingLogger logger, IRuntimeState runtimeState, IIOHelper ioHelper, AppCaches appCaches) + public Composition(IRegister register, TypeLoader typeLoader, IProfilingLogger logger, IRuntimeState runtimeState, Configs configs, IIOHelper ioHelper, AppCaches appCaches) { _register = register ?? throw new ArgumentNullException(nameof(register)); TypeLoader = typeLoader ?? throw new ArgumentNullException(nameof(typeLoader)); Logger = logger ?? throw new ArgumentNullException(nameof(logger)); RuntimeState = runtimeState ?? throw new ArgumentNullException(nameof(runtimeState)); + Configs = configs ?? throw new ArgumentNullException(nameof(configs)); IOHelper = ioHelper ?? throw new ArgumentNullException(nameof(ioHelper)); AppCaches = appCaches ?? throw new ArgumentNullException(nameof(appCaches)); } @@ -60,6 +62,7 @@ namespace Umbraco.Core.Composing /// public IRuntimeState RuntimeState { get; } + // TODO: remove this once no longer required for functionality in Umbraco.Web. /// /// Gets the configurations. /// @@ -133,8 +136,7 @@ namespace Umbraco.Core.Composing IFactory factory = null; - // TODO: what to do about this? - //Configs.RegisterWith(_register); + Configs.RegisterWith(_register); // ReSharper disable once AccessToModifiedClosure -- on purpose _register.Register(_ => factory, Lifetime.Singleton); diff --git a/src/Umbraco.Core/Configuration/Models/RequestHandlerSettings.cs b/src/Umbraco.Core/Configuration/Models/RequestHandlerSettings.cs index a2422fc899..d7203b4901 100644 --- a/src/Umbraco.Core/Configuration/Models/RequestHandlerSettings.cs +++ b/src/Umbraco.Core/Configuration/Models/RequestHandlerSettings.cs @@ -59,7 +59,7 @@ namespace Umbraco.Core.Configuration.Models //} // return DefaultCharCollection; - public IEnumerable CharCollection { get; set; } + public IEnumerable CharCollection { get; set; } = DefaultCharCollection; public class CharItem : IChar { diff --git a/src/Umbraco.Infrastructure/Configuration/ConfigModelConversionsFromLegacy.cs b/src/Umbraco.Infrastructure/Configuration/ConfigModelConversionsFromLegacy.cs new file mode 100644 index 0000000000..42ed290e63 --- /dev/null +++ b/src/Umbraco.Infrastructure/Configuration/ConfigModelConversionsFromLegacy.cs @@ -0,0 +1,57 @@ +using Umbraco.Core; +using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; + +namespace Umbraco.Infrastructure.Configuration +{ + /// + /// TEMPORARY: this class has been added just to ensure Umbraco.Web functionality continues to compile, by + /// converting between e.g. (used by + /// legacy configuration and (used by Netcore/IOptions configuration). + /// + public static class ConfigModelConversionsFromLegacy + { + public static GlobalSettings ConvertGlobalSettings(IGlobalSettings globalSettings) + { + return new GlobalSettings + { + DatabaseFactoryServerVersion = globalSettings.DatabaseFactoryServerVersion, + DefaultUILanguage = globalSettings.DefaultUILanguage, + DisableElectionForSingleServer = globalSettings.DisableElectionForSingleServer, + HideTopLevelNodeFromPath = globalSettings.HideTopLevelNodeFromPath, + InstallEmptyDatabase = globalSettings.InstallEmptyDatabase, + InstallMissingDatabase = globalSettings.InstallMissingDatabase, + MainDomLock = globalSettings.MainDomLock, + NoNodesViewPath = globalSettings.NoNodesViewPath, + RegisterType = globalSettings.RegisterType, + ReservedPaths = globalSettings.ReservedPaths, + ReservedUrls = globalSettings.ReservedUrls, + Smtp = new SmtpSettings + { + DeliveryMethod = globalSettings.SmtpSettings.DeliveryMethod, + From = globalSettings.SmtpSettings.From, + Host = globalSettings.SmtpSettings.Host, + Password = globalSettings.SmtpSettings.Password, + PickupDirectoryLocation = globalSettings.SmtpSettings.PickupDirectoryLocation, + Port = globalSettings.SmtpSettings.Port, + Username = globalSettings.SmtpSettings.Username, + }, + TimeOutInMinutes = globalSettings.TimeOutInMinutes, + UmbracoCssPath = globalSettings.UmbracoCssPath, + UmbracoMediaPath = globalSettings.UmbracoMediaPath, + Path = globalSettings.UmbracoPath, + UmbracoScriptsPath = globalSettings.UmbracoScriptsPath, + UseHttps = globalSettings.UseHttps, + VersionCheckPeriod = globalSettings.VersionCheckPeriod, + }; + } + + public static ConnectionStrings ConvertConnectionStrings(IConnectionStrings connectionStrings) + { + return new ConnectionStrings + { + UmbracoConnectionString = connectionStrings[Constants.System.UmbracoConnectionName].ConnectionString + }; + } + } +} diff --git a/src/Umbraco.Tests/TestHelpers/ConfigModelConversions.cs b/src/Umbraco.Infrastructure/Configuration/ConfigModelConversionsToLegacy.cs similarity index 80% rename from src/Umbraco.Tests/TestHelpers/ConfigModelConversions.cs rename to src/Umbraco.Infrastructure/Configuration/ConfigModelConversionsToLegacy.cs index 5417116713..5b3607992c 100644 --- a/src/Umbraco.Tests/TestHelpers/ConfigModelConversions.cs +++ b/src/Umbraco.Infrastructure/Configuration/ConfigModelConversionsToLegacy.cs @@ -1,15 +1,17 @@ -using System.Net.Mail; +using System.Collections.Generic; +using System.Net.Mail; +using Umbraco.Core; using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.Models; -namespace Umbraco.Tests.TestHelpers +namespace Umbraco.Infrastructure.Configuration { /// /// TEMPORARY: this class has been added just to ensure tests on Umbraco.Web functionality, that still use the interface /// based configuration, by converting between e.g (used by /// legacy configuration and (used by Netcore/IOptions configuration). /// - public static class ConfigModelConversions + public static class ConfigModelConversionsToLegacy { public static IGlobalSettings ConvertGlobalSettings(GlobalSettings globalSettings) { @@ -46,6 +48,13 @@ namespace Umbraco.Tests.TestHelpers }; } + public static IConnectionStrings ConvertConnectionStrings(ConnectionStrings connectionStrings) + { + var result = new TestConnectionStrings(); + result.AddEntry(Constants.System.UmbracoConnectionName, connectionStrings.UmbracoConnectionString); + return result; + } + private class TestGlobalSettings : IGlobalSettings { public string ReservedUrls { get; set; } @@ -105,5 +114,17 @@ namespace Umbraco.Tests.TestHelpers public string Password { get; set; } } + + private class TestConnectionStrings : IConnectionStrings + { + private IDictionary _dictionary = new Dictionary(); + + public ConfigConnectionString this[string key] => _dictionary[key]; + + public void AddEntry(string key, string connectionString) + { + _dictionary.Add(key, new ConfigConnectionString(connectionString, string.Empty, key)); + } + } } } diff --git a/src/Umbraco.Infrastructure/Models/ContentEditing/UserInvite.cs b/src/Umbraco.Infrastructure/Models/ContentEditing/UserInvite.cs index 06e4d0748c..428f85937b 100644 --- a/src/Umbraco.Infrastructure/Models/ContentEditing/UserInvite.cs +++ b/src/Umbraco.Infrastructure/Models/ContentEditing/UserInvite.cs @@ -33,6 +33,7 @@ namespace Umbraco.Web.Models.ContentEditing if (UserGroups.Any() == false) yield return new ValidationResult("A user must be assigned to at least one group", new[] { nameof(UserGroups) }); + // TODO: this will need another way of retrieving this setting if and when Configs are removed from Current. if (Current.Configs.Security().UsernameIsEmail == false && Username.IsNullOrWhiteSpace()) yield return new ValidationResult("A username cannot be empty", new[] { nameof(Username) }); } diff --git a/src/Umbraco.Infrastructure/Runtime/CoreRuntime.cs b/src/Umbraco.Infrastructure/Runtime/CoreRuntime.cs index ad036e12eb..968c240d62 100644 --- a/src/Umbraco.Infrastructure/Runtime/CoreRuntime.cs +++ b/src/Umbraco.Infrastructure/Runtime/CoreRuntime.cs @@ -12,6 +12,7 @@ using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Persistence; using Umbraco.Core.Persistence.Mappers; +using Umbraco.Infrastructure.Configuration; namespace Umbraco.Core.Runtime { @@ -179,7 +180,11 @@ namespace Umbraco.Core.Runtime var typeLoader = new TypeLoader(TypeFinder, appCaches.RuntimeCache, new DirectoryInfo(HostingEnvironment.LocalTempPath), ProfilingLogger); // create the composition - composition = new Composition(register, typeLoader, ProfilingLogger, _state, IOHelper, appCaches); + // TODO: remove the configs parameter once we no longer need to provide it for Umbraco.Web and Umbraco.Tests functionality. + var configs = new Configs(); + configs.Add(() => ConfigModelConversionsToLegacy.ConvertGlobalSettings(_globalSettings)); + configs.Add(() => ConfigModelConversionsToLegacy.ConvertConnectionStrings(_connectionStrings)); + composition = new Composition(register, typeLoader, ProfilingLogger, _state, configs, IOHelper, appCaches); composition.RegisterEssentials(Logger, Profiler, ProfilingLogger, MainDom, appCaches, databaseFactory, typeLoader, _state, TypeFinder, IOHelper, UmbracoVersion, DbProviderFactoryCreator, HostingEnvironment, BackOfficeInfo); // register ourselves (TODO: Should we put this in RegisterEssentials?) diff --git a/src/Umbraco.Tests.Integration/ContainerTests.cs b/src/Umbraco.Tests.Integration/ContainerTests.cs index a50a24e780..2098b7241e 100644 --- a/src/Umbraco.Tests.Integration/ContainerTests.cs +++ b/src/Umbraco.Tests.Integration/ContainerTests.cs @@ -44,7 +44,7 @@ namespace Umbraco.Tests.Integration // Register in the container var composition = new Composition(umbracoContainer, typeLoader, - testHelper.Logger, runtimeState, testHelper.IOHelper, testHelper.AppCaches); + testHelper.Logger, runtimeState, testHelper.GetConfigs(), testHelper.IOHelper, testHelper.AppCaches); composition.RegisterEssentials(testHelper.Logger, testHelper.Profiler, testHelper.Logger, testHelper.MainDom, testHelper.AppCaches, umbracoDatabaseFactory, typeLoader, runtimeState, testHelper.GetTypeFinder(), testHelper.IOHelper, testHelper.GetUmbracoVersion(), dbProviderFactoryCreator, diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Tests.Common/Builders/RequestHandlerSettingsBuilderTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Tests.Common/Builders/RequestHandlerSettingsBuilderTests.cs index 8d84a6d4c6..199b3dadde 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Tests.Common/Builders/RequestHandlerSettingsBuilderTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Tests.Common/Builders/RequestHandlerSettingsBuilderTests.cs @@ -24,6 +24,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Tests.Common.Builders var requestHandlerSettings = builder .WithAddTrailingSlash(addTrailingSlash) .WithConvertUrlsToAscii(convertUrlsToAscii) + .WithCharCollection(charCollection) .Build(); // Assert diff --git a/src/Umbraco.Tests/Components/ComponentTests.cs b/src/Umbraco.Tests/Components/ComponentTests.cs index 6f86108edb..4ce790db6c 100644 --- a/src/Umbraco.Tests/Components/ComponentTests.cs +++ b/src/Umbraco.Tests/Components/ComponentTests.cs @@ -75,7 +75,7 @@ namespace Umbraco.Tests.Components { var register = MockRegister(); var typeLoader = MockTypeLoader(); - var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Unknown), TestHelper.IOHelper, AppCaches.NoCache); + var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Unknown), TestHelper.GetConfigs(), TestHelper.IOHelper, AppCaches.NoCache); var types = TypeArray(); var composers = new Composers(composition, types, Enumerable.Empty(), Mock.Of()); @@ -114,7 +114,7 @@ namespace Umbraco.Tests.Components public void Boot1B() { var register = MockRegister(); - var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Run), TestHelper.IOHelper, AppCaches.NoCache); + var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Run), TestHelper.GetConfigs(), TestHelper.IOHelper, AppCaches.NoCache); var types = TypeArray(); var composers = new Composers(composition, types, Enumerable.Empty(), Mock.Of()); @@ -130,7 +130,7 @@ namespace Umbraco.Tests.Components public void Boot2() { var register = MockRegister(); - var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Unknown), TestHelper.IOHelper, AppCaches.NoCache); + var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Unknown), TestHelper.GetConfigs(), TestHelper.IOHelper, AppCaches.NoCache); var types = TypeArray(); var composers = new Composers(composition, types, Enumerable.Empty(), Mock.Of()); @@ -145,7 +145,7 @@ namespace Umbraco.Tests.Components public void Boot3() { var register = MockRegister(); - var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Unknown), TestHelper.IOHelper, AppCaches.NoCache); + var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Unknown), TestHelper.GetConfigs(), TestHelper.IOHelper, AppCaches.NoCache); var types = TypeArray(); var composers = new Composers(composition, types, Enumerable.Empty(), Mock.Of()); @@ -162,7 +162,7 @@ namespace Umbraco.Tests.Components public void BrokenRequire() { var register = MockRegister(); - var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Unknown), TestHelper.IOHelper, AppCaches.NoCache); + var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Unknown), TestHelper.GetConfigs(), TestHelper.IOHelper, AppCaches.NoCache); var types = TypeArray(); var composers = new Composers(composition, types, Enumerable.Empty(), Mock.Of()); @@ -185,7 +185,7 @@ namespace Umbraco.Tests.Components public void BrokenRequired() { var register = MockRegister(); - var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Unknown), TestHelper.IOHelper, AppCaches.NoCache); + var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Unknown), TestHelper.GetConfigs(), TestHelper.IOHelper, AppCaches.NoCache); var types = TypeArray(); var composers = new Composers(composition, types, Enumerable.Empty(), Mock.Of()); @@ -221,7 +221,7 @@ namespace Umbraco.Tests.Components throw new NotSupportedException(type.FullName); }); }); - var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Unknown), TestHelper.IOHelper, AppCaches.NoCache); + var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Unknown), TestHelper.GetConfigs(), TestHelper.IOHelper, AppCaches.NoCache); var types = new[] { typeof(Composer1), typeof(Composer5), typeof(Composer5a) }; var composers = new Composers(composition, types, Enumerable.Empty(), Mock.Of()); @@ -247,7 +247,7 @@ namespace Umbraco.Tests.Components public void Requires1() { var register = MockRegister(); - var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Unknown), TestHelper.IOHelper, AppCaches.NoCache); + var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Unknown), TestHelper.GetConfigs(), TestHelper.IOHelper, AppCaches.NoCache); var types = new[] { typeof(Composer6), typeof(Composer7), typeof(Composer8) }; var composers = new Composers(composition, types, Enumerable.Empty(), Mock.Of()); @@ -262,7 +262,7 @@ namespace Umbraco.Tests.Components public void Requires2A() { var register = MockRegister(); - var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Unknown), TestHelper.IOHelper, AppCaches.NoCache); + var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Unknown), TestHelper.GetConfigs(), TestHelper.IOHelper, AppCaches.NoCache); var types = new[] { typeof(Composer9), typeof(Composer2), typeof(Composer4) }; var composers = new Composers(composition, types, Enumerable.Empty(), Mock.Of()); @@ -280,7 +280,7 @@ namespace Umbraco.Tests.Components var register = MockRegister(); var typeLoader = MockTypeLoader(); var factory = MockFactory(); - var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Run), TestHelper.IOHelper, AppCaches.NoCache); + var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Run), TestHelper.GetConfigs(), TestHelper.IOHelper, AppCaches.NoCache); var types = new[] { typeof(Composer9), typeof(Composer2), typeof(Composer4) }; var composers = new Composers(composition, types, Enumerable.Empty(), Mock.Of()); @@ -299,7 +299,7 @@ namespace Umbraco.Tests.Components public void WeakDependencies() { var register = MockRegister(); - var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Unknown), TestHelper.IOHelper, AppCaches.NoCache); + var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Unknown), TestHelper.GetConfigs(), TestHelper.IOHelper, AppCaches.NoCache); var types = new[] { typeof(Composer10) }; var composers = new Composers(composition, types, Enumerable.Empty(), Mock.Of()); @@ -338,7 +338,7 @@ namespace Umbraco.Tests.Components public void DisableMissing() { var register = MockRegister(); - var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Unknown), TestHelper.IOHelper, AppCaches.NoCache); + var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Unknown), TestHelper.GetConfigs(), TestHelper.IOHelper, AppCaches.NoCache); var types = new[] { typeof(Composer6), typeof(Composer8) }; // 8 disables 7 which is not in the list var composers = new Composers(composition, types, Enumerable.Empty(), Mock.Of()); @@ -353,7 +353,7 @@ namespace Umbraco.Tests.Components public void AttributesPriorities() { var register = MockRegister(); - var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Unknown), TestHelper.IOHelper, AppCaches.NoCache); + var composition = new Composition(register, MockTypeLoader(), Mock.Of(), MockRuntimeState(RuntimeLevel.Unknown), TestHelper.GetConfigs(), TestHelper.IOHelper, AppCaches.NoCache); var types = new[] { typeof(Composer26) }; var enableDisableAttributes = new[] { new DisableComposerAttribute(typeof(Composer26)) }; @@ -380,7 +380,7 @@ namespace Umbraco.Tests.Components var register = MockRegister(); var composition = new Composition(register, typeLoader, Mock.Of(), - MockRuntimeState(RuntimeLevel.Run), TestHelper.IOHelper, AppCaches.NoCache); + MockRuntimeState(RuntimeLevel.Run), TestHelper.GetConfigs(), TestHelper.IOHelper, AppCaches.NoCache); var allComposers = typeLoader.GetTypes().ToList(); var types = allComposers.Where(x => x.FullName.StartsWith("Umbraco.Core.") || x.FullName.StartsWith("Umbraco.Web")).ToList(); diff --git a/src/Umbraco.Tests/Composing/CollectionBuildersTests.cs b/src/Umbraco.Tests/Composing/CollectionBuildersTests.cs index 4416723a55..2d977e89c7 100644 --- a/src/Umbraco.Tests/Composing/CollectionBuildersTests.cs +++ b/src/Umbraco.Tests/Composing/CollectionBuildersTests.cs @@ -24,7 +24,7 @@ namespace Umbraco.Tests.Composing Current.Reset(); var register = TestHelper.GetRegister(); - _composition = new Composition(register, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.IOHelper, AppCaches.NoCache); + _composition = new Composition(register, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.GetConfigs(), TestHelper.IOHelper, AppCaches.NoCache); } [TearDown] diff --git a/src/Umbraco.Tests/Composing/CompositionTests.cs b/src/Umbraco.Tests/Composing/CompositionTests.cs index 229ba1102b..380511eaaa 100644 --- a/src/Umbraco.Tests/Composing/CompositionTests.cs +++ b/src/Umbraco.Tests/Composing/CompositionTests.cs @@ -41,7 +41,7 @@ namespace Umbraco.Tests.Composing var typeFinder = TestHelper.GetTypeFinder(); var ioHelper = TestHelper.IOHelper; var typeLoader = new TypeLoader(typeFinder, Mock.Of(), new DirectoryInfo(ioHelper.MapPath("~/App_Data/TEMP")), logger); - var composition = new Composition(mockedRegister, typeLoader, logger, Mock.Of(), TestHelper.IOHelper, AppCaches.NoCache); + var composition = new Composition(mockedRegister, typeLoader, logger, Mock.Of(), TestHelper.GetConfigs(), TestHelper.IOHelper, AppCaches.NoCache); // create the factory, ensure it is the mocked factory var factory = composition.CreateFactory(); diff --git a/src/Umbraco.Tests/Composing/LazyCollectionBuilderTests.cs b/src/Umbraco.Tests/Composing/LazyCollectionBuilderTests.cs index c17e80a34a..4d0135d6c4 100644 --- a/src/Umbraco.Tests/Composing/LazyCollectionBuilderTests.cs +++ b/src/Umbraco.Tests/Composing/LazyCollectionBuilderTests.cs @@ -41,7 +41,7 @@ namespace Umbraco.Tests.Composing public void LazyCollectionBuilderHandlesTypes() { var container = CreateRegister(); - var composition = new Composition(container, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.IOHelper, AppCaches.NoCache); + var composition = new Composition(container, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.GetConfigs(), TestHelper.IOHelper, AppCaches.NoCache); composition.WithCollectionBuilder() .Add() @@ -67,7 +67,7 @@ namespace Umbraco.Tests.Composing public void LazyCollectionBuilderHandlesProducers() { var container = CreateRegister(); - var composition = new Composition(container, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.IOHelper, AppCaches.NoCache); + var composition = new Composition(container, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.GetConfigs(), TestHelper.IOHelper, AppCaches.NoCache); composition.WithCollectionBuilder() .Add(() => new[] { typeof(TransientObject3), typeof(TransientObject2) }) @@ -92,7 +92,7 @@ namespace Umbraco.Tests.Composing public void LazyCollectionBuilderHandlesTypesAndProducers() { var container = CreateRegister(); - var composition = new Composition(container, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.IOHelper, AppCaches.NoCache); + var composition = new Composition(container, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.GetConfigs(), TestHelper.IOHelper, AppCaches.NoCache); composition.WithCollectionBuilder() .Add() @@ -118,7 +118,7 @@ namespace Umbraco.Tests.Composing public void LazyCollectionBuilderThrowsOnIllegalTypes() { var container = CreateRegister(); - var composition = new Composition(container, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.IOHelper, AppCaches.NoCache); + var composition = new Composition(container, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.GetConfigs(), TestHelper.IOHelper, AppCaches.NoCache); composition.WithCollectionBuilder() .Add() @@ -140,7 +140,7 @@ namespace Umbraco.Tests.Composing public void LazyCollectionBuilderCanExcludeTypes() { var container = CreateRegister(); - var composition = new Composition(container, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.IOHelper, AppCaches.NoCache); + var composition = new Composition(container, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.GetConfigs(), TestHelper.IOHelper, AppCaches.NoCache); composition.WithCollectionBuilder() .Add() diff --git a/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs b/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs index 118eaab41a..390997173b 100644 --- a/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs +++ b/src/Umbraco.Tests/Composing/PackageActionCollectionTests.cs @@ -22,7 +22,7 @@ namespace Umbraco.Tests.Composing { var container = TestHelper.GetRegister(); - var composition = new Composition(container, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.IOHelper, AppCaches.NoCache); + var composition = new Composition(container, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.GetConfigs(), TestHelper.IOHelper, AppCaches.NoCache); var expectedPackageActions = TypeLoader.GetPackageActions(); composition.WithCollectionBuilder() diff --git a/src/Umbraco.Tests/IO/FileSystemsTests.cs b/src/Umbraco.Tests/IO/FileSystemsTests.cs index 71dd954052..c1d3fbb331 100644 --- a/src/Umbraco.Tests/IO/FileSystemsTests.cs +++ b/src/Umbraco.Tests/IO/FileSystemsTests.cs @@ -30,7 +30,7 @@ namespace Umbraco.Tests.IO { _register = TestHelper.GetRegister(); - var composition = new Composition(_register, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.IOHelper, AppCaches.NoCache); + var composition = new Composition(_register, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.GetConfigs(), TestHelper.IOHelper, AppCaches.NoCache); composition.Register(_ => Mock.Of()); composition.Register(_ => Mock.Of()); diff --git a/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueEditorTests.cs b/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueEditorTests.cs index 439036fa16..d2d8cb952b 100644 --- a/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueEditorTests.cs +++ b/src/Umbraco.Tests/PropertyEditors/PropertyEditorValueEditorTests.cs @@ -26,7 +26,7 @@ namespace Umbraco.Tests.PropertyEditors Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture; var register = TestHelper.GetRegister(); - var composition = new Composition(register, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.IOHelper, AppCaches.NoCache); + var composition = new Composition(register, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.GetConfigs(), TestHelper.IOHelper, AppCaches.NoCache); var requestHandlerSettings = new RequestHandlerSettingsBuilder().Build(); register.Register(_ diff --git a/src/Umbraco.Tests/Published/ConvertersTests.cs b/src/Umbraco.Tests/Published/ConvertersTests.cs index 2ae4c238cc..3ecae51ea8 100644 --- a/src/Umbraco.Tests/Published/ConvertersTests.cs +++ b/src/Umbraco.Tests/Published/ConvertersTests.cs @@ -182,7 +182,7 @@ namespace Umbraco.Tests.Published // Current.Reset(); var register = TestHelper.GetRegister(); - var composition = new Composition(register, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.IOHelper, AppCaches.NoCache); + var composition = new Composition(register, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.GetConfigs(), TestHelper.IOHelper, AppCaches.NoCache); composition.WithCollectionBuilder() .Append() diff --git a/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs b/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs index 252e03f4c0..87d63f3d8f 100644 --- a/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs +++ b/src/Umbraco.Tests/Routing/UmbracoModuleTests.cs @@ -1,23 +1,13 @@ using System; -using System.IO; using System.Threading; using Moq; using NUnit.Framework; using Umbraco.Core; -using Umbraco.Core.Composing; +using Umbraco.Core.Logging; +using Umbraco.Infrastructure.Configuration; +using Umbraco.Tests.Common.Builders; using Umbraco.Tests.TestHelpers; using Umbraco.Web; -using Umbraco.Core.IO; -using Umbraco.Core.Logging; -using Umbraco.Core.Sync; -using Umbraco.Core.Configuration.UmbracoSettings; -using Umbraco.Core.Models.PublishedContent; -using Umbraco.Core.Services; -using Umbraco.Web.PublishedCache; -using Umbraco.Web.Routing; -using Umbraco.Web.Configuration; -using ConfigModelConversions = Umbraco.Tests.TestHelpers.ConfigModelConversions; -using Umbraco.Tests.Common.Builders; namespace Umbraco.Tests.Routing { @@ -43,10 +33,10 @@ namespace Umbraco.Tests.Routing logger, null, // FIXME: PublishedRouter complexities... Mock.Of(), - new RoutableDocumentFilter(ConfigModelConversions.ConvertGlobalSettings(globalSettings), IOHelper), + new RoutableDocumentFilter(ConfigModelConversionsToLegacy.ConvertGlobalSettings(globalSettings), IOHelper), UriUtility, AppCaches.RequestCache, - ConfigModelConversions.ConvertGlobalSettings(globalSettings), + ConfigModelConversionsToLegacy.ConvertGlobalSettings(globalSettings), HostingEnvironment ); diff --git a/src/Umbraco.Tests/Routing/UrlProviderTests.cs b/src/Umbraco.Tests/Routing/UrlProviderTests.cs index d7a6cc701a..b84bf41bee 100644 --- a/src/Umbraco.Tests/Routing/UrlProviderTests.cs +++ b/src/Umbraco.Tests/Routing/UrlProviderTests.cs @@ -5,10 +5,11 @@ using System.Linq; using Moq; using NUnit.Framework; using Umbraco.Core; -using Umbraco.Web.Composing; -using Umbraco.Core.Configuration; using Umbraco.Core.Models; using Umbraco.Core.Models.PublishedContent; +using Umbraco.Infrastructure.Configuration; +using Umbraco.Tests.Common; +using Umbraco.Tests.Common.Builders; using Umbraco.Tests.LegacyXmlPublishedCache; using Umbraco.Tests.PublishedContent; using Umbraco.Tests.TestHelpers; @@ -16,8 +17,6 @@ using Umbraco.Tests.Testing; using Umbraco.Web; using Umbraco.Web.PublishedCache; using Umbraco.Web.Routing; -using Umbraco.Tests.Common; -using Umbraco.Tests.Common.Builders; namespace Umbraco.Tests.Routing { @@ -50,7 +49,7 @@ namespace Umbraco.Tests.Routing var requestHandlerSettings = new RequestHandlerSettingsBuilder().Build(); - var umbracoContext = GetUmbracoContext("/test", 1111, globalSettings: ConfigModelConversions.ConvertGlobalSettings(globalSettings)); + var umbracoContext = GetUmbracoContext("/test", 1111, globalSettings: ConfigModelConversionsToLegacy.ConvertGlobalSettings(globalSettings)); var umbracoContextAccessor = new TestUmbracoContextAccessor(umbracoContext); var urlProvider = new DefaultUrlProvider( Microsoft.Extensions.Options.Options.Create(requestHandlerSettings), @@ -127,7 +126,7 @@ namespace Umbraco.Tests.Routing var requestHandlerSettings = new RequestHandlerSettingsBuilder().Build(); - var umbracoContext = GetUmbracoContext("/test", 1111, globalSettings: ConfigModelConversions.ConvertGlobalSettings(globalSettings)); + var umbracoContext = GetUmbracoContext("/test", 1111, globalSettings: ConfigModelConversionsToLegacy.ConvertGlobalSettings(globalSettings)); var umbracoContextAccessor = new TestUmbracoContextAccessor(umbracoContext); var urlProvider = new DefaultUrlProvider( Microsoft.Extensions.Options.Options.Create(requestHandlerSettings), @@ -156,7 +155,7 @@ namespace Umbraco.Tests.Routing var globalSettings = new GlobalSettingsBuilder().WithHideTopLevelNodeFromPath(true).Build(); var requestHandlerSettings = new RequestHandlerSettingsBuilder().Build(); - var umbracoContext = GetUmbracoContext("/test", 1111, globalSettings: ConfigModelConversions.ConvertGlobalSettings(globalSettings)); + var umbracoContext = GetUmbracoContext("/test", 1111, globalSettings: ConfigModelConversionsToLegacy.ConvertGlobalSettings(globalSettings)); var umbracoContextAccessor = new TestUmbracoContextAccessor(umbracoContext); var urlProvider = new DefaultUrlProvider( Microsoft.Extensions.Options.Options.Create(requestHandlerSettings), @@ -198,7 +197,7 @@ namespace Umbraco.Tests.Routing .Returns(snapshot); var umbracoContext = GetUmbracoContext(currentUri, - globalSettings: ConfigModelConversions.ConvertGlobalSettings(globalSettings), + globalSettings: ConfigModelConversionsToLegacy.ConvertGlobalSettings(globalSettings), snapshotService: snapshotService.Object); var umbracoContextAccessor = new TestUmbracoContextAccessor(umbracoContext); var urlProvider = new DefaultUrlProvider( @@ -255,7 +254,7 @@ namespace Umbraco.Tests.Routing .Returns(snapshot); var umbracoContext = GetUmbracoContext(currentUri, - globalSettings: ConfigModelConversions.ConvertGlobalSettings(globalSettings), + globalSettings: ConfigModelConversionsToLegacy.ConvertGlobalSettings(globalSettings), snapshotService: snapshotService.Object); var umbracoContextAccessor = new TestUmbracoContextAccessor(umbracoContext); var urlProvider = new DefaultUrlProvider( @@ -312,7 +311,7 @@ namespace Umbraco.Tests.Routing .Returns(snapshot); var umbracoContext = GetUmbracoContext(currentUri, - globalSettings: ConfigModelConversions.ConvertGlobalSettings(globalSettings), + globalSettings: ConfigModelConversionsToLegacy.ConvertGlobalSettings(globalSettings), snapshotService: snapshotService.Object); var umbracoContextAccessor = new TestUmbracoContextAccessor(umbracoContext); var urlProvider = new DefaultUrlProvider( @@ -336,7 +335,7 @@ namespace Umbraco.Tests.Routing var requestHandlerSettings = new RequestHandlerSettingsBuilder().Build(); - var umbracoContext = GetUmbracoContext("http://example.com/test", 1111, globalSettings: ConfigModelConversions.ConvertGlobalSettings(globalSettings)); + var umbracoContext = GetUmbracoContext("http://example.com/test", 1111, globalSettings: ConfigModelConversionsToLegacy.ConvertGlobalSettings(globalSettings)); var umbracoContextAccessor = new TestUmbracoContextAccessor(umbracoContext); var urlProvider = new DefaultUrlProvider( Microsoft.Extensions.Options.Options.Create(requestHandlerSettings), @@ -362,7 +361,7 @@ namespace Umbraco.Tests.Routing Logger, Microsoft.Extensions.Options.Options.Create(globalSettings), new SiteDomainHelper(), UmbracoContextAccessor, UriUtility); - var umbracoContext = GetUmbracoContext("http://example.com/test", 1111, globalSettings: ConfigModelConversions.ConvertGlobalSettings(globalSettings)); + var umbracoContext = GetUmbracoContext("http://example.com/test", 1111, globalSettings: ConfigModelConversionsToLegacy.ConvertGlobalSettings(globalSettings)); var publishedUrlProvider = GetPublishedUrlProvider(umbracoContext, urlProvider); //mock the Umbraco settings that we need diff --git a/src/Umbraco.Tests/Routing/UrlsProviderWithDomainsTests.cs b/src/Umbraco.Tests/Routing/UrlsProviderWithDomainsTests.cs index 79813e662c..0998f1e722 100644 --- a/src/Umbraco.Tests/Routing/UrlsProviderWithDomainsTests.cs +++ b/src/Umbraco.Tests/Routing/UrlsProviderWithDomainsTests.cs @@ -4,14 +4,13 @@ using System.Linq; using Moq; using NUnit.Framework; using Umbraco.Core; -using Umbraco.Core.Configuration; using Umbraco.Core.Models; using Umbraco.Core.Models.PublishedContent; using Umbraco.Core.Services; +using Umbraco.Infrastructure.Configuration; using Umbraco.Tests.Common; using Umbraco.Tests.Common.Builders; using Umbraco.Tests.LegacyXmlPublishedCache; -using Umbraco.Tests.TestHelpers; using Umbraco.Web; using Umbraco.Web.Routing; @@ -183,7 +182,7 @@ namespace Umbraco.Tests.Routing var globalSettings = new GlobalSettingsBuilder().WithHideTopLevelNodeFromPath(false).Build(); - var umbracoContext = GetUmbracoContext("/test", 1111, globalSettings: ConfigModelConversions.ConvertGlobalSettings(globalSettings)); + var umbracoContext = GetUmbracoContext("/test", 1111, globalSettings: ConfigModelConversionsToLegacy.ConvertGlobalSettings(globalSettings)); var umbracoContextAccessor = new TestUmbracoContextAccessor(umbracoContext); var urlProvider = new DefaultUrlProvider(Microsoft.Extensions.Options.Options.Create(requestHandlerSettings), Logger, @@ -217,7 +216,7 @@ namespace Umbraco.Tests.Routing var requestHandlerSettings = new RequestHandlerSettingsBuilder().Build(); var globalSettings = new GlobalSettingsBuilder().WithHideTopLevelNodeFromPath(false).Build(); - var umbracoContext = GetUmbracoContext("/test", 1111, globalSettings: ConfigModelConversions.ConvertGlobalSettings(globalSettings)); + var umbracoContext = GetUmbracoContext("/test", 1111, globalSettings: ConfigModelConversionsToLegacy.ConvertGlobalSettings(globalSettings)); var umbracoContextAccessor = new TestUmbracoContextAccessor(umbracoContext); var urlProvider = new DefaultUrlProvider(Microsoft.Extensions.Options.Options.Create(requestHandlerSettings), Logger, @@ -244,7 +243,7 @@ namespace Umbraco.Tests.Routing var globalSettings = new GlobalSettingsBuilder().WithHideTopLevelNodeFromPath(false).Build(); - var umbracoContext = GetUmbracoContext("/test", 1111, globalSettings: ConfigModelConversions.ConvertGlobalSettings(globalSettings)); + var umbracoContext = GetUmbracoContext("/test", 1111, globalSettings: ConfigModelConversionsToLegacy.ConvertGlobalSettings(globalSettings)); var umbracoContextAccessor = new TestUmbracoContextAccessor(umbracoContext); var urlProvider = new DefaultUrlProvider(Microsoft.Extensions.Options.Options.Create(requestHandlerSettings), Logger, @@ -277,7 +276,7 @@ namespace Umbraco.Tests.Routing var globalSettings = new GlobalSettingsBuilder().WithHideTopLevelNodeFromPath(false).Build(); - var umbracoContext = GetUmbracoContext("/test", 1111, globalSettings: ConfigModelConversions.ConvertGlobalSettings(globalSettings)); + var umbracoContext = GetUmbracoContext("/test", 1111, globalSettings: ConfigModelConversionsToLegacy.ConvertGlobalSettings(globalSettings)); var umbracoContextAccessor = new TestUmbracoContextAccessor(umbracoContext); var urlProvider = new DefaultUrlProvider( Microsoft.Extensions.Options.Options.Create(requestHandlerSettings), @@ -301,7 +300,7 @@ namespace Umbraco.Tests.Routing var globalSettings = new GlobalSettingsBuilder().WithHideTopLevelNodeFromPath(false).Build(); - var umbracoContext = GetUmbracoContext("/test", 1111, globalSettings: ConfigModelConversions.ConvertGlobalSettings(globalSettings)); + var umbracoContext = GetUmbracoContext("/test", 1111, globalSettings: ConfigModelConversionsToLegacy.ConvertGlobalSettings(globalSettings)); var umbracoContextAccessor = new TestUmbracoContextAccessor(umbracoContext); var urlProvider = new DefaultUrlProvider( Microsoft.Extensions.Options.Options.Create(requestHandlerSettings), @@ -367,7 +366,7 @@ namespace Umbraco.Tests.Routing var globalSettings = new GlobalSettingsBuilder().WithHideTopLevelNodeFromPath(false).Build(); - var umbracoContext = GetUmbracoContext("http://domain1.com/test", 1111, globalSettings: ConfigModelConversions.ConvertGlobalSettings(globalSettings)); + var umbracoContext = GetUmbracoContext("http://domain1.com/test", 1111, globalSettings: ConfigModelConversionsToLegacy.ConvertGlobalSettings(globalSettings)); var umbracoContextAccessor = new TestUmbracoContextAccessor(umbracoContext); var urlProvider = new DefaultUrlProvider( Microsoft.Extensions.Options.Options.Create(requestHandlerSettings), @@ -394,7 +393,7 @@ namespace Umbraco.Tests.Routing var globalSettings = new GlobalSettingsBuilder().WithHideTopLevelNodeFromPath(false).Build(); - var umbracoContext = GetUmbracoContext("http://domain1.com/en/test", 1111, globalSettings: ConfigModelConversions.ConvertGlobalSettings(globalSettings)); + var umbracoContext = GetUmbracoContext("http://domain1.com/en/test", 1111, globalSettings: ConfigModelConversionsToLegacy.ConvertGlobalSettings(globalSettings)); var umbracoContextAccessor = new TestUmbracoContextAccessor(umbracoContext); var urlProvider = new DefaultUrlProvider( Microsoft.Extensions.Options.Options.Create(requestHandlerSettings), diff --git a/src/Umbraco.Tests/Routing/UrlsWithNestedDomains.cs b/src/Umbraco.Tests/Routing/UrlsWithNestedDomains.cs index 085cf7f274..6e00b7a7f0 100644 --- a/src/Umbraco.Tests/Routing/UrlsWithNestedDomains.cs +++ b/src/Umbraco.Tests/Routing/UrlsWithNestedDomains.cs @@ -13,6 +13,7 @@ using Umbraco.Tests.LegacyXmlPublishedCache; using Umbraco.Web; using Umbraco.Tests.Common; using Umbraco.Tests.Common.Builders; +using Umbraco.Infrastructure.Configuration; namespace Umbraco.Tests.Routing { @@ -42,7 +43,7 @@ namespace Umbraco.Tests.Routing const string url = "http://domain1.com/1001-1/1001-1-1"; // get the nice url for 100111 - var umbracoContext = GetUmbracoContext(url, 9999, globalSettings: ConfigModelConversions.ConvertGlobalSettings(globalSettings)); + var umbracoContext = GetUmbracoContext(url, 9999, globalSettings: ConfigModelConversionsToLegacy.ConvertGlobalSettings(globalSettings)); var umbracoContextAccessor = new TestUmbracoContextAccessor(umbracoContext); var urlProvider = new DefaultUrlProvider( Microsoft.Extensions.Options.Options.Create(requestHandlerSettings), diff --git a/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs b/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs index 26322aa801..369eaeeac5 100644 --- a/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs +++ b/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Data; using Examine; using Moq; using NUnit.Framework; @@ -9,14 +8,13 @@ using Umbraco.Core.Cache; using Umbraco.Core.Composing; using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.UmbracoSettings; -using Umbraco.Core.Events; using Umbraco.Core.Exceptions; using Umbraco.Core.Hosting; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Persistence; using Umbraco.Core.Runtime; -using Umbraco.Core.Scoping; +using Umbraco.Infrastructure.Configuration; using Umbraco.Net; using Umbraco.Tests.TestHelpers; using Umbraco.Tests.TestHelpers.Stubs; @@ -118,7 +116,7 @@ namespace Umbraco.Tests.Runtimes public class TestRuntime : CoreRuntime { public TestRuntime(Configs configs, IUmbracoVersion umbracoVersion, IIOHelper ioHelper, ILogger logger, IProfiler profiler, IHostingEnvironment hostingEnvironment, IBackOfficeInfo backOfficeInfo) - : base(Umbraco.Web.Configuration.ConfigModelConversions.ConvertGlobalSettings(configs.Global()), Umbraco.Web.Configuration.ConfigModelConversions.ConvertConnectionStrings(configs.ConnectionStrings()), umbracoVersion, ioHelper, logger, profiler, new AspNetUmbracoBootPermissionChecker(), hostingEnvironment, backOfficeInfo, TestHelper.DbProviderFactoryCreator, TestHelper.MainDom, TestHelper.GetTypeFinder(), NoAppCache.Instance) + : base(ConfigModelConversionsFromLegacy.ConvertGlobalSettings(configs.Global()), ConfigModelConversionsFromLegacy.ConvertConnectionStrings(configs.ConnectionStrings()), umbracoVersion, ioHelper, logger, profiler, new AspNetUmbracoBootPermissionChecker(), hostingEnvironment, backOfficeInfo, TestHelper.DbProviderFactoryCreator, TestHelper.MainDom, TestHelper.GetTypeFinder(), NoAppCache.Instance) { } diff --git a/src/Umbraco.Tests/Runtimes/StandaloneTests.cs b/src/Umbraco.Tests/Runtimes/StandaloneTests.cs index 394ed902f8..2773eef4ab 100644 --- a/src/Umbraco.Tests/Runtimes/StandaloneTests.cs +++ b/src/Umbraco.Tests/Runtimes/StandaloneTests.cs @@ -80,7 +80,7 @@ namespace Umbraco.Tests.Runtimes // create the register and the composition var register = TestHelper.GetRegister(); - var composition = new Composition(register, typeLoader, profilingLogger, runtimeState, ioHelper, appCaches); + var composition = new Composition(register, typeLoader, profilingLogger, runtimeState, configs, ioHelper, appCaches); composition.RegisterEssentials(logger, profiler, profilingLogger, mainDom, appCaches, databaseFactory, typeLoader, runtimeState, typeFinder, ioHelper, umbracoVersion, TestHelper.DbProviderFactoryCreator, hostingEnvironment, backOfficeInfo); // create the core runtime and have it compose itself @@ -271,7 +271,7 @@ namespace Umbraco.Tests.Runtimes // create the register and the composition var register = TestHelper.GetRegister(); - var composition = new Composition(register, typeLoader, profilingLogger, runtimeState, ioHelper, appCaches); + var composition = new Composition(register, typeLoader, profilingLogger, runtimeState, configs, ioHelper, appCaches); var umbracoVersion = TestHelper.GetUmbracoVersion(); composition.RegisterEssentials(logger, profiler, profilingLogger, mainDom, appCaches, databaseFactory, typeLoader, runtimeState, typeFinder, ioHelper, umbracoVersion, TestHelper.DbProviderFactoryCreator, hostingEnvironment, backOfficeInfo); diff --git a/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs b/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs index e47e9692bd..a0c954e7bb 100644 --- a/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs +++ b/src/Umbraco.Tests/Scoping/ScopeEventDispatcherTests.cs @@ -35,7 +35,7 @@ namespace Umbraco.Tests.Scoping var register = TestHelper.GetRegister(); - var composition = new Composition(register, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.IOHelper, AppCaches.NoCache); + var composition = new Composition(register, TestHelper.GetMockedTypeLoader(), Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.GetConfigs(), TestHelper.IOHelper, AppCaches.NoCache); _testObjects = new TestObjects(register); diff --git a/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs b/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs index 3faea42f01..6bc228bf83 100644 --- a/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs +++ b/src/Umbraco.Tests/TestHelpers/BaseUsingSqlCeSyntax.cs @@ -45,7 +45,7 @@ namespace Umbraco.Tests.TestHelpers logger, false); - var composition = new Composition(container, typeLoader, Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.IOHelper, AppCaches.NoCache); + var composition = new Composition(container, typeLoader, Mock.Of(), ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.GetConfigs(), TestHelper.IOHelper, AppCaches.NoCache); composition.RegisterUnique(_ => Mock.Of()); composition.RegisterUnique(_ => Mock.Of()); diff --git a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs index d339143c61..b8cab0d0f7 100644 --- a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs +++ b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs @@ -37,6 +37,7 @@ using Umbraco.Core.Serialization; using Umbraco.Core.Services; using Umbraco.Core.Services.Implement; using Umbraco.Core.Strings; +using Umbraco.Infrastructure.Configuration; using Umbraco.Net; using Umbraco.Tests.Common; using Umbraco.Tests.Common.Builders; @@ -58,7 +59,6 @@ using Umbraco.Web.Security.Providers; using Umbraco.Web.Services; using Umbraco.Web.Templates; using Umbraco.Web.Trees; -using ConfigModelConversions = Umbraco.Tests.TestHelpers.ConfigModelConversions; using Current = Umbraco.Web.Composing.Current; using FileSystems = Umbraco.Core.IO.FileSystems; @@ -176,7 +176,7 @@ namespace Umbraco.Tests.Testing var globalSettings = new GlobalSettingsBuilder().Build(); var settings = TestHelpers.SettingsForTests.GenerateMockWebRoutingSettings(); - IBackOfficeInfo backOfficeInfo = new AspNetBackOfficeInfo(ConfigModelConversions.ConvertGlobalSettings(globalSettings), IOHelper, logger, settings); + IBackOfficeInfo backOfficeInfo = new AspNetBackOfficeInfo(ConfigModelConversionsToLegacy.ConvertGlobalSettings(globalSettings), IOHelper, logger, settings); IIpResolver ipResolver = new AspNetIpResolver(); UmbracoVersion = new UmbracoVersion(globalSettings); @@ -188,7 +188,7 @@ namespace Umbraco.Tests.Testing - Composition = new Composition(register, typeLoader, proflogger, ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.IOHelper, AppCaches.NoCache); + Composition = new Composition(register, typeLoader, proflogger, ComponentTests.MockRuntimeState(RuntimeLevel.Run), TestHelper.GetConfigs(), TestHelper.IOHelper, AppCaches.NoCache); @@ -412,6 +412,23 @@ namespace Umbraco.Tests.Testing protected virtual void ComposeSettings() { + var contentSettings = new ContentSettingsBuilder().Build(); + var coreDebugSettings = new CoreDebugSettingsBuilder().Build(); + var globalSettings = new GlobalSettingsBuilder().Build(); + var nuCacheSettings = new NuCacheSettingsBuilder().Build(); + var requestHandlerSettings = new RequestHandlerSettingsBuilder().Build(); + var userPasswordConfigurationSettings = new UserPasswordConfigurationSettingsBuilder().Build(); + var webRoutingSettings = new WebRoutingSettingsBuilder().Build(); + + Composition.Register(x => Microsoft.Extensions.Options.Options.Create(contentSettings)); + Composition.Register(x => Microsoft.Extensions.Options.Options.Create(coreDebugSettings)); + Composition.Register(x => Microsoft.Extensions.Options.Options.Create(globalSettings)); + Composition.Register(x => Microsoft.Extensions.Options.Options.Create(nuCacheSettings)); + Composition.Register(x => Microsoft.Extensions.Options.Options.Create(requestHandlerSettings)); + Composition.Register(x => Microsoft.Extensions.Options.Options.Create(userPasswordConfigurationSettings)); + Composition.Register(x => Microsoft.Extensions.Options.Options.Create(webRoutingSettings)); + + // TODO: remove this once legacy config is fully extracted. Composition.Configs.Add(() => TestHelpers.SettingsForTests.DefaultGlobalSettings); Composition.Configs.Add(() => TestHelpers.SettingsForTests.DefaultHostingSettings); Composition.Configs.Add(TestHelpers.SettingsForTests.GenerateMockRequestHandlerSettings); @@ -420,8 +437,6 @@ namespace Umbraco.Tests.Testing Composition.Configs.Add(TestHelpers.SettingsForTests.GenerateMockUserPasswordConfiguration); Composition.Configs.Add(TestHelpers.SettingsForTests.GenerateMockMemberPasswordConfiguration); Composition.Configs.Add(TestHelpers.SettingsForTests.GenerateMockContentSettings); - - //Composition.Configs.Add(() => new DefaultUserPasswordConfig()); } protected virtual void ComposeApplication(bool withApplication) diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj index b21814cab7..193b4093f5 100644 --- a/src/Umbraco.Tests/Umbraco.Tests.csproj +++ b/src/Umbraco.Tests/Umbraco.Tests.csproj @@ -145,7 +145,6 @@ - diff --git a/src/Umbraco.Web.Common/Extensions/UmbracoCoreServiceCollectionExtensions.cs b/src/Umbraco.Web.Common/Extensions/UmbracoCoreServiceCollectionExtensions.cs index b4911d6b59..80ea591037 100644 --- a/src/Umbraco.Web.Common/Extensions/UmbracoCoreServiceCollectionExtensions.cs +++ b/src/Umbraco.Web.Common/Extensions/UmbracoCoreServiceCollectionExtensions.cs @@ -127,6 +127,11 @@ namespace Umbraco.Extensions services.Configure(configuration.GetSection(Constants.Configuration.ConfigSecurityPrefix + "UserPassword")); services.Configure(configuration.GetSection(Constants.Configuration.ConfigPrefix + "WebRouting")); + // TODO: remove this once no longer requred in Umbraco.Web. + var configsFactory = new AspNetCoreConfigsFactory(configuration); + var configs = configsFactory.Create(); + services.AddSingleton(configs); + return services; } diff --git a/src/Umbraco.Web/AppBuilderExtensions.cs b/src/Umbraco.Web/AppBuilderExtensions.cs index 18eb3a54fe..499ebbd929 100644 --- a/src/Umbraco.Web/AppBuilderExtensions.cs +++ b/src/Umbraco.Web/AppBuilderExtensions.cs @@ -4,7 +4,7 @@ using Microsoft.Owin.Logging; using Owin; using Umbraco.Core.Configuration; using Umbraco.Core.Hosting; -using Umbraco.Web.Configuration; +using Umbraco.Infrastructure.Configuration; using Umbraco.Web.Logging; namespace Umbraco.Web @@ -47,7 +47,7 @@ namespace Umbraco.Web /// public static IAppBuilder UseSignalR(this IAppBuilder app, IGlobalSettings globalSettings, IHostingEnvironment hostingEnvironment) { - var umbracoPath = ConfigModelConversions.ConvertGlobalSettings(globalSettings).GetUmbracoMvcArea(hostingEnvironment); + var umbracoPath = ConfigModelConversionsFromLegacy.ConvertGlobalSettings(globalSettings).GetUmbracoMvcArea(hostingEnvironment); var signalrPath = HttpRuntime.AppDomainAppVirtualPath + umbracoPath + "/BackOffice/signalr"; return app.MapSignalR(signalrPath, new HubConfiguration { EnableDetailedErrors = true }); } diff --git a/src/Umbraco.Web/Compose/AuditEventsComponent.cs b/src/Umbraco.Web/Compose/AuditEventsComponent.cs index 9b9a1671f3..9aabfd0a66 100644 --- a/src/Umbraco.Web/Compose/AuditEventsComponent.cs +++ b/src/Umbraco.Web/Compose/AuditEventsComponent.cs @@ -7,11 +7,11 @@ using Umbraco.Core.Configuration; using Umbraco.Core.Events; using Umbraco.Core.Models; using Umbraco.Core.Models.Membership; -using Umbraco.Net; using Umbraco.Core.Services; using Umbraco.Core.Services.Implement; using Umbraco.Extensions; -using Umbraco.Web.Configuration; +using Umbraco.Infrastructure.Configuration; +using Umbraco.Net; namespace Umbraco.Core.Compose { @@ -50,7 +50,7 @@ namespace Umbraco.Core.Compose public void Terminate() { } - public static IUser UnknownUser(IGlobalSettings globalSettings) => new User(ConfigModelConversions.ConvertGlobalSettings(globalSettings)) { Id = Constants.Security.UnknownUserId, Name = Constants.Security.UnknownUserName, Email = "" }; + public static IUser UnknownUser(IGlobalSettings globalSettings) => new User(ConfigModelConversionsFromLegacy.ConvertGlobalSettings(globalSettings)) { Id = Constants.Security.UnknownUserId, Name = Constants.Security.UnknownUserName, Email = "" }; private IUser CurrentPerformingUser { diff --git a/src/Umbraco.Web/Configuration/ConfigModelConversions.cs b/src/Umbraco.Web/Configuration/ConfigModelConversions.cs index 7225c1c058..f3b74734b4 100644 --- a/src/Umbraco.Web/Configuration/ConfigModelConversions.cs +++ b/src/Umbraco.Web/Configuration/ConfigModelConversions.cs @@ -9,54 +9,11 @@ namespace Umbraco.Web.Configuration { /// /// TEMPORARY: this class has been added just to ensure Umbraco.Web functionality continues to compile, by - /// converting between e.g. (used by - /// legacy configuration and (used by Netcore/IOptions configuration). + /// converting between e.g. (used by + /// legacy configuration and (used by Netcore/IOptions configuration). /// public static class ConfigModelConversions { - public static GlobalSettings ConvertGlobalSettings(IGlobalSettings globalSettings) - { - return new GlobalSettings - { - DatabaseFactoryServerVersion = globalSettings.DatabaseFactoryServerVersion, - DefaultUILanguage = globalSettings.DefaultUILanguage, - DisableElectionForSingleServer = globalSettings.DisableElectionForSingleServer, - HideTopLevelNodeFromPath = globalSettings.HideTopLevelNodeFromPath, - InstallEmptyDatabase = globalSettings.InstallEmptyDatabase, - InstallMissingDatabase = globalSettings.InstallMissingDatabase, - MainDomLock = globalSettings.MainDomLock, - NoNodesViewPath = globalSettings.NoNodesViewPath, - RegisterType = globalSettings.RegisterType, - ReservedPaths = globalSettings.ReservedPaths, - ReservedUrls = globalSettings.ReservedUrls, - Smtp = new SmtpSettings - { - DeliveryMethod = globalSettings.SmtpSettings.DeliveryMethod, - From = globalSettings.SmtpSettings.From, - Host = globalSettings.SmtpSettings.Host, - Password = globalSettings.SmtpSettings.Password, - PickupDirectoryLocation = globalSettings.SmtpSettings.PickupDirectoryLocation, - Port = globalSettings.SmtpSettings.Port, - Username = globalSettings.SmtpSettings.Username, - }, - TimeOutInMinutes = globalSettings.TimeOutInMinutes, - UmbracoCssPath = globalSettings.UmbracoCssPath, - UmbracoMediaPath = globalSettings.UmbracoMediaPath, - Path = globalSettings.UmbracoPath, - UmbracoScriptsPath = globalSettings.UmbracoScriptsPath, - UseHttps = globalSettings.UseHttps, - VersionCheckPeriod = globalSettings.VersionCheckPeriod, - }; - } - - public static Umbraco.Core.Configuration.Models.ConnectionStrings ConvertConnectionStrings(IConnectionStrings connectionStrings) - { - return new Umbraco.Core.Configuration.Models.ConnectionStrings - { - UmbracoConnectionString = connectionStrings[Constants.System.UmbracoConnectionName].ConnectionString - }; - } - public static IOptions ConvertToOptionsOfUserPasswordConfigurationSettings(IOptions identityOptions) { var passwordOptions = identityOptions.Value.Password; diff --git a/src/Umbraco.Web/Editors/BackOfficeController.cs b/src/Umbraco.Web/Editors/BackOfficeController.cs index 3106d02dc8..34d6e49563 100644 --- a/src/Umbraco.Web/Editors/BackOfficeController.cs +++ b/src/Umbraco.Web/Editors/BackOfficeController.cs @@ -11,13 +11,13 @@ using Umbraco.Core.Configuration; using Umbraco.Core.Logging; using Umbraco.Web.Mvc; using Umbraco.Core.Services; -using Umbraco.Web.Configuration; using Umbraco.Web.Features; using Umbraco.Web.Security; using Constants = Umbraco.Core.Constants; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Hosting; using BackOfficeIdentityUser = Umbraco.Core.BackOffice.BackOfficeIdentityUser; +using Umbraco.Infrastructure.Configuration; namespace Umbraco.Web.Editors { @@ -140,7 +140,7 @@ namespace Umbraco.Web.Editors if (defaultResponse == null) throw new ArgumentNullException("defaultResponse"); if (externalSignInResponse == null) throw new ArgumentNullException("externalSignInResponse"); - ViewData.SetUmbracoPath(ConfigModelConversions.ConvertGlobalSettings(GlobalSettings).GetUmbracoMvcArea(_hostingEnvironment)); + ViewData.SetUmbracoPath(ConfigModelConversionsFromLegacy.ConvertGlobalSettings(GlobalSettings).GetUmbracoMvcArea(_hostingEnvironment)); //check if there is the TempData with the any token name specified, if so, assign to view bag and render the view if (ViewData.FromTempData(TempData, ViewDataExtensions.TokenExternalSignInError) || @@ -255,7 +255,7 @@ namespace Umbraco.Web.Editors var groups = Services.UserService.GetUserGroupsByAlias(autoLinkOptions.GetDefaultUserGroups(UmbracoContext, loginInfo)); var autoLinkUser = BackOfficeIdentityUser.CreateNew( - ConfigModelConversions.ConvertGlobalSettings(GlobalSettings), + ConfigModelConversionsFromLegacy.ConvertGlobalSettings(GlobalSettings), loginInfo.Email, loginInfo.Email, autoLinkOptions.GetDefaultCulture(UmbracoContext, loginInfo)); diff --git a/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs b/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs index ec8d7e5dd5..8babcc703f 100644 --- a/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs +++ b/src/Umbraco.Web/Editors/BackOfficeServerVariables.cs @@ -7,17 +7,15 @@ using System.Web; using System.Web.Mvc; using Umbraco.Core; using Umbraco.Core.Configuration; -using Umbraco.Web.Configuration; -using Umbraco.Web.Features; -using Umbraco.Web.HealthCheck; -using Umbraco.Web.Models.ContentEditing; -using Umbraco.Web.Mvc; -using Umbraco.Web.Trees; -using Constants = Umbraco.Core.Constants; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Hosting; using Umbraco.Core.WebAssets; +using Umbraco.Infrastructure.Configuration; +using Umbraco.Web.Features; +using Umbraco.Web.Mvc; using Umbraco.Web.Security; +using Umbraco.Web.Trees; +using Constants = Umbraco.Core.Constants; namespace Umbraco.Web.Editors { @@ -144,7 +142,7 @@ namespace Umbraco.Web.Editors { "umbracoSettings", new Dictionary { - {"umbracoPath", ConfigModelConversions.ConvertGlobalSettings(_globalSettings).GetBackOfficePath(_hostingEnvironment)}, + {"umbracoPath", ConfigModelConversionsFromLegacy.ConvertGlobalSettings(_globalSettings).GetBackOfficePath(_hostingEnvironment)}, {"mediaPath", _hostingEnvironment.ToAbsolute(globalSettings.UmbracoMediaPath).TrimEnd('/')}, {"appPluginsPath", _hostingEnvironment.ToAbsolute(Constants.SystemDirectories.AppPlugins).TrimEnd('/')}, { @@ -168,8 +166,8 @@ namespace Umbraco.Web.Editors {"cssPath", _hostingEnvironment.ToAbsolute(globalSettings.UmbracoCssPath).TrimEnd('/')}, {"allowPasswordReset", _securitySettings.AllowPasswordReset}, {"loginBackgroundImage", _contentSettings.LoginBackgroundImage}, - {"showUserInvite", EmailSender.CanSendRequiredEmail(ConfigModelConversions.ConvertGlobalSettings(globalSettings))}, - {"canSendRequiredEmail", EmailSender.CanSendRequiredEmail(ConfigModelConversions.ConvertGlobalSettings(globalSettings))}, + {"showUserInvite", EmailSender.CanSendRequiredEmail(ConfigModelConversionsFromLegacy.ConvertGlobalSettings(globalSettings))}, + {"canSendRequiredEmail", EmailSender.CanSendRequiredEmail(ConfigModelConversionsFromLegacy.ConvertGlobalSettings(globalSettings))}, {"showAllowSegmentationForDocumentTypes", false}, } }, diff --git a/src/Umbraco.Web/Mvc/AreaRegistrationExtensions.cs b/src/Umbraco.Web/Mvc/AreaRegistrationExtensions.cs index eee675e9fd..679fb7987c 100644 --- a/src/Umbraco.Web/Mvc/AreaRegistrationExtensions.cs +++ b/src/Umbraco.Web/Mvc/AreaRegistrationExtensions.cs @@ -6,11 +6,8 @@ using System.Web.Routing; using System.Web.SessionState; using Umbraco.Core; using Umbraco.Core.Configuration; -using Umbraco.Core.Exceptions; using Umbraco.Core.Hosting; -using Umbraco.Core.IO; -using Umbraco.Web.Composing; -using Umbraco.Web.Configuration; +using Umbraco.Infrastructure.Configuration; using Umbraco.Web.WebApi; namespace Umbraco.Web.Mvc @@ -61,7 +58,7 @@ namespace Umbraco.Web.Mvc if (routes == null) throw new ArgumentNullException(nameof(routes)); if (defaultId == null) throw new ArgumentNullException(nameof(defaultId)); - var umbracoArea = ConfigModelConversions.ConvertGlobalSettings(globalSettings).GetUmbracoMvcArea(hostingEnvironment); + var umbracoArea = ConfigModelConversionsFromLegacy.ConvertGlobalSettings(globalSettings).GetUmbracoMvcArea(hostingEnvironment); //routes are explicitly named with controller names and IDs var url = umbracoArea + "/" + diff --git a/src/Umbraco.Web/Mvc/BackOfficeArea.cs b/src/Umbraco.Web/Mvc/BackOfficeArea.cs index 4a4202b42b..677ae18a1e 100644 --- a/src/Umbraco.Web/Mvc/BackOfficeArea.cs +++ b/src/Umbraco.Web/Mvc/BackOfficeArea.cs @@ -1,9 +1,7 @@ using System.Web.Mvc; -using Umbraco.Web.Composing; using Umbraco.Core.Configuration; using Umbraco.Core.Hosting; -using Umbraco.Core.IO; -using Umbraco.Web.Configuration; +using Umbraco.Infrastructure.Configuration; using Umbraco.Web.Editors; namespace Umbraco.Web.Mvc @@ -51,6 +49,6 @@ namespace Umbraco.Web.Mvc new[] {typeof (BackOfficeController).Namespace}); } - public override string AreaName => ConfigModelConversions.ConvertGlobalSettings(_globalSettings).GetUmbracoMvcArea(_hostingEnvironment); + public override string AreaName => ConfigModelConversionsFromLegacy.ConvertGlobalSettings(_globalSettings).GetUmbracoMvcArea(_hostingEnvironment); } } diff --git a/src/Umbraco.Web/Mvc/UmbracoAuthorizeAttribute.cs b/src/Umbraco.Web/Mvc/UmbracoAuthorizeAttribute.cs index 9fc58a208f..d9baa25823 100644 --- a/src/Umbraco.Web/Mvc/UmbracoAuthorizeAttribute.cs +++ b/src/Umbraco.Web/Mvc/UmbracoAuthorizeAttribute.cs @@ -2,9 +2,9 @@ using System.Web; using System.Web.Mvc; using Umbraco.Core; -using Umbraco.Web.Composing; using Umbraco.Core.Configuration; -using Umbraco.Web.Configuration; +using Umbraco.Infrastructure.Configuration; +using Umbraco.Web.Composing; using Umbraco.Web.Security; namespace Umbraco.Web.Mvc @@ -56,7 +56,7 @@ namespace Umbraco.Web.Mvc { if (redirectToUmbracoLogin) { - _redirectUrl = ConfigModelConversions.ConvertGlobalSettings(Current.Configs.Global()).GetBackOfficePath(Current.HostingEnvironment).EnsureStartsWith("~"); + _redirectUrl = ConfigModelConversionsFromLegacy.ConvertGlobalSettings(Current.Configs.Global()).GetBackOfficePath(Current.HostingEnvironment).EnsureStartsWith("~"); } } diff --git a/src/Umbraco.Web/Runtime/WebInitialComponent.cs b/src/Umbraco.Web/Runtime/WebInitialComponent.cs index 5ad51acbc0..4c66322cde 100644 --- a/src/Umbraco.Web/Runtime/WebInitialComponent.cs +++ b/src/Umbraco.Web/Runtime/WebInitialComponent.cs @@ -10,12 +10,9 @@ using Umbraco.Core.Composing; using Umbraco.Core.Configuration; using Umbraco.Core.Hosting; using Umbraco.Core.Strings; -using Umbraco.Core.IO; -using Umbraco.Web.Configuration; -using Umbraco.Web.Install; +using Umbraco.Infrastructure.Configuration; using Umbraco.Web.Mvc; using Umbraco.Web.WebApi; - using Constants = Umbraco.Core.Constants; using Current = Umbraco.Web.Composing.Current; @@ -118,7 +115,7 @@ namespace Umbraco.Web.Runtime UmbracoApiControllerTypeCollection apiControllerTypes, IHostingEnvironment hostingEnvironment) { - var umbracoPath = ConfigModelConversions.ConvertGlobalSettings(globalSettings).GetUmbracoMvcArea(hostingEnvironment); + var umbracoPath = ConfigModelConversionsFromLegacy.ConvertGlobalSettings(globalSettings).GetUmbracoMvcArea(hostingEnvironment); // create the front-end route var defaultRoute = RouteTable.Routes.MapRoute( @@ -155,7 +152,7 @@ namespace Umbraco.Web.Runtime UmbracoApiControllerTypeCollection apiControllerTypes, IHostingEnvironment hostingEnvironment) { - var umbracoPath = ConfigModelConversions.ConvertGlobalSettings(globalSettings).GetUmbracoMvcArea(hostingEnvironment); + var umbracoPath = ConfigModelConversionsFromLegacy.ConvertGlobalSettings(globalSettings).GetUmbracoMvcArea(hostingEnvironment); // need to find the plugin controllers and route them var pluginControllers = surfaceControllerTypes.Concat(apiControllerTypes).ToArray(); diff --git a/src/Umbraco.Web/Security/BackOfficeOwinUserManager.cs b/src/Umbraco.Web/Security/BackOfficeOwinUserManager.cs index 92e4fca420..d11edc7bba 100644 --- a/src/Umbraco.Web/Security/BackOfficeOwinUserManager.cs +++ b/src/Umbraco.Web/Security/BackOfficeOwinUserManager.cs @@ -11,6 +11,7 @@ using Umbraco.Core.Configuration; using Umbraco.Core.Mapping; using Umbraco.Core.Security; using Umbraco.Core.Services; +using Umbraco.Infrastructure.Configuration; using Umbraco.Net; using Umbraco.Web.Configuration; @@ -54,7 +55,7 @@ namespace Umbraco.Web.Security IDataProtectionProvider dataProtectionProvider, ILogger> logger) { - var store = new BackOfficeUserStore(userService, entityService, externalLoginService, ConfigModelConversions.ConvertGlobalSettings(globalSettings), mapper); + var store = new BackOfficeUserStore(userService, entityService, externalLoginService, ConfigModelConversionsFromLegacy.ConvertGlobalSettings(globalSettings), mapper); return Create( passwordConfiguration, diff --git a/src/Umbraco.Web/Security/BackOfficeSignInManager.cs b/src/Umbraco.Web/Security/BackOfficeSignInManager.cs index c998b579a1..fe90db9ec7 100644 --- a/src/Umbraco.Web/Security/BackOfficeSignInManager.cs +++ b/src/Umbraco.Web/Security/BackOfficeSignInManager.cs @@ -10,8 +10,7 @@ using Microsoft.Owin.Security; using Umbraco.Core; using Umbraco.Core.BackOffice; using Umbraco.Core.Configuration; -using Umbraco.Core.BackOffice; -using Umbraco.Web.Configuration; +using Umbraco.Infrastructure.Configuration; namespace Umbraco.Web.Security { @@ -79,7 +78,7 @@ namespace Umbraco.Web.Security var user = await _userManager.FindByNameAsync(userName); //if the user is null, create an empty one which can be used for auto-linking - if (user == null) user = BackOfficeIdentityUser.CreateNew(ConfigModelConversions.ConvertGlobalSettings(_globalSettings), userName, null, _globalSettings.DefaultUILanguage); + if (user == null) user = BackOfficeIdentityUser.CreateNew(ConfigModelConversionsFromLegacy.ConvertGlobalSettings(_globalSettings), userName, null, _globalSettings.DefaultUILanguage); //check the password for the user, this will allow a developer to auto-link //an account if they have specified an IBackOfficeUserPasswordChecker diff --git a/src/Umbraco.Web/Security/GetUserSecondsMiddleWare.cs b/src/Umbraco.Web/Security/GetUserSecondsMiddleWare.cs index f73f25f859..5c3ab46101 100644 --- a/src/Umbraco.Web/Security/GetUserSecondsMiddleWare.cs +++ b/src/Umbraco.Web/Security/GetUserSecondsMiddleWare.cs @@ -9,9 +9,7 @@ using Umbraco.Core; using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Hosting; -using Umbraco.Core.IO; -using Umbraco.Core.Security; -using Umbraco.Web.Configuration; +using Umbraco.Infrastructure.Configuration; namespace Umbraco.Web.Security { @@ -54,7 +52,7 @@ namespace Umbraco.Web.Security if (request.Uri.Scheme.InvariantStartsWith("http") && request.Uri.AbsolutePath.InvariantEquals( - $"{ConfigModelConversions.ConvertGlobalSettings(_globalSettings).GetBackOfficePath(_hostingEnvironment)}/backoffice/UmbracoApi/Authentication/GetRemainingTimeoutSeconds")) + $"{ConfigModelConversionsFromLegacy.ConvertGlobalSettings(_globalSettings).GetBackOfficePath(_hostingEnvironment)}/backoffice/UmbracoApi/Authentication/GetRemainingTimeoutSeconds")) { var cookie = _authOptions.CookieManager.GetRequestCookie(context, _security.AuthCookieName); if (cookie.IsNullOrWhiteSpace() == false) diff --git a/src/Umbraco.Web/UmbracoApplication.cs b/src/Umbraco.Web/UmbracoApplication.cs index 4cdcecc1ce..843082e884 100644 --- a/src/Umbraco.Web/UmbracoApplication.cs +++ b/src/Umbraco.Web/UmbracoApplication.cs @@ -1,20 +1,14 @@ -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.InteropServices; -using System.Threading; +using System.Runtime.InteropServices; using System.Web; using Umbraco.Core; using Umbraco.Core.Cache; -using Umbraco.Core.Logging; -using Umbraco.Core.Logging.Serilog; -using Umbraco.Core.Runtime; using Umbraco.Core.Configuration; using Umbraco.Core.Hosting; using Umbraco.Core.IO; using Umbraco.Core.Logging; +using Umbraco.Core.Runtime; +using Umbraco.Infrastructure.Configuration; using Umbraco.Web.Runtime; -using Umbraco.Web.Configuration; namespace Umbraco.Web { @@ -30,8 +24,8 @@ namespace Umbraco.Web var dbProviderFactoryCreator = new UmbracoDbProviderFactoryCreator(); - var globalSettings = ConfigModelConversions.ConvertGlobalSettings(configs.Global()); - var connectionStrings = ConfigModelConversions.ConvertConnectionStrings(configs.ConnectionStrings()); + var globalSettings = ConfigModelConversionsFromLegacy.ConvertGlobalSettings(configs.Global()); + var connectionStrings = ConfigModelConversionsFromLegacy.ConvertConnectionStrings(configs.ConnectionStrings()); // Determine if we should use the sql main dom or the default var appSettingMainDomLock = globalSettings.MainDomLock; diff --git a/src/Umbraco.Web/UmbracoApplicationBase.cs b/src/Umbraco.Web/UmbracoApplicationBase.cs index 984f46bd60..4f6f2c7f0f 100644 --- a/src/Umbraco.Web/UmbracoApplicationBase.cs +++ b/src/Umbraco.Web/UmbracoApplicationBase.cs @@ -1,10 +1,10 @@ -using Serilog.Context; -using System; +using System; using System.IO; using System.Reflection; using System.Threading; using System.Web; using System.Web.Hosting; +using Serilog.Context; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Composing; @@ -14,9 +14,8 @@ using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Logging.Serilog; using Umbraco.Core.Logging.Serilog.Enrichers; +using Umbraco.Infrastructure.Configuration; using Umbraco.Net; -using Umbraco.Web.AspNet; -using Umbraco.Web.Configuration; using Umbraco.Web.Hosting; using Umbraco.Web.Logging; using Current = Umbraco.Web.Composing.Current; @@ -128,7 +127,7 @@ namespace Umbraco.Web /// protected virtual IRegister GetRegister(IGlobalSettings globalSettings) { - return RegisterFactory.Create(ConfigModelConversions.ConvertGlobalSettings(globalSettings)); + return RegisterFactory.Create(ConfigModelConversionsFromLegacy.ConvertGlobalSettings(globalSettings)); } // events - in the order they trigger @@ -161,7 +160,7 @@ namespace Umbraco.Web var globalSettings = Umbraco.Composing.Current.Configs.Global(); - var umbracoVersion = new UmbracoVersion(ConfigModelConversions.ConvertGlobalSettings(globalSettings)); + var umbracoVersion = new UmbracoVersion(ConfigModelConversionsFromLegacy.ConvertGlobalSettings(globalSettings)); // create the register for the application, and boot // the boot manager is responsible for registrations diff --git a/src/Umbraco.Web/UmbracoContext.cs b/src/Umbraco.Web/UmbracoContext.cs index e94e0acc0b..73ee4a377e 100644 --- a/src/Umbraco.Web/UmbracoContext.cs +++ b/src/Umbraco.Web/UmbracoContext.cs @@ -4,8 +4,8 @@ using Umbraco.Core; using Umbraco.Core.Configuration; using Umbraco.Core.Hosting; using Umbraco.Core.Models.PublishedContent; +using Umbraco.Infrastructure.Configuration; using Umbraco.Web.Composing; -using Umbraco.Web.Configuration; using Umbraco.Web.PublishedCache; using Umbraco.Web.Routing; using Umbraco.Web.Security; @@ -182,7 +182,7 @@ namespace Umbraco.Web { var request = GetRequestFromContext(); if (request?.Url != null - && request.Url.IsBackOfficeRequest(ConfigModelConversions.ConvertGlobalSettings(_globalSettings), _hostingEnvironment) == false + && request.Url.IsBackOfficeRequest(ConfigModelConversionsFromLegacy.ConvertGlobalSettings(_globalSettings), _hostingEnvironment) == false && Security.CurrentUser != null) { var previewToken = _cookieManager.GetPreviewCookieValue(); // may be null or empty diff --git a/src/Umbraco.Web/UmbracoInjectedModule.cs b/src/Umbraco.Web/UmbracoInjectedModule.cs index a610d216a3..3bd627be71 100644 --- a/src/Umbraco.Web/UmbracoInjectedModule.cs +++ b/src/Umbraco.Web/UmbracoInjectedModule.cs @@ -1,19 +1,16 @@ using System; -using System.Collections.Generic; using System.Web; using System.Web.Routing; using Umbraco.Core; -using Umbraco.Core.Security; using Umbraco.Core.Cache; using Umbraco.Core.Configuration; using Umbraco.Core.Exceptions; using Umbraco.Core.Hosting; -using Umbraco.Core.IO; using Umbraco.Core.Logging; +using Umbraco.Core.Security; +using Umbraco.Infrastructure.Configuration; using Umbraco.Web.Composing; using Umbraco.Web.Routing; -using Umbraco.Web.Security; -using Umbraco.Web.Configuration; namespace Umbraco.Web { @@ -114,7 +111,7 @@ namespace Umbraco.Web var umbracoContext = Current.UmbracoContext; // re-write for the default back office path - if (httpContext.Request.Url.IsDefaultBackOfficeRequest(ConfigModelConversions.ConvertGlobalSettings(_globalSettings), _hostingEnvironment)) + if (httpContext.Request.Url.IsDefaultBackOfficeRequest(ConfigModelConversionsFromLegacy.ConvertGlobalSettings(_globalSettings), _hostingEnvironment)) { if (EnsureRuntime(httpContext, umbracoContext.OriginalRequestUrl)) RewriteToBackOfficeHandler(httpContext); @@ -247,7 +244,7 @@ namespace Umbraco.Web private void RewriteToBackOfficeHandler(HttpContextBase context) { // GlobalSettings.Path has already been through IOHelper.ResolveUrl() so it begins with / and vdir (if any) - var rewritePath = ConfigModelConversions.ConvertGlobalSettings(_globalSettings).GetBackOfficePath(_hostingEnvironment).TrimEnd('/') + "/Default"; + var rewritePath = ConfigModelConversionsFromLegacy.ConvertGlobalSettings(_globalSettings).GetBackOfficePath(_hostingEnvironment).TrimEnd('/') + "/Default"; // rewrite the path to the path of the handler (i.e. /umbraco/RenderMvc) context.RewritePath(rewritePath, "", "", false); @@ -280,7 +277,7 @@ namespace Umbraco.Web var query = pcr.Uri.Query.TrimStart('?'); // GlobalSettings.Path has already been through IOHelper.ResolveUrl() so it begins with / and vdir (if any) - var rewritePath = ConfigModelConversions.ConvertGlobalSettings(_globalSettings).GetBackOfficePath(_hostingEnvironment).TrimEnd('/') + "/RenderMvc"; + var rewritePath = ConfigModelConversionsFromLegacy.ConvertGlobalSettings(_globalSettings).GetBackOfficePath(_hostingEnvironment).TrimEnd('/') + "/RenderMvc"; // rewrite the path to the path of the handler (i.e. /umbraco/RenderMvc) context.RewritePath(rewritePath, "", query, false); diff --git a/src/Umbraco.Web/WebApi/Filters/CheckIfUserTicketDataIsStaleAttribute.cs b/src/Umbraco.Web/WebApi/Filters/CheckIfUserTicketDataIsStaleAttribute.cs index bae6d00048..ee057408e9 100644 --- a/src/Umbraco.Web/WebApi/Filters/CheckIfUserTicketDataIsStaleAttribute.cs +++ b/src/Umbraco.Web/WebApi/Filters/CheckIfUserTicketDataIsStaleAttribute.cs @@ -5,14 +5,13 @@ using System.Threading.Tasks; using System.Web.Http.Controllers; using System.Web.Http.Filters; using Umbraco.Core; -using Umbraco.Web.Composing; using Umbraco.Core.BackOffice; -using Umbraco.Core.Models.Membership; -using Umbraco.Core.Security; -using Umbraco.Web.Security; using Umbraco.Core.Mapping; using Umbraco.Core.Models; -using Umbraco.Web.Configuration; +using Umbraco.Core.Models.Membership; +using Umbraco.Infrastructure.Configuration; +using Umbraco.Web.Composing; +using Umbraco.Web.Security; namespace Umbraco.Web.WebApi.Filters { @@ -79,7 +78,7 @@ namespace Umbraco.Web.WebApi.Filters () => user.Username != identity.Username, () => { - var culture = user.GetUserCulture(Current.Services.TextService, ConfigModelConversions.ConvertGlobalSettings(Current.Configs.Global())); + var culture = user.GetUserCulture(Current.Services.TextService, ConfigModelConversionsFromLegacy.ConvertGlobalSettings(Current.Configs.Global())); return culture != null && culture.ToString() != identity.Culture; }, () => user.AllowedSections.UnsortedSequenceEqual(identity.AllowedApplications) == false, From 30e6f83358d99a498ebfb0a1dcd18e673ec5f0a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Tue, 25 Aug 2020 13:23:11 +0200 Subject: [PATCH 278/826] Update umbBlockCard.component.js change transparent to none --- .../src/views/components/blockcard/umbBlockCard.component.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/components/blockcard/umbBlockCard.component.js b/src/Umbraco.Web.UI.Client/src/views/components/blockcard/umbBlockCard.component.js index 454d264a89..f1d11e43ff 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/blockcard/umbBlockCard.component.js +++ b/src/Umbraco.Web.UI.Client/src/views/components/blockcard/umbBlockCard.component.js @@ -17,10 +17,9 @@ function BlockCardController($scope, umbRequestHelper) { var vm = this; - vm.styleBackgroundImage = "transparent"; + vm.styleBackgroundImage = "none"; var unwatch = $scope.$watch("vm.blockConfigModel.thumbnail", (newValue, oldValue) => { - console.log("updateThumbnail") if(newValue !== oldValue) { vm.updateThumbnail(); } @@ -37,7 +36,7 @@ vm.updateThumbnail = function () { if (vm.blockConfigModel.thumbnail == null || vm.blockConfigModel.thumbnail === "") { - vm.styleBackgroundImage = "transparent"; + vm.styleBackgroundImage = "none"; return; } From 8666547cf114f19de189ae94188062d74d0ce72a Mon Sep 17 00:00:00 2001 From: Andy Butland Date: Tue, 25 Aug 2020 14:19:33 +0200 Subject: [PATCH 279/826] Updated configuration models used within Umbraco.ModelsBuilder.Embedded project. --- .../BackOffice/ContentTypeModelValidator.cs | 3 ++- .../BackOffice/ContentTypeModelValidatorBase.cs | 6 +++--- .../BackOffice/DashboardReport.cs | 8 +++++--- .../BackOffice/MediaTypeModelValidator.cs | 4 ++-- .../BackOffice/MemberTypeModelValidator.cs | 4 ++-- .../BackOffice/ModelsBuilderDashboardController.cs | 8 +++++--- src/Umbraco.ModelsBuilder.Embedded/LiveModelsProvider.cs | 8 +++++--- .../Extensions/UmbracoCoreServiceCollectionExtensions.cs | 1 - 8 files changed, 24 insertions(+), 18 deletions(-) diff --git a/src/Umbraco.ModelsBuilder.Embedded/BackOffice/ContentTypeModelValidator.cs b/src/Umbraco.ModelsBuilder.Embedded/BackOffice/ContentTypeModelValidator.cs index 75affe09e7..af2a2a04cd 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/BackOffice/ContentTypeModelValidator.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/BackOffice/ContentTypeModelValidator.cs @@ -1,4 +1,5 @@ using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Web.Models.ContentEditing; namespace Umbraco.ModelsBuilder.Embedded.BackOffice @@ -10,7 +11,7 @@ namespace Umbraco.ModelsBuilder.Embedded.BackOffice // ReSharper disable once UnusedMember.Global - This is typed scanned public class ContentTypeModelValidator : ContentTypeModelValidatorBase { - public ContentTypeModelValidator(IModelsBuilderConfig config) : base(config) + public ContentTypeModelValidator(ModelsBuilderConfig config) : base(config) { } } diff --git a/src/Umbraco.ModelsBuilder.Embedded/BackOffice/ContentTypeModelValidatorBase.cs b/src/Umbraco.ModelsBuilder.Embedded/BackOffice/ContentTypeModelValidatorBase.cs index 1e96e64df8..02ac9e42eb 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/BackOffice/ContentTypeModelValidatorBase.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/BackOffice/ContentTypeModelValidatorBase.cs @@ -1,8 +1,8 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; -using Umbraco.Core.Configuration; using Umbraco.Core; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Models.PublishedContent; using Umbraco.Web.Editors; using Umbraco.Web.Models.ContentEditing; @@ -13,9 +13,9 @@ namespace Umbraco.ModelsBuilder.Embedded.BackOffice where TModel : ContentTypeSave where TProperty : PropertyTypeBasic { - private readonly IModelsBuilderConfig _config; + private readonly ModelsBuilderConfig _config; - public ContentTypeModelValidatorBase(IModelsBuilderConfig config) + public ContentTypeModelValidatorBase(ModelsBuilderConfig config) { _config = config; } diff --git a/src/Umbraco.ModelsBuilder.Embedded/BackOffice/DashboardReport.cs b/src/Umbraco.ModelsBuilder.Embedded/BackOffice/DashboardReport.cs index 6e22313474..a0928fafcf 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/BackOffice/DashboardReport.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/BackOffice/DashboardReport.cs @@ -1,18 +1,20 @@ using System.Text; +using Microsoft.Extensions.Options; using Umbraco.Configuration; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; namespace Umbraco.ModelsBuilder.Embedded.BackOffice { internal class DashboardReport { - private readonly IModelsBuilderConfig _config; + private readonly ModelsBuilderConfig _config; private readonly OutOfDateModelsStatus _outOfDateModels; private readonly ModelsGenerationError _mbErrors; - public DashboardReport(IModelsBuilderConfig config, OutOfDateModelsStatus outOfDateModels, ModelsGenerationError mbErrors) + public DashboardReport(IOptions config, OutOfDateModelsStatus outOfDateModels, ModelsGenerationError mbErrors) { - _config = config; + _config = config.Value; _outOfDateModels = outOfDateModels; _mbErrors = mbErrors; } diff --git a/src/Umbraco.ModelsBuilder.Embedded/BackOffice/MediaTypeModelValidator.cs b/src/Umbraco.ModelsBuilder.Embedded/BackOffice/MediaTypeModelValidator.cs index fcd42908e7..5e29a888a0 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/BackOffice/MediaTypeModelValidator.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/BackOffice/MediaTypeModelValidator.cs @@ -1,4 +1,4 @@ -using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Web.Models.ContentEditing; namespace Umbraco.ModelsBuilder.Embedded.BackOffice @@ -10,7 +10,7 @@ namespace Umbraco.ModelsBuilder.Embedded.BackOffice // ReSharper disable once UnusedMember.Global - This is typed scanned public class MediaTypeModelValidator : ContentTypeModelValidatorBase { - public MediaTypeModelValidator(IModelsBuilderConfig config) : base(config) + public MediaTypeModelValidator(ModelsBuilderConfig config) : base(config) { } } diff --git a/src/Umbraco.ModelsBuilder.Embedded/BackOffice/MemberTypeModelValidator.cs b/src/Umbraco.ModelsBuilder.Embedded/BackOffice/MemberTypeModelValidator.cs index 2e249eed4d..970259d06b 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/BackOffice/MemberTypeModelValidator.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/BackOffice/MemberTypeModelValidator.cs @@ -1,4 +1,4 @@ -using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Web.Models.ContentEditing; namespace Umbraco.ModelsBuilder.Embedded.BackOffice @@ -10,7 +10,7 @@ namespace Umbraco.ModelsBuilder.Embedded.BackOffice // ReSharper disable once UnusedMember.Global - This is typed scanned public class MemberTypeModelValidator : ContentTypeModelValidatorBase { - public MemberTypeModelValidator(IModelsBuilderConfig config) : base(config) + public MemberTypeModelValidator(ModelsBuilderConfig config) : base(config) { } } diff --git a/src/Umbraco.ModelsBuilder.Embedded/BackOffice/ModelsBuilderDashboardController.cs b/src/Umbraco.ModelsBuilder.Embedded/BackOffice/ModelsBuilderDashboardController.cs index 17b694de56..6179e7c756 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/BackOffice/ModelsBuilderDashboardController.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/BackOffice/ModelsBuilderDashboardController.cs @@ -3,8 +3,10 @@ using System.Net; using System.Net.Http; using System.Runtime.Serialization; using System.Web.Hosting; +using Microsoft.Extensions.Options; using Umbraco.Configuration; using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Exceptions; using Umbraco.ModelsBuilder.Embedded.Building; using Umbraco.Web.Editors; @@ -23,16 +25,16 @@ namespace Umbraco.ModelsBuilder.Embedded.BackOffice [UmbracoApplicationAuthorize(Core.Constants.Applications.Settings)] public class ModelsBuilderDashboardController : UmbracoAuthorizedJsonController { - private readonly IModelsBuilderConfig _config; + private readonly ModelsBuilderConfig _config; private readonly ModelsGenerator _modelGenerator; private readonly OutOfDateModelsStatus _outOfDateModels; private readonly ModelsGenerationError _mbErrors; private readonly DashboardReport _dashboardReport; - public ModelsBuilderDashboardController(IModelsBuilderConfig config, ModelsGenerator modelsGenerator, OutOfDateModelsStatus outOfDateModels, ModelsGenerationError mbErrors) + public ModelsBuilderDashboardController(IOptions config, ModelsGenerator modelsGenerator, OutOfDateModelsStatus outOfDateModels, ModelsGenerationError mbErrors) { //_umbracoServices = umbracoServices; - _config = config; + _config = config.Value; _modelGenerator = modelsGenerator; _outOfDateModels = outOfDateModels; _mbErrors = mbErrors; diff --git a/src/Umbraco.ModelsBuilder.Embedded/LiveModelsProvider.cs b/src/Umbraco.ModelsBuilder.Embedded/LiveModelsProvider.cs index 61d39cd373..ef3b215968 100644 --- a/src/Umbraco.ModelsBuilder.Embedded/LiveModelsProvider.cs +++ b/src/Umbraco.ModelsBuilder.Embedded/LiveModelsProvider.cs @@ -6,6 +6,8 @@ using Umbraco.Core.Hosting; using Umbraco.Core.Logging; using Umbraco.ModelsBuilder.Embedded.Building; using Umbraco.Web.Cache; +using Umbraco.Core.Configuration.Models; +using Microsoft.Extensions.Options; namespace Umbraco.ModelsBuilder.Embedded { @@ -15,7 +17,7 @@ namespace Umbraco.ModelsBuilder.Embedded private static Mutex _mutex; private static int _req; private readonly ILogger _logger; - private readonly IModelsBuilderConfig _config; + private readonly ModelsBuilderConfig _config; private readonly ModelsGenerator _modelGenerator; private readonly ModelsGenerationError _mbErrors; private readonly IHostingEnvironment _hostingEnvironment; @@ -23,10 +25,10 @@ namespace Umbraco.ModelsBuilder.Embedded // we do not manage pure live here internal bool IsEnabled => _config.ModelsMode.IsLiveNotPure(); - public LiveModelsProvider(ILogger logger, IModelsBuilderConfig config, ModelsGenerator modelGenerator, ModelsGenerationError mbErrors, IHostingEnvironment hostingEnvironment) + public LiveModelsProvider(ILogger logger, IOptions config, ModelsGenerator modelGenerator, ModelsGenerationError mbErrors, IHostingEnvironment hostingEnvironment) { _logger = logger; - _config = config ?? throw new ArgumentNullException(nameof(config)); + _config = config.Value ?? throw new ArgumentNullException(nameof(config)); _modelGenerator = modelGenerator; _mbErrors = mbErrors; _hostingEnvironment = hostingEnvironment; diff --git a/src/Umbraco.Web.Common/Extensions/UmbracoCoreServiceCollectionExtensions.cs b/src/Umbraco.Web.Common/Extensions/UmbracoCoreServiceCollectionExtensions.cs index 80ea591037..d829f6a3f2 100644 --- a/src/Umbraco.Web.Common/Extensions/UmbracoCoreServiceCollectionExtensions.cs +++ b/src/Umbraco.Web.Common/Extensions/UmbracoCoreServiceCollectionExtensions.cs @@ -14,7 +14,6 @@ using Serilog; using Serilog.Extensions.Hosting; using Serilog.Extensions.Logging; using Umbraco.Configuration; -using Umbraco.Configuration.Models; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Composing; From eee3d489f1b182db7cec26c66eda64bcef67c2ae Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Tue, 25 Aug 2020 13:32:05 +0100 Subject: [PATCH 280/826] Update src/Umbraco.Web.UI.Client/src/views/components/blockcard/umbBlockCard.component.js --- .../src/views/components/blockcard/umbBlockCard.component.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/components/blockcard/umbBlockCard.component.js b/src/Umbraco.Web.UI.Client/src/views/components/blockcard/umbBlockCard.component.js index f1d11e43ff..761e7c28ae 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/blockcard/umbBlockCard.component.js +++ b/src/Umbraco.Web.UI.Client/src/views/components/blockcard/umbBlockCard.component.js @@ -42,7 +42,7 @@ var path = umbRequestHelper.convertVirtualToAbsolutePath(vm.blockConfigModel.thumbnail); if (path.toLowerCase().endsWith(".svg") === false) { - path += "?upscale=false&width=400)"; + path += "?upscale=false&width=400"; } vm.styleBackgroundImage = 'url(\''+path+'\')'; } From 8fd59d546eea64d000ec3dbf0a59bc004a51c5cf Mon Sep 17 00:00:00 2001 From: Andy Butland Date: Wed, 26 Aug 2020 07:55:23 +0200 Subject: [PATCH 281/826] Fixed failing tests. --- src/Umbraco.Core/Umbraco.Core.csproj | 2 +- .../ConfigModelConversionsFromLegacy.cs | 22 ++-- .../Packaging/PackageDataInstallation.cs | 5 +- .../Persistence/UmbracoDatabaseFactory.cs | 3 - src/Umbraco.Tests.Integration/RuntimeTests.cs | 2 +- src/Umbraco.Tests/App.config | 2 +- src/Umbraco.Tests/IO/FileSystemsTests.cs | 5 +- .../Packaging/PackageInstallationTest.cs | 4 +- .../Routing/BaseUrlProviderTest.cs | 49 ++++++++ .../Routing/GetContentUrlsTests.cs | 2 +- ...oviderWithHideTopLevelNodeFromPathTests.cs | 60 +++++++++ ...erWithoutHideTopLevelNodeFromPathTests.cs} | 116 +++++------------- .../Routing/UrlsProviderWithDomainsTests.cs | 14 +-- .../Routing/UrlsWithNestedDomains.cs | 2 +- src/Umbraco.Tests/Runtimes/StandaloneTests.cs | 18 +++ .../Strings/DefaultShortStringHelperTests.cs | 69 ++++++----- .../TEMP/DatabaseContextTests.sdf | Bin 983040 -> 983040 bytes src/Umbraco.Tests/TestHelpers/TestObjects.cs | 6 +- src/Umbraco.Tests/Umbraco.Tests.csproj | 4 +- .../Controllers/ContentTypeController.cs | 2 +- 20 files changed, 235 insertions(+), 152 deletions(-) create mode 100644 src/Umbraco.Tests/Routing/BaseUrlProviderTest.cs create mode 100644 src/Umbraco.Tests/Routing/UrlProviderWithHideTopLevelNodeFromPathTests.cs rename src/Umbraco.Tests/Routing/{UrlProviderTests.cs => UrlProviderWithoutHideTopLevelNodeFromPathTests.cs} (76%) diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index 4f1c421d97..ca5569aa4d 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -15,7 +15,7 @@ - + diff --git a/src/Umbraco.Infrastructure/Configuration/ConfigModelConversionsFromLegacy.cs b/src/Umbraco.Infrastructure/Configuration/ConfigModelConversionsFromLegacy.cs index 42ed290e63..529568ca16 100644 --- a/src/Umbraco.Infrastructure/Configuration/ConfigModelConversionsFromLegacy.cs +++ b/src/Umbraco.Infrastructure/Configuration/ConfigModelConversionsFromLegacy.cs @@ -26,16 +26,18 @@ namespace Umbraco.Infrastructure.Configuration RegisterType = globalSettings.RegisterType, ReservedPaths = globalSettings.ReservedPaths, ReservedUrls = globalSettings.ReservedUrls, - Smtp = new SmtpSettings - { - DeliveryMethod = globalSettings.SmtpSettings.DeliveryMethod, - From = globalSettings.SmtpSettings.From, - Host = globalSettings.SmtpSettings.Host, - Password = globalSettings.SmtpSettings.Password, - PickupDirectoryLocation = globalSettings.SmtpSettings.PickupDirectoryLocation, - Port = globalSettings.SmtpSettings.Port, - Username = globalSettings.SmtpSettings.Username, - }, + Smtp = globalSettings.SmtpSettings != null + ? new SmtpSettings + { + DeliveryMethod = globalSettings.SmtpSettings.DeliveryMethod, + From = globalSettings.SmtpSettings.From, + Host = globalSettings.SmtpSettings.Host, + Password = globalSettings.SmtpSettings.Password, + PickupDirectoryLocation = globalSettings.SmtpSettings.PickupDirectoryLocation, + Port = globalSettings.SmtpSettings.Port, + Username = globalSettings.SmtpSettings.Username, + } + : new SmtpSettings(), TimeOutInMinutes = globalSettings.TimeOutInMinutes, UmbracoCssPath = globalSettings.UmbracoCssPath, UmbracoMediaPath = globalSettings.UmbracoMediaPath, diff --git a/src/Umbraco.Infrastructure/Packaging/PackageDataInstallation.cs b/src/Umbraco.Infrastructure/Packaging/PackageDataInstallation.cs index a868170c5f..79f830bc51 100644 --- a/src/Umbraco.Infrastructure/Packaging/PackageDataInstallation.cs +++ b/src/Umbraco.Infrastructure/Packaging/PackageDataInstallation.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Net; using System.Xml.Linq; using System.Xml.XPath; +using Microsoft.Extensions.Options; using Umbraco.Core.Collections; using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.Models; @@ -38,7 +39,7 @@ namespace Umbraco.Core.Packaging public PackageDataInstallation(ILogger logger, IFileService fileService, IMacroService macroService, ILocalizationService localizationService, IDataTypeService dataTypeService, IEntityService entityService, IContentTypeService contentTypeService, - IContentService contentService, PropertyEditorCollection propertyEditors, IScopeProvider scopeProvider, IShortStringHelper shortStringHelper, GlobalSettings globalSettings, + IContentService contentService, PropertyEditorCollection propertyEditors, IScopeProvider scopeProvider, IShortStringHelper shortStringHelper, IOptions globalSettings, ILocalizedTextService localizedTextService) { _logger = logger; @@ -49,7 +50,7 @@ namespace Umbraco.Core.Packaging _propertyEditors = propertyEditors; _scopeProvider = scopeProvider; _shortStringHelper = shortStringHelper; - _globalSettings = globalSettings; + _globalSettings = globalSettings.Value; _localizedTextService = localizedTextService; _entityService = entityService; _contentTypeService = contentTypeService; diff --git a/src/Umbraco.Infrastructure/Persistence/UmbracoDatabaseFactory.cs b/src/Umbraco.Infrastructure/Persistence/UmbracoDatabaseFactory.cs index 1b46a6a3cd..afdf4c879a 100644 --- a/src/Umbraco.Infrastructure/Persistence/UmbracoDatabaseFactory.cs +++ b/src/Umbraco.Infrastructure/Persistence/UmbracoDatabaseFactory.cs @@ -1,11 +1,8 @@ using System; using System.Data.Common; -using System.Data.SqlClient; using System.Threading; using NPoco; using NPoco.FluentMappings; -using Umbraco.Core.Composing; -using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.Models; using Umbraco.Core.Logging; using Umbraco.Core.Persistence.FaultHandling; diff --git a/src/Umbraco.Tests.Integration/RuntimeTests.cs b/src/Umbraco.Tests.Integration/RuntimeTests.cs index 11bda500b2..c51c991e26 100644 --- a/src/Umbraco.Tests.Integration/RuntimeTests.cs +++ b/src/Umbraco.Tests.Integration/RuntimeTests.cs @@ -75,7 +75,7 @@ namespace Umbraco.Tests.Integration Assert.IsFalse(MyComponent.IsInit); Assert.IsFalse(MyComponent.IsTerminated); - // TODO: found these registration were necessary here (as we haven't called the HostBuilder?), and dependencies for ComponentCollection + // TODO: found these registration were necessary here (as we haven't called the HostBuilder?), as dependencies for ComponentCollection // are not resolved. Need to check this if these explicit registrations are the best way to handle this. var contentSettings = new ContentSettingsBuilder().Build(); var coreDebugSettings = new CoreDebugSettingsBuilder().Build(); diff --git a/src/Umbraco.Tests/App.config b/src/Umbraco.Tests/App.config index 09c025aeb4..2781babfbe 100644 --- a/src/Umbraco.Tests/App.config +++ b/src/Umbraco.Tests/App.config @@ -16,7 +16,7 @@ - + diff --git a/src/Umbraco.Tests/IO/FileSystemsTests.cs b/src/Umbraco.Tests/IO/FileSystemsTests.cs index c1d3fbb331..eabd331a02 100644 --- a/src/Umbraco.Tests/IO/FileSystemsTests.cs +++ b/src/Umbraco.Tests/IO/FileSystemsTests.cs @@ -16,6 +16,7 @@ using Umbraco.Tests.TestHelpers; using Umbraco.Core.Composing.CompositionExtensions; using Current = Umbraco.Web.Composing.Current; using FileSystems = Umbraco.Core.IO.FileSystems; +using Umbraco.Tests.Common.Builders; namespace Umbraco.Tests.IO { @@ -42,7 +43,9 @@ namespace Umbraco.Tests.IO composition.RegisterUnique(TestHelper.GetHostingEnvironment()); composition.Configs.Add(() => SettingsForTests.DefaultGlobalSettings); - composition.Configs.Add(SettingsForTests.GenerateMockContentSettings); + + var globalSettings = new GlobalSettingsBuilder().Build(); + composition.Register(x => Microsoft.Extensions.Options.Options.Create(globalSettings)); composition.ComposeFileSystems(); diff --git a/src/Umbraco.Tests/Packaging/PackageInstallationTest.cs b/src/Umbraco.Tests/Packaging/PackageInstallationTest.cs index 04c51029c7..16c57a7dcb 100644 --- a/src/Umbraco.Tests/Packaging/PackageInstallationTest.cs +++ b/src/Umbraco.Tests/Packaging/PackageInstallationTest.cs @@ -60,8 +60,8 @@ namespace Umbraco.Tests.Packaging Factory.GetInstance(), Factory.GetInstance(), Factory.GetInstance(), - new GlobalSettingsBuilder().Build(), - Factory.GetInstance() ); + Microsoft.Extensions.Options.Options.Create(new GlobalSettingsBuilder().Build()), + Factory.GetInstance()); private IPackageInstallation PackageInstallation => new PackageInstallation( PackageDataInstallation, diff --git a/src/Umbraco.Tests/Routing/BaseUrlProviderTest.cs b/src/Umbraco.Tests/Routing/BaseUrlProviderTest.cs new file mode 100644 index 0000000000..999748bc73 --- /dev/null +++ b/src/Umbraco.Tests/Routing/BaseUrlProviderTest.cs @@ -0,0 +1,49 @@ +using System.Linq; +using Moq; +using Umbraco.Core; +using Umbraco.Core.Models.PublishedContent; +using Umbraco.Tests.Common; +using Umbraco.Tests.Common.Builders; +using Umbraco.Tests.TestHelpers; +using Umbraco.Web; +using Umbraco.Web.Routing; + +namespace Umbraco.Tests.Routing +{ + public abstract class BaseUrlProviderTest : BaseWebTest + { + protected IUmbracoContextAccessor UmbracoContextAccessor { get; } = new TestUmbracoContextAccessor(); + + protected abstract bool HideTopLevelNodeFromPath { get; } + + protected override void Compose() + { + base.Compose(); + Composition.Register(); + } + + protected override void ComposeSettings() + { + var contentSettings = new ContentSettingsBuilder().Build(); + var userPasswordConfigurationSettings = new UserPasswordConfigurationSettingsBuilder().Build(); + + Composition.Register(x => Microsoft.Extensions.Options.Options.Create(contentSettings)); + Composition.Register(x => Microsoft.Extensions.Options.Options.Create(userPasswordConfigurationSettings)); + + // TODO: remove this once legacy config is fully extracted. + Composition.Configs.Add(TestHelpers.SettingsForTests.GenerateMockContentSettings); + Composition.Configs.Add(TestHelpers.SettingsForTests.GenerateMockGlobalSettings); + } + + protected IPublishedUrlProvider GetPublishedUrlProvider(IUmbracoContext umbracoContext, DefaultUrlProvider urlProvider) + { + var webRoutingSettings = new WebRoutingSettingsBuilder().Build(); + return new UrlProvider( + new TestUmbracoContextAccessor(umbracoContext), + Microsoft.Extensions.Options.Options.Create(webRoutingSettings), + new UrlProviderCollection(new[] { urlProvider }), + new MediaUrlProviderCollection(Enumerable.Empty()), + Mock.Of()); + } + } +} diff --git a/src/Umbraco.Tests/Routing/GetContentUrlsTests.cs b/src/Umbraco.Tests/Routing/GetContentUrlsTests.cs index 7456d32aa4..27027c007f 100644 --- a/src/Umbraco.Tests/Routing/GetContentUrlsTests.cs +++ b/src/Umbraco.Tests/Routing/GetContentUrlsTests.cs @@ -27,7 +27,7 @@ namespace Umbraco.Tests.Routing _globalSettings = new GlobalSettingsBuilder().Build(); _webRoutingSettings = new WebRoutingSettingsBuilder().Build(); - _requestHandlerSettings = new RequestHandlerSettingsBuilder().Build(); + _requestHandlerSettings = new RequestHandlerSettingsBuilder().WithAddTrailingSlash(true).Build(); } private ILocalizedTextService GetTextService() diff --git a/src/Umbraco.Tests/Routing/UrlProviderWithHideTopLevelNodeFromPathTests.cs b/src/Umbraco.Tests/Routing/UrlProviderWithHideTopLevelNodeFromPathTests.cs new file mode 100644 index 0000000000..b38e7b5fc9 --- /dev/null +++ b/src/Umbraco.Tests/Routing/UrlProviderWithHideTopLevelNodeFromPathTests.cs @@ -0,0 +1,60 @@ +using Moq; +using NUnit.Framework; +using Umbraco.Core; +using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; +using Umbraco.Infrastructure.Configuration; +using Umbraco.Tests.Common; +using Umbraco.Tests.Common.Builders; +using Umbraco.Tests.Testing; +using Umbraco.Web.Routing; + +namespace Umbraco.Tests.Routing +{ + [TestFixture] + [UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerFixture)] + public class UrlProviderWithHideTopLevelNodeFromPathTests : BaseUrlProviderTest + { + private readonly GlobalSettings _globalSettings; + + public UrlProviderWithHideTopLevelNodeFromPathTests() + { + _globalSettings = new GlobalSettingsBuilder().WithHideTopLevelNodeFromPath(HideTopLevelNodeFromPath).Build(); + } + + protected override bool HideTopLevelNodeFromPath => true; + + protected override void ComposeSettings() + { + base.ComposeSettings(); + Composition.RegisterUnique(x => Microsoft.Extensions.Options.Options.Create(_globalSettings)); + } + + [TestCase(1046, "/")] + [TestCase(1173, "/sub1/")] + [TestCase(1174, "/sub1/sub2/")] + [TestCase(1176, "/sub1/sub-3/")] + [TestCase(1177, "/sub1/custom-sub-1/")] + [TestCase(1178, "/sub1/custom-sub-2/")] + [TestCase(1175, "/sub-2/")] + [TestCase(1172, "/test-page/")] // not hidden because not first root + public void Get_Url_Hiding_Top_Level(int nodeId, string niceUrlMatch) + { + var globalSettings = Mock.Get(Factory.GetInstance()); //this will modify the IGlobalSettings instance stored in the container + globalSettings.Setup(x => x.HideTopLevelNodeFromPath).Returns(true); + + var requestHandlerSettings = new RequestHandlerSettingsBuilder().WithAddTrailingSlash(true).Build(); + var umbracoContext = GetUmbracoContext("/test", 1111, globalSettings: ConfigModelConversionsToLegacy.ConvertGlobalSettings(_globalSettings)); + var umbracoContextAccessor = new TestUmbracoContextAccessor(umbracoContext); + var urlProvider = new DefaultUrlProvider( + Microsoft.Extensions.Options.Options.Create(requestHandlerSettings), + Logger, + Microsoft.Extensions.Options.Options.Create(_globalSettings), + new SiteDomainHelper(), umbracoContextAccessor, UriUtility); + var publishedUrlProvider = GetPublishedUrlProvider(umbracoContext, urlProvider); + + var result = publishedUrlProvider.GetUrl(nodeId); + Assert.AreEqual(niceUrlMatch, result); + } + } +} diff --git a/src/Umbraco.Tests/Routing/UrlProviderTests.cs b/src/Umbraco.Tests/Routing/UrlProviderWithoutHideTopLevelNodeFromPathTests.cs similarity index 76% rename from src/Umbraco.Tests/Routing/UrlProviderTests.cs rename to src/Umbraco.Tests/Routing/UrlProviderWithoutHideTopLevelNodeFromPathTests.cs index b84bf41bee..e4275fe391 100644 --- a/src/Umbraco.Tests/Routing/UrlProviderTests.cs +++ b/src/Umbraco.Tests/Routing/UrlProviderWithoutHideTopLevelNodeFromPathTests.cs @@ -4,7 +4,7 @@ using System.Globalization; using System.Linq; using Moq; using NUnit.Framework; -using Umbraco.Core; +using Umbraco.Core.Configuration.Models; using Umbraco.Core.Models; using Umbraco.Core.Models.PublishedContent; using Umbraco.Infrastructure.Configuration; @@ -12,9 +12,7 @@ using Umbraco.Tests.Common; using Umbraco.Tests.Common.Builders; using Umbraco.Tests.LegacyXmlPublishedCache; using Umbraco.Tests.PublishedContent; -using Umbraco.Tests.TestHelpers; using Umbraco.Tests.Testing; -using Umbraco.Web; using Umbraco.Web.PublishedCache; using Umbraco.Web.Routing; @@ -22,20 +20,21 @@ namespace Umbraco.Tests.Routing { [TestFixture] [UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerFixture)] - public class UrlProviderTests : BaseWebTest + public class UrlProviderWithoutHideTopLevelNodeFromPathTests : BaseUrlProviderTest { - private IUmbracoContextAccessor UmbracoContextAccessor { get; } = new TestUmbracoContextAccessor(); + private readonly GlobalSettings _globalSettings; - protected override void Compose() + public UrlProviderWithoutHideTopLevelNodeFromPathTests() { - base.Compose(); - Composition.Register(); + _globalSettings = new GlobalSettingsBuilder().WithHideTopLevelNodeFromPath(HideTopLevelNodeFromPath).Build(); } + protected override bool HideTopLevelNodeFromPath => false; + protected override void ComposeSettings() { - Composition.Configs.Add(TestHelpers.SettingsForTests.GenerateMockContentSettings); - Composition.Configs.Add(TestHelpers.SettingsForTests.GenerateMockGlobalSettings); + base.ComposeSettings(); + Composition.Register(x => Microsoft.Extensions.Options.Options.Create(_globalSettings)); } /// @@ -45,21 +44,17 @@ namespace Umbraco.Tests.Routing [Test] public void Ensure_Cache_Is_Correct() { - var globalSettings = new GlobalSettingsBuilder().WithHideTopLevelNodeFromPath(false).Build(); + var requestHandlerSettings = new RequestHandlerSettingsBuilder().WithAddTrailingSlash(false).Build(); - var requestHandlerSettings = new RequestHandlerSettingsBuilder().Build(); - - var umbracoContext = GetUmbracoContext("/test", 1111, globalSettings: ConfigModelConversionsToLegacy.ConvertGlobalSettings(globalSettings)); + var umbracoContext = GetUmbracoContext("/test", 1111, globalSettings: ConfigModelConversionsToLegacy.ConvertGlobalSettings(_globalSettings)); var umbracoContextAccessor = new TestUmbracoContextAccessor(umbracoContext); var urlProvider = new DefaultUrlProvider( Microsoft.Extensions.Options.Options.Create(requestHandlerSettings), Logger, - Microsoft.Extensions.Options.Options.Create(globalSettings), + Microsoft.Extensions.Options.Options.Create(_globalSettings), new SiteDomainHelper(), umbracoContextAccessor, UriUtility); var publishedUrlProvider = GetPublishedUrlProvider(umbracoContext, urlProvider); - var requestHandlerMock = Mock.Get(requestHandlerSettings); - requestHandlerMock.Setup(x => x.AddTrailingSlash).Returns(false);// (cached routes have none) var samples = new Dictionary { { 1046, "/home" }, @@ -100,18 +95,6 @@ namespace Umbraco.Tests.Routing Assert.AreEqual(0, cachedIds.Count); } - private IPublishedUrlProvider GetPublishedUrlProvider(IUmbracoContext umbracoContext, DefaultUrlProvider urlProvider) - { - var webRoutingSettings = new WebRoutingSettingsBuilder().Build(); - return new UrlProvider( - new TestUmbracoContextAccessor(umbracoContext), - Microsoft.Extensions.Options.Options.Create(webRoutingSettings), - new UrlProviderCollection(new []{urlProvider}), - new MediaUrlProviderCollection(Enumerable.Empty()), - Mock.Of()); - } - - // test hideTopLevelNodeFromPath false [TestCase(1046, "/home/")] [TestCase(1173, "/home/sub1/")] [TestCase(1174, "/home/sub1/sub2/")] @@ -122,45 +105,14 @@ namespace Umbraco.Tests.Routing [TestCase(1172, "/test-page/")] public void Get_Url_Not_Hiding_Top_Level(int nodeId, string niceUrlMatch) { - var globalSettings = new GlobalSettingsBuilder().WithHideTopLevelNodeFromPath(false).Build(); + var requestHandlerSettings = new RequestHandlerSettingsBuilder().WithAddTrailingSlash(true).Build(); - var requestHandlerSettings = new RequestHandlerSettingsBuilder().Build(); - - var umbracoContext = GetUmbracoContext("/test", 1111, globalSettings: ConfigModelConversionsToLegacy.ConvertGlobalSettings(globalSettings)); + var umbracoContext = GetUmbracoContext("/test", 1111, globalSettings: ConfigModelConversionsToLegacy.ConvertGlobalSettings(_globalSettings)); var umbracoContextAccessor = new TestUmbracoContextAccessor(umbracoContext); var urlProvider = new DefaultUrlProvider( Microsoft.Extensions.Options.Options.Create(requestHandlerSettings), Logger, - Microsoft.Extensions.Options.Options.Create(globalSettings), - new SiteDomainHelper(), umbracoContextAccessor, UriUtility); - var publishedUrlProvider = GetPublishedUrlProvider(umbracoContext, urlProvider); - - var result = publishedUrlProvider.GetUrl(nodeId); - Assert.AreEqual(niceUrlMatch, result); - } - - // no need for umbracoUseDirectoryUrls test = should be handled by UriUtilityTests - - // test hideTopLevelNodeFromPath true - [TestCase(1046, "/")] - [TestCase(1173, "/sub1/")] - [TestCase(1174, "/sub1/sub2/")] - [TestCase(1176, "/sub1/sub-3/")] - [TestCase(1177, "/sub1/custom-sub-1/")] - [TestCase(1178, "/sub1/custom-sub-2/")] - [TestCase(1175, "/sub-2/")] - [TestCase(1172, "/test-page/")] // not hidden because not first root - public void Get_Url_Hiding_Top_Level(int nodeId, string niceUrlMatch) - { - var globalSettings = new GlobalSettingsBuilder().WithHideTopLevelNodeFromPath(true).Build(); - - var requestHandlerSettings = new RequestHandlerSettingsBuilder().Build(); - var umbracoContext = GetUmbracoContext("/test", 1111, globalSettings: ConfigModelConversionsToLegacy.ConvertGlobalSettings(globalSettings)); - var umbracoContextAccessor = new TestUmbracoContextAccessor(umbracoContext); - var urlProvider = new DefaultUrlProvider( - Microsoft.Extensions.Options.Options.Create(requestHandlerSettings), - Logger, - Microsoft.Extensions.Options.Options.Create(globalSettings), + Microsoft.Extensions.Options.Options.Create(_globalSettings), new SiteDomainHelper(), umbracoContextAccessor, UriUtility); var publishedUrlProvider = GetPublishedUrlProvider(umbracoContext, urlProvider); @@ -173,9 +125,7 @@ namespace Umbraco.Tests.Routing { const string currentUri = "http://example.us/test"; - var globalSettings = new GlobalSettingsBuilder().WithHideTopLevelNodeFromPath(false).Build(); - - var requestHandlerSettings = new RequestHandlerSettingsBuilder().Build(); + var requestHandlerSettings = new RequestHandlerSettingsBuilder().WithAddTrailingSlash(true).Build(); var contentType = new PublishedContentType(Guid.NewGuid(), 666, "alias", PublishedItemType.Content, Enumerable.Empty(), Enumerable.Empty(), ContentVariation.Culture); var publishedContent = new SolidPublishedContent(contentType) { Id = 1234 }; @@ -197,13 +147,13 @@ namespace Umbraco.Tests.Routing .Returns(snapshot); var umbracoContext = GetUmbracoContext(currentUri, - globalSettings: ConfigModelConversionsToLegacy.ConvertGlobalSettings(globalSettings), + globalSettings: ConfigModelConversionsToLegacy.ConvertGlobalSettings(_globalSettings), snapshotService: snapshotService.Object); var umbracoContextAccessor = new TestUmbracoContextAccessor(umbracoContext); var urlProvider = new DefaultUrlProvider( Microsoft.Extensions.Options.Options.Create(requestHandlerSettings), Logger, - Microsoft.Extensions.Options.Options.Create(globalSettings), + Microsoft.Extensions.Options.Options.Create(_globalSettings), new SiteDomainHelper(), umbracoContextAccessor, UriUtility); var publishedUrlProvider = GetPublishedUrlProvider(umbracoContext, urlProvider); @@ -221,9 +171,7 @@ namespace Umbraco.Tests.Routing { const string currentUri = "http://example.fr/test"; - var globalSettings = new GlobalSettingsBuilder().WithHideTopLevelNodeFromPath(false).Build(); - - var requestHandlerSettings = new RequestHandlerSettingsBuilder().Build(); + var requestHandlerSettings = new RequestHandlerSettingsBuilder().WithAddTrailingSlash(true).Build(); var contentType = new PublishedContentType(Guid.NewGuid(), 666, "alias", PublishedItemType.Content, Enumerable.Empty(), Enumerable.Empty(), ContentVariation.Culture); var publishedContent = new SolidPublishedContent(contentType) { Id = 1234 }; @@ -254,13 +202,13 @@ namespace Umbraco.Tests.Routing .Returns(snapshot); var umbracoContext = GetUmbracoContext(currentUri, - globalSettings: ConfigModelConversionsToLegacy.ConvertGlobalSettings(globalSettings), + globalSettings: ConfigModelConversionsToLegacy.ConvertGlobalSettings(_globalSettings), snapshotService: snapshotService.Object); var umbracoContextAccessor = new TestUmbracoContextAccessor(umbracoContext); var urlProvider = new DefaultUrlProvider( Microsoft.Extensions.Options.Options.Create(requestHandlerSettings), Logger, - Microsoft.Extensions.Options.Options.Create(globalSettings), + Microsoft.Extensions.Options.Options.Create(_globalSettings), new SiteDomainHelper(), umbracoContextAccessor, UriUtility); var publishedUrlProvider = GetPublishedUrlProvider(umbracoContext, urlProvider); @@ -278,9 +226,7 @@ namespace Umbraco.Tests.Routing { const string currentUri = "http://example.us/test"; - var globalSettings = new GlobalSettingsBuilder().WithHideTopLevelNodeFromPath(false).Build(); - - var requestHandlerSettings = new RequestHandlerSettingsBuilder().Build(); + var requestHandlerSettings = new RequestHandlerSettingsBuilder().WithAddTrailingSlash(true).Build(); var contentType = new PublishedContentType(Guid.NewGuid(), 666, "alias", PublishedItemType.Content, Enumerable.Empty(), Enumerable.Empty(), ContentVariation.Culture); var publishedContent = new SolidPublishedContent(contentType) { Id = 1234 }; @@ -311,13 +257,13 @@ namespace Umbraco.Tests.Routing .Returns(snapshot); var umbracoContext = GetUmbracoContext(currentUri, - globalSettings: ConfigModelConversionsToLegacy.ConvertGlobalSettings(globalSettings), + globalSettings: ConfigModelConversionsToLegacy.ConvertGlobalSettings(_globalSettings), snapshotService: snapshotService.Object); var umbracoContextAccessor = new TestUmbracoContextAccessor(umbracoContext); var urlProvider = new DefaultUrlProvider( Microsoft.Extensions.Options.Options.Create(requestHandlerSettings), Logger, - Microsoft.Extensions.Options.Options.Create(globalSettings), + Microsoft.Extensions.Options.Options.Create(_globalSettings), new SiteDomainHelper(), umbracoContextAccessor, UriUtility); @@ -331,16 +277,14 @@ namespace Umbraco.Tests.Routing [Test] public void Get_Url_Relative_Or_Absolute() { - var globalSettings = new GlobalSettingsBuilder().WithHideTopLevelNodeFromPath(false).Build(); + var requestHandlerSettings = new RequestHandlerSettingsBuilder().WithAddTrailingSlash(true).Build(); - var requestHandlerSettings = new RequestHandlerSettingsBuilder().Build(); - - var umbracoContext = GetUmbracoContext("http://example.com/test", 1111, globalSettings: ConfigModelConversionsToLegacy.ConvertGlobalSettings(globalSettings)); + var umbracoContext = GetUmbracoContext("http://example.com/test", 1111, globalSettings: ConfigModelConversionsToLegacy.ConvertGlobalSettings(_globalSettings)); var umbracoContextAccessor = new TestUmbracoContextAccessor(umbracoContext); var urlProvider = new DefaultUrlProvider( Microsoft.Extensions.Options.Options.Create(requestHandlerSettings), Logger, - Microsoft.Extensions.Options.Options.Create(globalSettings), + Microsoft.Extensions.Options.Options.Create(_globalSettings), new SiteDomainHelper(), umbracoContextAccessor, UriUtility); var publishedUrlProvider = GetPublishedUrlProvider(umbracoContext, urlProvider); @@ -353,15 +297,13 @@ namespace Umbraco.Tests.Routing [Test] public void Get_Url_Unpublished() { - var globalSettings = new GlobalSettingsBuilder().WithHideTopLevelNodeFromPath(false).Build(); - var requestHandlerSettings = new RequestHandlerSettingsBuilder().Build(); var urlProvider = new DefaultUrlProvider(Microsoft.Extensions.Options.Options.Create(requestHandlerSettings), Logger, - Microsoft.Extensions.Options.Options.Create(globalSettings), + Microsoft.Extensions.Options.Options.Create(_globalSettings), new SiteDomainHelper(), UmbracoContextAccessor, UriUtility); - var umbracoContext = GetUmbracoContext("http://example.com/test", 1111, globalSettings: ConfigModelConversionsToLegacy.ConvertGlobalSettings(globalSettings)); + var umbracoContext = GetUmbracoContext("http://example.com/test", 1111, globalSettings: ConfigModelConversionsToLegacy.ConvertGlobalSettings(_globalSettings)); var publishedUrlProvider = GetPublishedUrlProvider(umbracoContext, urlProvider); //mock the Umbraco settings that we need diff --git a/src/Umbraco.Tests/Routing/UrlsProviderWithDomainsTests.cs b/src/Umbraco.Tests/Routing/UrlsProviderWithDomainsTests.cs index 0998f1e722..3e7fb611df 100644 --- a/src/Umbraco.Tests/Routing/UrlsProviderWithDomainsTests.cs +++ b/src/Umbraco.Tests/Routing/UrlsProviderWithDomainsTests.cs @@ -178,7 +178,7 @@ namespace Umbraco.Tests.Routing [TestCase(10011, "https://domain1.com", false, "/1001-1/")] public void Get_Url_SimpleDomain(int nodeId, string currentUrl, bool absolute, string expected) { - var requestHandlerSettings = new RequestHandlerSettingsBuilder().Build(); + var requestHandlerSettings = new RequestHandlerSettingsBuilder().WithAddTrailingSlash(true).Build(); var globalSettings = new GlobalSettingsBuilder().WithHideTopLevelNodeFromPath(false).Build(); @@ -213,7 +213,7 @@ namespace Umbraco.Tests.Routing [TestCase(10011, "https://domain1.com", false, "http://domain1.com/foo/1001-1/")] public void Get_Url_SimpleWithSchemeAndPath(int nodeId, string currentUrl, bool absolute, string expected) { - var requestHandlerSettings = new RequestHandlerSettingsBuilder().Build(); + var requestHandlerSettings = new RequestHandlerSettingsBuilder().WithAddTrailingSlash(true).Build(); var globalSettings = new GlobalSettingsBuilder().WithHideTopLevelNodeFromPath(false).Build(); var umbracoContext = GetUmbracoContext("/test", 1111, globalSettings: ConfigModelConversionsToLegacy.ConvertGlobalSettings(globalSettings)); @@ -239,7 +239,7 @@ namespace Umbraco.Tests.Routing [TestCase(1002, "http://domain1.com", false, "/1002/")] public void Get_Url_DeepDomain(int nodeId, string currentUrl, bool absolute, string expected) { - var requestHandlerSettings = new RequestHandlerSettingsBuilder().Build(); + var requestHandlerSettings = new RequestHandlerSettingsBuilder().WithAddTrailingSlash(true).Build(); var globalSettings = new GlobalSettingsBuilder().WithHideTopLevelNodeFromPath(false).Build(); @@ -272,7 +272,7 @@ namespace Umbraco.Tests.Routing [TestCase(100321, "http://domain3.com", false, "/fr/1003-2-1/")] public void Get_Url_NestedDomains(int nodeId, string currentUrl, bool absolute, string expected) { - var requestHandlerSettings = new RequestHandlerSettingsBuilder().Build(); + var requestHandlerSettings = new RequestHandlerSettingsBuilder().WithAddTrailingSlash(true).Build(); var globalSettings = new GlobalSettingsBuilder().WithHideTopLevelNodeFromPath(false).Build(); @@ -296,7 +296,7 @@ namespace Umbraco.Tests.Routing [Test] public void Get_Url_DomainsAndCache() { - var requestHandlerSettings = new RequestHandlerSettingsBuilder().Build(); + var requestHandlerSettings = new RequestHandlerSettingsBuilder().WithAddTrailingSlash(true).Build(); var globalSettings = new GlobalSettingsBuilder().WithHideTopLevelNodeFromPath(false).Build(); @@ -362,7 +362,7 @@ namespace Umbraco.Tests.Routing [Test] public void Get_Url_Relative_Or_Absolute() { - var requestHandlerSettings = new RequestHandlerSettingsBuilder().Build(); + var requestHandlerSettings = new RequestHandlerSettingsBuilder().WithAddTrailingSlash(true).Build(); var globalSettings = new GlobalSettingsBuilder().WithHideTopLevelNodeFromPath(false).Build(); @@ -389,7 +389,7 @@ namespace Umbraco.Tests.Routing [Test] public void Get_Url_Alternate() { - var requestHandlerSettings = new RequestHandlerSettingsBuilder().Build(); + var requestHandlerSettings = new RequestHandlerSettingsBuilder().WithAddTrailingSlash(true).Build(); var globalSettings = new GlobalSettingsBuilder().WithHideTopLevelNodeFromPath(false).Build(); diff --git a/src/Umbraco.Tests/Routing/UrlsWithNestedDomains.cs b/src/Umbraco.Tests/Routing/UrlsWithNestedDomains.cs index 6e00b7a7f0..fdd891bda6 100644 --- a/src/Umbraco.Tests/Routing/UrlsWithNestedDomains.cs +++ b/src/Umbraco.Tests/Routing/UrlsWithNestedDomains.cs @@ -36,7 +36,7 @@ namespace Umbraco.Tests.Routing public void DoNotPolluteCache() { var globalSettings = new GlobalSettingsBuilder().WithHideTopLevelNodeFromPath(false).Build(); - var requestHandlerSettings = new RequestHandlerSettingsBuilder().Build(); + var requestHandlerSettings = new RequestHandlerSettingsBuilder().WithAddTrailingSlash(true).Build(); SetDomains1(); diff --git a/src/Umbraco.Tests/Runtimes/StandaloneTests.cs b/src/Umbraco.Tests/Runtimes/StandaloneTests.cs index 2773eef4ab..4b4dfeec48 100644 --- a/src/Umbraco.Tests/Runtimes/StandaloneTests.cs +++ b/src/Umbraco.Tests/Runtimes/StandaloneTests.cs @@ -38,6 +38,7 @@ using Umbraco.Tests.Common; using Umbraco.Tests.Common.Composing; using Umbraco.Core.Media; using Umbraco.Tests.Common.Builders; +using Microsoft.Extensions.Options; namespace Umbraco.Tests.Runtimes { @@ -118,6 +119,23 @@ namespace Umbraco.Tests.Runtimes composition.RegisterUnique(); composition.RegisterUnique(_ => new MediaUrlProviderCollection(Enumerable.Empty())); + // TODO: found these registration were necessary here as dependencies for ComponentCollection + // are not resolved. Need to check this if these explicit registrations are the best way to handle this. + var contentSettings = new ContentSettingsBuilder().Build(); + var coreDebugSettings = new CoreDebugSettingsBuilder().Build(); + var nuCacheSettings = new NuCacheSettingsBuilder().Build(); + var requestHandlerSettings = new RequestHandlerSettingsBuilder().Build(); + var userPasswordConfigurationSettings = new UserPasswordConfigurationSettingsBuilder().Build(); + var webRoutingSettings = new WebRoutingSettingsBuilder().Build(); + + composition.Register(x => Options.Create(globalSettings)); + composition.Register(x => Options.Create(contentSettings)); + composition.Register(x => Options.Create(coreDebugSettings)); + composition.Register(x => Options.Create(nuCacheSettings)); + composition.Register(x => Options.Create(requestHandlerSettings)); + composition.Register(x => Options.Create(userPasswordConfigurationSettings)); + composition.Register(x => Options.Create(webRoutingSettings)); + // initialize some components only/individually composition.WithCollectionBuilder() .Clear() diff --git a/src/Umbraco.Tests/Strings/DefaultShortStringHelperTests.cs b/src/Umbraco.Tests/Strings/DefaultShortStringHelperTests.cs index 28d7d90f7e..12f5022b55 100644 --- a/src/Umbraco.Tests/Strings/DefaultShortStringHelperTests.cs +++ b/src/Umbraco.Tests/Strings/DefaultShortStringHelperTests.cs @@ -3,15 +3,12 @@ using System.Diagnostics; using System.Linq; using System.Text; using System.Text.RegularExpressions; -using Moq; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Composing; -using Umbraco.Core.Configuration.Models; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Strings; using Umbraco.Tests.Common.Builders; -using Umbraco.Tests.TestHelpers; using Umbraco.Tests.Testing; namespace Umbraco.Tests.Strings @@ -19,7 +16,6 @@ namespace Umbraco.Tests.Strings [TestFixture] public class DefaultShortStringHelperTests : UmbracoTestBase { - private RequestHandlerSettings _requestHandlerSettings; private DefaultShortStringHelper _helper; public override void SetUp() @@ -28,8 +24,8 @@ namespace Umbraco.Tests.Strings // NOTE pre-filters runs _before_ Recode takes place // so there still may be utf8 chars even though you want ascii - _requestHandlerSettings = new RequestHandlerSettingsBuilder().Build(); - _helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(_requestHandlerSettings) + var requestHandlerSettings = new RequestHandlerSettingsBuilder().Build(); + _helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(requestHandlerSettings) .WithConfig(CleanStringType.FileName, new DefaultShortStringHelperConfig.Config { //PreFilter = ClearFileChars, // done in IsTerm @@ -148,7 +144,8 @@ namespace Umbraco.Tests.Strings [Test] public void CleanStringUnderscoreInTerm() { - var helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(_requestHandlerSettings) + var requestHandlerSettings = new RequestHandlerSettingsBuilder().Build(); + var helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(requestHandlerSettings) .WithConfig(CleanStringType.Alias, new DefaultShortStringHelperConfig.Config { // underscore is accepted within terms @@ -158,7 +155,7 @@ namespace Umbraco.Tests.Strings })); Assert.AreEqual("foo_bar*nil", helper.CleanString("foo_bar nil", CleanStringType.Alias)); - helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(_requestHandlerSettings) + helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(requestHandlerSettings) .WithConfig(CleanStringType.Alias, new DefaultShortStringHelperConfig.Config { // underscore is not accepted within terms @@ -172,7 +169,8 @@ namespace Umbraco.Tests.Strings [Test] public void CleanStringLeadingChars() { - var helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(_requestHandlerSettings) + var requestHandlerSettings = new RequestHandlerSettingsBuilder().Build(); + var helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(requestHandlerSettings) .WithConfig(CleanStringType.Alias, new DefaultShortStringHelperConfig.Config { // letters and digits are valid leading chars @@ -182,7 +180,7 @@ namespace Umbraco.Tests.Strings })); Assert.AreEqual("0123foo*bar*543*nil*321", helper.CleanString("0123foo_bar 543 nil 321", CleanStringType.Alias)); - helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(_requestHandlerSettings) + helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(requestHandlerSettings) .WithConfig(CleanStringType.Alias, new DefaultShortStringHelperConfig.Config { // only letters are valid leading chars @@ -193,14 +191,15 @@ namespace Umbraco.Tests.Strings Assert.AreEqual("foo*bar*543*nil*321", helper.CleanString("0123foo_bar 543 nil 321", CleanStringType.Alias)); Assert.AreEqual("foo*bar*543*nil*321", helper.CleanString("0123 foo_bar 543 nil 321", CleanStringType.Alias)); - helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(_requestHandlerSettings)); + helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(requestHandlerSettings)); Assert.AreEqual("child2", helper.CleanStringForSafeAlias("1child2")); } [Test] public void CleanStringTermOnUpper() { - var helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(_requestHandlerSettings) + var requestHandlerSettings = new RequestHandlerSettingsBuilder().Build(); + var helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(requestHandlerSettings) .WithConfig(CleanStringType.Alias, new DefaultShortStringHelperConfig.Config { StringType = CleanStringType.Utf8 | CleanStringType.Unchanged, @@ -210,7 +209,7 @@ namespace Umbraco.Tests.Strings })); Assert.AreEqual("foo*Bar", helper.CleanString("fooBar", CleanStringType.Alias)); - helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(_requestHandlerSettings) + helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(requestHandlerSettings) .WithConfig(CleanStringType.Alias, new DefaultShortStringHelperConfig.Config { StringType = CleanStringType.Utf8 | CleanStringType.Unchanged, @@ -224,7 +223,8 @@ namespace Umbraco.Tests.Strings [Test] public void CleanStringAcronymOnNonUpper() { - var helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(_requestHandlerSettings) + var requestHandlerSettings = new RequestHandlerSettingsBuilder().Build(); + var helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(requestHandlerSettings) .WithConfig(CleanStringType.Alias, new DefaultShortStringHelperConfig.Config { StringType = CleanStringType.Utf8 | CleanStringType.Unchanged, @@ -237,7 +237,7 @@ namespace Umbraco.Tests.Strings Assert.AreEqual("foo*BAnil", helper.CleanString("foo BAnil", CleanStringType.Alias)); Assert.AreEqual("foo*Bnil", helper.CleanString("foo Bnil", CleanStringType.Alias)); - helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(_requestHandlerSettings) + helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(requestHandlerSettings) .WithConfig(CleanStringType.Alias, new DefaultShortStringHelperConfig.Config { StringType = CleanStringType.Utf8 | CleanStringType.Unchanged, @@ -254,7 +254,8 @@ namespace Umbraco.Tests.Strings [Test] public void CleanStringGreedyAcronyms() { - var helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(_requestHandlerSettings) + var requestHandlerSettings = new RequestHandlerSettingsBuilder().Build(); + var helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(requestHandlerSettings) .WithConfig(CleanStringType.Alias, new DefaultShortStringHelperConfig.Config { StringType = CleanStringType.Utf8 | CleanStringType.Unchanged, @@ -267,7 +268,7 @@ namespace Umbraco.Tests.Strings Assert.AreEqual("foo*BA*nil", helper.CleanString("foo BAnil", CleanStringType.Alias)); Assert.AreEqual("foo*Bnil", helper.CleanString("foo Bnil", CleanStringType.Alias)); - helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(_requestHandlerSettings) + helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(requestHandlerSettings) .WithConfig(CleanStringType.Alias, new DefaultShortStringHelperConfig.Config { StringType = CleanStringType.Utf8 | CleanStringType.Unchanged, @@ -284,7 +285,8 @@ namespace Umbraco.Tests.Strings [Test] public void CleanStringWhiteSpace() { - var helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(_requestHandlerSettings) + var requestHandlerSettings = new RequestHandlerSettingsBuilder().Build(); + var helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(requestHandlerSettings) .WithConfig(CleanStringType.Alias, new DefaultShortStringHelperConfig.Config { StringType = CleanStringType.Utf8 | CleanStringType.Unchanged, @@ -297,7 +299,8 @@ namespace Umbraco.Tests.Strings [Test] public void CleanStringSeparator() { - var helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(_requestHandlerSettings) + var requestHandlerSettings = new RequestHandlerSettingsBuilder().Build(); + var helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(requestHandlerSettings) .WithConfig(CleanStringType.Alias, new DefaultShortStringHelperConfig.Config { StringType = CleanStringType.Utf8 | CleanStringType.Unchanged, @@ -305,7 +308,7 @@ namespace Umbraco.Tests.Strings })); Assert.AreEqual("foo*bar", helper.CleanString("foo bar", CleanStringType.Alias)); - helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(_requestHandlerSettings) + helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(requestHandlerSettings) .WithConfig(CleanStringType.Alias, new DefaultShortStringHelperConfig.Config { StringType = CleanStringType.Utf8 | CleanStringType.Unchanged, @@ -313,14 +316,14 @@ namespace Umbraco.Tests.Strings })); Assert.AreEqual("foo bar", helper.CleanString("foo bar", CleanStringType.Alias)); - helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(_requestHandlerSettings) + helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(requestHandlerSettings) .WithConfig(CleanStringType.Alias, new DefaultShortStringHelperConfig.Config { StringType = CleanStringType.Utf8 | CleanStringType.Unchanged })); Assert.AreEqual("foobar", helper.CleanString("foo bar", CleanStringType.Alias)); - helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(_requestHandlerSettings) + helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(requestHandlerSettings) .WithConfig(CleanStringType.Alias, new DefaultShortStringHelperConfig.Config { StringType = CleanStringType.Utf8 | CleanStringType.Unchanged, @@ -332,7 +335,8 @@ namespace Umbraco.Tests.Strings [Test] public void CleanStringSymbols() { - var helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(_requestHandlerSettings) + var requestHandlerSettings = new RequestHandlerSettingsBuilder().Build(); + var helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(requestHandlerSettings) .WithConfig(CleanStringType.Alias, new DefaultShortStringHelperConfig.Config { StringType = CleanStringType.Utf8 | CleanStringType.Unchanged, @@ -386,7 +390,9 @@ namespace Umbraco.Tests.Strings [Test] public void CleanStringEncoding() { - var helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(_requestHandlerSettings) + var requestHandlerSettings = new RequestHandlerSettingsBuilder().Build(); + + var helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(requestHandlerSettings) .WithConfig(CleanStringType.Alias, new DefaultShortStringHelperConfig.Config { StringType = CleanStringType.Utf8 | CleanStringType.Unchanged, @@ -395,7 +401,7 @@ namespace Umbraco.Tests.Strings Assert.AreEqual("中文测试", helper.CleanString("中文测试", CleanStringType.Alias)); Assert.AreEqual("léger*中文测试*ZÔRG", helper.CleanString("léger 中文测试 ZÔRG", CleanStringType.Alias)); - helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(_requestHandlerSettings) + helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(requestHandlerSettings) .WithConfig(CleanStringType.Alias, new DefaultShortStringHelperConfig.Config { StringType = CleanStringType.Ascii | CleanStringType.Unchanged, @@ -408,12 +414,12 @@ namespace Umbraco.Tests.Strings [Test] public void CleanStringDefaultConfig() { - var settings = _requestHandlerSettings; - var contentMock = Mock.Get(settings); - contentMock.Setup(x => x.CharCollection).Returns(Enumerable.Empty()); - contentMock.Setup(x => x.ConvertUrlsToAscii).Returns("false"); + var requestHandlerSettings = new RequestHandlerSettingsBuilder() + .WithCharCollection(Enumerable.Empty()) + .WithConvertUrlsToAscii("false") + .Build(); - var helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(settings)); + var helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(requestHandlerSettings)); const string input = "0123 中文测试 中文测试 léger ZÔRG (2) a?? *x"; @@ -434,7 +440,8 @@ namespace Umbraco.Tests.Strings [Test] public void CleanStringCasing() { - var helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(_requestHandlerSettings) + var requestHandlerSettings = new RequestHandlerSettingsBuilder().Build(); + var helper = new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(requestHandlerSettings) .WithConfig(CleanStringType.Alias, new DefaultShortStringHelperConfig.Config { StringType = CleanStringType.Utf8 | CleanStringType.Unchanged, diff --git a/src/Umbraco.Tests/TEMP/DatabaseContextTests.sdf b/src/Umbraco.Tests/TEMP/DatabaseContextTests.sdf index d13671d77ac03808a75689089e57bfb8fcf82b8d..c21739c1249f0c8f447f8ff94d081f3b0448d5bb 100644 GIT binary patch delta 2869 zcmZuzdr(x@8Q;76eRuEPy_d((#Rn!JC=f9`8f(y!O4I^HYZox9@(@VXYK=&$CW>iT z1`|zHg06Tl6v4*U5{Qyga%`#&F&S-|wpr8Kis_8_M`l{-I4F{Uu}#lC_v{5S*%`RM z@Avy&d(L;xUB5re@6Uqco6`#p!K_&>#bz6@*=)f6F2zgizxfGgk9@n$Cfgh<$ju0; z;;pWgweZW%`3XJX&(|?yZjKb+l%XvTv>iNz3k{3($3aR@MMHZeR86lu6o7WG&fU6f zHva6XY;Q}0r>0+;+5^E|PW-mW;p@5fj}!@)8D`+b^=Umb`*%yY+%S7iTrc-P{+AFN zfT1EYB2YTC5uf1B9}KM$X!e~Ds=HH+-{I=Oof3hv?-t`C&b8ewHPPYW)q*M;F2QUr zo*yn0=o|M|3bf^(PoO{C3;89F6yahX;UDn{^vTE?T*|oxpRE+=@Mo*=yPUhtI1}Z5 zUM5h-=fwgkqm=?xjh15$kN9}BOrUvVA+C9>NN_`Ag#zW?FTgw=(Q2XL`^ES@&J})9 zB+wgQlnA6gD8_uQZhEjrpvw=QHc?ONe?N}*WUbKlMS$0KLktAp8tRFY2GczE?a#j( z#k5UqI*bqBC+hJU+Kj`IN28fmKUwojgW>Ra-1-6vjZ&5qR~XgV@c2jzk?OI;Flj=w zbPcf7l6aI zS&{WI+WZ5@#vo+XN6jM;2SNOap-^^=qa}gw&4dmxG25?v;(Z@_iTg4s1C7ZnS7kCYy6J`=+-TEsaQ|Xil zq~q_$74w^Cw@OY@dq@qZ(=+fiTC$HMJdVxyd?*k1KAMTtq>QC6r!fm~jf^{mPYgY> z2%o72`eE-03f;KEX-Q_|Z&IwsT~T#N3^kT?*U36*J1DnUA!e^l4RW(ZEvDOFl@DZlrbk~K*vw8#re>a&J-i`LP#%o+ zB)H!m+QPJ|$=Z-SxD^`a@3=;w!r5nKOrk>-PD#PNp+4#IP0ru?JnJtU4Xa^UAk3_= z&#chrWECDx(Qm!Lw3x}-fT7JF-v84VnU*$D>-8vuv5*#jD~ipe(vPo%ijmBj%6Zcy z1(LRbR>UhMi2H?Zu0V9M;Fj-k-5 zunXXTk<&b=O(&H|84r#Vu1=)}Fu)0xa|S(mMk%cZ?{C^}umNz{6+9w3@{!79mmiyi z$*XH*+9R$vCve8~K-l##)tu*%#v&WjC@KuX9)S1A{-wV?ouc|J?9q6n~P&pqlj+ zsz0daeuaAUin>^D6@mOoU$~;~N%g$(-D(V_^zs28s5#Ml8F*~ zNxBEqAf{|~IR&r#-+*nrc{VD=#<|tV>ZjbNOfqz%YP8tr4gj`?zUEr$Epd0BgijN1 zdz(N@#$OmpZ-y2lnUJz{OA%im4;YoT5eJ?$2%eU|F7w>l+3iqYo(k;N(UwT~E1@S5 zc9P?aeT|^6*J;&&rz|D(ZiyyUFKf-?LLlf>=)%3)X&HYloW*1;Y0%C~iMMk$p1KU# zw(mb|uGIVNC#94wbHjL1kMiO)u~ECe6*`t(tmy?k9qK7@-GV2db^BWBC(Hr`JCQoniF!w@6@|3ACcqHUHTLm RPluLbFIx&)T^rWu|39waNN)fD delta 2869 zcmZuzdr(wW7{7P-J9qEiy%*P^MG1|ECYTA>QyXR^Eg@1{QC9_&#me!8Qb{SAETf}6 z%uujH8G)147%0$2$4VO-O?ynWnoeRbtf`q=r;vw1QgrS;=UyK52kiI#e&6|h-+t#i z=WHO576_!lvcl#Kdtm%{2?U`{5Cr-moJtVse?f54zyAJy;X=G1NCGUxm)xSiseVBz zOy1u-Aqasi4J}CS5Tf=?QD;}wJhun=bPu=2!K9#nckM_xSN}_81=M;qBdlH!jL%>} zZA}Wie4uz+5JH`D&D+OFiHMTTg4M-I1YI`Wvcw{tOvmUfz9$2+q*c3sy3ZWVU< zxb<9QKlh3WQ zJ!af(y(U)GJD;=dz1iH#_-h`wsx7PYFH<@Dnz`c5Yq>m5>C550Ue&jRTc`V$Gb@<< z_t^wbRl~bayTL2`zy?AvwuX4(#BhoyKX2TLNXo6U8N*_7UY!esKfqCx+cuO7h~W{? z@Xp+B0_9?wgJse;9`DEEHk6|`hK#EcF96EbZG-Yvi`y+X3pZriRdV|);%Dxw~x1 zV8x`9jOn&_%i&D$y9f*+TggCZHmm1S$adLo#p{|1PC9RU-hvWwDAg{L@OfJc*JX(! zzOi*Y1aCdM*GC}Te!qy8^16&Ks*$?8?U8`;t!6~evTwKCL|jy=MdP9qFben1vhVy~ z;@gZND*|5vkn&7>NV1}DB~=gDSBBti^xF3r;vj_ldOkvrag@mIu6Q^E%%+=?g}o<1 zBfS%#??2$Yo1viscFw5pC(r_kc2qE^(+b{k0ybMv7NI&fDwdy)-}?eyvfM;Ms}10VTr&o&(T)IaYL9U;Ijv%z$>eIM8QI+MgKD{s%5eDh4&nGd{&=Sdt zi6NEK(b^&?Db9YKKqH##uqd{jhY8wdL5bMtqyH#+&yF56x-XGV{(=t_Mr)8y4 zkS8RCV?8}%r*#xkZrxC>T?(&r*g@TQP#!6vM+N|Aom>KFg8@*@G2~!_oL25Gx{RULnKmfUIP!GxqwxM(=TjEJFUGA0 zoFirQIM2*42qXHpL(V2fSS>J$aOz{NB+Qj?fvse>9tIqm*Wki;nN=`#y9xQYv>aMIT95I0d%; zlysJW*Yzu)%|`KbRC4rltK!8AU2ibZyirw><8xJ*k;X&h&2=>%gzn0pXYB(u32o6e zny08SA~Okq;^SiNE>8+#A6wy|F0p$}hJ;`zU zzPib)Woi)&V$8QC3a{ItRt*ppA+JpC+NmCqP$`$;lQDC*dR&}Pd1`g+X-F65+`u|@ zlK!L=QzgUEALIhjzdUR)1#uQ#n}1}y;%*D6C=4nhH*z=!W}XM(), Mock.Of(x => x.ApplicationPhysicalPath == ioHelper.MapPath("~"))), @@ -245,7 +246,8 @@ namespace Umbraco.Tests.TestHelpers public IScopeProvider GetScopeProvider(ILogger logger, ITypeFinder typeFinder = null, FileSystems fileSystems = null, IUmbracoDatabaseFactory databaseFactory = null) { var globalSettings = new GlobalSettingsBuilder().Build(); - var connectionStrings = new ConnectionStringsBuilder().Build(); + var connectionString = ConfigurationManager.ConnectionStrings[Constants.System.UmbracoConnectionName].ConnectionString; + var connectionStrings = new ConnectionStringsBuilder().WithUmbracoConnectionString(connectionString).Build(); var coreDebugSettings = new CoreDebugSettingsBuilder().Build(); if (databaseFactory == null) diff --git a/src/Umbraco.Tests/Umbraco.Tests.csproj b/src/Umbraco.Tests/Umbraco.Tests.csproj index 193b4093f5..75c4bd773d 100644 --- a/src/Umbraco.Tests/Umbraco.Tests.csproj +++ b/src/Umbraco.Tests/Umbraco.Tests.csproj @@ -141,6 +141,8 @@ + + @@ -195,7 +197,7 @@ - + diff --git a/src/Umbraco.Web.BackOffice/Controllers/ContentTypeController.cs b/src/Umbraco.Web.BackOffice/Controllers/ContentTypeController.cs index 659062f4f9..f8bdd20f3e 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/ContentTypeController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/ContentTypeController.cs @@ -578,7 +578,7 @@ namespace Umbraco.Web.BackOffice.Controllers } var dataInstaller = new PackageDataInstallation(_logger, _fileService, _macroService, _LocalizationService, - _dataTypeService, _entityService, _contentTypeService, _contentService, _propertyEditors, _scopeProvider, _shortStringHelper, _globalSettings, _localizedTextService); + _dataTypeService, _entityService, _contentTypeService, _contentService, _propertyEditors, _scopeProvider, _shortStringHelper, Options.Create(_globalSettings), _localizedTextService); var xd = new XmlDocument {XmlResolver = null}; xd.Load(filePath); From 3d55dcd3c4e3f222a922929c25fbcfb39644d1be Mon Sep 17 00:00:00 2001 From: Bjarke Berg Date: Wed, 26 Aug 2020 08:05:15 +0200 Subject: [PATCH 282/826] Merge remote-tracking branch 'netcore/dev' into netcore/netcore --- build/NuSpecs/UmbracoCms.Web.nuspec | 1 + .../Legacy/GlobalSettings.cs | 12 + .../Models/GlobalSettings.cs | 2 + .../Configuration/IGlobalSettings.cs | 10 + src/Umbraco.Core/Constants-AppSettings.cs | 9 +- src/Umbraco.Core/Constants-SvgSanitizer.cs | 23 + .../Constants-SystemDirectories.cs | 2 + .../ContentEditing/PropertyTypeBasic.cs | 8 + src/Umbraco.Core/Models/IconModel.cs | 8 + .../Repositories/IMemberGroupRepository.cs | 10 +- .../EmailAddressConfiguration.cs | 6 +- .../PropertyValueConverterBase.cs | 20 +- .../PropertyEditors/TrueFalseConfiguration.cs | 14 +- .../Scheduling/TempFileCleanup.cs | 2 + .../Services/IMemberGroupService.cs | 4 +- .../BackOfficeExamineSearcher.cs | 3 + .../Logging/Serilog/LoggerConfigExtensions.cs | 24 +- .../Logging/Viewer/SerilogJsonLogViewer.cs | 2 - .../Models/ContentEditing/EntityBasic.cs | 3 +- .../Models/ContentEditing/MediaItemDisplay.cs | 2 +- .../Models/ContentEditing/MemberDisplay.cs | 3 + .../Mapping/ContentTypeMapDefinition.cs | 4 +- .../Models/Mapping/EntityMapDefinition.cs | 6 +- .../Models/Mapping/PropertyTypeGroupMapper.cs | 2 + .../Querying/ExpressionVisitorBase.cs | 4 +- .../Implement/EntityRepository.cs | 6 +- .../Implement/MemberGroupRepository.cs | 12 +- .../Repositories/Implement/UserRepository.cs | 12 +- .../SqlSyntax/SqlServerSyntaxProvider.cs | 5 +- .../Persistence/UmbracoDatabaseFactory.cs | 1 + .../TrueFalsePropertyEditor.cs | 2 +- .../UserPickerConfiguration.cs | 3 +- .../UserPickerPropertyEditor.cs | 4 +- .../MemberPickerValueConverter.cs | 2 + .../Services/Implement/ContentService.cs | 2 + .../Services/Implement/MemberGroupService.cs | 8 + .../Services/Implement/RelationService.cs | 10 +- .../WebAssets/JsInitialize.js | 1 + .../integration/Settings/documentTypes.ts | 2 + .../Settings/partialsViewMacroFiles.ts | 140 +- .../integration/Settings/partialsViews.ts | 152 +- .../cypress/integration/Settings/scripts.ts | 2 +- .../cypress/integration/Settings/templates.ts | 151 +- .../integration/Tour/backofficeTour.ts | 49 + src/Umbraco.Tests.AcceptanceTest/package.json | 4 +- .../Builders/GlobalSettingsBuilder.cs | 4 + .../Services/UserServiceTests.cs | 57 + src/Umbraco.Tests/TestHelpers/TestObjects.cs | 2 +- .../Controllers/BackOfficeServerVariables.cs | 4 + .../Controllers/ContentTypeController.cs | 53 +- .../Controllers/DictionaryController.cs | 79 +- .../Controllers/IconController.cs | 108 ++ .../Controllers/ImagesController.cs | 63 +- .../Controllers/LogController.cs | 7 + .../Controllers/MediaController.cs | 21 +- .../Controllers/MediaTypeController.cs | 48 + .../Controllers/MemberGroupController.cs | 46 + .../Controllers/MemberTypeController.cs | 50 +- .../Controllers/RelationTypeController.cs | 37 + .../Controllers/TemplateController.cs | 41 +- .../Controllers/TemplateQueryController.cs | 6 +- .../Controllers/UsersController.cs | 28 + .../Mapping/MemberMapDefinition.cs | 1 + .../Umbraco.Web.BackOffice.csproj | 1 + .../gulp/tasks/dependencies.js | 16 +- .../lib/bootstrap/less/pager.less | 24 +- .../lib/bootstrap/less/pagination.less | 31 +- src/Umbraco.Web.UI.Client/package.json | 3 +- .../src/assets/icons/icon-activity.svg | 1 + .../src/assets/icons/icon-add.svg | 1 + .../src/assets/icons/icon-adressbook.svg | 1 + .../src/assets/icons/icon-alarm-clock.svg | 1 + .../src/assets/icons/icon-alert-alt.svg | 1 + .../src/assets/icons/icon-alert.svg | 1 + .../src/assets/icons/icon-alt.svg | 1 + .../src/assets/icons/icon-anchor.svg | 1 + .../src/assets/icons/icon-app.svg | 1 + .../assets/icons/icon-application-error.svg | 1 + .../icons/icon-application-window-alt.svg | 1 + .../assets/icons/icon-application-window.svg | 1 + .../src/assets/icons/icon-arrivals.svg | 1 + .../src/assets/icons/icon-arrow-down.svg | 1 + .../src/assets/icons/icon-arrow-left.svg | 1 + .../src/assets/icons/icon-arrow-right.svg | 1 + .../src/assets/icons/icon-arrow-up.svg | 1 + .../src/assets/icons/icon-art-easel.svg | 1 + .../src/assets/icons/icon-article.svg | 1 + .../src/assets/icons/icon-attachment.svg | 1 + .../src/assets/icons/icon-auction-hammer.svg | 1 + .../src/assets/icons/icon-autofill.svg | 1 + .../src/assets/icons/icon-award.svg | 1 + .../src/assets/icons/icon-axis-rotation-2.svg | 1 + .../src/assets/icons/icon-axis-rotation-3.svg | 1 + .../src/assets/icons/icon-axis-rotation.svg | 1 + .../src/assets/icons/icon-baby-stroller.svg | 1 + .../src/assets/icons/icon-backspace.svg | 1 + .../src/assets/icons/icon-badge-add.svg | 1 + .../src/assets/icons/icon-badge-count.svg | 1 + .../src/assets/icons/icon-badge-remove.svg | 1 + .../assets/icons/icon-badge-restricted.svg | 1 + .../src/assets/icons/icon-ball.svg | 1 + .../src/assets/icons/icon-band-aid.svg | 1 + .../src/assets/icons/icon-bar-chart.svg | 1 + .../src/assets/icons/icon-barcode.svg | 1 + .../src/assets/icons/icon-bars.svg | 1 + .../src/assets/icons/icon-battery-full.svg | 1 + .../src/assets/icons/icon-battery-low.svg | 1 + .../src/assets/icons/icon-beer-glass.svg | 1 + .../src/assets/icons/icon-bell-off.svg | 1 + .../src/assets/icons/icon-bell.svg | 1 + .../src/assets/icons/icon-bill-dollar.svg | 1 + .../src/assets/icons/icon-bill-euro.svg | 1 + .../src/assets/icons/icon-bill-pound.svg | 1 + .../src/assets/icons/icon-bill-yen.svg | 1 + .../src/assets/icons/icon-bill.svg | 1 + .../src/assets/icons/icon-billboard.svg | 1 + .../src/assets/icons/icon-bills-dollar.svg | 1 + .../src/assets/icons/icon-bills-euro.svg | 1 + .../src/assets/icons/icon-bills-pound.svg | 1 + .../src/assets/icons/icon-bills-yen.svg | 1 + .../src/assets/icons/icon-bills.svg | 1 + .../src/assets/icons/icon-binarycode.svg | 1 + .../src/assets/icons/icon-binoculars.svg | 1 + .../src/assets/icons/icon-bird.svg | 1 + .../src/assets/icons/icon-birthday-cake.svg | 1 + .../src/assets/icons/icon-block.svg | 1 + .../src/assets/icons/icon-blueprint.svg | 1 + .../src/assets/icons/icon-bluetooth.svg | 1 + .../src/assets/icons/icon-boat-shipping.svg | 1 + .../src/assets/icons/icon-bomb.svg | 1 + .../src/assets/icons/icon-bones.svg | 1 + .../src/assets/icons/icon-book-alt-2.svg | 1 + .../src/assets/icons/icon-book-alt.svg | 1 + .../src/assets/icons/icon-book.svg | 1 + .../src/assets/icons/icon-bookmark.svg | 1 + .../src/assets/icons/icon-books.svg | 1 + .../src/assets/icons/icon-box-alt.svg | 1 + .../src/assets/icons/icon-box-open.svg | 1 + .../src/assets/icons/icon-box.svg | 1 + .../src/assets/icons/icon-brackets.svg | 1 + .../src/assets/icons/icon-brick.svg | 1 + .../src/assets/icons/icon-briefcase.svg | 1 + .../src/assets/icons/icon-browser-window.svg | 1 + .../src/assets/icons/icon-brush-alt-2.svg | 1 + .../src/assets/icons/icon-brush-alt.svg | 1 + .../src/assets/icons/icon-brush.svg | 1 + .../src/assets/icons/icon-bug.svg | 1 + .../src/assets/icons/icon-bulleted-list.svg | 1 + .../src/assets/icons/icon-burn.svg | 1 + .../src/assets/icons/icon-bus.svg | 1 + .../src/assets/icons/icon-calculator.svg | 1 + .../src/assets/icons/icon-calendar-alt.svg | 1 + .../src/assets/icons/icon-calendar.svg | 1 + .../src/assets/icons/icon-camcorder.svg | 1 + .../src/assets/icons/icon-camera-roll.svg | 1 + .../src/assets/icons/icon-candy.svg | 1 + .../src/assets/icons/icon-caps-lock.svg | 1 + .../src/assets/icons/icon-car.svg | 1 + .../src/assets/icons/icon-cash-register.svg | 1 + .../src/assets/icons/icon-categories.svg | 1 + .../src/assets/icons/icon-certificate.svg | 1 + .../src/assets/icons/icon-chart-curve.svg | 1 + .../src/assets/icons/icon-chart.svg | 1 + .../src/assets/icons/icon-chat-active.svg | 1 + .../src/assets/icons/icon-chat.svg | 1 + .../src/assets/icons/icon-check.svg | 1 + .../icons/icon-checkbox-dotted-active.svg | 1 + .../src/assets/icons/icon-checkbox-dotted.svg | 1 + .../src/assets/icons/icon-checkbox-empty.svg | 1 + .../src/assets/icons/icon-checkbox.svg | 1 + .../src/assets/icons/icon-chess.svg | 1 + .../src/assets/icons/icon-chip-alt.svg | 1 + .../src/assets/icons/icon-chip.svg | 1 + .../src/assets/icons/icon-cinema.svg | 1 + .../icons/icon-circle-dotted-active.svg | 1 + .../src/assets/icons/icon-circle-dotted.svg | 1 + .../src/assets/icons/icon-circuits.svg | 1 + .../src/assets/icons/icon-circus.svg | 1 + .../src/assets/icons/icon-client.svg | 1 + .../src/assets/icons/icon-clothes-hanger.svg | 1 + .../src/assets/icons/icon-cloud-drive.svg | 1 + .../src/assets/icons/icon-cloud-upload.svg | 1 + .../src/assets/icons/icon-cloud.svg | 1 + .../src/assets/icons/icon-cloudy.svg | 1 + .../src/assets/icons/icon-clubs.svg | 1 + .../src/assets/icons/icon-cocktail.svg | 1 + .../src/assets/icons/icon-code.svg | 1 + .../src/assets/icons/icon-coffee.svg | 1 + .../src/assets/icons/icon-coin-dollar.svg | 1 + .../src/assets/icons/icon-coin-euro.svg | 1 + .../src/assets/icons/icon-coin-pound.svg | 1 + .../src/assets/icons/icon-coin-yen.svg | 1 + .../src/assets/icons/icon-coin.svg | 1 + .../src/assets/icons/icon-coins-alt.svg | 1 + .../assets/icons/icon-coins-dollar-alt.svg | 1 + .../src/assets/icons/icon-coins-dollar.svg | 1 + .../src/assets/icons/icon-coins-euro-alt.svg | 1 + .../src/assets/icons/icon-coins-euro.svg | 1 + .../src/assets/icons/icon-coins-pound-alt.svg | 1 + .../src/assets/icons/icon-coins-pound.svg | 1 + .../src/assets/icons/icon-coins-yen-alt.svg | 1 + .../src/assets/icons/icon-coins-yen.svg | 1 + .../src/assets/icons/icon-coins.svg | 1 + .../src/assets/icons/icon-color-bucket.svg | 1 + .../src/assets/icons/icon-colorpicker.svg | 1 + .../src/assets/icons/icon-columns.svg | 1 + .../src/assets/icons/icon-comb.svg | 1 + .../icons/icon-combination-lock-open.svg | 1 + .../assets/icons/icon-combination-lock.svg | 1 + .../src/assets/icons/icon-command.svg | 1 + .../src/assets/icons/icon-company.svg | 1 + .../src/assets/icons/icon-compress.svg | 1 + .../src/assets/icons/icon-connection.svg | 1 + .../src/assets/icons/icon-console.svg | 1 + .../src/assets/icons/icon-contrast.svg | 1 + .../assets/icons/icon-conversation-alt.svg | 1 + .../src/assets/icons/icon-conversation.svg | 1 + .../src/assets/icons/icon-coverflow.svg | 1 + .../src/assets/icons/icon-credit-card-alt.svg | 1 + .../src/assets/icons/icon-credit-card.svg | 1 + .../src/assets/icons/icon-crop.svg | 1 + .../src/assets/icons/icon-crosshair.svg | 1 + .../src/assets/icons/icon-crown-alt.svg | 1 + .../src/assets/icons/icon-crown.svg | 1 + .../src/assets/icons/icon-cupcake.svg | 1 + .../src/assets/icons/icon-curve.svg | 1 + .../src/assets/icons/icon-cut.svg | 1 + .../src/assets/icons/icon-dashboard.svg | 1 + .../src/assets/icons/icon-defrag.svg | 1 + .../src/assets/icons/icon-delete-key.svg | 1 + .../src/assets/icons/icon-delete.svg | 1 + .../src/assets/icons/icon-departure.svg | 1 + .../src/assets/icons/icon-desk.svg | 1 + .../src/assets/icons/icon-desktop.svg | 1 + .../src/assets/icons/icon-diagnostics.svg | 1 + .../assets/icons/icon-diagonal-arrow-alt.svg | 1 + .../src/assets/icons/icon-diagonal-arrow.svg | 1 + .../src/assets/icons/icon-diamond.svg | 1 + .../src/assets/icons/icon-diamonds.svg | 1 + .../src/assets/icons/icon-dice.svg | 1 + .../src/assets/icons/icon-diploma-alt.svg | 1 + .../src/assets/icons/icon-diploma.svg | 1 + .../src/assets/icons/icon-directions-alt.svg | 1 + .../src/assets/icons/icon-directions.svg | 1 + .../src/assets/icons/icon-disc.svg | 1 + .../src/assets/icons/icon-disk-image.svg | 1 + .../src/assets/icons/icon-display.svg | 1 + .../src/assets/icons/icon-dna.svg | 1 + .../src/assets/icons/icon-dock-connector.svg | 1 + .../icons/icon-document-dashed-line.svg | 1 + .../src/assets/icons/icon-document.svg | 1 + .../src/assets/icons/icon-documents.svg | 1 + .../src/assets/icons/icon-dollar-bag.svg | 1 + .../src/assets/icons/icon-donate.svg | 1 + .../src/assets/icons/icon-door-open-alt.svg | 1 + .../src/assets/icons/icon-door-open.svg | 1 + .../src/assets/icons/icon-download-alt.svg | 1 + .../src/assets/icons/icon-download.svg | 1 + .../src/assets/icons/icon-drop.svg | 1 + .../src/assets/icons/icon-eco.svg | 1 + .../src/assets/icons/icon-economy.svg | 1 + .../src/assets/icons/icon-edit.svg | 1 + .../src/assets/icons/icon-eject.svg | 1 + .../src/assets/icons/icon-employee.svg | 1 + .../assets/icons/icon-energy-saving-bulb.svg | 1 + .../src/assets/icons/icon-enter.svg | 1 + .../src/assets/icons/icon-equalizer.svg | 1 + .../src/assets/icons/icon-escape.svg | 1 + .../src/assets/icons/icon-ethernet.svg | 1 + .../src/assets/icons/icon-euro-bag.svg | 1 + .../src/assets/icons/icon-exit-fullscreen.svg | 1 + .../src/assets/icons/icon-eye.svg | 1 + .../src/assets/icons/icon-facebook-like.svg | 1 + .../src/assets/icons/icon-factory.svg | 1 + .../src/assets/icons/icon-favorite.svg | 1 + .../src/assets/icons/icon-female-symbol.svg | 1 + .../src/assets/icons/icon-file-cabinet.svg | 1 + .../src/assets/icons/icon-files.svg | 1 + .../src/assets/icons/icon-filter-arrows.svg | 1 + .../src/assets/icons/icon-filter.svg | 1 + .../src/assets/icons/icon-fingerprint.svg | 1 + .../src/assets/icons/icon-fire.svg | 1 + .../src/assets/icons/icon-firewall.svg | 1 + .../src/assets/icons/icon-firewire.svg | 1 + .../src/assets/icons/icon-flag-alt.svg | 1 + .../src/assets/icons/icon-flag.svg | 1 + .../src/assets/icons/icon-flash.svg | 1 + .../src/assets/icons/icon-flashlight.svg | 1 + .../src/assets/icons/icon-flowerpot.svg | 1 + .../src/assets/icons/icon-folder-open.svg | 1 + .../src/assets/icons/icon-folder-outline.svg | 1 + .../src/assets/icons/icon-folder.svg | 1 + .../src/assets/icons/icon-folders.svg | 1 + .../src/assets/icons/icon-font.svg | 1 + .../src/assets/icons/icon-food.svg | 1 + .../src/assets/icons/icon-footprints.svg | 1 + .../src/assets/icons/icon-forking.svg | 1 + .../src/assets/icons/icon-frame-alt.svg | 1 + .../src/assets/icons/icon-frame.svg | 1 + .../src/assets/icons/icon-fullscreen-alt.svg | 1 + .../src/assets/icons/icon-fullscreen.svg | 1 + .../src/assets/icons/icon-game.svg | 1 + .../src/assets/icons/icon-geometry.svg | 1 + .../src/assets/icons/icon-gift.svg | 1 + .../src/assets/icons/icon-glasses.svg | 1 + .../src/assets/icons/icon-globe-alt.svg | 1 + .../src/assets/icons/icon-globe-asia.svg | 1 + .../assets/icons/icon-globe-europe-africa.svg | 1 + .../icons/icon-globe-inverted-america.svg | 1 + .../assets/icons/icon-globe-inverted-asia.svg | 1 + .../icon-globe-inverted-europe-africa.svg | 1 + .../src/assets/icons/icon-globe.svg | 1 + .../src/assets/icons/icon-gps.svg | 1 + .../src/assets/icons/icon-graduate.svg | 1 + .../src/assets/icons/icon-grid.svg | 1 + .../src/assets/icons/icon-hammer.svg | 1 + .../src/assets/icons/icon-hand-active-alt.svg | 1 + .../src/assets/icons/icon-hand-active.svg | 1 + .../assets/icons/icon-hand-pointer-alt.svg | 1 + .../src/assets/icons/icon-hand-pointer.svg | 1 + .../src/assets/icons/icon-handprint.svg | 1 + .../src/assets/icons/icon-handshake.svg | 1 + .../src/assets/icons/icon-handtool-alt.svg | 1 + .../src/assets/icons/icon-handtool.svg | 1 + .../src/assets/icons/icon-hard-drive-alt.svg | 1 + .../src/assets/icons/icon-hard-drive.svg | 1 + .../src/assets/icons/icon-hat.svg | 1 + .../src/assets/icons/icon-hd.svg | 1 + .../src/assets/icons/icon-headphones.svg | 1 + .../src/assets/icons/icon-headset.svg | 1 + .../src/assets/icons/icon-hearts.svg | 1 + .../src/assets/icons/icon-height.svg | 1 + .../src/assets/icons/icon-help-alt.svg | 1 + .../src/assets/icons/icon-help.svg | 1 + .../src/assets/icons/icon-home.svg | 1 + .../src/assets/icons/icon-hourglass.svg | 1 + .../src/assets/icons/icon-imac.svg | 1 + .../src/assets/icons/icon-inactive-line.svg | 1 + .../src/assets/icons/icon-inbox-full.svg | 1 + .../src/assets/icons/icon-inbox.svg | 1 + .../src/assets/icons/icon-indent.svg | 1 + .../src/assets/icons/icon-infinity.svg | 1 + .../src/assets/icons/icon-info.svg | 1 + .../src/assets/icons/icon-invoice.svg | 1 + .../src/assets/icons/icon-ipad.svg | 1 + .../src/assets/icons/icon-iphone.svg | 1 + .../assets/icons/icon-item-arrangement.svg | 1 + .../src/assets/icons/icon-junk.svg | 1 + .../src/assets/icons/icon-key.svg | 1 + .../src/assets/icons/icon-keyboard.svg | 1 + .../src/assets/icons/icon-keychain.svg | 1 + .../src/assets/icons/icon-keyhole.svg | 1 + .../src/assets/icons/icon-lab.svg | 1 + .../src/assets/icons/icon-laptop.svg | 1 + .../src/assets/icons/icon-layers-alt.svg | 1 + .../src/assets/icons/icon-layers.svg | 1 + .../src/assets/icons/icon-layout.svg | 1 + .../assets/icons/icon-left-double-arrow.svg | 1 + .../src/assets/icons/icon-legal.svg | 1 + .../src/assets/icons/icon-lense.svg | 1 + .../src/assets/icons/icon-library.svg | 1 + .../src/assets/icons/icon-light-down.svg | 1 + .../src/assets/icons/icon-light-up.svg | 1 + .../assets/icons/icon-lightbulb-active.svg | 1 + .../src/assets/icons/icon-lightbulb.svg | 1 + .../src/assets/icons/icon-lightning.svg | 1 + .../src/assets/icons/icon-link.svg | 1 + .../src/assets/icons/icon-linux-tux.svg | 1 + .../src/assets/icons/icon-list.svg | 1 + .../src/assets/icons/icon-load.svg | 1 + .../src/assets/icons/icon-loading.svg | 1 + .../src/assets/icons/icon-locate.svg | 1 + .../assets/icons/icon-location-near-me.svg | 1 + .../src/assets/icons/icon-location-nearby.svg | 1 + .../src/assets/icons/icon-lock.svg | 1 + .../src/assets/icons/icon-log-out.svg | 1 + .../src/assets/icons/icon-logout.svg | 1 + .../src/assets/icons/icon-loupe.svg | 1 + .../src/assets/icons/icon-magnet.svg | 1 + .../src/assets/icons/icon-mailbox.svg | 1 + .../src/assets/icons/icon-male-and-female.svg | 1 + .../src/assets/icons/icon-male-symbol.svg | 1 + .../src/assets/icons/icon-map-alt.svg | 1 + .../src/assets/icons/icon-map-location.svg | 1 + .../src/assets/icons/icon-map-marker.svg | 1 + .../src/assets/icons/icon-map.svg | 1 + .../src/assets/icons/icon-medal.svg | 1 + .../assets/icons/icon-medical-emergency.svg | 1 + .../src/assets/icons/icon-medicine.svg | 1 + .../src/assets/icons/icon-meeting.svg | 1 + .../src/assets/icons/icon-megaphone.svg | 1 + .../src/assets/icons/icon-merge.svg | 1 + .../src/assets/icons/icon-message-open.svg | 1 + .../assets/icons/icon-message-unopened.svg | 1 + .../src/assets/icons/icon-message.svg | 1 + .../src/assets/icons/icon-microscope.svg | 1 + .../src/assets/icons/icon-mindmap.svg | 1 + .../src/assets/icons/icon-mobile.svg | 1 + .../assets/icons/icon-molecular-network.svg | 1 + .../src/assets/icons/icon-molecular.svg | 1 + .../src/assets/icons/icon-mountain.svg | 1 + .../src/assets/icons/icon-mouse-cursor.svg | 1 + .../src/assets/icons/icon-mouse.svg | 1 + .../src/assets/icons/icon-movie-alt.svg | 1 + .../src/assets/icons/icon-movie.svg | 1 + .../icons/icon-multiple-credit-cards.svg | 1 + .../assets/icons/icon-multiple-windows.svg | 1 + .../src/assets/icons/icon-music.svg | 1 + .../src/assets/icons/icon-name-badge.svg | 1 + .../assets/icons/icon-navigation-bottom.svg | 1 + .../src/assets/icons/icon-navigation-down.svg | 1 + .../assets/icons/icon-navigation-first.svg | 1 + .../icons/icon-navigation-horizontal.svg | 1 + .../src/assets/icons/icon-navigation-last.svg | 1 + .../src/assets/icons/icon-navigation-left.svg | 1 + .../assets/icons/icon-navigation-right.svg | 1 + .../src/assets/icons/icon-navigation-road.svg | 1 + .../src/assets/icons/icon-navigation-top.svg | 1 + .../src/assets/icons/icon-navigation-up.svg | 1 + .../assets/icons/icon-navigation-vertical.svg | 1 + .../src/assets/icons/icon-navigation.svg | 1 + .../assets/icons/icon-navigational-arrow.svg | 1 + .../src/assets/icons/icon-network-alt.svg | 1 + .../src/assets/icons/icon-newspaper-alt.svg | 1 + .../src/assets/icons/icon-newspaper.svg | 1 + .../src/assets/icons/icon-next-media.svg | 1 + .../src/assets/icons/icon-next.svg | 1 + .../src/assets/icons/icon-nodes.svg | 1 + .../src/assets/icons/icon-notepad-alt.svg | 1 + .../src/assets/icons/icon-notepad.svg | 1 + .../src/assets/icons/icon-old-key.svg | 1 + .../src/assets/icons/icon-old-phone.svg | 1 + .../src/assets/icons/icon-operator.svg | 1 + .../src/assets/icons/icon-ordered-list.svg | 1 + .../src/assets/icons/icon-os-x.svg | 1 + .../src/assets/icons/icon-out.svg | 1 + .../src/assets/icons/icon-outbox.svg | 1 + .../src/assets/icons/icon-outdent.svg | 1 + .../src/assets/icons/icon-page-add.svg | 1 + .../src/assets/icons/icon-page-down.svg | 1 + .../src/assets/icons/icon-page-remove.svg | 1 + .../src/assets/icons/icon-page-restricted.svg | 1 + .../src/assets/icons/icon-page-up.svg | 1 + .../src/assets/icons/icon-paint-roller.svg | 1 + .../src/assets/icons/icon-palette.svg | 1 + .../src/assets/icons/icon-panel-show.svg | 1 + .../src/assets/icons/icon-pannel-close.svg | 1 + .../src/assets/icons/icon-pants.svg | 1 + .../src/assets/icons/icon-paper-bag.svg | 1 + .../src/assets/icons/icon-paper-plane-alt.svg | 1 + .../src/assets/icons/icon-paper-plane.svg | 1 + .../src/assets/icons/icon-parachute-drop.svg | 1 + .../assets/icons/icon-parental-control.svg | 1 + .../src/assets/icons/icon-partly-cloudy.svg | 1 + .../src/assets/icons/icon-paste-in.svg | 1 + .../src/assets/icons/icon-path.svg | 1 + .../src/assets/icons/icon-pause.svg | 1 + .../src/assets/icons/icon-pc.svg | 1 + .../src/assets/icons/icon-people-alt-2.svg | 1 + .../src/assets/icons/icon-people-alt.svg | 1 + .../src/assets/icons/icon-people-female.svg | 1 + .../src/assets/icons/icon-people.svg | 1 + .../src/assets/icons/icon-phone-ring.svg | 1 + .../src/assets/icons/icon-phone.svg | 1 + .../src/assets/icons/icon-photo-album.svg | 1 + .../src/assets/icons/icon-picture.svg | 1 + .../src/assets/icons/icon-pictures-alt-2.svg | 1 + .../src/assets/icons/icon-pictures-alt.svg | 1 + .../src/assets/icons/icon-pictures.svg | 1 + .../src/assets/icons/icon-pie-chart.svg | 1 + .../src/assets/icons/icon-piggy-bank.svg | 1 + .../src/assets/icons/icon-pin-location.svg | 1 + .../src/assets/icons/icon-piracy.svg | 1 + .../src/assets/icons/icon-plane.svg | 1 + .../src/assets/icons/icon-planet.svg | 1 + .../src/assets/icons/icon-play.svg | 1 + .../src/assets/icons/icon-playing-cards.svg | 1 + .../src/assets/icons/icon-playlist.svg | 1 + .../src/assets/icons/icon-plugin.svg | 1 + .../src/assets/icons/icon-podcast.svg | 1 + .../src/assets/icons/icon-poker-chip.svg | 1 + .../src/assets/icons/icon-poll.svg | 1 + .../src/assets/icons/icon-post-it.svg | 1 + .../src/assets/icons/icon-pound-bag.svg | 1 + .../src/assets/icons/icon-power-outlet.svg | 1 + .../src/assets/icons/icon-power.svg | 1 + .../src/assets/icons/icon-presentation.svg | 1 + .../src/assets/icons/icon-previous-media.svg | 1 + .../src/assets/icons/icon-previous.svg | 1 + .../src/assets/icons/icon-price-dollar.svg | 1 + .../src/assets/icons/icon-price-euro.svg | 1 + .../src/assets/icons/icon-price-pound.svg | 1 + .../src/assets/icons/icon-price-yen.svg | 1 + .../src/assets/icons/icon-print.svg | 1 + .../src/assets/icons/icon-printer-alt.svg | 1 + .../src/assets/icons/icon-projector.svg | 1 + .../src/assets/icons/icon-pulse.svg | 1 + .../src/assets/icons/icon-pushpin.svg | 1 + .../src/assets/icons/icon-qr-code.svg | 1 + .../src/assets/icons/icon-quote.svg | 1 + .../src/assets/icons/icon-radio-alt.svg | 1 + .../src/assets/icons/icon-radio-receiver.svg | 1 + .../src/assets/icons/icon-radio.svg | 1 + .../src/assets/icons/icon-rain.svg | 1 + .../src/assets/icons/icon-rate.svg | 1 + .../src/assets/icons/icon-re-post.svg | 1 + .../src/assets/icons/icon-readonly.svg | 1 + .../src/assets/icons/icon-receipt-alt.svg | 1 + .../src/assets/icons/icon-receipt-dollar.svg | 1 + .../src/assets/icons/icon-receipt-euro.svg | 1 + .../src/assets/icons/icon-receipt-pound.svg | 1 + .../src/assets/icons/icon-receipt-yen.svg | 1 + .../src/assets/icons/icon-reception.svg | 1 + .../src/assets/icons/icon-record.svg | 1 + .../src/assets/icons/icon-redo.svg | 1 + .../src/assets/icons/icon-refresh.svg | 1 + .../src/assets/icons/icon-remote.svg | 1 + .../src/assets/icons/icon-remove.svg | 1 + .../src/assets/icons/icon-repeat-one.svg | 1 + .../src/assets/icons/icon-repeat.svg | 1 + .../src/assets/icons/icon-reply-arrow.svg | 1 + .../src/assets/icons/icon-resize.svg | 1 + .../src/assets/icons/icon-return-to-top.svg | 1 + .../assets/icons/icon-right-double-arrow.svg | 1 + .../src/assets/icons/icon-road.svg | 1 + .../src/assets/icons/icon-roadsign.svg | 1 + .../src/assets/icons/icon-rocket.svg | 1 + .../src/assets/icons/icon-rss.svg | 1 + .../src/assets/icons/icon-ruler-alt.svg | 1 + .../src/assets/icons/icon-ruler.svg | 1 + .../src/assets/icons/icon-safe.svg | 1 + .../src/assets/icons/icon-safedial.svg | 1 + .../src/assets/icons/icon-sandbox-toys.svg | 1 + .../src/assets/icons/icon-satellite-dish.svg | 1 + .../src/assets/icons/icon-save.svg | 1 + .../src/assets/icons/icon-scan.svg | 1 + .../src/assets/icons/icon-school.svg | 1 + .../src/assets/icons/icon-screensharing.svg | 1 + .../src/assets/icons/icon-script-alt.svg | 1 + .../src/assets/icons/icon-script.svg | 1 + .../src/assets/icons/icon-scull.svg | 1 + .../src/assets/icons/icon-search.svg | 1 + .../src/assets/icons/icon-security-camera.svg | 1 + .../src/assets/icons/icon-sensor.svg | 1 + .../src/assets/icons/icon-server-alt.svg | 1 + .../src/assets/icons/icon-server.svg | 1 + .../src/assets/icons/icon-settings-alt-2.svg | 1 + .../src/assets/icons/icon-settings-alt.svg | 1 + .../src/assets/icons/icon-settings.svg | 1 + .../src/assets/icons/icon-share-alt-2.svg | 1 + .../src/assets/icons/icon-share-alt.svg | 1 + .../src/assets/icons/icon-share.svg | 1 + .../src/assets/icons/icon-sharing-iphone.svg | 1 + .../src/assets/icons/icon-shield.svg | 1 + .../src/assets/icons/icon-shift.svg | 1 + .../src/assets/icons/icon-shipping-box.svg | 1 + .../src/assets/icons/icon-shipping.svg | 1 + .../src/assets/icons/icon-shoe.svg | 1 + .../icons/icon-shopping-basket-alt-2.svg | 1 + .../assets/icons/icon-shopping-basket-alt.svg | 1 + .../src/assets/icons/icon-shopping-basket.svg | 1 + .../src/assets/icons/icon-shorts.svg | 1 + .../src/assets/icons/icon-shuffle.svg | 1 + .../src/assets/icons/icon-sience.svg | 1 + .../src/assets/icons/icon-simcard.svg | 1 + .../src/assets/icons/icon-single-note.svg | 1 + .../src/assets/icons/icon-sitemap.svg | 1 + .../src/assets/icons/icon-sleep.svg | 1 + .../src/assets/icons/icon-slideshow.svg | 1 + .../src/assets/icons/icon-smiley-inverted.svg | 1 + .../src/assets/icons/icon-smiley.svg | 1 + .../src/assets/icons/icon-snow.svg | 1 + .../src/assets/icons/icon-sound-low.svg | 1 + .../src/assets/icons/icon-sound-medium.svg | 1 + .../src/assets/icons/icon-sound-off.svg | 1 + .../src/assets/icons/icon-sound-waves.svg | 1 + .../src/assets/icons/icon-sound.svg | 1 + .../src/assets/icons/icon-spades.svg | 1 + .../src/assets/icons/icon-speaker.svg | 1 + .../src/assets/icons/icon-speed-gauge.svg | 1 + .../src/assets/icons/icon-split-alt.svg | 1 + .../src/assets/icons/icon-split.svg | 1 + .../src/assets/icons/icon-sprout.svg | 1 + .../src/assets/icons/icon-squiggly-line.svg | 1 + .../src/assets/icons/icon-ssd.svg | 1 + .../src/assets/icons/icon-stacked-disks.svg | 1 + .../src/assets/icons/icon-stamp.svg | 1 + .../src/assets/icons/icon-stop-alt.svg | 1 + .../src/assets/icons/icon-stop-hand.svg | 1 + .../src/assets/icons/icon-stop.svg | 1 + .../src/assets/icons/icon-store.svg | 1 + .../src/assets/icons/icon-stream.svg | 1 + .../src/assets/icons/icon-sunny.svg | 1 + .../src/assets/icons/icon-sweatshirt.svg | 1 + .../src/assets/icons/icon-sync.svg | 1 + .../src/assets/icons/icon-t-shirt.svg | 1 + .../src/assets/icons/icon-tab-key.svg | 1 + .../src/assets/icons/icon-tab.svg | 1 + .../src/assets/icons/icon-tactics.svg | 1 + .../src/assets/icons/icon-tag.svg | 1 + .../src/assets/icons/icon-tags.svg | 1 + .../src/assets/icons/icon-takeaway-cup.svg | 1 + .../src/assets/icons/icon-target.svg | 1 + .../assets/icons/icon-temperatrure-alt.svg | 1 + .../src/assets/icons/icon-temperature.svg | 1 + .../src/assets/icons/icon-terminal.svg | 1 + .../src/assets/icons/icon-theater.svg | 1 + .../src/assets/icons/icon-theif.svg | 1 + .../src/assets/icons/icon-thought-bubble.svg | 1 + .../src/assets/icons/icon-thumb-down.svg | 1 + .../src/assets/icons/icon-thumb-up.svg | 1 + .../src/assets/icons/icon-thumbnail-list.svg | 1 + .../assets/icons/icon-thumbnails-small.svg | 1 + .../src/assets/icons/icon-thumbnails.svg | 1 + .../src/assets/icons/icon-ticket.svg | 1 + .../src/assets/icons/icon-time.svg | 1 + .../src/assets/icons/icon-timer.svg | 1 + .../src/assets/icons/icon-tools.svg | 1 + .../src/assets/icons/icon-top.svg | 1 + .../src/assets/icons/icon-traffic-alt.svg | 1 + .../src/assets/icons/icon-trafic.svg | 1 + .../src/assets/icons/icon-train.svg | 1 + .../src/assets/icons/icon-trash-alt-2.svg | 1 + .../src/assets/icons/icon-trash-alt.svg | 1 + .../src/assets/icons/icon-trash.svg | 1 + .../src/assets/icons/icon-tree.svg | 1 + .../src/assets/icons/icon-trophy.svg | 1 + .../src/assets/icons/icon-truck.svg | 1 + .../src/assets/icons/icon-tv-old.svg | 1 + .../src/assets/icons/icon-tv.svg | 1 + .../src/assets/icons/icon-umb-content.svg | 1 + .../src/assets/icons/icon-umb-contour.svg | 1 + .../src/assets/icons/icon-umb-deploy.svg | 1 + .../src/assets/icons/icon-umb-developer.svg | 1 + .../src/assets/icons/icon-umb-media.svg | 1 + .../src/assets/icons/icon-umb-members.svg | 1 + .../src/assets/icons/icon-umb-settings.svg | 1 + .../src/assets/icons/icon-umb-users.svg | 1 + .../src/assets/icons/icon-umbrella.svg | 1 + .../src/assets/icons/icon-undo.svg | 1 + .../src/assets/icons/icon-universal.svg | 1 + .../src/assets/icons/icon-unlocked.svg | 1 + .../src/assets/icons/icon-untitled.svg | 1 + .../src/assets/icons/icon-usb-connector.svg | 1 + .../src/assets/icons/icon-usb.svg | 1 + .../src/assets/icons/icon-user-female.svg | 1 + .../assets/icons/icon-user-females-alt.svg | 1 + .../src/assets/icons/icon-user-females.svg | 1 + .../src/assets/icons/icon-user-glasses.svg | 1 + .../src/assets/icons/icon-user.svg | 1 + .../src/assets/icons/icon-users-alt.svg | 1 + .../src/assets/icons/icon-users.svg | 1 + .../src/assets/icons/icon-utilities.svg | 1 + .../src/assets/icons/icon-vcard.svg | 1 + .../src/assets/icons/icon-video.svg | 1 + .../src/assets/icons/icon-voice.svg | 1 + .../src/assets/icons/icon-wall-plug.svg | 1 + .../src/assets/icons/icon-wallet.svg | 1 + .../src/assets/icons/icon-wand.svg | 1 + .../src/assets/icons/icon-war.svg | 1 + .../src/assets/icons/icon-weight.svg | 1 + .../src/assets/icons/icon-width.svg | 1 + .../src/assets/icons/icon-wifi.svg | 1 + .../src/assets/icons/icon-window-popin.svg | 1 + .../src/assets/icons/icon-window-sizes.svg | 1 + .../src/assets/icons/icon-windows.svg | 1 + .../src/assets/icons/icon-wine-glass.svg | 1 + .../src/assets/icons/icon-wrench.svg | 1 + .../src/assets/icons/icon-wrong.svg | 1 + .../src/assets/icons/icon-yen-bag.svg | 1 + .../src/assets/icons/icon-zip.svg | 1 + .../src/assets/icons/icon-zom-out.svg | 1 + .../src/assets/icons/icon-zoom-in.svg | 1 + .../application/umbappheader.directive.js | 28 +- .../application/umbsearch.directive.js | 3 +- .../components/buttons/umbbutton.directive.js | 4 +- .../buttons/umbbuttonellipsis.directive.js | 93 + .../components/buttons/umbtoggle.directive.js | 32 +- .../components/content/edit.controller.js | 8 +- .../umbvariantcontenteditors.directive.js | 47 +- .../components/forms/umbcheckbox.directive.js | 11 +- .../forms/umbfocuslock.directive.js | 82 + .../forms/umbradiobutton.directive.js | 15 +- .../forms/umbsearchfilter.directive.js | 84 + .../components/grid/grid.rte.directive.js | 15 +- .../imaging/umbimagecrop.directive.js | 389 ++-- .../media/umbmedianodeinfo.directive.js | 4 +- .../member/umbmembernodeinfo.directive.js | 13 + .../overlays/umboverlay.directive.js | 25 +- .../components/tree/umbtree.directive.js | 22 +- .../components/tree/umbtreeitem.directive.js | 4 +- .../components/umbchildselector.directive.js | 30 +- .../components/umbconfirmaction.directive.js | 32 +- .../components/umbdatetimepicker.directive.js | 2 +- .../components/umbgroupsbuilder.directive.js | 25 +- .../components/umbicon.directive.js | 86 + .../components/umbmediagrid.directive.js | 38 +- .../components/umbminilistview.directive.js | 5 +- .../components/umbtooltip.directive.js | 62 +- .../upload/umbfileupload.directive.js | 11 + .../upload/umbpropertyfileupload.directive.js | 23 +- .../validation/valformmanager.directive.js | 2 +- .../src/common/mocks/resources/media.mocks.js | 10 +- .../common/mocks/umbraco.servervariables.js | 3 +- .../src/common/resources/content.resource.js | 8 +- .../src/common/resources/media.resource.js | 4 +- .../common/resources/membergroup.resource.js | 4 +- .../common/resources/membertype.resource.js | 11 +- .../src/common/resources/users.resource.js | 33 + .../src/common/services/assets.service.js | 14 +- .../services/contenteditinghelper.service.js | 5 +- .../src/common/services/editor.service.js | 17 - .../src/common/services/focuslock.service.js | 26 + .../src/common/services/formhelper.service.js | 61 +- .../src/common/services/iconhelper.service.js | 155 +- .../common/services/mediahelper.service.js | 9 +- .../src/common/services/navigation.service.js | 7 +- .../src/common/services/overlay.service.js | 15 +- .../src/common/services/search.service.js | 39 +- .../src/common/services/tinymce.service.js | 5 + .../src/common/services/tree.service.js | 8 +- .../services/umbrequesthelper.service.js | 8 +- .../common/services/usershelper.service.js | 43 +- .../src/common/services/util.service.js | 6 +- .../src/installer/steps/database.html | 219 +-- src/Umbraco.Web.UI.Client/src/less/belle.less | 3 + .../src/less/buttons.less | 5 +- .../src/less/colors.less | 4 +- .../buttons/umb-button-ellipsis.less | 76 + .../components/buttons/umb-button-group.less | 2 +- .../less/components/buttons/umb-button.less | 5 + .../less/components/buttons/umb-toggle.less | 50 +- .../src/less/components/editor.less | 22 +- .../editor/umb-variant-switcher.less | 41 +- .../src/less/components/overlays.less | 2 +- .../less/components/tree/umb-tree-item.less | 5 +- .../src/less/components/tree/umb-tree.less | 34 +- .../src/less/components/umb-badge.less | 10 + .../src/less/components/umb-code-snippet.less | 1 + .../less/components/umb-confirm-action.less | 134 +- .../less/components/umb-date-time-picker.less | 25 +- .../umb-editor-navigation-item.less | 6 +- .../src/less/components/umb-form-check.less | 25 +- .../src/less/components/umb-grid.less | 14 +- .../less/components/umb-group-builder.less | 34 +- .../src/less/components/umb-icon.less | 9 + .../src/less/components/umb-iconpicker.less | 52 +- .../src/less/components/umb-list.less | 2 +- .../src/less/components/umb-logviewer.less | 15 +- .../src/less/components/umb-media-grid.less | 16 + .../less/components/umb-mini-list-view.less | 4 + .../less/components/umb-multiple-textbox.less | 19 +- .../less/components/umb-nested-content.less | 2 +- .../src/less/components/umb-packages.less | 19 +- .../src/less/components/umb-pagination.less | 8 +- .../less/components/umb-property-actions.less | 2 +- .../components/umb-property-file-upload.less | 12 + .../src/less/components/umb-stylesheet.less | 1 + .../src/less/components/umb-table.less | 22 +- .../src/less/components/umb-tags-editor.less | 53 + .../components/users/umb-user-preview.less | 15 +- src/Umbraco.Web.UI.Client/src/less/forms.less | 8 +- .../src/less/helveticons.less | 1302 +++++++------- .../src/less/listview.less | 5 +- src/Umbraco.Web.UI.Client/src/less/main.less | 2 +- .../src/less/modals.less | 50 +- .../src/less/pages/welcome-dashboard.less | 27 +- src/Umbraco.Web.UI.Client/src/less/panel.less | 7 +- .../src/less/properties.less | 9 +- .../src/less/property-editors.less | 58 +- .../src/less/variables.less | 6 +- .../common/drawers/help/help.controller.js | 8 +- .../src/views/common/drawers/help/help.html | 10 +- .../compositions/compositions.controller.js | 50 +- .../compositions/compositions.html | 54 +- .../datatypeconfigurationpicker.controller.js | 13 +- .../datatypepicker/datatypepicker.html | 23 +- .../iconpicker/iconpicker.controller.js | 19 +- .../iconpicker/iconpicker.html | 10 +- .../insertfield/insertfield.html | 2 +- .../itempicker/itempicker.html | 2 +- .../macroparameterpicker.html | 23 +- .../mediapicker/mediapicker.controller.js | 115 +- .../mediapicker/mediapicker.html | 189 +- .../overlays/mediacropdetails.controller.js | 59 + .../overlays/mediacropdetails.html | 78 + .../propertysettings.controller.js | 4 +- .../querybuilder/querybuilder.html | 16 +- .../sectionpicker/sectionpicker.controller.js | 8 +- .../treepicker/treepicker.controller.js | 182 +- .../treepicker/treepicker.html | 10 +- .../usergrouppicker.controller.js | 8 +- .../userpicker/userpicker.controller.js | 58 +- .../userpicker/userpicker.html | 4 +- .../itempicker/itempicker.controller.js | 6 +- .../overlays/itempicker/itempicker.html | 19 +- .../logviewersearch/logviewersearch.html | 6 +- .../src/views/common/overlays/user/user.html | 2 +- .../application/umb-app-header.html | 8 - .../application/umb-navigation.html | 2 +- .../components/application/umb-sections.html | 9 +- .../application/umbtour/umb-tour-step.html | 3 +- .../buttons/umb-button-ellipsis.html | 12 + .../components/buttons/umb-button-group.html | 19 +- .../views/components/buttons/umb-button.html | 14 +- .../views/components/buttons/umb-toggle.html | 8 +- .../src/views/components/content/edit.html | 4 +- .../editor/umb-editor-content-header.html | 15 +- .../components/editor/umb-editor-header.html | 2 +- .../components/editor/umb-editor-menu.html | 1 + .../editor/umb-editor-navigation.html | 17 +- .../views/components/forms/umb-checkbox.html | 35 +- .../components/forms/umb-radiobutton.html | 30 +- .../components/forms/umb-search-filter.html | 28 + .../components/imaging/umb-image-crop.html | 4 +- .../components/media/umb-media-node-info.html | 1 - .../member/umb-member-node-info.html | 4 +- .../components/overlays/umb-overlay.html | 9 +- .../umb-property-actions.html | 20 +- .../views/components/tabs/umb-tabs-nav.html | 12 +- .../components/tags/umb-tags-editor.html | 10 +- .../views/components/tree/umb-tree-item.html | 21 +- .../components/tree/umb-tree-search-box.html | 4 +- .../src/views/components/tree/umb-tree.html | 29 +- .../views/components/umb-child-selector.html | 2 +- .../views/components/umb-confirm-action.html | 31 +- .../components/umb-date-time-picker.html | 6 +- .../views/components/umb-groups-builder.html | 16 +- .../src/views/components/umb-icon.html | 4 + .../views/components/umb-layout-selector.html | 17 +- .../components/umb-list-view-settings.html | 12 +- .../src/views/components/umb-media-grid.html | 134 +- .../views/components/umb-mini-list-view.html | 10 +- .../src/views/components/umb-pagination.html | 24 +- .../components/upload/umb-file-dropzone.html | 156 +- .../upload/umb-property-file-upload.html | 14 +- .../components/users/umb-user-preview.html | 11 +- .../content/content.notify.controller.js | 2 +- .../content/content.rights.controller.js | 10 +- .../views/content/content.sort.controller.js | 5 +- .../content/overlays/publish.controller.js | 144 +- .../src/views/content/overlays/publish.html | 15 +- .../overlays/publishdescendants.controller.js | 44 +- .../content/overlays/publishdescendants.html | 15 +- .../views/content/overlays/save.controller.js | 62 +- .../content/overlays/schedule.controller.js | 72 +- .../src/views/content/overlays/schedule.html | 47 +- .../overlays/sendtopublish.controller.js | 26 +- .../content/overlays/unpublish.controller.js | 50 +- .../src/views/content/protect.html | 20 +- .../src/views/content/sort.html | 12 +- .../content/redirecturls.controller.js | 1 + .../views/dashboard/content/redirecturls.html | 24 +- .../dashboard/dashboard.tabs.controller.js | 9 +- .../views/dashboard/default/ourumbraco.jpg | Bin 25651 -> 0 bytes .../views/dashboard/default/ourumbraco.png | Bin 0 -> 186465 bytes .../default/startupdashboardintro.html | 19 +- .../src/views/dashboard/default/umbracotv.jpg | Bin 49817 -> 0 bytes .../src/views/dashboard/default/umbracotv.png | Bin 0 -> 314485 bytes .../settings/examinemanagementresults.html | 1 + .../src/views/dataTypes/delete.html | 4 +- .../src/views/dictionary/create.html | 8 +- .../dictionary.create.controller.js | 1 - .../dictionary/dictionary.list.controller.js | 2 +- .../src/views/dictionary/edit.html | 2 +- .../src/views/dictionary/list.html | 17 +- .../src/views/documentTypes/create.html | 2 + .../src/views/documentTypes/delete.html | 3 +- .../views/documentTypes/edit.controller.js | 24 +- .../permissions/permissions.controller.js | 25 +- .../src/views/languages/edit.controller.js | 2 +- .../views/logViewer/overview.controller.js | 62 +- .../src/views/logViewer/overview.html | 1 + .../src/views/logViewer/search.controller.js | 66 +- .../src/views/logViewer/search.html | 72 +- .../src/views/media/media.edit.controller.js | 9 +- .../src/views/mediaTypes/delete.html | 3 +- .../src/views/mediaTypes/edit.controller.js | 35 +- .../permissions/permissions.controller.js | 23 +- .../member/apps/content/content.controller.js | 8 + .../views/member/apps/content/content.html | 2 +- .../views/member/member.edit.controller.js | 219 ++- .../src/views/memberTypes/delete.html | 3 +- .../src/views/memberTypes/edit.controller.js | 75 +- .../src/views/packages/edit.html | 8 +- .../src/views/packages/views/repo.html | 98 +- .../src/views/partialViews/create.html | 18 +- .../views/prevalueeditors/imagepicker.html | 19 +- .../prevalueeditors/mediafolderpicker.html | 18 +- .../views/prevalueeditors/mediapicker.html | 11 +- .../views/prevalueeditors/multivalues.html | 4 +- .../src/views/prevalueeditors/treepicker.html | 11 +- .../src/views/prevalueeditors/treesource.html | 39 +- .../prevalueeditors/treesourcetypepicker.html | 9 +- .../boolean/boolean.controller.js | 36 +- .../propertyeditors/boolean/boolean.html | 4 +- .../contentpicker/contentpicker.controller.js | 70 +- .../contentpicker/contentpicker.html | 2 +- .../datepicker/datepicker.controller.js | 4 +- .../datepicker/datepicker.html | 19 +- .../dropdownFlexible.controller.js | 12 +- .../grid/dialogs/editconfig.controller.js | 60 +- .../grid/dialogs/editconfig.html | 14 +- .../grid/dialogs/layoutconfig.controller.js | 49 +- .../grid/dialogs/layoutconfig.html | 247 ++- .../grid/dialogs/rowconfig.controller.js | 68 +- .../grid/dialogs/rowconfig.html | 183 +- .../dialogs/rowdeleteconfirm.controller.js | 16 - .../grid/dialogs/rowdeleteconfirm.html | 46 - .../grid/editors/media.controller.js | 62 +- .../propertyeditors/grid/editors/media.html | 18 +- .../propertyeditors/grid/grid.controller.js | 18 +- .../src/views/propertyeditors/grid/grid.html | 47 +- .../grid/grid.prevalues.controller.js | 100 +- .../propertyeditors/grid/grid.prevalues.html | 33 +- .../grid/overlays/rowdeleteconfirm.html | 16 + .../listview/icon.prevalues.html | 2 +- .../listview/includeproperties.prevalues.html | 19 +- .../listview/layouts.prevalues.controller.js | 3 +- .../listview/layouts.prevalues.html | 71 +- .../list/list.listviewlayout.controller.js | 18 +- .../listview/listview.controller.js | 29 +- .../propertyeditors/listview/listview.html | 20 +- .../listview/overlays/listviewpublish.html | 4 +- .../overlays/listviewunpublish.controller.js | 2 +- .../listview/overlays/listviewunpublish.html | 4 +- .../mediapicker/mediapicker.html | 1 + .../membergrouppicker/membergrouppicker.html | 10 +- .../membergroups/membergroups.html | 8 +- .../memberpicker/memberpicker.controller.js | 3 +- .../memberpicker/memberpicker.html | 11 +- .../multipletextbox.controller.js | 39 +- .../multipletextbox/multipletextbox.html | 25 +- .../multiurlpicker/multiurlpicker.html | 29 +- .../nestedcontent/nestedcontent.controller.js | 79 +- .../nestedcontent.propertyeditor.html | 20 +- .../rte/rte.prevalues.controller.js | 8 +- .../propertyeditors/rte/rte.prevalues.html | 19 +- .../views/propertyeditors/slider/slider.html | 4 +- .../userpicker/userpicker.controller.js | 92 + .../userpicker/userpicker.html | 21 + .../views/relationTypes/edit.controller.js | 2 +- .../richtextrule/richtextrule.html | 7 +- .../views/rules/rules.controller.js | 1 - .../views/stylesheets/views/rules/rules.html | 10 +- .../src/views/templates/edit.controller.js | 4 +- .../src/views/templates/edit.html | 30 +- .../src/views/users/group.controller.js | 8 +- .../src/views/users/user.controller.js | 6 +- .../users/views/groups/groups.controller.js | 2 +- .../users/views/users/users.controller.js | 24 +- .../content-picker-controller.spec.js | 9 +- .../Umbraco.Web.UI.NetCore.csproj | 6 + .../umbraco/config/lang/cs.xml | 1587 +++++++++++++++-- .../umbraco/config/lang/da.xml | 5 +- .../umbraco/config/lang/de.xml | 4 - .../umbraco/config/lang/en.xml | 64 +- .../umbraco/config/lang/en_us.xml | 13 + .../umbraco/config/lang/fr.xml | 619 ++++++- .../umbraco/config/lang/nb.xml | 1 + .../umbraco/config/lang/nl.xml | 2 +- .../umbraco/config/lang/tr.xml | 2 +- src/Umbraco.Web.UI/Umbraco.Web.UI.csproj | 10 +- .../Views/Partials/Grid/Editors/Media.cshtml | 29 - src/Umbraco.Web/HtmlHelperRenderExtensions.cs | 6 + src/Umbraco.Web/Umbraco.Web.csproj | 3 + 966 files changed, 9352 insertions(+), 4199 deletions(-) create mode 100644 src/Umbraco.Core/Constants-SvgSanitizer.cs create mode 100644 src/Umbraco.Core/Models/IconModel.cs create mode 100644 src/Umbraco.Tests.AcceptanceTest/cypress/integration/Tour/backofficeTour.ts create mode 100644 src/Umbraco.Web.BackOffice/Controllers/IconController.cs create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-activity.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-add.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-adressbook.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-alarm-clock.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-alert-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-alert.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-anchor.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-app.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-application-error.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-application-window-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-application-window.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-arrivals.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-arrow-down.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-arrow-left.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-arrow-right.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-arrow-up.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-art-easel.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-article.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-attachment.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-auction-hammer.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-autofill.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-award.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-axis-rotation-2.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-axis-rotation-3.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-axis-rotation.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-baby-stroller.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-backspace.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-badge-add.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-badge-count.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-badge-remove.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-badge-restricted.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-ball.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-band-aid.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-bar-chart.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-barcode.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-bars.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-battery-full.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-battery-low.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-beer-glass.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-bell-off.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-bell.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-bill-dollar.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-bill-euro.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-bill-pound.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-bill-yen.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-bill.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-billboard.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-bills-dollar.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-bills-euro.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-bills-pound.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-bills-yen.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-bills.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-binarycode.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-binoculars.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-bird.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-birthday-cake.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-block.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-blueprint.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-bluetooth.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-boat-shipping.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-bomb.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-bones.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-book-alt-2.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-book-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-book.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-bookmark.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-books.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-box-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-box-open.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-box.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-brackets.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-brick.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-briefcase.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-browser-window.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-brush-alt-2.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-brush-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-brush.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-bug.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-bulleted-list.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-burn.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-bus.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-calculator.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-calendar-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-calendar.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-camcorder.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-camera-roll.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-candy.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-caps-lock.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-car.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-cash-register.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-categories.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-certificate.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-chart-curve.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-chart.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-chat-active.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-chat.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-check.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-checkbox-dotted-active.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-checkbox-dotted.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-checkbox-empty.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-checkbox.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-chess.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-chip-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-chip.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-cinema.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-circle-dotted-active.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-circle-dotted.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-circuits.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-circus.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-client.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-clothes-hanger.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-cloud-drive.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-cloud-upload.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-cloud.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-cloudy.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-clubs.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-cocktail.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-code.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-coffee.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-coin-dollar.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-coin-euro.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-coin-pound.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-coin-yen.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-coin.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-dollar-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-dollar.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-euro-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-euro.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-pound-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-pound.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-yen-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-yen.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-color-bucket.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-colorpicker.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-columns.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-comb.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-combination-lock-open.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-combination-lock.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-command.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-company.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-compress.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-connection.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-console.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-contrast.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-conversation-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-conversation.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-coverflow.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-credit-card-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-credit-card.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-crop.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-crosshair.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-crown-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-crown.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-cupcake.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-curve.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-cut.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-dashboard.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-defrag.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-delete-key.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-delete.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-departure.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-desk.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-desktop.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-diagnostics.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-diagonal-arrow-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-diagonal-arrow.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-diamond.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-diamonds.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-dice.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-diploma-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-diploma.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-directions-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-directions.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-disc.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-disk-image.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-display.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-dna.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-dock-connector.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-document-dashed-line.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-document.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-documents.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-dollar-bag.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-donate.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-door-open-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-door-open.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-download-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-download.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-drop.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-eco.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-economy.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-edit.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-eject.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-employee.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-energy-saving-bulb.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-enter.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-equalizer.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-escape.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-ethernet.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-euro-bag.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-exit-fullscreen.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-eye.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-facebook-like.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-factory.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-favorite.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-female-symbol.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-file-cabinet.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-files.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-filter-arrows.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-filter.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-fingerprint.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-fire.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-firewall.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-firewire.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-flag-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-flag.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-flash.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-flashlight.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-flowerpot.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-folder-open.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-folder-outline.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-folder.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-folders.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-font.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-food.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-footprints.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-forking.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-frame-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-frame.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-fullscreen-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-fullscreen.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-game.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-geometry.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-gift.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-glasses.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-globe-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-globe-asia.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-globe-europe-africa.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-globe-inverted-america.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-globe-inverted-asia.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-globe-inverted-europe-africa.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-globe.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-gps.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-graduate.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-grid.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-hammer.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-hand-active-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-hand-active.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-hand-pointer-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-hand-pointer.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-handprint.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-handshake.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-handtool-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-handtool.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-hard-drive-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-hard-drive.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-hat.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-hd.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-headphones.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-headset.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-hearts.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-height.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-help-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-help.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-home.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-hourglass.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-imac.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-inactive-line.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-inbox-full.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-inbox.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-indent.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-infinity.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-info.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-invoice.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-ipad.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-iphone.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-item-arrangement.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-junk.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-key.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-keyboard.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-keychain.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-keyhole.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-lab.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-laptop.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-layers-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-layers.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-layout.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-left-double-arrow.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-legal.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-lense.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-library.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-light-down.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-light-up.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-lightbulb-active.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-lightbulb.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-lightning.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-link.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-linux-tux.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-list.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-load.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-loading.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-locate.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-location-near-me.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-location-nearby.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-lock.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-log-out.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-logout.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-loupe.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-magnet.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-mailbox.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-male-and-female.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-male-symbol.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-map-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-map-location.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-map-marker.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-map.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-medal.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-medical-emergency.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-medicine.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-meeting.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-megaphone.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-merge.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-message-open.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-message-unopened.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-message.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-microscope.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-mindmap.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-mobile.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-molecular-network.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-molecular.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-mountain.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-mouse-cursor.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-mouse.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-movie-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-movie.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-multiple-credit-cards.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-multiple-windows.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-music.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-name-badge.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-bottom.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-down.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-first.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-horizontal.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-last.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-left.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-right.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-road.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-top.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-up.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-vertical.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigational-arrow.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-network-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-newspaper-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-newspaper.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-next-media.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-next.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-nodes.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-notepad-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-notepad.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-old-key.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-old-phone.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-operator.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-ordered-list.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-os-x.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-out.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-outbox.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-outdent.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-page-add.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-page-down.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-page-remove.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-page-restricted.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-page-up.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-paint-roller.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-palette.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-panel-show.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-pannel-close.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-pants.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-paper-bag.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-paper-plane-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-paper-plane.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-parachute-drop.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-parental-control.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-partly-cloudy.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-paste-in.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-path.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-pause.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-pc.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-people-alt-2.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-people-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-people-female.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-people.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-phone-ring.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-phone.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-photo-album.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-picture.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-pictures-alt-2.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-pictures-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-pictures.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-pie-chart.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-piggy-bank.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-pin-location.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-piracy.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-plane.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-planet.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-play.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-playing-cards.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-playlist.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-plugin.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-podcast.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-poker-chip.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-poll.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-post-it.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-pound-bag.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-power-outlet.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-power.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-presentation.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-previous-media.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-previous.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-price-dollar.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-price-euro.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-price-pound.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-price-yen.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-print.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-printer-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-projector.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-pulse.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-pushpin.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-qr-code.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-quote.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-radio-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-radio-receiver.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-radio.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-rain.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-rate.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-re-post.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-readonly.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-receipt-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-receipt-dollar.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-receipt-euro.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-receipt-pound.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-receipt-yen.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-reception.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-record.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-redo.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-refresh.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-remote.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-remove.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-repeat-one.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-repeat.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-reply-arrow.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-resize.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-return-to-top.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-right-double-arrow.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-road.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-roadsign.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-rocket.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-rss.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-ruler-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-ruler.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-safe.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-safedial.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-sandbox-toys.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-satellite-dish.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-save.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-scan.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-school.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-screensharing.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-script-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-script.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-scull.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-search.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-security-camera.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-sensor.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-server-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-server.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-settings-alt-2.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-settings-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-settings.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-share-alt-2.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-share-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-share.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-sharing-iphone.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-shield.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-shift.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-shipping-box.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-shipping.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-shoe.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-shopping-basket-alt-2.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-shopping-basket-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-shopping-basket.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-shorts.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-shuffle.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-sience.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-simcard.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-single-note.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-sitemap.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-sleep.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-slideshow.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-smiley-inverted.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-smiley.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-snow.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-sound-low.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-sound-medium.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-sound-off.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-sound-waves.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-sound.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-spades.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-speaker.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-speed-gauge.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-split-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-split.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-sprout.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-squiggly-line.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-ssd.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-stacked-disks.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-stamp.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-stop-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-stop-hand.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-stop.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-store.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-stream.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-sunny.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-sweatshirt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-sync.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-t-shirt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-tab-key.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-tab.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-tactics.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-tag.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-tags.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-takeaway-cup.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-target.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-temperatrure-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-temperature.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-terminal.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-theater.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-theif.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-thought-bubble.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-thumb-down.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-thumb-up.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-thumbnail-list.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-thumbnails-small.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-thumbnails.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-ticket.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-time.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-timer.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-tools.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-top.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-traffic-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-trafic.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-train.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-trash-alt-2.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-trash-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-trash.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-tree.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-trophy.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-truck.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-tv-old.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-tv.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-umb-content.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-umb-contour.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-umb-deploy.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-umb-developer.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-umb-media.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-umb-members.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-umb-settings.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-umb-users.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-umbrella.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-undo.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-universal.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-unlocked.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-untitled.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-usb-connector.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-usb.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-user-female.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-user-females-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-user-females.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-user-glasses.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-user.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-users-alt.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-users.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-utilities.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-vcard.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-video.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-voice.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-wall-plug.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-wallet.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-wand.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-war.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-weight.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-width.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-wifi.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-window-popin.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-window-sizes.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-windows.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-wine-glass.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-wrench.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-wrong.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-yen-bag.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-zip.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-zom-out.svg create mode 100644 src/Umbraco.Web.UI.Client/src/assets/icons/icon-zoom-in.svg create mode 100644 src/Umbraco.Web.UI.Client/src/common/directives/components/buttons/umbbuttonellipsis.directive.js create mode 100644 src/Umbraco.Web.UI.Client/src/common/directives/components/forms/umbfocuslock.directive.js create mode 100644 src/Umbraco.Web.UI.Client/src/common/directives/components/forms/umbsearchfilter.directive.js create mode 100644 src/Umbraco.Web.UI.Client/src/common/directives/components/umbicon.directive.js create mode 100644 src/Umbraco.Web.UI.Client/src/common/services/focuslock.service.js create mode 100644 src/Umbraco.Web.UI.Client/src/less/components/buttons/umb-button-ellipsis.less create mode 100644 src/Umbraco.Web.UI.Client/src/less/components/umb-icon.less create mode 100644 src/Umbraco.Web.UI.Client/src/less/components/umb-tags-editor.less create mode 100644 src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/overlays/mediacropdetails.controller.js create mode 100644 src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/overlays/mediacropdetails.html create mode 100644 src/Umbraco.Web.UI.Client/src/views/components/buttons/umb-button-ellipsis.html create mode 100644 src/Umbraco.Web.UI.Client/src/views/components/forms/umb-search-filter.html create mode 100644 src/Umbraco.Web.UI.Client/src/views/components/umb-icon.html delete mode 100644 src/Umbraco.Web.UI.Client/src/views/dashboard/default/ourumbraco.jpg create mode 100644 src/Umbraco.Web.UI.Client/src/views/dashboard/default/ourumbraco.png delete mode 100644 src/Umbraco.Web.UI.Client/src/views/dashboard/default/umbracotv.jpg create mode 100644 src/Umbraco.Web.UI.Client/src/views/dashboard/default/umbracotv.png delete mode 100644 src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/rowdeleteconfirm.controller.js delete mode 100644 src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/dialogs/rowdeleteconfirm.html create mode 100644 src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/overlays/rowdeleteconfirm.html create mode 100644 src/Umbraco.Web.UI.Client/src/views/propertyeditors/userpicker/userpicker.controller.js create mode 100644 src/Umbraco.Web.UI.Client/src/views/propertyeditors/userpicker/userpicker.html delete mode 100644 src/Umbraco.Web.UI/Views/Partials/Grid/Editors/Media.cshtml diff --git a/build/NuSpecs/UmbracoCms.Web.nuspec b/build/NuSpecs/UmbracoCms.Web.nuspec index 47aab4cdb8..1aeead52a5 100644 --- a/build/NuSpecs/UmbracoCms.Web.nuspec +++ b/build/NuSpecs/UmbracoCms.Web.nuspec @@ -33,6 +33,7 @@ + diff --git a/src/Umbraco.Configuration/Legacy/GlobalSettings.cs b/src/Umbraco.Configuration/Legacy/GlobalSettings.cs index d93297ca90..fabe95f5bd 100644 --- a/src/Umbraco.Configuration/Legacy/GlobalSettings.cs +++ b/src/Umbraco.Configuration/Legacy/GlobalSettings.cs @@ -146,6 +146,9 @@ namespace Umbraco.Core.Configuration.Legacy } } + + + /// /// Gets or sets the configuration status. This will return the version number of the currently installed umbraco instance. /// @@ -315,6 +318,15 @@ namespace Umbraco.Core.Configuration.Legacy private string _databaseFactoryServerVersion; public string DatabaseFactoryServerVersion => GetterWithDefaultValue(Constants.AppSettings.Debug.DatabaseFactoryServerVersion, string.Empty, ref _databaseFactoryServerVersion); + + + private string _iconsPath; + /// + /// Gets the path to folder containing the icons used in the umbraco backoffice (/umbraco/assets/icons by default). + /// + /// The icons path. + public string IconsPath => GetterWithDefaultValue(Constants.AppSettings.IconsPath, $"{UmbracoPath}/assets/icons", ref _iconsPath); + private string _mainDomLock; public string MainDomLock => GetterWithDefaultValue(Constants.AppSettings.MainDomLock, string.Empty, ref _mainDomLock); diff --git a/src/Umbraco.Configuration/Models/GlobalSettings.cs b/src/Umbraco.Configuration/Models/GlobalSettings.cs index d1f3f12017..02b73d1196 100644 --- a/src/Umbraco.Configuration/Models/GlobalSettings.cs +++ b/src/Umbraco.Configuration/Models/GlobalSettings.cs @@ -47,6 +47,8 @@ namespace Umbraco.Configuration.Models public bool UseHttps => _configuration.GetValue(Prefix + "UseHttps", false); public int VersionCheckPeriod => _configuration.GetValue(Prefix + "VersionCheckPeriod", 7); public string UmbracoPath => _configuration.GetValue(Prefix + "UmbracoPath", "~/umbraco"); + public string IconsPath => _configuration.GetValue(Prefix + "IconsPath", $"{UmbracoPath}/assets/icons"); + public string UmbracoCssPath => _configuration.GetValue(Prefix + "UmbracoCssPath", "~/css"); public string UmbracoScriptsPath => diff --git a/src/Umbraco.Core/Configuration/IGlobalSettings.cs b/src/Umbraco.Core/Configuration/IGlobalSettings.cs index bf963bcec7..26d833613f 100644 --- a/src/Umbraco.Core/Configuration/IGlobalSettings.cs +++ b/src/Umbraco.Core/Configuration/IGlobalSettings.cs @@ -20,6 +20,16 @@ /// The reserved paths. string ReservedPaths { get; } + /// + /// Gets the path to umbraco's icons directory (/umbraco/assets/icons by default). + /// + string IconsPath { get; } + + /// + /// Gets or sets the configuration status. This will return the version number of the currently installed umbraco instance. + /// + string ConfigurationStatus { get; set; } + /// /// Gets the time out in minutes. /// diff --git a/src/Umbraco.Core/Constants-AppSettings.cs b/src/Umbraco.Core/Constants-AppSettings.cs index 94370930de..36d471b950 100644 --- a/src/Umbraco.Core/Constants-AppSettings.cs +++ b/src/Umbraco.Core/Constants-AppSettings.cs @@ -41,15 +41,20 @@ namespace Umbraco.Core public const string ConfigurationStatus = "Umbraco.Core.ConfigurationStatus"; /// - /// Gets the path to umbraco's root directory (/umbraco by default). + /// The path to umbraco's root directory (/umbraco by default). /// public const string UmbracoPath = "Umbraco.Core.Path"; + /// + /// Gets the path to umbraco's icons directory (/umbraco/assets/icons by default). + /// + public const string IconsPath = "Umbraco.Icons.Path"; + /// /// The reserved urls from web.config. /// public const string ReservedUrls = "Umbraco.Core.ReservedUrls"; - + /// /// The path of the stylesheet folder. /// diff --git a/src/Umbraco.Core/Constants-SvgSanitizer.cs b/src/Umbraco.Core/Constants-SvgSanitizer.cs new file mode 100644 index 0000000000..447ea66668 --- /dev/null +++ b/src/Umbraco.Core/Constants-SvgSanitizer.cs @@ -0,0 +1,23 @@ +using System.Collections.Generic; + +namespace Umbraco.Core +{ + public static partial class Constants + { + /// + /// Defines the alias identifiers for Umbraco's core application sections. + /// + public static class SvgSanitizer + { + /// + /// Allowlist for SVG attributes. + /// + public static readonly IList Attributes = new [] { "accent-height", "accumulate", "additive", "alignment-baseline", "allowReorder", "alphabetic", "amplitude", "arabic-form", "ascent", "attributeName", "attributeType", "autoReverse", "azimuth", "baseFrequency", "baseline-shift", "baseProfile", "bbox", "begin", "bias", "by", "calcMode", "cap-height", "class", "clip", "clipPathUnits", "clip-path", "clip-rule", "color", "color-interpolation", "color-interpolation-filters", "color-profile", "color-rendering", "contentScriptType", "contentStyleType", "cursor", "cx", "cy", "d", "decelerate", "descent", "diffuseConstant", "direction", "display", "divisor", "dominant-baseline", "dur", "dx", "dy", "edgeMode", "elevation", "enable-background", "end", "exponent", "externalResourcesRequired", "Section", "fill", "fill-opacity", "fill-rule", "filter", "filterRes", "filterUnits", "flood-color", "flood-opacity", "font-family", "font-size", "font-size-adjust", "font-stretch", "font-style", "font-variant", "font-weight", "format", "from", "fr", "fx", "fy", "g1", "g2", "glyph-name", "glyph-orientation-horizontal", "glyph-orientation-vertical", "glyphRef", "gradientTransform", "gradientUnits", "hanging", "height", "href", "hreflang", "horiz-adv-x", "horiz-origin-x", "ISection", "id", "ideographic", "image-rendering", "in", "in2", "intercept", "k", "k1", "k2", "k3", "k4", "kernelMatrix", "kernelUnitLength", "kerning", "keyPoints", "keySplines", "keyTimes", "lang", "lengthAdjust", "letter-spacing", "lighting-color", "limitingConeAngle", "local", "MSection", "marker-end", "marker-mid", "marker-start", "markerHeight", "markerUnits", "markerWidth", "mask", "maskContentUnits", "maskUnits", "mathematical", "max", "media", "method", "min", "mode", "NSection", "name", "numOctaves", "offset", "opacity", "operator", "order", "orient", "orientation", "origin", "overflow", "overline-position", "overline-thickness", "panose-1", "paint-order", "path", "pathLength", "patternContentUnits", "patternTransform", "patternUnits", "ping", "pointer-events", "points", "pointsAtX", "pointsAtY", "pointsAtZ", "preserveAlpha", "preserveAspectRatio", "primitiveUnits", "r", "radius", "referrerPolicy", "refX", "refY", "rel", "rendering-intent", "repeatCount", "repeatDur", "requiredExtensions", "requiredFeatures", "restart", "result", "rotate", "rx", "ry", "scale", "seed", "shape-rendering", "slope", "spacing", "specularConstant", "specularExponent", "speed", "spreadMethod", "startOffset", "stdDeviation", "stemh", "stemv", "stitchTiles", "stop-color", "stop-opacity", "strikethrough-position", "strikethrough-thickness", "string", "stroke", "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin", "stroke-miterlimit", "stroke-opacity", "stroke-width", "style", "surfaceScale", "systemLanguage", "tabindex", "tableValues", "target", "targetX", "targetY", "text-anchor", "text-decoration", "text-rendering", "textLength", "to", "transform", "type", "u1", "u2", "underline-position", "underline-thickness", "unicode", "unicode-bidi", "unicode-range", "units-per-em", "v-alphabetic", "v-hanging", "v-ideographic", "v-mathematical", "values", "vector-effect", "version", "vert-adv-y", "vert-origin-x", "vert-origin-y", "viewBox", "viewTarget", "visibility", "width", "widths", "word-spacing", "writing-mode", "x", "x-height", "x1", "x2", "xChannelSelector", "xlink:actuate", "xlink:arcrole", "xlink:href", "xlink:role", "xlink:show", "xlink:title", "xlink:type", "xml:base", "xml:lang", "xml:space", "y", "y1", "y2", "yChannelSelector", "z", "zoomAndPan" }; + + /// + /// Allowlist for SVG tabs. + /// + public static readonly IList Tags = new [] { "a", "altGlyph", "altGlyphDef", "altGlyphItem", "animate", "animateColor", "animateMotion", "animateTransform", "circle", "clipPath", "color-profile", "cursor", "defs", "desc", "discard", "ellipse", "feBlend", "feColorMatrix", "feComponentTransfer", "feComposite", "feConvolveMatrix", "feDiffuseLighting", "feDisplacementMap", "feDistantLight", "feDropShadow", "feFlood", "feFuncA", "feFuncB", "feFuncG", "feFuncR", "feGaussianBlur", "feImage", "feMerge", "feMergeNode", "feMorphology", "feOffset", "fePointLight", "feSpecularLighting", "feSpotLight", "feTile", "feTurbulence", "filter", "font", "font-face", "font-face-format", "font-face-name", "font-face-src", "font-face-uri", "foreignObject", "g", "glyph", "glyphRef", "hatch", "hatchpath", "hkern", "image", "line", "linearGradient", "marker", "mask", "mesh", "meshgradient", "meshpatch", "meshrow", "metadata", "missing-glyph", "mpath", "path", "pattern", "polygon", "polyline", "radialGradient", "rect", "set", "solidcolor", "stop", "style", "svg", "switch", "symbol", "text", "textPath", "title", "tref", "tspan", "unknown", "use", "view", "vkern" }; + } + } +} diff --git a/src/Umbraco.Core/Constants-SystemDirectories.cs b/src/Umbraco.Core/Constants-SystemDirectories.cs index e33247be63..53e14bb6ec 100644 --- a/src/Umbraco.Core/Constants-SystemDirectories.cs +++ b/src/Umbraco.Core/Constants-SystemDirectories.cs @@ -31,6 +31,8 @@ public const string Packages = Data + "/packages"; public const string Preview = Data + "/preview"; + + public const string LogFiles= "~/Logs"; } } } diff --git a/src/Umbraco.Core/Models/ContentEditing/PropertyTypeBasic.cs b/src/Umbraco.Core/Models/ContentEditing/PropertyTypeBasic.cs index 5ff1744ea2..4252a29567 100644 --- a/src/Umbraco.Core/Models/ContentEditing/PropertyTypeBasic.cs +++ b/src/Umbraco.Core/Models/ContentEditing/PropertyTypeBasic.cs @@ -48,6 +48,14 @@ namespace Umbraco.Web.Models.ContentEditing [ReadOnly(true)] public Guid DataTypeKey { get; set; } + [DataMember(Name = "dataTypeName")] + [ReadOnly(true)] + public string DataTypeName { get; set; } + + [DataMember(Name = "dataTypeIcon")] + [ReadOnly(true)] + public string DataTypeIcon { get; set; } + //SD: Is this really needed ? [DataMember(Name = "groupId")] public int GroupId { get; set; } diff --git a/src/Umbraco.Core/Models/IconModel.cs b/src/Umbraco.Core/Models/IconModel.cs new file mode 100644 index 0000000000..5c79ad6219 --- /dev/null +++ b/src/Umbraco.Core/Models/IconModel.cs @@ -0,0 +1,8 @@ +namespace Umbraco.Web.Models +{ + public class IconModel + { + public string Name { get; set; } + public string SvgString { get; set; } + } +} diff --git a/src/Umbraco.Core/Persistence/Repositories/IMemberGroupRepository.cs b/src/Umbraco.Core/Persistence/Repositories/IMemberGroupRepository.cs index 9c75c051bd..d63b1bb9db 100644 --- a/src/Umbraco.Core/Persistence/Repositories/IMemberGroupRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/IMemberGroupRepository.cs @@ -1,10 +1,18 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using Umbraco.Core.Models; namespace Umbraco.Core.Persistence.Repositories { public interface IMemberGroupRepository : IReadWriteQueryRepository { + /// + /// Gets a member group by it's uniqueId + /// + /// + /// + IMemberGroup Get(Guid uniqueId); + /// /// Gets a member group by it's name /// diff --git a/src/Umbraco.Core/PropertyEditors/EmailAddressConfiguration.cs b/src/Umbraco.Core/PropertyEditors/EmailAddressConfiguration.cs index 4039a0e3a2..fa8eb830b0 100644 --- a/src/Umbraco.Core/PropertyEditors/EmailAddressConfiguration.cs +++ b/src/Umbraco.Core/PropertyEditors/EmailAddressConfiguration.cs @@ -1,4 +1,5 @@ -using Umbraco.Core.PropertyEditors; +using System; +using Umbraco.Core.PropertyEditors; namespace Umbraco.Web.PropertyEditors { @@ -7,7 +8,8 @@ namespace Umbraco.Web.PropertyEditors /// public class EmailAddressConfiguration { - [ConfigurationField("IsRequired", "Required?", "boolean")] + [ConfigurationField("IsRequired", "Required?", "hidden", Description = "Deprecated; Make this required by selecting mandatory when adding to the document type")] + [Obsolete("No longer used, use `Mandatory` for the property instead. Will be removed in the next major version")] public bool IsRequired { get; set; } } } diff --git a/src/Umbraco.Core/PropertyEditors/PropertyValueConverterBase.cs b/src/Umbraco.Core/PropertyEditors/PropertyValueConverterBase.cs index a584ea2a9c..2ec0438328 100644 --- a/src/Umbraco.Core/PropertyEditors/PropertyValueConverterBase.cs +++ b/src/Umbraco.Core/PropertyEditors/PropertyValueConverterBase.cs @@ -4,35 +4,43 @@ using Umbraco.Core.Models.PublishedContent; namespace Umbraco.Core.PropertyEditors { /// - /// Provides a default overridable implementation for that does nothing. + /// Provides a default implementation for . /// + /// public abstract class PropertyValueConverterBase : IPropertyValueConverter { + /// public virtual bool IsConverter(IPublishedPropertyType propertyType) => false; + /// public virtual bool? IsValue(object value, PropertyValueLevel level) { switch (level) { case PropertyValueLevel.Source: - return value != null && (!(value is string) || string.IsNullOrWhiteSpace((string) value) == false); + // the default implementation uses the old magic null & string comparisons, + // other implementations may be more clever, and/or test the final converted object values + return value != null && (!(value is string stringValue) || !string.IsNullOrWhiteSpace(stringValue)); + case PropertyValueLevel.Inter: + return null; + case PropertyValueLevel.Object: + return null; default: throw new NotSupportedException($"Invalid level: {level}."); } } + [Obsolete("This method is not part of the IPropertyValueConverter contract, therefore not used and will be removed in future versions; use IsValue instead.")] public virtual bool HasValue(IPublishedProperty property, string culture, string segment) { - // the default implementation uses the old magic null & string comparisons, - // other implementations may be more clever, and/or test the final converted object values var value = property.GetSourceValue(culture, segment); - return value != null && (!(value is string) || string.IsNullOrWhiteSpace((string) value) == false); + return value != null && (!(value is string stringValue) || !string.IsNullOrWhiteSpace(stringValue)); } /// public virtual Type GetPropertyValueType(IPublishedPropertyType propertyType) - => typeof (object); + => typeof(object); /// public virtual PropertyCacheLevel GetPropertyCacheLevel(IPublishedPropertyType propertyType) diff --git a/src/Umbraco.Core/PropertyEditors/TrueFalseConfiguration.cs b/src/Umbraco.Core/PropertyEditors/TrueFalseConfiguration.cs index c6b3953e8c..03973cfc90 100644 --- a/src/Umbraco.Core/PropertyEditors/TrueFalseConfiguration.cs +++ b/src/Umbraco.Core/PropertyEditors/TrueFalseConfiguration.cs @@ -7,10 +7,16 @@ namespace Umbraco.Web.PropertyEditors /// public class TrueFalseConfiguration { - [ConfigurationField("default", "Default Value", "boolean")] - public string Default { get; set; } // TODO: well, true or false?! + [ConfigurationField("default", "Initial State", "boolean", Description = "The initial state for the toggle, when it is displayed for the first time in the backoffice, eg. for a new content item.")] + public bool Default { get; set; } - [ConfigurationField("labelOn", "Write a label text", "textstring")] - public string Label { get; set; } + [ConfigurationField("showLabels", "Show toggle labels", "boolean", Description = "Show labels next to toggle button.")] + public bool ShowLabels { get; set; } + + [ConfigurationField("labelOn", "Label On", "textstring", Description = "Label text when enabled.")] + public string LabelOn { get; set; } + + [ConfigurationField("labelOff", "Label Off", "textstring", Description = "Label text when disabled.")] + public string LabelOff { get; set; } } } diff --git a/src/Umbraco.Core/Scheduling/TempFileCleanup.cs b/src/Umbraco.Core/Scheduling/TempFileCleanup.cs index 90bf4ee9eb..6ac1ff61fe 100644 --- a/src/Umbraco.Core/Scheduling/TempFileCleanup.cs +++ b/src/Umbraco.Core/Scheduling/TempFileCleanup.cs @@ -51,6 +51,7 @@ namespace Umbraco.Web.Scheduling if (!dir.Exists) { _logger.Debug("The cleanup folder doesn't exist {Folder}", dir.FullName); + return; } var files = dir.GetFiles("*.*", SearchOption.AllDirectories); @@ -60,6 +61,7 @@ namespace Umbraco.Web.Scheduling { try { + file.IsReadOnly = false; file.Delete(); } catch (Exception ex) diff --git a/src/Umbraco.Core/Services/IMemberGroupService.cs b/src/Umbraco.Core/Services/IMemberGroupService.cs index 6a554aad31..9261dcfdf6 100644 --- a/src/Umbraco.Core/Services/IMemberGroupService.cs +++ b/src/Umbraco.Core/Services/IMemberGroupService.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using Umbraco.Core.Models; namespace Umbraco.Core.Services @@ -7,6 +8,7 @@ namespace Umbraco.Core.Services { IEnumerable GetAll(); IMemberGroup GetById(int id); + IMemberGroup GetById(Guid id); IEnumerable GetByIds(IEnumerable ids); IMemberGroup GetByName(string name); void Save(IMemberGroup memberGroup, bool raiseEvents = true); diff --git a/src/Umbraco.Examine.Lucene/BackOfficeExamineSearcher.cs b/src/Umbraco.Examine.Lucene/BackOfficeExamineSearcher.cs index c4e7f264fb..24800fa98a 100644 --- a/src/Umbraco.Examine.Lucene/BackOfficeExamineSearcher.cs +++ b/src/Umbraco.Examine.Lucene/BackOfficeExamineSearcher.cs @@ -113,6 +113,9 @@ namespace Umbraco.Examine var allLangs = _languageService.GetAllLanguages().Select(x => x.IsoCode.ToLowerInvariant()).ToList(); + // the chars [*-_] in the query will mess everything up so let's remove those + query = Regex.Replace(query, "[\\*\\-_]", ""); + //check if text is surrounded by single or double quotes, if so, then exact match var surroundedByQuotes = Regex.IsMatch(query, "^\".*?\"$") || Regex.IsMatch(query, "^\'.*?\'$"); diff --git a/src/Umbraco.Infrastructure/Logging/Serilog/LoggerConfigExtensions.cs b/src/Umbraco.Infrastructure/Logging/Serilog/LoggerConfigExtensions.cs index dfcc401ea3..f2e028e6de 100644 --- a/src/Umbraco.Infrastructure/Logging/Serilog/LoggerConfigExtensions.cs +++ b/src/Umbraco.Infrastructure/Logging/Serilog/LoggerConfigExtensions.cs @@ -7,6 +7,7 @@ using Serilog.Core; using Serilog.Events; using Serilog.Formatting; using Serilog.Formatting.Compact; +using Umbraco.Core.IO; using Umbraco.Core.Hosting; using Umbraco.Core.Logging.Serilog.Enrichers; @@ -22,7 +23,7 @@ namespace Umbraco.Core.Logging.Serilog /// It is highly recommended that you keep/use this default in your own logging config customizations /// /// A Serilog LoggerConfiguration - /// + /// /// public static LoggerConfiguration MinimalConfiguration( this LoggerConfiguration logConfig, @@ -33,15 +34,15 @@ namespace Umbraco.Core.Logging.Serilog //Set this environment variable - so that it can be used in external config file //add key="serilog:write-to:RollingFile.pathFormat" value="%BASEDIR%\logs\log.txt" /> + Environment.SetEnvironmentVariable("BASEDIR", hostingEnvironment.MapPathContentRoot("/").TrimEnd("\\"), EnvironmentVariableTarget.Process); Environment.SetEnvironmentVariable("UMBLOGDIR", loggingConfiguration.LogDirectory, EnvironmentVariableTarget.Process); - Environment.SetEnvironmentVariable("BASEDIR", hostingEnvironment.ApplicationPhysicalPath, EnvironmentVariableTarget.Process); - Environment.SetEnvironmentVariable("MACHINENAME", Environment.MachineName, EnvironmentVariableTarget.Process); + Environment.SetEnvironmentVariable("MACHINENAME", Environment.MachineName, EnvironmentVariableTarget.Process); logConfig.MinimumLevel.Verbose() //Set to highest level of logging (as any sinks may want to restrict it to Errors only) .Enrich.WithProcessId() .Enrich.WithProcessName() .Enrich.WithThreadId() - .Enrich.WithProperty(AppDomainId, AppDomain.CurrentDomain.Id) + .Enrich.WithProperty(AppDomainId, AppDomain.CurrentDomain.Id) .Enrich.WithProperty("AppDomainAppId", hostingEnvironment.ApplicationId.ReplaceNonAlphanumericChars(string.Empty)) .Enrich.WithProperty("MachineName", Environment.MachineName) .Enrich.With() @@ -57,11 +58,14 @@ namespace Umbraco.Core.Logging.Serilog /// /// The log level you wish the JSON file to collect - default is Verbose (highest) /// The number of days to keep log files. Default is set to null which means all logs are kept - public static LoggerConfiguration OutputDefaultTextFile(this LoggerConfiguration logConfig, ILoggingConfiguration loggingConfiguration, LogEventLevel minimumLevel = LogEventLevel.Verbose, int? retainedFileCount = null) + public static LoggerConfiguration OutputDefaultTextFile( + this LoggerConfiguration logConfig, + IHostingEnvironment hostingEnvironment, + ILoggingConfiguration loggingConfiguration, LogEventLevel minimumLevel = LogEventLevel.Verbose, int? retainedFileCount = null) { //Main .txt logfile - in similar format to older Log4Net output //Ends with ..txt as Date is inserted before file extension substring - logConfig.WriteTo.File(Path.Combine(loggingConfiguration.LogDirectory, $@"UmbracoTraceLog.{Environment.MachineName}..txt"), + logConfig.WriteTo.File(Path.Combine(hostingEnvironment.MapPathContentRoot(Constants.SystemDirectories.LogFiles), $"UmbracoTraceLog.{Environment.MachineName}..txt"), shared: true, rollingInterval: RollingInterval.Day, restrictedToMinimumLevel: minimumLevel, @@ -115,11 +119,15 @@ namespace Umbraco.Core.Logging.Serilog /// /// The log level you wish the JSON file to collect - default is Verbose (highest) /// The number of days to keep log files. Default is set to null which means all logs are kept - public static LoggerConfiguration OutputDefaultJsonFile(this LoggerConfiguration logConfig, ILoggingConfiguration loggingConfiguration, LogEventLevel minimumLevel = LogEventLevel.Verbose, int? retainedFileCount = null) + public static LoggerConfiguration OutputDefaultJsonFile( + this LoggerConfiguration logConfig, + IHostingEnvironment hostingEnvironment, + ILoggingConfiguration loggingConfiguration, LogEventLevel minimumLevel = LogEventLevel.Verbose, int? retainedFileCount = null) { //.clef format (Compact log event format, that can be imported into local SEQ & will make searching/filtering logs easier) //Ends with ..txt as Date is inserted before file extension substring - logConfig.WriteTo.File(new CompactJsonFormatter(), Path.Combine(loggingConfiguration.LogDirectory, $@"UmbracoTraceLog.{Environment.MachineName}..json"), + logConfig.WriteTo.File(new CompactJsonFormatter(), + Path.Combine(hostingEnvironment.MapPathContentRoot(Constants.SystemDirectories.LogFiles) ,$"UmbracoTraceLog.{Environment.MachineName}..json"), shared: true, rollingInterval: RollingInterval.Day, //Create a new JSON file every day retainedFileCountLimit: retainedFileCount, //Setting to null means we keep all files - default is 31 days diff --git a/src/Umbraco.Infrastructure/Logging/Viewer/SerilogJsonLogViewer.cs b/src/Umbraco.Infrastructure/Logging/Viewer/SerilogJsonLogViewer.cs index 366a0fb9de..5bf079c1b4 100644 --- a/src/Umbraco.Infrastructure/Logging/Viewer/SerilogJsonLogViewer.cs +++ b/src/Umbraco.Infrastructure/Logging/Viewer/SerilogJsonLogViewer.cs @@ -5,8 +5,6 @@ using System.Linq; using Newtonsoft.Json; using Serilog.Events; using Serilog.Formatting.Compact.Reader; -using Umbraco.Core.Hosting; -using Umbraco.Core.IO; namespace Umbraco.Core.Logging.Viewer { diff --git a/src/Umbraco.Infrastructure/Models/ContentEditing/EntityBasic.cs b/src/Umbraco.Infrastructure/Models/ContentEditing/EntityBasic.cs index 512bc1517d..4776983687 100644 --- a/src/Umbraco.Infrastructure/Models/ContentEditing/EntityBasic.cs +++ b/src/Umbraco.Infrastructure/Models/ContentEditing/EntityBasic.cs @@ -61,8 +61,7 @@ namespace Umbraco.Web.Models.ContentEditing /// The path of the entity /// [DataMember(Name = "path")] - public string Path { get; set; } - + public string Path { get; set; } /// /// A collection of extra data that is available for this specific entity/entity type /// diff --git a/src/Umbraco.Infrastructure/Models/ContentEditing/MediaItemDisplay.cs b/src/Umbraco.Infrastructure/Models/ContentEditing/MediaItemDisplay.cs index 0118645b60..a5d538c6ac 100644 --- a/src/Umbraco.Infrastructure/Models/ContentEditing/MediaItemDisplay.cs +++ b/src/Umbraco.Infrastructure/Models/ContentEditing/MediaItemDisplay.cs @@ -7,7 +7,7 @@ using Umbraco.Core.Models.ContentEditing; namespace Umbraco.Web.Models.ContentEditing { /// - /// A model representing a content item to be displayed in the back office + /// A model representing a media item to be displayed in the back office /// [DataContract(Name = "content", Namespace = "")] public class MediaItemDisplay : ListViewAwareContentItemDisplayBase diff --git a/src/Umbraco.Infrastructure/Models/ContentEditing/MemberDisplay.cs b/src/Umbraco.Infrastructure/Models/ContentEditing/MemberDisplay.cs index 2f53f6f73b..8c97925403 100644 --- a/src/Umbraco.Infrastructure/Models/ContentEditing/MemberDisplay.cs +++ b/src/Umbraco.Infrastructure/Models/ContentEditing/MemberDisplay.cs @@ -18,6 +18,9 @@ namespace Umbraco.Web.Models.ContentEditing ContentApps = new List(); } + [DataMember(Name = "contentType")] + public ContentTypeBasic ContentType { get; set; } + [DataMember(Name = "username")] public string Username { get; set; } diff --git a/src/Umbraco.Infrastructure/Models/Mapping/ContentTypeMapDefinition.cs b/src/Umbraco.Infrastructure/Models/Mapping/ContentTypeMapDefinition.cs index 9341b2f756..75a64c7b1e 100644 --- a/src/Umbraco.Infrastructure/Models/Mapping/ContentTypeMapDefinition.cs +++ b/src/Umbraco.Infrastructure/Models/Mapping/ContentTypeMapDefinition.cs @@ -356,7 +356,7 @@ namespace Umbraco.Web.Models.Mapping target.Properties = context.MapEnumerable(source.Properties); } - // Umbraco.Code.MapAll -Editor -View -Config -ContentTypeId -ContentTypeName -Locked + // Umbraco.Code.MapAll -Editor -View -Config -ContentTypeId -ContentTypeName -Locked -DataTypeIcon -DataTypeName private static void Map(PropertyTypeBasic source, PropertyTypeDisplay target, MapperContext context) { target.Alias = source.Alias; @@ -373,7 +373,7 @@ namespace Umbraco.Web.Models.Mapping target.Validation = source.Validation; } - // Umbraco.Code.MapAll -Editor -View -Config -ContentTypeId -ContentTypeName -Locked + // Umbraco.Code.MapAll -Editor -View -Config -ContentTypeId -ContentTypeName -Locked -DataTypeIcon -DataTypeName private static void Map(MemberPropertyTypeBasic source, MemberPropertyTypeDisplay target, MapperContext context) { target.Alias = source.Alias; diff --git a/src/Umbraco.Infrastructure/Models/Mapping/EntityMapDefinition.cs b/src/Umbraco.Infrastructure/Models/Mapping/EntityMapDefinition.cs index ba7b5cddf2..3663095739 100644 --- a/src/Umbraco.Infrastructure/Models/Mapping/EntityMapDefinition.cs +++ b/src/Umbraco.Infrastructure/Models/Mapping/EntityMapDefinition.cs @@ -40,6 +40,7 @@ namespace Umbraco.Web.Models.Mapping target.Trashed = source.Trashed; target.Udi = Udi.Create(ObjectTypes.GetUdiType(source.NodeObjectType), source.Key); + if (source is IContentEntitySlim contentSlim) { source.AdditionalData["ContentTypeAlias"] = contentSlim.ContentTypeAlias; @@ -52,6 +53,8 @@ namespace Umbraco.Web.Models.Mapping if (source is IMediaEntitySlim mediaSlim) { + //pass UpdateDate for MediaPicker ListView ordering + source.AdditionalData["UpdateDate"] = mediaSlim.UpdateDate; source.AdditionalData["MediaPath"] = mediaSlim.MediaPath; } @@ -181,7 +184,8 @@ namespace Umbraco.Web.Models.Mapping target.Name = source.Values.ContainsKey($"nodeName_{culture}") ? source.Values[$"nodeName_{culture}"] : target.Name; } - if (source.Values.TryGetValue(UmbracoExamineFieldNames.UmbracoFileFieldName, out var umbracoFile)) + if (source.Values.TryGetValue(UmbracoExamineFieldNames.UmbracoFileFieldName, out var umbracoFile) && + umbracoFile.IsNullOrWhiteSpace() == false) { if (umbracoFile != null) { diff --git a/src/Umbraco.Infrastructure/Models/Mapping/PropertyTypeGroupMapper.cs b/src/Umbraco.Infrastructure/Models/Mapping/PropertyTypeGroupMapper.cs index 6cee1d9246..32ea6fce3f 100644 --- a/src/Umbraco.Infrastructure/Models/Mapping/PropertyTypeGroupMapper.cs +++ b/src/Umbraco.Infrastructure/Models/Mapping/PropertyTypeGroupMapper.cs @@ -241,6 +241,8 @@ namespace Umbraco.Web.Models.Mapping Inherited = inherited, DataTypeId = p.DataTypeId, DataTypeKey = p.DataTypeKey, + DataTypeName = dataType.Name, + DataTypeIcon = propertyEditor.Icon, SortOrder = p.SortOrder, ContentTypeId = contentType.Id, ContentTypeName = contentType.Name, diff --git a/src/Umbraco.Infrastructure/Persistence/Querying/ExpressionVisitorBase.cs b/src/Umbraco.Infrastructure/Persistence/Querying/ExpressionVisitorBase.cs index ab4f59591f..91844430a9 100644 --- a/src/Umbraco.Infrastructure/Persistence/Querying/ExpressionVisitorBase.cs +++ b/src/Umbraco.Infrastructure/Persistence/Querying/ExpressionVisitorBase.cs @@ -744,7 +744,9 @@ namespace Umbraco.Core.Persistence.Querying var c = exp[0]; return (c == '"' || c == '`' || c == '\'') && exp[exp.Length - 1] == c - ? exp.Substring(1, exp.Length - 2) + ? exp.Length == 1 + ? string.Empty + : exp.Substring(1, exp.Length - 2) : exp; } } diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/EntityRepository.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/EntityRepository.cs index 3d006914a2..61ced57149 100644 --- a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/EntityRepository.cs +++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/EntityRepository.cs @@ -368,7 +368,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement if (isContent || isMedia || isMember) sql - .AndSelect(x => Alias(x.Id, "versionId")) + .AndSelect(x => Alias(x.Id, "versionId"), x=>x.VersionDate) .AndSelect(x => x.Alias, x => x.Icon, x => x.Thumbnail, x => x.IsContainer, x => x.Variations); if (isContent) @@ -489,7 +489,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement if (isContent || isMedia || isMember) sql - .AndBy(x => x.Id) + .AndBy(x => x.Id, x => x.VersionDate) .AndBy(x => x.Alias, x => x.Icon, x => x.Thumbnail, x => x.IsContainer, x => x.Variations); if (defaultSort) @@ -593,6 +593,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement public string Text { get; set; } public Guid NodeObjectType { get; set; } public DateTime CreateDate { get; set; } + public DateTime VersionDate { get; set; } public int Children { get; set; } public int VersionId { get; set; } public string Alias { get; set; } @@ -626,6 +627,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement { entity.Trashed = dto.Trashed; entity.CreateDate = dto.CreateDate; + entity.UpdateDate = dto.VersionDate; entity.CreatorId = dto.UserId ?? Constants.Security.UnknownUserId; entity.Id = dto.NodeId; entity.Key = dto.UniqueId; diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/MemberGroupRepository.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/MemberGroupRepository.cs index c138550de5..edd6dc0ebb 100644 --- a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/MemberGroupRepository.cs +++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/MemberGroupRepository.cs @@ -69,7 +69,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement protected override string GetBaseWhereClause() { - return "umbracoNode.id = @id"; + return $"{Constants.DatabaseSchema.Tables.Node}.id = @id"; } protected override IEnumerable GetDeleteClauses() @@ -115,6 +115,16 @@ namespace Umbraco.Core.Persistence.Repositories.Implement entity.ResetDirtyProperties(); } + public IMemberGroup Get(Guid uniqueId) + { + var sql = GetBaseQuery(false); + sql.Where("umbracoNode.uniqueId = @uniqueId", new { uniqueId }); + + var dto = Database.Fetch(SqlSyntax.SelectTop(sql, 1)).FirstOrDefault(); + + return dto == null ? null : MemberGroupFactory.BuildEntity(dto); + } + public IMemberGroup GetByName(string name) { return IsolatedCache.GetCacheItem( diff --git a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/UserRepository.cs b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/UserRepository.cs index e191ac08bf..5ba32a4d2f 100644 --- a/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/UserRepository.cs +++ b/src/Umbraco.Infrastructure/Persistence/Repositories/Implement/UserRepository.cs @@ -548,9 +548,9 @@ ORDER BY colName"; { userDto.EmailConfirmedDate = null; userDto.SecurityStampToken = entity.SecurityStamp = Guid.NewGuid().ToString(); - + changedCols.Add("emailConfirmedDate"); - changedCols.Add("securityStampToken"); + changedCols.Add("securityStampToken"); } //only update the changed cols @@ -694,7 +694,13 @@ ORDER BY colName"; else sql.WhereNotIn(x => x.Id, inSql); - return ConvertFromDtos(Database.Fetch(sql)); + + var dtos = Database.Fetch(sql); + + //adds missing bits like content and media start nodes + PerformGetReferencedDtos(dtos); + + return ConvertFromDtos(dtos); } /// diff --git a/src/Umbraco.Infrastructure/Persistence/SqlSyntax/SqlServerSyntaxProvider.cs b/src/Umbraco.Infrastructure/Persistence/SqlSyntax/SqlServerSyntaxProvider.cs index 779e4362ae..ec4cfca498 100644 --- a/src/Umbraco.Infrastructure/Persistence/SqlSyntax/SqlServerSyntaxProvider.cs +++ b/src/Umbraco.Infrastructure/Persistence/SqlSyntax/SqlServerSyntaxProvider.cs @@ -32,6 +32,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax V2014 = 6, V2016 = 7, V2017 = 8, + V2019 = 9, Other = 99 } @@ -40,7 +41,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax Unknown = 0, Desktop = 1, Standard = 2, - Enterprise = 3, + Enterprise = 3,// Also developer edition Express = 4, Azure = 5 } @@ -81,6 +82,8 @@ namespace Umbraco.Core.Persistence.SqlSyntax { case "??": return VersionName.Invalid; + case "15": + return VersionName.V2019; case "14": return VersionName.V2017; case "13": diff --git a/src/Umbraco.Infrastructure/Persistence/UmbracoDatabaseFactory.cs b/src/Umbraco.Infrastructure/Persistence/UmbracoDatabaseFactory.cs index 837fe6cba3..e243ea45ef 100644 --- a/src/Umbraco.Infrastructure/Persistence/UmbracoDatabaseFactory.cs +++ b/src/Umbraco.Infrastructure/Persistence/UmbracoDatabaseFactory.cs @@ -182,6 +182,7 @@ namespace Umbraco.Core.Persistence case SqlServerSyntaxProvider.VersionName.V2014: case SqlServerSyntaxProvider.VersionName.V2016: case SqlServerSyntaxProvider.VersionName.V2017: + case SqlServerSyntaxProvider.VersionName.V2019: _databaseType = DatabaseType.SqlServer2012; break; // else leave unchanged diff --git a/src/Umbraco.Infrastructure/PropertyEditors/TrueFalsePropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/TrueFalsePropertyEditor.cs index 3d82dc2809..0bfa5899c9 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/TrueFalsePropertyEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/TrueFalsePropertyEditor.cs @@ -13,7 +13,7 @@ namespace Umbraco.Web.PropertyEditors [DataEditor( Constants.PropertyEditors.Aliases.Boolean, EditorType.PropertyValue | EditorType.MacroParameter, - "Checkbox", + "Toggle", "boolean", ValueType = ValueTypes.Integer, Group = Constants.PropertyEditors.Groups.Common, diff --git a/src/Umbraco.Infrastructure/PropertyEditors/UserPickerConfiguration.cs b/src/Umbraco.Infrastructure/PropertyEditors/UserPickerConfiguration.cs index 4d497867a1..bf3cd197a3 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/UserPickerConfiguration.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/UserPickerConfiguration.cs @@ -7,7 +7,8 @@ namespace Umbraco.Web.PropertyEditors { public override IDictionary DefaultConfiguration => new Dictionary { - {"entityType", "User"} + { "entityType", "User" }, + { "multiPicker", "0" } }; } } diff --git a/src/Umbraco.Infrastructure/PropertyEditors/UserPickerPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/UserPickerPropertyEditor.cs index 429527f3eb..194924adf1 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/UserPickerPropertyEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/UserPickerPropertyEditor.cs @@ -8,8 +8,8 @@ namespace Umbraco.Web.PropertyEditors { [DataEditor( Constants.PropertyEditors.Aliases.UserPicker, - "User picker", - "entitypicker", + "User Picker", + "userpicker", ValueType = ValueTypes.Integer, Group = Constants.PropertyEditors.Groups.People, Icon = Constants.Icons.User)] diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/MemberPickerValueConverter.cs b/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/MemberPickerValueConverter.cs index 19cca866df..87e5ebec15 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/MemberPickerValueConverter.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/MemberPickerValueConverter.cs @@ -31,6 +31,8 @@ namespace Umbraco.Web.PropertyEditors.ValueConverters public override object ConvertSourceToIntermediate(IPublishedElement owner, IPublishedPropertyType propertyType, object source, bool preview) { + if (source == null) return null; + var attemptConvertInt = source.TryConvertTo(); if (attemptConvertInt.Success) return attemptConvertInt.Result; diff --git a/src/Umbraco.Infrastructure/Services/Implement/ContentService.cs b/src/Umbraco.Infrastructure/Services/Implement/ContentService.cs index 4585433be6..4cd85bc408 100644 --- a/src/Umbraco.Infrastructure/Services/Implement/ContentService.cs +++ b/src/Umbraco.Infrastructure/Services/Implement/ContentService.cs @@ -3006,6 +3006,8 @@ namespace Umbraco.Core.Services.Implement _documentBlueprintRepository.Save(content); + Audit(AuditType.Save, Constants.Security.SuperUserId, content.Id, $"Saved content template: {content.Name}"); + scope.Events.Dispatch(SavedBlueprint, this, new SaveEventArgs(content), "SavedBlueprint"); scope.Complete(); diff --git a/src/Umbraco.Infrastructure/Services/Implement/MemberGroupService.cs b/src/Umbraco.Infrastructure/Services/Implement/MemberGroupService.cs index c879a00ccb..308080bbf4 100644 --- a/src/Umbraco.Infrastructure/Services/Implement/MemberGroupService.cs +++ b/src/Umbraco.Infrastructure/Services/Implement/MemberGroupService.cs @@ -70,6 +70,14 @@ namespace Umbraco.Core.Services.Implement } } + public IMemberGroup GetById(Guid id) + { + using (var scope = ScopeProvider.CreateScope(autoComplete: true)) + { + return _memberGroupRepository.Get(id); + } + } + public IMemberGroup GetByName(string name) { using (var scope = ScopeProvider.CreateScope(autoComplete: true)) diff --git a/src/Umbraco.Infrastructure/Services/Implement/RelationService.cs b/src/Umbraco.Infrastructure/Services/Implement/RelationService.cs index 4b53709de9..c629466edf 100644 --- a/src/Umbraco.Infrastructure/Services/Implement/RelationService.cs +++ b/src/Umbraco.Infrastructure/Services/Implement/RelationService.cs @@ -15,13 +15,15 @@ namespace Umbraco.Core.Services.Implement private readonly IEntityService _entityService; private readonly IRelationRepository _relationRepository; private readonly IRelationTypeRepository _relationTypeRepository; + private readonly IAuditRepository _auditRepository; public RelationService(IScopeProvider uowProvider, ILogger logger, IEventMessagesFactory eventMessagesFactory, IEntityService entityService, - IRelationRepository relationRepository, IRelationTypeRepository relationTypeRepository) + IRelationRepository relationRepository, IRelationTypeRepository relationTypeRepository, IAuditRepository auditRepository) : base(uowProvider, logger, eventMessagesFactory) { _relationRepository = relationRepository; _relationTypeRepository = relationTypeRepository; + _auditRepository = auditRepository; _entityService = entityService ?? throw new ArgumentNullException(nameof(entityService)); } @@ -476,6 +478,7 @@ namespace Umbraco.Core.Services.Implement } _relationTypeRepository.Save(relationType); + Audit(AuditType.Save, Constants.Security.SuperUserId, relationType.Id, $"Saved relation type: {relationType.Name}"); scope.Complete(); saveEventArgs.CanCancel = false; scope.Events.Dispatch(SavedRelationType, this, saveEventArgs); @@ -565,6 +568,11 @@ namespace Umbraco.Core.Services.Implement } return relations; } + + private void Audit(AuditType type, int userId, int objectId, string message = null) + { + _auditRepository.Save(new AuditItem(objectId, type, userId, ObjectTypes.GetName(UmbracoObjectTypes.RelationType), message)); + } #endregion #region Events Handlers diff --git a/src/Umbraco.Infrastructure/WebAssets/JsInitialize.js b/src/Umbraco.Infrastructure/WebAssets/JsInitialize.js index 2ca6f66510..ea9e4620c8 100644 --- a/src/Umbraco.Infrastructure/WebAssets/JsInitialize.js +++ b/src/Umbraco.Infrastructure/WebAssets/JsInitialize.js @@ -28,6 +28,7 @@ 'lib/chart.js/Chart.min.js', 'lib/angular-chart.js/angular-chart.min.js', + 'lib/wicg-inert/dist/inert.min.js', 'lib/umbraco/Extensions.js', diff --git a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/documentTypes.ts b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/documentTypes.ts index e28c75e922..ba903d1c63 100644 --- a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/documentTypes.ts +++ b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/documentTypes.ts @@ -10,6 +10,7 @@ context('Document Types', () => { const name = "Test document type"; cy.umbracoEnsureDocumentTypeNameNotExists(name); + cy.umbracoEnsureTemplateNameNotExists(name); cy.umbracoSection('settings'); cy.get('li .umb-tree-root:contains("Settings")').should("be.visible"); @@ -44,6 +45,7 @@ context('Document Types', () => { //Assert cy.umbracoSuccessNotification().should('be.visible'); + cy.umbracoEnsureTemplateNameNotExists(name); //Clean up cy.umbracoEnsureDocumentTypeNameNotExists(name); diff --git a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/partialsViewMacroFiles.ts b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/partialsViewMacroFiles.ts index f4c976de08..563ff77658 100644 --- a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/partialsViewMacroFiles.ts +++ b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/partialsViewMacroFiles.ts @@ -1,23 +1,34 @@ /// +import { PartialViewMacroBuilder } from "umbraco-cypress-testhelpers"; + context('Partial View Macro Files', () => { beforeEach(() => { cy.umbracoLogin(Cypress.env('username'), Cypress.env('password')); }); - it('Create new partial view macro', () => { - const name = "TestPartialViewMacro"; - const fileName = name + ".cshtml"; - - cy.umbracoEnsurePartialViewMacroFileNameNotExists(fileName); - cy.umbracoEnsureMacroNameNotExists(name); - + function openPartialViewMacroCreatePanel() { cy.umbracoSection('settings'); cy.get('li .umb-tree-root:contains("Settings")').should("be.visible"); cy.umbracoTreeItem("settings", ["Partial View Macro Files"]).rightclick(); - cy.umbracoContextMenuAction("action-create").click(); + } + + function cleanup(name, extension = ".cshtml") { + const fileName = name + extension; + + cy.umbracoEnsureMacroNameNotExists(name); + cy.umbracoEnsurePartialViewMacroFileNameNotExists(fileName); + } + + it('Create new partial view macro', () => { + const name = "TestPartialViewMacro"; + + cleanup(name); + + openPartialViewMacroCreatePanel(); + cy.get('.menu-label').first().click(); // TODO: Fucked we cant use something like cy.umbracoContextMenuAction("action-label").click(); //Type name @@ -28,10 +39,117 @@ context('Partial View Macro Files', () => { //Assert cy.umbracoSuccessNotification().should('be.visible'); + cy.umbracoMacroExists(name).then(exists => { expect(exists).to.be.true; }); //Clean up - cy.umbracoEnsurePartialViewMacroFileNameNotExists(fileName); - cy.umbracoEnsureMacroNameNotExists(name); - }); + cleanup(name); + }); + + it('Create new partial view macro without macro', () => { + const name = "TestPartialMacrolessMacro"; + + cleanup(name); + + openPartialViewMacroCreatePanel(); + + cy.get('.menu-label').eq(1).click(); + + // Type name + cy.umbracoEditorHeaderName(name); + + // Save + cy.get('.btn-success').click(); + + // Assert + cy.umbracoSuccessNotification().should('be.visible'); + cy.umbracoMacroExists(name).then(exists => { expect(exists).to.be.false; }); + + // Clean + cleanup(name); + }); + + it('Create new partial view macro from snippet', () => { + const name = "TestPartialFromSnippet"; + + cleanup(name); + + openPartialViewMacroCreatePanel(); + + cy.get('.menu-label').eq(2).click(); + + // Select snippet + cy.get('.menu-label').eq(1).click(); + + // Type name + cy.umbracoEditorHeaderName(name); + + // Save + cy.get('.btn-success').click(); + + // Assert + cy.umbracoSuccessNotification().should('be.visible'); + cy.umbracoMacroExists(name).then(exists => { expect(exists).to.be.true; }); + + // Clean + cleanup(name); + }); + + it('Delete partial view macro', () => { + const name = "TestDeletePartialViewMacro"; + const fullName = name + ".cshtml" + + cleanup(name); + + const partialViewMacro = new PartialViewMacroBuilder() + .withName(name) + .withContent("@inherits Umbraco.Web.Macros.PartialViewMacroPage") + .build(); + + cy.savePartialViewMacro(partialViewMacro); + + // Navigate to settings + cy.umbracoSection('settings'); + cy.get('li .umb-tree-root:contains("Settings")').should("be.visible"); + + // Delete partialViewMacro + cy.umbracoTreeItem("settings", ["Partial View Macro Files", fullName]).rightclick(); + cy.umbracoContextMenuAction("action-delete").click(); + cy.umbracoButtonByLabelKey("general_ok").click(); + + // Assert + cy.contains(fullName).should('not.exist'); + + // Clean + cleanup(name); + }); + + it('Edit partial view macro', () => { + const name = "TestPartialViewMacroEditable"; + const fullName = name + ".cshtml"; + + cleanup(name); + + const partialViewMacro = new PartialViewMacroBuilder() + .withName(name) + .withContent("@inherits Umbraco.Web.Macros.PartialViewMacroPage") + .build(); + + cy.savePartialViewMacro(partialViewMacro); + + // Navigate to settings + cy.umbracoSection('settings'); + cy.get('li .umb-tree-root:contains("Settings")').should("be.visible"); + cy.umbracoTreeItem("settings", ["Partial View Macro Files", fullName]).click(); + + // Type an edit + cy.get('.ace_text-input').type(" // test", {force:true} ); + // Save + cy.get('.btn-success').click(); + + // Assert + cy.umbracoSuccessNotification().should('be.visible'); + + cleanup(name); + }); }); diff --git a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/partialsViews.ts b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/partialsViews.ts index b644c6642b..068338f8fa 100644 --- a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/partialsViews.ts +++ b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/partialsViews.ts @@ -1,35 +1,145 @@ /// +import { PartialViewBuilder } from "umbraco-cypress-testhelpers"; + context('Partial Views', () => { - beforeEach(() => { - cy.umbracoLogin(Cypress.env('username'), Cypress.env('password')); - }); + beforeEach(() => { + cy.umbracoLogin(Cypress.env('username'), Cypress.env('password')); + }); - it('Create new empty partial view', () => { - const name = "TestPartialView"; - const fileName = name + ".cshtml"; + function navigateToSettings() { + cy.umbracoSection('settings'); + cy.get('li .umb-tree-root:contains("Settings")').should("be.visible"); + } - cy.umbracoEnsurePartialViewNameNotExists(fileName); + function openPartialViewsCreatePanel() { + navigateToSettings(); + cy.umbracoTreeItem("settings", ["Partial Views"]).rightclick(); + } - cy.umbracoSection('settings'); - cy.get('li .umb-tree-root:contains("Settings")').should("be.visible"); + it('Create new empty partial view', () => { + const name = "TestPartialView"; + const fileName = name + ".cshtml"; - cy.umbracoTreeItem("settings", ["Partial Views"]).rightclick(); + cy.umbracoEnsurePartialViewNameNotExists(fileName); - cy.umbracoContextMenuAction("action-create").click(); - cy.get('.menu-label').first().click(); // TODO: Fucked we cant use something like cy.umbracoContextMenuAction("action-mediaType").click(); + openPartialViewsCreatePanel(); - //Type name - cy.umbracoEditorHeaderName(name); + cy.umbracoContextMenuAction("action-create").click(); + cy.get('.menu-label').first().click(); // TODO: Fucked we cant use something like cy.umbracoContextMenuAction("action-mediaType").click(); - //Save - cy.get('.btn-success').click(); + //Type name + cy.umbracoEditorHeaderName(name); - //Assert - cy.umbracoSuccessNotification().should('be.visible'); + //Save + cy.get('.btn-success').click(); + + //Assert + cy.umbracoSuccessNotification().should('be.visible'); + cy.umbracoPartialViewExists(fileName).then(exists => { expect(exists).to.be.true; }); + + //Clean up + cy.umbracoEnsurePartialViewNameNotExists(fileName); + }); + + it('Create partial view from snippet', () => { + const name = "TestPartialViewFromSnippet"; + const fileName = name + ".cshtml"; + + cy.umbracoEnsurePartialViewNameNotExists(fileName); + + openPartialViewsCreatePanel(); + + cy.umbracoContextMenuAction("action-create").click(); + cy.get('.menu-label').eq(1).click(); + // Select snippet + cy.get('.menu-label').eq(2).click(); + + // Type name + cy.umbracoEditorHeaderName(name); + + // Save + cy.get('.btn-success').click(); + + // Assert + cy.umbracoSuccessNotification().should('be.visible'); + cy.umbracoPartialViewExists(fileName).then(exists => { expect(exists).to.be.true; }); + + // Clean up + cy.umbracoEnsurePartialViewNameNotExists(fileName); + }); + + it('Partial view with no name', () => { + openPartialViewsCreatePanel(); + + cy.umbracoContextMenuAction("action-create").click(); + cy.get('.menu-label').first().click(); + + // The test would fail intermittently, most likely because the editor didn't have time to load + // This should ensure that the editor is loaded and the test should no longer fail unexpectedly. + cy.get('.ace_content', {timeout: 5000}).should('exist'); + + // Click save + cy.get('.btn-success').click(); + + // Asserts + cy.umbracoErrorNotification().should('be.visible'); + }); + + it('Delete partial view', () => { + const name = "TestDeletePartialView"; + const fileName = name + ".cshtml"; + + cy.umbracoEnsurePartialViewNameNotExists(fileName); + + // Build and save partial view + const partialView = new PartialViewBuilder() + .withName(name) + .withContent("@inherits Umbraco.Web.Mvc.UmbracoViewPage") + .build(); + + cy.savePartialView(partialView); + + navigateToSettings(); + + // Delete partial view + cy.umbracoTreeItem("settings", ["Partial Views", fileName]).rightclick(); + cy.umbracoContextMenuAction("action-delete").click(); + cy.umbracoButtonByLabelKey("general_ok").click(); + + // Assert + cy.contains(fileName).should('not.exist'); + cy.umbracoPartialViewExists(fileName).then(exists => { expect(exists).to.be.false; }); + + // Clean + cy.umbracoEnsurePartialViewNameNotExists(fileName); + }); + + it('Edit partial view', () => { + const name = 'EditPartialView'; + const fileName = name + ".cshtml"; + + cy.umbracoEnsurePartialViewNameNotExists(fileName); + + const partialView = new PartialViewBuilder() + .withName(name) + .withContent("@inherits Umbraco.Web.Mvc.UmbracoViewPage\n") + .build(); + + cy.savePartialView(partialView); + + navigateToSettings(); + // Open partial view + cy.umbracoTreeItem("settings", ["Partial Views", fileName]).click(); + // Edit + cy.get('.ace_text-input').type("var num = 5;", {force:true} ); + cy.get('.btn-success').click(); + + // Assert + cy.umbracoSuccessNotification().should('be.visible'); + // Clean + cy.umbracoEnsurePartialViewNameNotExists(fileName); + }); - //Clean up - cy.umbracoEnsurePartialViewNameNotExists(fileName); - }); }); diff --git a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/scripts.ts b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/scripts.ts index 8cffd3e59b..cce8a45da6 100644 --- a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/scripts.ts +++ b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/scripts.ts @@ -14,7 +14,7 @@ context('Scripts', () => { cy.umbracoSection('settings'); cy.get('li .umb-tree-root:contains("Settings")').should("be.visible"); - cy.umbracoTreeItem("settings", ["Stylesheets"]).rightclick(); + cy.umbracoTreeItem("settings", ["Scripts"]).rightclick(); cy.umbracoContextMenuAction("action-create").click(); cy.get('.menu-label').first().click(); // TODO: Fucked we cant use something like cy.umbracoContextMenuAction("action-mediaType").click(); diff --git a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/templates.ts b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/templates.ts index 6871db7ffe..aff1c38093 100644 --- a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/templates.ts +++ b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Settings/templates.ts @@ -1,57 +1,168 @@ /// -import {DocumentTypeBuilder, TemplateBuilder} from "umbraco-cypress-testhelpers"; +import { TemplateBuilder } from 'umbraco-cypress-testhelpers'; context('Templates', () => { - beforeEach(() => { - cy.umbracoLogin(Cypress.env('username'), Cypress.env('password')); - }); - - it('Create template', () => { - const name = "Test template"; - - cy.umbracoEnsureTemplateNameNotExists(name); + beforeEach(() => { + cy.umbracoLogin(Cypress.env('username'), Cypress.env('password')); + }); + function navigateToSettings() { cy.umbracoSection('settings'); cy.get('li .umb-tree-root:contains("Settings")').should("be.visible"); + } + function createTemplate() { + navigateToSettings(); cy.umbracoTreeItem("settings", ["Templates"]).rightclick(); - cy.umbracoContextMenuAction("action-create").click(); + } + + + it('Create template', () => { + const name = "Test template test"; + cy.umbracoEnsureTemplateNameNotExists(name); + + createTemplate(); //Type name cy.umbracoEditorHeaderName(name); + /* Make an edit, if you don't the file will be create twice, + only happens in testing though, probably because the test is too fast + Certifiably mega wonk regardless */ + cy.get('.ace_text-input').type("var num = 5;", {force:true} ); //Save - cy.get("form[name='contentForm']").submit(); + cy.get('.btn-success').click(); //Assert cy.umbracoSuccessNotification().should('be.visible'); //Clean up cy.umbracoEnsureTemplateNameNotExists(name); - }); + }); - it('Delete template', () => { - const name = "Test template"; + it('Unsaved changes stay', () => { + const name = "Templates Unsaved Changes Stay test"; + const edit = "var num = 5;"; cy.umbracoEnsureTemplateNameNotExists(name); const template = new TemplateBuilder() .withName(name) + .withContent('@inherits Umbraco.Web.Mvc.UmbracoViewPage\n') .build(); cy.saveTemplate(template); - cy.umbracoSection('settings'); - cy.get('li .umb-tree-root:contains("Settings")').should("be.visible"); + navigateToSettings(); - cy.umbracoTreeItem("settings", ["Templates", name]).rightclick(); - cy.umbracoContextMenuAction("action-delete").click(); + // Open partial view + cy.umbracoTreeItem("settings", ["Templates", name]).click(); + // Edit + cy.get('.ace_text-input').type(edit, {force:true} ); - cy.umbracoButtonByLabelKey("general_ok").click(); + // Navigate away + cy.umbracoSection('content'); + // Click stay button + cy.get('umb-button[label="Stay"] button:enabled').click(); - cy.contains(name).should('not.exist'); + // Assert + // That the same document is open + cy.get('#headerName').should('have.value', name); + cy.get('.ace_content').contains(edit); cy.umbracoEnsureTemplateNameNotExists(name); }); + + it('Discard unsaved changes', () => { + const name = "Discard changes test"; + const edit = "var num = 5;"; + + cy.umbracoEnsureTemplateNameNotExists(name); + + const template = new TemplateBuilder() + .withName(name) + .withContent('@inherits Umbraco.Web.Mvc.UmbracoViewPage\n') + .build(); + + cy.saveTemplate(template); + + navigateToSettings(); + + // Open partial view + cy.umbracoTreeItem("settings", ["Templates", name]).click(); + // Edit + cy.get('.ace_text-input').type(edit, {force:true} ); + + // Navigate away + cy.umbracoSection('content'); + // Click discard + cy.get('umb-button[label="Discard changes"] button:enabled').click(); + // Navigate back + cy.umbracoSection('settings'); + + // Asserts + cy.get('.ace_content').should('not.contain', edit); + // cy.umbracoPartialViewExists(fileName).then(exists => { expect(exists).to.be.false; }); TODO: Switch to template + cy.umbracoEnsureTemplateNameNotExists(name); + }); + + it('Insert macro', () => { + const name = 'InsertMacroTest'; + + cy.umbracoEnsureTemplateNameNotExists(name); + cy.umbracoEnsureMacroNameNotExists(name); + + const template = new TemplateBuilder() + .withName(name) + .withContent('') + .build(); + + cy.saveTemplate(template); + + cy.saveMacro(name); + + navigateToSettings(); + cy.umbracoTreeItem("settings", ["Templates", name]).click(); + // Insert macro + cy.umbracoButtonByLabelKey('general_insert').click(); + cy.get('.umb-insert-code-box__title').contains('Macro').click(); + cy.get('.umb-card-grid-item').contains(name).click(); + + // Assert + cy.get('.ace_content').contains('@Umbraco.RenderMacro("' + name + '")').should('exist'); + + // Clean + cy.umbracoEnsureTemplateNameNotExists(name); + cy.umbracoEnsureMacroNameNotExists(name); + }); + + it('Insert value', () => { + const name = 'Insert Value Test'; + + cy.umbracoEnsureTemplateNameNotExists(name); + + const partialView = new TemplateBuilder() + .withName(name) + .withContent('') + .build(); + + cy.saveTemplate(partialView); + + navigateToSettings(); + cy.umbracoTreeItem("settings", ["Templates", name]).click(); + + // Insert value + cy.umbracoButtonByLabelKey('general_insert').click(); + cy.get('.umb-insert-code-box__title').contains('Value').click(); + cy.get('select').select('umbracoBytes'); + cy.umbracoButtonByLabelKey('general_submit').click(); + + // assert + cy.get('.ace_content').contains('@Model.Value("umbracoBytes")').should('exist'); + + // Clean + cy.umbracoEnsureTemplateNameNotExists(name); + }); + }); diff --git a/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Tour/backofficeTour.ts b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Tour/backofficeTour.ts new file mode 100644 index 0000000000..ed891a2eea --- /dev/null +++ b/src/Umbraco.Tests.AcceptanceTest/cypress/integration/Tour/backofficeTour.ts @@ -0,0 +1,49 @@ +/// +context('Backoffice Tour', () => { + + beforeEach(() => { + cy.umbracoLogin(Cypress.env('username'), Cypress.env('password')); + }); + + it('Backoffice introduction tour should run', () => { + //arrange + cy.umbracoGlobalHelp().should("be.visible"); + + //act + cy.umbracoGlobalHelp().click() + //assert + cy.get('[data-element="help-tours"]').should("be.visible"); + //act + cy.get('[data-element="help-tours"]').click(); + //assert + cy.get('[data-element="tour-umbIntroIntroduction"] .umb-button').should("be.visible"); + //act + cy.get('[data-element="tour-umbIntroIntroduction"] .umb-button').click(); + //assert + cy.get('.umb-tour-step', { timeout: 60000 }).should('be.visible'); + cy.get('.umb-tour-step__footer').should('be.visible'); + cy.get('.umb-tour-step__counter').should('be.visible'); + + for(let i=1;i<7;i++){ + cy.get('.umb-tour-step__counter').contains(i + '/12'); + cy.get('.umb-tour-step__footer .umb-button').should('be.visible').click(); + } + cy.umbracoGlobalUser().click() + cy.get('.umb-tour-step__counter').contains('8/12'); + cy.get('.umb-tour-step__footer .umb-button').should('be.visible').click(); + cy.get('.umb-tour-step__counter').contains('9/12'); + cy.get('.umb-overlay-drawer__align-right .umb-button').should('be.visible').click(); + cy.get('.umb-tour-step__counter').contains('10/12'); + cy.umbracoGlobalHelp().click() + + for(let i=11;i<13;i++){ + cy.get('.umb-tour-step__counter').contains(i + '/12'); + cy.get('.umb-tour-step__footer .umb-button').should('be.visible').click(); + } + cy.get('.umb-tour-step__footer .umb-button').should('be.visible').click(); + + //assert + cy.umbracoGlobalHelp().should("be.visible"); + cy.get('[data-element="help-tours"] .umb-progress-circle').contains('17%'); + }); +}); diff --git a/src/Umbraco.Tests.AcceptanceTest/package.json b/src/Umbraco.Tests.AcceptanceTest/package.json index 3b4177ce3f..867b7f5cf3 100644 --- a/src/Umbraco.Tests.AcceptanceTest/package.json +++ b/src/Umbraco.Tests.AcceptanceTest/package.json @@ -5,9 +5,9 @@ }, "devDependencies": { "cross-env": "^7.0.2", + "cypress": "^4.12.1", "ncp": "^2.0.0", - "cypress": "^4.9.0", - "umbraco-cypress-testhelpers": "1.0.0-beta-44" + "umbraco-cypress-testhelpers": "^1.0.0-beta-48" }, "dependencies": { "typescript": "^3.9.2" diff --git a/src/Umbraco.Tests.Common/Builders/GlobalSettingsBuilder.cs b/src/Umbraco.Tests.Common/Builders/GlobalSettingsBuilder.cs index 4a88d4a571..b1fe45f1f7 100644 --- a/src/Umbraco.Tests.Common/Builders/GlobalSettingsBuilder.cs +++ b/src/Umbraco.Tests.Common/Builders/GlobalSettingsBuilder.cs @@ -220,8 +220,12 @@ namespace Umbraco.Tests.Common.Builders private class TestGlobalSettings : IGlobalSettings { + private string _iconsPath; public string ReservedUrls { get; set; } public string ReservedPaths { get; set; } + + public string IconsPath{ get; set; } + public string Path { get; set; } public string ConfigurationStatus { get; set; } public int TimeOutInMinutes { get; set; } diff --git a/src/Umbraco.Tests/Services/UserServiceTests.cs b/src/Umbraco.Tests/Services/UserServiceTests.cs index dbd71870d4..3c1b0bcc31 100644 --- a/src/Umbraco.Tests/Services/UserServiceTests.cs +++ b/src/Umbraco.Tests/Services/UserServiceTests.cs @@ -7,6 +7,7 @@ using System.Threading; using NUnit.Framework; using Umbraco.Core; using Umbraco.Core.Exceptions; +using Umbraco.Core.Models; using Umbraco.Core.Models.Membership; using Umbraco.Core.Persistence.DatabaseModelDefinitions; using Umbraco.Tests.TestHelpers.Entities; @@ -968,16 +969,72 @@ namespace Umbraco.Tests.Services Assert.That(updatedItem.AllowedSections.Count(), Is.EqualTo(originalUser.AllowedSections.Count())); } + [Test] + public void Can_Get_Assigned_StartNodes_For_User() + { + var startContentItems = BuildContentItems(3); + + var testUserGroup = CreateTestUserGroup(); + + var userGroupId = testUserGroup.Id; + + CreateTestUsers(startContentItems.Select(x => x.Id).ToArray(), testUserGroup, 3); + + var usersInGroup = ServiceContext.UserService.GetAllInGroup(userGroupId); + + foreach (var user in usersInGroup) + Assert.AreEqual(user.StartContentIds.Length, startContentItems.Length); + } + + private Content[] BuildContentItems(int numberToCreate) + { + var contentType = MockedContentTypes.CreateSimpleContentType(); + + ServiceContext.ContentTypeService.Save(contentType); + + var startContentItems = new List(); + + for (var i = 0; i < numberToCreate; i++) + startContentItems.Add(MockedContent.CreateSimpleContent(contentType)); + + ServiceContext.ContentService.Save(startContentItems); + + return startContentItems.ToArray(); + } + private IUser CreateTestUser(out IUserGroup userGroup) { userGroup = CreateTestUserGroup(); var user = ServiceContext.UserService.CreateUserWithIdentity("test1", "test1@test.com"); + user.AddGroup(userGroup.ToReadOnlyGroup()); + ServiceContext.UserService.Save(user); + return user; } + private List CreateTestUsers(int[] startContentIds, IUserGroup userGroup, int numberToCreate) + { + var users = new List(); + + for (var i = 0; i < numberToCreate; i++) + { + var user = ServiceContext.UserService.CreateUserWithIdentity($"test{i}", $"test{i}@test.com"); + user.AddGroup(userGroup.ToReadOnlyGroup()); + + var updateable = (User)user; + updateable.StartContentIds = startContentIds; + + ServiceContext.UserService.Save(user); + + users.Add(user); + } + + return users; + } + private UserGroup CreateTestUserGroup(string alias = "testGroup", string name = "Test Group") { var userGroup = new UserGroup(ShortStringHelper) diff --git a/src/Umbraco.Tests/TestHelpers/TestObjects.cs b/src/Umbraco.Tests/TestHelpers/TestObjects.cs index 44f6be8e7d..7356018c58 100644 --- a/src/Umbraco.Tests/TestHelpers/TestObjects.cs +++ b/src/Umbraco.Tests/TestHelpers/TestObjects.cs @@ -190,7 +190,7 @@ namespace Umbraco.Tests.TestHelpers Mock.Of(x => x.ApplicationPhysicalPath == ioHelper.MapPath("~"))), ioHelper); }); - var relationService = GetLazyService(factory, c => new RelationService(scopeProvider, logger, eventMessagesFactory, entityService.Value, GetRepo(c), GetRepo(c))); + var relationService = GetLazyService(factory, c => new RelationService(scopeProvider, logger, eventMessagesFactory, entityService.Value, GetRepo(c), GetRepo(c), GetRepo(c))); var tagService = GetLazyService(factory, c => new TagService(scopeProvider, logger, eventMessagesFactory, GetRepo(c))); var redirectUrlService = GetLazyService(factory, c => new RedirectUrlService(scopeProvider, logger, eventMessagesFactory, GetRepo(c))); var consentService = GetLazyService(factory, c => new ConsentService(scopeProvider, logger, eventMessagesFactory, GetRepo(c))); diff --git a/src/Umbraco.Web.BackOffice/Controllers/BackOfficeServerVariables.cs b/src/Umbraco.Web.BackOffice/Controllers/BackOfficeServerVariables.cs index f3d11dea78..34494e1492 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/BackOfficeServerVariables.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/BackOfficeServerVariables.cs @@ -180,6 +180,10 @@ namespace Umbraco.Web.BackOffice.Controllers "mediaApiBaseUrl", _linkGenerator.GetUmbracoApiServiceBaseUrl( controller => controller.GetRootMedia()) }, + { + "iconApiBaseUrl", _linkGenerator.GetUmbracoApiServiceBaseUrl( + controller => controller.GetIcon("")) + }, { "imagesApiBaseUrl", _linkGenerator.GetUmbracoApiServiceBaseUrl( controller => controller.GetBigThumbnail("")) diff --git a/src/Umbraco.Web.BackOffice/Controllers/ContentTypeController.cs b/src/Umbraco.Web.BackOffice/Controllers/ContentTypeController.cs index 444667b591..146f2c32b7 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/ContentTypeController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/ContentTypeController.cs @@ -3,8 +3,6 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; -using System.Net.Http; -using System.Net.Http.Headers; using System.Net.Mime; using System.Text; using System.Threading.Tasks; @@ -13,30 +11,25 @@ using System.Xml.Linq; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Umbraco.Core; -using Umbraco.Core.Cache; using Umbraco.Core.Configuration; using Umbraco.Core.Dictionary; using Umbraco.Core.Hosting; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Models; -using Umbraco.Core.Models.Editors; using Umbraco.Core.Packaging; -using Umbraco.Core.Persistence; using Umbraco.Core.PropertyEditors; using Umbraco.Core.Scoping; using Umbraco.Core.Services; using Umbraco.Core.Strings; using Umbraco.Web.Models; using Umbraco.Web.Models.ContentEditing; -using Umbraco.Web.WebApi.Filters; using Constants = Umbraco.Core.Constants; using Umbraco.Core.Mapping; using Umbraco.Web.BackOffice.Filters; using Umbraco.Web.Common.Attributes; using Umbraco.Web.Common.Exceptions; using Umbraco.Web.Editors; -using Umbraco.Web.Routing; using Umbraco.Web.Security; using ContentType = Umbraco.Core.Models.ContentType; @@ -140,6 +133,12 @@ namespace Umbraco.Web.BackOffice.Controllers return _contentTypeService.HasContentNodes(id); } + /// + /// Gets the document type a given id + /// + /// + /// + [DetermineAmbiguousActionByPassingParameters] public DocumentTypeDisplay GetById(int id) { var ct = _contentTypeService.Get(id); @@ -152,6 +151,46 @@ namespace Umbraco.Web.BackOffice.Controllers return dto; } + /// + /// Gets the document type a given guid + /// + /// + /// + [DetermineAmbiguousActionByPassingParameters] + public DocumentTypeDisplay GetById(Guid id) + { + var contentType = _contentTypeService.Get(id); + if (contentType == null) + { + throw new HttpResponseException(HttpStatusCode.NotFound); + } + + var dto = _umbracoMapper.Map(contentType); + return dto; + } + + /// + /// Gets the document type a given udi + /// + /// + /// + [DetermineAmbiguousActionByPassingParameters] + public DocumentTypeDisplay GetById(Udi id) + { + var guidUdi = id as GuidUdi; + if (guidUdi == null) + throw new HttpResponseException(HttpStatusCode.NotFound); + + var contentType = _contentTypeService.Get(guidUdi.Guid); + if (contentType == null) + { + throw new HttpResponseException(HttpStatusCode.NotFound); + } + + var dto = _umbracoMapper.Map(contentType); + return dto; + } + /// /// Deletes a document type with a given ID /// diff --git a/src/Umbraco.Web.BackOffice/Controllers/DictionaryController.cs b/src/Umbraco.Web.BackOffice/Controllers/DictionaryController.cs index 7d362e52b6..26cccb9141 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/DictionaryController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/DictionaryController.cs @@ -1,9 +1,9 @@ using System; using System.Collections.Generic; -using System.Net; using System.Linq; using System.Net.Http; using Microsoft.AspNetCore.Mvc; +using Umbraco.Core; using Umbraco.Core.Configuration; using Umbraco.Core.Logging; using Umbraco.Core.Mapping; @@ -129,7 +129,7 @@ namespace Umbraco.Web.BackOffice.Controllers } } - /// + /// /// Gets a dictionary item by id /// /// @@ -141,10 +141,58 @@ namespace Umbraco.Web.BackOffice.Controllers /// /// Returns a not found response when dictionary item does not exist /// + [DetermineAmbiguousActionByPassingParameters] public ActionResult GetById(int id) { var dictionary = _localizationService.GetDictionaryItemById(id); + if (dictionary == null) + return NotFound(); + return _umbracoMapper.Map(dictionary); + } + + /// + /// Gets a dictionary item by guid + /// + /// + /// The id. + /// + /// + /// The . + /// + /// + /// Returns a not found response when dictionary item does not exist + /// + [DetermineAmbiguousActionByPassingParameters] + public ActionResult GetById(Guid id) + { + var dictionary = _localizationService.GetDictionaryItemById(id); + if (dictionary == null) + return NotFound(); + + return _umbracoMapper.Map(dictionary); + } + + /// + /// Gets a dictionary item by udi + /// + /// + /// The id. + /// + /// + /// The . + /// + /// + /// Returns a not found response when dictionary item does not exist + /// + [DetermineAmbiguousActionByPassingParameters] + public ActionResult GetById(Udi id) + { + var guidUdi = id as GuidUdi; + if (guidUdi == null) + return NotFound(); + + var dictionary = _localizationService.GetDictionaryItemById(guidUdi.Guid); if (dictionary == null) return NotFound(); @@ -222,19 +270,30 @@ namespace Umbraco.Web.BackOffice.Controllers /// public IEnumerable GetList() { - var list = new List(); + var items = _localizationService.GetDictionaryItemDescendants(null).ToArray(); + var list = new List(items.Length); - const int level = 0; - - foreach (var dictionaryItem in _localizationService.GetRootDictionaryItems().OrderBy(ItemSort())) + // recursive method to build a tree structure from the flat structure returned above + void BuildTree(int level = 0, Guid? parentId = null) { - var item = _umbracoMapper.Map(dictionaryItem); - item.Level = 0; - list.Add(item); + var children = items.Where(t => t.ParentId == parentId).ToArray(); + if(children.Any() == false) + { + return; + } - GetChildItemsForList(dictionaryItem, level + 1, list); + foreach(var child in children.OrderBy(ItemSort())) + { + var display = _umbracoMapper.Map(child); + display.Level = level; + list.Add(display); + + BuildTree(level + 1, child.Key); + } } + BuildTree(); + return list; } diff --git a/src/Umbraco.Web.BackOffice/Controllers/IconController.cs b/src/Umbraco.Web.BackOffice/Controllers/IconController.cs new file mode 100644 index 0000000000..2aa2761134 --- /dev/null +++ b/src/Umbraco.Web.BackOffice/Controllers/IconController.cs @@ -0,0 +1,108 @@ +using System.Collections.Generic; +using System.Linq; +using Umbraco.Web.Models; +using System.IO; +using Umbraco.Core; +using Ganss.XSS; +using Umbraco.Core.Configuration; +using Umbraco.Core.Hosting; +using Umbraco.Web.BackOffice.Controllers; +using Umbraco.Web.Common.Attributes; + +namespace Umbraco.Web.Editors +{ + [PluginController("UmbracoApi")] + public class IconController : UmbracoAuthorizedApiController + { + private readonly IHostingEnvironment _hostingEnvironment; + private readonly IGlobalSettings _globalSettings; + + public IconController( + IHostingEnvironment hostingEnvironment, + IGlobalSettings globalSettings) + { + _hostingEnvironment = hostingEnvironment; + _globalSettings = globalSettings; + } + + /// + /// Gets an IconModel containing the icon name and SvgString according to an icon name found at the global icons path + /// + /// + /// + public IconModel GetIcon(string iconName) + { + return string.IsNullOrWhiteSpace(iconName) + ? null + : CreateIconModel(iconName.StripFileExtension(), + _hostingEnvironment.MapPathWebRoot($"{_globalSettings.IconsPath}/{iconName}.svg")); + } + + /// + /// Gets an IconModel using values from a FileInfo model + /// + /// + /// + public IconModel GetIcon(FileInfo fileInfo) + { + return fileInfo == null || string.IsNullOrWhiteSpace(fileInfo.Name) + ? null + : CreateIconModel(fileInfo.Name.StripFileExtension(), fileInfo.FullName); + } + + /// + /// Gets a list of all svg icons found at at the global icons path. + /// + /// + public List GetAllIcons() + { + var icons = new List(); + var directory = new DirectoryInfo(_hostingEnvironment.MapPathWebRoot($"{_globalSettings.IconsPath}/")); + var iconNames = directory.GetFiles("*.svg"); + + iconNames.OrderBy(f => f.Name).ToList().ForEach(iconInfo => + { + var icon = GetIcon(iconInfo); + + if (icon != null) + { + icons.Add(icon); + } + }); + + return icons; + } + + /// + /// Gets an IconModel containing the icon name and SvgString + /// + /// + /// + /// + private IconModel CreateIconModel(string iconName, string iconPath) + { + var sanitizer = new HtmlSanitizer(); + sanitizer.AllowedAttributes.UnionWith(Core.Constants.SvgSanitizer.Attributes); + sanitizer.AllowedCssProperties.UnionWith(Core.Constants.SvgSanitizer.Attributes); + sanitizer.AllowedTags.UnionWith(Core.Constants.SvgSanitizer.Tags); + + try + { + var svgContent = System.IO.File.ReadAllText(iconPath); + var sanitizedString = sanitizer.Sanitize(svgContent); + + var svg = new IconModel + { + Name = iconName, + SvgString = sanitizedString + }; + + return svg; + } + catch + { + return null; + } + } + } +} diff --git a/src/Umbraco.Web.BackOffice/Controllers/ImagesController.cs b/src/Umbraco.Web.BackOffice/Controllers/ImagesController.cs index 6ce6d3a1c6..b264fd987b 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/ImagesController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/ImagesController.cs @@ -21,7 +21,8 @@ namespace Umbraco.Web.BackOffice.Controllers private readonly IContentSettings _contentSettings; private readonly IImageUrlGenerator _imageUrlGenerator; - public ImagesController(IMediaFileSystem mediaFileSystem, IContentSettings contentSettings, IImageUrlGenerator imageUrlGenerator) + public ImagesController(IMediaFileSystem mediaFileSystem, IContentSettings contentSettings, + IImageUrlGenerator imageUrlGenerator) { _mediaFileSystem = mediaFileSystem; _contentSettings = contentSettings; @@ -65,7 +66,6 @@ namespace Umbraco.Web.BackOffice.Controllers try { imageLastModified = _mediaFileSystem.GetLastModified(imagePath); - } catch (Exception) { @@ -76,7 +76,14 @@ namespace Umbraco.Web.BackOffice.Controllers } var rnd = imageLastModified.HasValue ? $"&rnd={imageLastModified:yyyyMMddHHmmss}" : null; - var imageUrl = _imageUrlGenerator.GetImageUrl(new ImageUrlGenerationOptions(imagePath) { UpScale = false, Width = width, AnimationProcessMode = "first", ImageCropMode = ImageCropMode.Max, CacheBusterValue = rnd }); + var imageUrl = _imageUrlGenerator.GetImageUrl(new ImageUrlGenerationOptions(imagePath) + { + UpScale = false, + Width = width, + AnimationProcessMode = "first", + ImageCropMode = ImageCropMode.Max, + CacheBusterValue = rnd + }); return new RedirectResult(imageUrl, false); } @@ -92,20 +99,30 @@ namespace Umbraco.Web.BackOffice.Controllers /// /// /// + /// + /// + /// /// /// /// If there is no media, image property or image file is found then this will return not found. /// public string GetProcessedImageUrl(string imagePath, - int? width = null, - int? height = null, - int? focalPointLeft = null, - int? focalPointTop = null, - string animationProcessMode = "first", + int? width = null, + int? height = null, + decimal? focalPointLeft = null, + decimal? focalPointTop = null, + string animationProcessMode = "first", ImageCropMode mode = ImageCropMode.Max, - bool upscale = false, - string cacheBusterValue = "") -{ + bool upscale = false, + string cacheBusterValue = "", + decimal? cropX1 = null, + decimal? cropX2 = null, + decimal? cropY1 = null, + decimal? cropY2 = null + ) + { + + var options = new ImageUrlGenerationOptions(imagePath) { AnimationProcessMode = animationProcessMode, @@ -114,13 +131,35 @@ namespace Umbraco.Web.BackOffice.Controllers ImageCropMode = mode, UpScale = upscale, Width = width, + Crop = (cropX1.HasValue && cropX2.HasValue && cropY1.HasValue && cropY2.HasValue) ? new ImageUrlGenerationOptions.CropCoordinates(cropX1.Value, cropY1.Value, cropX2.Value, cropY2.Value) : null, + FocalPoint = new ImageUrlGenerationOptions.FocalPointPosition(focalPointTop.GetValueOrDefault(0.5m), focalPointLeft.GetValueOrDefault(0.5m)), }; if (focalPointLeft.HasValue && focalPointTop.HasValue) { - options.FocalPoint = new ImageUrlGenerationOptions.FocalPointPosition(focalPointTop.Value, focalPointLeft.Value); + options.FocalPoint = + new ImageUrlGenerationOptions.FocalPointPosition(focalPointTop.Value, focalPointLeft.Value); } return _imageUrlGenerator.GetImageUrl(options); } + + public class FocalPointPositionModel + { + public decimal Left { get; set; } + public decimal Top { get; set; } + } + + /// + /// The bounds of the crop within the original image, in whatever units the registered + /// IImageUrlGenerator uses, typically a percentage between 0 and 100. + /// + public class CropCoordinatesModel + { + + public decimal X1 { get; set; } + public decimal Y1 { get; set; } + public decimal X2 { get; set;} + public decimal Y2 { get; set;} + } } } diff --git a/src/Umbraco.Web.BackOffice/Controllers/LogController.cs b/src/Umbraco.Web.BackOffice/Controllers/LogController.cs index 297c39a450..e99ea890d7 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/LogController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/LogController.cs @@ -98,6 +98,13 @@ namespace Umbraco.Web.BackOffice.Controllers }; } + public IEnumerable GetLog(AuditType logType, DateTime? sinceDate = null) + { + var result = _auditService.GetLogs(Enum.Parse(logType.ToString()), sinceDate); + var mapped = _umbracoMapper.MapEnumerable(result); + return mapped; + } + private IEnumerable MapAvatarsAndNames(IEnumerable items) { var mappedItems = items.ToList(); diff --git a/src/Umbraco.Web.BackOffice/Controllers/MediaController.cs b/src/Umbraco.Web.BackOffice/Controllers/MediaController.cs index 6bb68248b1..ba19f7c2b4 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/MediaController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/MediaController.cs @@ -160,15 +160,15 @@ namespace Umbraco.Web.BackOffice.Controllers [DetermineAmbiguousActionByPassingParameters] public MediaItemDisplay GetById(int id) { - var foundContent = GetObjectFromRequest(() => _mediaService.GetById(id)); + var foundMedia = GetObjectFromRequest(() => _mediaService.GetById(id)); - if (foundContent == null) + if (foundMedia == null) { HandleContentNotFound(id); //HandleContentNotFound will throw an exception return null; } - return _umbracoMapper.Map(foundContent); + return _umbracoMapper.Map(foundMedia); } /// @@ -181,15 +181,15 @@ namespace Umbraco.Web.BackOffice.Controllers [DetermineAmbiguousActionByPassingParameters] public MediaItemDisplay GetById(Guid id) { - var foundContent = GetObjectFromRequest(() => _mediaService.GetById(id)); + var foundMedia = GetObjectFromRequest(() => _mediaService.GetById(id)); - if (foundContent == null) + if (foundMedia == null) { HandleContentNotFound(id); //HandleContentNotFound will throw an exception return null; } - return _umbracoMapper.Map(foundContent); + return _umbracoMapper.Map(foundMedia); } /// @@ -800,10 +800,13 @@ namespace Umbraco.Web.BackOffice.Controllers var total = long.MaxValue; while (page * pageSize < total) { - var children = _mediaService.GetPagedChildren(mediaId, page, pageSize, out total, + var children = _mediaService.GetPagedChildren(mediaId, page++, pageSize, out total, _sqlContext.Query().Where(x => x.Name == nameToFind)); - foreach (var c in children) - return c; //return first one if any are found + var match = children.FirstOrDefault(c => c.ContentType.Alias == contentTypeAlias); + if (match != null) + { + return match; + } } return null; } diff --git a/src/Umbraco.Web.BackOffice/Controllers/MediaTypeController.cs b/src/Umbraco.Web.BackOffice/Controllers/MediaTypeController.cs index d030d03cf9..617d3f1538 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/MediaTypeController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/MediaTypeController.cs @@ -71,6 +71,12 @@ namespace Umbraco.Web.BackOffice.Controllers public int GetCount() => _contentTypeService.Count(); + /// + /// Gets the media type a given id + /// + /// + /// + [DetermineAmbiguousActionByPassingParameters] [UmbracoTreeAuthorize(Constants.Trees.MediaTypes, Constants.Trees.Media)] public MediaTypeDisplay GetById(int id) { @@ -84,6 +90,48 @@ namespace Umbraco.Web.BackOffice.Controllers return dto; } + /// + /// Gets the media type a given guid + /// + /// + /// + [DetermineAmbiguousActionByPassingParameters] + [UmbracoTreeAuthorize(Constants.Trees.MediaTypes, Constants.Trees.Media)] + public MediaTypeDisplay GetById(Guid id) + { + var mediaType = _mediaTypeService.Get(id); + if (mediaType == null) + { + throw new HttpResponseException(HttpStatusCode.NotFound); + } + + var dto = _umbracoMapper.Map(mediaType); + return dto; + } + + /// + /// Gets the media type a given udi + /// + /// + /// + [DetermineAmbiguousActionByPassingParameters] + [UmbracoTreeAuthorize(Constants.Trees.MediaTypes, Constants.Trees.Media)] + public MediaTypeDisplay GetById(Udi id) + { + var guidUdi = id as GuidUdi; + if (guidUdi == null) + throw new HttpResponseException(HttpStatusCode.NotFound); + + var mediaType = _mediaTypeService.Get(guidUdi.Guid); + if (mediaType == null) + { + throw new HttpResponseException(HttpStatusCode.NotFound); + } + + var dto = _umbracoMapper.Map(mediaType); + return dto; + } + /// /// Deletes a media type with a given ID /// diff --git a/src/Umbraco.Web.BackOffice/Controllers/MemberGroupController.cs b/src/Umbraco.Web.BackOffice/Controllers/MemberGroupController.cs index 153990937d..d3d06132d3 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/MemberGroupController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/MemberGroupController.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Net; using Microsoft.AspNetCore.Mvc; +using Umbraco.Core; using Umbraco.Core.Mapping; using Umbraco.Core.Models; using Umbraco.Core.Services; @@ -37,6 +38,12 @@ namespace Umbraco.Web.BackOffice.Controllers localizedTextService ?? throw new ArgumentNullException(nameof(localizedTextService)); } + /// + /// Gets the member group json for the member group id + /// + /// + /// + [DetermineAmbiguousActionByPassingParameters] public MemberGroupDisplay GetById(int id) { var memberGroup = _memberGroupService.GetById(id); @@ -49,6 +56,45 @@ namespace Umbraco.Web.BackOffice.Controllers return dto; } + + /// + /// Gets the member group json for the member group guid + /// + /// + /// + [DetermineAmbiguousActionByPassingParameters] + public MemberGroupDisplay GetById(Guid id) + { + var memberGroup = _memberGroupService.GetById(id); + if (memberGroup == null) + { + throw new HttpResponseException(HttpStatusCode.NotFound); + } + + return _umbracoMapper.Map(memberGroup); + } + + /// + /// Gets the member group json for the member group udi + /// + /// + /// + [DetermineAmbiguousActionByPassingParameters] + public MemberGroupDisplay GetById(Udi id) + { + var guidUdi = id as GuidUdi; + if (guidUdi == null) + throw new HttpResponseException(HttpStatusCode.NotFound); + + var memberGroup = _memberGroupService.GetById(guidUdi.Guid); + if (memberGroup == null) + { + throw new HttpResponseException(HttpStatusCode.NotFound); + } + + return _umbracoMapper.Map(memberGroup); + } + public IEnumerable GetByIds([FromQuery]int[] ids) { return _memberGroupService.GetByIds(ids) diff --git a/src/Umbraco.Web.BackOffice/Controllers/MemberTypeController.cs b/src/Umbraco.Web.BackOffice/Controllers/MemberTypeController.cs index 240a2e0f5b..8ef8749c2d 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/MemberTypeController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/MemberTypeController.cs @@ -64,7 +64,13 @@ namespace Umbraco.Web.Editors localizedTextService ?? throw new ArgumentNullException(nameof(localizedTextService)); } + /// + /// Gets the member type a given id + /// + /// + /// [UmbracoTreeAuthorize(Constants.Trees.MemberTypes)] + [DetermineAmbiguousActionByPassingParameters] public MemberTypeDisplay GetById(int id) { var ct = _memberTypeService.Get(id); @@ -78,7 +84,49 @@ namespace Umbraco.Web.Editors } /// - /// Deletes a document type with a given ID + /// Gets the member type a given guid + /// + /// + /// + [UmbracoTreeAuthorize(Constants.Trees.MemberTypes)] + [DetermineAmbiguousActionByPassingParameters] + public MemberTypeDisplay GetById(Guid id) + { + var memberType = _memberTypeService.Get(id); + if (memberType == null) + { + throw new HttpResponseException(HttpStatusCode.NotFound); + } + + var dto = _umbracoMapper.Map(memberType); + return dto; + } + + /// + /// Gets the member type a given udi + /// + /// + /// + [UmbracoTreeAuthorize(Constants.Trees.MemberTypes)] + [DetermineAmbiguousActionByPassingParameters] + public MemberTypeDisplay GetById(Udi id) + { + var guidUdi = id as GuidUdi; + if (guidUdi == null) + throw new HttpResponseException(HttpStatusCode.NotFound); + + var memberType = _memberTypeService.Get(guidUdi.Guid); + if (memberType == null) + { + throw new HttpResponseException(HttpStatusCode.NotFound); + } + + var dto = _umbracoMapper.Map(memberType); + return dto; + } + + /// + /// Deletes a document type with a given id /// /// /// diff --git a/src/Umbraco.Web.BackOffice/Controllers/RelationTypeController.cs b/src/Umbraco.Web.BackOffice/Controllers/RelationTypeController.cs index ef7fe94e77..0991dca09f 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/RelationTypeController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/RelationTypeController.cs @@ -49,6 +49,7 @@ namespace Umbraco.Web.BackOffice.Controllers /// /// The relation type ID. /// Returns the . + [DetermineAmbiguousActionByPassingParameters] public RelationTypeDisplay GetById(int id) { var relationType = _relationService.GetRelationTypeById(id); @@ -63,6 +64,42 @@ namespace Umbraco.Web.BackOffice.Controllers return display; } + /// + /// Gets a relation type by guid + /// + /// The relation type ID. + /// Returns the . + [DetermineAmbiguousActionByPassingParameters] + public RelationTypeDisplay GetById(Guid id) + { + var relationType = _relationService.GetRelationTypeById(id); + if (relationType == null) + { + throw new HttpResponseException(HttpStatusCode.NotFound); + } + return _umbracoMapper.Map(relationType); + } + + /// + /// Gets a relation type by udi + /// + /// The relation type ID. + /// Returns the . + [DetermineAmbiguousActionByPassingParameters] + public RelationTypeDisplay GetById(Udi id) + { + var guidUdi = id as GuidUdi; + if (guidUdi == null) + throw new HttpResponseException(HttpStatusCode.NotFound); + + var relationType = _relationService.GetRelationTypeById(guidUdi.Guid); + if (relationType == null) + { + throw new HttpResponseException(HttpStatusCode.NotFound); + } + return _umbracoMapper.Map(relationType); + } + public PagedResult GetPagedResults(int id, int pageNumber = 1, int pageSize = 100) { diff --git a/src/Umbraco.Web.BackOffice/Controllers/TemplateController.cs b/src/Umbraco.Web.BackOffice/Controllers/TemplateController.cs index b99ebce7a7..f80c3015e9 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/TemplateController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/TemplateController.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Net; using Microsoft.AspNetCore.Mvc; +using Umbraco.Core; using Umbraco.Core.IO; using Umbraco.Core.Mapping; using Umbraco.Core.Models; @@ -55,10 +56,11 @@ namespace Umbraco.Web.BackOffice.Controllers } /// - /// Gets the content json for the content id + /// Gets the template json for the template id /// /// /// + [DetermineAmbiguousActionByPassingParameters] public TemplateDisplay GetById(int id) { var template = _fileService.GetTemplate(id); @@ -68,6 +70,43 @@ namespace Umbraco.Web.BackOffice.Controllers return _umbracoMapper.Map(template); } + + /// + /// Gets the template json for the template guid + /// + /// + /// + [DetermineAmbiguousActionByPassingParameters] + public TemplateDisplay GetById(Guid id) + { + var template = _fileService.GetTemplate(id); + if (template == null) + throw new HttpResponseException(HttpStatusCode.NotFound); + + return _umbracoMapper.Map(template); + } + + /// + /// Gets the template json for the template udi + /// + /// + /// + [DetermineAmbiguousActionByPassingParameters] + public TemplateDisplay GetById(Udi id) + { + var guidUdi = id as GuidUdi; + if (guidUdi == null) + throw new HttpResponseException(HttpStatusCode.NotFound); + + var template = _fileService.GetTemplate(guidUdi.Guid); + if (template == null) + { + throw new HttpResponseException(HttpStatusCode.NotFound); + } + + return _umbracoMapper.Map(template); + } + /// /// Deletes a template with a given ID /// diff --git a/src/Umbraco.Web.BackOffice/Controllers/TemplateQueryController.cs b/src/Umbraco.Web.BackOffice/Controllers/TemplateQueryController.cs index e0808682d5..b1dd2e94e5 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/TemplateQueryController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/TemplateQueryController.cs @@ -95,7 +95,11 @@ namespace Umbraco.Web.BackOffice.Controllers QueryExpression = queryExpression.ToString(), ResultCount = results.Count, ExecutionTime = timer.ElapsedMilliseconds, - SampleResults = results.Take(20).Select(x => new TemplateQueryResult { Icon = "icon-file", Name = x.Name }) + SampleResults = results.Take(20).Select(x => new TemplateQueryResult + { + Icon = "icon-document", + Name = x.Name + }) }; } diff --git a/src/Umbraco.Web.BackOffice/Controllers/UsersController.cs b/src/Umbraco.Web.BackOffice/Controllers/UsersController.cs index fff609322c..75f7a6e512 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/UsersController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/UsersController.cs @@ -34,6 +34,7 @@ using Umbraco.Core.Hosting; using Umbraco.Core.Media; using Umbraco.Extensions; using Umbraco.Web.BackOffice.Filters; +using Umbraco.Web.BackOffice.ModelBinders; using Umbraco.Web.BackOffice.Security; using Umbraco.Web.Common.ActionResults; using Umbraco.Web.Common.Attributes; @@ -235,6 +236,33 @@ namespace Umbraco.Web.BackOffice.Controllers return result; } + /// + /// Get users by integer ids + /// + /// + /// + [TypeFilter(typeof(OutgoingEditorModelEventAttribute))] + [AdminUsersAuthorize] + public IEnumerable GetByIds([FromJsonPath]int[] ids) + { + if (ids == null) + { + throw new HttpResponseException(HttpStatusCode.NotFound); + } + + if (ids.Length == 0) + return Enumerable.Empty(); + + var users = _userService.GetUsersById(ids); + if (users == null) + { + throw new HttpResponseException(HttpStatusCode.NotFound); + } + + var result = _umbracoMapper.MapEnumerable(users); + return result; + } + /// /// Returns a paged users collection /// diff --git a/src/Umbraco.Web.BackOffice/Mapping/MemberMapDefinition.cs b/src/Umbraco.Web.BackOffice/Mapping/MemberMapDefinition.cs index cf001b17db..aba2d4a12c 100644 --- a/src/Umbraco.Web.BackOffice/Mapping/MemberMapDefinition.cs +++ b/src/Umbraco.Web.BackOffice/Mapping/MemberMapDefinition.cs @@ -39,6 +39,7 @@ namespace Umbraco.Web.Models.Mapping private void Map(IMember source, MemberDisplay target, MapperContext context) { target.ContentApps = _commonMapper.GetContentApps(source); + target.ContentType = _commonMapper.GetContentType(source, context); target.ContentTypeId = source.ContentType.Id; target.ContentTypeAlias = source.ContentType.Alias; target.ContentTypeName = source.ContentType.Name; diff --git a/src/Umbraco.Web.BackOffice/Umbraco.Web.BackOffice.csproj b/src/Umbraco.Web.BackOffice/Umbraco.Web.BackOffice.csproj index 0e98bc8cd7..2547117531 100644 --- a/src/Umbraco.Web.BackOffice/Umbraco.Web.BackOffice.csproj +++ b/src/Umbraco.Web.BackOffice/Umbraco.Web.BackOffice.csproj @@ -15,6 +15,7 @@ + diff --git a/src/Umbraco.Web.UI.Client/gulp/tasks/dependencies.js b/src/Umbraco.Web.UI.Client/gulp/tasks/dependencies.js index dbc0b7fc57..fb03cbd1b1 100644 --- a/src/Umbraco.Web.UI.Client/gulp/tasks/dependencies.js +++ b/src/Umbraco.Web.UI.Client/gulp/tasks/dependencies.js @@ -29,12 +29,15 @@ function dependencies() { "./node_modules/ace-builds/src-min-noconflict/snippets/text.js", "./node_modules/ace-builds/src-min-noconflict/snippets/javascript.js", "./node_modules/ace-builds/src-min-noconflict/snippets/css.js", + "./node_modules/ace-builds/src-min-noconflict/snippets/json.js", "./node_modules/ace-builds/src-min-noconflict/theme-chrome.js", "./node_modules/ace-builds/src-min-noconflict/mode-razor.js", "./node_modules/ace-builds/src-min-noconflict/mode-javascript.js", "./node_modules/ace-builds/src-min-noconflict/mode-css.js", "./node_modules/ace-builds/src-min-noconflict/worker-javascript.js", - "./node_modules/ace-builds/src-min-noconflict/worker-css.js" + "./node_modules/ace-builds/src-min-noconflict/worker-css.js", + "./node_modules/ace-builds/src-min-noconflict/mode-json.js", + "./node_modules/ace-builds/src-min-noconflict/worker-json.js" ], "base": "./node_modules/ace-builds" }, @@ -45,7 +48,8 @@ function dependencies() { }, { "name": "angular-aria", - "src": ["./node_modules/angular-aria/angular-aria.min.js"], + "src": ["./node_modules/angular-aria/angular-aria.min.js", + "./node_modules/angular-aria/angular-aria.min.js.map"], "base": "./node_modules/angular-aria" }, { @@ -238,6 +242,14 @@ function dependencies() { "name": "underscore", "src": ["node_modules/underscore/underscore-min.js"], "base": "./node_modules/underscore" + }, + { + "name": "wicg-inert", + "src": [ + "./node_modules/wicg-inert/dist/inert.min.js", + "./node_modules/wicg-inert/dist/inert.min.js.map" + ], + "base": "./node_modules/wicg-inert" } ]; diff --git a/src/Umbraco.Web.UI.Client/lib/bootstrap/less/pager.less b/src/Umbraco.Web.UI.Client/lib/bootstrap/less/pager.less index 1476188297..718ade757e 100644 --- a/src/Umbraco.Web.UI.Client/lib/bootstrap/less/pager.less +++ b/src/Umbraco.Web.UI.Client/lib/bootstrap/less/pager.less @@ -13,6 +13,7 @@ display: inline; } .pager li > a, +.pager li > button, .pager li > span { display: inline-block; padding: 5px 14px; @@ -21,23 +22,30 @@ .border-radius(15px); } .pager li > a:hover, -.pager li > a:focus { - text-decoration: none; - background-color: #f5f5f5; +.pager li > a:focus, +.pager li > button:hover, +.pager li > button:focus { + text-decoration: none; + background-color: #f5f5f5; } .pager .next > a, +.pager .next > button, .pager .next > span { float: right; } .pager .previous > a, +.pager .previous > button, .pager .previous > span { - float: left; + float: left; } .pager .disabled > a, .pager .disabled > a:hover, .pager .disabled > a:focus, +.pager .disabled > button, +.pager .disabled > button:hover, +.pager .disabled > button:focus .pager .disabled > span { - color: @grayLight; - background-color: #fff; - cursor: default; -} \ No newline at end of file + color: @grayLight; + background-color: #fff; + cursor: default; +} diff --git a/src/Umbraco.Web.UI.Client/lib/bootstrap/less/pagination.less b/src/Umbraco.Web.UI.Client/lib/bootstrap/less/pagination.less index 6f6e6ac7de..ae10700eb3 100644 --- a/src/Umbraco.Web.UI.Client/lib/bootstrap/less/pagination.less +++ b/src/Umbraco.Web.UI.Client/lib/bootstrap/less/pagination.less @@ -21,6 +21,7 @@ display: inline; // Remove list-style and block-level defaults } .pagination ul > li > a, +.pagination ul > li > button, .pagination ul > li > span { float: left; // Collapse white-space padding: 4px 12px; @@ -32,29 +33,38 @@ } .pagination ul > li > a:hover, .pagination ul > li > a:focus, +.pagination ul > li > button:hover, +.pagination ul > li > button:focus, .pagination ul > .active > a, +.pagination ul > .active > button, .pagination ul > .active > span { - background-color: @paginationActiveBackground; + background-color: @paginationActiveBackground; } .pagination ul > .active > a, +.pagination ul > .active > button, .pagination ul > .active > span { - color: @grayLight; - cursor: default; + color: @grayLight; + cursor: default; } .pagination ul > .disabled > span, .pagination ul > .disabled > a, .pagination ul > .disabled > a:hover, -.pagination ul > .disabled > a:focus { - color: @grayLight; - background-color: transparent; - cursor: default; +.pagination ul > .disabled > a:focus, +.pagination ul > .disabled > button, +.pagination ul > .disabled > button:hover, +.pagination ul > .disabled > button:focus { + color: @grayLight; + background-color: transparent; + cursor: default; } .pagination ul > li:first-child > a, +.pagination ul > li:first-child > button, .pagination ul > li:first-child > span { border-left-width: 1px; .border-left-radius(@baseBorderRadius); } .pagination ul > li:last-child > a, +.pagination ul > li:last-child > button, .pagination ul > li:last-child > span { .border-right-radius(@baseBorderRadius); } @@ -77,15 +87,18 @@ // Large .pagination-large { ul > li > a, + ul > li > button, ul > li > span { padding: @paddingLarge; font-size: @fontSizeLarge; } ul > li:first-child > a, + ul > li:first-child > button, ul > li:first-child > span { .border-left-radius(@borderRadiusLarge); } ul > li:last-child > a, + ul > li:last-child > button, ul > li:last-child > span { .border-right-radius(@borderRadiusLarge); } @@ -95,10 +108,12 @@ .pagination-mini, .pagination-small { ul > li:first-child > a, + ul > li:first-child > button, ul > li:first-child > span { .border-left-radius(@borderRadiusSmall); } ul > li:last-child > a, + ul > li:last-child > button, ul > li:last-child > span { .border-right-radius(@borderRadiusSmall); } @@ -107,6 +122,7 @@ // Small .pagination-small { ul > li > a, + ul > li > button, ul > li > span { padding: @paddingSmall; font-size: @fontSizeSmall; @@ -115,6 +131,7 @@ // Mini .pagination-mini { ul > li > a, + ul > li > button, ul > li > span { padding: @paddingMini; font-size: @fontSizeMini; diff --git a/src/Umbraco.Web.UI.Client/package.json b/src/Umbraco.Web.UI.Client/package.json index 454d081fe7..100774f385 100644 --- a/src/Umbraco.Web.UI.Client/package.json +++ b/src/Umbraco.Web.UI.Client/package.json @@ -44,7 +44,8 @@ "spectrum-colorpicker": "1.8.0", "tinymce": "4.9.11", "typeahead.js": "0.11.1", - "underscore": "1.9.1" + "underscore": "1.9.1", + "wicg-inert": "^3.0.2" }, "devDependencies": { "@babel/core": "7.6.4", diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-activity.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-activity.svg new file mode 100644 index 0000000000..84c1202f04 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-activity.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-add.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-add.svg new file mode 100644 index 0000000000..9abe4f9085 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-add.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-adressbook.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-adressbook.svg new file mode 100644 index 0000000000..1c6676a711 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-adressbook.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-alarm-clock.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-alarm-clock.svg new file mode 100644 index 0000000000..4aa9ce1485 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-alarm-clock.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-alert-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-alert-alt.svg new file mode 100644 index 0000000000..dbb78a2188 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-alert-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-alert.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-alert.svg new file mode 100644 index 0000000000..3a75464feb --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-alert.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-alt.svg new file mode 100644 index 0000000000..1d4c0eb3e6 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-anchor.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-anchor.svg new file mode 100644 index 0000000000..033467b283 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-anchor.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-app.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-app.svg new file mode 100644 index 0000000000..02b19fe989 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-app.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-application-error.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-application-error.svg new file mode 100644 index 0000000000..cd57ff336f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-application-error.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-application-window-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-application-window-alt.svg new file mode 100644 index 0000000000..e87dae6ec8 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-application-window-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-application-window.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-application-window.svg new file mode 100644 index 0000000000..f99af0f195 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-application-window.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-arrivals.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-arrivals.svg new file mode 100644 index 0000000000..bfbe503d6b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-arrivals.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-arrow-down.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-arrow-down.svg new file mode 100644 index 0000000000..fcdf4548ec --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-arrow-down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-arrow-left.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-arrow-left.svg new file mode 100644 index 0000000000..2cf42ff7d6 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-arrow-left.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-arrow-right.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-arrow-right.svg new file mode 100644 index 0000000000..d1349b3b23 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-arrow-right.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-arrow-up.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-arrow-up.svg new file mode 100644 index 0000000000..f7ca5f8249 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-arrow-up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-art-easel.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-art-easel.svg new file mode 100644 index 0000000000..c4df06598b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-art-easel.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-article.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-article.svg new file mode 100644 index 0000000000..28b2e35c71 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-article.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-attachment.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-attachment.svg new file mode 100644 index 0000000000..a3c4f466c3 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-attachment.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-auction-hammer.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-auction-hammer.svg new file mode 100644 index 0000000000..50f8b8ef26 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-auction-hammer.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-autofill.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-autofill.svg new file mode 100644 index 0000000000..15cbe9fc35 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-autofill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-award.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-award.svg new file mode 100644 index 0000000000..18a82455f8 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-award.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-axis-rotation-2.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-axis-rotation-2.svg new file mode 100644 index 0000000000..d8ef136b72 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-axis-rotation-2.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-axis-rotation-3.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-axis-rotation-3.svg new file mode 100644 index 0000000000..77a56e9984 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-axis-rotation-3.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-axis-rotation.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-axis-rotation.svg new file mode 100644 index 0000000000..5f56a648d1 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-axis-rotation.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-baby-stroller.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-baby-stroller.svg new file mode 100644 index 0000000000..d8edc730c1 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-baby-stroller.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-backspace.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-backspace.svg new file mode 100644 index 0000000000..6c84aa5cbc --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-backspace.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-badge-add.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-badge-add.svg new file mode 100644 index 0000000000..0c6be8a34b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-badge-add.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-badge-count.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-badge-count.svg new file mode 100644 index 0000000000..e309c884f9 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-badge-count.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-badge-remove.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-badge-remove.svg new file mode 100644 index 0000000000..a6317092b8 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-badge-remove.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-badge-restricted.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-badge-restricted.svg new file mode 100644 index 0000000000..c7ad647e22 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-badge-restricted.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-ball.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-ball.svg new file mode 100644 index 0000000000..5416815534 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-ball.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-band-aid.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-band-aid.svg new file mode 100644 index 0000000000..8232ea9b23 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-band-aid.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bar-chart.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bar-chart.svg new file mode 100644 index 0000000000..c2fc1a2e2f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bar-chart.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-barcode.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-barcode.svg new file mode 100644 index 0000000000..7b7e4e151e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-barcode.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bars.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bars.svg new file mode 100644 index 0000000000..2199f4fb11 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bars.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-battery-full.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-battery-full.svg new file mode 100644 index 0000000000..5aff9d10df --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-battery-full.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-battery-low.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-battery-low.svg new file mode 100644 index 0000000000..72909d1d84 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-battery-low.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-beer-glass.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-beer-glass.svg new file mode 100644 index 0000000000..dc9e44cff7 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-beer-glass.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bell-off.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bell-off.svg new file mode 100644 index 0000000000..d7c9422857 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bell-off.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bell.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bell.svg new file mode 100644 index 0000000000..6843f8dbc7 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bell.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bill-dollar.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bill-dollar.svg new file mode 100644 index 0000000000..7ed749b1c8 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bill-dollar.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bill-euro.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bill-euro.svg new file mode 100644 index 0000000000..c526f106a0 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bill-euro.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bill-pound.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bill-pound.svg new file mode 100644 index 0000000000..339006dc08 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bill-pound.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bill-yen.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bill-yen.svg new file mode 100644 index 0000000000..76b9a1d318 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bill-yen.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bill.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bill.svg new file mode 100644 index 0000000000..ad75b69591 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-billboard.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-billboard.svg new file mode 100644 index 0000000000..468e0dc8bd --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-billboard.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bills-dollar.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bills-dollar.svg new file mode 100644 index 0000000000..dcd3a8f227 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bills-dollar.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bills-euro.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bills-euro.svg new file mode 100644 index 0000000000..3f2fbc38ef --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bills-euro.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bills-pound.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bills-pound.svg new file mode 100644 index 0000000000..32a30de1c6 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bills-pound.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bills-yen.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bills-yen.svg new file mode 100644 index 0000000000..ea352b33d5 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bills-yen.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bills.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bills.svg new file mode 100644 index 0000000000..a6d9b7a76e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bills.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-binarycode.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-binarycode.svg new file mode 100644 index 0000000000..5a7e9ee9d2 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-binarycode.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-binoculars.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-binoculars.svg new file mode 100644 index 0000000000..407a88c58d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-binoculars.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bird.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bird.svg new file mode 100644 index 0000000000..182a02be79 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bird.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-birthday-cake.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-birthday-cake.svg new file mode 100644 index 0000000000..205a06715a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-birthday-cake.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-block.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-block.svg new file mode 100644 index 0000000000..ed19756dd9 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-block.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-blueprint.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-blueprint.svg new file mode 100644 index 0000000000..4382644745 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-blueprint.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bluetooth.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bluetooth.svg new file mode 100644 index 0000000000..2c73fb77a7 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bluetooth.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-boat-shipping.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-boat-shipping.svg new file mode 100644 index 0000000000..15a8d6f9ff --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-boat-shipping.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bomb.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bomb.svg new file mode 100644 index 0000000000..b39d18938c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bomb.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bones.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bones.svg new file mode 100644 index 0000000000..f956d77bf3 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bones.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-book-alt-2.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-book-alt-2.svg new file mode 100644 index 0000000000..2003b3d233 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-book-alt-2.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-book-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-book-alt.svg new file mode 100644 index 0000000000..c959cdea3a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-book-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-book.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-book.svg new file mode 100644 index 0000000000..2516a55f83 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-book.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bookmark.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bookmark.svg new file mode 100644 index 0000000000..a3268596ac --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bookmark.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-books.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-books.svg new file mode 100644 index 0000000000..ddb9162770 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-books.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-box-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-box-alt.svg new file mode 100644 index 0000000000..0189daab6d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-box-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-box-open.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-box-open.svg new file mode 100644 index 0000000000..b2ec5d8bd3 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-box-open.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-box.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-box.svg new file mode 100644 index 0000000000..84fa9ca794 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-box.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-brackets.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-brackets.svg new file mode 100644 index 0000000000..142eb9f746 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-brackets.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-brick.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-brick.svg new file mode 100644 index 0000000000..e06862f8aa --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-brick.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-briefcase.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-briefcase.svg new file mode 100644 index 0000000000..e6e0705ecf --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-briefcase.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-browser-window.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-browser-window.svg new file mode 100644 index 0000000000..8279fb9198 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-browser-window.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-brush-alt-2.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-brush-alt-2.svg new file mode 100644 index 0000000000..3599902e1f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-brush-alt-2.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-brush-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-brush-alt.svg new file mode 100644 index 0000000000..65849ec18e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-brush-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-brush.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-brush.svg new file mode 100644 index 0000000000..a5b889c60d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-brush.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bug.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bug.svg new file mode 100644 index 0000000000..9b5b667387 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bug.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bulleted-list.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bulleted-list.svg new file mode 100644 index 0000000000..72bdf63388 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bulleted-list.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-burn.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-burn.svg new file mode 100644 index 0000000000..4f6ebe6865 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-burn.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bus.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bus.svg new file mode 100644 index 0000000000..95e728138e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-bus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-calculator.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-calculator.svg new file mode 100644 index 0000000000..3dcce7ec35 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-calculator.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-calendar-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-calendar-alt.svg new file mode 100644 index 0000000000..fb485f5a83 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-calendar-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-calendar.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-calendar.svg new file mode 100644 index 0000000000..b405db5525 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-calendar.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-camcorder.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-camcorder.svg new file mode 100644 index 0000000000..de0b071abb --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-camcorder.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-camera-roll.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-camera-roll.svg new file mode 100644 index 0000000000..172e0d92b0 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-camera-roll.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-candy.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-candy.svg new file mode 100644 index 0000000000..1da869963f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-candy.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-caps-lock.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-caps-lock.svg new file mode 100644 index 0000000000..1a466182c9 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-caps-lock.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-car.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-car.svg new file mode 100644 index 0000000000..9c72758d41 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-car.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-cash-register.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-cash-register.svg new file mode 100644 index 0000000000..f4f1779b86 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-cash-register.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-categories.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-categories.svg new file mode 100644 index 0000000000..2bd633a8f1 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-categories.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-certificate.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-certificate.svg new file mode 100644 index 0000000000..e3e16b5054 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-certificate.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-chart-curve.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-chart-curve.svg new file mode 100644 index 0000000000..219d05a1f8 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-chart-curve.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-chart.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-chart.svg new file mode 100644 index 0000000000..72c6534c38 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-chart.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-chat-active.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-chat-active.svg new file mode 100644 index 0000000000..b899dfc3fe --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-chat-active.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-chat.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-chat.svg new file mode 100644 index 0000000000..21abb255ef --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-chat.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-check.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-check.svg new file mode 100644 index 0000000000..5bd7161118 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-check.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-checkbox-dotted-active.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-checkbox-dotted-active.svg new file mode 100644 index 0000000000..f717f8063b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-checkbox-dotted-active.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-checkbox-dotted.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-checkbox-dotted.svg new file mode 100644 index 0000000000..cf650c0085 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-checkbox-dotted.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-checkbox-empty.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-checkbox-empty.svg new file mode 100644 index 0000000000..9a3edf8a28 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-checkbox-empty.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-checkbox.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-checkbox.svg new file mode 100644 index 0000000000..748b269cd2 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-checkbox.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-chess.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-chess.svg new file mode 100644 index 0000000000..8cb5685672 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-chess.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-chip-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-chip-alt.svg new file mode 100644 index 0000000000..5d459f13b1 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-chip-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-chip.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-chip.svg new file mode 100644 index 0000000000..0d622b2506 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-chip.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-cinema.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-cinema.svg new file mode 100644 index 0000000000..f3bc729bf1 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-cinema.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-circle-dotted-active.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-circle-dotted-active.svg new file mode 100644 index 0000000000..f9c60410cb --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-circle-dotted-active.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-circle-dotted.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-circle-dotted.svg new file mode 100644 index 0000000000..9cd9fd9252 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-circle-dotted.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-circuits.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-circuits.svg new file mode 100644 index 0000000000..4feb78fa69 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-circuits.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-circus.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-circus.svg new file mode 100644 index 0000000000..ff712b18ed --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-circus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-client.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-client.svg new file mode 100644 index 0000000000..23e23117e9 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-client.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-clothes-hanger.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-clothes-hanger.svg new file mode 100644 index 0000000000..f17c449cb0 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-clothes-hanger.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-cloud-drive.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-cloud-drive.svg new file mode 100644 index 0000000000..df5fcf03d7 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-cloud-drive.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-cloud-upload.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-cloud-upload.svg new file mode 100644 index 0000000000..41e015fa89 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-cloud-upload.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-cloud.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-cloud.svg new file mode 100644 index 0000000000..10a95d9562 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-cloud.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-cloudy.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-cloudy.svg new file mode 100644 index 0000000000..75aad3d4d2 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-cloudy.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-clubs.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-clubs.svg new file mode 100644 index 0000000000..68617041d5 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-clubs.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-cocktail.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-cocktail.svg new file mode 100644 index 0000000000..cc13e78a6f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-cocktail.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-code.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-code.svg new file mode 100644 index 0000000000..2615644cea --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-code.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coffee.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coffee.svg new file mode 100644 index 0000000000..d9e23e1259 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coffee.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coin-dollar.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coin-dollar.svg new file mode 100644 index 0000000000..6f3e0659da --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coin-dollar.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coin-euro.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coin-euro.svg new file mode 100644 index 0000000000..20527e3526 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coin-euro.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coin-pound.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coin-pound.svg new file mode 100644 index 0000000000..9ba0de073b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coin-pound.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coin-yen.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coin-yen.svg new file mode 100644 index 0000000000..2d7f31caf1 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coin-yen.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coin.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coin.svg new file mode 100644 index 0000000000..ec3b147525 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coin.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-alt.svg new file mode 100644 index 0000000000..a2349aaa12 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-dollar-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-dollar-alt.svg new file mode 100644 index 0000000000..8f283ea006 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-dollar-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-dollar.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-dollar.svg new file mode 100644 index 0000000000..0b2b7a2ea6 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-dollar.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-euro-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-euro-alt.svg new file mode 100644 index 0000000000..c8bbff6628 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-euro-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-euro.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-euro.svg new file mode 100644 index 0000000000..e1b77f5941 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-euro.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-pound-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-pound-alt.svg new file mode 100644 index 0000000000..e91acce12c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-pound-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-pound.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-pound.svg new file mode 100644 index 0000000000..6d1443a6c9 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-pound.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-yen-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-yen-alt.svg new file mode 100644 index 0000000000..d477b86158 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-yen-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-yen.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-yen.svg new file mode 100644 index 0000000000..63aa1da6b2 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins-yen.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins.svg new file mode 100644 index 0000000000..6af11e0945 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coins.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-color-bucket.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-color-bucket.svg new file mode 100644 index 0000000000..08fcb021d9 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-color-bucket.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-colorpicker.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-colorpicker.svg new file mode 100644 index 0000000000..69d0362805 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-colorpicker.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-columns.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-columns.svg new file mode 100644 index 0000000000..913a681162 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-columns.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-comb.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-comb.svg new file mode 100644 index 0000000000..d15c099fbe --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-comb.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-combination-lock-open.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-combination-lock-open.svg new file mode 100644 index 0000000000..3cdba5cf20 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-combination-lock-open.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-combination-lock.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-combination-lock.svg new file mode 100644 index 0000000000..10332f449f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-combination-lock.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-command.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-command.svg new file mode 100644 index 0000000000..7a4b9094f9 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-command.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-company.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-company.svg new file mode 100644 index 0000000000..b22bdb63ad --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-company.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-compress.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-compress.svg new file mode 100644 index 0000000000..48664d5a36 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-compress.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-connection.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-connection.svg new file mode 100644 index 0000000000..0619278e2a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-connection.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-console.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-console.svg new file mode 100644 index 0000000000..8599aeb13a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-console.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-contrast.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-contrast.svg new file mode 100644 index 0000000000..8dbd2d9e74 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-contrast.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-conversation-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-conversation-alt.svg new file mode 100644 index 0000000000..111b651f89 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-conversation-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-conversation.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-conversation.svg new file mode 100644 index 0000000000..d16115fdb0 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-conversation.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coverflow.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coverflow.svg new file mode 100644 index 0000000000..72a230d15d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-coverflow.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-credit-card-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-credit-card-alt.svg new file mode 100644 index 0000000000..c113197cf5 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-credit-card-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-credit-card.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-credit-card.svg new file mode 100644 index 0000000000..af896af5f9 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-credit-card.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-crop.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-crop.svg new file mode 100644 index 0000000000..570c261e8a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-crop.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-crosshair.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-crosshair.svg new file mode 100644 index 0000000000..802be32987 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-crosshair.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-crown-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-crown-alt.svg new file mode 100644 index 0000000000..20bbacb2eb --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-crown-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-crown.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-crown.svg new file mode 100644 index 0000000000..8ad5f1464a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-crown.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-cupcake.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-cupcake.svg new file mode 100644 index 0000000000..de3a7c7c81 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-cupcake.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-curve.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-curve.svg new file mode 100644 index 0000000000..ac749474d3 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-curve.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-cut.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-cut.svg new file mode 100644 index 0000000000..63d892780c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-cut.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-dashboard.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-dashboard.svg new file mode 100644 index 0000000000..13cd3bfa96 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-dashboard.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-defrag.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-defrag.svg new file mode 100644 index 0000000000..e26de351e9 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-defrag.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-delete-key.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-delete-key.svg new file mode 100644 index 0000000000..c738e7c8cf --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-delete-key.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-delete.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-delete.svg new file mode 100644 index 0000000000..1d931cc09b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-delete.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-departure.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-departure.svg new file mode 100644 index 0000000000..243f789b80 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-departure.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-desk.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-desk.svg new file mode 100644 index 0000000000..270e0f1dff --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-desk.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-desktop.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-desktop.svg new file mode 100644 index 0000000000..de5366b44b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-desktop.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-diagnostics.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-diagnostics.svg new file mode 100644 index 0000000000..66e2b4c653 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-diagnostics.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-diagonal-arrow-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-diagonal-arrow-alt.svg new file mode 100644 index 0000000000..fb4970d319 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-diagonal-arrow-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-diagonal-arrow.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-diagonal-arrow.svg new file mode 100644 index 0000000000..c10853ffcc --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-diagonal-arrow.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-diamond.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-diamond.svg new file mode 100644 index 0000000000..e831ae1172 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-diamond.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-diamonds.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-diamonds.svg new file mode 100644 index 0000000000..bf1cd0b8a4 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-diamonds.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-dice.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-dice.svg new file mode 100644 index 0000000000..bbb86cf68d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-dice.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-diploma-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-diploma-alt.svg new file mode 100644 index 0000000000..b4a5fcfeb9 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-diploma-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-diploma.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-diploma.svg new file mode 100644 index 0000000000..31b542d112 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-diploma.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-directions-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-directions-alt.svg new file mode 100644 index 0000000000..4a07354199 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-directions-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-directions.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-directions.svg new file mode 100644 index 0000000000..a56100bb2a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-directions.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-disc.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-disc.svg new file mode 100644 index 0000000000..8f694bc43f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-disc.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-disk-image.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-disk-image.svg new file mode 100644 index 0000000000..80a69f30d0 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-disk-image.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-display.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-display.svg new file mode 100644 index 0000000000..22cf1ef0eb --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-display.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-dna.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-dna.svg new file mode 100644 index 0000000000..a4cc100411 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-dna.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-dock-connector.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-dock-connector.svg new file mode 100644 index 0000000000..82480deaa1 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-dock-connector.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-document-dashed-line.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-document-dashed-line.svg new file mode 100644 index 0000000000..6117d4c7f4 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-document-dashed-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-document.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-document.svg new file mode 100644 index 0000000000..d2da15ad9e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-document.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-documents.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-documents.svg new file mode 100644 index 0000000000..4e56ca7b49 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-documents.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-dollar-bag.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-dollar-bag.svg new file mode 100644 index 0000000000..bc9dcb83cf --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-dollar-bag.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-donate.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-donate.svg new file mode 100644 index 0000000000..c2669c3a5c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-donate.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-door-open-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-door-open-alt.svg new file mode 100644 index 0000000000..57552cc455 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-door-open-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-door-open.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-door-open.svg new file mode 100644 index 0000000000..02339e4b8b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-door-open.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-download-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-download-alt.svg new file mode 100644 index 0000000000..3b788ff610 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-download-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-download.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-download.svg new file mode 100644 index 0000000000..a328fe65f7 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-download.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-drop.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-drop.svg new file mode 100644 index 0000000000..7523004cad --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-drop.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-eco.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-eco.svg new file mode 100644 index 0000000000..dad4c564c0 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-eco.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-economy.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-economy.svg new file mode 100644 index 0000000000..4e710b572a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-economy.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-edit.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-edit.svg new file mode 100644 index 0000000000..2faeea0891 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-edit.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-eject.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-eject.svg new file mode 100644 index 0000000000..5f74a4ccc1 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-eject.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-employee.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-employee.svg new file mode 100644 index 0000000000..b1c4877b2b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-employee.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-energy-saving-bulb.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-energy-saving-bulb.svg new file mode 100644 index 0000000000..a45bbf5f4f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-energy-saving-bulb.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-enter.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-enter.svg new file mode 100644 index 0000000000..4dc8c5af3d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-enter.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-equalizer.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-equalizer.svg new file mode 100644 index 0000000000..64b43e8537 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-equalizer.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-escape.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-escape.svg new file mode 100644 index 0000000000..edb544f9d3 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-escape.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-ethernet.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-ethernet.svg new file mode 100644 index 0000000000..2b16efe994 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-ethernet.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-euro-bag.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-euro-bag.svg new file mode 100644 index 0000000000..cb19eafeb9 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-euro-bag.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-exit-fullscreen.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-exit-fullscreen.svg new file mode 100644 index 0000000000..820c79522d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-exit-fullscreen.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-eye.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-eye.svg new file mode 100644 index 0000000000..8ea896a1f4 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-eye.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-facebook-like.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-facebook-like.svg new file mode 100644 index 0000000000..0f27d54a06 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-facebook-like.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-factory.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-factory.svg new file mode 100644 index 0000000000..855727aad5 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-factory.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-favorite.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-favorite.svg new file mode 100644 index 0000000000..5fee2201b0 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-favorite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-female-symbol.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-female-symbol.svg new file mode 100644 index 0000000000..9e003e51e5 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-female-symbol.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-file-cabinet.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-file-cabinet.svg new file mode 100644 index 0000000000..8d34dc684f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-file-cabinet.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-files.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-files.svg new file mode 100644 index 0000000000..228b54980d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-files.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-filter-arrows.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-filter-arrows.svg new file mode 100644 index 0000000000..2f17186e0c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-filter-arrows.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-filter.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-filter.svg new file mode 100644 index 0000000000..41a89b3eb0 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-filter.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-fingerprint.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-fingerprint.svg new file mode 100644 index 0000000000..b80eebd81c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-fingerprint.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-fire.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-fire.svg new file mode 100644 index 0000000000..b0811f59f0 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-fire.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-firewall.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-firewall.svg new file mode 100644 index 0000000000..b857e4349e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-firewall.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-firewire.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-firewire.svg new file mode 100644 index 0000000000..64807e9110 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-firewire.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-flag-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-flag-alt.svg new file mode 100644 index 0000000000..16d5b65bb6 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-flag-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-flag.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-flag.svg new file mode 100644 index 0000000000..3665770b99 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-flag.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-flash.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-flash.svg new file mode 100644 index 0000000000..f37a9e3483 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-flash.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-flashlight.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-flashlight.svg new file mode 100644 index 0000000000..4610c03a5b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-flashlight.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-flowerpot.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-flowerpot.svg new file mode 100644 index 0000000000..0524daab90 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-flowerpot.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-folder-open.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-folder-open.svg new file mode 100644 index 0000000000..44de932cfd --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-folder-open.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-folder-outline.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-folder-outline.svg new file mode 100644 index 0000000000..77059225c7 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-folder-outline.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-folder.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-folder.svg new file mode 100644 index 0000000000..ce20ed705e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-folder.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-folders.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-folders.svg new file mode 100644 index 0000000000..08875280e9 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-folders.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-font.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-font.svg new file mode 100644 index 0000000000..91689c5b49 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-font.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-food.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-food.svg new file mode 100644 index 0000000000..d39b58346a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-food.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-footprints.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-footprints.svg new file mode 100644 index 0000000000..118b8dc44f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-footprints.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-forking.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-forking.svg new file mode 100644 index 0000000000..441dead254 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-forking.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-frame-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-frame-alt.svg new file mode 100644 index 0000000000..24c8834c55 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-frame-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-frame.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-frame.svg new file mode 100644 index 0000000000..6d48f3165d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-frame.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-fullscreen-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-fullscreen-alt.svg new file mode 100644 index 0000000000..c2145c8171 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-fullscreen-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-fullscreen.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-fullscreen.svg new file mode 100644 index 0000000000..a63101cfe0 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-fullscreen.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-game.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-game.svg new file mode 100644 index 0000000000..78797b5601 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-game.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-geometry.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-geometry.svg new file mode 100644 index 0000000000..c7ed79e0a1 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-geometry.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-gift.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-gift.svg new file mode 100644 index 0000000000..4e2030a6f1 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-gift.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-glasses.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-glasses.svg new file mode 100644 index 0000000000..72b7c8b05b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-glasses.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-globe-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-globe-alt.svg new file mode 100644 index 0000000000..b02f41ad97 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-globe-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-globe-asia.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-globe-asia.svg new file mode 100644 index 0000000000..6a7334d5e8 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-globe-asia.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-globe-europe-africa.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-globe-europe-africa.svg new file mode 100644 index 0000000000..4c9b6fac01 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-globe-europe-africa.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-globe-inverted-america.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-globe-inverted-america.svg new file mode 100644 index 0000000000..a95c1a1975 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-globe-inverted-america.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-globe-inverted-asia.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-globe-inverted-asia.svg new file mode 100644 index 0000000000..c62b1e835a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-globe-inverted-asia.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-globe-inverted-europe-africa.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-globe-inverted-europe-africa.svg new file mode 100644 index 0000000000..af162e7949 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-globe-inverted-europe-africa.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-globe.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-globe.svg new file mode 100644 index 0000000000..28e4b649be --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-globe.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-gps.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-gps.svg new file mode 100644 index 0000000000..90572f37f6 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-gps.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-graduate.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-graduate.svg new file mode 100644 index 0000000000..81067c4cdb --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-graduate.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-grid.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-grid.svg new file mode 100644 index 0000000000..2e363c0c47 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-grid.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-hammer.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-hammer.svg new file mode 100644 index 0000000000..dfafc27d3c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-hammer.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-hand-active-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-hand-active-alt.svg new file mode 100644 index 0000000000..102ae217cf --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-hand-active-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-hand-active.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-hand-active.svg new file mode 100644 index 0000000000..49612abea3 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-hand-active.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-hand-pointer-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-hand-pointer-alt.svg new file mode 100644 index 0000000000..3e1185fe73 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-hand-pointer-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-hand-pointer.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-hand-pointer.svg new file mode 100644 index 0000000000..a002ace0f3 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-hand-pointer.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-handprint.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-handprint.svg new file mode 100644 index 0000000000..c9c254204b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-handprint.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-handshake.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-handshake.svg new file mode 100644 index 0000000000..b83e3bf315 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-handshake.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-handtool-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-handtool-alt.svg new file mode 100644 index 0000000000..1464083b74 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-handtool-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-handtool.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-handtool.svg new file mode 100644 index 0000000000..2202ced6d6 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-handtool.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-hard-drive-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-hard-drive-alt.svg new file mode 100644 index 0000000000..89ce2fea0e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-hard-drive-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-hard-drive.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-hard-drive.svg new file mode 100644 index 0000000000..98a2a993d4 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-hard-drive.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-hat.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-hat.svg new file mode 100644 index 0000000000..c8a1106446 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-hat.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-hd.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-hd.svg new file mode 100644 index 0000000000..77bf64d4fa --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-hd.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-headphones.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-headphones.svg new file mode 100644 index 0000000000..811c656c7e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-headphones.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-headset.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-headset.svg new file mode 100644 index 0000000000..98db2e30db --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-headset.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-hearts.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-hearts.svg new file mode 100644 index 0000000000..c2edaafe03 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-hearts.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-height.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-height.svg new file mode 100644 index 0000000000..bf6a75975b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-height.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-help-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-help-alt.svg new file mode 100644 index 0000000000..101c65318d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-help-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-help.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-help.svg new file mode 100644 index 0000000000..a1c5fdc7c1 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-help.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-home.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-home.svg new file mode 100644 index 0000000000..ebb93f4056 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-home.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-hourglass.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-hourglass.svg new file mode 100644 index 0000000000..c918b5407b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-hourglass.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-imac.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-imac.svg new file mode 100644 index 0000000000..76a01b97b8 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-imac.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-inactive-line.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-inactive-line.svg new file mode 100644 index 0000000000..60a16437c2 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-inactive-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-inbox-full.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-inbox-full.svg new file mode 100644 index 0000000000..c0beabfa29 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-inbox-full.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-inbox.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-inbox.svg new file mode 100644 index 0000000000..0fd7c71b22 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-inbox.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-indent.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-indent.svg new file mode 100644 index 0000000000..329b0f413e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-indent.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-infinity.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-infinity.svg new file mode 100644 index 0000000000..c42e3bd49e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-infinity.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-info.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-info.svg new file mode 100644 index 0000000000..f07ac8e7d1 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-info.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-invoice.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-invoice.svg new file mode 100644 index 0000000000..dd8457a63a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-invoice.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-ipad.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-ipad.svg new file mode 100644 index 0000000000..e79195e670 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-ipad.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-iphone.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-iphone.svg new file mode 100644 index 0000000000..b235644b03 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-iphone.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-item-arrangement.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-item-arrangement.svg new file mode 100644 index 0000000000..fd9939dba3 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-item-arrangement.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-junk.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-junk.svg new file mode 100644 index 0000000000..a8f48754d4 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-junk.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-key.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-key.svg new file mode 100644 index 0000000000..4a32d0004e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-key.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-keyboard.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-keyboard.svg new file mode 100644 index 0000000000..c08d8d9e93 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-keyboard.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-keychain.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-keychain.svg new file mode 100644 index 0000000000..e206a9150e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-keychain.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-keyhole.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-keyhole.svg new file mode 100644 index 0000000000..b97b156002 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-keyhole.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-lab.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-lab.svg new file mode 100644 index 0000000000..b750677812 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-lab.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-laptop.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-laptop.svg new file mode 100644 index 0000000000..dc120cca29 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-laptop.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-layers-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-layers-alt.svg new file mode 100644 index 0000000000..e02a1cadbf --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-layers-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-layers.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-layers.svg new file mode 100644 index 0000000000..c6965e3e95 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-layers.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-layout.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-layout.svg new file mode 100644 index 0000000000..355f314f0f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-layout.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-left-double-arrow.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-left-double-arrow.svg new file mode 100644 index 0000000000..0958c291da --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-left-double-arrow.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-legal.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-legal.svg new file mode 100644 index 0000000000..e4ea59375e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-legal.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-lense.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-lense.svg new file mode 100644 index 0000000000..229a7749bd --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-lense.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-library.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-library.svg new file mode 100644 index 0000000000..1551dec3c9 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-library.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-light-down.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-light-down.svg new file mode 100644 index 0000000000..c214226f59 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-light-down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-light-up.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-light-up.svg new file mode 100644 index 0000000000..dbac39d507 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-light-up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-lightbulb-active.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-lightbulb-active.svg new file mode 100644 index 0000000000..522460a54c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-lightbulb-active.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-lightbulb.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-lightbulb.svg new file mode 100644 index 0000000000..2d67f238ee --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-lightbulb.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-lightning.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-lightning.svg new file mode 100644 index 0000000000..4f8b5a1146 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-lightning.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-link.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-link.svg new file mode 100644 index 0000000000..2bb9b95c01 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-link.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-linux-tux.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-linux-tux.svg new file mode 100644 index 0000000000..cd90e979cd --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-linux-tux.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-list.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-list.svg new file mode 100644 index 0000000000..78a748f1a1 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-list.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-load.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-load.svg new file mode 100644 index 0000000000..6f4ac6197c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-load.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-loading.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-loading.svg new file mode 100644 index 0000000000..91372f4e34 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-loading.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-locate.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-locate.svg new file mode 100644 index 0000000000..b6d715d2f0 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-locate.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-location-near-me.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-location-near-me.svg new file mode 100644 index 0000000000..69028bf985 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-location-near-me.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-location-nearby.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-location-nearby.svg new file mode 100644 index 0000000000..884edb711b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-location-nearby.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-lock.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-lock.svg new file mode 100644 index 0000000000..8f94c7cb96 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-lock.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-log-out.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-log-out.svg new file mode 100644 index 0000000000..07c4ae9856 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-log-out.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-logout.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-logout.svg new file mode 100644 index 0000000000..e3eb856a9a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-logout.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-loupe.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-loupe.svg new file mode 100644 index 0000000000..ab5137dc24 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-loupe.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-magnet.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-magnet.svg new file mode 100644 index 0000000000..b7c9ed6ab1 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-magnet.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-mailbox.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-mailbox.svg new file mode 100644 index 0000000000..e55cdc452c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-mailbox.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-male-and-female.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-male-and-female.svg new file mode 100644 index 0000000000..5ddf3b95e1 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-male-and-female.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-male-symbol.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-male-symbol.svg new file mode 100644 index 0000000000..eb91f509f5 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-male-symbol.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-map-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-map-alt.svg new file mode 100644 index 0000000000..fcc39f5bb0 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-map-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-map-location.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-map-location.svg new file mode 100644 index 0000000000..ad9efb05ed --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-map-location.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-map-marker.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-map-marker.svg new file mode 100644 index 0000000000..a4f71dc084 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-map-marker.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-map.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-map.svg new file mode 100644 index 0000000000..2c9ae42407 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-map.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-medal.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-medal.svg new file mode 100644 index 0000000000..c97ccf0f32 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-medal.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-medical-emergency.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-medical-emergency.svg new file mode 100644 index 0000000000..0265c28988 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-medical-emergency.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-medicine.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-medicine.svg new file mode 100644 index 0000000000..1e2cb6aeef --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-medicine.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-meeting.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-meeting.svg new file mode 100644 index 0000000000..09af0d97c2 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-meeting.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-megaphone.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-megaphone.svg new file mode 100644 index 0000000000..25387c9357 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-megaphone.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-merge.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-merge.svg new file mode 100644 index 0000000000..57ac52511a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-merge.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-message-open.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-message-open.svg new file mode 100644 index 0000000000..98aaeeeb64 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-message-open.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-message-unopened.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-message-unopened.svg new file mode 100644 index 0000000000..e29ecbf60d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-message-unopened.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-message.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-message.svg new file mode 100644 index 0000000000..75785c1896 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-message.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-microscope.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-microscope.svg new file mode 100644 index 0000000000..9985552be3 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-microscope.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-mindmap.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-mindmap.svg new file mode 100644 index 0000000000..043927014b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-mindmap.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-mobile.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-mobile.svg new file mode 100644 index 0000000000..92532b8005 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-mobile.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-molecular-network.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-molecular-network.svg new file mode 100644 index 0000000000..20d87126aa --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-molecular-network.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-molecular.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-molecular.svg new file mode 100644 index 0000000000..904e0976c3 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-molecular.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-mountain.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-mountain.svg new file mode 100644 index 0000000000..a21324f819 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-mountain.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-mouse-cursor.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-mouse-cursor.svg new file mode 100644 index 0000000000..b64dd7f88b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-mouse-cursor.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-mouse.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-mouse.svg new file mode 100644 index 0000000000..f063df5259 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-mouse.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-movie-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-movie-alt.svg new file mode 100644 index 0000000000..1878dc9ec0 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-movie-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-movie.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-movie.svg new file mode 100644 index 0000000000..d5b3481a83 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-movie.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-multiple-credit-cards.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-multiple-credit-cards.svg new file mode 100644 index 0000000000..1330826784 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-multiple-credit-cards.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-multiple-windows.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-multiple-windows.svg new file mode 100644 index 0000000000..c8b3ac5669 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-multiple-windows.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-music.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-music.svg new file mode 100644 index 0000000000..87f4ba36a6 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-music.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-name-badge.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-name-badge.svg new file mode 100644 index 0000000000..22f66c9234 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-name-badge.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-bottom.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-bottom.svg new file mode 100644 index 0000000000..eeb3e79bdc --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-bottom.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-down.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-down.svg new file mode 100644 index 0000000000..007e8dd8ff --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-first.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-first.svg new file mode 100644 index 0000000000..85d44722ee --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-first.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-horizontal.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-horizontal.svg new file mode 100644 index 0000000000..4988e723eb --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-horizontal.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-last.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-last.svg new file mode 100644 index 0000000000..53f70d36fd --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-last.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-left.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-left.svg new file mode 100644 index 0000000000..56cdecce10 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-left.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-right.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-right.svg new file mode 100644 index 0000000000..251b6934d3 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-right.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-road.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-road.svg new file mode 100644 index 0000000000..f05567099f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-road.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-top.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-top.svg new file mode 100644 index 0000000000..c932714737 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-top.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-up.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-up.svg new file mode 100644 index 0000000000..612ec9193e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-vertical.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-vertical.svg new file mode 100644 index 0000000000..fbe3906472 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation-vertical.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation.svg new file mode 100644 index 0000000000..67d9c2a0c2 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigation.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigational-arrow.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigational-arrow.svg new file mode 100644 index 0000000000..bf60bde293 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-navigational-arrow.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-network-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-network-alt.svg new file mode 100644 index 0000000000..e6b2c25036 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-network-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-newspaper-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-newspaper-alt.svg new file mode 100644 index 0000000000..1bcf422c64 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-newspaper-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-newspaper.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-newspaper.svg new file mode 100644 index 0000000000..d585513f28 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-newspaper.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-next-media.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-next-media.svg new file mode 100644 index 0000000000..57d4c8e0e3 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-next-media.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-next.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-next.svg new file mode 100644 index 0000000000..b00b37dd17 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-next.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-nodes.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-nodes.svg new file mode 100644 index 0000000000..e912e52d15 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-nodes.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-notepad-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-notepad-alt.svg new file mode 100644 index 0000000000..bca4d0c462 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-notepad-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-notepad.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-notepad.svg new file mode 100644 index 0000000000..5fc428082e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-notepad.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-old-key.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-old-key.svg new file mode 100644 index 0000000000..a4003027a4 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-old-key.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-old-phone.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-old-phone.svg new file mode 100644 index 0000000000..8eb7804e74 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-old-phone.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-operator.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-operator.svg new file mode 100644 index 0000000000..ad78b8602f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-operator.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-ordered-list.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-ordered-list.svg new file mode 100644 index 0000000000..de140283b8 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-ordered-list.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-os-x.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-os-x.svg new file mode 100644 index 0000000000..170f3aad47 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-os-x.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-out.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-out.svg new file mode 100644 index 0000000000..73d2cfe147 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-out.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-outbox.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-outbox.svg new file mode 100644 index 0000000000..3b59c93933 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-outbox.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-outdent.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-outdent.svg new file mode 100644 index 0000000000..85ff01f440 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-outdent.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-page-add.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-page-add.svg new file mode 100644 index 0000000000..538defed20 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-page-add.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-page-down.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-page-down.svg new file mode 100644 index 0000000000..2fae28dfd9 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-page-down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-page-remove.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-page-remove.svg new file mode 100644 index 0000000000..c5009604d4 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-page-remove.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-page-restricted.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-page-restricted.svg new file mode 100644 index 0000000000..4a7c8696e2 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-page-restricted.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-page-up.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-page-up.svg new file mode 100644 index 0000000000..db6ad88927 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-page-up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-paint-roller.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-paint-roller.svg new file mode 100644 index 0000000000..59665d6232 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-paint-roller.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-palette.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-palette.svg new file mode 100644 index 0000000000..26c9f7f6b2 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-palette.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-panel-show.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-panel-show.svg new file mode 100644 index 0000000000..91c3e9f0ca --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-panel-show.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pannel-close.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pannel-close.svg new file mode 100644 index 0000000000..8006a60541 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pannel-close.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pants.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pants.svg new file mode 100644 index 0000000000..9604660ce0 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pants.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-paper-bag.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-paper-bag.svg new file mode 100644 index 0000000000..e7435caf75 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-paper-bag.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-paper-plane-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-paper-plane-alt.svg new file mode 100644 index 0000000000..2c4259e954 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-paper-plane-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-paper-plane.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-paper-plane.svg new file mode 100644 index 0000000000..fe60af779b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-paper-plane.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-parachute-drop.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-parachute-drop.svg new file mode 100644 index 0000000000..cdd4a501d7 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-parachute-drop.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-parental-control.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-parental-control.svg new file mode 100644 index 0000000000..3a19170b80 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-parental-control.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-partly-cloudy.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-partly-cloudy.svg new file mode 100644 index 0000000000..57af81127e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-partly-cloudy.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-paste-in.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-paste-in.svg new file mode 100644 index 0000000000..eae1a1bd12 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-paste-in.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-path.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-path.svg new file mode 100644 index 0000000000..a8f5df6e4c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-path.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pause.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pause.svg new file mode 100644 index 0000000000..7d9dce3838 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pause.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pc.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pc.svg new file mode 100644 index 0000000000..a8c8196797 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pc.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-people-alt-2.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-people-alt-2.svg new file mode 100644 index 0000000000..4aa84eae75 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-people-alt-2.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-people-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-people-alt.svg new file mode 100644 index 0000000000..7f129069c7 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-people-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-people-female.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-people-female.svg new file mode 100644 index 0000000000..0cf6088418 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-people-female.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-people.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-people.svg new file mode 100644 index 0000000000..ab861f8814 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-people.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-phone-ring.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-phone-ring.svg new file mode 100644 index 0000000000..1797603bbc --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-phone-ring.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-phone.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-phone.svg new file mode 100644 index 0000000000..085e41600e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-phone.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-photo-album.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-photo-album.svg new file mode 100644 index 0000000000..532615bf2a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-photo-album.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-picture.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-picture.svg new file mode 100644 index 0000000000..9250074063 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-picture.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pictures-alt-2.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pictures-alt-2.svg new file mode 100644 index 0000000000..4bc1120750 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pictures-alt-2.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pictures-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pictures-alt.svg new file mode 100644 index 0000000000..eee91913ed --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pictures-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pictures.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pictures.svg new file mode 100644 index 0000000000..8844e068b2 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pictures.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pie-chart.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pie-chart.svg new file mode 100644 index 0000000000..1db73f63d3 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pie-chart.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-piggy-bank.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-piggy-bank.svg new file mode 100644 index 0000000000..45c74819f8 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-piggy-bank.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pin-location.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pin-location.svg new file mode 100644 index 0000000000..5907d6e541 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pin-location.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-piracy.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-piracy.svg new file mode 100644 index 0000000000..577d04e517 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-piracy.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-plane.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-plane.svg new file mode 100644 index 0000000000..c09d4522e2 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-plane.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-planet.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-planet.svg new file mode 100644 index 0000000000..455ce2da3a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-planet.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-play.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-play.svg new file mode 100644 index 0000000000..3a041b7e2b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-play.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-playing-cards.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-playing-cards.svg new file mode 100644 index 0000000000..132d264d5b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-playing-cards.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-playlist.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-playlist.svg new file mode 100644 index 0000000000..0492601307 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-playlist.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-plugin.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-plugin.svg new file mode 100644 index 0000000000..c88e396dfa --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-plugin.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-podcast.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-podcast.svg new file mode 100644 index 0000000000..796c263f0a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-podcast.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-poker-chip.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-poker-chip.svg new file mode 100644 index 0000000000..6f3698bd66 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-poker-chip.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-poll.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-poll.svg new file mode 100644 index 0000000000..089fa647d1 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-poll.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-post-it.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-post-it.svg new file mode 100644 index 0000000000..61a2787df8 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-post-it.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pound-bag.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pound-bag.svg new file mode 100644 index 0000000000..dfb460d22a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pound-bag.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-power-outlet.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-power-outlet.svg new file mode 100644 index 0000000000..41e3e51e20 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-power-outlet.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-power.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-power.svg new file mode 100644 index 0000000000..9c4fb4b087 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-power.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-presentation.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-presentation.svg new file mode 100644 index 0000000000..59e720c81e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-presentation.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-previous-media.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-previous-media.svg new file mode 100644 index 0000000000..656c29d14c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-previous-media.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-previous.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-previous.svg new file mode 100644 index 0000000000..f858829633 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-previous.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-price-dollar.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-price-dollar.svg new file mode 100644 index 0000000000..72d42718a9 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-price-dollar.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-price-euro.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-price-euro.svg new file mode 100644 index 0000000000..0c437bc769 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-price-euro.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-price-pound.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-price-pound.svg new file mode 100644 index 0000000000..0858462da8 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-price-pound.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-price-yen.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-price-yen.svg new file mode 100644 index 0000000000..96c3917842 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-price-yen.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-print.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-print.svg new file mode 100644 index 0000000000..3bce86bedd --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-print.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-printer-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-printer-alt.svg new file mode 100644 index 0000000000..050ec1d81c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-printer-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-projector.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-projector.svg new file mode 100644 index 0000000000..afc95283c3 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-projector.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pulse.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pulse.svg new file mode 100644 index 0000000000..8a655631af --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pulse.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pushpin.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pushpin.svg new file mode 100644 index 0000000000..586bf4fdc0 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-pushpin.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-qr-code.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-qr-code.svg new file mode 100644 index 0000000000..bdbf3d64fb --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-qr-code.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-quote.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-quote.svg new file mode 100644 index 0000000000..16746643b6 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-quote.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-radio-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-radio-alt.svg new file mode 100644 index 0000000000..c7dcf65677 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-radio-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-radio-receiver.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-radio-receiver.svg new file mode 100644 index 0000000000..a3bea41462 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-radio-receiver.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-radio.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-radio.svg new file mode 100644 index 0000000000..2cf8718a2e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-radio.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-rain.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-rain.svg new file mode 100644 index 0000000000..0007d98d6c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-rain.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-rate.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-rate.svg new file mode 100644 index 0000000000..aac2ba0481 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-rate.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-re-post.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-re-post.svg new file mode 100644 index 0000000000..80b7a9673d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-re-post.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-readonly.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-readonly.svg new file mode 100644 index 0000000000..b0840b5171 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-readonly.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-receipt-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-receipt-alt.svg new file mode 100644 index 0000000000..d7b6f5e860 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-receipt-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-receipt-dollar.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-receipt-dollar.svg new file mode 100644 index 0000000000..6784c6e8df --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-receipt-dollar.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-receipt-euro.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-receipt-euro.svg new file mode 100644 index 0000000000..82e99b2eec --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-receipt-euro.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-receipt-pound.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-receipt-pound.svg new file mode 100644 index 0000000000..b28cf9e00d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-receipt-pound.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-receipt-yen.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-receipt-yen.svg new file mode 100644 index 0000000000..529fd87d4e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-receipt-yen.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-reception.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-reception.svg new file mode 100644 index 0000000000..01a61f4ae9 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-reception.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-record.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-record.svg new file mode 100644 index 0000000000..5a928928d3 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-record.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-redo.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-redo.svg new file mode 100644 index 0000000000..b1fcfc01d6 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-redo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-refresh.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-refresh.svg new file mode 100644 index 0000000000..b3c932583f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-refresh.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-remote.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-remote.svg new file mode 100644 index 0000000000..ff3d1de672 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-remote.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-remove.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-remove.svg new file mode 100644 index 0000000000..97bff0169f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-remove.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-repeat-one.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-repeat-one.svg new file mode 100644 index 0000000000..054185177f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-repeat-one.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-repeat.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-repeat.svg new file mode 100644 index 0000000000..68e7b30f8a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-repeat.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-reply-arrow.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-reply-arrow.svg new file mode 100644 index 0000000000..fd708c5173 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-reply-arrow.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-resize.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-resize.svg new file mode 100644 index 0000000000..e26e9fb196 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-resize.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-return-to-top.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-return-to-top.svg new file mode 100644 index 0000000000..15e5d82289 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-return-to-top.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-right-double-arrow.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-right-double-arrow.svg new file mode 100644 index 0000000000..a8f4a03cb7 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-right-double-arrow.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-road.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-road.svg new file mode 100644 index 0000000000..e9dedee5bd --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-road.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-roadsign.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-roadsign.svg new file mode 100644 index 0000000000..4115c305c4 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-roadsign.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-rocket.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-rocket.svg new file mode 100644 index 0000000000..5fab3cf1ba --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-rocket.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-rss.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-rss.svg new file mode 100644 index 0000000000..96a210c20c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-rss.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-ruler-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-ruler-alt.svg new file mode 100644 index 0000000000..695d110031 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-ruler-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-ruler.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-ruler.svg new file mode 100644 index 0000000000..15eff181d8 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-ruler.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-safe.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-safe.svg new file mode 100644 index 0000000000..9bdce49ca5 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-safe.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-safedial.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-safedial.svg new file mode 100644 index 0000000000..da9a6a6275 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-safedial.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sandbox-toys.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sandbox-toys.svg new file mode 100644 index 0000000000..727e62cc18 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sandbox-toys.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-satellite-dish.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-satellite-dish.svg new file mode 100644 index 0000000000..235d67c316 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-satellite-dish.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-save.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-save.svg new file mode 100644 index 0000000000..c4a56c7268 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-save.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-scan.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-scan.svg new file mode 100644 index 0000000000..de0a84c4b6 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-scan.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-school.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-school.svg new file mode 100644 index 0000000000..216a3ff764 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-school.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-screensharing.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-screensharing.svg new file mode 100644 index 0000000000..065d04c278 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-screensharing.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-script-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-script-alt.svg new file mode 100644 index 0000000000..4efc77d194 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-script-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-script.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-script.svg new file mode 100644 index 0000000000..224b12e0a4 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-script.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-scull.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-scull.svg new file mode 100644 index 0000000000..fc2d5cc4b2 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-scull.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-search.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-search.svg new file mode 100644 index 0000000000..1e0715b800 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-search.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-security-camera.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-security-camera.svg new file mode 100644 index 0000000000..09bb6613aa --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-security-camera.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sensor.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sensor.svg new file mode 100644 index 0000000000..a73de18bb1 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sensor.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-server-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-server-alt.svg new file mode 100644 index 0000000000..e1d6a449a5 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-server-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-server.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-server.svg new file mode 100644 index 0000000000..04636e254a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-server.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-settings-alt-2.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-settings-alt-2.svg new file mode 100644 index 0000000000..da84deb9e5 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-settings-alt-2.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-settings-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-settings-alt.svg new file mode 100644 index 0000000000..ab9eb44951 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-settings-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-settings.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-settings.svg new file mode 100644 index 0000000000..6311ad6122 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-settings.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-share-alt-2.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-share-alt-2.svg new file mode 100644 index 0000000000..6f220aaa6d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-share-alt-2.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-share-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-share-alt.svg new file mode 100644 index 0000000000..7cff7b3840 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-share-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-share.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-share.svg new file mode 100644 index 0000000000..2e4584a775 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-share.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sharing-iphone.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sharing-iphone.svg new file mode 100644 index 0000000000..04d34e0fe3 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sharing-iphone.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-shield.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-shield.svg new file mode 100644 index 0000000000..f34195c7d4 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-shield.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-shift.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-shift.svg new file mode 100644 index 0000000000..3d6f9aea9d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-shift.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-shipping-box.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-shipping-box.svg new file mode 100644 index 0000000000..66e12cea40 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-shipping-box.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-shipping.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-shipping.svg new file mode 100644 index 0000000000..102cb0be70 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-shipping.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-shoe.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-shoe.svg new file mode 100644 index 0000000000..f784c832a6 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-shoe.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-shopping-basket-alt-2.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-shopping-basket-alt-2.svg new file mode 100644 index 0000000000..06beb2dc40 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-shopping-basket-alt-2.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-shopping-basket-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-shopping-basket-alt.svg new file mode 100644 index 0000000000..5cdd20bf19 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-shopping-basket-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-shopping-basket.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-shopping-basket.svg new file mode 100644 index 0000000000..71cdd1de20 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-shopping-basket.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-shorts.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-shorts.svg new file mode 100644 index 0000000000..e3f8ab2625 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-shorts.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-shuffle.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-shuffle.svg new file mode 100644 index 0000000000..546f0a2965 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-shuffle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sience.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sience.svg new file mode 100644 index 0000000000..e692a2ec0c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sience.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-simcard.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-simcard.svg new file mode 100644 index 0000000000..a65fc9ffb5 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-simcard.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-single-note.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-single-note.svg new file mode 100644 index 0000000000..f98a14c285 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-single-note.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sitemap.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sitemap.svg new file mode 100644 index 0000000000..0cbd6659a4 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sitemap.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sleep.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sleep.svg new file mode 100644 index 0000000000..c85ac0dc8a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sleep.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-slideshow.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-slideshow.svg new file mode 100644 index 0000000000..484e86cd28 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-slideshow.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-smiley-inverted.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-smiley-inverted.svg new file mode 100644 index 0000000000..8c2bc19928 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-smiley-inverted.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-smiley.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-smiley.svg new file mode 100644 index 0000000000..5504a545cd --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-smiley.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-snow.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-snow.svg new file mode 100644 index 0000000000..2ba7134a91 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-snow.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sound-low.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sound-low.svg new file mode 100644 index 0000000000..1a5abc0193 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sound-low.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sound-medium.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sound-medium.svg new file mode 100644 index 0000000000..d6497c7c88 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sound-medium.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sound-off.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sound-off.svg new file mode 100644 index 0000000000..173ea47692 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sound-off.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sound-waves.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sound-waves.svg new file mode 100644 index 0000000000..cf21b5606b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sound-waves.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sound.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sound.svg new file mode 100644 index 0000000000..ff3ba17166 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sound.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-spades.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-spades.svg new file mode 100644 index 0000000000..f97a5457f8 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-spades.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-speaker.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-speaker.svg new file mode 100644 index 0000000000..dc922a00d3 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-speaker.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-speed-gauge.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-speed-gauge.svg new file mode 100644 index 0000000000..ce52283ddb --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-speed-gauge.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-split-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-split-alt.svg new file mode 100644 index 0000000000..a5ad049940 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-split-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-split.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-split.svg new file mode 100644 index 0000000000..1bdfd8a66b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-split.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sprout.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sprout.svg new file mode 100644 index 0000000000..1d139dd355 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sprout.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-squiggly-line.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-squiggly-line.svg new file mode 100644 index 0000000000..2c88881018 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-squiggly-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-ssd.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-ssd.svg new file mode 100644 index 0000000000..483398df2d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-ssd.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-stacked-disks.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-stacked-disks.svg new file mode 100644 index 0000000000..0c6fb6e8d1 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-stacked-disks.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-stamp.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-stamp.svg new file mode 100644 index 0000000000..2468ef2c74 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-stamp.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-stop-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-stop-alt.svg new file mode 100644 index 0000000000..ed61a5b6cc --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-stop-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-stop-hand.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-stop-hand.svg new file mode 100644 index 0000000000..3742256b80 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-stop-hand.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-stop.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-stop.svg new file mode 100644 index 0000000000..6b61d9904b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-stop.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-store.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-store.svg new file mode 100644 index 0000000000..3a9618fef2 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-store.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-stream.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-stream.svg new file mode 100644 index 0000000000..97ea6bed56 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-stream.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sunny.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sunny.svg new file mode 100644 index 0000000000..07391fec24 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sunny.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sweatshirt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sweatshirt.svg new file mode 100644 index 0000000000..3b33e88738 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sweatshirt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sync.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sync.svg new file mode 100644 index 0000000000..b3e8e396bc --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-sync.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-t-shirt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-t-shirt.svg new file mode 100644 index 0000000000..860762bf35 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-t-shirt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-tab-key.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-tab-key.svg new file mode 100644 index 0000000000..dcd4d918c8 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-tab-key.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-tab.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-tab.svg new file mode 100644 index 0000000000..a03fd4e379 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-tab.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-tactics.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-tactics.svg new file mode 100644 index 0000000000..ba1a383471 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-tactics.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-tag.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-tag.svg new file mode 100644 index 0000000000..ffeadcc433 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-tag.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-tags.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-tags.svg new file mode 100644 index 0000000000..681f38712d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-tags.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-takeaway-cup.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-takeaway-cup.svg new file mode 100644 index 0000000000..5360908485 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-takeaway-cup.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-target.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-target.svg new file mode 100644 index 0000000000..f61b84adc6 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-target.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-temperatrure-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-temperatrure-alt.svg new file mode 100644 index 0000000000..235b8a1eb9 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-temperatrure-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-temperature.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-temperature.svg new file mode 100644 index 0000000000..fa6c7859fa --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-temperature.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-terminal.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-terminal.svg new file mode 100644 index 0000000000..edb6b159e0 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-terminal.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-theater.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-theater.svg new file mode 100644 index 0000000000..b3a293ab48 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-theater.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-theif.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-theif.svg new file mode 100644 index 0000000000..f3b3ec69ad --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-theif.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-thought-bubble.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-thought-bubble.svg new file mode 100644 index 0000000000..59b9b71150 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-thought-bubble.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-thumb-down.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-thumb-down.svg new file mode 100644 index 0000000000..933450deab --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-thumb-down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-thumb-up.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-thumb-up.svg new file mode 100644 index 0000000000..1068c845bd --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-thumb-up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-thumbnail-list.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-thumbnail-list.svg new file mode 100644 index 0000000000..c6ddb31ec2 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-thumbnail-list.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-thumbnails-small.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-thumbnails-small.svg new file mode 100644 index 0000000000..ced7db6e71 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-thumbnails-small.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-thumbnails.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-thumbnails.svg new file mode 100644 index 0000000000..b8800a7000 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-thumbnails.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-ticket.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-ticket.svg new file mode 100644 index 0000000000..b69e61beec --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-ticket.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-time.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-time.svg new file mode 100644 index 0000000000..cd65d62e2e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-time.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-timer.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-timer.svg new file mode 100644 index 0000000000..f93538095b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-timer.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-tools.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-tools.svg new file mode 100644 index 0000000000..a8a1aec10f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-tools.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-top.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-top.svg new file mode 100644 index 0000000000..2bea18be1e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-top.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-traffic-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-traffic-alt.svg new file mode 100644 index 0000000000..9cb29dfaa0 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-traffic-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-trafic.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-trafic.svg new file mode 100644 index 0000000000..420832c521 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-trafic.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-train.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-train.svg new file mode 100644 index 0000000000..b1de2d26e1 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-train.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-trash-alt-2.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-trash-alt-2.svg new file mode 100644 index 0000000000..8bb390a394 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-trash-alt-2.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-trash-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-trash-alt.svg new file mode 100644 index 0000000000..5fba12abc3 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-trash-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-trash.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-trash.svg new file mode 100644 index 0000000000..abae234837 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-trash.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-tree.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-tree.svg new file mode 100644 index 0000000000..8da9048412 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-tree.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-trophy.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-trophy.svg new file mode 100644 index 0000000000..75229f89a8 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-trophy.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-truck.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-truck.svg new file mode 100644 index 0000000000..112c57941f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-truck.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-tv-old.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-tv-old.svg new file mode 100644 index 0000000000..6bde7d04ac --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-tv-old.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-tv.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-tv.svg new file mode 100644 index 0000000000..d3fc2d2cd9 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-tv.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-umb-content.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-umb-content.svg new file mode 100644 index 0000000000..3ee9892c48 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-umb-content.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-umb-contour.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-umb-contour.svg new file mode 100644 index 0000000000..2590acf88d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-umb-contour.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-umb-deploy.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-umb-deploy.svg new file mode 100644 index 0000000000..37c500ddd3 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-umb-deploy.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-umb-developer.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-umb-developer.svg new file mode 100644 index 0000000000..f99365c4b4 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-umb-developer.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-umb-media.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-umb-media.svg new file mode 100644 index 0000000000..9230e040bd --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-umb-media.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-umb-members.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-umb-members.svg new file mode 100644 index 0000000000..9193b6baa6 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-umb-members.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-umb-settings.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-umb-settings.svg new file mode 100644 index 0000000000..554ecdef32 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-umb-settings.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-umb-users.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-umb-users.svg new file mode 100644 index 0000000000..f8ef77731c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-umb-users.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-umbrella.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-umbrella.svg new file mode 100644 index 0000000000..620eac158a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-umbrella.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-undo.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-undo.svg new file mode 100644 index 0000000000..ca5152f6da --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-undo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-universal.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-universal.svg new file mode 100644 index 0000000000..49118f2935 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-universal.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-unlocked.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-unlocked.svg new file mode 100644 index 0000000000..2254dfc910 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-unlocked.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-untitled.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-untitled.svg new file mode 100644 index 0000000000..4e621d71c1 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-untitled.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-usb-connector.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-usb-connector.svg new file mode 100644 index 0000000000..0d97d4094d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-usb-connector.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-usb.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-usb.svg new file mode 100644 index 0000000000..7478d50f9e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-usb.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-user-female.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-user-female.svg new file mode 100644 index 0000000000..61b554428b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-user-female.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-user-females-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-user-females-alt.svg new file mode 100644 index 0000000000..e4813ece0b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-user-females-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-user-females.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-user-females.svg new file mode 100644 index 0000000000..b4f9776fa5 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-user-females.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-user-glasses.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-user-glasses.svg new file mode 100644 index 0000000000..3816df4ce6 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-user-glasses.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-user.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-user.svg new file mode 100644 index 0000000000..9f46a9853d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-user.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-users-alt.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-users-alt.svg new file mode 100644 index 0000000000..6d87232e4d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-users-alt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-users.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-users.svg new file mode 100644 index 0000000000..65f0703bcc --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-users.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-utilities.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-utilities.svg new file mode 100644 index 0000000000..5181d06074 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-utilities.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-vcard.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-vcard.svg new file mode 100644 index 0000000000..485275849a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-vcard.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-video.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-video.svg new file mode 100644 index 0000000000..48cb996cae --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-video.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-voice.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-voice.svg new file mode 100644 index 0000000000..786dc7572c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-voice.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-wall-plug.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-wall-plug.svg new file mode 100644 index 0000000000..d7d6d12e26 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-wall-plug.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-wallet.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-wallet.svg new file mode 100644 index 0000000000..36506ede4a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-wallet.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-wand.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-wand.svg new file mode 100644 index 0000000000..beeffe5d4e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-wand.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-war.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-war.svg new file mode 100644 index 0000000000..ae01d407d2 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-war.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-weight.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-weight.svg new file mode 100644 index 0000000000..cd5f49fbb8 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-weight.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-width.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-width.svg new file mode 100644 index 0000000000..77864d37b5 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-width.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-wifi.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-wifi.svg new file mode 100644 index 0000000000..0118ed13b1 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-wifi.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-window-popin.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-window-popin.svg new file mode 100644 index 0000000000..aec2173f09 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-window-popin.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-window-sizes.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-window-sizes.svg new file mode 100644 index 0000000000..26af884833 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-window-sizes.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-windows.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-windows.svg new file mode 100644 index 0000000000..3e00719e9e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-windows.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-wine-glass.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-wine-glass.svg new file mode 100644 index 0000000000..abb0115e23 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-wine-glass.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-wrench.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-wrench.svg new file mode 100644 index 0000000000..96040a486e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-wrench.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-wrong.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-wrong.svg new file mode 100644 index 0000000000..09f0a7376d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-wrong.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-yen-bag.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-yen-bag.svg new file mode 100644 index 0000000000..2680a40cca --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-yen-bag.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-zip.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-zip.svg new file mode 100644 index 0000000000..2691f1c586 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-zip.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-zom-out.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-zom-out.svg new file mode 100644 index 0000000000..8afc74de61 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-zom-out.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/assets/icons/icon-zoom-in.svg b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-zoom-in.svg new file mode 100644 index 0000000000..df7748938e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/assets/icons/icon-zoom-in.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umbappheader.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umbappheader.directive.js index 8efaf0c024..b52b0a5763 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umbappheader.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umbappheader.directive.js @@ -1,7 +1,7 @@ (function () { "use strict"; - function AppHeaderDirective(eventsService, appState, userService, focusService, backdropService) { + function AppHeaderDirective(eventsService, appState, userService, focusService, backdropService, overlayService) { function link(scope, el, attr, ctrl) { @@ -71,21 +71,17 @@ }; scope.avatarClick = function () { - if (!scope.userDialog) { - backdropService.open(); - scope.userDialog = { - view: "user", - show: true, - close: function (oldModel) { - scope.userDialog.show = false; - scope.userDialog = null; - backdropService.close(); - } - }; - } else { - scope.userDialog.show = false; - scope.userDialog = null; - } + + const dialog = { + view: "user", + position: "right", + name: "overlay-user", + close: function () { + overlayService.close(); + } + }; + + overlayService.open(dialog); }; } diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umbsearch.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umbsearch.directive.js index e03e63b68f..42daf1dd75 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umbsearch.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/application/umbsearch.directive.js @@ -160,7 +160,8 @@ searchService.searchAll(search).then(function (result) { //result is a dictionary of group Title and it's results var filtered = {}; - _.each(result, function (value, key) { + Object.keys(result).forEach(key => { + let value = result[key]; if (value.results.length > 0) { filtered[key] = value; } diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/buttons/umbbutton.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/buttons/umbbutton.directive.js index dc012945dd..5e007a7ff4 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/buttons/umbbutton.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/buttons/umbbutton.directive.js @@ -55,8 +55,8 @@ Use this directive to render an umbraco button. The directive can be used to gen @param {callback} action The button action which should be performed when the button is clicked. -@param {string=} href Url/Path to navigato to. -@param {string=} type Set the button type ("button" or "submit"). +@param {string=} href Url/Path to navigato to. (requires "type" to be set to "link") +@param {string=} type Set the button type ("button", "link", "submit"). @param {string=} buttonStyle Set the style of the button. The directive uses the default bootstrap styles ("primary", "info", "success", "warning", "danger", "inverse", "link", "block"). Pass in array to add multple styles [success,block]. @param {string=} state Set a progress state on the button ("init", "busy", "success", "error"). @param {string=} shortcut Set a keyboard shortcut for the button ("ctrl+c"). diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/buttons/umbbuttonellipsis.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/buttons/umbbuttonellipsis.directive.js new file mode 100644 index 0000000000..67b85c13b9 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/buttons/umbbuttonellipsis.directive.js @@ -0,0 +1,93 @@ +/** +@ngdoc directive +@name umbraco.directives.directive:umbButtonEllipsis +@restrict E +@scope + +@description +Added in Umbraco version 8.7.0 Use this directive to render an umbraco ellipsis. + +

    Markup example

    +
    +    
    + + + + +
    +
    + +@param {string} text Set the text for the checkbox label. +@param {string} labelKey Set a dictinary/localization string for the checkbox label +@param {callback} action Callback when the value of the checkbox change by interaction. +@param {string} cssClass Set a css class modifier +@param {string} color Set a hex code like #f5c1bc +@param {boolean} showText Set to true to show the text. false by default +@param {domElement} element Highlights a DOM-element (HTML-selector) +@param {string} state Set the initial state of the component. To have it hidden use hidden +@param {string} mode Set the mode, which decides how to style the component. "small" and "tab" are currently supported +**/ + +(function () { + 'use strict'; + + function UmbButtonEllipsis($timeout, localizationService) { + + var vm = this; + + vm.$onInit = onInit; + vm.clickButton = clickButton; + + function onInit() { + setText(); + + setColor(); + } + + function clickButton(event) { + if(vm.action) { + vm.action({$event: event}); + } + } + + function setText() { + if (vm.labelKey) { + localizationService.localize(vm.labelKey).then(function (data) { + // If a labelKey is passed let's update the returned text if it's does not contain an opening square bracket [ + if(data.indexOf('[') === -1){ + vm.text = data; + } + }); + } + } + + function setColor() { + vm.color = vm.color ? vm.color : '#000000'; + } + } + + var component = { + templateUrl: 'views/components/buttons/umb-button-ellipsis.html', + controller: UmbButtonEllipsis, + controllerAs: 'vm', + transclude: true, + bindings: { + text: "@", + labelKey: "@?", + action: "&", + cssClass: "@?", + color: "@?", + showText: " { if ((vm.culture === "invariant" || v.language && v.language.culture === vm.culture) && v.segment === vm.segment) { activeVariant = v; } }); + if (!activeVariant) { // Set the first variant to active if we can't find it. // If the content item is invariant, then only one item exists in the array. @@ -103,13 +105,16 @@ //now re-sync any other editor content (i.e. if split view is open) for (var s = 1; s < vm.editors.length; s++) { //get the variant from the scope model - var variant = _.find(vm.content.variants, function (v) { - return (!v.language || v.language.culture === vm.editors[s].content.language.culture) && v.segment === vm.editors[s].content.segment; - }); + var variant = vm.content.variants.find(v => + (!v.language || v.language.culture === vm.editors[s].content.language.culture) && v.segment === vm.editors[s].content.segment); + vm.editors[s].content = variant; } } - + + if (vm.content.variants.length > 1) { + eventsService.emit('editors.content.cultureChanged', activeVariant.language); + } } /** @@ -160,32 +165,30 @@ */ function openSplitView(selectedVariant) { // enforce content contentApp in splitview. - var contentApp = vm.content.apps.find((app) => app.alias === "umbContent"); + var contentApp = vm.content.apps.find(app => app.alias === "umbContent"); if(contentApp) { selectApp(contentApp); } insertVariantEditor(vm.editors.length, selectedVariant); - splitViewChanged(); - + splitViewChanged(); } - - $scope.$on("editors.content.splitViewRequest", function(event, args) {requestSplitView(args);}); - vm.requestSplitView = requestSplitView; + function requestSplitView(args) { var culture = args.culture; var segment = args.segment; - var variant = _.find(vm.content.variants, function (v) { - return (!v.language || v.language.culture === culture) && v.segment === segment; - }); + var variant = vm.content.variants.find(v => + (!v.language || v.language.culture === culture) && v.segment === segment); if (variant != null) { openSplitView(variant); } } + eventsService.on("editors.content.splitViewRequest", (_, args) => requestSplitView(args)); + /** Closes the split view */ function closeSplitView(editorIndex) { // TODO: hacking animation states - these should hopefully be easier to do when we upgrade angular @@ -194,8 +197,9 @@ editor.content.active = false; //update the current culture to reflect the last open variant (closing the split view corresponds to selecting the other variant) - - $location.search({"cculture": vm.editors[0].content.language ? vm.editors[0].content.language.culture : null, "csegment": vm.editors[0].content.segment}); + const culture = vm.editors[0].content.language ? vm.editors[0].content.language.culture : null; + + $location.search({"cculture": culture, "csegment": vm.editors[0].content.segment}); splitViewChanged(); } @@ -222,11 +226,9 @@ $location.search("cculture", variantCulture).search("csegment", variantSegment); } else { - //update the editors collection - insertVariantEditor(editorIndex, variant); - - } + insertVariantEditor(editorIndex, variant); + } } /** @@ -244,7 +246,6 @@ vm.onSelectAppAnchor({"app": app, "anchor": anchor}); } } - function getScope() { return $scope; } diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/umbcheckbox.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/umbcheckbox.directive.js index 389aec2044..717cefbb0a 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/umbcheckbox.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/umbcheckbox.directive.js @@ -31,8 +31,10 @@ @param {boolean} disabled Set the checkbox to be disabled. @param {boolean} required Set the checkbox to be required. @param {callback} onChange Callback when the value of the checkbox change by interaction. -@param {string} cssClass Set a css class modifier -@param {boolean} disableDirtyCheck Disable checking if the model is dirty +@param {string} cssClass Set a css class modifier. +@deprecated @param {string} iconClass Set an icon next to checkbox. Use "icon" parameter instead. +@param {string} icon Set an icon next to checkbox. +@param {boolean} disableDirtyCheck Disable checking if the model is dirty. **/ @@ -49,6 +51,8 @@ function onInit() { vm.inputId = vm.inputId || "umb-check_" + String.CreateGuid(); + vm.icon = vm.icon || vm.iconClass || null; + // If a labelKey is passed let's update the returned text if it's does not contain an opening square bracket [ if (vm.labelKey) { localizationService.localize(vm.labelKey).then(function (data) { @@ -85,7 +89,8 @@ required: "<", onChange: "&?", cssClass: "@?", - iconClass: "@?", + iconClass: "@?", // deprecated + icon: "@?", disableDirtyCheck: "=?" } }; diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/umbfocuslock.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/umbfocuslock.directive.js new file mode 100644 index 0000000000..569f49b88a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/umbfocuslock.directive.js @@ -0,0 +1,82 @@ +(function() { + 'use strict'; + + function FocusLock($timeout) { + + function getAutoFocusElement (elements) { + var elmentWithAutoFocus = null; + + elements.forEach((element) => { + if(element.getAttribute('umb-auto-focus') === 'true') { + elmentWithAutoFocus = element; + } + }); + + return elmentWithAutoFocus; + } + + function link(scope, element) { + + function onInit() { + // List of elements that can be focusable within the focus lock + var focusableElementsSelector = 'a[href]:not([disabled]), button:not([disabled]), textarea:not([disabled]), input:not([disabled]), select:not([disabled])'; + var bodyElement = document.querySelector('body'); + + $timeout(function() { + var target = element[0]; + + var focusableElements = target.querySelectorAll(focusableElementsSelector); + var defaultFocusedElement = getAutoFocusElement(focusableElements); + var firstFocusableElement = focusableElements[0]; + var lastFocusableElement = focusableElements[focusableElements.length -1]; + + // We need to add the tabbing-active class in order to highlight the focused button since the default style is + // outline: none; set in the stylesheet specifically + bodyElement.classList.add('tabbing-active'); + + // If there is no default focused element put focus on the first focusable element in the nodelist + if(defaultFocusedElement === null ){ + firstFocusableElement.focus(); + } + + target.addEventListener('keydown', function(event){ + var isTabPressed = (event.key === 'Tab' || event.keyCode === 9); + + if (!isTabPressed){ + return; + } + + // If shift + tab key + if(event.shiftKey){ + // Set focus on the last focusable element if shift+tab are pressed meaning we go backwards + if(document.activeElement === firstFocusableElement){ + lastFocusableElement.focus(); + event.preventDefault(); + } + } + // Else only the tab key is pressed + else{ + // Using only the tab key we set focus on the first focusable element mening we go forward + if (document.activeElement === lastFocusableElement) { + firstFocusableElement.focus(); + event.preventDefault(); + } + } + }); + }, 250); + } + + onInit(); + } + + var directive = { + restrict: 'A', + link: link + }; + + return directive; + } + + angular.module('umbraco.directives').directive('umbFocusLock', FocusLock); + +})(); diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/umbradiobutton.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/umbradiobutton.directive.js index d79140f947..3232ed7f34 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/umbradiobutton.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/umbradiobutton.directive.js @@ -26,10 +26,14 @@ @param {string} value Set the value of the radiobutton. @param {string} name Set the name of the radiobutton. @param {string} text Set the text for the radiobutton label. -@param {string} labelKey Set a dictinary/localization string for the checkbox label +@param {string} labelKey Set a dictinary/localization string for the checkbox label. +@param {string} serverValidationField Set the val-server-field of the radiobutton. @param {boolean} disabled Set the radiobutton to be disabled. @param {boolean} required Set the radiobutton to be required. @param {callback} onChange Callback when the value of the radiobutton change by interaction. +@param {string} cssClass Set a css class modifier. +@param {string} iconClass Set an icon next to radiobutton. +@param {boolean} disableDirtyCheck Disable checking if the model is dirty. **/ @@ -46,6 +50,8 @@ function onInit() { vm.inputId = vm.inputId || "umb-radio_" + String.CreateGuid(); + vm.icon = vm.icon || vm.iconClass || null; + // If a labelKey is passed let's update the returned text if it's does not contain an opening square bracket [ if (vm.labelKey) { localizationService.localize(vm.labelKey).then(function (data) { @@ -77,9 +83,14 @@ name: "@", text: "@", labelKey: "@?", + serverValidationField: "@", disabled: "<", required: "<", - onChange: "&?" + onChange: "&?", + cssClass: "@?", + iconClass: "@?", // deprecated + icon: "@?", + disableDirtyCheck: "=?" } }; diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/umbsearchfilter.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/umbsearchfilter.directive.js new file mode 100644 index 0000000000..7929316275 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/forms/umbsearchfilter.directive.js @@ -0,0 +1,84 @@ +/** +@ngdoc directive +@name umbraco.directives.directive:umbSearchFilter +@restrict E +@scope + +@description +Added in Umbraco version 8.7.0 Use this directive to render an umbraco search filter. + +

    Markup example

    +
    +    
    + + + + +
    +
    + +@param {boolean} model Set to true or false to set the checkbox to checked or unchecked. +@param {string} inputId Set the id of the checkbox. +@param {string} text Set the text for the checkbox label. +@param {string} labelKey Set a dictinary/localization string for the checkbox label +@param {callback} onChange Callback when the value of the checkbox change by interaction. +@param {boolean} autoFocus Add autofocus to the input field +@param {boolean} preventSubmitOnEnter Set the enter prevent directive or not + +**/ + +(function () { + 'use strict'; + + function UmbSearchFilterController($timeout, localizationService) { + + var vm = this; + + vm.$onInit = onInit; + vm.change = change; + + function onInit() { + vm.inputId = vm.inputId || "umb-check_" + String.CreateGuid(); + + // If a labelKey is passed let's update the returned text if it's does not contain an opening square bracket [ + if (vm.labelKey) { + localizationService.localize(vm.labelKey).then(function (data) { + if(data.indexOf('[') === -1){ + vm.text = data; + } + }); + } + } + + function change() { + if (vm.onChange) { + $timeout(function () { + vm.onChange({ model: vm.model, value: vm.value }); + }, 0); + } + } + } + + var component = { + templateUrl: 'views/components/forms/umb-search-filter.html', + controller: UmbSearchFilterController, + controllerAs: 'vm', + transclude: true, + bindings: { + model: "=", + inputId: "@", + text: "@", + labelKey: "@?", + onChange: "&?", + autoFocus: " constraints.left.max) - { - left = constraints.left.max; - } + var validatePosition = function (left, top) { + if (left > constraints.left.max) { + left = constraints.left.max; + } - if(left <= constraints.left.min){ - left = constraints.left.min; - } + if (left <= constraints.left.min) { + left = constraints.left.min; + } - if(top > constraints.top.max) - { - top = constraints.top.max; - } - if(top <= constraints.top.min){ - top = constraints.top.min; - } + if (top > constraints.top.max) { + top = constraints.top.max; + } + if (top <= constraints.top.min) { + top = constraints.top.min; + } - if(scope.dimensions.image.left !== left){ - scope.dimensions.image.left = left; - } + if (scope.dimensions.image.left !== left) { + scope.dimensions.image.left = left; + } - if(scope.dimensions.image.top !== top){ - scope.dimensions.image.top = top; - } - }; + if (scope.dimensions.image.top !== top) { + scope.dimensions.image.top = top; + } + }; - //sets scope.crop to the recalculated % based crop - var calculateCropBox = function(){ - scope.crop = cropperHelper.pixelsToCoordinates(scope.dimensions.image, scope.dimensions.cropper.width, scope.dimensions.cropper.height, scope.dimensions.margin); - }; + //sets scope.crop to the recalculated % based crop + var calculateCropBox = function () { + scope.crop = cropperHelper.pixelsToCoordinates(scope.dimensions.image, scope.dimensions.cropper.width, scope.dimensions.cropper.height, scope.dimensions.margin); + }; - //Drag and drop positioning, using jquery ui draggable - var onStartDragPosition, top, left; - $overlay.draggable({ - drag: function(event, ui) { - scope.$apply(function(){ - validatePosition(ui.position.left, ui.position.top); - }); - }, - stop: function(event, ui){ - scope.$apply(function(){ - //make sure that every validates one more time... - validatePosition(ui.position.left, ui.position.top); + //Drag and drop positioning, using jquery ui draggable + var onStartDragPosition, top, left; + $overlay.draggable({ + drag: function (event, ui) { + scope.$apply(function () { + validatePosition(ui.position.left, ui.position.top); + }); + }, + stop: function (event, ui) { + scope.$apply(function () { + //make sure that every validates one more time... + validatePosition(ui.position.left, ui.position.top); - calculateCropBox(); - scope.dimensions.image.rnd = Math.random(); - }); - } - }); + calculateCropBox(); + scope.dimensions.image.rnd = Math.random(); + }); + } + }); - var init = function(image){ - scope.loaded = false; + var init = function (image) { + scope.loaded = false; - //set dimensions on image, viewport, cropper etc - setDimensions(image); + //set dimensions on image, viewport, cropper etc + setDimensions(image); - //create a default crop if we haven't got one already + //create a default crop if we haven't got one already var createDefaultCrop = !scope.crop; if (createDefaultCrop) { calculateCropBox(); } - resizeImageToCrop(); + resizeImageToCrop(); //if we're creating a new crop, make sure to zoom out fully if (createDefaultCrop) { scope.dimensions.scale.current = scope.dimensions.scale.min; - resizeImageToScale(scope.dimensions.scale.min); + resizeImageToScale(scope.dimensions.scale.min); + + if (scope.center) { + // Move image to focal point if set + // Repeating a few calls here, but logic is too difficult to follow elsewhere + var x1 = Math.min( + Math.max( + scope.center.left * scope.dimensions.image.width - scope.dimensions.cropper.width / 2, + 0 + ), + scope.dimensions.image.width - scope.dimensions.cropper.width + ); + var y1 = Math.min( + Math.max( + scope.center.top * scope.dimensions.image.height - scope.dimensions.cropper.height / 2, + 0 + ), + scope.dimensions.image.height - scope.dimensions.cropper.height + ); + scope.dimensions.image.left = x1; + scope.dimensions.image.top = y1; + calculateCropBox(); + resizeImageToCrop(); + } } - //sets constaints for the cropper - setConstraints(); - scope.loaded = true; - }; + //sets constaints for the cropper + setConstraints(); + scope.loaded = true; + }; - // Watchers - scope.$watchCollection('[width, height]', function(newValues, oldValues){ - // We have to reinit the whole thing if - // one of the external params changes - if(newValues !== oldValues){ - setDimensions($image); - setConstraints(); - } - }); + // Watchers + scope.$watchCollection('[width, height]', function (newValues, oldValues) { + // We have to reinit the whole thing if + // one of the external params changes + if (newValues !== oldValues) { + setDimensions($image); + setConstraints(); + } + }); - var throttledResizing = _.throttle(function(){ + var throttledResizing = _.throttle(function () { resizeImageToScale(scope.dimensions.scale.current); - calculateCropBox(); - }, 15); + calculateCropBox(); + }, 15); - // Happens when we change the scale + // Happens when we change the scale scope.$watch("dimensions.scale.current", function (newValue, oldValue) { - if (scope.loaded) { - throttledResizing(); - } - }); + if (scope.loaded) { + throttledResizing(); + } + }); - // Init - $image.on("load", function(){ - $timeout(function(){ - init($image); - }); - }); - } - }; - }); + // Init + $image.on("load", function () { + $timeout(function () { + init($image); + }); + }); + } + }; + }); diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/media/umbmedianodeinfo.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/media/umbmedianodeinfo.directive.js index dfa1afc247..6f34cfc0a1 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/media/umbmedianodeinfo.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/media/umbmedianodeinfo.directive.js @@ -1,7 +1,7 @@ (function () { 'use strict'; - function MediaNodeInfoDirective($timeout, $location, eventsService, userService, dateHelper, editorService, mediaHelper, mediaResource, $q) { + function MediaNodeInfoDirective($timeout, $location, $q, eventsService, userService, dateHelper, editorService, mediaHelper, mediaResource) { function link(scope, element, attrs, ctrl) { @@ -37,7 +37,7 @@ }); }); - // get document type details + // get media type details scope.mediaType = scope.node.contentType; // set the media link initially diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/member/umbmembernodeinfo.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/member/umbmembernodeinfo.directive.js index 3b6a2c069a..8dd6d56139 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/member/umbmembernodeinfo.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/member/umbmembernodeinfo.directive.js @@ -11,6 +11,19 @@ scope.allowChangeMemberType = false; function onInit() { + + userService.getCurrentUser().then(function (user) { + // only allow change of member type if user has access to the settings sections + Utilities.forEach(user.sections, function (section) { + if (section.alias === "settings") { + scope.allowChangeMemberType = true; + } + }); + }); + + // get member type details + scope.memberType = scope.node.contentType; + // make sure dates are formatted to the user's locale formatDatesToLocal(); } diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/overlays/umboverlay.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/overlays/umboverlay.directive.js index d1bdf6f42f..f7ba043ef1 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/overlays/umboverlay.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/overlays/umboverlay.directive.js @@ -221,6 +221,10 @@ Opens an overlay to show a custom YSOD.
    $timeout(function () { + if (!scope.name) { + scope.name = 'overlay'; + } + if (scope.position === "target" && scope.model.event) { setTargetPosition(); @@ -403,11 +407,15 @@ Opens an overlay to show a custom YSOD.
    function setTargetPosition() { - var container = $("#contentwrapper"); - var containerLeft = container[0].offsetLeft; - var containerRight = containerLeft + container[0].offsetWidth; - var containerTop = container[0].offsetTop; - var containerBottom = containerTop + container[0].offsetHeight; + var overlay = $(scope.model.event.target).closest('.umb-overlay'); + var container = overlay.length > 0 ? overlay : $("#contentwrapper"); + + let rect = container[0].getBoundingClientRect(); + + var containerLeft = rect.left; + var containerRight = containerLeft + rect.width; + var containerTop = rect.top; + var containerBottom = containerTop + rect.height; var mousePositionClickX = null; var mousePositionClickY = null; @@ -430,8 +438,9 @@ Opens an overlay to show a custom YSOD.
    elementWidth = el[0].clientWidth; // move element to this position - position.left = mousePositionClickX - (elementWidth / 2); - position.top = mousePositionClickY - (elementHeight / 2); + // when using hotkey it fallback to center of container + position.left = mousePositionClickX ? mousePositionClickX - (elementWidth / 2) : (containerLeft + containerRight) / 2 - (elementWidth / 2); + position.top = mousePositionClickY ? mousePositionClickY - (elementHeight / 2) : (containerTop + containerBottom) / 2 - (elementHeight / 2); // check to see if element is outside screen // outside right @@ -459,6 +468,7 @@ Opens an overlay to show a custom YSOD.
    } el.css(position); + el.css("visibility", "visible"); } scope.submitForm = function (model) { @@ -530,6 +540,7 @@ Opens an overlay to show a custom YSOD.
    view: "=", position: "@", size: "=?", + name: "=?", parentScope: "=?" }, link: link diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/tree/umbtree.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/tree/umbtree.directive.js index 0ccaf7b05c..a412f73c5a 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/tree/umbtree.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/tree/umbtree.directive.js @@ -88,9 +88,8 @@ function umbTreeDirective($q, $rootScope, treeService, notificationsService, use /** Helper function to emit tree events */ function emitEvent(eventName, args) { if (registeredCallbacks[eventName] && Utilities.isArray(registeredCallbacks[eventName])) { - _.each(registeredCallbacks[eventName], function (c) { - c(args);//call it - }); + // call it + registeredCallbacks[eventName].forEach(c => c(args)); } } @@ -342,26 +341,17 @@ function umbTreeDirective($q, $rootScope, treeService, notificationsService, use var css = []; if (node.cssClasses) { - _.each(node.cssClasses, function (c) { - css.push(c); - }); + node.cssClasses.forEach(c => css.push(c)); } return css.join(" "); }; - $scope.selectEnabledNodeClass = function (node) { - return node ? - node.selected ? - 'icon umb-tree-icon sprTree icon-check green temporary' : - '' : - ''; - }; + $scope.selectEnabledNodeClass = node => + node && node.selected ? 'icon umb-tree-icon sprTree icon-check green temporary' : ''; /* helper to force reloading children of a tree node */ - $scope.loadChildren = function (node, forceReload) { - return loadChildren(node, forceReload); - }; + $scope.loadChildren = (node, forceReload) => loadChildren(node, forceReload); /** Method called when the options button next to the root node is called. diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/tree/umbtreeitem.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/tree/umbtreeitem.directive.js index 8767de446a..f2fc0d2dae 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/tree/umbtreeitem.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/tree/umbtreeitem.directive.js @@ -70,9 +70,7 @@ angular.module("umbraco.directives") var css = []; if (node.cssClasses) { - _.each(node.cssClasses, function(c) { - css.push(c); - }); + node.cssClasses.forEach(c => css.push(c)); } if (node.selected) { css.push("umb-tree-node-checked"); diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbchildselector.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbchildselector.directive.js index 96ce8735eb..9a841e3e4a 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbchildselector.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbchildselector.directive.js @@ -21,14 +21,6 @@ Use this directive to render a ui component for selecting child items to a paren on-remove="vm.removeChild"> - - - -
    @@ -37,7 +29,7 @@ Use this directive to render a ui component for selecting child items to a paren (function () { "use strict"; - function Controller() { + function Controller(overlayService) { var vm = this; @@ -64,23 +56,29 @@ Use this directive to render a ui component for selecting child items to a paren vm.removeChild = removeChild; function addChild($event) { - vm.overlay = { + + const dialog = { view: "itempicker", title: "Choose child", availableItems: vm.availableChildren, selectedItems: vm.selectedChildren, event: $event, - show: true, submit: function(model) { - - // add selected child - vm.selectedChildren.push(model.selectedItem); + + if (model.selectedItem) { + // add selected child + vm.selectedChildren.push(model.selectedItem); + } // close overlay - vm.overlay.show = false; - vm.overlay = null; + overlayService.close(); + }, + close: function() { + overlayService.close(); } }; + + overlayService.open(dialog); } function removeChild($index) { diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbconfirmaction.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbconfirmaction.directive.js index 1dcccda481..2f682205ad 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbconfirmaction.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbconfirmaction.directive.js @@ -14,10 +14,10 @@ The prompt can be opened in four direction up, down, left or right.

    - @@ -71,17 +71,23 @@ The prompt can be opened in four direction up, down, left or right.

    function link(scope, el, attr, ctrl) { - scope.clickConfirm = function() { - if(scope.onConfirm) { - scope.onConfirm(); - } - }; + scope.clickButton = function (event) { + if(scope.onDelete) { + scope.onDelete({$event: event}); + } + } - scope.clickCancel = function() { - if(scope.onCancel) { - scope.onCancel(); - } - }; + scope.clickConfirm = function() { + if(scope.onConfirm) { + scope.onConfirm(); + } + }; + + scope.clickCancel = function() { + if(scope.onCancel) { + scope.onCancel(); + } + }; } @@ -91,6 +97,8 @@ The prompt can be opened in four direction up, down, left or right.

    templateUrl: 'views/components/umb-confirm-action.html', scope: { direction: "@", + show: "<", + onDelete: "&?", onConfirm: "&", onCancel: "&" }, diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbdatetimepicker.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbdatetimepicker.directive.js index 0498b81963..ed9c011d72 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbdatetimepicker.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbdatetimepicker.directive.js @@ -189,7 +189,7 @@ Use this directive to render a date time picker }; } - // bind hook for onOpen + // bind hook for onOpen if (ctrl.options && ctrl.onClose) { ctrl.options.onClose = function (selectedDates, dateStr, instance) { $timeout(function () { diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbgroupsbuilder.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbgroupsbuilder.directive.js index 3f53a1e18c..92d2df43e5 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbgroupsbuilder.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbgroupsbuilder.directive.js @@ -161,19 +161,17 @@ var resourceLookup = scope.contentType === "documentType" ? contentTypeResource.getAvailableCompositeContentTypes : mediaTypeResource.getAvailableCompositeContentTypes; return resourceLookup(scope.model.id, selectedContentTypeAliases, propAliasesExisting).then(function (filteredAvailableCompositeTypes) { - _.each(scope.compositionsDialogModel.availableCompositeContentTypes, function (current) { + scope.compositionsDialogModel.availableCompositeContentTypes.forEach(current => { //reset first current.allowed = true; //see if this list item is found in the response (allowed) list - var found = _.find(filteredAvailableCompositeTypes, function (f) { - return current.contentType.alias === f.contentType.alias; - }); + var found = filteredAvailableCompositeTypes.find(f => current.contentType.alias === f.contentType.alias); //allow if the item was found in the response (allowed) list - // and ensure its set to allowed if it is currently checked, // DO not allow if it's a locked content type. - current.allowed = scope.model.lockedCompositeContentTypes.indexOf(current.contentType.alias) === -1 && - (selectedContentTypeAliases.indexOf(current.contentType.alias) !== -1) || ((found !== null && found !== undefined) ? found.allowed : false); + current.allowed = scope.model.lockedCompositeContentTypes.includes(current.contentType.alias) && + (selectedContentTypeAliases.includes(current.contentType.alias)) || (found ? found.allowed : false); }); }); @@ -192,15 +190,15 @@ function setupAvailableContentTypesModel(result) { scope.compositionsDialogModel.availableCompositeContentTypes = result; //iterate each one and set it up - _.each(scope.compositionsDialogModel.availableCompositeContentTypes, function (c) { + scope.compositionsDialogModel.availableCompositeContentTypes.forEach(c => { //enable it if it's part of the selected model - if (scope.compositionsDialogModel.compositeContentTypes.indexOf(c.contentType.alias) !== -1) { + if (scope.compositionsDialogModel.compositeContentTypes.includes(c.contentType.alias)) { c.allowed = true; } //set the inherited flags c.inherited = false; - if (scope.model.lockedCompositeContentTypes.indexOf(c.contentType.alias) > -1) { + if (scope.model.lockedCompositeContentTypes.includes(c.contentType.alias)) { c.inherited = true; } // convert icons for composite content types @@ -281,6 +279,8 @@ }, selectCompositeContentType: function (selectedContentType) { + var deferred = $q.defer(); + //first check if this is a new selection - we need to store this value here before any further digests/async // because after that the scope.model.compositeContentTypes will be populated with the selected value. var newSelection = scope.model.compositeContentTypes.indexOf(selectedContentType.alias) === -1; @@ -308,7 +308,10 @@ //based on the selection, we need to filter the available composite types list filterAvailableCompositions(selectedContentType, newSelection).then(function () { + deferred.resolve({ selectedContentType, newSelection }); // TODO: Here we could probably re-enable selection if we previously showed a throbber or something + }, function () { + deferred.reject(); }); }); } @@ -318,10 +321,14 @@ //based on the selection, we need to filter the available composite types list filterAvailableCompositions(selectedContentType, newSelection).then(function () { + deferred.resolve({ selectedContentType, newSelection }); // TODO: Here we could probably re-enable selection if we previously showed a throbber or something + }, function () { + deferred.reject(); }); } + return deferred.promise; } }; diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbicon.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbicon.directive.js new file mode 100644 index 0000000000..517776388b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbicon.directive.js @@ -0,0 +1,86 @@ +/** +@ngdoc directive +@name umbraco.directives.directive:umbIcon +@restrict E +@scope +@description +Use this directive to show an render an umbraco backoffice svg icon. All svg icons used by this directive should use the following naming convention to keep things consistent: icon-[name of icon]. For example
    icon-alert.svg
    + +

    Markup example

    + +Simple icon +
    +    
    +
    + +Icon with additional attribute. It can be treated like any other dom element +
    +    
    +
    + +Manual svg string +This format is only used in the iconpicker.html +
    +    
    +    
    +
    +@example + **/ + +(function () { + "use strict"; + + function UmbIconDirective(iconHelper) { + + var directive = { + replace: true, + transclude: true, + templateUrl: "views/components/umb-icon.html", + scope: { + icon: "@", + svgString: "=?" + }, + + link: function (scope) { + + if (scope.svgString === undefined && scope.svgString !== null && scope.icon !== undefined && scope.icon !== null) { + var icon = scope.icon.split(" ")[0]; // Ensure that only the first part of the icon is used as sometimes the color is added too, e.g. see umbeditorheader.directive scope.openIconPicker + + _requestIcon(icon); + } + scope.$watch("icon", function (newValue, oldValue) { + if (newValue && oldValue) { + var newicon = newValue.split(" ")[0]; + var oldicon = oldValue.split(" ")[0]; + + if (newicon !== oldicon) { + _requestIcon(newicon); + } + } + }); + + function _requestIcon(icon) { + // Reset svg string before requesting new icon. + scope.svgString = null; + + iconHelper.getIcon(icon) + .then(data => { + if (data !== null && data.svgString !== undefined) { + // Watch source SVG string + //icon.svgString.$$unwrapTrustedValue(); + scope.svgString = data.svgString; + } + }); + } + } + + }; + + return directive; + } + + angular.module("umbraco.directives").directive("umbIcon", UmbIconDirective); + +})(); diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbmediagrid.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbmediagrid.directive.js index aa28d49c4a..241f1e80e8 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbmediagrid.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbmediagrid.directive.js @@ -322,6 +322,41 @@ Use this directive to generate a thumbnail grid of media items. scope.$on('$destroy', function() { unbindItemsWatcher(); }); + //determine if sort is current + scope.sortColumn = "name"; + scope.sortReverse = false; + scope.sortDirection = "asc"; + //check sort status + scope.isSortDirection = function (col, direction) { + return col === scope.sortColumn && direction === scope.sortDirection; + }; + //change sort + scope.setSort = function (col) { + if (scope.sortColumn === col) { + scope.sortReverse = !scope.sortReverse; + } + else { + scope.sortColumn = col; + if (col === "updateDate") { + scope.sortReverse = true; + } + else { + scope.sortReverse = false; + } + } + scope.sortDirection = scope.sortReverse ? "desc" : "asc"; + + } + // sort function + scope.sortBy = function (item) { + if (scope.sortColumn === "updateDate") { + return [-item['isFolder'],item['updateDate']]; + } + else { + return [-item['isFolder'],item['name']]; + } + }; + } @@ -345,7 +380,8 @@ Use this directive to generate a thumbnail grid of media items. onlyImages: "@", onlyFolders: "@", includeSubFolders: "@", - currentFolderId: "@" + currentFolderId: "@", + showMediaList: "=" }, link: link }; diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbminilistview.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbminilistview.directive.js index 66e03a7302..3865ffcdae 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbminilistview.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbminilistview.directive.js @@ -63,7 +63,7 @@ } // update children miniListView.children = data.items; - _.each(miniListView.children, function(c) { + miniListView.children.forEach(c => { // child allowed by default c.allowed = true; @@ -95,7 +95,8 @@ var filtered = angular.isFunction(scope.entityTypeFilter.filter) ? _.filter(miniListView.children, scope.entityTypeFilter.filter) : _.where(miniListView.children, scope.entityTypeFilter.filter); - _.each(filtered, (node) => node.allowed = false); + + filtered.forEach(node => node.allowed = false); } // update pagination diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbtooltip.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbtooltip.directive.js index ef7006be2c..ce1885a7cf 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbtooltip.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbtooltip.directive.js @@ -77,13 +77,17 @@ Use this directive to render a tooltip. scope.tooltipStyles.left = 0; scope.tooltipStyles.top = 0; - function setTooltipPosition(event) { + function setTooltipPosition(event) { - var container = $("#contentwrapper"); - var containerLeft = container[0].offsetLeft; - var containerRight = containerLeft + container[0].offsetWidth; - var containerTop = container[0].offsetTop; - var containerBottom = containerTop + container[0].offsetHeight; + var overlay = $(event.target).closest('.umb-overlay'); + var container = overlay.length > 0 ? overlay : $("#contentwrapper"); + + let rect = container[0].getBoundingClientRect(); + + var containerLeft = rect.left; + var containerRight = containerLeft + rect.width; + var containerTop = rect.top; + var containerBottom = containerTop + rect.height; var elementHeight = null; var elementWidth = null; @@ -102,39 +106,43 @@ Use this directive to render a tooltip. position.left = event.pageX - (elementWidth / 2); position.top = event.pageY; - // check to see if element is outside screen - // outside right - if (position.left + elementWidth > containerRight) { - position.right = 10; - position.left = "inherit"; + if (overlay.length > 0) { + position.left = event.pageX - rect.left - (elementWidth / 2); + position.top = event.pageY - rect.top; } + else { + // check to see if element is outside screen + // outside right + if (position.left + elementWidth > containerRight) { + position.right = 10; + position.left = "inherit"; + } - // outside bottom - if (position.top + elementHeight > containerBottom) { - position.bottom = 10; - position.top = "inherit"; - } + // outside bottom + if (position.top + elementHeight > containerBottom) { + position.bottom = 10; + position.top = "inherit"; + } - // outside left - if (position.left < containerLeft) { - position.left = containerLeft + 10; - position.right = "inherit"; - } + // outside left + if (position.left < containerLeft) { + position.left = containerLeft + 10; + position.right = "inherit"; + } - // outside top - if (position.top < containerTop) { - position.top = 10; - position.bottom = "inherit"; + // outside top + if (position.top < containerTop) { + position.top = 10; + position.bottom = "inherit"; + } } scope.tooltipStyles = position; el.css(position); - } setTooltipPosition(scope.event); - } var directive = { diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/upload/umbfileupload.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/upload/umbfileupload.directive.js index 6a8ffa7969..3581aed9e0 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/upload/umbfileupload.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/upload/umbfileupload.directive.js @@ -19,6 +19,17 @@ function umbFileUpload() { //clear the element value - this allows us to pick the same file again and again el.val(''); }); + + el.on('drag dragstart dragend dragover dragenter dragleave drop', function (e) { + e.preventDefault(); + e.stopPropagation(); + }) + .on('dragover dragenter', function () { + scope.$emit("isDragover", { value: true }); + }) + .on('dragleave dragend drop', function () { + scope.$emit("isDragover", { value: false }); + }); } }; } diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/upload/umbpropertyfileupload.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/upload/umbpropertyfileupload.directive.js index 653b4f427c..db1e38adc6 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/upload/umbpropertyfileupload.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/upload/umbpropertyfileupload.directive.js @@ -78,6 +78,8 @@ /** Called when the component initializes */ function onInit() { $scope.$on("filesSelected", onFilesSelected); + $scope.$on("isDragover", isDragover); + initialize(); } @@ -118,7 +120,9 @@ isImage: mediaHelper.detectIfImageByExtension(file), extension: getExtension(file) }; + f.fileSrc = getThumbnail(f); + return f; }); @@ -228,19 +232,22 @@ var index = i; //capture var isImage = mediaHelper.detectIfImageByExtension(files[i].name); + var extension = getExtension(files[i].name); - //save the file object to the files collection - vm.files.push({ + var f = { isImage: isImage, - extension: getExtension(files[i].name), + extension: extension, fileName: files[i].name, isClientSide: true - }); + }; + + // Save the file object to the files collection + vm.files.push(f); //special check for a comma in the name newVal += files[i].name.split(',').join('-') + ","; - if (isImage) { + if (isImage || extension === "svg") { var deferred = $q.defer(); @@ -293,6 +300,11 @@ } } + function isDragover(e, args) { + vm.dragover = args.value; + angularHelper.safeApply($scope); + } + }; var umbPropertyFileUploadComponent = { @@ -303,6 +315,7 @@ propertyAlias: "@", value: "<", hideSelection: "<", + dragover: "<", /** * Called when a file is selected on this instance */ diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valformmanager.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valformmanager.directive.js index 77c26e066e..c7894da171 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valformmanager.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valformmanager.directive.js @@ -204,7 +204,7 @@ function valFormManager(serverValidationManager, $rootScope, $timeout, $location var parts = nextPath.split("?"); var query = {}; if (parts.length > 1) { - _.each(parts[1].split("&"), function (q) { + parts[1].split("&").forEach(q => { var keyVal = q.split("="); query[keyVal[0]] = keyVal[1]; }); diff --git a/src/Umbraco.Web.UI.Client/src/common/mocks/resources/media.mocks.js b/src/Umbraco.Web.UI.Client/src/common/mocks/resources/media.mocks.js index 3b58c127a7..aeb6229360 100644 --- a/src/Umbraco.Web.UI.Client/src/common/mocks/resources/media.mocks.js +++ b/src/Umbraco.Web.UI.Client/src/common/mocks/resources/media.mocks.js @@ -8,12 +8,12 @@ angular.module('umbraco.mocks'). } function returnNodebyIds(status, data, headers) { - var ids = mocksUtils.getParameterByName(data, "ids") || "1234,1234,4234"; + var ids = mocksUtils.getParameterByName(data, "ids") || ['1234','1234','4234']; var items = []; - _.each(ids, function(id){ - items.push(_getNode( parseInt( id, 10 )) ); - }); + for (var i = 0; i < ids.length; i += 1) { + items.push(_getNode(parseInt(ids[i], 10))); + } return [200, items, null]; } @@ -26,8 +26,6 @@ angular.module('umbraco.mocks'). var id = mocksUtils.getParameterByName(data, "id") || 1234; id = parseInt(id, 10); - - return [200, _getNode(id), null]; } diff --git a/src/Umbraco.Web.UI.Client/src/common/mocks/umbraco.servervariables.js b/src/Umbraco.Web.UI.Client/src/common/mocks/umbraco.servervariables.js index da6f78a6a5..868bc4c6d5 100644 --- a/src/Umbraco.Web.UI.Client/src/common/mocks/umbraco.servervariables.js +++ b/src/Umbraco.Web.UI.Client/src/common/mocks/umbraco.servervariables.js @@ -19,7 +19,8 @@ Umbraco.Sys.ServerVariables = { "dashboardApiBaseUrl": "/umbraco/UmbracoApi/Dashboard/", "updateCheckApiBaseUrl": "/umbraco/Api/UpdateCheck/", "relationApiBaseUrl": "/umbraco/UmbracoApi/Relation/", - "rteApiBaseUrl": "/umbraco/UmbracoApi/RichTextPreValue/" + "rteApiBaseUrl": "/umbraco/UmbracoApi/RichTextPreValue/", + "iconApiBaseUrl": "/umbraco/UmbracoApi/Icon/" }, umbracoSettings: { "umbracoPath": "/umbraco", diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/content.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/content.resource.js index 4ca85f44e6..3dfbeade4f 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/content.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/content.resource.js @@ -442,9 +442,7 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) { getByIds: function (ids) { var idQuery = ""; - _.each(ids, function (item) { - idQuery += "ids=" + item + "&"; - }); + ids.forEach(id => idQuery += `ids=${id}&`); return umbRequestHelper.resourcePromise( $http.get( @@ -455,9 +453,7 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) { 'Failed to retrieve data for content with multiple ids') .then(function (result) { //each item needs to be re-formatted - _.each(result, function (r) { - umbDataFormatter.formatContentGetData(r) - }); + result.forEach(r => umbDataFormatter.formatContentGetData(r)); return $q.when(result); }); }, diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/media.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/media.resource.js index e24f4786eb..06eb2ed4d2 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/media.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/media.resource.js @@ -226,9 +226,7 @@ function mediaResource($q, $http, umbDataFormatter, umbRequestHelper) { getByIds: function (ids) { var idQuery = ""; - _.each(ids, function (item) { - idQuery += "ids=" + item + "&"; - }); + ids.forEach(id => idQuery += `ids=${id}&`); return umbRequestHelper.resourcePromise( $http.get( diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/membergroup.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/membergroup.resource.js index c83a31e47c..f9b9da9944 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/membergroup.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/membergroup.resource.js @@ -32,9 +32,7 @@ function memberGroupResource($q, $http, umbRequestHelper) { getByIds: function (ids) { var idQuery = ""; - _.each(ids, function (item) { - idQuery += "ids=" + item + "&"; - }); + ids.forEach(id => idQuery += `ids=${id}&`); return umbRequestHelper.resourcePromise( $http.get( diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/membertype.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/membertype.resource.js index 6c15b89c0e..2314fa6d6c 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/membertype.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/membertype.resource.js @@ -16,16 +16,15 @@ function memberTypeResource($q, $http, umbRequestHelper, umbDataFormatter) { } var query = ""; - _.each(filterContentTypes, function (item) { - query += "filterContentTypes=" + item + "&"; - }); + filterContentTypes.forEach(fct => query += `filterContentTypes=${fct}&`); + // if filterContentTypes array is empty we need a empty variable in the querystring otherwise the service returns a error if (filterContentTypes.length === 0) { query += "filterContentTypes=&"; } - _.each(filterPropertyTypes, function (item) { - query += "filterPropertyTypes=" + item + "&"; - }); + + filterPropertyTypes.forEach(fpt => query += `filterPropertyTypes=${fpt}&`); + // if filterPropertyTypes array is empty we need a empty variable in the querystring otherwise the service returns a error if (filterPropertyTypes.length === 0) { query += "filterPropertyTypes=&"; diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/users.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/users.resource.js index 2b9e0c0fd5..91f00a36e3 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/users.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/users.resource.js @@ -295,6 +295,38 @@ "Failed to retrieve data for user " + userId); } + + /** + * @ngdoc method + * @name umbraco.resources.usersResource#getUsers + * @methodOf umbraco.resources.usersResource + * + * @description + * Gets users from ids + * + * ##usage + *
    +          * usersResource.getUsers([1,2,3])
    +          *    .then(function(data) {
    +          *        alert("It's here");
    +          *    });
    +          * 
    + * + * @param {Array} userIds user ids. + * @returns {Promise} resourcePromise object containing the users array. + * + */ + function getUsers(userIds) { + + return umbRequestHelper.resourcePromise( + $http.get( + umbRequestHelper.getApiUrl( + "userApiBaseUrl", + "GetByIds", + { ids: userIds })), + "Failed to retrieve data for users " + userIds); + } + /** * @ngdoc method * @name umbraco.resources.usersResource#createUser @@ -481,6 +513,7 @@ setUserGroupsOnUsers: setUserGroupsOnUsers, getPagedResults: getPagedResults, getUser: getUser, + getUsers: getUsers, createUser: createUser, inviteUser: inviteUser, saveUser: saveUser, diff --git a/src/Umbraco.Web.UI.Client/src/common/services/assets.service.js b/src/Umbraco.Web.UI.Client/src/common/services/assets.service.js index 30e59e9a88..b474b66174 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/assets.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/assets.service.js @@ -276,7 +276,7 @@ angular.module('umbraco.services') //blocking var promises = []; var assets = []; - _.each(nonEmpty, function (path) { + nonEmpty.forEach(path => { path = convertVirtualPath(path); var asset = service._getAssetPromise(path); //if not previously loaded, add to list of promises @@ -325,19 +325,17 @@ angular.module('umbraco.services') scope = $rootScope; } angularHelper.safeApply(scope, - function () { - asset.deferred.resolve(true); - }); + () => asset.deferred.resolve(true)); } if (cssAssets.length > 0) { - var cssPaths = _.map(cssAssets, function (asset) { return appendRnd(asset.path) }); - LazyLoad.css(cssPaths, function () { _.each(cssAssets, assetLoaded); }); + var cssPaths = cssAssets.map(css => appendRnd(css.path)); + LazyLoad.css(cssPaths, () => cssAssets.forEach(assetLoaded)); } if (jsAssets.length > 0) { - var jsPaths = _.map(jsAssets, function (asset) { return appendRnd(asset.path) }); - LazyLoad.js(jsPaths, function () { _.each(jsAssets, assetLoaded); }); + var jsPaths = jsAssets.map(js => appendRnd(js.path)); + LazyLoad.js(jsPaths, () => jsAssets.forEach(assetLoaded)); } return promise; diff --git a/src/Umbraco.Web.UI.Client/src/common/services/contenteditinghelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/contenteditinghelper.service.js index 4ffd0c3c0b..c27283d5ad 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/contenteditinghelper.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/contenteditinghelper.service.js @@ -123,10 +123,7 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, editorSt self.handleSaveError({ showNotifications: args.showNotifications, softRedirect: args.softRedirect, - err: err, - rebindCallback: function () { - rebindCallback.apply(self, [args.content, err.data]); - } + err: err }); //update editor state to what is current diff --git a/src/Umbraco.Web.UI.Client/src/common/services/editor.service.js b/src/Umbraco.Web.UI.Client/src/common/services/editor.service.js index 538bd41ce0..0f4f04c6bf 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/editor.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/editor.service.js @@ -669,23 +669,6 @@ When building a custom infinite editor view you can use the same components as a open(editor); } - /** - * @ngdoc method - * @name umbraco.services.editorService#memberTypeEditor - * @methodOf umbraco.services.editorService - * - * @description - * Opens the member type editor in infinite editing, the submit callback returns the saved member type - * @param {Object} editor rendering options - * @param {Callback} editor.submit Submits the editor - * @param {Callback} editor.close Closes the editor - * @returns {Object} editor object - */ - function memberTypeEditor(editor) { - editor.view = "views/membertypes/edit.html"; - open(editor); - } - /** * @ngdoc method * @name umbraco.services.editorService#queryBuilder diff --git a/src/Umbraco.Web.UI.Client/src/common/services/focuslock.service.js b/src/Umbraco.Web.UI.Client/src/common/services/focuslock.service.js new file mode 100644 index 0000000000..a3dd91194e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/services/focuslock.service.js @@ -0,0 +1,26 @@ +(function () { + "use strict"; + + function focusLockService() { + var elementToInert = document.querySelector('#mainwrapper'); + + function addInertAttribute() { + elementToInert.setAttribute('inert', true); + } + + function removeInertAttribute() { + elementToInert.removeAttribute('inert'); + } + + var service = { + addInertAttribute: addInertAttribute, + removeInertAttribute: removeInertAttribute + } + + return service; + + } + + angular.module("umbraco.services").factory("focusLockService", focusLockService); + +})(); diff --git a/src/Umbraco.Web.UI.Client/src/common/services/formhelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/formhelper.service.js index 5866e28b1e..d9c11770cc 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/formhelper.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/formhelper.service.js @@ -17,10 +17,10 @@ function formHelper(angularHelper, serverValidationManager, notificationsService * @function * * @description - * Called by controllers when submitting a form - this ensures that all client validation is checked, + * Called by controllers when submitting a form - this ensures that all client validation is checked, * server validation is cleared, that the correct events execute and status messages are displayed. * This returns true if the form is valid, otherwise false if form submission cannot continue. - * + * * @param {object} args An object containing arguments for form submission */ submitForm: function (args) { @@ -33,6 +33,7 @@ function formHelper(angularHelper, serverValidationManager, notificationsService if (!args.scope) { throw "args.scope cannot be null"; } + if (!args.formCtrl) { //try to get the closest form controller currentForm = angularHelper.getRequiredCurrentForm(args.scope); @@ -44,15 +45,13 @@ function formHelper(angularHelper, serverValidationManager, notificationsService //the first thing any form must do is broadcast the formSubmitting event args.scope.$broadcast("formSubmitting", { scope: args.scope, action: args.action }); - // Some property editors need to perform an action after all property editors have reacted to the formSubmitting. - args.scope.$broadcast("formSubmittingFinalPhase", { scope: args.scope, action: args.action }); - - // Set the form state to submitted - currentForm.$setSubmitted(); + this.focusOnFirstError(currentForm); + args.scope.$broadcast("postFormSubmitting", { scope: args.scope, action: args.action }); //then check if the form is valid if (!args.skipValidation) { if (currentForm.$invalid) { + return false; } } @@ -68,6 +67,32 @@ function formHelper(angularHelper, serverValidationManager, notificationsService return true; }, + /** + * @ngdoc function + * @name umbraco.services.formHelper#focusOnFirstError + * @methodOf umbraco.services.formHelper + * @function + * + * @description + * Called by submitForm when a form has been submitted, it will fire a focus on the first found invalid umb-property it finds in the form.. + * + * @param {object} form Pass in a form object. + */ + focusOnFirstError: function(form) { + var invalidNgForms = form.$$element.find(`.umb-property ng-form.ng-invalid, .umb-property-editor ng-form.ng-invalid-required`); + var firstInvalidNgForm = invalidNgForms.first(); + + if(firstInvalidNgForm.length !== 0) { + var focusableFields = [...firstInvalidNgForm.find("umb-range-slider .noUi-handle,input,textarea,select,button")]; + if(focusableFields.length !== 0) { + var firstErrorEl = focusableFields.find(el => el.type !== "hidden" && el.hasAttribute("readonly") === false); + if(firstErrorEl.length !== 0) { + firstErrorEl.focus(); + } + } + } + }, + /** * @ngdoc function * @name umbraco.services.formHelper#submitForm @@ -76,32 +101,18 @@ function formHelper(angularHelper, serverValidationManager, notificationsService * * @description * Called by controllers when a form has been successfully submitted, this ensures the correct events are raised. - * + * * @param {object} args An object containing arguments for form submission */ resetForm: function (args) { - - var currentForm; - if (!args) { throw "args cannot be null"; } if (!args.scope) { throw "args.scope cannot be null"; } - if (!args.formCtrl) { - //try to get the closest form controller - currentForm = angularHelper.getRequiredCurrentForm(args.scope); - } - else { - currentForm = args.formCtrl; - } - // Set the form state to pristine - currentForm.$setPristine(); - currentForm.$setUntouched(); - - args.scope.$broadcast(args.hasErrors ? "formSubmittedValidationFailed" : "formSubmitted", { scope: args.scope }); + args.scope.$broadcast("formSubmitted", { scope: args.scope }); }, showNotifications: function (args) { @@ -126,7 +137,7 @@ function formHelper(angularHelper, serverValidationManager, notificationsService * @description * Needs to be called when a form submission fails, this will wire up all server validation errors in ModelState and * add the correct messages to the notifications. If a server error has occurred this will show a ysod. - * + * * @param {object} err The error object returned from the http promise */ handleError: function (err) { @@ -165,7 +176,7 @@ function formHelper(angularHelper, serverValidationManager, notificationsService * * @description * This wires up all of the server validation model state so that valServer and valServerField directives work - * + * * @param {object} err The error object returned from the http promise */ handleServerValidation: function (modelState) { diff --git a/src/Umbraco.Web.UI.Client/src/common/services/iconhelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/iconhelper.service.js index 0fa2d0df1a..0d0135fff8 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/iconhelper.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/iconhelper.service.js @@ -3,7 +3,7 @@ * @name umbraco.services.iconHelper * @description A helper service for dealing with icons, mostly dealing with legacy tree icons **/ -function iconHelper($q, $timeout) { +function iconHelper($http, $q, $sce, $timeout, umbRequestHelper) { var converter = [ { oldIcon: ".sprNew", newIcon: "add" }, @@ -85,11 +85,15 @@ function iconHelper($q, $timeout) { { oldIcon: ".sprTreeDeveloperPython", newIcon: "icon-linux" } ]; + var collectedIcons; + var imageConverter = [ {oldImage: "contour.png", newIcon: "icon-umb-contour"} ]; - var collectedIcons; + var iconCache = []; + var liveRequests = []; + var allIconsRequested = false; return { @@ -154,9 +158,110 @@ function iconHelper($q, $timeout) { return false; }, - /** Return a list of icons, optionally filter them */ + /** Converts the icon from legacy to a new one if an old one is detected */ + convertFromLegacyIcon: function (icon) { + if (this.isLegacyIcon(icon)) { + //its legacy so convert it if we can + var found = _.find(converter, function (item) { + return item.oldIcon.toLowerCase() === icon.toLowerCase(); + }); + return (found ? found.newIcon : icon); + } + return icon; + }, + + convertFromLegacyImage: function (icon) { + var found = _.find(imageConverter, function (item) { + return item.oldImage.toLowerCase() === icon.toLowerCase(); + }); + return (found ? found.newIcon : undefined); + }, + + /** If we detect that the tree node has legacy icons that can be converted, this will convert them */ + convertFromLegacyTreeNodeIcon: function (treeNode) { + if (this.isLegacyTreeNodeIcon(treeNode)) { + return this.convertFromLegacyIcon(treeNode.icon); + } + return treeNode.icon; + }, + + /** Gets a single IconModel */ + getIcon: function(iconName) { + return $q((resolve, reject) => { + var icon = this._getIconFromCache(iconName); + + if(icon !== undefined) { + resolve(icon); + } else { + var iconRequestPath = Umbraco.Sys.ServerVariables.umbracoUrls.iconApiBaseUrl + 'GetIcon?iconName=' + iconName; + + // If the current icon is being requested, wait a bit so that we don't have to make another http request and can instead get the icon from the cache. + // This is a bit rough and ready and could probably be improved used an event based system + if(liveRequests.indexOf(iconRequestPath) >= 0) { + setTimeout(() => { + resolve(this.getIcon(iconName)); + }, 10); + } else { + liveRequests.push(iconRequestPath); + // TODO - fix bug where Umbraco.Sys.ServerVariables.umbracoUrls.iconApiBaseUrl is undefinied when help icon + umbRequestHelper.resourcePromise( + $http.get(iconRequestPath) + ,'Failed to retrieve icon: ' + iconName) + .then(icon => { + if(icon) { + var trustedIcon = { + name: icon.Name, + svgString: $sce.trustAsHtml(icon.SvgString) + }; + this._cacheIcon(trustedIcon); + + liveRequests = _.filter(liveRequests, iconRequestPath); + + resolve(trustedIcon); + } + }) + .catch(err => { + console.warn(err); + }); + }; + + } + }); + }, + + /** Gets all the available icons in the backoffice icon folder and returns them as an array of IconModels */ + getAllIcons: function() { + return $q((resolve, reject) => { + if(allIconsRequested === false) { + allIconsRequested = true; + + umbRequestHelper.resourcePromise( + $http.get(Umbraco.Sys.ServerVariables.umbracoUrls.iconApiBaseUrl + 'GetAllIcons') + ,'Failed to retrieve icons') + .then(icons => { + icons.forEach(icon => { + var trustedIcon = { + name: icon.Name, + svgString: $sce.trustAsHtml(icon.SvgString) + }; + + this._cacheIcon(trustedIcon); + }); + + resolve(iconCache); + }) + .catch(err => { + console.warn(err); + });; + } else { + resolve(iconCache); + } + }); + }, + + /** LEGACY - Return a list of icons from icon fonts, optionally filter them */ /** It fetches them directly from the active stylesheets in the browser */ - getIcons: function(){ + getLegacyIcons: function(){ var deferred = $q.defer(); $timeout(function(){ if(collectedIcons){ @@ -188,8 +293,13 @@ function iconHelper($q, $timeout) { s = s.substring(0, hasPseudo); } - if(collectedIcons.indexOf(s) < 0){ - collectedIcons.push(s); + var icon = { + name: s, + svgString: undefined + }; + + if(collectedIcons.indexOf(icon) < 0 && s !== "icon-chevron-up" && s !== "icon-chevron-down"){ + collectedIcons.push(icon); } } } @@ -198,35 +308,20 @@ function iconHelper($q, $timeout) { deferred.resolve(collectedIcons); } }, 100); - + return deferred.promise; }, - /** Converts the icon from legacy to a new one if an old one is detected */ - convertFromLegacyIcon: function (icon) { - if (this.isLegacyIcon(icon)) { - //its legacy so convert it if we can - var found = _.find(converter, function (item) { - return item.oldIcon.toLowerCase() === icon.toLowerCase(); - }); - return (found ? found.newIcon : icon); - } - return icon; + /** A simple cache to ensure that the icon is only requested from the server if is isn't already in memory */ + _cacheIcon: function(icon) { + if(_.find(iconCache, {name: icon.name}) === undefined) { + iconCache = _.union(iconCache, [icon]); + } }, - convertFromLegacyImage: function (icon) { - var found = _.find(imageConverter, function (item) { - return item.oldImage.toLowerCase() === icon.toLowerCase(); - }); - return (found ? found.newIcon : undefined); - }, - - /** If we detect that the tree node has legacy icons that can be converted, this will convert them */ - convertFromLegacyTreeNodeIcon: function (treeNode) { - if (this.isLegacyTreeNodeIcon(treeNode)) { - return this.convertFromLegacyIcon(treeNode.icon); - } - return treeNode.icon; + /** Returns the cached icon or undefined */ + _getIconFromCache: function(iconName) { + return _.find(iconCache, {name: iconName}); } }; } diff --git a/src/Umbraco.Web.UI.Client/src/common/services/mediahelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/mediahelper.service.js index 75c9dccc30..6e5ee82ec7 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/mediahelper.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/mediahelper.service.js @@ -435,11 +435,16 @@ function mediaHelper(umbRequestHelper, $http, $log) { imagePath, animationProcessMode: options.animationProcessMode, cacheBusterValue: options.cacheBusterValue, - focalPoint: options.focalPoint, + focalPointLeft: options.focalPoint.left, + focalPointTop: options.focalPoint.top, height: options.height, mode: options.mode, upscale: options.upscale || false, - width: options.width + width: options.width, + cropX1: options.crop.x1, + cropX2: options.crop.x2, + cropY1: options.crop.y1, + cropY2: options.crop.y2 })), "Failed to retrieve processed image URL for image: " + imagePath); } diff --git a/src/Umbraco.Web.UI.Client/src/common/services/navigation.service.js b/src/Umbraco.Web.UI.Client/src/common/services/navigation.service.js index f903c44ad5..2a5d182a59 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/navigation.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/navigation.service.js @@ -169,7 +169,7 @@ function navigationService($routeParams, $location, $q, $injector, eventsService //if the routing parameter keys are the same, we'll compare their values to see if any have changed and if so then the routing will be allowed. if (diff1.length === 0 && diff2.length === 0) { var partsChanged = 0; - _.each(currRoutingKeys, function (k) { + currRoutingKeys.forEach(k => { if (currUrlParams[k] != nextUrlParams[k]) { partsChanged++; } @@ -206,7 +206,8 @@ function navigationService($routeParams, $location, $q, $injector, eventsService var toRetain = _.union(retainedQueryStrings, toRetain); var currentSearch = $location.search(); $location.search(''); - _.each(toRetain, function (k) { + + toRetain.forEach(k => { if (currentSearch[k]) { $location.search(k, currentSearch[k]); } @@ -240,7 +241,7 @@ function navigationService($routeParams, $location, $q, $injector, eventsService var toRetain = Utilities.copy(nextRouteParams); var updated = false; - _.each(retainedQueryStrings, function (r) { + retainedQueryStrings.forEach(r => { // if mculture is set to null in nextRouteParams, the value will be undefined and we will not retain any query string that has a value of "null" if (currRouteParams[r] && nextRouteParams[r] !== undefined && !nextRouteParams[r]) { toRetain[r] = currRouteParams[r]; diff --git a/src/Umbraco.Web.UI.Client/src/common/services/overlay.service.js b/src/Umbraco.Web.UI.Client/src/common/services/overlay.service.js index 123845a63b..ea05dad4e7 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/overlay.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/overlay.service.js @@ -8,14 +8,14 @@ (function () { "use strict"; - function overlayService(eventsService, backdropService) { + function overlayService(eventsService, backdropService, focusLockService) { var currentOverlay = null; function open(newOverlay) { // prevent two open overlays at the same time - if(currentOverlay) { + if (currentOverlay) { close(); } @@ -23,32 +23,34 @@ var overlay = newOverlay; // set the default overlay position to center - if(!overlay.position) { + if (!overlay.position) { overlay.position = "center"; } // set the default overlay size to small - if(!overlay.size) { + if (!overlay.size) { overlay.size = "small"; } // use a default empty view if nothing is set - if(!overlay.view) { + if (!overlay.view) { overlay.view = "views/common/overlays/default/default.html"; } // option to disable backdrop clicks - if(overlay.disableBackdropClick) { + if (overlay.disableBackdropClick) { backdropOptions.disableEventsOnClick = true; } overlay.show = true; + focusLockService.addInertAttribute(); backdropService.open(backdropOptions); currentOverlay = overlay; eventsService.emit("appState.overlay", overlay); } function close() { + focusLockService.removeInertAttribute(); backdropService.close(); currentOverlay = null; eventsService.emit("appState.overlay", null); @@ -90,7 +92,6 @@ } open(overlay); - } function confirmDelete(overlay) { diff --git a/src/Umbraco.Web.UI.Client/src/common/services/search.service.js b/src/Umbraco.Web.UI.Client/src/common/services/search.service.js index fef286ec7e..803cd857b7 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/search.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/search.service.js @@ -21,8 +21,8 @@ * */ angular.module('umbraco.services') - .factory('searchService', function ($q, $log, entityResource, contentResource, umbRequestHelper, $injector, searchResultFormatter) { - + .factory('searchService', function (entityResource, $injector, searchResultFormatter) { + return { /** @@ -42,12 +42,11 @@ angular.module('umbraco.services') throw "args.term is required"; } - return entityResource.search(args.term, "Member", args.searchFrom).then(function (data) { - _.each(data, function (item) { - searchResultFormatter.configureMemberResult(item); + return entityResource.search(args.term, "Member", args.searchFrom) + .then(data => { + data.forEach(item => searchResultFormatter.configureMemberResult(item)); + return data; }); - return data; - }); }, /** @@ -67,12 +66,11 @@ angular.module('umbraco.services') throw "args.term is required"; } - return entityResource.search(args.term, "Document", args.searchFrom, args.canceler, args.dataTypeKey).then(function (data) { + return entityResource.search(args.term, "Document", args.searchFrom, args.canceler, args.dataTypeKey) _.each(data, function (item) { - searchResultFormatter.configureContentResult(item); + data.forEach(item => searchResultFormatter.configureContentResult(item)); + return data; }); - return data; - }); }, /** @@ -92,12 +90,11 @@ angular.module('umbraco.services') throw "args.term is required"; } - return entityResource.search(args.term, "Media", args.searchFrom, args.canceler, args.dataTypeKey).then(function (data) { - _.each(data, function (item) { - searchResultFormatter.configureMediaResult(item); + return entityResource.search(args.term, "Media", args.searchFrom, args.canceler, args.dataTypeKey) + .then(data => { + data.forEach(item => searchResultFormatter.configureMediaResult(item)); + return data; }); - return data; - }); }, /** @@ -117,10 +114,8 @@ angular.module('umbraco.services') throw "args.term is required"; } - return entityResource.searchAll(args.term, args.canceler).then(function (data) { - - _.each(data, function (resultByType) { - + return entityResource.searchAll(args.term, args.canceler).then(data => { + Object.values(data).forEach(resultByType => { //we need to format the search result data to include things like the subtitle, urls, etc... // this is done with registered angular services as part of the SearchableTreeAttribute, if that // is not found, than we format with the default formatter @@ -140,7 +135,7 @@ angular.module('umbraco.services') } } //now apply the formatter for each result - _.each(resultByType.results, function (item) { + resultByType.results.forEach(item => { formatterMethod.apply(this, [item, resultByType.treeAlias, resultByType.appAlias]); }); @@ -148,12 +143,10 @@ angular.module('umbraco.services') return data; }); - }, // TODO: This doesn't do anything! setCurrent: function (sectionAlias) { - var currentSection = sectionAlias; } }; diff --git a/src/Umbraco.Web.UI.Client/src/common/services/tinymce.service.js b/src/Umbraco.Web.UI.Client/src/common/services/tinymce.service.js index 9945396262..5d6b4646a3 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/tinymce.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/tinymce.service.js @@ -1372,6 +1372,9 @@ function tinyMceService($rootScope, $q, imageHelper, $locale, $http, $timeout, s // throw "args.model.value is required"; //} + // force TinyMCE to load plugins/themes from minified files (see http://archive.tinymce.com/wiki.php/api4:property.tinymce.suffix.static) + args.editor.suffix = ".min"; + var unwatch = null; //Starts a watch on the model value so that we can update TinyMCE if the model changes behind the scenes or from the server @@ -1516,6 +1519,8 @@ function tinyMceService($rootScope, $q, imageHelper, $locale, $http, $timeout, s }); args.editor.on('Dirty', function (e) { + syncContent(); // Set model.value to the RTE's content + //make the form dirty manually so that the track changes works, setting our model doesn't trigger // the angular bits because tinymce replaces the textarea. if (args.currentForm) { diff --git a/src/Umbraco.Web.UI.Client/src/common/services/tree.service.js b/src/Umbraco.Web.UI.Client/src/common/services/tree.service.js index 0d6216f7cc..37485ea7eb 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/tree.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/tree.service.js @@ -54,7 +54,7 @@ function treeService($q, treeResource, iconHelper, notificationsService, eventsS //take the last child var childPath = this.getPath(node.children[node.children.length - 1]).join(","); //check if this already exists, if so exit - if (expandedPaths.indexOf(childPath) !== -1) { + if (expandedPaths.includes(childPath)) { return; } @@ -65,18 +65,18 @@ function treeService($q, treeResource, iconHelper, notificationsService, eventsS var clonedPaths = expandedPaths.slice(0); //make a copy to iterate over so we can modify the original in the iteration - _.each(clonedPaths, function (p) { + clonedPaths.forEach(p => { if (childPath.startsWith(p + ",")) { //this means that the node's path supercedes this path stored so we can remove the current 'p' and replace it with node.path expandedPaths.splice(expandedPaths.indexOf(p), 1); //remove it - if (expandedPaths.indexOf(childPath) === -1) { + if (expandedPaths.includes(childPath) === false) { expandedPaths.push(childPath); //replace it } } else if (p.startsWith(childPath + ",")) { //this means we've already tracked a deeper node so we shouldn't track this one } - else if (expandedPaths.indexOf(childPath) === -1) { + else if (expandedPaths.includes(childPath) === false) { expandedPaths.push(childPath); //track it } }); diff --git a/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js index 90125e7de6..78c8b5fa88 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js @@ -264,9 +264,7 @@ function umbRequestHelper($http, $q, notificationsService, eventsService, formHe //reset the tabs and set the active one if (response.data.tabs && response.data.tabs.length > 0) { - _.each(response.data.tabs, function (item) { - item.active = false; - }); + response.data.tabs.forEach(item => item.active = false); response.data.tabs[activeTabIndex].active = true; } @@ -327,7 +325,7 @@ function umbRequestHelper($http, $q, notificationsService, eventsService, formHe if (!jsonData) { throw "jsonData cannot be null"; } if (Utilities.isArray(jsonData)) { - _.each(jsonData, function (item) { + jsonData.forEach(item => { if (!item.key || !item.value) { throw "jsonData array item must have both a key and a value property"; } }); } @@ -345,7 +343,7 @@ function umbRequestHelper($http, $q, notificationsService, eventsService, formHe var formData = new FormData(); //add the json data if (Utilities.isArray(data)) { - _.each(data, function(item) { + data.forEach(item => { formData.append(item.key, !Utilities.isString(item.value) ? Utilities.toJson(item.value) : item.value); }); } diff --git a/src/Umbraco.Web.UI.Client/src/common/services/usershelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/usershelper.service.js index 1bda86c3b3..e6450798fb 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/usershelper.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/usershelper.service.js @@ -12,36 +12,23 @@ { "value": 4, "name": "Inactive", "key": "Inactive", "color": "warning" } ]; - localizationService.localizeMany(_.map(userStates, function (userState) { - return "user_state" + userState.key; - })).then(function (data) { - var reg = /^\[[\S\s]*]$/g; - _.each(data, function (value, index) { - if (!reg.test(value)) { - // Only translate if key exists - userStates[index].name = value; - } + localizationService.localizeMany(userStates.map(userState => "user_state" + userState.key)) + .then(data => { + var reg = /^\[[\S\s]*]$/g; + data.forEach((value, index) => { + if (!reg.test(value)) { + // Only translate if key exists + userStates[index].name = value; + } + }); }); - }); - function getUserStateFromValue(value) { - var foundUserState; - angular.forEach(userStates, function (userState) { - if(userState.value === value) { - foundUserState = userState; - } - }); - return foundUserState; + function getUserStateFromValue(value) { + return userStates.find(userState => userState.value === value); } function getUserStateByKey(key) { - var foundUserState; - angular.forEach(userStates, function (userState) { - if(userState.key === key) { - foundUserState = userState; - } - }); - return foundUserState; + return userStates.find(userState => userState.key === key); } function getUserStatesFilter(userStatesObject) { @@ -49,7 +36,7 @@ var userStatesFilter = []; for (var key in userStatesObject) { - if (userStatesObject.hasOwnProperty(key)) { + if (hasOwnProperty.call(userStatesObject, key)) { var userState = getUserStateByKey(key); if(userState) { userState.count = userStatesObject[key]; @@ -59,7 +46,6 @@ } return userStatesFilter; - } //////////// @@ -71,10 +57,7 @@ }; return service; - } angular.module('umbraco.services').factory('usersHelper', usersHelperService); - - })(); diff --git a/src/Umbraco.Web.UI.Client/src/common/services/util.service.js b/src/Umbraco.Web.UI.Client/src/common/services/util.service.js index 82353df744..1fb5884d4c 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/util.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/util.service.js @@ -173,9 +173,9 @@ function umbModelMapper() { /** This converts the source model to a basic entity model, it will throw an exception if there isn't enough data to create the model */ convertToEntityBasic: function (source) { var required = ["id", "name", "icon", "parentId", "path"]; - _.each(required, function (k) { - if (!_.has(source, k)) { - throw "The source object does not contain the property " + k; + required.forEach(k => { + if (!hasOwnProperty.call(source, k)) { + throw `The source object does not contain the property ${k}`; } }); var optional = ["metaData", "key", "alias"]; diff --git a/src/Umbraco.Web.UI.Client/src/installer/steps/database.html b/src/Umbraco.Web.UI.Client/src/installer/steps/database.html index fc870858cf..cfe0940aa2 100644 --- a/src/Umbraco.Web.UI.Client/src/installer/steps/database.html +++ b/src/Umbraco.Web.UI.Client/src/installer/steps/database.html @@ -1,118 +1,121 @@
    -

    Configure your database

    -

    - Enter connection and authentication details for the database you want to install Umbraco on -

    +

    Configure your database

    +

    + Enter connection and authentication details for the database you want to install Umbraco on +

    -
    -
    - What type of database do you use? - -
    - -
    -
    + +
    + What type of database do you use? + +
    + +
    +
    -
    +

    Great! No need to configure anything, you can simply click the continue button below to continue to the next step

    -
    +
    -
    - What is the exact connection string we should use? -
    - -
    - - - Enter a valid database connection string. -
    -
    -
    - -
    -
    - Where do we find your database? -
    -
    - -
    - - Enter server domain or IP -
    -
    -
    - -
    -
    - -
    - - Enter the name of the database -
    -
    -
    -
    - -
    - What credentials are used to access the database? -
    -
    - -
    - - Enter the database user name -
    -
    -
    - -
    -
    - -
    - - Enter the database password -
    -
    -
    - -
    -
    - -
    -
    -
    -
    - -
    -
    -
    - - - - - - Validating your database connection... - - - - Could not connect to database - +
    + What is the exact connection string we should use? +
    + +
    + + Enter a valid database connection string.
    -
    -
    +
    +
    +
    +
    + Where do we find your database? +
    +
    + +
    + + Enter server domain or IP +
    +
    +
    - +
    +
    + +
    + + Enter the name of the database +
    +
    +
    +
    + +
    + What credentials are used to access the database? +
    +
    + +
    + + Enter the database user name +
    +
    +
    + +
    +
    + +
    + + Enter the database password +
    +
    +
    + +
    +
    + +
    +
    +
    +
    + +
    +
    +
    + + + + + + Validating your database connection... + + + + Could not connect to database + +
    +
    +
    +
    diff --git a/src/Umbraco.Web.UI.Client/src/less/belle.less b/src/Umbraco.Web.UI.Client/src/less/belle.less index cdccbf527b..d99573decb 100644 --- a/src/Umbraco.Web.UI.Client/src/less/belle.less +++ b/src/Umbraco.Web.UI.Client/src/less/belle.less @@ -147,6 +147,7 @@ @import "components/umb-color-swatches.less"; @import "components/check-circle.less"; @import "components/umb-file-icon.less"; +@import "components/umb-icon.less"; @import "components/umb-iconpicker.less"; @import "components/umb-insert-code-box.less"; @import "components/umb-packages.less"; @@ -174,11 +175,13 @@ @import "components/umb-dropdown.less"; @import "components/umb-range-slider.less"; @import "components/umb-number.less"; +@import "components/umb-tags-editor.less"; @import "components/buttons/umb-button.less"; @import "components/buttons/umb-button-group.less"; @import "components/buttons/umb-toggle.less"; @import "components/buttons/umb-toggle-group.less"; +@import "components/buttons/umb-button-ellipsis.less"; @import "components/notifications/umb-notifications.less"; @import "components/umb-file-dropzone.less"; diff --git a/src/Umbraco.Web.UI.Client/src/less/buttons.less b/src/Umbraco.Web.UI.Client/src/less/buttons.less index 2b50b60ae8..2caa223647 100644 --- a/src/Umbraco.Web.UI.Client/src/less/buttons.less +++ b/src/Umbraco.Web.UI.Client/src/less/buttons.less @@ -336,20 +336,17 @@ input[type="submit"].btn { // This is lifted from umb-group-builder.less .btn-icon { - border: none; - + border: none; font-size: 18px; position: relative; cursor: pointer; color: @ui-icon; - margin: 0; padding: 5px 10px; width: auto; overflow: visible; background: transparent; line-height: normal; - outline: 0; -webkit-appearance: none; &:hover { diff --git a/src/Umbraco.Web.UI.Client/src/less/colors.less b/src/Umbraco.Web.UI.Client/src/less/colors.less index 4cb70cdf5e..ba4909c997 100644 --- a/src/Umbraco.Web.UI.Client/src/less/colors.less +++ b/src/Umbraco.Web.UI.Client/src/less/colors.less @@ -24,7 +24,7 @@ /* Colors based on https://zavoloklom.github.io/material-design-color-palette/colors.html */ .btn-color-black {background-color: @black;} -.color-black i { color: @black;} +.color-black, .color-black i { color: @black !important;} .btn-color-blue-grey {background-color: @blueGrey;} .color-blue-grey, .color-blue-grey i { color: @blueGrey !important;} @@ -78,4 +78,4 @@ .color-deep-purple, .color-deep-purple i { color: @deepPurpleIcon !important; } .btn-color-indigo{background-color: @indigoIcon;} -.color-indigo, .color-indigo i { color: @indigoIcon !important; } \ No newline at end of file +.color-indigo, .color-indigo i { color: @indigoIcon !important; } diff --git a/src/Umbraco.Web.UI.Client/src/less/components/buttons/umb-button-ellipsis.less b/src/Umbraco.Web.UI.Client/src/less/components/buttons/umb-button-ellipsis.less new file mode 100644 index 0000000000..54302ba869 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/less/components/buttons/umb-button-ellipsis.less @@ -0,0 +1,76 @@ +.umb-button-ellipsis{ + padding: 0 5px; + text-align: center; + margin: 0 auto; + cursor: pointer; + border-radius: @baseBorderRadius; + color: black; + position: relative; + opacity: 0.8; + transition: opacity .3s ease-out; + + &--absolute { + position: absolute; + } + + &--small { + height: 15px; + } + + &.show-text { + display: flex; + flex-wrap: wrap; + justify-content: center; + } + + .umb-button-ellipsis--tab, + .umb-tour-is-visible .umb-tree &, + &:hover, + &:focus{ + opacity: 1; + } + + &--hidden{ + opacity: 0; + + &:hover, + &:focus { + opacity: 1; + } + } + + &__content { + display: flex; + flex-wrap: wrap; + } + + &__icon { + color: inherit; + flex-basis: 100%; + + .umb-button-ellipsis--tab & { + margin: 0 0 7px; + } + + .umb-button-ellipsis--small & { + font-size: 8px; + position: relative; + top: -2px; + } + } + + &__text { + color: inherit; + font-size: 12px; + line-height: 1em; + flex-basis: 100%; + + .umb-button-ellipsis--tab & { + position: absolute; + right: 0; + left: 0; + bottom: 13px; + margin: 0 auto; + } + } +} diff --git a/src/Umbraco.Web.UI.Client/src/less/components/buttons/umb-button-group.less b/src/Umbraco.Web.UI.Client/src/less/components/buttons/umb-button-group.less index 02b67460f6..24800c1142 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/buttons/umb-button-group.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/buttons/umb-button-group.less @@ -14,7 +14,7 @@ display: flex; } -.umb-button-group { +.umb-button-group.-with-button-group-toggle { .umb-button__button { border-radius: @baseBorderRadius 0 0 @baseBorderRadius; diff --git a/src/Umbraco.Web.UI.Client/src/less/components/buttons/umb-button.less b/src/Umbraco.Web.UI.Client/src/less/components/buttons/umb-button.less index 4127c2201c..d523b24141 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/buttons/umb-button.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/buttons/umb-button.less @@ -31,6 +31,11 @@ margin-left: 5px; } +.umb-button__button[disabled] .umb-button__caret { + border-top-color: @gray-7; + border-bottom-color: @gray-7; +} + .umb-button__progress { position: absolute; left: 50%; diff --git a/src/Umbraco.Web.UI.Client/src/less/components/buttons/umb-toggle.less b/src/Umbraco.Web.UI.Client/src/less/components/buttons/umb-toggle.less index ff4122b258..701af849cc 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/buttons/umb-toggle.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/buttons/umb-toggle.less @@ -41,9 +41,6 @@ } } - - - .umb-toggle__handler { position: absolute; top: 1px; @@ -59,10 +56,8 @@ transform: translateX(20px); background-color: @white; } - } - /* Icons */ .umb-toggle__icon { @@ -78,9 +73,7 @@ color:@white; transition: opacity 120ms; opacity: 0; - // .umb-toggle:hover & { - // color: @ui-btn-hover; - // } + .umb-toggle--checked & { opacity: 1; } @@ -93,6 +86,7 @@ right: 5px; color: @ui-btn; transition: opacity 120ms; + .umb-toggle--checked & { opacity: 0; } @@ -101,23 +95,41 @@ } } - - -.umb-toggle.umb-toggle--disabled.umb-toggle--checked, .umb-toggle.umb-toggle--disabled { .umb-toggle__toggle { cursor: not-allowed; - background-color: @gray-9; - border-color: @gray-9; } - .umb-toggle__icon--left { - color: @gray-6; + + &, &.umb-toggle--checked { + + .umb-toggle__toggle { + .umb-toggle__handler { + background-color: @gray-10; + } + } } - .umb-toggle__icon--right { - color: @gray-6; + + &:not(.umb-toggle--checked) { + .umb-toggle__toggle { + background-color: @gray-8; + border-color: @gray-8; + } + + .umb-toggle__icon--left, + .umb-toggle__icon--right { + color: @gray-6; + } } - .umb-toggle__handler { - background-color: @gray-10; + + &.umb-toggle--checked { + .umb-toggle__toggle { + background-color: lighten(@ui-btn, 50%); + border-color: lighten(@ui-btn, 50%); + } + .umb-toggle__icon--left, + .umb-toggle__icon--right { + color: @gray-9; + } } } diff --git a/src/Umbraco.Web.UI.Client/src/less/components/editor.less b/src/Umbraco.Web.UI.Client/src/less/components/editor.less index ac55c6ffb1..d4069cdd2b 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/editor.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/editor.less @@ -73,6 +73,11 @@ height: @editorHeaderHeight; } +.umb-editor-header .umb-button__button[disabled] { + // do not dim down the background color of disabled buttons in the header + background-color: unset; +} + .umb-editor-header__back { background: transparent; border: 0; @@ -135,22 +140,19 @@ input.umb-editor-header__name-input:disabled { margin-left: auto; } -a.umb-editor-header__close-split-view { - +.umb-editor-header__close-split-view { display: flex; justify-content: center; align-items: center; position: relative; height: 69px; width: 69px; - - font-size: 20px; - color: @gray-6; - text-decoration: none !important; -} + font-size: 20px; + color: @gray-6; -a.umb-editor-header__close-split-view:hover { - color: @black; + &:hover { + color: @black; + } } .umb-editor-header { @@ -162,9 +164,7 @@ a.umb-editor-header__close-split-view:hover { } } - // container - .umb-editor-container { position: absolute; top: @editorHeaderHeight; diff --git a/src/Umbraco.Web.UI.Client/src/less/components/editor/umb-variant-switcher.less b/src/Umbraco.Web.UI.Client/src/less/components/editor/umb-variant-switcher.less index eae25b273c..95625d9e73 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/editor/umb-variant-switcher.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/editor/umb-variant-switcher.less @@ -90,6 +90,7 @@ button.umb-variant-switcher__toggle { align-items: center; border-bottom: 1px solid @gray-9; position: relative; + .umb-variant-switcher__name-wrapper:hover { .umb-variant-switcher__name { color: @blueMid; @@ -99,6 +100,11 @@ button.umb-variant-switcher__toggle { } } } + +.umb-variant-switcher__item.--not-allowed:not(.--current) .umb-variant-switcher__name-wrapper:hover { + cursor: default; +} + .umb-variant-switcher__item.--state-notCreated:not(.--active) { .umb-variant-switcher__name-wrapper::before { content: "+"; @@ -106,38 +112,44 @@ button.umb-variant-switcher__toggle { float: left; font-size: 15px; font-weight: 900; - padding: 8px 16px 8px 6px; + padding: 8px 12px 8px 0; color: @gray-5; } + .umb-variant-switcher__item-expand-button + .umb-variant-switcher__name-wrapper::before { padding: 8px 16px 8px 20px; } + .umb-variant-switcher__name { color: @gray-5; } + .umb-variant-switcher__state { color: @gray-6; } + .umb-variant-switcher__name-wrapper::after { content: ""; position: absolute; z-index: 1; - border: 1px dashed @gray-9; - top: 7px; - bottom: 7px; - left: 7px; - right: 7px; - border-radius: 3px; + border: 2px dashed @gray-9; + margin: 2px; + top: 0; + bottom: 0; + left: 0; + right: 0; pointer-events: none; } - + .umb-variant-switcher__name-wrapper:hover { &::before { color: @blueMid; } + .umb-variant-switcher__name { color: @blueMid; } + .umb-variant-switcher__state { color: @blueMid; } @@ -183,8 +195,11 @@ button.umb-variant-switcher__toggle { } .umb-variant-switcher__item.--current { - //color: @ui-light-active-type; + color: @ui-light-active-type; //background-color: @pinkExtraLight; + .umb-variant-switcher__name-wrapper { + border-left: 4px solid @ui-active; + } .umb-variant-switcher__name { //color: @ui-light-active-type; font-weight: 700; @@ -216,7 +231,7 @@ button.umb-variant-switcher__toggle { .umb-variant-switcher__item:focus-within .umb-variant-switcher__split-view, .umb-variant-switcher__item:hover .umb-variant-switcher__split-view, .umb-variant-switcher__split-view:focus { - display: block; + display: flex; cursor: pointer; } @@ -263,7 +278,10 @@ button.umb-variant-switcher__toggle { cursor: pointer; background-color: transparent; border: none; + padding-top: 6px !important; + padding-bottom: 6px !important; } + .dropdown-menu>li { > .umb-variant-switcher__name-wrapper { padding-top: 10px; @@ -290,7 +308,7 @@ button.umb-variant-switcher__toggle { .umb-variant-switcher__split-view { font-size: 12px; display: none; - padding: 20px 20px; + padding: 16px 20px; position: absolute; right: 0; top: 0; @@ -303,7 +321,6 @@ button.umb-variant-switcher__toggle { } } - .umb-variant-switcher__sub-variants { position: relative; diff --git a/src/Umbraco.Web.UI.Client/src/less/components/overlays.less b/src/Umbraco.Web.UI.Client/src/less/components/overlays.less index 25bfc2fce5..035bf02f91 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/overlays.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/overlays.less @@ -106,7 +106,6 @@ height: auto; top: 50%; left: 50%; - transform: translate(-50%, 0); transform: translate(-50%, -50%); border-radius: @baseBorderRadius; } @@ -128,6 +127,7 @@ width: 400px; max-height: 100vh; box-sizing: border-box; + visibility: hidden; border-radius: @baseBorderRadius; &.umb-overlay--small { diff --git a/src/Umbraco.Web.UI.Client/src/less/components/tree/umb-tree-item.less b/src/Umbraco.Web.UI.Client/src/less/components/tree/umb-tree-item.less index 4a483ce3f0..97caf66497 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/tree/umb-tree-item.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/tree/umb-tree-item.less @@ -17,8 +17,9 @@ .umb-tree-item__arrow { position: relative; margin-left: -16px; - width: 16px; - height: 16px; + margin-right: 4px; + width: 12px; + height: 12px; visibility: hidden; text-decoration: none; font-size: 12px; diff --git a/src/Umbraco.Web.UI.Client/src/less/components/tree/umb-tree.less b/src/Umbraco.Web.UI.Client/src/less/components/tree/umb-tree.less index 839e61c5f9..59d81eb3ea 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/tree/umb-tree.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/tree/umb-tree.less @@ -15,6 +15,16 @@ text-decoration: none; } + .umb-tree-item__arrow { + visibility: hidden; + text-decoration: none; + font-size: 12px; + transition: color 120ms; + + &:hover { + color: @ui-option-type-hover; + } + } i.noSpr { display: inline-block; margin-top: 1px; @@ -75,8 +85,8 @@ body.touch .umb-tree { &:hover { background: @ui-option-hover; - color: @ui-option-type-hover; + a { color: @ui-option-type-hover; } @@ -85,11 +95,15 @@ body.touch .umb-tree { position: relative; width: auto; height: auto; - margin: 0 10px 0 auto; - padding: 9px 5px; + margin: 0 5px 0 auto; + padding: 7px 5px; overflow: visible; clip: auto; } + + .umb-button-ellipsis--hidden { + opacity: 1; + } .umb-tree-icon { color: @ui-option-type-hover; @@ -171,9 +185,9 @@ body.touch .umb-tree { display: flex; flex: 0 0 auto; justify-content: flex-end; - padding: 9px 5px; + padding: 7px 5px; text-align: center; - margin: 0 10px 0 auto; + margin: 0 5px 0 auto; cursor: pointer; border-radius: @baseBorderRadius; @@ -184,18 +198,20 @@ body.touch .umb-tree { display: inline-block; margin: 0 2px 0 0; background: @ui-active-type; - + &:last-child { margin: 0; } } + &:hover { background: rgba(255, 255, 255, .5); + i { background: @ui-active-type-hover; } } - + // NOTE - We're having to repeat ourselves here due to an .sr-only class appearing in umbraco/lib/font-awesome/css/font-awesome.min.css &.sr-only--hoverable:hover, &.sr-only--focusable:focus { @@ -203,9 +219,9 @@ body.touch .umb-tree { display: flex; flex: 0 0 auto; justify-content: flex-end; - padding: 9px 5px; + padding: 7px 5px; text-align: center; - margin: 0 10px 0 auto; + margin: 0 auto; cursor: pointer; border-radius: 3px; } diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-badge.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-badge.less index 9a18bef2de..d79bbbde20 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-badge.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-badge.less @@ -29,6 +29,11 @@ color: @white; } +.umb-badge--info { + background-color: @blue; + color: @white; +} + .umb-badge--warning { background-color: @orange; color: @white; @@ -39,6 +44,11 @@ color: @white; } +.umb-badge--dark { + background-color: @grayDark; + color: @white; +} + // Size .umb-badge--xxs { font-size: 11px; diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-code-snippet.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-code-snippet.less index b372841910..96b4fc08c8 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-code-snippet.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-code-snippet.less @@ -18,6 +18,7 @@ justify-content: flex-start; flex-grow: 1; padding: 2px 10px; + text-transform: uppercase; } button { diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-confirm-action.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-confirm-action.less index f972633bf4..a6548123ac 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-confirm-action.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-confirm-action.less @@ -1,3 +1,8 @@ +//WRAPPER +.umb_confirm-action { + display: inline-block; +} + // OVERLAY .umb_confirm-action__overlay { position: absolute; @@ -13,19 +18,6 @@ left: 0; animation: fadeInUp 0.2s; flex-direction: column; - - .umb_confirm-action__overlay-action { - margin-bottom: 5px; - } - - .umb_confirm-action__overlay-action.-confirm { - order: 1; - } - - .umb_confirm-action__overlay-action.-cancel { - order: 2; - } - } .umb_confirm-action__overlay.-right { @@ -35,18 +27,6 @@ left: auto; animation: fadeInLeft 0.2s; flex-direction: row; - - .umb_confirm-action__overlay-action { - margin-left: 5px; - } - - .umb_confirm-action__overlay-action.-confirm { - order: 2; - } - - .umb_confirm-action__overlay-action.-cancel { - order: 1; - } } .umb_confirm-action__overlay.-bottom { @@ -56,18 +36,6 @@ left: 0; animation: fadeInDown 0.2s; flex-direction: column; - - .umb_confirm-action__overlay-action { - margin-top: 5px; - } - - .umb_confirm-action__overlay-action.-confirm { - order: 2; - } - - .umb_confirm-action__overlay-action.-cancel { - order: 1; - } } .umb_confirm-action__overlay.-left { @@ -77,55 +45,59 @@ left: -50px; animation: fadeInRight 0.2s; flex-direction: row; +} + +.umb_confirm-action__overlay { .umb_confirm-action__overlay-action { margin-right: 5px; + + &.-confirm { + order: 1; + } + + &.-cancel { + order: 2; + } } - .umb_confirm-action__overlay-action.-confirm { - order: 1; - } + // BUTTONS + .umb_confirm-action__overlay-action { + width: 20px; + height: 20px; + display: flex; + align-items: center; + justify-content: center; + color: @white; + border-radius: 40px; + box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.26); + font-size: 18px; + cursor: pointer; + user-select: none; - .umb_confirm-action__overlay-action.-cancel { - order: 2; + &:hover { + text-decoration: none; + color: @white; + } + + // confirm button + &.-confirm { + background: @white; + color: @green !important; + + &:hover { + color: @green !important; + } + } + + // cancel button + &.-cancel { + background: @white; + color: @red !important; + + &:hover { + color: @red !important; + } + } } } - -// BUTTONS -.umb_confirm-action__overlay-action { - width: 20px; - height: 20px; - display: flex; - align-items: center; - justify-content: center; - color: @white; - border-radius: 40px; - box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.26); - font-size: 18px; - cursor: pointer; -} - -.umb_confirm-action__overlay-action:hover { - text-decoration: none; - color: @white; -} - -// confirm button -.umb_confirm-action__overlay-action.-confirm { - background: @white; - color: @green !important; -} - -.umb_confirm-action__overlay-action.-confirm:hover { - color: @green !important; -} - -// cancel button -.umb_confirm-action__overlay-action.-cancel { - background: @white; - color: @red !important; -} - -.umb_confirm-action__overlay-action.-cancel:hover { - color: @red !important; -} diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-date-time-picker.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-date-time-picker.less index 5bcfdd1c71..b8084bc435 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-date-time-picker.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-date-time-picker.less @@ -3,23 +3,28 @@ box-shadow: 0 5px 10px 0 rgba(0,0,0,0.16); } -span.flatpickr-day { +.flatpickr-day { border-radius: @baseBorderRadius; border: none; &.today:not(.active) { border: 1px solid; } -} -span.flatpickr-day:hover { - background-color: @gray-10; -} + &:hover { + background-color: @gray-10; + } -span.flatpickr-day.selected { - background-color: @ui-selected; -} + &.selected, &.startRange, &.endRange { + background-color: @ui-selected-type !important; + border-color: @ui-selected-type !important; -span.flatpickr-day.selected:hover { - background-color: @ui-selected-hover; + &:hover { + background-color: @ui-selected-type-hover !important; + } + + &.startRange + .endRange:not(:nth-child(7n+1)) { + box-shadow: -10px 0 0 @ui-selected-type !important; + } + } } diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-editor-navigation-item.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-editor-navigation-item.less index 2fc705b11b..641e0dc7a7 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-editor-navigation-item.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-editor-navigation-item.less @@ -46,7 +46,7 @@ } &.is-active { - color: @ui-light-active-type; + color: @ui-light-active-type !important; &::before { opacity: 1; @@ -93,8 +93,8 @@ .box-shadow(~"inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05)"); } - &:focus-within &__anchor_dropdown, - &:hover &__anchor_dropdown { + &:focus-within > &__anchor_dropdown, + &:hover > &__anchor_dropdown { visibility: visible; opacity: 1; transition: opacity 20ms 0; diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-form-check.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-form-check.less index 8a24d948ac..cff9980483 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-form-check.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-form-check.less @@ -1,25 +1,18 @@ @checkboxWidth: 18px; @checkboxHeight: 18px; -label.umb-form-check--checkbox{ - margin:3px 0; -} .umb-form-check { display: flex; + align-items: center; position: relative; - padding-left: 0px; - margin: 0; - min-height: 22px; + padding-left: 0; + margin: 5px 0; + min-height: 20px; cursor: pointer !important; - .umb-form-check__symbol { - margin-top: 4px; - margin-right: 10px; - } .umb-form-check__info { - margin-left:20px; + margin-left: 30px; position: relative; - top: 3px; } @@ -84,7 +77,6 @@ label.umb-form-check--checkbox{ } .tabbing-active &.umb-form-check--radiobutton &__input:focus ~ .umb-form-check__state .umb-form-check__check { - //outline: 2px solid @inputBorderTabFocus; border: 2px solid @inputBorderTabFocus; margin: -1px; } @@ -102,11 +94,10 @@ label.umb-form-check--checkbox{ &__state { display: flex; - height: 18px; + height: 20px; + width: 20px; position: absolute; - margin-top: 2px; - top: 0; - left: -1px; + top: -1px; } &__check { diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-grid.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-grid.less index 26d61412ae..a8c428ba7a 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-grid.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-grid.less @@ -751,9 +751,19 @@ margin-right: 5px; position: relative; cursor: pointer; - display:inline-block; + display: inline-block; } +.umb-grid .cell-tools, +.umb-grid .umb-control-tool { + .btn-icon { + padding: 0; + } +} + +.umb-grid .umb-control-tool .btn-icon { + color: @white; +} // Template @@ -1007,8 +1017,6 @@ display: block; } - - // Configuration specific styles // ------------------------- .umb-grid-configuration .umb-templates { diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-group-builder.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-group-builder.less index 6eded29b8b..2590e0610a 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-group-builder.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-group-builder.less @@ -347,23 +347,20 @@ input.umb-group-builder__group-title-input:disabled:hover { .umb-group-builder__property-actions { flex: 0 0 44px; display: flex; - align-items: center; + align-items: flex-start; justify-content: flex-end; } .umb-group-builder__property-action { - position: relative; margin: 5px 0; > button { border: none; - font-size: 18px; position: relative; cursor: pointer; color: @ui-icon; - margin: 0; padding: 5px 10px; width: auto; @@ -399,18 +396,21 @@ input.umb-group-builder__group-title-input:disabled:hover { padding: 0 4px; display: flex; border-radius: 3px; -} + align-items: center; -.umb-group-builder__property-tag:first-child { - margin-left: 0; -} + &:first-child { + margin-left: 0; + } -.umb-group-builder__property-tag.-white { - background-color: @white; + &.-white { + background-color: @white; + } } .umb-group-builder__property-tag-icon { margin-right: 3px; + display: flex; + align-items: center; } /* ---------- SORTABLE ---------- */ @@ -513,17 +513,14 @@ input.umb-group-builder__group-sort-value { display: flex; align-items: center; align-content: stretch; - min-height: 80px; - border: 1px solid @gray-9; color: @ui-action-discreet-type; border-radius: @baseBorderRadius; - } .editor-info { - flex: 1 0 auto; + flex: 1 1 auto; text-align: left; display: flex; align-items: center; @@ -537,6 +534,9 @@ input.umb-group-builder__group-sort-value { } .editor-icon-wrapper { + display: flex; + justify-content: center; + align-items: center; width: 60px; height: 60px; text-align: center; @@ -548,12 +548,12 @@ input.umb-group-builder__group-sort-value { font-size: 32px; } } - + .editor-details { flex: 1 1 auto; margin-top: 10px; margin-bottom: 10px; - + .editor-name { display: block; font-weight: bold; @@ -570,9 +570,9 @@ input.umb-group-builder__group-sort-value { width: 48px; height: 48px; font-size: 18px; - min-height: 80px; color: @ui-action-discreet-type; + &:hover { color: @ui-action-discreet-type-hover; background-color: @ui-action-discreet-hover; diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-icon.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-icon.less new file mode 100644 index 0000000000..e3b0550d15 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-icon.less @@ -0,0 +1,9 @@ +.umb-icon { + &:before, &:after { + content: none !important; + } + + > i { + font-family: inherit; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-iconpicker.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-iconpicker.less index 98b2b1d72d..e23325a7d2 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-iconpicker.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-iconpicker.less @@ -26,6 +26,11 @@ padding: 15px 0; text-decoration: none; border-radius: 3px; + background: none; + background: none; + border: none; + cursor: pointer; + color: currentColor; } .umb-iconpicker-item button:hover, @@ -41,34 +46,41 @@ box-sizing: border-box; } +.umb-iconpicker-svg svg { + display: block; + width: 30px; + height: 30px; + fill: currentColor; +} + .umb-iconpicker-item button:active { background: @gray-10; } .umb-iconpicker-item i { + font-family: inherit; font-size: 30px; } - // Color swatch .button { - border: none; - color: @white; - padding: 5px; - text-align: center; - text-decoration: none; - display: inline-block; - margin: 5px; - border-radius: 3px; - } + border: none; + color: @white; + padding: 5px; + text-align: center; + text-decoration: none; + display: inline-block; + margin: 5px; + border-radius: 3px; +} - // Circle behind the checkmark - i.small.active{ - font-size: 14px; - display: inline-block; - width: 20px; - height: 20px; - border-radius: 50%; - background-color: rgba(0,0,0,.15); - float: right; - } +// Circle behind the checkmark +i.small.active{ + font-size: 14px; + display: inline-block; + width: 20px; + height: 20px; + border-radius: 50%; + background-color: rgba(0,0,0,.15); + float: right; +} diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-list.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-list.less index 44955e8f8e..57ba73305a 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-list.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-list.less @@ -40,7 +40,7 @@ a.umb-list-item:focus { } .umb-list-item__description--checkbox{ - margin: 0 0 0 26px; + margin: 0 0 0 30px; } .umb-list-checkbox { diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-logviewer.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-logviewer.less index 8beff55b7c..56fa905310 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-logviewer.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-logviewer.less @@ -78,19 +78,22 @@ padding-right: 160px; } - .icon-rate { + .save-search, + .filter-search { position: absolute; top: 0; - line-height: 32px; + display: flex; + align-items: center;; + height: 32px; + } + + .save-search { right: 140px; color: @yellow-d1; cursor: pointer; } - .icon-wrong { - position: absolute; - top: 0; - line-height: 32px; + .filter-search { right: 120px; color: @gray-7; cursor: pointer; diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-media-grid.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-media-grid.less index 5d6b7ad962..abd1bfd047 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-media-grid.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-media-grid.less @@ -217,3 +217,19 @@ text-decoration: none; box-shadow: 0 1px 2px rgba(0,0,0,.2); } + +/*for the listview*/ + +.umb-media-grid__list-item.selected, .umb-media-grid__list-item.selected:hover, .umb-media-grid__list-item.selected:focus { + border: 2px solid #f5c1bc !important; +} + +.umb-media-grid__list-view .umb-table-cell.umb-table__name { + flex: 1 1 25%; + max-width: none; + white-space: normal; +} + +.umb-media-grid__list-view .umb-table-cell.umb-table__name .item-name { + white-space:normal; +} diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-mini-list-view.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-mini-list-view.less index 8cd08f5045..ecb1ad1904 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-mini-list-view.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-mini-list-view.less @@ -44,6 +44,10 @@ color: @black; } +.umb-minilistview { + overflow: hidden; +} + /* Animations */ .umb-mini-list-view.ng-animate { transition: 120ms cubic-bezier(0.250, 0.250, 0.750, 0.750) all; diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-multiple-textbox.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-multiple-textbox.less index 30a32b8123..39eb7e92e4 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-multiple-textbox.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-multiple-textbox.less @@ -1,9 +1,11 @@ -.umb-multiple-textbox{ - &__confirm{ +.umb-multiple-textbox { + .umb-property-editor--limit-width(); + + &__confirm { position: relative; display: inline-block; - &-action{ + &-action { margin: -2px 0 0 0; padding: 2px; background: transparent; @@ -12,10 +14,6 @@ } } -.umb-multiple-textbox .icon-wrapper { - width: 50px; -} - .umb-multiple-textbox .textbox-wrapper { align-items: center; margin-bottom: 15px; @@ -30,15 +28,10 @@ } .umb-multiple-textbox .textbox-wrapper i.handle { - margin-left: 5px; + margin-left: 10px; cursor: move; } -.umb-multiple-textbox .textbox-wrapper a.remove { - margin-left: 5px; - text-decoration: none; -} - .umb-multiple-textbox .add-link { &:extend(.umb-node-preview-add); } diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-nested-content.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-nested-content.less index 0f2b1402dc..384d9b4ac1 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-nested-content.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-nested-content.less @@ -210,7 +210,7 @@ .umb-nested-content__add-content.--disabled:hover { color: @gray-7; border-color: @gray-7; - cursor: default; + cursor: not-allowed; } diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-packages.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-packages.less index b808e6574a..197a5eb176 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-packages.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-packages.less @@ -59,15 +59,12 @@ .umb-package-link { display: block; - flex-wrap: wrap; - flex-direction: column; - justify-content: center; position: relative; box-sizing: border-box; height: 100%; width: 100%; border-radius: 3px; - border: 0 none; + border: 1px solid transparent; text-decoration: none !important; transition: border-color 100ms ease; background-color: @white; @@ -78,8 +75,6 @@ } } - - // Icon .umb-package-icon { display: flex; @@ -94,22 +89,20 @@ border-top-right-radius: 3px; border-top-left-radius: 3px; min-height: 60px; -} -.umb-package-icon img { - max-width: 70px; - width: 70px; - height: auto; + img { + max-width: 70px; + width: 70px; + height: auto; + } } - // Info .umb-package-info { padding: 15px; text-align: center; } - // Name .umb-package-name { font-size: 14px; diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-pagination.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-pagination.less index 8d3d563cab..f44aa645c4 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-pagination.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-pagination.less @@ -1,3 +1,5 @@ -.umb-pagination ul { - box-shadow: none; -} \ No newline at end of file +.umb-pagination { + ul { + box-shadow: none; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-property-actions.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-property-actions.less index 17c4bf1a55..f86b27af17 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-property-actions.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-property-actions.less @@ -85,7 +85,7 @@ .umb-contextmenu { border-top-left-radius: 0; - margin-top:1px; + margin-top:-2px; } diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-property-file-upload.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-property-file-upload.less index 39b2f4002e..83774e2dae 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-property-file-upload.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-property-file-upload.less @@ -14,6 +14,12 @@ color: @gray-8; } + &:focus-within { + .tabbing-active & { + box-shadow: 0 0 2px @ui-outline, inset 0 0 2px 1px @ui-outline; + } + } + i.icon { font-size: 55px; line-height: 70px @@ -26,4 +32,10 @@ width: 100%; } } + + .drag-over { + .umb-upload-button-big { + border-color: @gray-1; + } + } } diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-stylesheet.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-stylesheet.less index 38ceba2a59..36d9913d66 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-stylesheet.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-stylesheet.less @@ -41,6 +41,7 @@ textarea.umb-stylesheet-rule-styles { width: 300px; height: 100px; resize: none; + font-family: @monoFontFamily; } .umb-stylesheet-rule-preview { diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-table.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-table.less index 202c488bb4..d0427cad0a 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-table.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-table.less @@ -164,7 +164,7 @@ input.umb-table__input { } } -.umb-table-body__icon { +.umb-table-body .umb-table-body__icon { margin: 0 auto; font-size: 20px; line-height: 20px; @@ -173,7 +173,7 @@ input.umb-table__input { text-decoration: none; } -.umb-table-body__checkicon { +.umb-table-body .umb-table-body__icon.umb-table-body__checkicon { display: none; font-size: 18px; line-height: 20px; @@ -218,15 +218,15 @@ input.umb-table__input { } // Show checkmark when checked, hide file icon -.umb-table-row.-selected { - - .umb-table-body__fileicon { - display: none; - } - .umb-table-body__checkicon { - display: inline-block; - } - +.umb-table-body .umb-table-row.-selected { + .umb-table-body__icon { + &.umb-table-body__fileicon { + display: none; + } + &.umb-table-body__checkicon { + display: inline-block; + } + } } // Table Row Styles diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-tags-editor.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-tags-editor.less new file mode 100644 index 0000000000..9a80aa4ff3 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-tags-editor.less @@ -0,0 +1,53 @@ +.umb-tags-editor { + border: @inputBorder solid 1px; + padding: 5px; + min-height: 54px; + font-size: 13px; + text-shadow: none; + box-sizing: border-box; + + .tag { + cursor: default; + margin: 10px; + padding: 10px 15px; + background: @blueExtraDark; + position: relative; + user-select: all; + + .umb_confirm-action { + + > .btn-icon { + color: @white; + padding: 0; + position: relative; + cursor: pointer; + padding-left: 2px; + font-size: 15px; + right: -5px; + bottom: -1px; + user-select: none; + } + + .umb_confirm-action__overlay.-left { + top: 8px; + left: auto; + right: 15px; + } + } + } + + input { + border: none; + background: @white; + } + + .twitter-typeahead { + margin: 10px; + margin-top: 16px; + vertical-align: top; + + input { + padding-left: 0; + } + } +} diff --git a/src/Umbraco.Web.UI.Client/src/less/components/users/umb-user-preview.less b/src/Umbraco.Web.UI.Client/src/less/components/users/umb-user-preview.less index f62f3afd37..d0dca54403 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/users/umb-user-preview.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/users/umb-user-preview.less @@ -4,6 +4,11 @@ display: flex; box-sizing: border-box; border-bottom: 1px solid @gray-9; + flex-wrap: wrap; +} + +.umb-editor-wrapper .umb-user-preview { + .umb-property-editor--limit-width(); } .umb-user-preview:last-of-type { @@ -29,22 +34,26 @@ flex: 0 0 auto; display: flex; align-items: center; + margin-left: auto; } .umb-user-preview__action { + background: transparent; + padding: 0; + border: 0 none; margin-left: 5px; margin-right: 5px; font-size: 13px; font-weight: bold; - color: @gray-5; + color: @ui-action-type; } .umb-user-preview__action:hover { - color: @turquoise; + color: @ui-action-type-hover; text-decoration: none; opacity: 1; } .umb-user-preview__action--red:hover { color: @red; -} \ No newline at end of file +} diff --git a/src/Umbraco.Web.UI.Client/src/less/forms.less b/src/Umbraco.Web.UI.Client/src/less/forms.less index ffc0626981..ed5a2c0622 100644 --- a/src/Umbraco.Web.UI.Client/src/less/forms.less +++ b/src/Umbraco.Web.UI.Client/src/less/forms.less @@ -29,7 +29,7 @@ label.control-label, .control-label { } -.controls-row label{padding: 0 10px 0 10px; vertical-align: middle;} +.controls-row label:not(.umb-form-check){padding: 0 10px 0 10px; vertical-align: middle;} @@ -68,8 +68,9 @@ label.control-label, .control-label { .form-search .icon, .form-search .icon-search { position: absolute; z-index: 1; - top: 6px; + top: 50%; left: 6px; + transform: translateY(-50%); color: @gray-8; } @@ -113,6 +114,9 @@ label.control-label, .control-label { } } +.form-search .umb-search-field { + width: 100%; +} // GENERAL STYLES // -------------- diff --git a/src/Umbraco.Web.UI.Client/src/less/helveticons.less b/src/Umbraco.Web.UI.Client/src/less/helveticons.less index 82663270e9..a51f4e9f6f 100644 --- a/src/Umbraco.Web.UI.Client/src/less/helveticons.less +++ b/src/Umbraco.Web.UI.Client/src/less/helveticons.less @@ -8,35 +8,57 @@ font-style: normal; } +span[class^="icon-"], +span[class*=" icon-"] { + display: inline-block; + width: 1em; + height: 1em; + *margin-right: .3em; + + svg { + width: 100%; + height: 100%; + fill: currentColor; + } + + &.large{ + width: 32px; + height: 32px; + } + &.medium{ + width: 24px; + height: 24px; + } + &.small{ + width: 14px; + height: 14px; + } +} + [class^="icon-"], -[class*=" icon-"] { - font-family: icomoon; - font-weight: normal; - font-style: normal; - text-decoration: inherit; - -webkit-font-smoothing: antialiased; - *margin-right: .3em; +[class*=" icon-"], +button.icon-trash { + font-family: 'icomoon'; + speak: none; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + + /* Better Font Rendering =========== */ + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; } [class^="icon-"]:before, -[class*=" icon-"]:before { - text-decoration: inherit; - display: inline-block; - speak: none; +[class*=" icon-"]:before, +button.icon-trash { + text-decoration: inherit; + display: inline-block; + speak: none; } -/* -[class^="icon-"]:before, [class*=" icon-"]:before { - font-family: 'icomoon'; - speak: none; - font-weight: normal; - font-style: normal; - display: inline-block; - text-decoration: inherit; - font-size: 14px; - -webkit-font-smoothing: antialiased; -}*/ - i.large{ font-size: 32px; } @@ -47,1834 +69,1838 @@ i.small{ font-size: 14px; } -.icon-zoom-out:before { +i.icon-zoom-out:before { content: "\e000"; } -.icon-truck:before { +i.icon-truck:before { content: "\e001"; } -.icon-zoom-in:before { +i.icon-zoom-in:before { content: "\e002"; } -.icon-zip:before { +i.icon-zip:before { content: "\e003"; } -.icon-axis-rotation:before { +i.icon-axis-rotation:before { content: "\e004"; } -.icon-yen-bag:before { +i.icon-yen-bag:before { content: "\e005"; } -.icon-axis-rotation-2:before { +i.icon-axis-rotation-2:before { content: "\e006"; } -.icon-axis-rotation-3:before { +i.icon-axis-rotation-3:before { content: "\e007"; } -.icon-wrench:before { +i.icon-wrench:before { content: "\e008"; } -.icon-wine-glass:before { +i.icon-wine-glass:before { content: "\e009"; } -.icon-wrong:before { +i.icon-wrong:before { content: "\e00a"; } -.icon-windows:before { +i.icon-windows:before { content: "\e00b"; } -.icon-window-sizes:before { +i.icon-window-sizes:before { content: "\e00c"; } -.icon-window-popin:before { +i.icon-window-popin:before { content: "\e00d"; } -.icon-wifi:before { +i.icon-wifi:before { content: "\e00e"; } -.icon-width:before { +i.icon-width:before { content: "\e00f"; } -.icon-weight:before { +i.icon-weight:before { content: "\e010"; } -.icon-war:before { +i.icon-war:before { content: "\e011"; } -.icon-wand:before { +i.icon-wand:before { content: "\e012"; } -.icon-wallet:before { +i.icon-wallet:before { content: "\e013"; } -.icon-wall-plug:before { +i.icon-wall-plug:before { content: "\e014"; } -.icon-voice:before { +i.icon-voice:before { content: "\e016"; } -.icon-video:before { +i.icon-video:before { content: "\e017"; } -.icon-vcard:before { +i.icon-vcard:before { content: "\e018"; } -.icon-utilities:before { +i.icon-utilities:before { content: "\e019"; } -.icon-users:before { +i.icon-users:before { content: "\e01a"; } -.icon-users-alt:before { +i.icon-users-alt:before { content: "\e01b"; } -.icon-user:before { +i.icon-user:before { content: "\e01c"; } -.icon-user-glasses:before { +i.icon-user-glasses:before { content: "\e01d"; } -.icon-user-females:before { +i.icon-user-females:before { content: "\e01e"; } -.icon-user-females-alt:before { +i.icon-user-females-alt:before { content: "\e01f"; } -.icon-user-female:before { +i.icon-user-female:before { content: "\e020"; } -.icon-usb:before { +i.icon-usb:before { content: "\e021"; } -.icon-usb-connector:before { +i.icon-usb-connector:before { content: "\e022"; } -.icon-unlocked:before { +i.icon-unlocked:before { content: "\e023"; } -.icon-universal:before { +i.icon-universal:before { content: "\e024"; } -.icon-undo:before { +i.icon-undo:before { content: "\e025"; } -.icon-umbrella:before { +i.icon-umbrella:before { content: "\e026"; } -.icon-umb-deploy:before { +i.icon-umb-deploy:before { content: "\e027"; } -.icon-umb-contour:before, .traycontour:before, { +i.icon-umb-contour:before, .traycontour:before { content: "\e028"; } -.icon-umb-settings:before, .traysettings:before, { +i.icon-umb-settings:before, .traysettings:before { content: "\e029"; } -.icon-umb-users:before, .trayuser:before, .trayusers:before{ +i.icon-umb-users:before, .trayuser:before, .trayusers:before{ content: "\e02a"; } -.icon-umb-media:before, .traymedia:before, { +i.icon-umb-media:before, .traymedia:before { content: "\e02b"; } -.icon-umb-content:before, .traycontent:before{ +i.icon-umb-content:before, .traycontent:before{ content: "\e02c"; } -.icon-umb-developer:before, .traydeveloper:before, { +i.icon-umb-developer:before, .traydeveloper:before { content: "\e02d"; } -.icon-umb-members:before, .traymember:before { +i.icon-umb-members:before, .traymember:before { content: "\e015"; } -.icon-umb-translation:before, .traytranslation:before { +i.icon-umb-translation:before, .traytranslation:before { content: "\e1fd"; } -.icon-tv:before { +i.icon-tv:before { content: "\e02e"; } -.icon-tv-old:before { +i.icon-tv-old:before { content: "\e02f"; } -.icon-trophy:before { +i.icon-trophy:before { content: "\e030"; } -.icon-tree:before { +i.icon-tree:before { content: "\e031"; } -.icon-trash:before { +i.icon-trash:before, +button.icon-trash:before { content: "\e032"; } -.icon-trash-alt:before { +i.icon-trash-alt:before, +button.icon-trash-alt:before { content: "\e033"; } -.icon-trash-alt-2:before { +i.icon-trash-alt-2:before, +button.icon-trash-alt-2:before { content: "\e034"; } -.icon-train:before { +i.icon-train:before { content: "\e035"; } -.icon-trafic:before, -.icon-traffic:before { +i.icon-trafic:before, +i.icon-traffic:before { content: "\e036"; } -.icon-traffic-alt:before { +i.icon-traffic-alt:before { content: "\e037"; } -.icon-top:before { +i.icon-top:before { content: "\e038"; } -.icon-tools:before { +i.icon-tools:before { content: "\e039"; } -.icon-timer:before { +i.icon-timer:before { content: "\e03a"; } -.icon-time:before { +i.icon-time:before { content: "\e03b"; } -.icon-t-shirt:before { +i.icon-t-shirt:before { content: "\e03c"; } -.icon-tab-key:before { +i.icon-tab-key:before { content: "\e03d"; } -.icon-tab:before { +i.icon-tab:before { content: "\e03e"; } -.icon-tactics:before { +i.icon-tactics:before { content: "\e03f"; } -.icon-tag:before { +i.icon-tag:before { content: "\e040"; } -.icon-tags:before { +i.icon-tags:before { content: "\e041"; } -.icon-takeaway-cup:before { +i.icon-takeaway-cup:before { content: "\e042"; } -.icon-target:before { +i.icon-target:before { content: "\e043"; } -.icon-temperature-alt:before, -.icon-temperatrure-alt:before { +i.icon-temperature-alt:before, +i.icon-temperatrure-alt:before { content: "\e044"; } -.icon-temperature:before { +i.icon-temperature:before { content: "\e045"; } -.icon-terminal:before { +i.icon-terminal:before { content: "\e046"; } -.icon-theater:before { +i.icon-theater:before { content: "\e047"; } -.icon-thief:before, -.icon-theif:before { +i.icon-thief:before, +i.icon-theif:before { content: "\e048"; } -.icon-thought-bubble:before { +i.icon-thought-bubble:before { content: "\e049"; } -.icon-thumb-down:before { +i.icon-thumb-down:before { content: "\e04a"; } -.icon-thumb-up:before { +i.icon-thumb-up:before { content: "\e04b"; } -.icon-thumbnail-list:before { +i.icon-thumbnail-list:before { content: "\e04c"; } -.icon-thumbnails-small:before { +i.icon-thumbnails-small:before { content: "\e04d"; } -.icon-thumbnails:before { +i.icon-thumbnails:before { content: "\e04e"; } -.icon-ticket:before { +i.icon-ticket:before { content: "\e04f"; } -.icon-sync:before { +i.icon-sync:before { content: "\e050"; } -.icon-sweatshirt:before { +i.icon-sweatshirt:before { content: "\e051"; } -.icon-sunny:before { +i.icon-sunny:before { content: "\e052"; } -.icon-stream:before { +i.icon-stream:before { content: "\e053"; } -.icon-store:before { +i.icon-store:before { content: "\e054"; } -.icon-stop:before { +i.icon-stop:before { content: "\e055"; } -.icon-stop-hand:before { +i.icon-stop-hand:before { content: "\e056"; } -.icon-stop-alt:before { +i.icon-stop-alt:before { content: "\e057"; } -.icon-stamp:before { +i.icon-stamp:before { content: "\e058"; } -.icon-stacked-disks:before { +i.icon-stacked-disks:before { content: "\e059"; } -.icon-ssd:before { +i.icon-ssd:before { content: "\e05a"; } -.icon-squiggly-line:before { +i.icon-squiggly-line:before { content: "\e05b"; } -.icon-sprout:before { +i.icon-sprout:before { content: "\e05c"; } -.icon-split:before { +i.icon-split:before { content: "\e05d"; } -.icon-split-alt:before { +i.icon-split-alt:before { content: "\e05e"; } -.icon-speed-gauge:before { +i.icon-speed-gauge:before { content: "\e05f"; } -.icon-speaker:before { +i.icon-speaker:before { content: "\e060"; } -.icon-sound:before { +i.icon-sound:before { content: "\e061"; } -.icon-spades:before { +i.icon-spades:before { content: "\e062"; } -.icon-sound-waves:before { +i.icon-sound-waves:before { content: "\e063"; } -.icon-shipping-box:before { +i.icon-shipping-box:before { content: "\e064"; } -.icon-shipping:before { +i.icon-shipping:before { content: "\e065"; } -.icon-shoe:before { +i.icon-shoe:before { content: "\e066"; } -.icon-shopping-basket-alt-2:before { +i.icon-shopping-basket-alt-2:before { content: "\e067"; } -.icon-shopping-basket:before { +i.icon-shopping-basket:before { content: "\e068"; } -.icon-shopping-basket-alt:before { +i.icon-shopping-basket-alt:before { content: "\e069"; } -.icon-shorts:before { +i.icon-shorts:before { content: "\e06a"; } -.icon-shuffle:before { +i.icon-shuffle:before { content: "\e06b"; } -.icon-science:before, -.icon-sience:before { +i.icon-science:before, +i.icon-sience:before { content: "\e06c"; } -.icon-simcard:before { +i.icon-simcard:before { content: "\e06d"; } -.icon-single-note:before { +i.icon-single-note:before { content: "\e06e"; } -.icon-sitemap:before { +i.icon-sitemap:before { content: "\e06f"; } -.icon-sleep:before { +i.icon-sleep:before { content: "\e070"; } -.icon-slideshow:before { +i.icon-slideshow:before { content: "\e071"; } -.icon-smiley-inverted:before { +i.icon-smiley-inverted:before { content: "\e072"; } -.icon-smiley:before { +i.icon-smiley:before { content: "\e073"; } -.icon-snow:before { +i.icon-snow:before { content: "\e074"; } -.icon-sound-low:before { +i.icon-sound-low:before { content: "\e075"; } -.icon-sound-medium:before { +i.icon-sound-medium:before { content: "\e076"; } -.icon-sound-off:before { +i.icon-sound-off:before { content: "\e077"; } -.icon-shift:before { +i.icon-shift:before { content: "\e078"; } -.icon-shield:before { +i.icon-shield:before { content: "\e079"; } -.icon-sharing-iphone:before { +i.icon-sharing-iphone:before { content: "\e07a"; } -.icon-share:before { +i.icon-share:before { content: "\e07b"; } -.icon-share-alt:before { +i.icon-share-alt:before { content: "\e07c"; } -.icon-share-alt-2:before { +i.icon-share-alt-2:before { content: "\e07d"; } -.icon-settings:before { +i.icon-settings:before, +button.icon-settings:before { content: "\e07e"; } -.icon-settings-alt:before { +i.icon-settings-alt:before { content: "\e07f"; } -.icon-settings-alt-2:before { +i.icon-settings-alt-2:before { content: "\e080"; } -.icon-server:before { +i.icon-server:before { content: "\e081"; } -.icon-server-alt:before { +i.icon-server-alt:before { content: "\e082"; } -.icon-sensor:before { +i.icon-sensor:before { content: "\e083"; } -.icon-security-camera:before { +i.icon-security-camera:before { content: "\e084"; } -.icon-search:before { +i.icon-search:before { content: "\e085"; } -.icon-scull:before { +i.icon-scull:before { content: "\e086"; } -.icon-script:before { +i.icon-script:before { content: "\e087"; } -.icon-script-alt:before { +i.icon-script-alt:before { content: "\e088"; } -.icon-screensharing:before { +i.icon-screensharing:before { content: "\e089"; } -.icon-school:before { +i.icon-school:before { content: "\e08a"; } -.icon-scan:before { +i.icon-scan:before { content: "\e08b"; } -.icon-refresh:before { +i.icon-refresh:before { content: "\e08c"; } -.icon-remote:before { +i.icon-remote:before { content: "\e08d"; } -.icon-remove:before { +i.icon-remove:before { content: "\e08e"; } -.icon-repeat-one:before { +i.icon-repeat-one:before { content: "\e08f"; } -.icon-repeat:before { +i.icon-repeat:before { content: "\e090"; } -.icon-resize:before { +i.icon-resize:before { content: "\e091"; } -.icon-reply-arrow:before { +i.icon-reply-arrow:before { content: "\e092"; } -.icon-return-to-top:before { +i.icon-return-to-top:before { content: "\e093"; } -.icon-right-double-arrow:before { +i.icon-right-double-arrow:before { content: "\e094"; } -.icon-road:before { +i.icon-road:before { content: "\e095"; } -.icon-roadsign:before { +i.icon-roadsign:before { content: "\e096"; } -.icon-rocket:before { +i.icon-rocket:before { content: "\e097"; } -.icon-rss:before { +i.icon-rss:before { content: "\e098"; } -.icon-ruler-alt:before { +i.icon-ruler-alt:before { content: "\e099"; } -.icon-ruler:before { +i.icon-ruler:before { content: "\e09a"; } -.icon-sandbox-toys:before { +i.icon-sandbox-toys:before { content: "\e09b"; } -.icon-satellite-dish:before { +i.icon-satellite-dish:before { content: "\e09c"; } -.icon-save:before { +i.icon-save:before { content: "\e09d"; } -.icon-safedial:before { +i.icon-safedial:before { content: "\e09e"; } -.icon-safe:before { +i.icon-safe:before { content: "\e09f"; } -.icon-redo:before { +i.icon-redo:before { content: "\e0a0"; } -.icon-printer-alt:before { +i.icon-printer-alt:before { content: "\e0a1"; } -.icon-planet:before { +i.icon-planet:before { content: "\e0a2"; } -.icon-paste-in:before { +i.icon-paste-in:before { content: "\e0a3"; } -.icon-os-x:before { +i.icon-os-x:before { content: "\e0a4"; } -.icon-navigation-left:before { +i.icon-navigation-left:before { content: "\e0a5"; } -.icon-message:before { +i.icon-message:before { content: "\e0a6"; } -.icon-lock:before { +i.icon-lock:before { content: "\e0a7"; } -.icon-layers-alt:before { +i.icon-layers-alt:before { content: "\e0a8"; } -.icon-record:before { +i.icon-record:before { content: "\e0a9"; } -.icon-print:before { +i.icon-print:before { content: "\e0aa"; } -.icon-plane:before { +i.icon-plane:before { content: "\e0ab"; } -.icon-partly-cloudy:before { +i.icon-partly-cloudy:before { content: "\e0ac"; } -.icon-ordered-list:before { +i.icon-ordered-list:before { content: "\e0ad"; } -.icon-navigation-last:before { +i.icon-navigation-last:before { content: "\e0ae"; } -.icon-message-unopened:before { +i.icon-message-unopened:before { content: "\e0af"; } -.icon-location-nearby:before { +i.icon-location-nearby:before { content: "\e0b0"; } -.icon-laptop:before { +i.icon-laptop:before { content: "\e0b1"; } -.icon-reception:before { +i.icon-reception:before { content: "\e0b2"; } -.icon-price-yen:before { +i.icon-price-yen:before { content: "\e0b3"; } -.icon-piracy:before { +i.icon-piracy:before { content: "\e0b4"; } -.icon-parental-control:before { +i.icon-parental-control:before { content: "\e0b5"; } -.icon-operator:before { +i.icon-operator:before { content: "\e0b6"; } -.icon-navigation-horizontal:before { +i.icon-navigation-horizontal:before { content: "\e0b7"; } -.icon-message-open:before { +i.icon-message-open:before { content: "\e0b8"; } -.icon-lab:before { +i.icon-lab:before { content: "\e0b9"; } -.icon-location-near-me:before { +i.icon-location-near-me:before { content: "\e0ba"; } -.icon-receipt-yen:before { +i.icon-receipt-yen:before { content: "\e0bb"; } -.icon-price-pound:before { +i.icon-price-pound:before { content: "\e0bc"; } -.icon-pin-location:before { +i.icon-pin-location:before { content: "\e0bd"; } -.icon-parachute-drop:before { +i.icon-parachute-drop:before { content: "\e0be"; } -.icon-old-phone:before { +i.icon-old-phone:before { content: "\e0bf"; } -.icon-merge:before { +i.icon-merge:before { content: "\e0c0"; } -.icon-navigation-first:before { +i.icon-navigation-first:before { content: "\e0c1"; } -.icon-locate:before { +i.icon-locate:before { content: "\e0c2"; } -.icon-keyhole:before { +i.icon-keyhole:before { content: "\e0c3"; } -.icon-receipt-pound:before { +i.icon-receipt-pound:before { content: "\e0c4"; } -.icon-price-euro:before { +i.icon-price-euro:before { content: "\e0c5"; } -.icon-piggy-bank:before { +i.icon-piggy-bank:before { content: "\e0c6"; } -.icon-paper-plane:before { +i.icon-paper-plane:before { content: "\e0c7"; } -.icon-old-key:before { +i.icon-old-key:before { content: "\e0c8"; } -.icon-navigation-down:before { +i.icon-navigation-down:before { content: "\e0c9"; } -.icon-megaphone:before { +i.icon-megaphone:before { content: "\e0ca"; } -.icon-loading:before { +i.icon-loading:before { content: "\e0cb"; } -.icon-keychain:before { +i.icon-keychain:before { content: "\e0cc"; } -.icon-receipt-euro:before { +i.icon-receipt-euro:before { content: "\e0cd"; } -.icon-price-dollar:before { +i.icon-price-dollar:before { content: "\e0ce"; } -.icon-pie-chart:before { +i.icon-pie-chart:before { content: "\e0cf"; } -.icon-paper-plane-alt:before { +i.icon-paper-plane-alt:before { content: "\e0d0"; } -.icon-notepad:before { +i.icon-notepad:before { content: "\e0d1"; } -.icon-navigation-bottom:before { +i.icon-navigation-bottom:before { content: "\e0d2"; } -.icon-meeting:before { +i.icon-meeting:before { content: "\e0d3"; } -.icon-keyboard:before { +i.icon-keyboard:before { content: "\e0d4"; } -.icon-load:before { +i.icon-load:before { content: "\e0d5"; } -.icon-receipt-dollar:before { +i.icon-receipt-dollar:before { content: "\e0d6"; } -.icon-previous:before { +i.icon-previous:before { content: "\e0d7"; } -.icon-pictures:before { +i.icon-pictures:before { content: "\e0d8"; } -.icon-notepad-alt:before { +i.icon-notepad-alt:before { content: "\e0d9"; } -.icon-paper-bag:before { +i.icon-paper-bag:before { content: "\e0da"; } -.icon-name-badge:before { +i.icon-badge:before { content: "\e0db"; } -.icon-medicine:before { +i.icon-medicine:before { content: "\e0dc"; } -.icon-list:before { +i.icon-list:before { content: "\e0dd"; } -.icon-key:before { +i.icon-key:before { content: "\e0de"; } -.icon-receipt-alt:before { +i.icon-receipt-alt:before { content: "\e0df"; } -.icon-previous-media:before { +i.icon-previous-media:before { content: "\e0e0"; } -.icon-pictures-alt:before { +i.icon-pictures-alt:before { content: "\e0e1"; } -.icon-pants:before { +i.icon-pants:before { content: "\e0e2"; } -.icon-nodes:before { +i.icon-nodes:before { content: "\e0e3"; } -.icon-music:before { +i.icon-music:before { content: "\e0e4"; } -.icon-readonly:before { +i.icon-readonly:before { content: "\e0e5"; } -.icon-presentation:before { +i.icon-presentation:before { content: "\e0e6"; } -.icon-pictures-alt-2:before { +i.icon-pictures-alt-2:before { content: "\e0e7"; } -.icon-panel-close:before, -.icon-pannel-close:before { +i.icon-panel-close:before, +i.icon-pannel-close:before { content: "\e0e8"; } -.icon-next:before { +i.icon-next:before { content: "\e0e9"; } -.icon-multiple-windows:before { +i.icon-multiple-windows:before { content: "\e0ea"; } -.icon-medical-emergency:before { +i.icon-medical-emergency:before { content: "\e0eb"; } -.icon-medal:before { +i.icon-medal:before { content: "\e0ec"; } -.icon-link:before { +i.icon-link:before { content: "\e0ed"; } -.icon-linux-tux:before { +i.icon-linux-tux:before { content: "\e0ee"; } -.icon-junk:before { +i.icon-junk:before { content: "\e0ef"; } -.icon-item-arrangement:before { +i.icon-item-arrangement:before { content: "\e0f0"; } -.icon-iphone:before { +i.icon-iphone:before { content: "\e0f1"; } -.icon-lightning:before { +i.icon-lightning:before { content: "\e0f2"; } -.icon-map:before { +i.icon-map:before { content: "\e0f3"; } -.icon-multiple-credit-cards:before { +i.icon-multiple-credit-cards:before { content: "\e0f4"; } -.icon-next-media:before { +i.icon-next-media:before { content: "\e0f5"; } -.icon-panel-show:before { +i.icon-panel-show:before { content: "\e0f6"; } -.icon-picture:before { +i.icon-picture:before { content: "\e0f7"; } -.icon-power:before { +i.icon-power:before { content: "\e0f8"; } -.icon-re-post:before { +i.icon-re-post:before { content: "\e0f9"; } -.icon-rate:before { +i.icon-rate:before { content: "\e0fa"; } -.icon-rain:before { +i.icon-rain:before { content: "\e0fb"; } -.icon-radio:before { +i.icon-radio:before { content: "\e0fc"; } -.icon-radio-receiver:before { +i.icon-radio-receiver:before { content: "\e0fd"; } -.icon-radio-alt:before { +i.icon-radio-alt:before { content: "\e0fe"; } -.icon-quote:before { +i.icon-quote:before { content: "\e0ff"; } -.icon-qr-code:before { +i.icon-qr-code:before { content: "\e100"; } -.icon-pushpin:before { +i.icon-pushpin:before { content: "\e101"; } -.icon-pulse:before { +i.icon-pulse:before { content: "\e102"; } -.icon-projector:before { +i.icon-projector:before { content: "\e103"; } -.icon-play:before { +i.icon-play:before { content: "\e104"; } -.icon-playing-cards:before { +i.icon-playing-cards:before { content: "\e105"; } -.icon-playlist:before { +i.icon-playlist:before { content: "\e106"; } -.icon-plugin:before { +i.icon-plugin:before { content: "\e107"; } -.icon-podcast:before { +i.icon-podcast:before { content: "\e108"; } -.icon-poker-chip:before { +i.icon-poker-chip:before { content: "\e109"; } -.icon-poll:before { +i.icon-poll:before { content: "\e10a"; } -.icon-post-it:before { +i.icon-post-it:before { content: "\e10b"; } -.icon-pound-bag:before { +i.icon-pound-bag:before { content: "\e10c"; } -.icon-power-outlet:before { +i.icon-power-outlet:before { content: "\e10d"; } -.icon-photo-album:before { +i.icon-photo-album:before { content: "\e10e"; } -.icon-phone:before { +i.icon-phone:before { content: "\e10f"; } -.icon-phone-ring:before { +i.icon-phone-ring:before { content: "\e110"; } -.icon-people:before { +i.icon-people:before { content: "\e111"; } -.icon-people-female:before { +i.icon-people-female:before { content: "\e112"; } -.icon-people-alt:before { +i.icon-people-alt:before { content: "\e113"; } -.icon-people-alt-2:before { +i.icon-people-alt-2:before { content: "\e114"; } -.icon-pc:before { +i.icon-pc:before { content: "\e115"; } -.icon-pause:before { +i.icon-pause:before { content: "\e116"; } -.icon-path:before { +i.icon-path:before { content: "\e117"; } -.icon-out:before { +i.icon-out:before { content: "\e118"; } -.icon-outbox:before { +i.icon-outbox:before { content: "\e119"; } -.icon-outdent:before { +i.icon-outdent:before { content: "\e11a"; } -.icon-page-add:before { +i.icon-page-add:before { content: "\e11b"; } -.icon-page-down:before { +i.icon-page-down:before { content: "\e11c"; } -.icon-page-remove:before { +i.icon-page-remove:before { content: "\e11d"; } -.icon-page-restricted:before { +i.icon-page-restricted:before { content: "\e11e"; } -.icon-page-up:before { +i.icon-page-up:before { content: "\e11f"; } -.icon-paint-roller:before { +i.icon-paint-roller:before { content: "\e120"; } -.icon-palette:before { +i.icon-palette:before { content: "\e121"; } -.icon-newspaper:before { +i.icon-newspaper:before { content: "\e122"; } -.icon-newspaper-alt:before { +i.icon-newspaper-alt:before { content: "\e123"; } -.icon-network-alt:before { +i.icon-network-alt:before { content: "\e124"; } -.icon-navigational-arrow:before { +i.icon-navigational-arrow:before { content: "\e125"; } -.icon-navigation:before { +i.icon-navigation:before { content: "\e126"; } -.icon-navigation-vertical:before { +i.icon-navigation-vertical:before { content: "\e127"; } -.icon-navigation-up:before { +i.icon-navigation-up:before { content: "\e128"; } -.icon-navigation-top:before { +i.icon-navigation-top:before { content: "\e129"; } -.icon-navigation-road:before { +i.icon-navigation-road:before { content: "\e12a"; } -.icon-navigation-right:before { +i.icon-navigation-right:before { content: "\e12b"; } -.icon-microscope:before { +i.icon-microscope:before { content: "\e12c"; } -.icon-mindmap:before { +i.icon-mindmap:before { content: "\e12d"; } -.icon-molecular-network:before { +i.icon-molecular-network:before { content: "\e12e"; } -.icon-molecular:before { +i.icon-molecular:before { content: "\e12f"; } -.icon-mountain:before { +i.icon-mountain:before { content: "\e130"; } -.icon-mouse-cursor:before { +i.icon-mouse-cursor:before { content: "\e131"; } -.icon-mouse:before { +i.icon-mouse:before { content: "\e132"; } -.icon-movie-alt:before { +i.icon-movie-alt:before { content: "\e133"; } -.icon-map-marker:before { +i.icon-map-marker:before { content: "\e134"; } -.icon-movie:before { +i.icon-movie:before { content: "\e135"; } -.icon-map-location:before { +i.icon-map-location:before { content: "\e136"; } -.icon-map-alt:before { +i.icon-map-alt:before { content: "\e137"; } -.icon-male-symbol:before { +i.icon-male-symbol:before { content: "\e138"; } -.icon-male-and-female:before { +i.icon-male-and-female:before { content: "\e139"; } -.icon-mailbox:before { +i.icon-mailbox:before { content: "\e13a"; } -.icon-magnet:before { +i.icon-magnet:before { content: "\e13b"; } -.icon-loupe:before { +i.icon-loupe:before { content: "\e13c"; } -.icon-mobile:before { +i.icon-mobile:before { content: "\e13d"; } -.icon-logout:before { +i.icon-logout:before { content: "\e13e"; } -.icon-log-out:before { +i.icon-log-out:before { content: "\e13f"; } -.icon-layers:before { +i.icon-layers:before { content: "\e140"; } -.icon-left-double-arrow:before { +i.icon-left-double-arrow:before { content: "\e141"; } -.icon-layout:before { +i.icon-layout:before { content: "\e142"; } -.icon-legal:before { +i.icon-legal:before { content: "\e143"; } -.icon-lense:before { +i.icon-lense:before { content: "\e144"; } -.icon-library:before { +i.icon-library:before { content: "\e145"; } -.icon-light-down:before { +i.icon-light-down:before { content: "\e146"; } -.icon-light-up:before { +i.icon-light-up:before { content: "\e147"; } -.icon-lightbulb-active:before { +i.icon-lightbulb-active:before { content: "\e148"; } -.icon-lightbulb:before { +i.icon-lightbulb:before { content: "\e149"; } -.icon-ipad:before { +i.icon-ipad:before { content: "\e14a"; } -.icon-invoice:before { +i.icon-invoice:before { content: "\e14b"; } -.icon-info:before { +i.icon-info:before { content: "\e14c"; } -.icon-infinity:before { +i.icon-infinity:before { content: "\e14d"; } -.icon-indent:before { +i.icon-indent:before { content: "\e14e"; } -.icon-inbox:before { +i.icon-inbox:before { content: "\e14f"; } -.icon-inbox-full:before { +i.icon-inbox-full:before { content: "\e150"; } -.icon-inactive-line:before { +i.icon-inactive-line:before { content: "\e151"; } -.icon-imac:before { +i.icon-imac:before { content: "\e152"; } -.icon-hourglass:before { +i.icon-hourglass:before { content: "\e153"; } -.icon-home:before { +i.icon-home:before { content: "\e154"; } -.icon-grid:before { +i.icon-grid:before { content: "\e155"; } -.icon-food:before { +i.icon-food:before { content: "\e156"; } -.icon-favorite:before { +i.icon-favorite:before { content: "\e157"; } -.icon-door-open-alt:before { +i.icon-door-open-alt:before { content: "\e158"; } -.icon-diagnostics:before { +i.icon-diagnostics:before { content: "\e159"; } -.icon-contrast:before { +i.icon-contrast:before { content: "\e15a"; } -.icon-coins-dollar-alt:before { +i.icon-coins-dollar-alt:before { content: "\e15b"; } -.icon-circle-dotted-active:before { +i.icon-circle-dotted-active:before { content: "\e15c"; } -.icon-cinema:before { +i.icon-cinema:before { content: "\e15d"; } -.icon-chip:before { +i.icon-chip:before { content: "\e15e"; } -.icon-chip-alt:before { +i.icon-chip-alt:before { content: "\e15f"; } -.icon-chess:before { +i.icon-chess:before { content: "\e160"; } -.icon-checkbox:before { +i.icon-checkbox:before { content: "\e161"; } -.icon-checkbox-empty:before { +i.icon-checkbox-empty:before { content: "\e162"; } -.icon-checkbox-dotted:before { +i.icon-checkbox-dotted:before { content: "\e163"; } -.icon-checkbox-dotted-active:before { +i.icon-checkbox-dotted-active:before { content: "\e164"; } -.icon-check:before { +i.icon-check:before { content: "\e165"; } -.icon-chat:before { +i.icon-chat:before { content: "\e166"; } -.icon-chat-active:before { +i.icon-chat-active:before { content: "\e167"; } -.icon-chart:before { +i.icon-chart:before { content: "\e168"; } -.icon-chart-curve:before { +i.icon-chart-curve:before { content: "\e169"; } -.icon-certificate:before { +i.icon-certificate:before { content: "\e16a"; } -.icon-categories:before { +i.icon-categories:before { content: "\e16b"; } -.icon-cash-register:before { +i.icon-cash-register:before { content: "\e16c"; } -.icon-car:before { +i.icon-car:before { content: "\e16d"; } -.icon-caps-lock:before { +i.icon-caps-lock:before { content: "\e16e"; } -.icon-candy:before { +i.icon-candy:before { content: "\e16f"; } -.icon-circle-dotted:before { +i.icon-circle-dotted:before { content: "\e170"; } -.icon-circuits:before { +i.icon-circuits:before { content: "\e171"; } -.icon-circus:before { +i.icon-circus:before { content: "\e172"; } -.icon-client:before { +i.icon-client:before { content: "\e173"; } -.icon-clothes-hanger:before { +i.icon-clothes-hanger:before { content: "\e174"; } -.icon-cloud-drive:before { +i.icon-cloud-drive:before { content: "\e175"; } -.icon-cloud-upload:before { +i.icon-cloud-upload:before { content: "\e176"; } -.icon-cloud:before { +i.icon-cloud:before { content: "\e177"; } -.icon-cloudy:before { +i.icon-cloudy:before { content: "\e178"; } -.icon-clubs:before { +i.icon-clubs:before { content: "\e179"; } -.icon-cocktail:before { +i.icon-cocktail:before { content: "\e17a"; } -.icon-code:before { +i.icon-code:before { content: "\e17b"; } -.icon-coffee:before { +i.icon-coffee:before { content: "\e17c"; } -.icon-coin-dollar:before { +i.icon-coin-dollar:before { content: "\e17d"; } -.icon-coin-pound:before { +i.icon-coin-pound:before { content: "\e17e"; } -.icon-coin-yen:before { +i.icon-coin-yen:before { content: "\e17f"; } -.icon-coin:before { +i.icon-coin:before { content: "\e180"; } -.icon-coins-alt:before { +i.icon-coins-alt:before { content: "\e181"; } -.icon-console:before { +i.icon-console:before { content: "\e182"; } -.icon-connection:before { +i.icon-connection:before { content: "\e183"; } -.icon-compress:before { +i.icon-compress:before { content: "\e184"; } -.icon-company:before { +i.icon-company:before { content: "\e185"; } -.icon-command:before { +i.icon-command:before { content: "\e186"; } -.icon-coin-euro:before { +i.icon-coin-euro:before { content: "\e187"; } -.icon-combination-lock:before { +i.icon-combination-lock:before { content: "\e188"; } -.icon-combination-lock-open:before { +i.icon-combination-lock-open:before { content: "\e189"; } -.icon-comb:before { +i.icon-comb:before { content: "\e18a"; } -.icon-columns:before { +i.icon-columns:before { content: "\e18b"; } -.icon-colorpicker:before { +i.icon-colorpicker:before { content: "\e18c"; } -.icon-color-bucket:before { +i.icon-color-bucket:before { content: "\e18d"; } -.icon-coins:before { +i.icon-coins:before { content: "\e18e"; } -.icon-coins-yen:before { +i.icon-coins-yen:before { content: "\e18f"; } -.icon-coins-yen-alt:before { +i.icon-coins-yen-alt:before { content: "\e190"; } -.icon-coins-pound:before { +i.icon-coins-pound:before { content: "\e191"; } -.icon-coins-pound-alt:before { +i.icon-coins-pound-alt:before { content: "\e192"; } -.icon-coins-euro:before { +i.icon-coins-euro:before { content: "\e193"; } -.icon-coins-euro-alt:before { +i.icon-coins-euro-alt:before { content: "\e194"; } -.icon-coins-dollar:before { +i.icon-coins-dollar:before { content: "\e195"; } -.icon-conversation-alt:before { +i.icon-conversation-alt:before { content: "\e196"; } -.icon-conversation:before { +i.icon-conversation:before { content: "\e197"; } -.icon-coverflow:before { +i.icon-coverflow:before { content: "\e198"; } -.icon-credit-card-alt:before { +i.icon-credit-card-alt:before { content: "\e199"; } -.icon-credit-card:before { +i.icon-credit-card:before { content: "\e19a"; } -.icon-crop:before { +i.icon-crop:before { content: "\e19b"; } -.icon-crosshair:before { +i.icon-crosshair:before { content: "\e19c"; } -.icon-crown-alt:before { +i.icon-crown-alt:before { content: "\e19d"; } -.icon-crown:before { +i.icon-crown:before { content: "\e19e"; } -.icon-cupcake:before { +i.icon-cupcake:before { content: "\e19f"; } -.icon-curve:before { +i.icon-curve:before { content: "\e1a0"; } -.icon-cut:before { +i.icon-cut:before { content: "\e1a1"; } -.icon-dashboard:before { +i.icon-dashboard:before { content: "\e1a2"; } -.icon-defrag:before { +i.icon-defrag:before { content: "\e1a3"; } -.icon-delete:before { +i.icon-delete:before { content: "\e1a4"; } -.icon-delete-key:before { +i.icon-delete-key:before { content: "\e1a5"; } -.icon-departure:before { +i.icon-departure:before { content: "\e1a6"; } -.icon-desk:before { +i.icon-desk:before { content: "\e1a7"; } -.icon-desktop:before { +i.icon-desktop:before { content: "\e1a8"; } -.icon-donate:before { +i.icon-donate:before { content: "\e1a9"; } -.icon-dollar-bag:before { +i.icon-dollar-bag:before { content: "\e1aa"; } -.icon-documents:before { +i.icon-documents:before { content: "\e1ab"; } -.icon-document:before { +i.icon-document:before { content: "\e1ac"; } -.icon-document-dashed-line:before { +i.icon-document-dashed-line:before { content: "\e1ad"; } -.icon-dock-connector:before { +i.icon-dock-connector:before { content: "\e1ae"; } -.icon-dna:before { +i.icon-dna:before { content: "\e1af"; } -.icon-display:before { +i.icon-display:before { content: "\e1b0"; } -.icon-disk-image:before { +i.icon-disk-image:before { content: "\e1b1"; } -.icon-disc:before { +i.icon-disc:before { content: "\e1b2"; } -.icon-directions:before { +i.icon-directions:before { content: "\e1b3"; } -.icon-directions-alt:before { +i.icon-directions-alt:before { content: "\e1b4"; } -.icon-diploma:before { +i.icon-diploma:before { content: "\e1b5"; } -.icon-diploma-alt:before { +i.icon-diploma-alt:before { content: "\e1b6"; } -.icon-dice:before { +i.icon-dice:before { content: "\e1b7"; } -.icon-diamonds:before { +i.icon-diamonds:before { content: "\e1b8"; } -.icon-diamond:before { +i.icon-diamond:before { content: "\e1b9"; } -.icon-diagonal-arrow:before { +i.icon-diagonal-arrow:before { content: "\e1ba"; } -.icon-diagonal-arrow-alt:before { +i.icon-diagonal-arrow-alt:before { content: "\e1bb"; } -.icon-door-open:before { +i.icon-door-open:before { content: "\e1bc"; } -.icon-download-alt:before { +i.icon-download-alt:before { content: "\e1bd"; } -.icon-download:before { +i.icon-download:before { content: "\e1be"; } -.icon-drop:before { +i.icon-drop:before { content: "\e1bf"; } -.icon-eco:before { +i.icon-eco:before { content: "\e1c0"; } -.icon-economy:before { +i.icon-economy:before { content: "\e1c1"; } -.icon-edit:before { +i.icon-edit:before { content: "\e1c2"; } -.icon-eject:before { +i.icon-eject:before { content: "\e1c3"; } -.icon-employee:before { +i.icon-employee:before { content: "\e1c4"; } -.icon-energy-saving-bulb:before { +i.icon-energy-saving-bulb:before { content: "\e1c5"; } -.icon-enter:before { +i.icon-enter:before { content: "\e1c6"; } -.icon-equalizer:before { +i.icon-equalizer:before { content: "\e1c7"; } -.icon-escape:before { +i.icon-escape:before { content: "\e1c8"; } -.icon-ethernet:before { +i.icon-ethernet:before { content: "\e1c9"; } -.icon-euro-bag:before { +i.icon-euro-bag:before { content: "\e1ca"; } -.icon-exit-fullscreen:before { +i.icon-exit-fullscreen:before { content: "\e1cb"; } -.icon-eye:before { +i.icon-eye:before { content: "\e1cc"; } -.icon-facebook-like:before { +i.icon-facebook-like:before { content: "\e1cd"; } -.icon-factory:before { +i.icon-factory:before { content: "\e1ce"; } -.icon-font:before { +i.icon-font:before { content: "\e1cf"; } -.icon-folders:before { +i.icon-folders:before { content: "\e1d0"; } -.icon-folder:before, .icon-folder-close:before { +i.icon-folder:before, i.icon-folder-close:before { content: "\e1d1"; } -.icon-folder-outline:before { +i.icon-folder-outline:before { content: "\e1d2"; } -.icon-folder-open:before { +i.icon-folder-open:before { content: "\e1d3"; } -.icon-flowerpot:before { +i.icon-flowerpot:before { content: "\e1d4"; } -.icon-flashlight:before { +i.icon-flashlight:before { content: "\e1d5"; } -.icon-flash:before { +i.icon-flash:before { content: "\e1d6"; } -.icon-flag:before { +i.icon-flag:before { content: "\e1d7"; } -.icon-flag-alt:before { +i.icon-flag-alt:before { content: "\e1d8"; } -.icon-firewire:before { +i.icon-firewire:before { content: "\e1d9"; } -.icon-firewall:before { +i.icon-firewall:before { content: "\e1da"; } -.icon-fire:before { +i.icon-fire:before { content: "\e1db"; } -.icon-fingerprint:before { +i.icon-fingerprint:before { content: "\e1dc"; } -.icon-filter:before { +i.icon-filter:before { content: "\e1dd"; } -.icon-filter-arrows:before { +i.icon-filter-arrows:before { content: "\e1de"; } -.icon-files:before { +i.icon-files:before { content: "\e1df"; } -.icon-file-cabinet:before { +i.icon-file-cabinet:before { content: "\e1e0"; } -.icon-female-symbol:before { +i.icon-female-symbol:before { content: "\e1e1"; } -.icon-footprints:before { +i.icon-footprints:before { content: "\e1e2"; } -.icon-hammer:before { +i.icon-hammer:before { content: "\e1e3"; } -.icon-hand-active-alt:before { +i.icon-hand-active-alt:before { content: "\e1e4"; } -.icon-forking:before { +i.icon-forking:before { content: "\e1e5"; } -.icon-hand-active:before { +i.icon-hand-active:before { content: "\e1e6"; } -.icon-hand-pointer-alt:before { +i.icon-hand-pointer-alt:before { content: "\e1e7"; } -.icon-hand-pointer:before { +i.icon-hand-pointer:before { content: "\e1e8"; } -.icon-handprint:before { +i.icon-handprint:before { content: "\e1e9"; } -.icon-handshake:before { +i.icon-handshake:before { content: "\e1ea"; } -.icon-handtool:before { +i.icon-handtool:before { content: "\e1eb"; } -.icon-hard-drive:before { +i.icon-hard-drive:before { content: "\e1ec"; } -.icon-help:before { +i.icon-help:before { content: "\e1ed"; } -.icon-graduate:before { +i.icon-graduate:before { content: "\e1ee"; } -.icon-gps:before { +i.icon-gps:before { content: "\e1ef"; } -.icon-help-alt:before { +i.icon-help-alt:before { content: "\e1f0"; } -.icon-height:before { +i.icon-height:before { content: "\e1f1"; } -.icon-globe:before { +i.icon-globe:before { content: "\e1f2"; } -.icon-hearts:before { +i.icon-hearts:before { content: "\e1f3"; } -.icon-globe-inverted-europe-africa:before { +i.icon-globe-inverted-europe-africa:before { content: "\e1f4"; } -.icon-headset:before { +i.icon-headset:before { content: "\e1f5"; } -.icon-globe-inverted-asia:before { +i.icon-globe-inverted-asia:before { content: "\e1f6"; } -.icon-headphones:before { +i.icon-headphones:before { content: "\e1f7"; } -.icon-globe-inverted-america:before { +i.icon-globe-inverted-america:before { content: "\e1f8"; } -.icon-hd:before { +i.icon-hd:before { content: "\e1f9"; } -.icon-globe-europe-africa:before, -.icon-globe-europe---africa:before { +i.icon-globe-europe-africa:before, +i.icon-globe-europe---africa:before { content: "\e1fa"; } -.icon-hat:before { +i.icon-hat:before { content: "\e1fb"; } -.icon-globe-asia:before { +i.icon-globe-asia:before { content: "\e1fc"; } -.icon-globe-alt:before { +i.icon-globe-alt:before { content: "\e1fd"; } -.icon-hard-drive-alt:before { +i.icon-hard-drive-alt:before { content: "\e1fe"; } -.icon-glasses:before { +i.icon-glasses:before { content: "\e1ff"; } -.icon-gift:before { +i.icon-gift:before { content: "\e200"; } -.icon-handtool-alt:before { +i.icon-handtool-alt:before { content: "\e201"; } -.icon-geometry:before { +i.icon-geometry:before { content: "\e202"; } -.icon-game:before { +i.icon-game:before { content: "\e203"; } -.icon-fullscreen:before { +i.icon-fullscreen:before { content: "\e204"; } -.icon-fullscreen-alt:before { +i.icon-fullscreen-alt:before { content: "\e205"; } -.icon-frame:before { +i.icon-frame:before { content: "\e206"; } -.icon-frame-alt:before { +i.icon-frame-alt:before { content: "\e207"; } -.icon-camera-roll:before { +i.icon-camera-roll:before { content: "\e208"; } -.icon-bookmark:before { +i.icon-bookmark:before { content: "\e209"; } -.icon-bill:before { +i.icon-bill:before { content: "\e20a"; } -.icon-baby-stroller:before { +i.icon-baby-stroller:before { content: "\e20b"; } -.icon-alarm-clock:before { +i.icon-alarm-clock:before { content: "\e20c"; } -.icon-addressbook:before, -.icon-adressbook:before { +i.icon-addressbook:before, +i.icon-adressbook:before { content: "\e20d"; } -.icon-add:before { +i.icon-add:before { content: "\e20e"; } -.icon-activity:before { +i.icon-activity:before { content: "\e20f"; } -.icon-untitled:before { +i.icon-untitled:before { content: "\e210"; } -.icon-glasses:before { +i.icon-glasses:before { content: "\e211"; } -.icon-camcorder:before { +i.icon-camcorder:before { content: "\e212"; } -.icon-calendar:before { +i.icon-calendar:before { content: "\e213"; } -.icon-calendar-alt:before { +i.icon-calendar-alt:before { content: "\e214"; } -.icon-calculator:before { +i.icon-calculator:before { content: "\e215"; } -.icon-bus:before { +i.icon-bus:before { content: "\e216"; } -.icon-burn:before { +i.icon-burn:before { content: "\e217"; } -.icon-bulleted-list:before { +i.icon-bulleted-list:before { content: "\e218"; } -.icon-bug:before { +i.icon-bug:before { content: "\e219"; } -.icon-brush:before { +i.icon-brush:before { content: "\e21a"; } -.icon-brush-alt:before { +i.icon-brush-alt:before { content: "\e21b"; } -.icon-brush-alt-2:before { +i.icon-brush-alt-2:before { content: "\e21c"; } -.icon-browser-window:before { +i.icon-browser-window:before { content: "\e21d"; } -.icon-briefcase:before { +i.icon-briefcase:before { content: "\e21e"; } -.icon-brick:before { +i.icon-brick:before { content: "\e21f"; } -.icon-brackets:before { +i.icon-brackets:before { content: "\e220"; } -.icon-box:before { +i.icon-box:before { content: "\e221"; } -.icon-box-open:before { +i.icon-box-open:before { content: "\e222"; } -.icon-box-alt:before { +i.icon-box-alt:before { content: "\e223"; } -.icon-books:before { +i.icon-books:before { content: "\e224"; } -.icon-billboard:before { +i.icon-billboard:before { content: "\e225"; } -.icon-bills-dollar:before { +i.icon-bills-dollar:before { content: "\e226"; } -.icon-bills-euro:before { +i.icon-bills-euro:before { content: "\e227"; } -.icon-bills-pound:before { +i.icon-bills-pound:before { content: "\e228"; } -.icon-bills-yen:before { +i.icon-bills-yen:before { content: "\e229"; } -.icon-bills:before { +i.icon-bills:before { content: "\e22a"; } -.icon-binarycode:before { +i.icon-binarycode:before { content: "\e22b"; } -.icon-binoculars:before { +i.icon-binoculars:before { content: "\e22c"; } -.icon-bird:before { +i.icon-bird:before { content: "\e22d"; } -.icon-birthday-cake:before { +i.icon-birthday-cake:before { content: "\e22e"; } -.icon-blueprint:before { +i.icon-blueprint:before { content: "\e22f"; } -.icon-block:before { +i.icon-block:before { content: "\e230"; } -.icon-bluetooth:before { +i.icon-bluetooth:before { content: "\e231"; } -.icon-boat-shipping:before { +i.icon-boat-shipping:before { content: "\e232"; } -.icon-bomb:before { +i.icon-bomb:before { content: "\e233"; } -.icon-book-alt-2:before { +i.icon-book-alt-2:before { content: "\e234"; } -.icon-bones:before { +i.icon-bones:before { content: "\e235"; } -.icon-book-alt:before { +i.icon-book-alt:before { content: "\e236"; } -.icon-book:before { +i.icon-book:before { content: "\e237"; } -.icon-bill-yen:before { +i.icon-bill-yen:before { content: "\e238"; } -.icon-award:before { +i.icon-award:before { content: "\e239"; } -.icon-bill-pound:before { +i.icon-bill-pound:before { content: "\e23a"; } -.icon-autofill:before { +i.icon-autofill:before { content: "\e23b"; } -.icon-bill-euro:before { +i.icon-bill-euro:before { content: "\e23c"; } -.icon-auction-hammer:before { +i.icon-auction-hammer:before { content: "\e23d"; } -.icon-bill-dollar:before { +i.icon-bill-dollar:before { content: "\e23e"; } -.icon-attachment:before { +i.icon-attachment:before { content: "\e23f"; } -.icon-bell:before { +i.icon-bell:before { content: "\e240"; } -.icon-article:before { +i.icon-article:before { content: "\e241"; } -.icon-bell-off:before { +i.icon-bell-off:before { content: "\e242"; } -.icon-art-easel:before { +i.icon-art-easel:before { content: "\e243"; } -.icon-beer-glass:before { +i.icon-beer-glass:before { content: "\e244"; } -.icon-arrow-up:before { +i.icon-arrow-up:before { content: "\e245"; } -.icon-battery-low:before { +i.icon-battery-low:before { content: "\e246"; } -.icon-arrow-right:before { +i.icon-arrow-right:before { content: "\e247"; } -.icon-battery-full:before { +i.icon-battery-full:before { content: "\e248"; } -.icon-arrow-left:before { +i.icon-arrow-left:before { content: "\e249"; } -.icon-bars:before { +i.icon-bars:before { content: "\e24a"; } -.icon-arrow-down:before { +i.icon-arrow-down:before { content: "\e24b"; } -.icon-barcode:before { +i.icon-barcode:before { content: "\e24c"; } -.icon-arrivals:before { +i.icon-arrivals:before { content: "\e24d"; } -.icon-bar-chart:before { +i.icon-bar-chart:before { content: "\e24e"; } -.icon-application-window:before { +i.icon-application-window:before { content: "\e24f"; } -.icon-band-aid:before { +i.icon-band-aid:before { content: "\e250"; } -.icon-application-window-alt:before { +i.icon-application-window-alt:before { content: "\e251"; } -.icon-ball:before { +i.icon-ball:before { content: "\e252"; } -.icon-application-error:before { +i.icon-application-error:before { content: "\e253"; } -.icon-badge-restricted:before { +i.icon-badge-restricted:before { content: "\e254"; } -.icon-app:before { +i.icon-app:before { content: "\e255"; } -.icon-badge-remove:before { +i.icon-badge-remove:before { content: "\e256"; } -.icon-anchor:before { +i.icon-anchor:before { content: "\e257"; } -.icon-badge-count:before { +i.icon-badge-count:before { content: "\e258"; } -.icon-alt:before { +i.icon-alt:before { content: "\e259"; } -.icon-badge-add:before { +i.icon-badge-add:before { content: "\e25a"; } -.icon-alert:before { +i.icon-alert:before { content: "\e25b"; } -.icon-backspace:before { +i.icon-backspace:before { content: "\e25c"; } -.icon-alert-alt:before { +i.icon-alert-alt:before { content: "\e25d"; } -.icon-section:before { +i.icon-section:before { content: "\e24f"; } diff --git a/src/Umbraco.Web.UI.Client/src/less/listview.less b/src/Umbraco.Web.UI.Client/src/less/listview.less index fe8af6dbc4..9d0ed002bb 100644 --- a/src/Umbraco.Web.UI.Client/src/less/listview.less +++ b/src/Umbraco.Web.UI.Client/src/less/listview.less @@ -32,7 +32,10 @@ position: absolute; padding: 5px 8px; pointer-events: none; - top: 2px; + + &i { + top: 2px; + } } input[type="text"] { diff --git a/src/Umbraco.Web.UI.Client/src/less/main.less b/src/Umbraco.Web.UI.Client/src/less/main.less index 2354e96d38..3bf00fb25c 100644 --- a/src/Umbraco.Web.UI.Client/src/less/main.less +++ b/src/Umbraco.Web.UI.Client/src/less/main.less @@ -284,7 +284,7 @@ label:not([for]) { margin-left: 0; } -.controls-row label { +.controls-row label:not(.umb-form-check) { display: inline-block; } diff --git a/src/Umbraco.Web.UI.Client/src/less/modals.less b/src/Umbraco.Web.UI.Client/src/less/modals.less index 4ce907d06f..a23756f412 100644 --- a/src/Umbraco.Web.UI.Client/src/less/modals.less +++ b/src/Umbraco.Web.UI.Client/src/less/modals.less @@ -24,18 +24,18 @@ } .umb-modalcolumn-body { - padding: 0px; + padding: 0; background: @white; top: @editorHeaderHeight; position: absolute; - left: 0px; - right: 0px; - bottom: 0px; + left: 0; + right: 0; + bottom: 0; overflow: auto; } .no-padding .umb-modalcolumn-body { - padding: 0px + padding: 0; } .umb-modalcolumn .umb-modalcolumn-header .btn { @@ -46,12 +46,12 @@ .umb-modalcolumn iframe.auto-expand, .umb-modal iframe.auto-expand { border: none; - padding: 0px; - margin: 0px; - top: 0px; - bottom: 0px; - left: 0px; - right: 0px; + padding: 0; + margin: 0; + top: 0; + bottom: 0; + left: 0; + right: 0; position: absolute; } @@ -79,12 +79,12 @@ /* umb.dialog is used for the dialogs on the conent tree*/ .umb-dialog { outline: none; - top: 0px; - left: 0px; - right: 0px; - bottom: 0px; + top: 0; + left: 0; + right: 0; + bottom: 0; position: absolute; - padding: 0px; + padding: 0; background: @white; } @@ -100,9 +100,9 @@ .umb-dialog-body{ position: absolute; overflow:auto; - top: 0px; - left: 0px; - right: 0px; + top: 0; + left: 0; + right: 0; bottom: 49px; } .umb-dialog-body .umb-pane{margin-top: 15px;} @@ -112,9 +112,9 @@ overflow:auto; text-align: right; height: 32px; - left: 0px; - right: 0px; - bottom: 0px; + left: 0; + right: 0; + bottom: 0; padding: 8px; margin: 0; @@ -129,13 +129,13 @@ height: auto !Important; padding: 20px; } -.umbracoDialog .umb-pane{margin-left: 0px; margin-right: 0px; margin-top: 0px;} +.umbracoDialog .umb-pane{margin-left: 0; margin-right: 0; margin-top: 0;} .umbracoDialog .umb-dialog-body .umb-pane{margin-left: 20px; margin-right: 20px; margin-top: 20px;} .umbracoDialog form{height: 100%;} /*ensures dialogs doesnt have side-by-side labels*/ .umbracoDialog .controls-row, -.umb-modal .controls-row{margin-left: 0px !important;} +.umb-modal .controls-row{margin-left: 0 !important;} /* modal and umb-modal are used for right.hand dialogs */ .modal { @@ -185,7 +185,7 @@ height: auto; } .umb-modal .umb-panel-body{ - padding: 0px 20px 0px 20px; + padding: 0 20px 0 20px; } .umb-modal.fade.in.wide { diff --git a/src/Umbraco.Web.UI.Client/src/less/pages/welcome-dashboard.less b/src/Umbraco.Web.UI.Client/src/less/pages/welcome-dashboard.less index 59c58c914e..426ffcb5e2 100644 --- a/src/Umbraco.Web.UI.Client/src/less/pages/welcome-dashboard.less +++ b/src/Umbraco.Web.UI.Client/src/less/pages/welcome-dashboard.less @@ -39,21 +39,20 @@ text-decoration: none; display: block; margin: 10px; -} -.welcome-dashboard__info-box:hover { - border: 2px solid @turquoise; - cursor: pointer; - transition: border-color 150ms ease-in-out; - text-decoration: none; -} + &:hover { + border: 2px solid @turquoise; + cursor: pointer; + transition: border-color 150ms ease-in-out; + text-decoration: none; + } -.welcome-dashboard__info-box:active, -.welcome-dashboard__info-box:focus { - text-decoration: none; + &:active, + &:focus { + text-decoration: none; + } } - .welcome-dashboard__info-box-title { color: @turquoise-d1; font-size: 16px; @@ -74,7 +73,7 @@ } .welcome-dashboard__card { - background-color: @gray-10; + background-color: @grayLighter; border-radius: 3px; margin: 10px; display: flex; @@ -113,6 +112,6 @@ } .welcome-dashboard__card-teaser { - font-size: 14px; + font-size: 13px; margin-bottom: 15px; -} \ No newline at end of file +} diff --git a/src/Umbraco.Web.UI.Client/src/less/panel.less b/src/Umbraco.Web.UI.Client/src/less/panel.less index 40c70f5331..115bdaed70 100644 --- a/src/Umbraco.Web.UI.Client/src/less/panel.less +++ b/src/Umbraco.Web.UI.Client/src/less/panel.less @@ -48,6 +48,10 @@ .form-search { flex: 1; + .icon-search { + top: 16px; + } + &__toggle { margin: 10px 0; display: flex; @@ -392,6 +396,7 @@ font-size: 30px; color: @gray-7; transition: opacity 120ms; + line-height: 1; } .umb-panel-header-icon-text { @@ -428,7 +433,7 @@ input.umb-panel-header-description { .umb-panel-header-locked-description { font-size: 12px; - margin-top: 2px; + margin: 2px 0 0 0; height: 22px; line-height: 22px; } diff --git a/src/Umbraco.Web.UI.Client/src/less/properties.less b/src/Umbraco.Web.UI.Client/src/less/properties.less index 9e951feb1a..dc6d2ff6cd 100644 --- a/src/Umbraco.Web.UI.Client/src/less/properties.less +++ b/src/Umbraco.Web.UI.Client/src/less/properties.less @@ -16,8 +16,8 @@ border-left: 1px solid @gray-10; } -.date-wrapper__date .flatpickr-input > a { - +.date-wrapper__date .flatpickr-input > a, +.date-wrapper__date .flatpickr-input > button { display: flex; align-items: center; justify-content: center; @@ -25,16 +25,15 @@ padding: 4px 15px; box-sizing: border-box; min-width: 200px; - color: @ui-action-discreet-type; border: 1px dashed @ui-action-discreet-border; border-radius: 3px; - + &:hover, &:focus { text-decoration: none; color: @ui-action-discreet-type-hover; border-color: @ui-action-discreet-border-hover; - + localize { text-decoration: none; } diff --git a/src/Umbraco.Web.UI.Client/src/less/property-editors.less b/src/Umbraco.Web.UI.Client/src/less/property-editors.less index 1d68c9f927..664be1dafc 100644 --- a/src/Umbraco.Web.UI.Client/src/less/property-editors.less +++ b/src/Umbraco.Web.UI.Client/src/less/property-editors.less @@ -131,7 +131,7 @@ pre { display: inline-flex; - font-family: monospace; + font-family: @monoFontFamily; margin-left: 15px; margin-right: 15px; white-space: nowrap; @@ -168,7 +168,7 @@ label { border: 1px solid @white; padding: 6px 10px; - font-family: monospace; + font-family: @monoFontFamily; border: 1px solid @gray-8; background: @gray-11; margin: 0 15px 0 3px; @@ -712,8 +712,9 @@ margin-top: 0; } } + // -// folder-browser +// Folder browser // -------------------------------------------------- .umb-folderbrowser .add-link { display: inline-block; @@ -811,55 +812,18 @@ } +// +// Slider +// -------------------------------------------------- +.umb-slider { + .umb-property-editor--limit-width(); +} + // // Tags // -------------------------------------------------- .umb-tags { - border: @inputBorder solid 1px; - padding: 5px; - min-height: 54px; - font-size: 13px; - text-shadow: none; - box-sizing: border-box; .umb-property-editor--limit-width(); - - .tag { - cursor: default; - margin: 10px; - padding: 10px 15px; - background: @blueExtraDark; - position: relative; - user-select: all; - - .icon-trash { - position: relative; - cursor: pointer; - padding-left: 2px; - font-size: 15px; - right: -5px; - bottom: -1px; - } - - .umb_confirm-action__overlay.-left{ - top: 6px; - left: auto; - right: 15px; - } - } - - input { - border: none; - background: @white; - } - - .twitter-typeahead { - margin: 10px; - margin-top: 16px; - vertical-align: top; - input { - padding-left: 0; - } - } } // diff --git a/src/Umbraco.Web.UI.Client/src/less/variables.less b/src/Umbraco.Web.UI.Client/src/less/variables.less index 840c6d529f..cab0745a42 100644 --- a/src/Umbraco.Web.UI.Client/src/less/variables.less +++ b/src/Umbraco.Web.UI.Client/src/less/variables.less @@ -156,11 +156,11 @@ @ui-active-type-hover: @blueMid; @ui-selected: @sand-5; -@ui-selected-hover: ligthen(@sand-5, 10); +@ui-selected-hover: ligthen(@sand-5, 10%); @ui-selected-type: @blueExtraDark; @ui-selected-type-hover: @blueMid; @ui-selected-border: @blueDark; -@ui-selected-border-hover: darken(@blueDark, 10); +@ui-selected-border-hover: darken(@blueDark, 10%); @ui-light-border: @pinkLight; @ui-light-type: @gray-4; @@ -518,7 +518,7 @@ // ------------------------- @gridColumns: 12; @gridColumnWidth: 60px; -@gridGutterWidth: 0px; +@gridGutterWidth: 0; @gridRowWidth: (@gridColumns * @gridColumnWidth) + (@gridGutterWidth * (@gridColumns - 1)); // 1200px min diff --git a/src/Umbraco.Web.UI.Client/src/views/common/drawers/help/help.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/drawers/help/help.controller.js index 268bfb3a8c..c212a08951 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/drawers/help/help.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/drawers/help/help.controller.js @@ -157,8 +157,8 @@ } function openTourGroup(tourAlias) { - angular.forEach(vm.tours, function (group) { - angular.forEach(group, function (tour) { + vm.tours.forEach(function (group) { + group.tours.forEach(function (tour) { if (tour.alias === tourAlias) { group.open = true; } @@ -168,9 +168,9 @@ function getTourGroupCompletedPercentage() { // Finding out, how many tours are completed for the progress circle - angular.forEach(vm.tours, function(group){ + vm.tours.forEach(function(group){ var completedTours = 0; - angular.forEach(group.tours, function(tour){ + group.tours.forEach(function(tour){ if(tour.completed) { completedTours++; } diff --git a/src/Umbraco.Web.UI.Client/src/views/common/drawers/help/help.html b/src/Umbraco.Web.UI.Client/src/views/common/drawers/help/help.html index aa6126e73e..6b924d0aef 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/drawers/help/help.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/drawers/help/help.html @@ -18,16 +18,16 @@
    -
    +
    {{ tour.name }}
    - +
    -
    +
    @@ -102,10 +102,10 @@ {{topic.name}} - + {{topic.description}} - + diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/compositions/compositions.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/compositions/compositions.controller.js index aa0cd54dff..ab8c133211 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/compositions/compositions.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/compositions/compositions.controller.js @@ -1,15 +1,17 @@ (function () { "use strict"; - function CompositionsController($scope, $location, $filter, overlayService, localizationService) { + function CompositionsController($scope, $location, $filter, $timeout, overlayService, localizationService) { var vm = this; var oldModel = null; vm.showConfirmSubmit = false; + vm.loading = false; vm.isSelected = isSelected; vm.openContentType = openContentType; + vm.selectCompositeContentType = selectCompositeContentType; vm.submit = submit; vm.close = close; @@ -23,10 +25,13 @@ $scope.model.title = "Compositions"; } - // group the content types by their container paths + // Group the content types by their container paths vm.availableGroups = $filter("orderBy")( _.map( _.groupBy($scope.model.availableCompositeContentTypes, function (compositeContentType) { + + compositeContentType.selected = isSelected(compositeContentType.contentType.alias); + return compositeContentType.contentType.metaData.containerPath; }), function (group) { return { @@ -39,12 +44,12 @@ }); } - - + function isSelected(alias) { if ($scope.model.contentType.compositeContentTypes.indexOf(alias) !== -1) { return true; } + return false; } function openContentType(contentType, section) { @@ -52,6 +57,43 @@ $location.path(url); } + function selectCompositeContentType(compositeContentType) { + + vm.loading = true; + + var contentType = compositeContentType.contentType; + + $scope.model.selectCompositeContentType(contentType).then(function (response) { + + Utilities.forEach(vm.availableGroups, function (group) { + + Utilities.forEach(group.compositeContentTypes, function (obj) { + if (obj.allowed === false) { + obj.selected = false; + } + }); + }); + + $timeout(function () { + vm.loading = false; + }, 500); + + }, function () { + $timeout(function () { + vm.loading = false; + }, 500); + }); + + // Check if the template is already selected. + var index = $scope.model.contentType.compositeContentTypes.indexOf(contentType.alias); + + if (index === -1) { + $scope.model.contentType.compositeContentTypes.push(contentType.alias); + } else { + $scope.model.contentType.compositeContentTypes.splice(index, 1); + } + } + function submit() { if ($scope.model && $scope.model.submit) { diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/compositions/compositions.html b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/compositions/compositions.html index 4096192081..436c4ea30a 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/compositions/compositions.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/compositions/compositions.html @@ -19,38 +19,39 @@
    - +
    - - + + - + +
    + +
    +

    diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/overlays/mediacropdetails.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/overlays/mediacropdetails.controller.js new file mode 100644 index 0000000000..d9ea5a7a09 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/overlays/mediacropdetails.controller.js @@ -0,0 +1,59 @@ +angular.module("umbraco") + .controller("Umbraco.Editors.MediaCropDetailsController", + function ($scope) { + + var vm = this; + + vm.submit = submit; + vm.close = close; + + if (!$scope.model.target.coordinates && !$scope.model.target.focalPoint) { + $scope.model.target.focalPoint = { left: .5, top: .5 }; + } + + vm.shouldShowUrl = shouldShowUrl; + vm.focalPointChanged = focalPointChanged; + + if (!$scope.model.target.image) { + $scope.model.target.image = $scope.model.target.url; + } + + function shouldShowUrl() { + if (!$scope.model.target) { + return false; + } + if ($scope.model.target.id) { + return false; + } + if ($scope.model.target.url && $scope.model.target.url.toLower().indexOf("blob:") === 0) { + return false; + } + return true; + } + + /** + * Called when the umbImageGravity component updates the focal point value + * @param {any} left + * @param {any} top + */ + function focalPointChanged(left, top) { + // update the model focalpoint value + $scope.model.target.focalPoint = { + left: left, + top: top + }; + } + + function submit() { + if ($scope.model && $scope.model.submit) { + $scope.model.submit($scope.model); + } + } + + function close() { + if ($scope.model && $scope.model.close) { + $scope.model.close($scope.model); + } + } + + }); diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/overlays/mediacropdetails.html b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/overlays/mediacropdetails.html new file mode 100644 index 0000000000..3814ac851e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/overlays/mediacropdetails.html @@ -0,0 +1,78 @@ +
    + + + + + + + +
    +
    + +
    + +
    + +
    +
    + +
    + +
    + +
    + +
    +
    + Preview +
    + + {{model.target.name}} +
    + +
    +
    + Crop section +
    + +
    + + +
    +
    + +
    + +
    + + + + + + + + + + + + + +
    +
    diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/propertysettings/propertysettings.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/propertysettings/propertysettings.controller.js index a6d1383640..6310545b20 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/propertysettings/propertysettings.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/propertysettings/propertysettings.controller.js @@ -202,7 +202,7 @@ var match = false; // find and show if a match from the list has been chosen - angular.forEach(vm.validationTypes, function (validationType, index) { + vm.validationTypes.forEach(function (validationType, index) { if ($scope.model.property.validation.pattern === validationType.pattern) { vm.selectedValidationType = vm.validationTypes[index]; vm.showValidationPattern = true; @@ -212,7 +212,7 @@ // if there is no match - choose the custom validation option. if (!match) { - angular.forEach(vm.validationTypes, function (validationType) { + vm.validationTypes.forEach(function (validationType) { if (validationType.key === "custom") { vm.selectedValidationType = validationType; vm.showValidationPattern = true; diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/querybuilder/querybuilder.html b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/querybuilder/querybuilder.html index 37a0d41207..05ebc56083 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/querybuilder/querybuilder.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/querybuilder/querybuilder.html @@ -71,7 +71,7 @@ -
    + {{property.name}} @@ -90,7 +90,7 @@ - + {{term.name}} @@ -112,13 +112,13 @@ - + - +
    @@ -137,7 +137,7 @@ - + {{property.name}} @@ -159,7 +159,7 @@ diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/sectionpicker/sectionpicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/sectionpicker/sectionpicker.controller.js index 55d7a75000..f2a89ba7ea 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/sectionpicker/sectionpicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/sectionpicker/sectionpicker.controller.js @@ -47,8 +47,8 @@ } function preSelect(selection) { - angular.forEach(selection, function(selected){ - angular.forEach(vm.sections, function(section){ + selection.forEach(function(selected){ + vm.sections.forEach(function(section){ if(selected.alias === section.alias) { section.selected = true; } @@ -65,7 +65,7 @@ } else { - angular.forEach($scope.model.selection, function(selectedSection, index){ + $scope.model.selection.forEach(function(selectedSection, index){ if(selectedSection.alias === section.alias) { section.selected = false; $scope.model.selection.splice(index, 1); @@ -77,7 +77,7 @@ } function setSectionIcon(sections) { - angular.forEach(sections, function(section) { + sections.forEach(function(section) { section.icon = "icon-section"; }); } diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/treepicker/treepicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/treepicker/treepicker.controller.js index 387dd71da8..c519a1d4fa 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/treepicker/treepicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/treepicker/treepicker.controller.js @@ -188,8 +188,17 @@ angular.module("umbraco").controller("Umbraco.Editors.TreePickerController", //used advanced filtering if ($scope.model.filter.startsWith("{")) { $scope.model.filterAdvanced = true; - //convert to object - $scope.model.filter = Utilities.fromJson($scope.model.filter); + + if ($scope.model.filterByMetadata && !angular.isFunction($scope.model.filter)) + { + var filter = angular.fromJson($scope.model.filter); + $scope.model.filter = function (node){ return _.isMatch(node.metaData, filter);}; + } + else + { + //convert to object + $scope.model.filter = Utilities.fromJson($scope.model.filter); + } } } } @@ -274,19 +283,14 @@ angular.module("umbraco").controller("Umbraco.Editors.TreePickerController", if (Utilities.isArray(args.children)) { //iterate children - _.each(args.children, - function (child) { - - //now we need to look in the already selected search results and - // toggle the check boxes for those ones that are listed - var exists = _.find(vm.searchInfo.selectedSearchResults, - function (selected) { - return child.id == selected.id; - }); - if (exists) { - child.selected = true; - } - }); + args.children.forEach(child => { + //now we need to look in the already selected search results and + // toggle the check boxes for those ones that are listed + var exists = vm.searchInfo.selectedSearchResults.find(selected => child.id === selected.id); + if (exists) { + child.selected = true; + } + }); //check filter performFiltering(args.children); @@ -456,8 +460,7 @@ angular.module("umbraco").controller("Umbraco.Editors.TreePickerController", ? _.filter(nodes, $scope.model.filter) : _.where(nodes, $scope.model.filter); - angular.forEach(filtered, - function (value, key) { + filtered.forEach(function (value) { value.filtered = true; if ($scope.model.filterCssClass) { if (!value.cssClasses) { @@ -470,8 +473,7 @@ angular.module("umbraco").controller("Umbraco.Editors.TreePickerController", } else { var a = $scope.model.filter.toLowerCase().replace(/\s/g, '').split(','); - angular.forEach(nodes, - function (value, key) { + nodes.forEach(function (value) { var found = a.indexOf(value.metaData.contentType.toLowerCase()) >= 0; @@ -541,78 +543,66 @@ angular.module("umbraco").controller("Umbraco.Editors.TreePickerController", //we need to ensure that any currently displayed nodes that get selected // from the search get updated to have a check box! function checkChildren(children) { - _.each(children, - function (child) { - //check if the id is in the selection, if so ensure it's flagged as selected - var exists = _.find(vm.searchInfo.selectedSearchResults, - function (selected) { - return child.id == selected.id; + children.forEach(child => { + //check if the id is in the selection, if so ensure it's flagged as selected + var exists = vm.searchInfo.selectedSearchResults.find(selected => child.id === selected.id); + //if the curr node exists in selected search results, ensure it's checked + if (exists) { + child.selected = true; + } + //if the curr node does not exist in the selected search result, and the curr node is a child of a list view search result + else if (child.metaData.isSearchResult) { + //if this tree node is under a list view it means that the node was added + // to the tree dynamically under the list view that was searched, so we actually want to remove + // it all together from the tree + var listView = child.parent(); + listView.children = _.reject(listView.children, + function (c) { + return c.id == child.id; }); - //if the curr node exists in selected search results, ensure it's checked - if (exists) { - child.selected = true; - } - //if the curr node does not exist in the selected search result, and the curr node is a child of a list view search result - else if (child.metaData.isSearchResult) { - //if this tree node is under a list view it means that the node was added - // to the tree dynamically under the list view that was searched, so we actually want to remove - // it all together from the tree - var listView = child.parent(); - listView.children = _.reject(listView.children, - function (c) { - return c.id == child.id; - }); - } + } - //check if the current node is a list view and if so, check if there's any new results - // that need to be added as child nodes to it based on search results selected - if (child.metaData.isContainer) { + //check if the current node is a list view and if so, check if there's any new results + // that need to be added as child nodes to it based on search results selected + if (child.metaData.isContainer) { - child.cssClasses = _.reject(child.cssClasses, - function (c) { - return c === 'tree-node-slide-up-hide-active'; - }); + child.cssClasses = _.reject(child.cssClasses, + function (c) { + return c === 'tree-node-slide-up-hide-active'; + }); - var listViewResults = _.filter(vm.searchInfo.selectedSearchResults, - function (i) { - return i.parentId == child.id; - }); - _.each(listViewResults, - function (item) { - var childExists = _.find(child.children, - function (c) { - return c.id == item.id; - }); - if (!childExists) { - var parent = child; - child.children.unshift({ - id: item.id, - name: item.name, - cssClass: "icon umb-tree-icon sprTree " + item.icon, - level: child.level + 1, - metaData: { - isSearchResult: true - }, - hasChildren: false, - parent: function () { - return parent; - } - }); - } - }); - } + var listViewResults = vm.searchInfo.selectedSearchResults.filter(i => i.parentId === child.id); - //recurse - if (child.children && child.children.length > 0) { - checkChildren(child.children); - } - }); + listViewResults.forEach(item => { + var childExists = child.children.find(c => c.id === item.id); + + if (!childExists) { + var parent = child; + child.children.unshift({ + id: item.id, + name: item.name, + cssClass: "icon umb-tree-icon sprTree " + item.icon, + level: child.level + 1, + metaData: { + isSearchResult: true + }, + hasChildren: false, + parent: () => parent + }); + } + }); + } + + //recurse + if (child.children && child.children.length > 0) { + checkChildren(child.children); + } + }); } checkChildren(tree.root.children); } - vm.searchInfo.showSearch = false; vm.searchInfo.searchFromId = vm.startNodeId; vm.searchInfo.searchFromName = null; @@ -625,24 +615,16 @@ angular.module("umbraco").controller("Umbraco.Editors.TreePickerController", performFiltering(results); //now actually remove all filtered items so they are not even displayed - results = _.filter(results, - function (item) { - return !item.filtered; - }); - + results = results.filter(item => !item.filtered); vm.searchInfo.results = results; //sync with the curr selected results - _.each(vm.searchInfo.results, - function (result) { - var exists = _.find($scope.model.selection, - function (item) { - return result.id == item.id; - }); - if (exists) { - result.selected = true; - } - }); + vm.searchInfo.results.forEach(result => { + var exists = $scope.model.selection.find(item => result.id === item.id); + if (exists) { + result.selected = true; + } + }); vm.searchInfo.showSearch = true; } @@ -664,12 +646,8 @@ angular.module("umbraco").controller("Umbraco.Editors.TreePickerController", } function listViewItemsLoaded(items) { - var selectedIds = _.pluck($scope.model.selection, "id"); - _.each(items, function (item) { - if (_.contains(selectedIds, item.id)) { - item.selected = true; - } - }); + var selectedIds = $scope.model.selection.map(x => x.id); + items.forEach(item => item.selected = selectedIds.includes(item.id)); } function submit(model) { diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/treepicker/treepicker.html b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/treepicker/treepicker.html index 0c10d94136..c816c31b3e 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/treepicker/treepicker.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/treepicker/treepicker.html @@ -19,12 +19,12 @@
    -
    -
    {{vm.selectedLanguage.name}}
    -   -
    +
    - {{language.name}} +
    diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/usergrouppicker/usergrouppicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/usergrouppicker/usergrouppicker.controller.js index 8e075e1ab4..b11ae02e4e 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/usergrouppicker/usergrouppicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/usergrouppicker/usergrouppicker.controller.js @@ -46,9 +46,9 @@ function preSelect(selection) { - angular.forEach(selection, function(selected){ - - angular.forEach(vm.userGroups, function(userGroup){ + selection.forEach(function (selected) { + + vm.userGroups.forEach(function(userGroup){ if(selected.id === userGroup.id) { userGroup.selected = true; } @@ -66,7 +66,7 @@ } else { - angular.forEach($scope.model.selection, function(selectedUserGroup, index){ + $scope.model.selection.forEach(function(selectedUserGroup, index){ if(selectedUserGroup.id === userGroup.id) { userGroup.selected = false; $scope.model.selection.splice(index, 1); diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/userpicker/userpicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/userpicker/userpicker.controller.js index 2bd73a5558..a7021b2867 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/userpicker/userpicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/userpicker/userpicker.controller.js @@ -1,7 +1,7 @@ (function () { "use strict"; - function UserPickerController($scope, usersResource, localizationService) { + function UserPickerController($scope, usersResource, localizationService, eventsService) { var vm = this; @@ -15,15 +15,18 @@ vm.submit = submit; vm.close = close; - ////////// + vm.multiPicker = $scope.model.multiPicker === false ? false : true; function onInit() { vm.loading = true; // set default title - if(!$scope.model.title) { - localizationService.localize("defaultdialogs_selectUsers").then(function(value){ + if (!$scope.model.title) { + + var labelKey = vm.multiPicker ? "defaultdialogs_selectUsers" : "defaultdialogs_selectUser"; + + localizationService.localize(labelKey).then(function(value){ $scope.model.title = value; }); } @@ -35,12 +38,11 @@ // get users getUsers(); - } function preSelect(selection, users) { - angular.forEach(selection, function(selected){ - angular.forEach(users, function(user){ + Utilities.forEach(selection, function(selected){ + Utilities.forEach(users, function(user){ if(selected.id === user.id) { user.selected = true; } @@ -50,22 +52,39 @@ function selectUser(user) { - if(!user.selected) { - + if (!user.selected) { user.selected = true; $scope.model.selection.push(user); - } else { - angular.forEach($scope.model.selection, function(selectedUser, index){ - if(selectedUser.id === user.id) { - user.selected = false; - $scope.model.selection.splice(index, 1); + if (user.selected) { + Utilities.forEach($scope.model.selection, function (selectedUser, index) { + if (selectedUser.id === user.id) { + user.selected = false; + $scope.model.selection.splice(index, 1); + } + }); + } else { + if (!vm.multiPicker) { + deselectAllUsers($scope.model.selection); } - }); - + eventsService.emit("dialogs.userPicker.select", user); + user.selected = true; + $scope.model.selection.push(user); + } } + if (!vm.multiPicker) { + submit($scope.model); + } + } + + function deselectAllUsers(users) { + for (var i = 0; i < users.length; i++) { + var user = users[i]; + user.selected = false; + } + users.length = 0; } var search = _.debounce(function () { @@ -95,7 +114,6 @@ preSelect($scope.model.selection, vm.users); vm.loading = false; - }); } @@ -105,14 +123,14 @@ } function submit(model) { - if($scope.model.submit) { + if ($scope.model.submit) { $scope.model.submit(model); } } function close() { - if($scope.model.close) { - $scope.model.close(); + if ($scope.model.close) { + $scope.model.close(); } } diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/userpicker/userpicker.html b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/userpicker/userpicker.html index e39d693b47..5536ce38c2 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/userpicker/userpicker.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/userpicker/userpicker.html @@ -19,7 +19,7 @@ -
    @@ -49,27 +48,27 @@
    -

    {{ article.title }}

    -
    {{ article.description }}
    - {{article.buttonText}} +

    {{article.title}}

    +
    {{article.description}}
    + {{article.buttonText}}
    -
    \ No newline at end of file +
    diff --git a/src/Umbraco.Web.UI.Client/src/views/dashboard/default/umbracotv.jpg b/src/Umbraco.Web.UI.Client/src/views/dashboard/default/umbracotv.jpg deleted file mode 100644 index 22ae3653e29eb07c489c976049007c9909034a9e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 49817 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

    Y+C^8i^ig)q#CDII(Q>0IG;>%E~_PH(-ko+jDh? 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 z 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 diff --git a/src/Umbraco.Web.UI.Client/src/views/dashboard/default/umbracotv.png b/src/Umbraco.Web.UI.Client/src/views/dashboard/default/umbracotv.png new file mode 100644 index 0000000000000000000000000000000000000000..173d2f36d089d560723bc34dd4f779d3986b2885 GIT binary patch literal 314485 zcmd432T)V%_b!YF6{U&|rK+f?2&nW>qJko#V5Jj8L`n!fR0ARidJv)_phyvsP7+!I zBoq-PAWD@45(3g8A)$razVH6;%*~8t?@9Js*Lt7ztY__~*UU}C zgr$WA1O&uPFB#tu5Duz)$(PsfUXBz5eU-Fz~Fk$nOgQ0p`P!z5iZOHaV&MdsQL$$@bqXH=$_kzgHdN+o1pU z=N>)tJIWKOocx~!O!LEmgCwcEV@dMycg%FzKRo#`*#IX;F z=6`0jw&{$BwzRb+*CDuHFGx8YuIDkm$NK%-lh)QAw0!;gvfErwg|!3%uUZS(3jNc) zcYPZ6et%H9Ex@#`=cORQS@wZ_E`BRxDXlZ%96bT~#q|!Z@r+ch_u{(mBkFiG&b*`0 zQ4UmZf|U1L>T_*9l45@s3IDRks`<8+gUgg}J9y*4ejT58i&Nbup=|mQ2SQ+cZ|tFx zEfn#8+q6m09p6Vib4p#kI|eL$*8M=hSdvwY?$C~hmsmh+GPMzlhFx6K8Rgpg8WzFL zyrgh&V{HOlsp2joA_BV<#$%IPziSVk)E)@VwhyAg{n$NLROcz*fR!y$_IK?1#P^*# z>*wcpSX1+M_)4qe*W-CS~=0vb^R z+U5_7IEe#Rp%GJvarj2Ht`l7?d`?6L=b`MN^nu5liSVu`J5SbOA2V}OARYuGQZjZT z%|8K#pw>r3OwkCHqvPY3FJJyMEtFm$8HwTs|L1%kI8GV1h&s%y>)GzEDT-gBK%L#7 zh61HEEU8-LVtCg_%Ne!W_LuHXMGb{9#nLqceyu8g-B-0+#I*bGa0rS!?jr>8One! zQ4R-(ReI45D=IeP(7YZ@_*jU(fC}>WqW3!V3TWL%hqyfv-M@1xtLUa;RHr<-#VE^# zBO1uez8a9okQYy4qR+{<>OH#iE-jR81oSs_QrgsDb+c{@cKsdUe5-t&Ilg*)Mx_Ei zm=!DUVRRsfOzd<@OzCrkC4YabsFE>K>&1Po5*LKK;=ebx-JSWqbAVCtXJ?rYY!^`$ zdyN!W1&zB2%F=b!j+G4Y$yyJ0VN`GS^$`?7~}RYkgp+(&_ZkIJLUxvGSqK z2{uJes4j$_Gx-lUhu<#oqu0>A{gV}}D?eG0Sr1R2({3J8MI?!Tj3^lS2JvawB8hTu*PGGbuOD2J1}EA0QDK!WpB{_A4!m`vRJbQzNeA7Y zpP&EagbIAT_I7ZsX`xEMcJFVCEV1)}tE_cszMK-j7P5ODBBa6I$!+woacv zhIS~01aw~bPG8sQy-*Tl%{abWHHKie?h!Z*LVLwV9pZQ!{lx6uYPWcisfgDbZ`#ql z9UA4>$Ox7jlytDPnw1rOFOza1rn-UD6ep$Wr67|VV|$n=J4j=fnrJs)ckxS*tlem4 z{B!`%VQyavFfgvnXj1k6XEOWpEEHr&c)RWl#8TgxJ0At6sFj$01cw&*fO7W0jz3*$ zmBjp|)F3A>T(~e)Vo5kp`bc8@Pcs?&q@hEt-=j-ehb;_!JH1L)ERHAk&^0WFOGs2B zKbUqM>fpNHLho<5ONP=YJ{QmCg9 zFREzwmTTW%v86Bu_X2gz`4c5^YmA*Dfmj;9Ez-c~$9M*}Ee0#m%65$*!7FRb_mvUz zoL(fv6%4(wD%tIL3wm4mM6`zIlYOq9c1njU7{)@6t~WS!AIwYX?a-_iIO9Rcp9dXk zeRZ#7s#J}TIji}nDAWMs7|<-8_dt@`w7ImD5e#vz5dP)wq)1CMgN|Fpr0>~v(>at> zOF=RpowT%+M%+2=+9q32P_X?=*+6&DAVMkI1ex65Z~w{mKR^-T#gkK~QUh(KE6Uj0 zpfZBJ`R~}@n&80VHp68I5(6tGOIbe4MZ=F@z&^^|ZR%h>m9gtXwkp zQWpm7_?Kxr@X3-6Cb1g0^KyrRB!nT1XeU?@XGy8`qxcRIXe=;Izj^8p>MQb;eD(eW z5d9eSyT=0IT!P}EkI$sE@L#rDB#J?6&;KZCzNYTx+GvaH=*lQk2d|Wn5b<{jx`8uF zZH9_y-!tTc4WPM4ZmrwBcFo9q&*P6cbR&e80zg^pP%$p|ds`cB2*zR2j;O2OWK~bd zuS{kmJ+BpYD`RR7`A@VZ?NPSueZIuN)F-zjDz!RptXl0qb?2<{wW5H*y!61-3Exc> z#Rzl5m3w~!|Bi-gJPk2fxO=L<+CO?dLVQaQZtR0iJwf?^?CyTzJ3=~~^|IVt=Xk|T z;%M}>M^ zCdd+2?LOlmH4$1xA3>K}JWo8&HJpkLs9w#==kFH>C+6+_es|r%ZxTZ$3j=hAK6DtG zgU)qf{2otdAvB2mFeEQC9B+?c_h_B%+8c58P0pr~)W>JOI`?4}rM{+qhu#~y#0zVLoex1%#AHhZZeq9H zMZ4VZaW2U`-KxP^t?jxl*0Le8Od82KRPkM8s zU+vbx`@CMpklb=^w9$1k|CB{Tbw^dFGDm$iD(XQhyAAU+W9E!l@}s`ba(Uz0^`#D_ z^yN1#F(eP1zPXd5dxxunZNKeF(&h5%) z?!hjfnvAF9?ZIZg9@*TwSCS;%Ft6L-I}#WVco}M~`K?Kr{f0uC`^Vq+EgE)nul^0f zZkp?U3A9Q}N^)^$^e!$2Q11qEmzcOc%v~1xPIiMAV@sb-T4SYmLgT=gkw4sQxM=}h zrhmtrceH;B+l^Ga`nb`&$T5O=f{-rPM<_y70=yf-$%2+mb?aWh<9F?( z2czQ`6kS@d=0)vJXKSjCnys@nBV%x1$<`32cIexxH0Vx$b9wGl ze0ZD`=v;9ap_lRVw$uxT+cnv0{Z(0*Lshaf*}ce?e;{@959M3b%zCs0v?FxMH{{I@45nb2GBZSw;{HrsThL7i`(uiz;9T0W;k^Nl3+K*9(zsVxf{ za&N+UYs z|7MUnWGOBlz*z)a&PJ_PFf7H=DqIdc%$@p85>4?waFWP8lD)Kmu7e`fjQZ@E=oAU{ zmRAU7_*NW2p(n5g4{_z~r-`zPzn?iRDu$@|0%^}M$g#pe1X9oa)ya8$y}Op+k&KYgI1WVr+mFYh0zwxKo`4RXVOSN1QKej5rp%HYt?B z{bw@Hat{`72^5T7Ulw{vS`nyTBZHHK!sJejY?VEz-mZ5ULMSP(32W(`9~vVXFaIoa zzSodr(pq$XWziq`vXh5=9$O}n1Z|%@>?+Su)Ezb9hR6&3^Ke*f$==C#;%h_U^R12H z$D$&_->v0P8|M8o8(rE~(p~0m6TjlXX$SPYOb22H71SIZ5ydsW*IoDbY;3DmV%*W4 zNfG)wWg>e3Ov(KD5B2)a03cB1p2g%T$yd}b8cr$AlUYL4y%j|maGQEG%?4jzEftW= z4U<2CFkgR~7CgH??|k0wcc&g|0l+(82Y0{p>-FIdg|Eyhp%$u?0&{-_?!$L&1+`4a zkm9vY*_j`W;ciIG*z5^~-@p77=XacQt0W4VuROh?&%LxVp6cw)sff*b-fy@T&a#T*Te4L$?k8`E|ufAj}b5?mGy6rPn2abM8Xdu&VAOO{qIAUyqoB zImfCsnFn;&-|@zTxFIQf{`s9sRLNd9R|;+l((E66)gV@BiHDJ)lZJxhQlS!Wh z{rO7(=bX55!w5;GgX&wkhPqDGa#>reN{fpi;oW!0IX~ zr(+NODtA_-S*B%mw8-i6JKnjfv-~qEu@LzLbecWnWn+e@P-V#ooHa4F7O5zW67RJL z1vc@Uuyd{}tfqwhKR^{`qklG-w5-(YcP!Zd>it=+4y$U!Qz!VRh4`~=8SfjF^6bd> z{y2{rIiPE+5G(uOk{?^La98`O=c{hFRYC^&RKKk-FhMa(8x0$#eDhSA7f*!C>F2|X zt5`ZAS)8HyIHQPT;NEs_&0kGWK||5IMxPr!8oHwsEd1D9a_DBhot09sU#vx^%9h%M zs8KhBY-n@V3%2BKB~!9VzIjbTltXthx9PS?2KzHYP{8eAH1@0v{lQO(QMx*)r3{KJ zr-_C=&X((Z-=Ol-#rEyZ ziq&*b*#79F4xUn z{i+Z7sTh<79~S|-szpAwuzy))v;Ib_)hpqcFX1jkEbj@>Rqlv0SQ zw+b~rhb-^f8nJfn*_U6N`fQlq*sGh5vbrszvJ$P%=BFj6iHl`yOSjD+5r<+GGVBpm z^v`meZz!PD-f)k~7WxkYXV^AijV_iYth^9qgjIP~_v!7pda{f0L4bV2xo zl3VL5+8GRNOuV+7nl~h%;sf09^YgCB`SN=y!|$b+sllajhtLYw9jV3ijdZnjZ>h_7Xg3NXFtkdw{S+Puu!^XTC_PK_Xr~@8H+Muv~2GQ%FXcnHM75**w!0*3J1#D!C%$aJQF5M zNao?0n{mZSt5%NB3xyV3h%lwr1Urkx{<wP8jmvweiT+6u28Fgy|Rg)z^Va!=TaHSi3ubyr2Nx@T>^|#)bX+qDx)1T(fy;e z|2=YKAeOwEU`$-H1>3AjWa!P*+}x`M@x&CwU^)H%NI97%T{TX%?wC*e!f76O=4ehB-1*=xLi6s@MDJ-!?(=}jT-$HHmc^F`=X7}&srU5uL(Ej-( zd@+j?z03T$7Y%P?qJXGCYzxHr|F~|_=X;?drzj>sNZ~;VGk5u`GUnA=?>ZZF{d%Y_ z&~Ik=VwQ~p4hwzj-=<4c?S`uorq57SFkVGYAHp_HfQotK`t>8nj~~Br>(*hiy?;C{ z7Q`qn_k1E#TiX@OOEd?y1Qrxe?qFJX`iiIVZEI#^SS+uPRMTrxIGF`v@x@efeo{Hct74iJr0mr{r~hMD@F3M7;o z%RKwegk7~l*&eX~^C}D?P_8_om+P8EThX@RJevsyy9+k5rIgP>IH(yI(7Z;lfZG!g zn4U5R^8$3~&Dn>H@~+LkIu=mofZs{N>DVclV6OmK1zd(htv5gAi;4t}Zb6GNg`j98w^5Lkh#?o}(&87r7 zW%c{to)_HAqs*QTO$Ty7D-6et6Y8#Q6#@O$Vx#?xH9i^g^5xDDAWJ(&vhz+#frPds zMB#mg&hz=I(I^SS=aqxub}`~|Cn7eugJXjm>y=kB^!wVnUGQy>wuszYU7VW#anqu2 zhZg8#KrB`-aQZpG%UYc{abmQ`$}#Ce+}=J!zV_gQn~>n4Ei%t8&SZyiSo6yxNUAeK z*8qqTZrIwMSQ!5<;=KVpn;g@GuQU7sJ!WrddDOd>Z5b>V+a{xa|JmAb!7_Dn4&qm~r`3}Z~He)&SMjMyDbA5w`OCMP4CTNUcy+Mc1(Zoo+s z-FNEadQ>;!o3Xj>*zW4J`Br8)n74Qn$dgr&D+&uQ*R9f(?YwQ<8)GFZvr4uuNbd!2 ztStoAWz1aFrtMb8q1K%*8QF?GfE&~{HO7d=S^vVQOM6#^I@6JKPouo5Un{sj&rqBm z(4k5ea)L2BL;cRP(+iY<`y6Npym_dE}#BeJpIx@gjBK zSQyr9nDg}Bcr#%b)D!_=;$7l@!rsuwy3Ev)Qd3i}wS10=>14R=%WrtA?*4=f5Z_PW zkO&@pZskE)I4^Vsm{QoR)V9s%?KI4(I9Q^0J&%MNUQAsJulJ->n6hd)1Fz5a%8}@G zMMXsh$gJ-1?{8tj{TRpkCkQt)h?tp-wDc&Sj-09AfY2F=3^SwKu=FAZL$F@{X6qjB zF24tJU!?qKaB|;Al5X-=G{s}7MJbb?W{f5!q%Y#Xzfm^<^68(b9%om%gBt@7GRm$p zhV(3Lv7a4ko~qG8>O2@LyK}(sg&|_~QbkzQl=Z@N&_t>xbabH|EKwQU^Rrz} z)Z=y0LYn1!$MBULG52&+!5$#nZX&A)D(*qJN!7I(Y8)mZNIgA$a4pZ?J9d$DBSNC^~Jof7mB))i&x7bjuWp}k$-0Lrd@F-rSs|49%l<9 zOEU739f>LM*s6B@g=fq_>q_rGw{}XC=m4*m4oF+PR56 zhC-oCyo|P2g-Q%t7M>Ye2XGQNmFMs`=AkGwo?iHRgdeucQS0V6)(1D@ya$`v92z++ zJht5XN64E@12T2b5VTX6J0O;mn|oALDE(*4_ViB;Hy@Q~t%YzS<}h=0lJFYu`Ejo8*2wG_!J*msf9QJF|}vI(S$d`gWPe`Wa;1 zoyy}5j8K9eGGy1&C)Tv}Ss`D-SwU|%)&<=p`G|E^SU;$#EgB2b{6YRR0yv%2mn_Og z5*$+zOxrtlzHQh2SZWfB`eZkhB+27v&<2lVW@(u$7hy>Z0P=u#dEo%1z)#rrsfMt# z@FgYJj$V1a!&VxgOA5IASS6NGwzSwlVo^hGOd)Wb$OZKuEV9Dj7?U3&v&!u`l5!-E zI7=0ins+x9rf2H7USXap+1(VYb~9p0PsdFqvG4Nmcc zooMHq5|tK-?5s?1NFNlDGG0uO=~~qppLDiWD%Pyu1#BOG2X4vjGh8jJ9Y0djxHXzH zV1xFQ#h}qcA)U|=krK{T^-s2TCIBaXl@}f~t5)=d)&DI++ImCnU zoat5FN=it^#Mnyp;MH}m#Jev*%mn+WJlnrtPlj~aC`#kUZPPm=!gCRG_#dJK(-Rx1 ztdM8-DuS$wP-iqhcgIcvaBFaDjM zlS@ZTHm>j~urFV};BKSL%~DjcC_SXk@HPT+5>VMBc<5FXvz&DU>hTt0m$1)5Mbj}8 zIaw2f>r0g#8IM$4*`f6LMsdAwF&WBM=!(_=duurnOX5aP*(CVHqJk6!UbAbW^UYyCXyG{TOHT$+I7)C zkS`N=8Llsnz*3q*^(P)ALG+XkkVf3KyUm+XW7VtlqDE9URX@ z7j|bZrd_v4+mbe4>b}O|?_&Dy!C;KgX?~Ypfff;_#!NY-idH zoK#9G0iuZV(CTNkdLXD6ew2B%3U_&JQ1#U+fZ)G($b6VbtEbX5{la3gnGfbob%F!j zw6$0zfxRV8lC4R44}KiKZe66JGeej$qzd=cCd3p;>v%}jgWQ$v#169+n(_Le;#xqS zbqI$vv18J!Q2fZl^JCHaD!Kmav;FGl!-UQ8_GGdp7M~EPUYroZ8Y%7bAA6Jywu0dpMKTEb%Q?2MRpJBuE|o7-N5T_`?SL0+W@ zuNLHGlsO!Po(XJj_-5`OBK*=!kUO1|^R znc}B(Kdrk6Wb#GaSVma-Jv&CVE%$M2ua4T(HPtsGdJ}g@@vjv+c`lRvcS*1&_LHDA zpZzjq>jlcrWN$fKjk`}A6I*`Syx-fk+ zB>bW?*bLSgpN~R1+ZqG`ISd>#0{ zn-TF0cbZmASKR31{4tfB>WI;fP$$?eo^fW;if+}F2?7befu75+^pP{MXXGPfOv!Iz zb1Pvd3CT+Hb!?FND7FLkQUuDmI!iq7B_E;l>Sy`nwiIeODf{arTkpuYK0gzWH(RSl z>W6=5hSIU-3-kl`BeIz9$$}lB{8Repo?zB92XUyw%|_D9hxPQ*8|=(OeZJI|3}T$C zw*(Zf$2?@CB&H5G;0e7^^)|OIl3+`R1KEH}>kFA1m)zY8YIsXj+>ydA)krMVnKK%V zrLfDrMk;1|PJ3myE6KwUMZ^L$8b>ux)9HlNPqHiCy4T9L>6G#H1VAp9e46p4yC3lP z)z!<#fD|L5X|t?+!-F(|z`+fv z9?Dh0I%;lcF_hk}3BDv4H~H=?*h*eya#3AMQr|d2-kzbkVl$v=t3Z_Z_e^B_{I*rEB!P)L2{ zdD@SQnXV)A#^-2l?kq%iaf#OD{^U=m>nj)S)1i_CrU(oE9d2>UJG15$Ye{j#nokr& zVwGwZe56u3UVo|XbR?R3D5PQg)nQiqDb6+MRtZ~$PA6s?$wa3Z?%+5Rc6w3o(1~xR zi+bldBlfYgt_JdiK^=BM>rN83Kq~JFw`qG$8hcp9Vm|1SzXqr7sSN2NO&e0vNI~pc z8}L{=X|e`^cZMnX*1j2R*p6}81s@ka;C$F_@G9<?2qly4G%)L()|~F- zOgh4dadh?DR?UIL77U@t3D#9Fl8BBnc0sOs3p}(0h;qQEe)M;p4%KencN@H^-JppLLrdW&|%SGzFR3Rvr1d<&`40`r`)M)d^FwjNDoJ~UA9%3__1b(5W~!T+ z=_}i3vY)i`&^*;Ec=7)FM(k~zLpvi#{UPZhutJgEXkAOKfq)v<**;mqPLdX&;i|ik z_+h-dHHW?~Td>yco!YrS+%aB>+7~W9I~a07OpTL#-X#df`}^d+9-+wk!3H zc(hW(Sk**T|J-0FCLjm#5FD6v4mQ;)HUMZrmzI}DZa6Be)zkv%~c*V3vDKMs|JsNJWjU4fmI@r;-0MwFC8`cq~) zv(7GxjM<&%ir0SjeiX!c8n1?6wmv8a2L-)&@e&;V&CH986|KKiY0nKHU0n_REFmE6 zn6Ia{va6;eQ0Ne9_YRz`wG5nh_mK#v8t=GB1uw6L{}kbv*f3vZrOSv(r^ zB^Ly_^^{TcisP5RfigoB*9iIn2pMu5Dr_b+Zh?DjRecmML34Ssp$EFr&4w8dGTN3p zIes)RyG8#Z{AsQx2|H&9M|Q8?4}@KCb_a@1Vv=kW&}@=c?{-knhV( zApsR2N9HEz?f9UgxOzyZ{b#vu;L&1O?`rL`Va9Q+%f?H(Qd`njJ&Po{%8b$KjeBCp zLH1oBV#GdpoH%p_&rsFVDhNxbsT3oC)V#~e{8(TuKPE?24xHd;WgP|psbS+a*Dewk zX}Ie4ErbTp(pj315`lQzx)Sd#76^7F-zpR3g3@>+CQW$V(K<-805(6Hnf;CKZBl_k}_I$x+eyCkezLktpw&gYy&P-~eyy&EzakE4<{ zlLwt`x-;2Lv(5fAorvNgw|RBRFN`V`RBa<=7XD1R%IiIJ$idq;T;WSUm^Da^PXoU) zU5*tq?WvTU$%tP^y!bhg!0CHdnGhtg6;xNmNZZMScs0$GO_qI8gZgbC=Fm{&h*A~g zbn8o$pt_p*5^3(7qvQ+nocK`Um&I?j4B$OS~IveE9_?BT1M%i(TN4KgkL%}A#zjaMv{E+-a zx%yVC1<+yV z!(WM-jF-`-AUtN*fC`j8IG_OxriNMy_HL|m>I19IDUYlOiX^6{D5)f1_GiQV=Uo=f zuTMLBiri5l#MHE{xbOD{1Y0X>3++rpjR3jRccTr|3=(2+otrRSmS00@Y4f@_VK9_f zayD27*f}4)j&!z?_5mk^15E`0$$MUc7+(;_<-m75A2>~yg?p@dJ!qU5HjF7c>C}=2 z?It2aTGD^oHdUy40sx#dTwD5}lw51@iSq5+H%k#HZH(-{F#QKmrSLQ4=(h3qBzE!4 zwk$^4WQK2L8(hsFp(UeoSzmrawQJRFu0-p-yw_7P^R(G3QG2+tV%yR6#Ijs4L;hek zl=g(x?#yb<1@C%suAJj*XX`)n)$u*%i*3v3%$nW8ax`L4Q&14#6>JvS$RLFy+(D@s{E|-iBgUQu!l^#cwwXq_e#+|& z+$J|oK1Z_byxK6o?m`USn)$u+o^_FP7s-;J{+UCZy6q8Te=sR1bEq1VjvdM!85@5U zrQhCd1~79jo$oIUk={^Htd1-r*uK09Gb$Mp_8s>+AU9zLKzo?Ou!TeOfJoK7wGj0P zTP$5nzjgDbGcm2lGRHh5l`2-2Q5nc7O7zMjH&$zbAgDm^=?uWLxSs;SC>nh@*jqp} zZslsXS~vSiL`$HaiKBX2wE%D&hq|lT-^0|X=t0L|RnwrkR0Du{UrGgVc|=JT{cDmk z^GrG>9ia>IZOVl;?fNGuNFj+BJa4M#!8Eic5e4>2fX-70uIUNFMkc&~FwpbT&5>*tG?C-g zFI85mhQy9tzfu`HX?o5X;%8DkBD`-2?x4*_d&s7d zswg_bAu{J?&5q7hrFzkUfm2b4%ALS8zc-q8+>d^j_e~<-)Au-ea+D;0=5!- zw>59RTv`+8rjc7E(Z3pOpyRuCmPU?A+=6jb$6W3NM?(wz4veCP4>8adH zADJqpkuN9#49~`~DqugkG(6gpl{4T%+F^xpbaKj~nYR`>>_f_Ew*_WSd!|hGQVK1J zUGRh=6x=a_#|FsWkwK3G#VG&ud1n2_Iu1TF-B)e|y&!KAHN$6fhS)TXYozwb7(&~J z5pv*E*O6Qq7_e>bRPLPFQkd79f{j;$%Q#*!35c6!-ynxXdR?gR2&(NMb$kx#WX`?R zjp1IX4znY-hQ-4AMzP5Ivf!m7l~5`hfRG(HNpho&Hh@Iyni~8}Qu0b!_QW6zLwx(r zEn&4>rdMA4cC4Im9K=7o{cWHATole6Ee2VT%dLlH;y zX9}*>Rw1bY+S7U_i~@s3TaH1uH5knp_f-L~Ev(;rB*N$rSfP|Ca=ET9Q9_tjFC{$# zYabl))rk4?Y4C#t#kRrQ;+R3b>-E}q(e+$;O-9p?0?Cbf=Q%?Tgc$VQ-$4x%c6XOuxfyn_l8|B9J@aEwHWmnu1}gw&H^Z3 zq%TmnXnZn=0cc!c4tDnTo>9${rgkhoReZ+f>u##wZ3lqw8DeS%7z{sAoIVYtzC6j_ zA&HRk7m6knplkr9d8sEEhcsAv&Ai+P?Rp;6SLQO0j961VbhsxOyGs6)lamuDS33@B z!enrPpjH05A?+fDk*4eK`HqoMQ3t=`?26Fl^}8|b@^(ozOm~v#bpI|8Ql!1mD389e5 z!ceSgKl{b9{OM0l=GWeHyATewtm8ewHBBJo@hIKp`&(iN39@jKNzxo;mNIYOlVP4c5UelE0Q*$12lt2AHKHP-cQQIRQ;&I>r!G6ni6S+O5NFcauPlzZCkhK>RrL`gfkrVZdWhL3`!NS6V zVzM%f9m21-WL6HU0?EyCz64aV)k2S{L50mESwY-evmJC8>+&I^FP@wM@}?WOtSNvg zlrF7Z1@c*5c5(F6i`Mn)Y>YF>cT#r}EFdf_tdGn_*{D_h{6o(Rjr+qAr0TgC9%CfmRutV;Yl-}m^x!%q2juT1Kno=bha9R zrK*@GZ0!c<;9LES<4jyt1mMTkX~d3sk04?vLz#w@=KyAcb?F=tmDV_xEBgx}DGi9+ zvhanFF4p$;NTE-wEg2YT?3s96M;7^c)bVAkalM=6(EL_p$}xeGmpb7!caG05H!L7+ zDyzwgt7+d>G$13r9Y&S$qH-?_1|6~^9?HmprWEQf#+rko%|H3f#?GD3%THN`s4+(% zdk7BMZs>ZN<1&q( zV->s}RI>arXGD$WNJ7AEGpN__+X1z~54;W~&)~-gv;l8X#ks0D!`Qd;Cin&8Foi@I zNL_Wc7fPlg^}0_HsPHv470x2Ie+y+D^=lGwuM*_wyIE0JrA zZ$|fMGeLFAqx22&-GjvP&l_yQ4XeP+TL#Z3sv%HoIL~)}u)lG1BK9*bZ8OlSz`O6& zcK4e0XIH?Dek_SW;Z>>Q(dK}#q?KeM@_0fVGjfOQX5jAa1=MvuOo#@eSVivsiM8Rg zZ$coh?WZ*MCq^RFs+gzyYY+KX`xoT&wf5=Dp-PCnhF>$GHFae;UX% z9l@`xbra)nk=40%uIc)AaI(!rQ1Vr6=7XSSn0xDYrRE=i0ASi-U(sJu)QV!D-2N&c zpltS;yeFt+1*8$XBf(Dx&p$80xws>$j6OOPNW_wTOQ6#T|IclM+Wd(k0dEwjD0S9j zs#&EEm>RCoP7^NN;R1NRIrEG}a^{*3n3_~h*8Md#4{>mMK^~=};HHulS4b zz21oWjYQ{geEqZOpy=Y-tPva4j zp4%Zw-A=J`O?(02H6R@k7%+*9I1m-#`|jCfQ1r>#r7H2xBl9ndkV#nxiIi}qjn9GP z>DykvTIr}W2TdK;o$hG-gc8g)IwzyU`>eQ6^s#xx4o@4Lq4+|+gjKpRIhJ7F&pu~O z4XyG9(&>@_Hg3}>`3?pY)>j&w=KJ;#adyg7746JB2@%iq9RpsErq4Q4=gCEX2|VBN z(tSQ{=ev?7?}mcN#O|abJ)b{?w{B0jy;x3HG~YJ)LlDrPl(GZ1@l~+S0ImWFh+VYM zaf=8!#=T|}(096QokMJ0((-U2&^jJ2FDN6EghJ&HIV9+REPwXbbdB(Js(^@8+;pFg zE=rIVd9#KT$ydMWvL)qyT#Uv3FyXgw>Yo;#@HkvBpg!V_c6E!tYKcNtM53&!C|w%) z2;QeQKA`_vn!c2G;jedI5F!Ds?L~3J<)2SJwro$8H9zIn*l_LGql>mw(KwAYSSY4JgW_4%@_FTqPy4Uqj)u~zYJ0UlnWHdTn02k*Nn-ixkn8? z9lPJ3yQvdE$?PaN0w^H!pRS&&;g3AeFby;Z5)Tyntz!n2@Ror2osH$Tydkb%T7Mq; z9M~CER{-622zNM}*^A>lFH8HNw7fC0yprRaF$MeZXEktN*EgYU*XJJrq(Md0VeaxB zGh2-FFWv6Lgc-o(p98hcj|G*2I!4F$=u}7jZE!6l6JzD8$khXzJstQnpYWt)Z*RPt zPZ-?^{3^~u?;5LF#~Lz?sQRXZDOVD6bv)BL(*o*EFyX#c+-LNww&S6}7r=^+f_YOG z&YzA_5k*BJR_!InKg;Pzf|#knfHfx`rbq1nWZQr+6?EvI${cNfzLGdnNPcqvw$R5{ zDTpF+RlXDWKmcWrtpeC!Ht#CQU~i9r$=$RQ z9m)a1A^<&2`!f-6N{8(fIvX+x=J`lc9{YpCfv}#NRS7Tu656Q%$Io9+;Q#&K@n)9) zV`UmkeLx!PcWn*O*$&*2sp-@q2SSFbYucR52>IV}JhWVpdE4$`PG|>SZgL3B?Q8$U z2NeH);jD=NL|JM#D_h+Ha9jUzU#2rHFq3~ewdt1=_$81MN_Y^)1nKq7S$^R)QGfh2 zGUWg5zcrSrmF@do(^OYhs^AKNhhy$yC|yanFnR1&lhdhri|3Z1{r_I*fg z34r-}-v%2f0u>#yf4|Sd3!vep-o|lop;}idOtPeDVP%?mTUzf$ZOAEZ02kg`KR!(EcP(`(t?f0S5c=xw% z^GLOw0>OZh|NGMrGE_vZnR`nT_=}9q$sFUy2?{(1dI+{Z9pD916ysXB(c41&AVk~v z6X*Z>m~fMFX%X3Ta+E0zeBsVV?y1X0i+&js1QCI=fBZAp``zE>pMK#==5hFcEHJnE zs)84S0~e63O5|MXgJ5mij`z@)|43ow8ZUU?N#26uxTN#+tIs?vW;H4unRd;~jdkcYP42dub(d@5 zpB|4ec=ercvPU3P;-8g$KikRg?cVTJT=?Xa_mDJSFcxB-ranVe0;-H~c+-d&^HT}NQx0AK=ve-;STtq>0VOJU1F zPi}kBuCIBP!d;em*&KccFytNo4fzw_qI=^*w^*O1b1#x|b$hG1eyug}`w)fpZl^8)*XpNO}x?vo>ik0eu8(sh{(cdvr$Cdj{ddtv*w$-7vIylW@aE93VghPp%38Ojm@(@(aia|8Ubk>Jv4 z7F*MkGCR?)VB3CNp?l#P^!8}>)(6*-Q2CML&xmKsP2;wq_}}ZGtUAY^k_TZ}*%ZGm z+o_cwe*zQ5nPWdKV!VoWg7FhK1O|2jjgVsR-zp1JgTQ4ss_xKCS)L1MxH?tr=rt4F8{b8o(7E^He}C8OKHKU5n4t{)NWe09 z|BgCvsW%JTp1@kYd!ctBMUbSKi@5FOq&3DjA8Wv+k>a{;+Pwk-l`NpM3jja8jIehP z-c3|157?3yT5MfW2_Q#B|LWURIN5h-bM9uh za4fJi9^p}2TFp8sbvxMubmE)$YKz&z^9O(O`EQA8 zPbvv{if8c~CziZL)+0#Bw?ctOO*JEMj3q=o(EMn(t-Zx8`d(?`fg+MM4xSAPm%jSD zYF_DQa@Bv&5!6v~EBb@|eBwHO;-Fkdu&91 z|MFOC^IP?DYr}`1L$0$7O@m^m`Pslip4{eN@i@Q;PBFl-h>!f9f?~aSGpo2}u@IB` zIYy%crw#!IR3Sh%_JNgXi}*Eo2tbE$A`IPw_YeU#gSTtWLa^=#kJSIfg0Q9BtCKP* z-c#3xHyx-~TkH^yIJAf~14QE>Fy7W0*D}(>cy+{J75uxCB`y%{Jup?5BP=EywB$~6 z?Myc+;jf&pM^q^5`rsB#);mhoO2$Jly(envL`Y6Zk=w!Ol|B~JLORIsG(yeEPB0Q5z!q!b8rR)-Ws@` z_$Gz4IPBE^#%Ux<>k(A5t2)=%I!9rBQZf;Z$iQ0igMwS`yfw zQk%1(#R!}a$_fg(HWlkGn~LZUc%$8BhU`XetB$fqO|O;DMX|2pVAzMm(r}k@U~N{H z_x>l(?i-=+!lnFzVo$T{NiQmGLbMhBczbQh}Kd=jhj*y4mT!WoQUv<635RB`sW0tm+#x-ZEA|t8SyDYN#NTK$EkR*n4Y## zc}s`jIRanBpWE`1Qz{Aq2C^Soa>K`qXkJ$b2C2e(2NbPaLh#{QKlOGzHn@^5vSvi8n<=3bY_S6%zeUx`}T(yPix z@ze7A7-iXm=uTq_(paNrJE!H;jdBg9@x&jf4Hi&#idFt&4AVW~uaHmS;fS zC!U4E?ba5uuu@)C86LehRU+?^GYnIGn;B3;$@|KZNkDb&(~SfGzeDoSfe90k!H~J7 zL^0{0nbd24^LoVm2fTCpv`2g;Nwt0QOX!_8oSBLskx|o<>i(OJRo5!-AH^|$K$=9x z(TzxT!?-S~^|jhDdi_%ndv~>a8S8uR)+Sop@ibshU-KskcK%$}&nh^=_VXDh zxhHauDf(*YSvB0_vnp^NciC3o=zaO$Q86YxPiBTs(qSGp)(o798-7)v+bptV%ZodnSS_2WBtc+pD?K;uE-NM=L_)+Zt(^(U{hNh|I`$NW%nJkN($Y`2h6}6I;=J`aN;*P!)zm2=Y*D1k`_q$OHL*`?-k8qEnFO46 zDx!UFN^O+$2_s&15-5foyPYUq)@Dy~0(-;{7`FU)F&BP(*o+am)SrleNQvk!LwNQN z#oMX~0VlOj_yKLJQgS(@0kNk0Rbu+~lgp;NzpaRQ`Hcw6dJ{NvP#?p)%whG?r_%v7-} z|NRTxJu@p8dC{9uA|mQ3FinKyabNGiFw`3Ia4oExI0*3-XyyzP-f(m1F8oh*{%FBp zT-{|>n}yiLZ~Yq=L?YGhT@}Y`&AI?E`Xl^xm79HtGntKdV=!1g;m34Q$)8r>v~8R8 zOJ^`sMATNd&AemttXl&e$l$)sX8lluQa*AY48B<|8OFbmlCvathmzMUYFFCELUP%F zpPHBF*jo4T0Gz)Y+xYYA2@w`9HxM60Z@T^Y@meg)h8VuNRQ|v2{a zW%`D4+l=+W3j76$7`=0B5hla>`Pz(D;oJ-`u0R?og#~?HVw_AKMeWupd4XOzZ*nl`A>9mMGD?Htc@wUlqb{T=rZuacj5{p;#*8f`F6( z(*2CMuNB8f#sKD0V0&YaMC*3$g9nkcKskAdZvm>I;5=xGppilo-~MA2<>P^iqw$gT z7h{R6JYRSK!ecHurOUjJWi45n7>v6T6cZu1Ncg6TV^+5)A2V63`J6$b8{VY>-@Hx(xCq zqgMn71%)@15f27g&)xO$?souJ7w}vV#ph#)BAcJ!r^=eml!mZUBCi-_l9Rco=~A$&Qiwq) z;;7v4z#EbLw3!d@T1DPZ{Vv3o4<|hg8w_S#=$SBUvkwn${g8nmPs75mDF!_8Dp@%6 zk$t%w5%1fz@!;0riP`zqcl;xBytkHlzHJB4;L+S&0`DysX;;rH6$?cZ&D&y#fn-)} z+d$Qq#as8A)}S>*v%shg|FhV)mamB0%?&1QAA z?0#MxL(*sQ*j(m?)j`QM`+F~@&SN$_m^E=wOK>z1cdrX@w)V=!=Vbahdb}2&i-@zW zohqplN5=f_T$P-&b8ZH#ifx$OKlV93Fxj^vZ ze>XZv*9l8qWOf8bd$r-joVUIt00D^z-~l5p-P>FAq(ra?%D!cMEK^nW)*j0jpiiWa zW5;1LR3}8<^+w6Un~aI=uq_|(KLB6EkUZ<3g7F`;64O;hZoSY6>MW_f$*=NnvFSz( zYTmG8i*Wj8V@6Gp-R~HtH@k0jQ{hI7A&IubUrrdB%|7c$#8tE;JlLS;+v!}5Mw0UG(d^Bx`^r;+{_Yvsz&VW0;*c~x^6ORfvuczvu^+gn$K5U1Ol^jQ?3q#53Jj*f^B6R z%fIg0t&zp>q;C~%fOOB!XQ#jO{(F6E@}BB$F#wO3fDwX=dz~v+?G6E^uw<}ZO%hpJ zaz|ad`_%>mtS~$00|@`{d1c^4(a*E|#+NJANMW7B(67Jks%7TY`^LyfvzMC-so{D*`TxX__;1~b%xwk9 z1q{9G`>2*_E-Cp{T6aXO zOj0T+sZ>saNE>yzI0FNN%>bi{oAK3xzMjyD0UJlZK!^cLCgg-TFXqhB{?wobg!(Uw z(T}JA68Nck3+qW@+@olsf)Tb!Tjo||NN?lWMdYJ*;OCQq%wKj2az3cGbzkMCj^4Sb zJO&_|9*~vD-pVDzH81*{PGaTK{EP3EY9|LW-6_QtN#}F_qU1{KxPSQXqS?(+3meAD zSRF%WX|O^Abh*60x_+5$u|%(28uFndy$J-V$lviZI$FcW02*B)SjM$$Lgqo&m3yym z+lltkIeqdKqo&(d{=v}AK*{oWoe98mU-%Uloy+}WTT??@RmJG(AAx!Nao2Gdt8yv# z;>>{?c;Q$vL(t}hNsyhq^lr}hnv!96mh7pzuW=ZZw<)@YERBNEjcNF#nx`cwsNztD zD+%j5Zkke2$3cPax}~Ryi1ePw;z*+I**$2?oa4QMe8({(^@_nRLP%bRPP~<0Tn*WN zoO_TLkeP#ZN_YRMmit5zNVz;%3DSXKsa|$#-NG*Kcj^Ps#UtD5MjKE!@tvz)bt)>s zd%QH4H#ppDweW=TXGD>co)55RKQ0~Y1O7c#2YcBTAc54H_@7t|mlN(&^ zvOtRVU6=L?l1fA>#?y=qX8oz3G0p|!ovBs?=u7+bo*-2I2@K!wa@-^erDY2^Ag+yO z=*18F3Bxz3QxMsqH4{|ahkdAYU7Oy8){N0O^x~i)%8g_^sd~!-X_n%>+pi$>2{Xt% z$JU92m6Bfh3h)Xvtyo@=v(+D^qA*~y?Ob7?(PmEKo$uOPulB+DOu6l&7Px)X+_sO} zT6fK|3t$2-?SGMT8P4UbFoJLa2)_>?Z5va{^3{4=f2p_mA^6eVuB_cvfe^qO^7Ev4 zYy_LKhUVYxex+UOcVYh|z=O-G&-QDwbK1J!0*7_E-)?J6P*>%LByKvR=&MnHgMIB5 zC63)+Y2$bh20!$-fWRW6{X4Pp(jrOY=!_6aR5Dm%vW`_B0J>Bxm!6t;rB^bt#@;8- zb8*Ez9z7f-b*JZb)%aQuO7}i_jE}va zo`^1=-q$PF;DF3<_NQT7m)_v~+KkbE_{HT__4ZGnFL*86#|o^Mjtvs-08%C|f@6r| z7*p(!AfVl^|4q)LV^<}AEIQa+M$H?oB}M*Thfu1a^#xn{EAr93wXPdWQ(t;N8#WB| zR|F2NB^0vpY#T|UPLt5n^m6t&p9mtzpm8nwn#z#Y&!LnS)B5BSvFlq3JMv@OG%9mBVw zmP$LwM*b!_pjF->f$OhcB2S^M?ACsN1mx}ErSkCmKfQ(Ng%hS}ePsLQidfa+enmBW zUzp=%mYlDV-i!QW@hPdp&XRB6uV+Kf4RtWQL!9H$lC{f<8goA^>SmX}avJwcP=8$+ zX=G9bmarB z#x^~d3}r;5A)$%s^0!7MZ#B4eVPRl);dpetsUV=WV#r!&(mym{lZKad&TnjL+!P!X zKSe*Z>Emyw1+Z?shXOAid(68w6un;;r5JdOl(T!M-!E+&Q7vQoN5qwq6kEl#OV>8N z;jSNiJs#)lp%}*$?i(GWw;tFZbPEi0%?6m4e~0I#ztn8>BL8U(hUmKLXw^gWDs6V^ z3T@^s&wN?!L&mHBMHeInXb?H&q}TE4;SCY+6r96EI6=*u>j1zgfZP+PkM=I-5PWOp zX}CnOf*?^f7BI4hBz<6&H0PPs0aAI6hld^5t>KQ@6|Toa7O~Q#H`EO6&HS2wdv+I9 zTI3wsQQ06j!uttXdrQl{svbm|Ek?J)nnD^qlSFv36|hc%E9A8vY(vOmhG%FEp?Kjd z(5fT0)L5){x^QgdS;pYCd(~^&?g_dUz59))f7d~XpM3P9{jao{b}IPDDgdeuh1w6t z0j?VHK!x2$(VKk6^y?;C+bTe8s{8MshiyRsV9YLd}X<{v^r3v>qjnttuY@vx-ILro41C69)7$pr`WYVtH= z1c~+7n^-`hzFxXiv{`kFT;J23u<3M*{N9FpwnrTH^Vl3O_tJV|5I`sMxA|SF06418 zsW~Fdby~mJ8{eeMZ;%bRye$MQ)lzRD=+*a#{Dsp zSAG|fd%pD3Tv_sC0B62y-9|qOrr1HCtYEK4*%vw@9*Zh=V;OSj2vY( z9pjuiDr}mfY!Xs`BJB=LuP&bhXVBsxfc`@Xs{<-;8*}posOfrK6v^}qYBMzz8T633 zgLpJKYh%|SPOpg3wWsKnPLcIb;62@+O3OtFwv7tQlHTBY=SBmt-K}V|t9OFGldOn+mFa;+Ib37oU#h-}u|Y)wx} zgwO1!d*j1Fv!9&C{oY_N&S_ot-7c{BdjJkjrYJp^KlfLIr=8X7g zEwoWe<8~@td?yt1Zin)Sf~tiN9lx*7ut4FgF{6+A<&jLmT-~T7;eK9zhI8R^&N;|J zP1@WA!@nz8o%dT<4QJH5-OPEBKgOID7fGSwkUzRO*11Yh4i`FK4W4NXlh;6!nQ~P0Z}X$x`cJgC5TSVT=OheT|6vX z*5UV-M8;i#2@O?1*9~&;(5X(62#daF%Jpl)WAeh%vhR?bazSX%Nkgji6;7tCXGmdr zh~>dnJW#u%0#klGww;rnp0w40^(3kE%5=+sq8&CELKZ7b9(n|L=l>1TUB~sUm3^EjtA?C`|Ac|NGPgF>2U=@boGKl| z46JBa^L@3aU)xD~e?;&s!=sqy*Vi}2ejN5Xifw8=-KJn{)7K8!%8=AvxSd&@YJ`Mh z@;R9cb@}K17H@Xf(2Zov7dpRz6BsGs9V%#SWKg0k?W=sJjiLA4S>z&l36Ug9n_p6M|XZ z&_giRCs7abC(?~-$--mxx^c<7#UtEvSN`~MxX%~?A^r{v_)&&G+T;X~4Jha6(3yCV z-b{B*W2_W8V@nm_oGp|5wtPzU$1+0IvG&D?BRtoUo8Nk^Mc)1%aNri|7cYriKDBc6 zLQ7yzInHalCU*Vn!sc(F03~n%pgH<^wnjBaFjTHTpu&uGW1%IDi#RzQ&=Fk2DHFUk z51I%uMV7nlbSmI_GXF5#MG`rJoH=j*;zn(H=8@>2!)Bq~f?d??GG)*E71-Edh+%^# z+*7Pg1w-LZ(3o>A$|u@Mu(>N<46l-!(I54R`T!>|(MDsaCSkFDiqhYgKP1J~E^Cg+ z`+C3`3TPb%WnV zaKB(f0)zCAsHU0(7s(}ztRjhFwL~M8$9`CR3_|3KJfz85D*Tse@0(ivC`uJim@S{e zcg-dEY=A81YWY@9I!9+WrqpO^UI!{ps(OY1VVUX2D*%^&5seGBRU=FDmojBA8iaz-uA3Tjy**02 zG>!$N?7J6bm&$V@c!zycC+~K7o!1?6exzz4e`UI!H zZ0j=~ULTz05M+s2{4D0$ZYx!y4RD+d`}aKZvfOVZSy0&*6D7hb6i&_H^CrP4CwDoxxylGj#J$;(0R6RZM7)ZYD5^i%rzOiOR{{SB=No2efiU*UzWY8>KX zb~dlquh(XvIekEHydKO-BlWu0Q!4Q6-OEQ0z6MeNp@6+lIt_S7J40c!v1-rl39hk1 zK0|u(W+EA|KZ|z6kxE6?Bj@G!)CdInym)H6p?_%O{6YK-;JyR_#&v1BQtj9xvyx;| zFCty{^@3bzx{IqhYCXc4!%4HF=4D@O*Z$ zZ`kPD5^@uqvikbY{y3cA2qztcDQ<~=sYrv*Fs?_LhmDV%w&n{dId>^ds{eGIOjp-a z@>NOds|Eow z?tjB1DCrc)4NqjMxyQ(bDq8jb*}v~uPIV@J>DuDyymtwVuzFl>;w<}>{DFl-?m4`k z`S@2+`#YB}lRGpVV{>cIsQYdKN8l#kqc$uGP@8@^CJy&jMnT&+wx&Uy7CC=q={*;Di?GNa7j$Y#CKg#s(-XbTLS%1S$tc-Ns@m|XP z^6bc!OPI}eBj!Efr24zY_FB1K?+VJge3C!}6EwTZ69Qb4lajsYLSoQs`1QKHUH6Kb z@k8!8Z-!*|w1BV}+tFnzgBJLiW1EQXJJW&~z@%>PzeA8#N#6x!a!rfrA@izkb$O z1$+Q@1Afk<;X#|?Y}O6Z{9q3E?F~KB zQF;t|(iUQ?F)@*i@OFyD1SRb0$+A`oGcqU)|TZT$2x_T z=MB>5e|FreE-(VOd^CfO{<#w{LEEbq`hkT(Wp0(`kEI%Q>*#avhfPufz+o2L1BasW zW+22{h$zRle7>qNY*RP&r2?h`)X06Iz4dKtQ z9l$~g0c;0CB)hY!OXkX&tg6(V<@N8q+U9M;awP6lV?(C1f4}n>{Oak04=w$ooP6Bg zc;nyTV{%2FX$BO_y&%$lC>hH2{d#w;xN>kBj{0j5E%$b)D7Q#Dk;D>;Wh6+uMf@tG z1dby=ec`$$mNmogeAI0AGgEEbTTvG9=W2Fc`$2*0+o*$oms~H5zcKzL%W}@Jts-Ky z%$jt(g3uZN7Md)9k39D(JzPAf9F#+{VYCCzx$q;P_M({zWF7J|!;O6Ho!SEqHFbT0nkg(oB&|v*hw~LJ*k?Z_oBEST=Pt?)Jag z;Tr97+yos*_Cys*z@H?r;T47?ra9i%u!`q~+2~4=*KiY$w(KMu_FC@*`^f@SmH@F8 zc-#=hD(eXA_fCi!QgI(ML7NaLg5NPKmie|LN_9WmANlqNq>Mc^Ha&IV zOdY_R#&b-!g@VuVb!INtfj-U&H<{NOtCb^?TxCeKPiSpPZC-9t?uvPPy!zpk0B)HV zz?=vN^hyk|F-FY7ojzhQiCz;Ag&>c?Y(H~Qx$yQ1C!7Yhk8FstSM1LPgNjvQ4+rT= zlPK^JFI=YjtzO@bdbOHtmx7r2@wANaRO8wYcNw2W-c4;1I@OpQHw;vr;6s2I z4ENn1U=nUvR0n7w49lGGO!?3lrgu7X*kJ@ngaR2uVTYCaj;)6cvW^g$nb1NFbpkHtJ&+hJdsy!>)?LY=pCF$i%|3Od_Q}8I6&l9a z-`>fsSPJVPPgj4_B<&6;aXFTH$3R>tw(|<2%#P4VGNHc*>)ZRqEA8*pICfk;HA5EY3XqDPpq`kC z84#>#{?h-~UX{<|raCKZ-HAKPgMR_xoLN_6aGvaHa7y0__tV_SW?0iN)7NLl^!V34g*&+9j+ zH1(dCSj|9OATO&z;%zeOtwgcCjg_qQI2<{*pZXIwfrBi-GVHzRIUe+{532{KGI4AV z5AfxZI=4EAxxT4b7SXPLSw1=LL(e#p;zbviu)pQp`KayG(avh$NqT6F{gx~Bv#7N8 zT6&hRDXPOkNUMlxLoA^fjV*|dB>C88@P4hh^z0cip4)L=QqKLIzg)0h?<)BMrtpx` z!fnIaK?}l+is-JQ<5tfTc4Q^n%G*;+LrgS!_g~DwAN6{l1)Gwf1#Xpp=Ut`BeyJo5 zq`H%ZzBRZsdC*T?o-Ca9jQ%vPnU=wmSLVVt;KDtY9d&zl!iD_5F0^I(iMw@q#%V17 zRd~%gADj$z_uJG+$-mufLT%5HKgDDz4LGpL_m;A|r{U>Y@MKpV%X(;`##Rlq0OhLd zjs&<{{>SMAPUoLO)=l=c1-JeH54DwcYK=9%Z1qmrA@H*jD4NV@JK+-CK~fYTC4pC1 zH!BTqe!a~r^Ozncx*5{R5~=&a>gm-E%61t)PTOs3nqE)_&!;;|Z@zci_Z!HJeWkxM zH4nrJ1uP83fa;bvgYs{C*ZFr#qY2$&3UeK6^1S^e4vNtbo;i1Q;DH*X;aHcbj5LtI*l0CcVvZKvZkl)7+(ng@t#$G? zfMWa=GG(<_6VSOEFF74Lnow>qkjiWJ#@_Q7Kb&z%J5<$&>)0rV^%5=URzm&#-nN88FI$9 z^npjnk*)jj2X(e2Cxd49YRr{dXfUR0=c1iC9Utxi>HM4Z9GeU!SP+eavQfF$HLYt? z&%Z*8>loITbpLYcRPZg#!Ofuye&h$#b}@JyYIb)^fjjoE-nHzi!U!pBPWSgVqgk^!xp%_1nJA&_mNFC*5kEFGKVss@Dk-~B_E6kYG#S~L_{OxvH+CFctSe4*>&LykLJ?K)*4&60xy`0 z)-0U4*&`qKmDk$t;}d3TH13sdi1$eWI#pgEe zY_P|JhLt&y8!a$pADlx3@7N@LO_JInYEA>(<%a+D-JWOzU{%a=Culovwd(hTrw`DT zp2P?O*l!vD0bc=<4k0U@=KDN%2sB{-@!Gg~kUbM9^CYD zMy>@Q82>fDY@zbYmD;Y5?7dskx6N?`C8rhUhN*CLr+>(`?#K;d%G z6P2la%i@5Pk-_lQN#%!e9pD;kSlBsiB*jz^auw9;Uk(x~Cfsg^M24D@tXEwdq+5Q? zkK9SjdlAU)%YNaz2JvYxl#8(6g2b1D>L6-1E3W!DN0L<*q5ODB*`d!lcfQ5~5kt&24T*;7Gj*sh5Ai>k(I!Jc&khr1m13o=z81BILqz`#LAYWy{f>64_`c0CxduM&Q za}(CF3N~3$@Bi&uW*=FmLBEZ~p}||%4C{sCYxR%@n<|Ec$dj+J8XNjMW`KMA{Pqf5 zm-(Og3aDbT9RKzIIu+1;gZmbWLLJd^Y@iD0Mifa{eei+Bn82Z)5)7UvjI!PWS2OTG z$5!KvfQxojRm*WcP&?6Lv}R3zHoecO`ajjseNJLbK)oAU%P?W2Rjt$4A7BU z#wM&fAeS%~AUvZB=Y29=PHF0R!MdyrE*Lj?*)_RhjmV*+# zJjPa4wSady@kp8>yqr1Lk3Y>hbrTb`{Dp$*uvZUnm>7 z8M2YnY2j$A(66eqvd$G#idawznc^&SdM1Ra0g+*r$i*{qn2?sS#@o8+I-Xj4zGvCk zC$tXQJ$L=i%eF{)-DL)h%kBZcOcgH5oRw1ph1FrUa z3>TzMd-uZe^8hN*Wfi#bp?BI;>GuM&7uS7qGW0u5DP+m0q#T~q2@YRiWyx?#grVq* zj@dGP!z%`Av&AW5<4CheSK^{ht%*f-(X$UA0MzII>Y#v!=>Nn7+YKtOkf&;aB8hZ} zYp<$%&HCtw&mC7&#q$0?RRJE8N~f7}hRvObNU?^Rju?R7Y$JNQ_zHJGRo@Ax_QVv{ z`;BNb)j99hNHJ1cO+eM;DQS_oU-eJC>@Ipz#U#YE1#ZG~UAMh=0q#^+l&w{J{^iWWRfVmc1*GNg)0HBlm7%7U$(X}lhH?pUpD zeDZqZ`MB@COB&}n826DBId+%@yj{6*`hfIR_wsD$)qC}PQ8^zn!7z-t!@i;3W^?6R zR&VGpJF2K6sB2maRL{rAdhXVo^{N^>bo#uzqng8Nj=IIdTE+&TKQ`U96%wzh4P~1b zc$M*KDJ?o^=uV@81`WoC9SXF#x-!>LoH-q_M19_4JT~~s%?P_gvUg(oUT@H^I~v?| zYV(!I1K5F}g z5fa{J>^6H$gHUXhdos@nXF!Y~7*Hx)8Rp(fp@`yI=drHbT2M8x^L8)6vDoY3x5p0$lrY25$2jQwuDcT4;hs_-}E7snw=4K>-{f~#fH887jTdMCmvp~%B$+{evpoV;t-t9&;B8(YRYYt>)kNqXtwU^&KSM1sbM?D0z|4z(tuV&D%yv5VMbtnCL z4)_iq|K!^bcp>q%Xxdi=@?|#3mX@H2jk^SqTZy`S;e1d{cF@Y5kS&6##S9)mP7KPU z9du0VbL}tNha3mo0J8LmBDi(&!;5jd?)HtuCb_KAbqiM=8GVB=mzK4T!6SatPQ8Sm zw?YDcx>r9cbEKE!lShUW@AWPiWOUnmj!no9N&-D_xb42rzr)DwUZ2SARCPLVk#g7! zO3MUL>9QpyIAJlo+MmbiQw*fz_4Xq9lEmWeI_`-nyARav2Gcd25cm=|Obqepn7k-`b!MQVrA;pFOtc$&y%&H1 z8Yz~mvSH{CAv>jvVN0i}O6;xgkIAdENUAF5PIs1sy@n-cLB_ouJz~Y; zWiC@e(jr%FlopH%z|B|de$>}hKL8%FBV;a0$U@O056G4qp@&ln;Lxhho;qe`%9XhQt6MsZH$)~ReATkGs0sZ(j5Nb%gjnV; zN5ADX7EQFr?WT=U@U`veGOo)?jHZ1P&J4ztalIWLfAAE=WMPjPx?_Fbmm}x8(Esvs z$r6K_t!@Lvs)g6wMoPxRR9re`FDIu?Q+o>-E~3LaON;K+#LH*3F7I6Uk|J)TzHyM# zk$jM+D&s>Q+!_e2c5^0{k66etHk`8S(iJi`Qcu2l1XC^U%sR4u2Iv<8xJv&?Jp)@^ z)3oj78QWz+@5+0woFBt(h1?=p(~ZyGy%>QFjG9i|3nvD^K6P+VjG#Ohz~D|dri_hj zg*uX~;n(4GA%L@jNNN~!DT;Y~2RCw2c^E418Lcl#d5Fqi&OB?bz1-Nh@)V-5r-Si$ zB=vg3O*O9Ct}u(E#pw&DMhx+d8~~2>RJutp#x*9_GCKb_CPd@tSh*j~W%I*~1$=3K z<%gVaSIGGbxS|AiElZ_^Rw{OLq10>SJ9E5IW|o{sxc#|-$9UdUq1U)sZz116 zva)z(V4N7CfLRemJa2g5N^}V2%KBZKsSbIWKas{%v;!|Kow{mhVB&CDMvdN{&Jwg= z4F@8X2Px#n`)RVPE(Lw`$#*poA&)wIrB7b{>JWRRZaiJO+TS$3F9WW%)~{;ur7hcd z)5Nl{q*rwtwU%mVH0-|(c{yEVvbj8Xgb8H=D2YgIHFG83LL;N4tisdyJ2t=_HmBuM zRk>5HEp$-bCjAO3Q~P5dU^EN8Rr4i_cMH^Pcg1ek&H)h+c)hV*?gM{d#eFa&m9auM zHQGoQ`srm48blNJ!#mXp!*+7fJ6}qk56W~IOa1I9o}mCPRVl|E72}c`-x&M>K;k>! z)Nnb~Oqyib91z79;nZINvDAq>l$a(~Jp(^Vhn*~cf|Is=@1EXIEq-B~AL>+<@8N*~ zOO!A53&np#XZMTig&^*C6o0ytSUI=VB@b_8iYiqL4%}xu-@$EgctM8 z&{@VVmw}%?1-Fv}56nCx;_E-Kj-#~iKdm!UzHq+5%KP_*iG9PcJDA=``ldzI2+j8I zd3@EU+#xUk6GrfD=)-Uow^E3`bJT=kwy>9mS)hz%ZBJ38Ox_|EL5pjq{ha1d2> zP1SWyEBKl0x(B7tYRz^22dr)^lZvuXF{@t=H5|@u>hYRLIbL>|QxBHOhkrlGetMP2 zxJp&x%wTjKHvPL#+gBBK<#spl=(LfoC6a^xBg{b^pLc_g7?+sj0?=iy$k?ZzvI|>Y zma&BnjA2c1BNTd3wGmKSts;}oT?FGyUI3vByK7Z)@QxUT-(2%=P- zHg&M6Pu+tyI0hiy&)~X!+Ty~eS3*$CAaZsxezejo6>SjV(ZYI+FlFCwe~a_tyIaaP zjRZ!m_a!Y$D*HUmKasw>g#}HKEV~~wBd9S@9Y|gjyQ+6W_F%$}hG44HDgW=h@$B2X z+v?1srSc_~cPW$d?4{_T5pVg&j=xcbZ&=iN`8X6(;P;$GV+`L?zTshg(E zsR0O!v&ZPUss{BZ;*%H2SA0V*mE#zdOQUlIBO0R@OlcThJ^8wbim(P)EVIb*#8d_m zzY}(jlZBE#o$(ufiu3JqJ>FYT45S{#<$XHX-}b|c?ihVPX-LCf z8d_*C$kLd|9@ghnZBZn_r2Z_w(zJ`%VB`IMw~Ye3k4&a5=M4sPY1K~7X;$#M}N(Wj$19wW&*045)M1`~B5si8gp#=$Vwdf9(GmRnnCER-`RN0Q8y8Pu+a$8|u zxn3pvGd6yYML*&d*lxWUCllF|FMQqRoEAF1EW0?nQfBtA1gU56W;KRo-Q)hR+8A)M z|BK!F<)0Bb6UQ0p)G1YBb4843jp*2YyRx3L-YO4W$9hOt<3k`Rm~LE~Ev@wPsgnKg zd7yiH<&*f{=iOeT%Iu5Eo_1wySw{+_f`WLOe>^@#zD}~Y%;$wwhXZ1#sStcaM+kmv zops#z^{^m0O_jf}ya!6ag<95#P5@PubV~`qlaHF{(>i%(Nz_W#r;*YV_?-;-$+3Cj=}ZhKP^;07BR|7*%&iFjF6; zx{Mt{i+bl?hBFwk^?LMlAQmY2a{8-R5Hs!gLgz~{lH|f4Lhx>}i_#$m-%r;4YQ-${ zml`z;-Nqu4jPa*sv=2a2p|@HJJl-pYEUfIVjsVA7F;-l>=4~w$-&vU{$f9T6<57&^ zA&)j8Xk)2SMT2X7{Z99CCu zAy0mQ%6HE~Qn7ARw|0U70HjJFpwAJH|9_rbW~G`>waYk~`krUd-iGx)(d5{0{ZKSf zC>ikU^ClzLZovSG{>qGH_1&D_net?{a@^O-K-V;fP@0J!#pvnK zy$PF))hu~WW`Qr;5sLPq)2V6z(Sc+At(Z86ONTe-5T`Wf;r72*q)JM7dm8l45Uloh z<(&20t)Cy-{K|JrUpxa2Qb-#Qqh~mG2L})jp4x0AUt4v?*j0fH%vrKg3Zd3Yt8r-r zdFk|O%*f~T`p4z?(v&(Low@~Gx64J&8)N3_%heU_3T#u2iN+1e;wi5Rcl;!fUIF@X z1UwG^zry#)kgpfY?iY?Nip!5mMM|(s^+)MbC#yCE*`>rcdS2YVsrJX@Yl}Ojr8m0gjI(PL$BEtfrF4a?+BFwu=4I*J zwSw%(jXQ=4CuKY-Zbr+4`&UM_{aiRPpc3x^iGU}U=hwIe&F+1k_ql{8zdm%+srJGN zNpacx4QU~N0}dE@^S#8^b`}eTcQTpgwS!8N$yyfPb$$t9E2hNhVnij00o1BWAA2dK zM>gp~Zv8qiCZF=50{-3lv88o_FIK!k(mYHtYWo_ts%iw%z*hW1uL4AV`OF zgD`XqN=i$JbPOFsICM&bLr6%6(nt>7DBayDHA5pgwBL=-v)}#h{d?X2esjzp9QSbC zbI-cgwc=doT9>s{M_lozj9b|wq8=HJy(H9=a~d@A{HG=`FaJJISR=s^XVfFL>%N9} zwWoEeXArk=^+eM{u_>mjdlB4|E?HTtVV@SSy{kMME3_w)4=Ey~*w>*&@9Nvdu z!>;wp;Mt2(_@>*jre#)eW#KWKWUJMJwdB={9qfaVnx|E!P;Fo5 zVG+4=gXbDSikdXN%>}%j&)4z}lieS_$`%anM<%3m6nyHnOQ21xHKs2>6W8tzkQ^X8 zbxg{qOM-fZ`*`QSPL7WaO9Lar)1gs1yIw#L{Xy}nk1w68BOizZAOEK~u%ZE=%J9o@ z9|m_9xe)ax9giwa3j(SK!O5(4KtaL%uG9Z?sJk(z&Ag~N-} z`(>H?<4=7+1J5T>VDJZ16m$98?kb`5v91%tEp49{mzCZ?=C`>8m7hWdvwzfYG>Gk+ zV~$R`O3GSQj)~3Kk5+yDJw>_JB;m^PZU6jXhrIWq!$GH5Geb;nNgNtHMNQ>dCb6Jj zs>BfM#qM%dBzf(+XHO!$K~{UU%THI2c9k9EyXc}|Md=CZ>8I34b|~u6xLm=$9I-IP z^nv=pFvgzGixKfg^zx?5M{f?k`80pr&Ujcp&(_VBK-b7g&N>)zuFBA_&HBq@7uLP^ z7U)Vcwy~bSCQ^>UTj{$r2gmAM3+ShLZHOjboeKfUyp`KttCibYWxv@pjo@B%)JUd% z1G7y2v~8gyr>n;G#dfeN*y&S)h*kchx(apfhYU%k+QA^8_FiX_$ZfLP$cDPM4HLO; z5l_52aXI)-^rmb*2FmR=134R{9bFql#{tx8gI=hQ7M-ZOGT*G_RkD|*p~rLHXf zlV$nao(n2y3}>8rZzsIEmvyf=#yr@ITq=%p57D(OOrI(I`4=LfclInD@ zWG-wnY(Bd>j&6#Nhl@oO*z!+)wa>%uABCZAW?sx-|EKuUYC#={m8cWXGEIKcb9T>S zY253CkK+OJs-=K~sD-=>tBQ}it5}-DI4&dy>Rj_o2p{p!Du3+D;NF<1pSn&NwW}dW z5mjRL?4fb~h?4p2 zO0Eyw&nIoQAke*j6}_5r=tqzyre1cD4C_mzBWdKho5nW(p(6>#5|sh#kS*~>HXJGn zy7%)=IwWNg;ly9UWL~8ocD%ZN{~+45YShb&K!Hn+&h8rljG}K)kW*giR}}Zp5!KqG z4$F7lmE~(G^5$~R%@3lZtc&Frcwn}pbmc&vjd~Oh_V4KV3)TR>(b&MQ{+n7Dm{80#?&`yo!( zRi3}8v+A9@WJbDwdZn?z1j7#Mokm4OFY2pMztuOOjyEu1L+SH<*UfYonb++tOwo#t zgBHJBa_!y}R)081%0Z;B!SOa>Mb}#|Fa=$|AI)!(XYv#~rm*FSS`M&dLF3y%=y7s= zdF!vCB%mwinIPb$fYGt7(PP_O(eoZPB4?ML(;5`G1}{1bi=u*ptSoV_ z^xGysQ-4)%THK9~T9aRGDCh+8Z{sZa5*4!x;5b_cvlElUQL*Z&@}P8Dy)|M(J}u>kc%QYNmOgh-%fTcEXC{g`g^|PJC>(KhN4xB{8H1 z**j@2n}wgE7hUp9))YU6iNGGgaF{W2E-|vBH9q?~AWT-{6HH0pDRJc_87oH>UNYx+ znnsTp`yF*9vdw!aezFx@i~c11Jr)$63wYx3Bij0BEx!0doBYqbgRO*)=8ZwK1;&9#ihwr*X3!@cN{!%(dN# z>XulqhD!#InzPy|8z6Q5MxJ|vEvC~lpMm;CC}OH~>()NWxp?T~D|&sBlUq;+@U^!C zU1>l&WOb+94)4pdhdqygV#3?OA5H^3sVt&>XD)-RQM)tZQ^2Wwm!8tal#9CQG%#r2 zb$y~&x@DXT|Ao>ZU*|gSOdluT>;TX4`G>6ZGj01vGcAzr%}jRh+$67LnBXXR=a@@Q zErS-4eDtu-{5!drVu_1w;#N6Ov!4A|74lz+31cB}Vw;9D(6U*WM*r@NH^yYCQzwf9 z7uQFk@-8Wh{})UDSKkaceP5)Goo|}1;50WJ4&QTwtTP^5)T6rGnv>b2?!f7DE&KpG z9hHXB-f>s393Vq#2}loYi%Qo$4UgV!l#%t-visStwpO>;Odlz_k7&3)aVax`HI5}- zSxDMKcx{|sWgyf$5jz~TU75pCygVZs!hprt@nJJipk{2KKDQ+fJZX!mD%V z4Gb(Tz4Qpyz-%^eX_m?y9Sxo6PG!?VCgcm!BWuVz!_F;~4F$wR|o*p9XV3DL@h<8({s%U7UQA9zlW~ zHfnt3YRVHf#+y=P`?$0O3Qwq>1U@FnXO%Qt1v2wG$|3(>=HFa!bUsbo{ zN6#34SUqNsx}bE^nXt`|-+ZsUdB|1`|SqZShP(aa}6%lDSb{P&h|#By6^|R=mr~(5F)}y#w2{Z@`*gK$_B6xoJ~uE zH5tel2J9k6U$c6*R;`a4Yk@5-^0+$lql(^mCknV_6W}B;B~AmxZF|ce{pZ6&#gY9D zbNSIx<^$bdad(yldF{0A6=p91=*Me8j! z37y^?tKJnqh%7tL(Z!r#2WyATVYybWeFIQ8=3`;1rnZ{A4Ye%DNjfv_kStGsGW&39 zSGhBlcQ%JGET+P5A1U&ofAWcJFDGa=PVQ}eiENGtDW)>0Gs!kCv4nIe=}b?&Q?7qp z=#gA6s1q@3O~P=$*J#i{XE6zexOiYo#TKKbJor-QI?4KD&b(amo?4%XUYb>0F5%sh zOu5mm!cML=g<fHkiAkJfk|gGfFoC~oE< zuX#g?*RVi-LcMm?#6^}yJ#{f!{@dGvt7pk2#m~m?74Y))6@d<|w>(wVbU0^Ow@i9Z z+@~AH8I!Atky~*T$7SPvi~4GeZ=5Ps^$ci_uZ3pa0bp>H)Hi76CvoL6K9?~6VFi{+ zdc&^`hO-^s6?%|)3KTE-%luR8X(;h}K;@{v0Xw$oo4_nWi>a?)j1#k_KB`ElVarQ= zxAd;fTE)22Ysi%U1?kv(FJY!`;$D7GRSI@s(n$d}hf{-YIVUagl+eqKEJG%%NV^C% zO`G0A-!gr>U}q!pOVXrV)8Thk0yh5hhP_7UGmF=oY}IR{KeS8yYbi-@=Mq>J=<$9p zH19D#A!^{LYt+YLS1#>y*Bd!HG%QYRv?XOB3I}xnEpOoM$`NQ^?ab>b^3FbaX40qH zG9|fM#ir$x^8SuH`m@ZyxV67N1Lu<8e(~<6B@}q=aQ;Kgdz}!c2Wd6~ew-G|ynAF^ zfn6#G7I>cJQ>FL*#ns4<0uZT9fi|{v_Lqer2h-}%yUqzEGkWhnY2|#et~^^{D`z*p z^8|AYF7}z-yb`{`Vq8CVQJrv>+<(B{;e6O=YkUGdJr;1nJ`tFqD65*gx@b0tDV(Do z(ev*~i=pRzs}o}NEYCP2F4#{RdbW{3V`=85-E^-A7)Te&HB8KzAGi``h-<0SJM%)l zo^#^)yRvBwoy2?fQWJz3-(PD=$YghNPb#*)y0W?>%P#Spr^?sfs21Czo>1u##@D*O z!kD)lBxXK|f}`SQcm2(0DGnXWZL~uKn}S;So=v>7KI0{rfN`yrn_{O%iaM8)TjuOm zkbgf+d1i?e8SQhs7tY^%B$D#ic&u!%X)mEr$&cQI+@?9N0-KiCbKtxR9NXunZxWV9;@P(qU{F$#C;_=%IO ztkti;Q|CNWw|QM7lwNEEeEt5Jdx{j8;9~`U4LzG7u9?BrkeJb>*qg9?pkuUNQ!M0c zQ|e(r0phPw=yb=9ds(eG&JhbZji{=caoZ$+<8?FSU7gFEWUsquDiP_ARnpk({3tw; zVl~^~QE^^Z4tGy7x-GsX81}oWYM|EdVXpt$%=Yz4!_f7Pn+1ttVnx__IYp+1gdyV` zpXu}2yOC6o-p@v5`u-ht_DFz44~!A|U$NTW18Y_~cJmKeNK5M>Lzh}h(g9N<`K9+< z2YbPbv3Bu$ABB91PDwY5-k)Z_hF7C0^PjYQ1gkS3MkO zE7y}8eB@n8U8JR)=w)s;7*|MMZbu!kYNCtQ6tDs-geHn3e8?Vo{11BPe-SMv z11fuhY|b0+rF{7akQvL)!{XAe^y8Yvgp`}Kbr^ZC-;eR0w&fa+^8rM@*PPf83v|2C zM4_{uu3Zx!u~}&GO7&72PE2~BBa4qptp;ph=Q zVs7no){g7Cx*LztOU!(bfHTh^*&Ip85#y0o@JOGg>KIo)$JZ{ey#%{#-nXFM=8OH* zh_#_W=W{!&n`qpIrkgmNMt51?*OxAyx0jxdr`9k2r+2{qEHdi%h_7Yx9>J166Ov z{|7Of465X_AGI%5A35-!Kg}Ts`(*1C+%xV&%-F8h6uo9`on6N9%*oe%e^#UFymG>` zsM5fHWl-pn18Kg)Q41y>Ip4YjPPiW2i)TqUn1B|?yj{>@^=WWPT0Nm+(32Z}md zT@x681^&vCihT<7CEw(l3R5Ru}+k1Xlwjj6`}|vbHs_s<~_Q+qJY`4fJU6LGk7Bm$QRhpGIc>OG}`P=#+RQ z=998|LPiZ>3kg>dT%AmDwt=HSX)S0v{$5+%uZI9>j=!f5?dS_kQ%;KfPg2q;vtrtE zbSj{>NmL=dT;KqJ>{?Kk^|hny1KIv$LYuQB9cmzb2)o^ClOCtWkzX4_$D2Fm$sSkS z$k0O~%9vEr9&L-vMJYwarU7$dJn9_#i%Ty6u*b4#fLm;^;=6t6o07Qp*e~B~%zIZk zK!6}d{~s4p^1vEe-8$-L0L9Y4wvu1{RgPxFQAyRh7Q4QG)ikQ&ESXLC)n2x*3C%Zp zp-?>!YRry5ic3p$M4OMmWf`U0F>Xz};PNH~wpnDwJ3N*DqSB@)tCs0K1l@=)l`VSSV`6RA~Loxp4JhgHkUKn(bZ-4L=g8 zmZ7o6c!_)WrKSMQ#6!PlCP5*Ue$O!fez)u}T5|0!;8};Ocgj68Rf)~i(kfgF(SRGu zPae!)<{J#MTRxYZWiS~%{^Y3mW!G9F4c_C-OEdXK-o9>?bhXYpFU_4`NE9QD&?KIZ zx_36jhJ|r*w(#x`*IDh4dsg(C4ZNA&zrP-rTc%C>C2l|;EeYTEy`dol7{QJ@^8${z_}ejGVJ zdqp(zv4WWK=Jvqiw#F;%`smHrnLTV6jA;46E zuxsxXq)Lf>q9fB3MHUHKAI8e$0z+U|6SR<`k6he1F3)Ht7Fa_xJ?zj1uOvnwDgUK_ zF8u$kk)<}C3m6Bt9vv|2k7;<2S`GCTF=Uc<1eX}fKb?OoH7V`)Q>$2yYO@vYyav+> zKDW1(BRU+zdzjITCQmD0P+rF>7)w+0Y*umQdARtx#9Ghd)zcxy&KwEGZ4SNE|%(8)bsO})jp!CFK}84Ub#vpx+3dcMPO{nIFx|uxL+zL zkzQeZ-G!8w*4}Cp4dJJ%3oxE=lL#hEkRIHiv{7>P21k7-&vd+w#YFReA28uhE7ysb znUdXiL-|d2tV;MSCR}sB;zOas+)g`!mzkqCC>&iaNWq|RZVK(M4rL@d)&}=4+>gzL zP&2->A8mdKwjqCt+#gT>N!~2u)>q{9iVG=ki!aQfK&DJj`M~?cZR>T{B8{~h!aVNG zPUTYc0H?>Dk;^vh0agCxYs6p8sf!v|9_Z}sulKRN<{lRe=NGOzC~z5o&M)ZZ$bjt` z3TWz$wXk;q*7IMg+wp|`qcv%VTNEE@`{^mqJ$Cr)%z8-E;+OeK>-c4?60QAsrzO$n9}e!`IuyVG zsMk(jYL{W0O@`!kp+Qqup=;LCXDep=!_NjN^s)@e%AMRDpykY27W^tuSZY4y1leF! zRXruji#%DiI+~NN^1@TMG_l;(%YCHgdB)ug9hQk`Wu`B!N8$U1x~D%73a$|yoq7I` zVVA}$_|&t`+PnN)rTEroTJ++5dofjQ8K1q@ZOdzIA8rO=pUojNGl}^xaxk10Q@ND? zT6sIj7(yt|JYfq4fJ!N%%-t=kK~*6dX|gA6Gua7PjRGBBDbFdnk%vE~6v@HlXd=aN zyRbXct^78aBB^6C<^9O=jSgnMg_rXKNRS5E*f=-X%{tcqYt{``kZgI0BOk+v*y85F)tQ{iiwvd%-GE2s=lc z>zH)xG!$4XP3QAsPW5=pq8D>MP5KCh)Ocpc^DmqxZ_h6>d$^GWmY~rfqCxajJo}u- z|GB=0QFPu=uyu&5C!K*XUgU`lXrR3}m-g(sI@m#v{hrLQk5JRP4ad1(nuyucg#_9- zp6{|)YD_BLZ|+q|)4oZCKS)fX4rs9V*511l?{k@Y+E~))Zv|UQ zxiDfJ=$GjuJPfgZ^ES+4iism>S@yPBo7vZ`P@7svg+~SFl4on>sd(+1*Cx?YZ-w#r zMq$i|b7@0@@rk^$fm2QGOz)eOTy&iky6zlyRxA-VYBngx5k|yC(xsQ4uafUWa6}R6 zV>!=^+6l%wONd)u=;&VlumD*TEW$b!sc8`l+4$BgmgV?cV860na4Tw~bjnf|0FDw!ANT0PHROq4sSMFiemqRh6+Ful#&8z80Is+<&pxDyl-RQ%jpJ!Vl&3gD=@3wv&q)u43y~Bi7-NO3yR;?`Wdk zYD;Kkh>HPBRg%vj5_3tWG<%ZVs0_ZQeU8qvSC09kU6-$Z0e%}$rdyxl*-wDSZra{c zjZeu&6H5Qd#%4HPEm3>dRKJd=h{mO2n6*kp0GfH8>4137p?aL23iQZ$uXZUdGJP#t zPKE}|?@#%ipME1r-a5oBZ$D~SPMUrUTLRybAG6jakn`8F^LuS}#7oMf3elc5nepvZ z5R1=$ZtcQBud!H)mpU50_5&kX>WYO7Z?CPSLN>xYD<>`BY0^o9?UIN2 zMzeX6){V%T93m3JXA?=_7`nL4wksiTuTYd<(PQlZ*?Q+h=tSXgkVB!LF56RAq4dov zUC^bFG#kC^y{Z&{sh@K6Ofxg{*H_i6e6q3+5hrnDfd92cEoNwnZL3ywa^G$9^5ODM z9?*chp{HTD=T}lfsjciJGJKO0R%A1vw)W-OJJLr*3Ir%cJSZcPYdNOPj>f+}a2e`_I)RG3h^cHy*N| z=F*y33)eFk&u}w8d>%(5*bdHTeonM#%q$qbE~qqYEiIb3;co1KRC?4-leH~5r7)On zLg_Kc+#7ZZLJw6?SJ^GqP&-bK8>Pu_#PF%OF}nd?+Owp+Dj@N;ASJd%BAHClpiZJN zaswrfyuH!@W0_Vu3{z|YCH4gptYse(mG@72?9i-7?{Z0fuGmpBFX@9OzBe^c-j#qz z8i@#v%(22aULIgN$@ERe%`q?|eBu|Agt%SPlZ_dD;N10-4UGP0@l90SeEKPiImNBq zgjlX<(-v5&D3h?@dmwVwU2XIUueE>@#q0|_L{rMb9e&3&fXAGhzlrhuK9T?zTFMX! z81J?qr|g=~_}j|``@GDW0>@DikBx^2)(U0R{Rh`wY<%YkDC6CIJ-=k&lz%ht7v(F$ zv(=y;*S9ZaJV`;=L8ss7Tk#Wi^mo0GNZ}2fpVBXo%xSR^`eKQ5IOU&k%dqoktG&|*^OlHjJi zefC>43Q)`TXz&c5m-XE4A(cb3=8fJgFxn|nZ1k#4oyT0VYk&A#7!i@vmof}ha{NjR z`$DK={DtyrJJO~aN=h+t6ExlT)b6(2K#$lz>Qd>h3%~NJ8e1TWUH@6Nq$L9+)NFHN zFk446JeNG1_D5^GFEu&X4M#_4QDqW^Ns-9rp3G+AD-v@Mt@UlWu0+8IkwwzV4T&HE2?}wo>Dg)tL%z%$b?2Lo;2sQtOXl*OTIn z-SSTEz4f1p^ODMYf05RC{Dg=aDDRD8ZA98f{xMXiHFL}&kxl$S#6i~E{{XA0+R#^I z-0xjd;~tWukTO(n#X_wf!^P{@o8H^Cif5rmU&O@MEFG`rv*#J@adOyItLRDK0=*s* z+LABz8uT!8ELxbQ!}r6FzZ2M5&MA?c$jKF1GCnhP=b%44?MNxBV?Rl@8K8tA&rr_VYyLl+ z8ZBb1uwlxY>{v>@ooF7P2x<5IcJ0p9zIyWnQ`;C;!T!k%N1a9@UetsX@)T4xoW~f( z^s4f`UHENb;Mi&TnbANtNT=re8Z(HZfz1b!8T*o*#zUhIFD7Le-lP|K4UN*=Spjvp z(mh~xzO9;rQss_x<*sG}HQImO=W5$|MX++G1LW+~)G5rl$Xsy?F=GVw0u|fulUa zd3-&0yc!&BF#S7P5FgA0A#NveY#&GQh@~p0?=9D^#I+x0?zeB<2=iP8~!k|_=%G8=uU*q!xsV!QVP`(}(Xnl21T z(l&TI2bKq&owD}3`(VE$Tdbkw7ZSJKaNaJ($oTZxKLYwW1pYIJa5 zpoF@D5UIfy*Q98md~$V#ZYE z>~Xcl7sw9ek`GD&cSTP_%;HOH`S(*3*71=kWfvoG`^Y~AXCOJ(5A6CmLOe(5iu%tQ zF|byt6@P_U)qsIio*8xw{;01OMq;IfF#&aZUX?9Idb4gwpx?F!UM z_n-f@NFWMA`VVRM;w-9R#|_tzP)O>BSZm6t22QZnyntTtMsXX&uVTcv4f>cq%FwEgj=IMUaIiG%aYK)j+^ zswvMlW;Z%%^y^yoVz+z^lQf9ko7m$Q*;)X@uvq3V3#g0&9sjw*enUu=-^)MX3--c! zV*bUxmSMrm@Qlq6iyE*<*gb1UtZc_-Hb_--+wG6CuG@TAtCTL2Ob#&389m1>^Vncnc2OV}R zOnFX(=%%fBgxY||g3}z-#)co;ULf$9H+Qz%5nR1jYyyuAUTU#9*&wfZa&6P@-0^Z9 zK3ckK6sq+@_m$KK#6Xw9=HM3(I?Qyb?G*Q;Iwtm5zX-DpxgbT5Ti(LyMF|+q7dCuLZvJ`DdK3~*^z`rkppnya}dhzSLM@^&fEr|s0ca70v|9Iutjyh0_rhY$c>Vxk}Y z!Qug*Rj1SATSxw=byt$=$(IYiVig-qYpIT=HIvhzs*4%P1-s0Z-uGJv450K4Y}nNG zr{oui-Mr&o7w)9JX32Gs+h+D;b)yRITqct`&&lBuknT%Bv z|1UAfC)}&GZo?JMB)#V`XjI-W>VmWPdHa&--W`Ww!eJ&)P|W(ScPG;O2FyIY{U>ws z8-uxlVJ>9r%?*rm^Pcnm^Yi|`1+aL3mh<0tsZRexc=r#qiyJVj z{D-~x&r@LjMxT}bL2(1>$$lpu+!Fs>xOtGJlmCCku@tdVyG#8jBJ%T``!xV3zmT!u z*}qg(^TC-n9$j}EM9!3f-oM-hqCC*amYpU6kZmd3pVX=)RfM;M?q?wUYAGr z@;n=Dj2eY6^U=f!f>&1IjV6y_#NwmtU>mOqN?39Gm3vcdZRwefj`zU@1Ofi|UNAyd z#_uz!4^c-%;Hg#Lb$9T%3!!RoDpR6#USAi=1L8g9GjmW#vkO~!>mFU4cmiKuez0{$ zzy`VA@DYw)c-jF9-P=^yfuyW(@%_S~yKu;Lv!lT}zK|Tb&@OBqD{&r_>0lhg9 zM@G$GSj$4|3@;ib_L5}7bZox)%(^P|#=8g9$Nj;K7)=ZK9TdFuI*!Fz3`4je)je;K z_^QO3<4&7%;2d5jZ|1&w{mDshr@BXmz@I3BQRHwLV?|$x2WHo~Z|LbO!X4iF0RBC6 zXFTjAA~{gfa~%w+ZHE2jkA%2LwjO6Sg&T;9l^E*G%M27SSLzJjNaCz|v70=!C+a+>nue`&@rZ2S?>zQe!IS(+rqB-I z`HIQ22};UuQt}u5T(z$HL>`1AgdWSw(QhikMy)XwULGYZXO4Fu6SO+?$jH9IfdeSlEX3M8 z$aulV%Yd!rK61#vwKeX5_v(sZQQkSt1+M6W8i5<@B2&=qisTwQ+7=XiE0!J+n(qgb zTTaM*_|ZtDF@$M<-gOGMFEhrXJgwRoacCFhDK&2xrr1ZcPTE+o;$&h)v_k&L{9*99 zFw?ct8*t(g#{0nYE8UTcq-le2B;C`zU;UpwyjmMK&jJT%>(P_ZGmbA$gd>Vo%8xs) z5LKhXT|cq#tOM&K{_adkW&-jyGDNAE>kvm zUd6Gkas0)AeQw~XL;Bafb}5*{6blo1vn3lu%_CBW)+sU*+Lq@7!Q{+?p&SM@4bggA z^0@c;nnlC5r01`4QF}THKjlJN%2QCZ&p%jM6F|-9y!SDyXf4Rbm917n{iMV^jg>YaGl6pWN3t!zMf%QHVwM z&|K~P+N=IH!P5*&R(1|1&c6F2_TRz0J6I@1U$(P(@xu`UO=y6qj%ouZp}q|1E%v3k z+g{g4Sq?PA`kX^G9T9XY&gJd48(tRshmnsLU)zbVLi>oG%*5pD^}!rJ>eUzF<-b8T zD1D&O&s)r;4J>KD5S~O69l8wfUR74`Wz$Mrv^Twv^7JvM;z;u2rvM-+7m7c4_!jQ{ zk!;JS8yVsH2)*}qWaC5{J5q&`5P0jbtYg1c7dXOL?R;&jWw$%ooz!p_l-z~%(|YIiI%)$?UkKS?@W`+3uF?4_7`geFMz_pN>=CKS2;J&` zXZr=FSw%UxO!$4e70J-Xi0|^_LF)ZuXufs z5#a>H)mccZRU;c|x#ch4Ep~>xxg4~FB&o7T#q$>s6{o5G%32iR?xBNDN9J|7M_zw$$z~HNky*dX-X(K` z*x+S3n!f%lK2dKOwXOyKNp2j$$%a@QWSlS)aw(jOwM1WQYbTpoh`}QVuWsMNr}FqW z>tR&;yVCqpQ~Tc}@}Pksn8}3a}Y3H{Y3J{m`G9m7_2We z2j}>DF*QVY&%EOF+7lsVS>L{@t{M1j!FUkIn6o(mV~e1Vabo5;v{Xkj5_Xr9eEsF| zG_|7vrPME1T=1vs=*QMnJA@OXYG6amhe*8f=U~1MyD{cJ#Ybq|&-u*i^3t^>bzkX> z?6=Sxzv!ld_?0AHPduT3R;{?(sk*CRAv_)#=+$5oDk+F`AN4*|*v7)xuOnig$oZ+F z138wqEZj!o80~u1uAkW`V%d;e8LT9)3(mrcikRE`FF;4W6;lr^5~sQvf@!69igggI zb}CL;_(RJm!j;3Eb>c%eSf9+r@-X5OWYC+nbFUZli@O|tC5YAC^waGMoaol3eQ~Yb zWluT%$z{vNin`W^aI)k|^rsX-DC3#QB{A};R zdje_&Qr_WBm{G^0pEp==cciA}XoZ(XE}b#G#NO#I!izQxfg2K-;R0m9LL zd$Rwei$;l4o?~SK6hD`izv1Gfiv+W$?&WPAva{%L?J1I|d?MGH6@32^6s?X0v9}iyF23SN*ef?O;Kk3qTt>AAo-HJ}=Dj(=r7-MPGBSI=%~+V5;aFl|0p z4)`ZOTC=f*%X|~Xsw9=}xUu?;9UBne;b|T_qVXLl(fS@>54#)uiRwAOcvz4&CD=(0 z`^*SMB%ZwhhKfgph7&?$>OF|w1kdXxd)RV;sg$7#YeV%i$_6&)HHnGu)%d6or@EU5 ziiD$a*>3ku-3P?WIN3V(Mx$C#qbDwShh4=DI_7Fv-B7MyqEQ{4D@`Uodbqoqepk!W_K7VvsB)A*UQIndLlXi1v1vdZJ~q{l$DCGT*2n!I4wVY&)6Q zAhv3o(W2TXjrzHTHZCfHy>RC+TFxR-=6#|u{-O8zqH!v0ubK!e?iHKK*S@lkMh{hC z2=6ATD=D^?*$PuIU-I%_GN*}EbiYc^cSrWLtj+z~?HS^dglW?Yx!ZZllyjn5xqg*} z^^1V523sx~ex9X7tZ=FDxsikRe{W3mTw0|NvT5NecW}eNHdHC2zs4+1&~?FcFUPj} zQ+B!!^6IeBpIg-2D1tKq&H24P4spm!qvt~eirnt0cjBx3I43q;u5n89J4e}hvSK@| z(!7g}r?|RfIS=fII>*XN{}Fl%^2{L0qxB z{gSBzP<^0(h-m~P?CWpeAwV}`#MfNwAdFdE-|Q*@1?NwVb~M*NaoCmc!W_Qb=n|gH`T(= zo!=~6biqt!8RZ4)SXf958SA5&dAAiHRSzRXp0>1HfzRA;S2e{oHDjg81n9X{59AOc zk2rT%{E2K9HW1slnXmh)F#r^li%rnw^T`F;l9;{C~ec?E}mJBf*<5si-A>iEqhBN+Vy~PEdw(xL{ zFiP&LAAg=zn3NB`^0T8sE& z`4-=pc#0!BGOZ(?IfB7eD-sV@20UJ#kQu!G!4(>Q;Rh|%wBTs-)M+)`6YLe?$`cFT zMVyLudp}vcIAQp@wSwZOBK?r7Tp7`y(WYIHm-FRUW?F#Y6ZE)i(lW*%>MQuD;6%C` zCv;8hjq+re%#mYfoHfbW3(`LIBH85?pr~YgrFitlO02PYjQ8YmeaNYa>Xhe_lL^ab z_7+rPtHXX+WI!$1#R1&g`N_rhOTCKUcHA%Z zN=bS11g?FUI8JM>^GG|&S|nL#Bui3=P%N+aV}zWaozhM$V!dkwRp)@H~~e3GM&RbL}lz7o}>V4=)o zPW3`B_Oyjhj~8Qyy(PX4nK3wc4baq?-V)20J(}7-t*q6=c*(;2Lv8S9P15~pMh@|| z(ZjD^j-Bj$ABF}&o<>blUh?X>MkqK+>r~4^2Wft&Mf)x?a+vjGP#f*V(>br2%f}T~ z7T{ozhfO?+(~Ux{VD@laK)`)FYR3*_=F3pYwqRqsSxj-RsF;Y=CJc)v=3j`gewy}~ z)!GgZ?JXz|qw>fUI|SV9`kjDt1CwNrs`qkiz0o-SAs;Q(E2-rDb}XT>OESvm0X&;~ zZ&tiyI#XP*Dvy?#>q9ijRA)TDII+EWp;I~t%CYE_As|vVafeb8PQ~dkvgMS13Wct2 z-M#`-Fnh8?eTcaJv8;yH%_{;TW{9U~VZPkV4wU#}qM!Z!-{n@Q*}8bawdHk67<0#_ zUm>Mnce>zioIp@W?{XnauhihknJ$r0KCMRa6WEz~xy|*o2;*G1iLmv0IZnaE{$Qmh z!i-9TaFV8T`hANk<*c+5_$2Vw4cwV<|G%M2O=*1*Ucc`zJRP3mVXx4(TKvc(1|6{Y zuUDQf+jI7~=Ptq7CuEk$s9q-X_H-B?&PuFTKUCjbP$Az%=7C@(ZM9MHoRm~bo)I&i zUU{5c?h^sDPi6e}Pkz2cKgP+b5yRk2BW*v{{FKyWx9iugozY_v*}kf6NQxTRQi(%? zqaWm_3E!am*YEc>YfpJ~A`E*svK+Ggw>AV*3EI0}C)Wje?epymls=oc%vnpZQ!(JA zrNom9M)2?Z&2m${dHblj6kbNQ z#;hG0He*^Li@6;OlOt%CrT+>on0L@P#~$1#^mO1G4BdOSSpQ{>{O{@l-vdIKdFWl4 zwlaa9i~`EFJa}GCUXMzY5R#YB43_$-3-;#okdAN0@tS721Ludt3)Xct^ZuZRh1v$b zBFY%=<~*WSW@Jpq$ksIP3Pn_fOC2A$t!OKJdm4AAva^&FE>L^fjS>|htb0r+7XQK1 zozFmOP~+Q$g=kaL8T4`sS^fIlg5s>jwl0@Y(9xg}=YK0n4OXJvEp6PmdlH43VejcY zU*b~X2Gl=>YxWvAmo>`Z?*3g+;BDtSPYhIfd;cIc_$XbJx9d=27zIA|C@!bKpudRP zv5_pUrWDMs)LdGC&qcGW66^(`zsQMPjX%8Ho}_SfLd#Y(IAH9hHHAiUDreXkKDoN1 zCNL@NTOGOh0%|P=jIXNR58vBs&0%C+Vk*iiV||lan|6=>HnP6%BT67d_bqGL#--fj z@f9QADFXXI9c-)|Eqb2aG#r8&(r*6E*Xkp_A_sxGc8muTPD7_-w9Q!&yUL7HWkUm# zg8dF4jVOaF6lb0Na^KzJ@E|UcjHT6S6;F>ta3PIYm-DU+&ZMzU+)Xin?%#3{mmA`9 zuW#b*w`9AOjU1l)cz|exqYed7D~(xR0?t#&y4uHOp55X#WWVw73BM0tp)zR&6lc5l zRy|Je-gI&1e>tS+a&rD^-H>k4l$*3W4d=}k-XFK)Um7n1xo)jLE5;cx^yCiMctH$i z_j_SNNQ#FegNrSL7b?BgTrMmS1u#Fx#5_Np(ciEoD}j^HVKe|omaE>v^P>KiEd6AY(s&fjV1wX@d5dy%Mtbr43G(%2(@lE|c z?Xfo5j*jcO$IF`e-)=8CKu%OA_%hl`uh3}{H=N0lO1!BY3uBj%z>Nh_=SX&aJgb;j z*z~^Xn&i|APqIZtk`}K|I&>PB29I!wM~LX|)n5VTTx3Sy`2wD&MoNkgt!pRjJ{~!< zHhx*L+Z^`m)abql8TwiCsZ-&*c-lcNe{%EtW%Ktx878xDIK*QU+LX&_m-fsCyounh znQRP-#x5DIoQzs2k}0mH5NxmHk#<@YW^U7_h4SXs3^+|fb~;k?_DH`u3Ow?$*F}>+ z35^t69bZW}&0-L^x(tJ&ceMe_`2RYz z_3zQrh8AT!vi`*6$qZ~BzW1e7n%*}qV=P5b|Au5(*{a5A<3}mWHMfc-n#vy(=A%b+&6Z(q0qg+j4nEf%CLZpAf4)8Z8OBE{V;&_ZztP)czx?iMKS1Sqb-wYXa# zgxoyOJ$L@+J@1^Ee9ebs_Fj9fpDns~Il%#*M?HQ0#@*0XtCQVqz@9Zeg z43$|{>*nmJ%ySQDg!7?6OdfXCN7YNhzLqqSX9S$CkK?NV<6|6*G!e>yPRlnZ8s2ov zUkxb>wV|x4{}6)T|67yNOpHNS4EjI`W6`|}>^Vb10TQuO6uPAQW+>rAF83rvCR|qFkGyX7bcg|`Xw*C1?vo-SW|dg8<2Kck_CQGp z;J%D>1*Oi{cAZ7wedJ|?m|R(r)7UN)_H&_ON?<^AtNRKDIeP~Urb-KM%KR8S!_GtO zB-r>LicN8W@N0|?VQ2h|N%MurfwpyNa$TCzIkeU9Rq;Kqmx533J0kcQR@6hd(RMFG zD@TiXXRV{TiAGk3Rw_U_ep$~i&ZC+!_M1GU0qNM`&_?&xdGd4~tQMd9{!&5-Vf}~c zAzOm!L!k6Mac>kit;}+&D_IdLet3KMbgNp`-i@Yhlt!^)sBzX;CGj(Ki2myCZNeCL z-^5=(Jhw$9gT+!$3^jZH-<&M}gIHD$>SfZQ#*@IQ8Uz#D?OY2~7$F9@#hiCb0Fs=~ z954kWry53O`c*J8jgM;ieiiTj?ko+_M|5S1%4=S0Yp0N_@GWv5e0|AsGL;822ou=1 zRcmn}ngO=at|0XUpjx!uyF(kv7dOR9Dp@qrJY;?D^pO=zS?it5Y}Jt=G){a+ZrV(< z-DZU5&=fhL(j5VSzY}Jpe#((bF3f(C1$64!8UCVRL<_+h7ZQ%)4ou6dER8$1mdVTu zz6(7l>g!Z6bl*TZ-CS!O$%~&@6YNo8*0){KTLzgbVG9_x9(7j?p6fOg%O|GnSB2L< zbx^=wq9irp3^M5wIXA}Cl)rp`MV3^bACdfjd&B=aWdD!Wc6g2{zKz!#iXoS}8xH+! zvxNTV$V&v`?A6^G&)xiw=Lf=FZ)KH27#mM^U)^sXgQ|9SjbL8K@}@SNXX2NQm5rf; z8}FCoEi~ZpOp47Pbrbazn|@T`wq)L=J1K9)FNZDpq2S2zGzLT+eL+1BSHNDkSKwUu zBb>sXaw#brT5aLo0Pcp%^YHqt$685=pG&Tx_#J&8vwE-8@W)7Ln zc)wMsW`B5AMHaXdEkx(lD=t*eAVo8g%9MNhm7lDpKinZ^FP+N*$=PS)OuQlV3%^a4 zvPyGZlkgl>G5~fR)_drmV#}V<~a&vOk2SI4@}Vaj+?)sCH#$YnU0%e0O_B#k8g}Aa!ca& zi}SOn<3_uZn@Mhte92De3Lutcr*!YWmIen@gjvbF&h%@;XXak)`OPkQcRzZZJJ(EI zs+byQuoy0#c;A>>#LU5H@ZGuu;PG6?zwQIW3CO3_M0cOM_4H;Q-_TH}^ zG=k(3_!XtwS|rhQD9Dse5ApOZyd7~{Lq-R@UbON$Qt7BtJn&LP9zUnpi@LgA$Y`GI zQ^0gUwEr0~{>L#oG;|fegk2xVoQBR;mEQ@!kuk-}m9ieUk!5@++g*!`$lcl5>n`Xw z>74fvQ`;$*tEeSl$JB>?k#FKo%wR$K6$8v$&E!hM33G!ou1p6#(qRG%GBr0oVV~6; zA5~^?7Gh{`q$pJ!tX>;8@?PDQU}5n|%!Ehzvk5sJKEzbs>XIKJ`V{u%W)8VKz46H$ zc==@CpN;d(e$K{{I`?Jc9S~oMdsmSLOgL_rlTLVPI+(S$&3~DE{l-+jxS&QE!c0P8 z7}Y{{B+Ct7r z-j!{o+eSS_J1$$XIz8M>{Z-|qZ+5tL`#a`fK|8PpI&>nnHG5a)6OeMsF`{iNc~&U3 z?lJU&caTd{RT^+Zw||T&b`k%PcK^T9hmjxs3lt};7QJ`kJCoQ#+>hE#OXjXwlj#e8 z3#X75rs;_WMhi8APR95yVP1#wQXdG;3_W1mMS4!`XDymf5)(_YlAp+U^Y&0;N2$11 z&innuRy8Ub*oNtO(YhKE zh(t}C!uKP_3*V%h8oms2W{cwKesUGa8-st*s_-q#ZNk%i;OWWOzZ4SaQm2t6wsXT~ z(aavdu`cMvn3We?eCMxbUyNPBVlZd{+h!xHOEnmTSIQD2_jJ`q*Wu^lo!S;!^f;&5l3Cbqtewaf}b0 zt(6P=^yG)n2Zeqj()BR`g#j9YA|(P@dm}C%vvz2X&(ky}f;ie#Jhl@(i+)Urhzm{$ zQVfeQruK*J8|;?%4^F%()13_p%xS7sBs6!hdAy8rCd+YtQCllXuD2k>A5-aH88bf{ zp4bD{TmfeWH&)gqWFBT`EyT+m4!=SEZ6f^6d7Z$SR^-5+c_g%R{y%zd(d*PsWB%+ga>~HOLzVfZaC{(PsO3mr)n{*EFQrABw(0v0ZD#?wg7UxLbGI_;aQitDcXqdZqwMxm<~|Gj1<9M zCyjCFgi(viO3;-kRBR!Bbo@Az$`{fXJ`X$m>(g=hw>In50;bdA7XM!hzCNwS#ejN{ zIiF$L;JE7vDOO#0R2EJHYJNVbS(jHBDQQ>SrrlJi z9MKIgA>hy!Qq$8UtY=!#%EwydXq$zAu?Ptly<+D1=-RDSsgm?obn=ne10fCqheX>y(GJKt{GP&@exf+XdXexKD)Z6 z0@T1DOiNRq0UpUzRclDA87NVoupqlJB3=I6&Vax)v9GZ1yM2ug0J-i-Rxb7qTJ|Pw z+{f1MCz2k%nO&n=;Rm>3ja8Sp5rRj|r-L@nDWB0?YC5sU=#)Ok(`kYe>1uv9jhk2f zyvxYhkZ*)esjN=kFMn-tYDKE8CUQ`S-D7*(n*A$s&(x%3vOmH9YhE~hal6QoYi{U> z*GFoi1kUBLp-Wewjmjw{mhL+b8b-qJfz{di%7FsP!G93--xloSi$wpuOM0DjZ7rhUopU-Ks zUGcorz3)kzbcdvQhDlOEY$X9k0`Q;yQN0TjTvX;zk{jAs>`V5_AA1&lldafO*Iny` zwr)v#R?y&W1AK{vU-(U%)W0qK?o+lu5)S9nP&owvs>*%t=jWv{r=9W;Ivbl8AcpkP168Vf4O6lAwWY-5S}@ZwWZs?` zi{DPs{cxNQ706tIv0LWUV6)GB{LNus{bld70oC{zSDq0^Rkdy-geihO{*a>(dek-B zrV-NC$tnvYl5YDTn=5req_S$avJ@<^KU6i?Oj^1qz;aQ;V+b*Hdg%%qfjjzUV!LZe z=JY`yhU{OPYuVt(EV08l177yN_JctJK_l~&@fs~jnebTh%qNT6jMQV^+a<1gh7O>w z`vgs4;3JQ_KsmJHR;#>cQOBSFQcZV|krw~3oW;F8LK-J#a$fY-KjYvekYAG9d~$NZ zI@-9mfVshZa)aOTda{wyNv_Q;tLEWxVOl<8g|f>Gu{HT!Ef;+n36x!r#~3tPk=K+V zz><5aR}cMo9ii-Z(m^`SFNi#W@ojnUL}ciqVf!cI7ozFZLq8CMUF@JZ%gUTnXMuQH z5oO_F8K#=VwVPh`Z4r*2qI1lm15o$nWTNxV;(n3m8B7s3zZ0io6Z!Aa0CP>K$ztD|`f?x=Fd>2ueJrE?xglMozdzUb>? zHZJtLCZ7{qXlKD6-DTihV4(n6fI*RLkhN_ZoKNeo-|`d6)qbwH1W&j+yPSMJH$?*os` zE<@jL{?N>>sv{BUCHNGtoj>Q%_ElVmS$O)?){7c%mcMJOxU<%zv>T1=7qfOizc{9) z?(0vobiT1ArUY*7Y`pY$wtP{JBiV&+z2jPHCbC;Sp zlJ%y4hiX-tL`)D&%?fT-ION>!SIyKC#0L6M8sF`k9@q&(8kP^cLllKv4x0c%@~9WN zqeEFEtB3*WIRg}L!0k}?$+C%*hjz|b_pTRp-2P{Vv^+8DB7Y+?4rhT+F&J$B8-dOT_dprT6L1Gc)7HDA&8)0thjIsVXU3EK|vik|N( zPPB_RDp`1?6XAsEfG1uEH>nxw$D(f*Tn@?tR8RGNh}uwjGOO0R(pHq(B-nO)>IWrV zv*_}dXzv@AD*)mJAd{{uU$t-?xCugM10<}RvNt-gTk5u6WZvi#%)|l9&7`2-K;dcE zie?$g2b^Y{Am{VK=VuX*RGi8WnuxF=wBCq#FkIbeAx$0HDa7Dy;4P#6<-M! zrRlj*Ejal*UdmD_8Igr5!H*R;j+yS=(%mR}g8{n@qZrR-wKmzY??S>qrrKrF!dwrT z4BS8ETLIf-FDtUIdbX8qT?g8Q*L|=hnu9c?{HSakPa2PVQ!lsXE@a6A&ifmx8?N}5 z{n2knj9R{S#y@aed}jLXFKkN{Y|%hn=juSr`AUv}u@uQG^y(zzV-RY`ThmfH7gZk5S!~90Fr%e``{XA3^`a=AX96{ z6X!7dn3WzDf9#EaGvX<#Ls)oCE{?1>n$x-FeG(d+{8XOgnH{d2H14;@xauhkDwH%a zB@)KL`Y-s}SR_$Xu}g_oC(};aX4CVt>bgoE&c2_7K<{1Ksp6F{U46|ca77+{*N|{a z-SzjvuD8L7R5a;LFjz*D?&(c=)*8d2JE|Vu;$_R^ny9uADh(2#1LqQQqgts2JPMr;<~$7dsQayim`TEw zr0}tb3BG+<<)~A8A;ZM?qERq7$4=t~&6W8{DnO?D;qArRU>s4{^2^S?ezv&db$9p_ zHsSRtk6Z0Ws((?$+S%$f2q}1DxfB#KZ5UJ#g9TpVtM$TV(K&$5V8oCWay3mAAat zxR-=|e4mq&+Iy8G_;Zk@JMFa8 z#A{WkeYdAFa5mheW$a5<`&hKoy$=42eVN?PJc673<&Gp6x6T;N`($R;Pt~3w3QJ2R z-~Nb?I+FP`tVeJsZB$meZ!Gq*MyrB|alf}aV@bee@~S^ARK?7N`FB>;T=pov0L2D| zqJ7&)d-siBiyh|sNZtS0{UIX22YRHj@I%+&V{H0_wtsOW-9BI?Di#UeOrS|oJ~vg6 zk=c0dJv&)@L`5~LbK1k#JT~V~(#<5Lq*RM`HSmtLPc_gKicOGj6DP$rPoF>SELOj} z_{~+uUf!9y{)Vjj)BZ0P2H?Q@Dc>?V#)BjFzhDTBe#T`U=gftP4j*ll&NKW@hfHYu z5Lozn42fqy^X!;vC7(URIXP$_M-i$#RvhiYBGFJYqVqNxw^zkaryd-e^QFLKUgq0E zPE!rF(V(-EIl4Z+ly=wP5?bHMzC4SlO{pFBQuU zOLG@m1dvk$(CqhD^VEo)GvPOns2-6}WWKCmSMVUw9JTkR;Mbi32F(}BSrSJg*6>4| z@6WITZvAnz-8OlT)dz$4r~CZ|Db6I@A+3l@r~@DBi*0I8#<#~aNieI(xN5Ahr#sCsEY(v8Y#D*zO20=?b%n+t z6d!Wn&Inz18|f>1=J37=)b#83y#$;1tSm@_a1;P@QF;B98esm+DK3hYO2hMwluFG{ zmwOU(cP3${%Q#HQ$xlC`1#0AoYd4wHfeXw^S8LTzSp!X*Lw5OI5U$^P<4$t|)YH7; zhD+69(oK=lj`9>Y(iAZoZPyQKq714EE^yCgpb5kCCv!>r<5M2wGUigRCBvqYt;4?q zi+<<*B@R6OisF9Py}?|tYekjj{D4mq_{PdVIhoMRRrFg#F>zmE(2F#}Pd@^Hh!Lw3 z`;vDfRGE49GE{s{VTX%6yzTz+LvC_%YcuMBo}JAu`1goHlrVA}x4^QC-8BCqEpDwpmR$92(E0Y92OceFc>l4dqn`f$Vj|7i+oa&F7t^d>jNxlXua8LGs{CrU zHHoAfiSchSv4=hR?Bd(7`v3}iCSea>ENZ}9q`-1H;xMb}WW3i!>0ChhdYdJdq&|2t zoZjS3R_g1(XJJ;>EvOSas)_)Lj+t4Nyq;E^-p%$96-a0SuYS^6KpUnv%=u4mh>>MJ zd=?aILj!Gf><+QH#OlL2sKi(7TXR{O3Z^XEj>U)`)D7DOXYWTnh)kXRv9>;JAL}0J znbf3trDPgNFH?uaMiIp`)PQQECmV^?R?pOhf)m z@$<;kxy*Keg+*;URB&RY6b3ol{i`zg3G}G`IhjoH^PtCW0mAfR0=old|6p7Xg7<7a zXxr)_EkeY`#D9oO`J$?iTM&CKQvQ{<$Yk7UQzTD9ud->zb2RvlWvn! zAo`$h&VrccwQ#9iP6)rXDKM7=xJ3PG$10{`vK|_ov>}SJTb4-VJqa5H`&+s#FQ0? z)8H&x*~~nJr$=z{d;ZMQq6)@YrDK0=UIJ}z2k_77{`u`r zRLrW&9XS2K?udk}oXWt#69&4pmuFE=jXJb~xbQKTlH$6X-_m{qciGqL#XcQNKUJnv zix=-~mgy@$!ea)5iO5G*JzpTc<*ChjH%B``97{*x;_oWTQ%4P!#M^L$ykAAMM6)R4Hx!rZK8bc9k+671EN>?aw&25N^Y z>J%hC7zzsf^yW)vr;GnhDffm`WkC2>5{lmgvBmA;mBNn#TvO-YE&hU@q!We~5vY}t#rR=%~^}(Pnr?+${riIgqFhGQLS$*qY{p(4b6!u)aU;eyBm$4nzf8od+0JkK8iIZb^ z-+w)%oU(b5JwslC=7+a$>yCi<$`M($xTCkk85#2QFZwV{5Ft$_TOvfT^4I=VL_HR0 zOl0OzRt7_G6gkwgl^;H{^nciLQs{eka6P@#{I@W`S(YAOg2Y*2HR2_KP$7S`s{HCX z=yFHhH(=q2l*P3bBCT4^g=m~te<#T5p4i=ds@2lA0aj89Bgw51K8qbn#gpfC?v4eQ z1J(-L9lDax4&0fyuCM9*e1$R*w<`Wfkl5+%Q3Ef}W*9e2y^-T>HA~UjpjE&fq7bKg zP(3W@`~zS_QQ&H(&i$7Q}tde^9h6WFAKH*!Zg8kw6+D8F;V@`zuMW_-{l4%o*3 zHMLIzaok?F1_H8o2i_q(?)GBqt(OCz$}lx$Q)SYIP|(V=y!|>57s_-T7-&Ph|=0159s6Qr;~a9Cl$z5B4q}utH)D;--0d9i9;)qyOQg- z(Jqy$OQWpum1CngE3FWM*kd`##39xYw?(6=O0Lb{sm^H9<{!G$TGE^`D+kZuQ?a2x zhn#&&i5E6;kMa@C1GK)L71E;?>th{6l%sqYj)On@=u+*_BUveR*CnOBOb(ZP( z)}epvg8+`g2zd@>uoC1W`-nwK~ zezOJHPg-ec4OnQ@>D6EOgB$e@<6mkN_*YT1P=Zg*aUe{+7GRCD3>+`aeWk@Vwew6E z`wZcZi@ryRmU(LDj>%m&MQtK+;LK<-L?UN;+K$-0O)^U&hzg5L~P4)4)gzkj^hwZcGUxg$~{spK|4<7Rj~M z;^}2(z+78H>zCj9?~5sWHzU~!P&BgOR{zi5(T{KC37d#b^N$U^&(#)5x8FI8+{8qy1;xmMZq@yw}m zr;Kb_I9UQ5_51b9ldOiX!@fn*5y<;vdh#v+`a;lksadP!^YqF(McI|0d1B$CeY&NP zu*~JJ{p~G}V5z#)~vb=|5VYN*Up30EngxujL zhW6)j6%vTf*fbZJr{VS{wt<^(ZbFEfudY@*!@Mwqw?dh#0KJt127JF>ESFQqhz2Xm zy9#iwSFBX1 zVB)R<_e>wXA7xyt;*3sqeI7s(aKjVTMKxV2=W?_zjF~fd#ZNtKH~KPQ*GJL;A4FVf z{M1$}zI8W0HbHBXUjYt+fgR(!92_`_&SEN`9hSh4>}C^p9bCP}5GRsX>qOsg5#J#9`H33hk98QVl*xygYw8Q1 z?*q!Z+}eHd3xQNRhcnVN5r2@jIMawj7IfS)&O-clQU1*g$>W7&VQ5B{$(sf{JP z!_$wX`U*cXyxxnzt5FyEySFnRPyf=LWqOGz;;gJQF(ja$c>lnWXtCvEk=nrM%~9 zz-BWfJNyABvi^Veu-x?GzdH{OiUnxrar&8*Ny+q$QP zSd*IU))v`4=_tB_d=?aZf-U{xB|%Qh8Hb=aLUiWmf&3MfZ{Je*fk%e!fb@D3;bw(X zo*M?H=iewbvFl^b!kU(>xnF%1H2wimhb!6SPnrqxVv54H)M0j|bzpI>&l{VJd_)1F z6@VElqFfKUk1-ZNjeFKTzX#zXUo_qay1xG66pM@8xN7@nt}m^Rez zrf;|{^?Lo3uK(tBy?X^A=F;IC)Dr>0NkjtM5>0N5Vv0JMQu8Xx@m`w8u9gdM-+Rrk~Jv8 zgHj;Kb8F{-n55vXwD#yw6$ zUiIOlpaTs}d3R3=jZFh`0%mo?v$w7~hcZX0D2!-SDyM-IBLaStPoS&b1+Bs?QZ9?H zFZI>2>wNG4eepq7N>edyfUt6{8MqjB{}3Qte>PmqBT8u8nP*b`PKq^gf43t^p(LDY zOGYnKW$*l9*}D67?`Q9eVh6;k%-IS(s7jSBJ{^f1-(t1*_NP1(ry&_J6OF1b$3n_5 zX^T)hqnWlE$BrNWmMAK<9o17Q9Y(G`2_oSaH163@{b}xTN+>M&y*%R*F=2aEs*+lW zQ)JJU(AO4s(0BuEcK!|gLJSw9IUN^IeNq@L>2pLiJbkF}X(Xu#^QtlbH%HahDngm% z_q*nZC(Zknv>zhd6gZza{2R>^b1$Q?^Z=`19Ca06hkx8+Ws8p9O8KvBh}`Y(M_OZn zi*$6Uq1z(f3HCA{z?65=i6RZ8b8cgTlBk{J=~Rw)tA7zRb@75{ub3_ z8H}++eV85DFbuDhbveaCIdXNy66KU79elcCmxW5Ex6C<7rn!HUcNu8pK7CK6QR8v_ zo@ac9zd)kUuL|x9AZZv7o2tO%E9_~Fri*4eqy0G+lQ8=K2vdQXYI8}Gbrb{6+tb&} zPVQL24{Led|L8zNICY{mYxBTv6#|BQgBLNM6ek2UV3QR_xhs6+mXr)LZx+5H1qBqq ze5n5Q{Q<_YpcO#hO|(N+5EIi_)MZZd@Ly5Wc~Ae28l3${%YfYwP3ncY@4kdJs4|Z~ zr`7IPi1aJI{S3DvAAwjR_#dg-mQH*@w_aT&^UDgK4=zL0OZC9RGkgIe*LN1P#h z9@Cxb`Vmb9k_ex`B^XB?eZANLh-XtqZIXwlY>kK;{9qg97k6AP4UNisF5+5GuE$~N zLmjW7UwHM3GuzcoWVoy_=18nawo4#$wyNP)hFoq4+2DHN_#;mNr|=Yzc5Nn5s9a!m zCazhK=FrKgMG4;~o*ob7C}AIhM?bQnUTUUXK}nHH-nc(8g>X#;jltTEvr>BstV-hg z8PgjcvMZ*=$vD8)U=#J6y2_r$Ml}TOh^1x(lKsL9(I2K>V=6TB<3KJaVG_HxV^Ilg z-HS(wA9*2u$=bgpKTFi9^)a~p{t)YpKPI{M*6rgo&~-A_>AvdW?-5(FMxrq*u`@+c znB<{?=AZmqJ@+B@ivIJ!ou23{CR-6B7vga^@onW33_woz4iY@M^qpJyO5>%&#k0hm zk1uMS`-9j6&**ZWAwNiZys~_>DMQ+I87Eh{dU3_2RT1Zf65;V{ zrK@4B`1y^n z2~}!;ptzw-!d|8{*Ff3NWPn#IK9q2N$nRwe3qNm@4f#Es8%KMtKR8j)X?|$4T8k-l z8@g8I?(mZ6w04Cq6#12Q>L*xJ@|f8_*;el8LVkipmv@kC3m@uelOsQ)XSc3Kk0z3x26H9r%%pi zuB+B^By{B@)jNtarrj)tlncM;9X$R2uHvSH!IV)}@ zs>IpZ#$B4VYCpMO53w=Y$&ta=&0J%m>iM1bL0Xr2nwInjzhNN~r*J(tSWqyos-x}Z z!lKN7CAtl;v8rS*M;A;<@rFK?L!~Sx3gp%Ua68tOd=vVda*2pKSJVBu!(H=lTvfE` z2zb(es_>M)ZcJHo@=~@MiW3&b37!dRA_&EC{?TXQ+*Jj!8LBqb3N67TCc+F2VofBn z##CCDS^AW#`F+IU%iDa4^-azuqL`4FPhuEdml233IDgB6v?`*y0D?>WHgpT54WpNeo&les?BSW+eZR5WfIsESlqGQV(qkhE__L-> zjbmF2ivm*Zo_^-~ih`!Mr|^LOi15wLD$Z`7=J1=9JB7}70xia3u}9sG8g6p=kq(mP zG~(K)*Wbs9Vve?4RIi*w>&8izetOPU^sYRNG`LX_7ylCF&gmo0l_}KLVy@G$6`=L= z@;C(pu>1=^HqZ9X8@}eDLUuImosRJ(zQ}6_jq6c-)-A)ny9kgtA9!&Tc;-Pi)(Rg% zsriN1yr(3!KOAZ&cmDOcqL~6R0WNa7CHqR;YFHd&d#rK0(53E2DoL<#m0s9(D4p3% z$R1@E*FPT4!RY!@L70DNs<+nAOG5jnyIDT+%X6}%+Lf~6BvBNHn(Ux1N^ zVvyX%%`DA8oU?R?L5knTY$kFsf;k=4CesN9(%zylD5rZlUP!)y`t%*I^qQWt=$5rR z#q7??DeztyV-`t-u{rdDIqphOdeqf}(_f`2-VKc0OhKisNY7|5HJN9-ca1TnTC^nU zR{HWZphSe9LWCw|(4!I_%h)gJk20ul^j!+0kFt+{S)voX0_X(XyAzApUFD8>BoFRS zVZWu2&7jpZ!OtiyY|~ty4Ybx#AKWBU(2N<89}Aogvuf`Im%VAmXd35Bu7D6Y|5J*9 z>Cwd`Fb3a~5I#S}P3-k!s?}9Q&zo06w@Ay3`r|YC`|O1RMr6R22rC`@mNd_`ov_*6 z6(!SYO3w*v;h^hSqED#2g(5gI4lDjg~ViU$Moa5_f-d`LsaTz;!I?!dm2X>?{S zVe}EMeAmS&0fosfAB~)m47Y;N3~S(!@k%(ix}U2Nj`~jab&n34%i)t@(lfC(pg6TG zdi5EdPi}NyF=0zX1=o)n;Uxvn&8s+N^NneUA&7}Cpb4)~k}9Mxmk+fch4~dF0FxVE zKJD@?*t*bkqh&(imbY%Q6~m9oXUuS+*PBF}%pw-&G+yK=;|PD%*Yy$EB0aeUbf`r+ zRIcEJRfQd}M%+PHeg4bA$Gx!g2k>etB491`Hn%Ec7i*eGiB_643t8_>O@i(QT&~SH zIMFx&Fr|SkIzH%cu{!L&Z1nC`MJqwZ4A(U$sVre50-Ti9o+v@GlerO_Yr`o@P8z=x zR2EHN)$R9BUk-ZBv&Y5gqgU>aN!Us!h@%gOFrI^`sQ;jg9Hf7xo9Q}}yd7$P^8k6j zQBH|8hunEzBs&$&K3{T|O{B%gs^MzsXN=%CR0?kr$3(kd09^c8-$p=_zmQY1)SWU& zFb;ZKp69Ud2vL-81bt!sTNVC;rJ!}rt_)$<)M3;5^Jx^hU6!asafvb{*Z=D+wV0Cn z483JwO~&&_W}cJ%>{3ef&wKTQHPvldDK9plS4N7_JPUVMJQeKY^pW?IF3qWzXE&Y3 zc0ZDi9`98}&}9sDfpD8dqDk|gYGU97*zoy;-S(bLyQStY@De}%L5 zW!i6-!pt*Hk8L`l_@3_?;VfdwvZn7Z{W_$$M7=yy}~=afKUq#*0lA@VK#*P7la#OcGx|t zY3d)TQS&6xxo1TNPu9}qDnWe_jj&qL5wKz_n6~(8jT4-w7>}+$Y@rA)PZ$aH8GE zG`T=j*90o-yMah%JPENMMNL7vzbgpY6|Whhn50D>jrFP*;1rJp!(3^z--_)n`Yor^@S2ND3)c!$YZRDV~d_o zATbMxMy^X7?w)Gx7##(7eG+!y>yMrt)sVscmyZjXAaTc4F9vo~RMVRxF4NcsoT%dK zF%Xc;w=yKXHhIIk-AYj>0&AEAQkK6h+;#P*pOi%pEvl`aL8JVKQ6ly=$aOoOdvj9v z%wL_PY?E>ka9uDv4sOZnd;JcY{K_A3kQ(ZQ1|^j+Hz(i4+s7-nRrKgn*bdBa%#BpL z;MM5azoE8BAgIAy<1OG6mx`XlpA~<|#TF_`q$G7x!Y{Qtw~p}I#l3Wc2ZMC4E;dpl zSN8JSYK|ww7)A3KN2nKo@-D1V_0z?@^8plg@Z(FC%@1eoI-Z&I3rAY4J%{rWIMdsr z;ujVKlE1r<(|aZ(pQQQk#Y!bRQwfko#%WgA81(nQFDMB~`RJ~~rlE*8se6$+EZxQ` zJs+86Wk%wB8gk9FLp7}m$7kqwu~%rPE1mralIfCeg?M~zRWuS>NTI2Q?bw6~I8ZGa z4b1)pH4HHJ%!@oqS4qQgx*LNknvPy)0*ZKgQ7{Lc_CquDqu%-CxOlT1w48<^G~9yM zv`a;pFE5yngqZR`@h9%kkZ1gai%DdDw*X4wFMEV05vY?rdPB!=GKwyAt_1sI{sT;O zG?NM`wV2a|$6{fW8YY$XuVMF8m8mKwZ)wu4m`BdS&m=OY_OdBMg5vBx9G*FEmCzK^O% z%Zm(Ub;t-m^oJjW^`gymEA%Ga*#FdBoYwr@&#(s4VVJ9HiSSIOne!)}pZ^IF{jd2d zp=aLe+SEO$cRud9T^=S^8J*rP9*UFYPvFy=E_zKbELY4mwfv-7d)laSf__%$k|A5& zAnzG|pt_Pu*tBG+oXT={4GA2hQ>_i(b5!%InNQSPoscWASCKND2&&(|&W3K)JR=&DScU1g?)0C+;T1yMUG+9$3JnG@zmcZ>MDIRnPRvSf8%=3vLHw>|Dhn5} z#4ke|{av*wZ+{-K+jM|0{GdqsGa9GdxZAe-PFnA6a81H<29f9Lu{4~e{*lIj)&ZTaMz$M@>`*GcV0)EzIHinIr>7J=5``#uzTi^of zfzf`?-h`{B;C0+mar(F0ByRaj2 zKM|(9kT9kJoNO`C33a3FE25!7eNAi#4SD()-u&r9NwkGkXAtm7Bt6oYQ+&OnN$?U{kNXKKnQ(*b zrXsL&0u42Hp5Va4XZgCKjlRsb$0h7{E^-lMPIHbC<0S2&67_zwQLxh-=s zVQ`{mUIn25w@S`gvGD-$zug5K7z$@?=Kn4d$ox1>W+x<}^)<)tp{%73P>sUgiX=CS z+xTU-`KUce@)H~0t>M-=kXGNo5v%j+@CKAYN#|I3G*;d;yMZ=Y+c$5V30u6Kew zvtfGpDhr0IpBcVmH_MY@L~#_~zxU7>m6gjt!a~ZQ{E%#+EF4{t#rU+U=#;6Zy5`zS zaY|>}f?9IHEY47-(jrp!NQ3H{#)t6UdW=nEtIScRGu3yqvX}{xFkkH{ghw0LYp#mM zMrAE)9;Q#bGawKVQuhAq9-E@2KN|axU{`%hF5v8NkO{4JS?R~|W_Uga%RVyFviXWB z%!Ti8$`eB8AWZ=etK1SJj3=Yth0F59gp#dqR044~!;F8J4)NYdn|&KLZJ%`+OBCUnUiD54|=lZYft{6cx*Y4%$h z0dEA{s8RH}+O-SYCJ($ma4ZazITw<<{)R0{?$)#Hm0!h4T&y?78w8?Q6#1wxXCh{M zdcr5>a%;XEm~?=zQb^OA|MjK#=@u24OC5V`J(U-Q9rX{~vYz>8*eclgyB0#ripdM3 zyT3)WctBK@7lIlq?(OQ*f*Dp>8!MOGI8`U}6?ZP2!wp8$07kO4i=Dd=LX}e5zBG(w z*s(+jv$m=ZQ?ibE@%JZlSnjJgWXkm0@o)UIjG7Z*Inb>!-HOYDt_TgGDM}X0?gHJ? zoZ@{d8Y1ma`Dy-dZ36IvPI~{_4!@uA<&SUI8wLOPQS5D-jmtjGommVqb^Ge$`0ab= z&97e6T$d-=M&GiZ8_%^UKSi3k$Hlyy*6ynYrcAn7;T>Q&SVL&s4NA$a|FNy$^&5z# zvjsgzGNY{h_(~mil(%JF3hNG>vvIT**Qt4~oxXa8&2=Fmd2iEL2NIf7nELeae-2=ec;qwy2+)r|W~IR;ET67^(=*fC6^=xNqjqT1h8? z-87x}IKFCNPu!&>&^VB;?qcbq_M2ll%*sNQ3A4pku9>|@X(ai(CHu_G z3&>MX7nk_vLG76Xdrw&!rHLT|=PMY=H;{U+D|*DQ(m9r0s6IiA%X(#04|`9-Uy6v} zL*_om@0K^*RvliNdtXkIdT&i@c;6)QA^PnKPh!iNtG4Pl=FawTyl=9YPu`;L&g}Z9 zw%IG`x`8Hsl$EW^F-v~SJ;S`Vr4)Vk$=IiQ>0+bO-Y?H+$fqEdWFOOnYqXyRObJ5v z41YuD{j6%|3@7qILX-ftT@RnwaeoTBLDwK^^t{atq2RUAqD)?c%6BYa1YTf9UK$(*91{V~p=7w;@eV zMx#t%P$P&HKMPY6^yG*NM79Kw#K){k1Wn@37`At7$KGgh_^RdsJo;e0Rrh*_tHp0m z6#nBbsJ9FLK)z7g`)C%Yx=*kCn>J);B=@#Pfv}`CPDH{3nsgoWnp)T(k@y|}wCP!m z`4ahzz(yTWeB|XPuZH1$@G|V#OJ-#@K8$YFtTc%d7)&7g{-*VgxMlklMf$cN)U*EzPX63gvn6Q(*{r|(*TSrCxu5I520*Xj?3?Whj zNO#8|O4ra*(%r3ecc*|z#{ffzbV+x2H_}7AUw?bw@80*b*0a_#i~nH_SDe>*9>?cc zuFaCjPP&TUGC7#D4hYb^1m52sjCOY$bP3{-IGZfy(ehQ$#z$gp4E5;dneHzsyOz{| zTHxh>)B;est>6!*DqSIFwA;*V!;QZznMu>oj<=3eNTocs^g1J#4e?%Q?vwwjw;Lc2 zhEa#^s}JP|%YBT}jasDgK~DDKzGC2zcuAv~91|{;WjJb_X!`pGf7R-+8rb5v3~anY zS?~3Gn%2|%laywtSIKj|`Gr6HPnx4n-e7k;)Oyx?pr*p@j`UlZ=>3U4rKbt!B#^W92r&qO& zR=-J+`v@m#^$ouiC-Tm5+HK!|?`t44GqIX(HB?eG()W*miXVntR8cT5ehC$La8T+! zD^7c>mkCO!c0{jzHD!K$0G~KG^rhVZ%~a+4nOBfqAr1~7->+L8;4rQU-AG3PH+RBJ z^i7!qj;y|`9bYD&?*27rk_|rS#G0TF{JpZiYdK4bA_i|ENJl=xQl<^{)_8)p1o9^aI% zIW@eP`mqi%hU4b>z!FZ<`VU_A3LrJ^>|cseRPHssaKPF#P~p7J6>m8g5fP}l zYOqA*&&6jud~lj1#O|IF*Nm<=)w`*pUd_GD&2Ov%Cp&8H-XN7%hBk}|qK77{6EM8_ z%M8UF!}r+VhXMQn<{R=G+{`g6+xUaLnvv!Oy=hS+0vGyLrW3C0Xv?Nl%SP*QU6m=H zaC+I?29x)Kn>{m*ge+D*S)R5SvsqX4TdcGB2kAXr&WHIz6=d}offPhlR;28e9LwVO zEPy@Pz&+EO<-{@PyMMo}?YSePT0-SXdA=&Mea&a4S;GhiVR)2he=|-OiL=3auIkLW zEfcwqJ&Sp&d;FsW^lcWBiHPmg+~dzzSvrvx6bcD}Hw_<@Fi#!vNLn%G z*8B`B;ap}F@VWVj)ByE3c-xvgW9PbrGO2AL$b&pBj@SEh|G;F+A!PHV?}?=3f8+#- zcHuH@VP;ngDHSN;Sy47`vLQe`7&=8)iU~ zkGm6_d1B=~)-l33zbCpUTq=t*Gbh0Vq|fD+Qw_4l-SAh}hoM6((j|gH4o{t2%qhE& z=iLpBm?^ru-z)3&OTMVm;@H~X)P`7mP^v3^3hTqQj}f7U|jn3iKJ@WLKo#ybBl$3JQIbw-pY4>HI%?cdp*pgLY2XA$^F1C5_G`m#_=A#8@EY z*&cjQOV1d0l|zAw_79wSt`4{x=2I^K7=i6m(Iu@|$rKIzFYPBm?bqWUQ4|geMTNow z^U{A_I)}g;cDCqBxjN^*Vk_lViMTrBgVKq7_q`)$EIxV;VOAK}Hp;qYDeej9_cGb4 zucACoe(R&Bz9`4G;GI*Frz}Czz^}>$w^SC$W+8*WR6Z#j9VP~9-+9!qrPoQKCz%P$kqL^gA> z!tD8{QTF-})Np!x$!=`{ExUn*#6lz)O-GbAp87VWUP~x@W)}NRT&0@|DZ2|5#~G+t@nI%bV1rp_ zAKA6@x7DVz7pM-3lT7q*o`<J$8m7Yd z0>g#~5XA1(KV!w3n|$|{wN`ew?C&G;l4v~thHTo5*T&##GvDn&4%N3p`rn!&IM^1q z&SmvN@VKMg&WJ87w1J}V@~5W@W|m0>ZG>0A@Y zc{P@$&Z(CwZEo?p>1mqhR=o+Z7+5{A?lBxb=#=-F^e>uo;BnA@mKA}-%1ic*1yhRd z2W5^V)|;U0(R}8!2!JmqglZ+0ovo;28VKZ-+t$OF3V?tL-+GrZ=4O7jx~xq z=Pu9NXV^mEk?8X~EuT6yZ#T|I%bq)QX);FYyzU<j|dyXV=aPo||f?yep^&~7r>%s~nA55Ml2z{aaFJ;tqX9uM@NayLVZ zJ4QEhB4 zq7U?2#eB9(KPe~3mrnir{+y^=>lnSQF~qA!w*3${;hZc zp4y9nt8xqp_y7!cAQ1JxDnaW{s{`D=N6FulJ+lUZ`vmg#_+=_)z(6PU@>&?;)S(G# zL(5m7@)MjKLF}7C?>IX(8aep$r1NlXzekEy?vXXg9Of-V`qC7K4YV!}S_l^xqcwvC+pbOd5%VMYvr z&+kRI4cZGh(d$2yfQVX9{%7ZDjR(bgMZ?nkvT{KwLk{D|O4m-FcO~mF*395fB|2p; z26I;~p)L<$KP#-5EHYbhd?~>HB8)Q`ls1yTI1;>`wV8j~-=B`QAxJ}x%G zUsaD&-z*{M_A(ahR0B;0OlUkQ(J3=&17c~7A41?4vRz$1rjUnCCr807~V7fg?-VA%#hA!hH;{n4;S8+o|UhzgjGW#69x0O!^X1XKOLE+Vqwjok3L=-o7b;Xil4Zcj`NfDS3~uMK2lZ!r z(7E@d4TifDZ=4%2#X~)WAyW;+(d(YiXO93JOOGe@SHxKQ zs;MItVQ6&gwcTl)Vmc3NcP#P{_CZ!>uLSDD2>2P+Qlk^{LoY{J)Qgkbnkw7! z<&d0<30-*t`)Tr=8j>|IgsIWBT;n05+(C1F zUis<2*1a-}?VbX?p~QWu)Or*4^57VJJ$|ehc|Ex!Y}Fg(i*-Tsb)I3$JylV=A;{9L zL#m|t<+M1$G#!u_b)f(g46*;7U_{nS4?TVx0-XjA^Eik7HZkx`;S%~vU>Tu$Qh#21g7NaWg#4KjU;G&iD*LX-RJL#MjiI;*;~re8 zNaWZ2Z}hSh%~4O|r(}c&anE%^<~1Dpqrm$&mhhH_f341eu(?1S_%1aju5Vr2_^0_# zh*bI8ncKqKrE8w>%dUe4LjCs40K^#D_TV4lAu=CY=S*cibqvBBmx-XGu%g1Z^%v2CrIM_!xy&fU(ot@E!!Kq6V2m_w-QUzlN9nJU~QCf}EPkpKQw4 zMK>Kmk|Q$vJ}FJYYispf?6C^8#{;ugKRsyXEoEJq$+jNqPTjXdPtZJl-f!`TdTmE< z3hJjke^~=Ww({0}j&TS%G!eF0Z`mO^>T-bnDcoLZN5Fo$ksZq-?bL;{(zTxJxA{89Dxgzf)7?8f!+{;k-ttIG7(A=L&k(c_~Qq&1C;9pbJ)46f$g&*4m zhO^LRz!URhKdE#b;&%+&ePv0!_Hxp4tC25cvnVhPo(4Yzk7UW?r$uHpzuNYjS4p|N z=Va~V#|JX7P3<@gsYBE8uKTB*4L!A^sEk%aUzDWb=zAWU94nFR!Nxw^Z#Nt1OrY%1 z*0KjtJLoJ(F~mu#Eul?)uc!Ft^q_M%@3*Of$JrARWn zD&?p=X#b)4dh@v9WHpGoj+a~__#qp2!uJH_9(82#%>Jqwof~FmjEXwR^@1@;2;iF?pYof`Ggd)?;Kg|fBH~d~26mlyl@HVQ3);)k zVQMd@!DZO2uqhn~Kw$z(uaT-DIkJaY+<^kmMG&;4^nujCstPF0B;S&XTJ&h}OeKwa zaU2~8AF1Jvx#HR)Of4$~C%9EJTb7HlAGLL$hqHc%o3!Y#L`0wB+(geeR!dJKk_*4? zAyQ*AuA@Nkl|dH>D<6?4h1lbk+TqJ@SE_IPIe-C}?FGBAoR_1r zCTU`ABgTNXf#T!y5`0NT^~2l&G`{;e6oG#$~)&+>&O=%P5|Z{^@{30 z02*78U`fnTeUMYC!PBO=p)|CubI_xo;dq_(E8;-!&pHd+k~e3JfzjQNU-_9t>8v(W z1P?e8Y8GVYpo;06heGJfk#~WLUo<3qVsfb>EJ$Gm{h+90&Qv;VFzrvmUnuz(zt4$b zgs>?p$LpWH$Q{oEKN}q#f2cVby@BbgkPKT2@%f$_X=z#Ztm)QwO?{-D!VWvlD-PU| z4&v(YO5vhXxf!uNRZ*I-GSU8?w*OIaFUZYjO*bWVHy^(>Z9U&invT)TJFoGJO$VUX z`ligArYuC0r@vNOYNJvP&4cwX${# zi+1xyLhnd~v29&ne6^#76c?XXT+%FROOO8Km`+^JAWRdMx*-^@G9{6p9}YSLHE>y9 zf8}Bi+3!2V1EMXh(fRLl0xUkf{p^tA-;x^#Vc?sSVft=*==o zZ!_A;P_39lih}fmSmb*?ID60HhpbW+2qWnd@dUS?mBtN%F*y= zK}muJO!V`=-d1;Ogam<>Lszkcp)28IkAq|RQ4ff%00Q~!;4X1m2xYBdUR;)OT?80g z$<0xBSuZ}9A3a`VpqhlRwQ=% zVV)qcUc+3;yL-IY0gy%z2$-wnKRR)fdsbqXp%fJ?@Zs__1e?cO-qJ=k`NTX-!4w7* zYq9)yG4!nV>2W=r^;PX?U-f0Wfm0bt_C2;MU9+|qfKuB`ILrWSVfCpbV$6rX;+p7XF8p4AbpLA13p@dP zZBR~#llAU4uo8kitHKzo+a8Bc(txKjr@Ay57;m!`okb8&E~5W|rsZl%hHdK&_AK^Mr&ewL!wHZyVoo{*TZ_&|#+ov#+TUz75%7(3L)ZUvXjc!4){Z3Oe9yG0`;xNdTxa_Pj@$0mo@BrH zIqJYiPdwFG(xJ_f?+0)_9@1%^fg`PMvMFvo4v+Pif2%Y)J9Aut;Sry-!=Z>dEKX#Y z9c-ghhT&0t$zfWyDt}La{eYcnH-nDysD;vn^e2&jAk$Vym z^*y4C!>L_q%9CoO=@`RrgYSl7S;^2c0)H^Rh*3&r+bw64;QB#9h|Lm9Y?kXTFHmlL z`><1p|6qG1M?&sP$U&0zQj4o6&*(Og{CT%S%9SQ`;?|}4MfA_zb-GZoi`y~{kn?;f zNrtmOJ{S-X1`pM`mwW58PaYOF2J?d7G)>AmLhq;U(pZITrCI@d?EhHn29kY|(Wv2c zbhCk=yJ~X4^b#z!(@gqu)Iv#F(J>bX&_6#mhdi5pv*A$`U7mBd7p{TR^ z3RZ=6q{M-WnX}vDr00@HLRT{qv}7Y#v|)Js8>u=;Wyalt_q~Q{CYIgDL&I;fFN@C) zltSS3{@5seZ@@pwoR2#0F|4{${!pVTEO(r{M7-dZqi-@i)+nK0{HD6Zu)#;XJNpJt zwjeCbNs2@NdAvvlc2Sb#TYNZ=QtY9mvyo_Q*O@ki9gwC&+ET3mmNX3I$#n;R?I2ix~4Z=1=x(sX-Bj`gJI zu#xjcGBx%YJnxX!~&_B*h4p_;7gt+Xed7Bqp;9<|Tuq`b_XD?4Up>!F2c; z6J!El#zFUrH0)tqu}USzik>ioL)j7^BicpCm6C==BykB9|0Y2dp?nrtDz@3@HqFKE zXbj1771dJ{$;5*en513-FxBVPWP3gHkRaQ;4#g(K5vQZ0Zu?Ov`Q7Po&}o8=+IQE* z;)(o>387SBx#ld5B`>7>4r_|uWjFArEX5N68sW<83PI9{CF%RJUoJkCpd=K}4Tun) zU`dP~f*R}GlOweCeqBf4Vq)L66hRv*qbnI{NKzSkMU~dg)YBF72OO{V-S(bwMh!TK zVToRRhOorj{u;QA@IUW_e>UU4W!=Eutc`Fqn9c}5z?d~aUno9xy9jOb%?j--`L;dE)^zF( z5>pA3+5c_8l%PC67WWOR6|sD$FYF04Jt^ZJQltWpNK${XFPHw{O2TO@)N5?>SgQQo zvzfe}*I~d^8&w}*U^PD$3io=xK6A3etV#~?*=pFU2pwnOhjLivZM&?b2^Y2X+zb7_ z=7m=W4&289GJJ;J7Qni3XcvDPBJ^h9 z&7lhU;8TJKQTo|Qtq+H#RQw0j!2Kodtm4ZQhG_U@v)$8BXEwBr45;*YKxLhc`Q58% zH+^!-Bh_ZV74(+xPmnWjHEC`{IH!2_VS#(SIsDsaniY5NJo2l0POqkK$BH8|IssU&(Z&^X)u;00wGVJ#EuDM3?mZ08XeD5c&4ldQ`3PO?jtjbN9!FlZvLH!3mod#X7~z&U{0y7= z=me`MkdTyHwg?@)HSyF_CAT2IlBzr%%NK1iHaMhCKTEqy>Sy>4qj%(@gE@Dl67zs& zBdB{&Sj7(`mF}Bb9lY*?Y~3HjsTiuFyQ$_!C0iW7dT*I(lh3gk0g zWSW;Kw6s6`@|NaOqTBkeHX`e_meS zPh&+6t&AlQdF~@NJl<4tLPQ%e3aXa^XgDr8YSl_Mw=rTP-i(r(jJ5&-{&Iu;rFCo# zUJ$$0bg)nV@S4G=*D1R6(AR* zV+*t8`Q(hM&-P<=v+`=C;Spq%D^uhrIp-%+F=#NFK+Rl88rUU?Z+oMinE!&YV41P7 z3{N5vLSR|7IOxc-2pk*B!#Rb;nYT4K87O7HKt?fEskfY>_ph@nZ#hC2Jz^RYtrkNN z1?hNsmg`>@wuQd3U@=bBu71qqD)}5UHYsgbO#)fkSNC`W$t8|3j_#je3oCIt>NwWj z@m-dGluk2-Ijg;N^zu`7z2pbGjwRQnq2iai39r7n{lQisTrXougRu8!L9=qy6FTnO zFKT}tbzFmG0Y`#yT?!l%6?gX2U|Xp6n^`w94*{2#On&e6;C_rh-D=(6I;~aqm;|hOE1Gx36>UTxLpZP0V84 z6t(eNVYM&y?Cs_ZFHwA3>lEz2-tB!4CFX}iKURo**r=q_ zsU*>ICJkW0eMcfYQWqtLhGGZAHSlncc)s=NTO5%T>T4PBo(W7>BKA4KLY`4%ZSrm1GK?g?9`V6cxD5uV#T3vJFbQ>&s(N>m-Y-wDJ zKlp&^EBUXo_3G7sp2@&!v_*4U1xhW!0m!eQHXy<)5+z&mLV51`iEg#qk=$p8@@x*0 zATF-21eQlQ0GiUD=AYz{ISJR+SyC4Q`wSpaC2`$DxTI%O^wvd+8C7Qz0mlEyiK)fY2&%Q-pM1dzhCjjN` zH4x3KCf6A9>SdaZ>}ffZpWw)7+i@g}(?qf%YmKCRgp&pwHPfwJ!e%yC3I;!Q0sQr? z%h5OZN%0h&RLR(=SM7F>13c$Tm_NnS*Al4#Ibg8Vi10?w)ni!hSC=9$i>j&WxW!8x zGV`cmPlAi((Ex!S(aHgRa|ERkLG4$`y*njq90 z7N!66%N3r4#!9F^Rz`+W`=PKdZ@4Oe13f42mKpX2INkmU`^CN8>0C*_AhVBBj;9YD{x2Ien{GXj*CKoSeBhBaZ>!utvc00}RLe z_GL=R3&oY9r<$9_HM(yJaiU(tX6&VH&%RJb*y1ddWsbpGT>OH15&gH97)Vo+Kk zlA)AJ>$nS8>7ik84(m_RcMQx^l_D}$Yp@dq4I_TRqUuwJ5IDnL{2fG|@wb5~f2d49 z&_)`Ut%8zdUv_qBCLlvY0-cNyYPdWF;Ij_U!zH2APg6Ms{_A?wo8FcD_3IlJ#+~{@ zXfq7kZQpr3`RMy;Sc<*qTJo_BUx93om>}xm;yy8UA|}rS=T3{S2%5`ONT_= z!#>kU!`(gx2^J`4(`q!=Nt@?W-f#dw39=axs>Liwwu-E zPC)Cdz19aB1$gEE;vgYZ=F8I}JfYO*$7Qscvwo^WWOQqeaJfBph_1ckTX^Y6eO8%M z_Q+^qXERlU+RhRLDDJ-XIIk14-=_g_P$;itE{k>yB8vv?jv+0zZz3c30m|mU zNIP+k3d?Z{$y=@IiL37bJ!3ZeC8KG$T0ECwfC;E_8unh=>V)faUX^Urh~q>@qdv*Q zl|0IOHhcvvIO!r`$TgOVS+sHp@V~N0VhDpHPWFWzKX)ICzy0lzS;@l{W-%>(y@X-r zIn9w>a803BdMFmNk9rn1ueeeqRc1jDIyFh3ttc5%`572qzGA5LJT)lwAo{ze-MABa zu!s_0u6-Xp8zo*E+@C3G;i^U(W(#mzi*_At(099fJzj&-Jm|IpE<(KPFY2Z)MHE@aryh+@*EuIaJbY2(UG~+b z7{Ihui0NxgnkcDz6-d~v1wTrt5ywJC7qT>$(W}w1`}u0G4t1Lux54?lks%SeR|Bc= zy)i97H0Uzn76Yhfo<1UZW*09wuc@l)YynV&&m*cD>}2cEcaC6+YO1m>KMYPub4?Gs z{B2?@ToHF$g$YaST0zz+**q@?zgD^_ZYs~IT&?!(FPji3gIq&&${K z&%TLq&-x!|t{i-a35z^*7Wyz29!wZm8SZc1bj``~pDqPWzlL!c1;eqbYgm*@@=j-4 zdQy=!l&L;1{{o)xKf>n*5u33Q^(vuFr9?_nh{$_nkCAnL>W8{JYIq<&D(+L^yE3R}@<(e)%zVv=HAj!O+7PL(`5^0+| zgo>{#c5;1hIMZ$du?>I3w{$C+)r-4N9_`XRD$hg)n9J^Pl7}bou(=*@Ty)9NtKHY+ z_h5sE_%g1tI=QWw^eea~6eS$u@QS{Qo!*S!Wre$oxV z`!mAFIz+NW)fe{euQB`8e`f0cN3@F-Rr*mvz#LefNzsoKf*!iS1bzHWt-I`n++p|> zenp=z5h>xyG95kl$nmLl_*$Hh2xH~^Mv=qGGkn^GtV6HHas7&gyxryz@kICgaI3W& z$-E1>q{Tdh$HV${Zqv3&u%w8v?^6(m?DF#o$foWNsH(^7v4! z&+pOSVx5_1S{-od(=??4(N5z0rw6S^?OBh`NI^>t!K)Z8o2Gf=-XkV(>C}4U6UvLtB+I!P7+>-6xPPQDsY_AkZOG5(uYmW2A6x) zl0Bb(R@Ce+VT>utP`thV;co9L=yZkJm~QbzUZ7&P{JI=8ol}2Loh~38d3;~@wD_a5 z@~n{|&D2?D0oYRwEK*|CuTX+M9|{NK=Hpo`S_MKq<}fYX^mHSqCP%p62ckz==R1!J ztg!LgyIV273I(piJu07tkjFbGba!F0AV7}7Bk^Dox^F}q(H|nw%c5}?p-{iEURC87 zITX~_bK@R72g>pOZ7Xr)_=G?>Lre$4^01!I301yjo2){)Vcu&jCWAFcs2VXLEGj|l zb}+SzQ7zzattRTo<+#*evVnG3&IA#qT9l%&tcgH=Az;x-{ar415JD21;l?5AX)#rlNdhE5`cUA?zAJzzGx!@KyT*S-fK-ns+r64lDpqJc{-Xs zquc{QETo>De{hl=^0%u%u-_quQ%^UhiGgmF6`+Q|_uNloa$SwGSuZ`>uVZbiiHf$$ zA*^SOs9kagjkAMs1N(-;>8BF2dq;nU0V`E@aMyYE9T+(_LuU|rbt2^H`XzqOLPACA zX8|bpBKF0V|YaL_byoFFC$;y^WKMgi&_lYVS5#zm zB||TOwuu7{L==GHIHm}Yy{-@S-oz~GwlT1T!QF3dFN|Lplhk}%@L5kbV0!#?f1&p4 zX2fDgh&N}8DnBAKA~FtR`4`8{BrJ~mbU=@^hg}}johyIPV<=x6Ew8$+&O$0NPtrk1 zh^{Y_dqa}mwUZ25gb4o{Jhj_I8AbK!qYAB!)D65^oi1$g+Tcg@nYbx#RDn8>^Z705lyV30+5tGjgc3}==|R}aY-Crh7Z02twqD?ZOC_&M68?$? zBa&Cz=nUv!G*yjEwGuij5j8XRR|1E&uC=*&_r7!Ts%Y{>x4cTH*Y%V{Y(<%RnC%t4ub_9{6eK!-$~w*@iIZF{zW`b7-f9grYGxY2B>>ceTOiK-cV zieq>nWly@QxxJ}M})30>0`)1Eu60s(E`o^;!oqayLda{ciCEWGHj zcR=TTQ|u0q`pQ?Tuqtujw4|#l<4M#!VKNM39t83jZr`PiijCZ z-{I4G9vND;(X2t;KgAv2OP*(E(k2%&Ql)*xAvO^hjo%h=`ri8?joLQ;NGj7W*U;^F zO^Uc@apwBmIsK?v&N~-Nz#GRXi-^NT_t)Oo;fi3KLlXxw0~vReWD?b|PLvbIar@{x zb>Q-+5omY^=rTKRADA&Z)A{r{gCv|k(DIaWLr}LHN&1pzYAq57Gi2}A;-^WQ8@n4( zj5oJg*Vl1}*(b6-P<hk5)a=>BUoKe`}@uN z0j%2FrUpkR?B)Amd~=tG)Sx>_-vr$n5ZWH;z2$Ku--0^1a%7@6`r~Oa{`s3*%VIKTm=lg}&xzy1jh-z;AEC1tZf8~z zwsi0Q)R@S|M)M?mZpDY{WNE*nhgd)@%bOXQ; z#!77?H20e5t*^P~cz1`JxrD^$9mg24k3sKwwt6m$4C@{X+3Jp${VvkXPiNL;UAI#B zJpasdUbkWFpN{L*tXw@JkagWRc^F8B3?EnJfhkkyT|4gOg{k&Zt(#Puqz(d)p*Xes z>kErBQ5(U*=Ylj98O!f}J)^x~ZLKCNo;vJ$yt@#8?TPP?zj5A{KIReld37;gDXMtK z>Jr2JIYhSVySpKuKX*gTDDRJnt~#X$j5p3dfP>@Fk?# z6gj1PJAv#!zC70D+1Z9V1SIs zA#xc)Yp%}TGFZs1_XwM{2L=Jr5LGC}>2L-nn{UN9H%%@jGR6JvI@FVTL11~D%0*dV zDPUZ3YPSvAG1#OghZuyr{^=mG6|6*IOy7FQn<#$`fQ<|vKRs-mmjvXw^XV*6Cs8w~ z^B1qqR*)>;M!BnSpRb8MzAcm8^N75qrra}mqAxcfbHC9neXoy>)AC-3hG#rww7N0Vbg()psJ z%hSi5E2d~y8?6pToc5p93Uf-S_;dk@VhH@XvBaAAjNRs|$SO+8uoyD7UW$;onbSmL zrh(z(oAhGFzB9NXtsJ4?9-=AMY54kgu5A{Acl(07W_{dm`u%$ugv?}#*c0-(u>m&$ z9MQTaQSHM&1_L$ar}N8B6h0cPu~nhb@j4+Y+sK{@?#~ErpAkBuj0)q6XpDdOK@h*1 z$w6tsP1z;|kR=N{3QC&ir@ny{GCkN_J}bI2CYGCb%{lehJ@{(HI0+3E)@UYPeU3gu zV&x(J)mJ6%>N03u;$D~jun=sdMFZr!<*`}qn;ITWP#%BdJK$&YrBufh?+^`-l>P4G z`Ya)0J0?}nx6#yr@;-jqEKAZp(LB;q-7h>ZZ>Git_4xs#YSEa>*N1W|-T+)JEW@8< zF6>_-4t@8`FmjXMhnWR4~22M;2 zO3RvwX}Y72vF(N(u>F`#7LH`#NmN;VfE1t9a=VOJGe;Vy%O6}s6j+7HdkY47fD-yY z8-CR9lci+Zd>S}26VYuj${tpeOLjCg7a&Qb6&<4$MBu#)_*u(VZ@!%%HDW3`PZl*QBP=8MqS%CrpN5TFM8~U!{9ZtJJ?X)_zTaPT zZQW6xs38+a)UeMqi+$-Fsd8@5?LyCTOxSAY_3S0qEdtA*VrzsiIy-S_Ed{`_J#nA=!Z+`w_-kv_=*LvZ7yHDo&r*!yat5v95_|fZ$ z&&{w2^uC`~nxUYF%0qCT8+**f+Nku`TT7e+raDF)>B@JV15;Hg>HHaNUpSS9WPb2Z zuRru~uWYtjcc2)fjMnYq@;RrAUqO;a;D4SG^S4Ua4eH-r=w;E_*M8oV`Z3=hlRV|y z87@2FfP-)1xJnKmtir6xNcTIw^K@~iRyxoLmba23HvZ7387zq&bHoBboPX3_iU z{M9-3^hnJG<3tU4j~2+=S5IL6>z(nYbYF>xrxX+Rp)53BQp+f*qoop?rKJU@y!8U> zu$n~J&6ypW%rb5~bmQRAywL)7O69?M1e;#7Cb_qomvCG!19yw7aeAqSm}FXYq^>PZjb0Q1$pkQ34P3|e_e|VL z2|VrzHJu(0pG5f__6RS}`S~P6^|*(P-)F0UZq-0vFu$7@u^$h^(3Rm z$*qr2*YZPE(*5Q7v5i+~e%7*78Y{D^N1<2(VZmzCSw=KGoJMTTEv8f_re3MAp;zM@ zMBS$C@qSXe7Yf>T zghWGZHC7!uDHqZTT29>T-d)p&(x1%4?KSyh*)|un=3+5V%(=t&m*QBe!tnHRBf3$WqeQ0h3TQ33E1oNU;&N>-Fzib z)j;7pGqg|!40dNZL&U?tOy!kD_rc5CbHXLYxuD5bi*F8_e37Tj*gGArh0^%5yRG0k zql@F3werV%((*?az%0~3EA3Pf5q%n3!dX+^lE&-Ky(w*{ww5q0+?Dn?8|2f{CvZPZ zes_3C?Rv7CQJ2<|!mhzM@2{NIRozkLGZWVO802lzbbmM)b<#bbwVtwk40-nF0VUi` zcFNrJ?pQPqP7Hh;{N7n`a{Sk)#jSH8eB8(i>`%(tt4V2+SE=@WC|q`5L~Q6?r*Tc8 z%tuO*dG;~-h)z`L%S&wb zqUg8tXePFI=Yzq+*p;>@_{Nsoq*}P5jdU4os2`-=)~fOvDgq9T!sgX_)hbTqC_9Rx zW8qkZDWJ0q!+AzKd1t&MSS{9=x=8bu=+rBGJ6+1gHHQKhsoWx5+%-nsUMelY?Sids z;z+IjE2{nnO6)_6m`wFh4imh}v(%Va4@omD_PR#_rm z*z}NRhc(i@0+d3V;Yy92@_0@$GJ8~SO-i@x;suMbPwOM<(x#95e=KQKUcl^hi!qB` z><$`9H{)a2W@K#TyEQwFOCYHk%XxUpHigd!s9IwVEp}@e_UMeP(5z@TS``buqN0p99euFBd!?$5{0xIXLb5)fX=wr^h*$m|U?Ti>1Z zy?QI1ZVUXbi#mRQtfS=zdXKSY+UQSu8_((_|3%PSWI^2RXo$=4R#c8&xLkb5%f@gx zn=$&ZW#sieoR&3zjUuZ9b<%f+n0Jl*0=&GCFCG(sv_>y_c9 zsR5|m!DGmG!rkYKYy5j8S&F~!w4>s~F|Os(Mvh%r<$Qh-VvQ|mVu<>eBoJOdCilD? zlC7i7sLxdOuO__}*cadHni(!z^^`S7`||(1TVhK6a;1kXDSz?dsU(!%Hlo{S?g&~k zN^DWNC3(*tBrU#HMQ8M4YrxE+G%_UF&{m<;dSRyoW7Mku;^a`m1dXr9yE4Ms`~7kD zXH7^!mqD7!MITp<*n~5tPSMyId4J7J_c2dW^k-jJu`M;#gvu@}ISc9hG(Sas#`!I& z7WNtguJ1#7c>Dp5YFYp#TeFSXO@|6sGV`u4t^e|$yHpf$?1!t8-FT7;?q z8#I80&BPrhWc^r+|5H#ep|p9wYR|U4Kn9Pi`^m}YMWH&w5>K|v>P~y3h$JkGojH~ErxT)D_*a9@ffH{-*|s~E#*w^B^1 z5eg6g3J!hDaIq(ghQ)1E5E}gXA}m^oFE!DoVoFY;4BEyYHD7ph4V@gQOiyr?R1Pw2 zC&@JJHVk5HCHB6es^wGX`ceBEtF-(^PNz$^|NkTGEyLR0x^L0lmQtiZaF+nZo#Ix4 zYYP;2g1Z#AQrv?The9dtZpB?ov7p(wOMn7FPul%I_q_YP_c?cc$QP0)i>%+AbIdX3 zoXc@P=6y|O4POor=WR{J*D=KC%0F#{T4Iyf?HSE}1VY2?W+eax5BIH!+@0j7HExuwj>4Jco8aVO^1p5> z_1ZE3abYf4U8H)U_lMHjzYI{ijoqBRNE z+V(4FJp=~ZS-+FDu$EQ3UAf2j4&r8!gu*1^a?0qu){Dpixq7P94Qr1U zd>fCWwp}>Mocv(5fx)mUrub59%jKwL&uC6Je!8Flg&`*75UG@n9t#|XPev#Vo8>z+ z;)r_cxK9}L%%3#S{Jo0|@|ASv(}9GAXC}dYS-9b5Zo`C;PfB<`clHxk;69d#<}d5& zGZz6yG6`DzQddr+aUU(INX*M6e~di)Yg_6sP&+w-nQMI{1iBCt=pBE##0CjaH>KqL z{N_w0mY8h1_Rqsa_W$!R?K}l`gtQa(BnPs7l15Vx7JUt%RU{OmD~N(5s)Q(fRtPMC zI=m~G%?C)9l#)@VV5sL216^XH#Jp2k-U5N&%+!%CBB;RZou(XyY3g*OZ>>m;4sHS{ zSyAMx;E2mW6~*`dWbmFKjX_TA*Ab1!l0QCrOM!cbf6cWI;x0MWI4uGyd7 zzr)aF1vBR-9~Hjo(70FjP3On=4gF%zPMD4AQh1nu2!@W(sD(1&i-eYz%z84sRrD&r`mBPe`Sl6BKk8ve1nB~78CzfjO zlfaw&i2VCI%$@;{LbzaK9T%ZwtUTdrk?bf)+mcqitIo!i<0%}Xb)mofhLdu*q9c8e z$J+)b2#I+G1RQC<($BS%atFOpP^>%ZJ?Lm*jiir zb>$VS(VLga6<2Dh)l8#Q5k+gbh)_vV49r!>W(NQ)HnWsicnzy-E84eQgX;@2Ic zrinJ&UJUs=v8|PdOkBewfOOd*cc5$ku`Kztkr`{r;%h$>h%@S1p?J8-dkYL*#`zcw zMR2AmJRDF8%vZ-fRO1P?u<#|s;URw9rWk0Plhv$v-;}YLCn=4|OnLMyVUngD%asp> zk8_azrD6Xnh#{){rxBW7NluCmUj7`(+l!=;b+jN3&CyIqTFr2AxdlZDub&L#L$+BN z@>Ze7XLMkEG}UXaHS%!Sf!qlp=fnNUTa!uSNq)kJ(Q@g;Y*+K2*n3zMqY>m_ax)>{ zW}}2^-Ag>tOC3_%18lPy!jFR+awcX^SG!Qe7q9p}mm|lIpl*#p2M{7sDP4SFkII>2 zs5MdyM>I>8m@Z1B?+r@MeWZ|$Cmgm*4qKy;PNp*2roG%#{#_OhdIk`jZ9_={UUF7; zk!mL^vIUN_*erQ-X9p-P#M#D<>kRU|N0HGtgXkeemkOO zjUVPmDr@?3bH@*j2slZcw=|7J+=^wb$L+^4Ue7?gTCI)1=NaYqus#9Fxd~6oxgXaP zz&}xs9YR@J`aTeI!7R~%0m0B`M7i#e0(?&=Ui2AK#~PZ97cxWv!qwDOLy1?o3zZj0 z^3qtU9q}$#zn3FP@y}y$hVHg%0fZ1qneJ z7%i{p^B`I3v&^%x`4UH8B4obmX*>9rUpRK-%SBthl9Epp+-Tdht>`<5< zfNIL>AL7LuVIwmTE^nmytF!|@m&}z^pFbRssBu@-I7O6QoC)Nt8s;Al!3BeUC^l4@ zD(!(6xg{r7VyTjZOU?~a?D_1CmENHOpHH*a?AKsWi2i&LXz~;vUmT?!|1|EFn`^!I zaz*TV<%>)|0x&7+DT zt7)PbiAA~6WSJdl_saS`&)^V&LuMg1xYa;#j9p`jA1@Vh{MW1>2z&G{j1z0!Fv7HV zP?my(i;5(T=U=Pb?s#!zUR6C7ZI#4i;T>ZfLmbWwXO&?S_vLjQb@Ec0i4!c z#iMwU{Ut)5X0}b1Z|@LNVHc|?U+2opBQY2aDo}UY=5InJb*dEBHyP1+I%W0w()2s{ zR)M;Erjd8j!HBNMgWDqRVd;(o15}V6;eao)lk8Fs*k{b`1!ur?5uC2GU$^XB^d6J->}HM2)4 zE4kAi;1IPN-8cIpjc=Az^K*_$F`{x>!#*w(hE7^CgGWO;JDWLl7LMZKw5n|*{ z{Kjp@Qw>ahE@Ll#w8(CX4USaSg4rSCLDhf7gN*X;%*bC=7HP1rk<8u(wp3EXW9Eu)H`#Bm)kBL-@*otf&oFYvyG6r=sI)qzdiaa6l5IP@v>%{MK+{F@0YN% zL`7m;fclJ|Fls|xOnyEObbi_KF+T0%JoU$L=i8?wS8uy^Qa$XcA+~y)ckSCa%4U6h zLGjoZ>ybPA@JEZg=<{T{?$rnsP4^WCd#UoXzH*bsL_;LoxDkl|p9sgLhzmdHy*q7v zEW0t4QCZ@Nl)&=0iY&Rsolucty}!C?mZkiyPol`^VvsX*&&vcQECFx#EgE61bU%+z zBV5K;!aWNwPP*)@Qj!k^K3%5SmA!3^vHPkGCwt666mo9~E{Bg&X;^nK+>z`bbPt3< z8&NkYpw=z-U+)zMNfllTHJ#*R9;3T2{Lr|u&kk*W?O=1cHhSW+_V-$_4&{m?YTAve zzsf5aEhn+y`>BU@J8`!(uA{a1%UdX#$H^+8jnxg^HsMixs)uo34KNP>Tb+e6ps<27 zH<8zwuEROrcMZ!wE?^}hE$VVbB>Z-&?9Qyca4+BaS^n^h=dRhNNLhPEXnFSAEZzPl zcy`|$hrKA@r#zTUXvLMgzP{?C;{p zVUxVM6=!T(9chJ0j^Vi14VeEmlHWn-}&;F)R(ua_lxQ$N6x~ zijtd~ecQ?=(C%PclHz6P1){fRe&X*B@*#PcFTj=QorIEE52E|G-gm0fa}gw+nQod=8>%#aB7@Tt4VE)dwXGGp4SDo#sSv)Ff2ZVf;shBCOMV%h z)E3g9zV=

    {&Fg#po6)+vlUtM=3h?`q6SZ2H||Ks5kmrfCkj??k&tN%F}KU(vO^i z-GOu}rBS+)A5Wie`5G~bKH(g=e_}v=xjx-He|qBC1m40CpjmA}ji%gc9@L5z%(Ryp z^Pbh3c=~nmPCuReH}?jk`L_q_PJAQ$@klB!v(z+S3(%@?a24h>)+T4zEc$oc@>q_u zsc+kYQS~#6RNCZ>K;^|YF7s7Z93K~Zr`-XUTg{77P9fQ`Sl@F|(YUTljjDz#a_zCq zRW0++iF6;%jg5|Vgrtv2@)5B~921u9cgMw-^}~*scq(Ye!C;^iN-znTS?<&iw7Vr5 zMzf(sj>VaFpxBxm=MLJ{n%(ZtNb)1ZM%A2)ub`i3?$y!*1zv z3n}NV;o&YB{wmZNHSRakYzS_`HNjH^mJo=4kB?e4VonAamKD*@p4f06%UgEM-|^K! z8IQ$$o>@2>O6oJANu*Gl61)L@4r>`wG3gZ#FrTZ{Ym@98&pc?@epBbdN8(d3P`AkN94DXqvPo(n>ftD2!q@Y{X`IbF@K)f(yd9F*nVCpa!6HLz?EC9Min$I`eB7| zj8(#HuJ?%8sTv!$ZSWiZM6{3={l?v~B>>tPQ9C5RDx^NO7-~L9)Ipw7;c2BwJEa@l zcSu_xygK+jo@j0I5gJy}#!+^Z(Aja^`-_`8Y|!7?+mGb@hA>Rb=;9o9oqE$Q_%O@V z>S54zVtfKxyC;WO>W9<&q7yB#)Cd+~yVO2+ZOr<76{9MHs>1}V+@HN@%Z#K$y`JBY%hD*$GaP^Mub_$n2#$BNQBqGv$SCbZm z_TDFC+v6%LLp|l<=aZzEG}TR&@ICU9%M6xD@*&z5aB~ZgN z949*pPxJ0Y&{SDxTfX_QESKcKb0uPFA2PfUIt)i_pNjxV@8>6!felo<`;tyW4@FWq z_|iMyj7tT-e$e~=>*+*huW@aZTCaA3P+Z8bl=&IE7uA6?*Q>7MSqFN2m}AWmanyFw zbC;wWEW*ZR*5U8$RXd5`7JY*W@D%E=kv)}ef|RvaKSJr&POQdnGj-&s1i7rCn%lW& z`qFKeq1$A~+$>GRwkuhAiJ}HF993zGXU>E|Zj%uyh(}fFJ4<)H$j^W&N{^B+xN+rxcRiSJ1svvxi`(xoI;!?JlP*$cgBRb)+lm0LPkRFbIx*YY#!rxM=p+fz zS1hnhbMkp9lfcglwP8p!VF($_R7Y6R;w2@JG%+ytG(WHPcyO_-a7xRnAsZY^U_yL7 z67^qYT7Rv_sN@&7BBjnp)ra`X9g@*=(cb)vA~#Sx^Kws&&rnwLUJ$o$i#L}XmX4BX z;m749fs+u>jr$?IQf~15X3+Cz2}GHTsFjw=XdUzScR(^_70Ili{kUm7}}t> z3mJ=D7g0ZpVc5~IPt_`44+ZR2Cw(awf*k9FMK1JtpC6&(GTA{d3!fVZl;zLG73=V@ z^nWK&@8uHk7&O8cA${mfhecMy$~QY_@6t@gUJs_V{*R+dLOLo>k>SPu1$Eq_JePy& zD9#{FeXM5!PE`z`Qa$q6&bk;kJ7V;Nj9J`(R9^Fw;pI4A9uE_>0scMmgXWJaC7h?p)#ew0a4(FYfAIwD3rp8`GIJpz2&pH9ID=B+V|trK*sBlA_$;sv_S zke->VambK(lBF>;g(2zCM~;67Qef1ZeR1+qmY1zHORkwJ=L|?n)3-xgjTAaOqmeye8vvg0yi`ZoovU zeWBM&?WW>j-=r9>t(>*6n`fG0Kz(WXG8=GT&nNRt+|TAm9cXaDU@F{}cERSAbsrMk z^%V*Jh@)Ga<-ZTRNQV~5yFXpOOyZwHF(N2e_>^uM$C#q8HQ&okm@}D?g|<;RyqFom z+oNcFExyoilC6`Q1NoP>0@r^9&M>&m=e_R zll~C(K5oL6v+O!;Z&78JpS;J#CEC0~Gf-ov#gKO}cdx07{)o1d-86Foa#d%RG5&R+ zbIqq7a$sp*E}!DU6wr)qkAsUy@KzS0+gKet3E68(-^5AU6G))utq9jT_<1y;i4`jn z^@oI+y{>#S2)%Q*yTr@q&nV|ZThduhT9L8u$uF<`;mIB`X-`X*0MU)_8xy9-9R?0r z0c|$w_MweA_hit{bnE_=1&X%=!^t%vFSoO%YMt%D*ewh@P}$Mn^#Slstba2BT<8VN zRq2k_`mh2lx=YlSS3xAt>QvIQxLM(Xa=Y7=F1*@~Mwuab-gLfln}r_;_Ff+q*61=5 zi%+@>_w3lQEU54>L`>&~4@3m%vJ-a%iIW4r0+jS*l5*#G45?1Z3g!&ZP?hxM#!1~! ztx*K#W~I%Q4t}tbg!p~{yolFZc^5xB|5Wq#^yH}MhkxmdTVGjc?=fm2C!UeGx&+Wu zr9=~=w2g83zBD*quA!ZBC}vGaE(`9K|?(Y|m*tg%7gv4+1O zk~R-(Ow1OZXWzbVKTr41Z*1T*cAePUiza?IP5AwlW8Y_9+=WlhneSeXlYOmQ;JI8J z-{r?t7P6wh>EQyK?_bW;_0QT1zwIOeU91Yn6U}g z!Aa^$4#!ar%*3Hp)~9nk_Ut)b8mkROpUNDHPq(*0VjCfCzSqZ0W{v|Zs|RrmVY>+Ujx5Y>8)3jUjh}MLsTE8iaP{Y2blYJMK~pqZJvf znKyM&#jk1zrwOqq2>GH(kF1bz{Ua%({5$J1S*6h8l<*k@dA6`OdA4_Bo#?D1A#aSN zSAg3Xnh+R*Iv8_)0}?>=N@volEB|Cv52a7@n1&|Xad5u6T^?pTM{Q@;4xxyUIZWGz zxp|M%hNCO#PfEr!36)27lz7=($xx6-(Mt7H(fDvm=f(=2FS{P^*ziu|8-pHhKrp!l zxNO0=eMlnV7~IlcV*K-YjBikiM4`XHi^smc^e#o%f&+lH6LA&0lP#3n_jb3%k^486%nQI8to|PEIslM7JBz;zom|RR5>0n7JBRVeTGd$`He}8^p!SUj z@s@+l`1QvM&oAuq;8qCsh-^EpOuTbFxx)L2v9RYx0^=>?if8y?@q|-OTDxI~cnoU2 zA~Mq3EpS%aD$`N#?JJ6NaN(~XJX(%!mA2N)YDiJOZ3UTFhYffF7F@;I@*W&BNE`L~ z7Rn;Y`j!rGo$SyI@p}Y`2B5BU4((Z?We=ZEGND!6GurY7my_7pDVZw@A3|5RoDyvI zy?!SjWH)2~aJ!)2g#exyYnjjh3Xy6|oDZZ{SHopj?++I~%?a4_Mtpx_FQe1nlONl1 zRMM*8Z|wQo?WUnndx!FBOs7Nf;1yRXv9VMXmxpTISdua)G{YDm@_b>@qhi`M zx4X>kb>6va#+Z0(|L4fcvtE~Vi{3+vJ2I`7G0X3`kJ=D}|NGb;Uv@->rKo<65Z=k) z)U@&6rzP{GeyORiKk2R{B!1$T6PMZ=mj{0@!I7!y?}xaZEJ3K~Pn6X1&sffpWRHKY znJ0SFWSyozHqrjg4UK529@8?qY~e#r06Rf2?>?cXu5Zt^qgLjGFJ+4)_S+Q=d@cvLP$7A8K>o z+=LIjL%VlKtkTWA_D-^O`VtIAGp|Gi$s5Kct*F>*ImEiiP$ezLCTjm-J1G9k?j*y? z(Q`?6dM=rFFjxN$^E|{l%M_~9GI7LbhJ`v_VjBut8}JTZTznOyw_?NPJ}QJCL*nu> zx27B_YBs{GBEu%{cq2nH1?!Lu>`hNbOd2QK@M5T_uM0l~+7jzJrd=Y3@?oq|Kl$1N zZraj=EWUnSB7fg+Lvwt+`hgaF*^F~QpfWHXS^hmzkgoh9dj+-TjPvjG2F-0KNKil4 z!YG&QMN{&|`NYlwJgfyZl*QL+YfNu6Edxilt*bQ@Eac_wQkY`c8ylv26`!&yH3E;--m^Y+XMjrku2 zOBlp*qRveo{lk6KjtFhiV)kui`n;6GpQ;&xe?yP%#LZ|3t_G`4xzo=u?%3pr_e#HV zVk>?UQlP;Ia((C)vtY63{;pSx)S5to)&(riuz^kgebVSpNRawAlqJ(L5u7WTp@PEP z3LLbv0)5g?e3AgCb(KqaGF9*%tt>vQl<#Y0_zr}8QcIu~hXf@GCh_S=g=qe(>E0ky zttG1ZM(n##uzjZu6c!I$xb+J2VDNUOtDU=u<%0tv!>!Hi_{C*a!r9tMib=6 za=0VOc#kV0(%&5pv1Y_%;_LeIBC+bpA%9v<(^~VFu__fC)(EHxa|u5Bd08Q~167n*J+^B|=Fw!5FTcZy%O0u5El)mF+Aukl^sS_sBDE+iZ9H!;jb% z!|f~7u@UNDQKcZfv=sRPR!~}6b*l|UM~nDce>b!1VV6jeGO4$N-0p3un;`X~r3P9M znyE^QN^N|VbuEoS!r`7=?Bdh8uKfzJ1a^^r>}{1@7B^qzxaq(rC(;K~&MfWsTUm{M zuUWsF+5dVY;!iZUL0}ZsdigU*{AFmR3hYc6)zlZo1u@fIa`yUEPd@%!Zd@nweXK0L z1E023N0L|OdQ*ue3lm2qhHs>}T zlkCN2q-`OdHkwcnqxONkS~RX3*lizL%+x8flp$~#&Pkoj?#|HSm9t~q zcYF4~(FxGbVlZq)pYB|GP~pSNasG$#ayr~~;q9j4eHss((DjW)(%vG>2FDC8)?ukC zW;@L^CVr#oi|>&z^l7K*GZ95?U<(F#$3q3;nW)WGJ}zxvO-MxUn}e85&fp1jI|?d`!bkePKX?0egG3agnzt z&_1q6|0@bf5gcW7Wta$lJbpMWFctEV5@?-OIZEO-pI!|}yJ}c-d7C0~ai2_npvmaW z_Q9B}nfM{3(T>`^ zgti(NkaJ3lIPP=IednVri(fiyt6x@ni7rA1A`@rdcFM)$GrVVrX}tXw#k#M&Y3(2D z=44YBa8>V>m4ZgslVX(zSIte!uE&bsLATl9^&^ja4kYZsVItA-_oC1DWg;58JkEoR zO}R*D*M3fO%3?>;RZ@mqjkP~;saZIjqj`LR+j=Dzw_~6mlXoNDx!af9Hzoe|x4XQm zq>L;AUys=IJLDv|@TQIWOVUUE5aCs3;P*xoWM2z8H0JsjD#rsWG6)TEKY4ExyPbe8 zdY_^aWtIQBUDNWws)$!R2nQrg9SoN9e~)yRz9%w76Qk*yuZQKQHF)IBsXViM)zWS@ zS)6l}5rlY9B?-WEjpZdH=|op+<>73zio9Al@AVN&_onRl-eNm2d=c1dZOz7o#HBX> zPqFYu+kYhnX$j@8T4@O-q=?NARFktP{_>%2hky!lGN^tLjeyR^p^Bfm7Z zFuROc^P9P*iV$zN$tyX)aSiU_Dy1PDzk9!8$Ju#^x`kPMZE!1k=Z83c!aH}s5wRf< z^of%+uo&ma^_iZ(scBmn7`n0(dy$}Rol}w`Q@0T-b-#-R!@qhfgw&;}{32IxCE`mG zzdtcrTnRo0YYf6~+XVynp~?Hap_OiGn!dOal@Cx7x;u6L{XvhdV7EMWVY-xHWR(2G zvgkx(+kUEBH^(*D=I4rJpK4EMUveV`g32_&gF6Fz8-vx0V|khMcF)fv>q2Smo)=2= zRzWzOtk0PRx%jpb>fA2JF;TG7&$TtP&P|XF)a~?1-pz$~#yI@4nmvt8&d*+s&BO-Se>DNlJ%1TK3YxiHMcI zp%gd|8U0m}Uk|hR!#-^+z0eIe`%Q;|*Z%uUD7qyZ2HAi3vRFos{TMg*CS6jHGo1c$ zjaq%P8-WYykepFo(E9LVRfte{)WZzr=o}iR{~MgCZZsruG|SyiQTd}*AvH0iOxBD% z)e3oDtXOg>wE52@r@s2P@1f6Y{QqpvMyJAb4kyvtdRg^988KuUfL)c1mSAvp*6iZl z6*?-ldg>kikQeRMo1cpefP;~zz0X}eHh%!XDey&dpW-*!o-LkX=LLTfv)2#v|KOZO zX}Q}gY%Kw)=UNVYMA&W(?jPE$bsCVRWzBWh#$)3PAL1U$^ISy!>%UiMufL^@!$S0; zRJ7lTb57(6ho!PD+FAR7i-jWw+~`QoWS-k`p|EJ=gF6NKlZulq`a_UK` zmb=7O$w`pE!wnbf>~<=exKyPFL|#?`q<1Vk!vD4g>Y*dVN2t_7qhDoWL)^Rs$Zv&K^3pnq@kcU1Ui!9spmM|!`DBMnqe{f&o^;e#+~G!s0`ntj*E!1q=mBKY`tJtp#su;c zkocJR>Y=r4yVU9uqzi#pD=wSwz`O3y5HV^iSqkQTbnIFmW1wGXO)z(otF6P0RJ9Y) zGrh@jbMRz!8|$6at(d8Jc4a_r4Nmly@mQb4Yug<*Yk>z%*wkH(e)d}6D)bqi?k;E zU97!ne%Q|2ZM&*(V-?zR*shf8bxqTp>izuwRIJ|RCbOQEX$M|fM~;MA z=Q`b`Ck8b?HpXALWiORx6B4za9CcNUiOqLluBx7;3n9AV`8RskIo}z00AwtTnf$8P z0G}o5(+{lZ&UNO#?}7EYU2}vQ+X!{WO+y74194oJs-arJF+GZ+cN^HE_XpX{CsPdO z1n+6$V4Uk@)F)X>i^*NTR04?CQ(kWOGS(B%H-{{v23Na(aIV-m3F`Oqd|JaZN!-M< zZE(A)D8jm|2t#z)QnBj%n*GfngbghJV<p^)N6i(g*H zI4fRToY`K8_@#&=uU}3pUN@oRLrm7{(s`ON1gNxN#!4TP;yL^E5vx9Yu(JW#nXm}I zm1x>X5om>vMN`wgDoS!_1T`9~a^3pjAn%BOqi#e=BxIKWnUA@+BdWI-#&M#F=<1_q zKttTYi|CwJwL|IUupD3!=5mbdwfZmDGr)a27(r92XpxR$smN^~$+UmRwL$P*|5DPQ zIyvj*T?-P}{p8sb&3bQicfF^&&EdAfu#~AE4>y!@Jtm^x)}lMfYhbDr37ahzLu)vj10o9}WjWmPWKjpcoQ#syLF(E1zN$gv?}g^#Ou0wQdjzOlJ``!8tu z|L&1EdOs9=*+mw5fH7yq8;9Eu4RvqW&0pzg4zxBUDAEvh=@1CrsEdBcA zYUuLkglxeM-xv3D?b8?E)3PpT<*ymVuCKfPs!b)NThNWZrU2S)mFr(>qlD=?Fql`^ zzZG-mKx!x=&wzj=w=#J2&e9JF{xEpt6E6m2Z2)$@RadB7z+yzfvhem{kLcmq_*X1= zdc{y%)yvowW3z}(!qt!QB!kV9(GO~z{967azuK}oS=nt@>ZlkoF8S$~gcEui#24lW zLE(#PG{dIlp6C-keLMWs_sgu@d>xO!6`TLtL&i7MMBclP`c<<{KXg`9t9m~(Yx-k2 zl~YgZ&cNSTHvqI7bn1a%Bfqo$zc7wdcu6wZhxN+fma-yvt|Hf~pXhzXa=c2hwQs`K za9Ra(-xqjuAulpLep^Lb_621xR3ESdjS*~ketywXVZwJ(QD4_%aI4p#^o0W+rxKC0 z|5}dt=R&3b^mApD;J>&@v%au@y0(7&>yUNS8rjCOSx>vr{lH`C$U9YB>WXiksb-bB zC8~Ay$Huwm;pK}fEalrZpEO}DW_g2|INQQanj)-hA7D#C`su!v{=}_@26GJbRsw4R zoX1_KX`oolLkvG80Fj5AeKPPoIo31pK$-Q zw3oCbXf%K0be(M7hENmxEPEYBG8CL$^^^u4w%5jf2>Y7IB->htQgW9ya*}v-m+gG& zDc2~aW$qw$J83u(DqTKy-d_A&z#vq24Ki~hQ|E^g?WiEgilC=^O z9yk-Cv14%hHjYkk4>+*4al1PCqI$DKuhB*(5fDan59U6PoztS<3|m|{fF~7YxKzxC zn*69>QDj6KGRmcY!1K!}id76dQIBD`hz!{zN9K)HI+Tps67v64WsA*A2wQZ40 z*|lR|ZxdmR(zau*1Mkm6cCWoHLlSaKp7>{_pn$}a`)2{7zoOZr>Xj`g^yAN0q-;I# zA1+cWNX}ipV@FitpWZ$_jT^lY3j?N7m*v8wzqe@hU#KL*{#vAaRi$!N3z1%0NYz@a zdRz=`y-cz`6pi$p%l+u)-5}g1y1-$VCAvA?$5#~uUVb2%^@gtm{R_6qJ|<2)9V7EQ(jx%RpX78B=tCpVyv{WKUS6*B6oWvw=jVgv8T{Oa0XNzY+S zO?}M0t0$cIS;<4(rAhzQJ&aCqo&RFu+bj98lsdyUz*Y9EL+O)U^7{&T0J&ghi3Tgt zxtot8uP}eM)H@ctXGs|97PnIm;(}T;z-}!E`ye*+3aEtiT&ZWk<2{`n-!Z`l(PfO6 z`maPX5;F87i65$;gOAabQ454~($b_Kzu-uC7h*BDXv%+HK`AVM4x8nR9V+c*tvcx% zYNmeZBAMsl{Dd#Aj54s6>zwBV4KK>Ek*lq+(K80xC1p|8E07Z{W!Q8Q-CYw?3cA@) zfFIDCZ92ajzck&uw~%j`ca2do*l0zxbqBQYtRBUyWfQ|F{{?B0PUC;pfI$2ouox>N zlIWTN{}G?*eA7;jpADmIY!??5g=8 zjwV5VocL*De{s3{>-Bj~hn^p4I8>c49u%m>#XeAup1>kr>pxSs*B6@Lr$6<4(-?s4 zpp||7pCse|NB^v<+@}gE9I>egjh#U*ZlS!=o=^CaDA(S(S-NedQ4Z#qiU$uhX$Z@! z_qCVsT!Hm7cVY$t-BE8wAt$bgXSv2fZVDxmbK4$%gTs1B5M0WTYU?-ob#cP8VD5y^ z+R>Ne#>{Qgrx+T;i)1o$3=0KOCxJobgz3L?qYW+iN<_F5U7u>==(xPe0|PO^8bZ7E zZ?Y>lEKEF9(dwf#+te&;h?H;_MLQ6Px>b7CiYq{l`Rjd&3%XJ-fHhIsI94%!WTp*x_wxrtFx}P076K?tYcE-{lvoIvzcfmA z#F|$y8`mb+Q4E2eFca_gcCBB;u?=JN9GuG$-iKEsM6UjJ-!&y zOBgKfiXLdvn9Cd--*pwa5I7>kD)WG8E(iE8ws1ItKt}jEx4m*C?r%dpUYx?kK6Xe- z1Y9UB^fZy8s|wZ4l@}7Wu+4>$(7QQY^WRt`e8=7!-5NWL^|~Imv}Y2DpQ{vaZ#t&e z5;F=I#4V)9Bs@zRF!@S(FDl8 z^e7NS^DX-XDF9{BZ({_}gt$MGaGO|`y|gpUVd8T5xh&doqs$AC_L=ZGfZ#x!sqzi*(W!9b2YLG4{^ z`76yKHb_I%5HIp>=iH?xp17u|V|~)cOj2@#aMwl}ppyN<)4?;A8NOU(16k0Q^2Z<= zY^wdiGhZc0!t}@2jhY9kyAbVBp*^MNy85wvB0;$_9*FFSqB!{elU!`J2|LDSj-LT8 zv`JAem6&;1gw*s~O4O11ixO||=n#|3m=&hAtEIo<-1>McV;g2qzw60a7{0GzLvV7l z2+?sDxG?^UF@cd9^jQpzh8|79v?-;1(|iAU0=CI$d5<^d3JU#y+lT zwhVHrpsM@3jp^LLh4BOH0lZ9TS&Wgb3dYhg`G64LXuNd@Yq$s!yLTqnI7plNP1&s= zaZ!`Ad4GJx*QL8Q zREZlIET78wlFSPpnE9JHhm?xcs_w>mnFNcUM!4vpxS?3r7E=y$2tath4SPejt<~EO z&-N*hKcsy3O{p8c`sRR-Dmh*qvs|2kolJWLRN|dkP-a5f z{BR3X@OLAJg>?H=H-ZIYw47y*zAblC+${j<%UbCn7NG9_OdBLk(G%#MKSZXjB}j5xB)^R;hC`~OlXUBlq~SV~lK~YB zGemUT$|{N0DfA=3&u$t!fzU&1KrO=pI5B&FyNQ;!iK&G^NS5*?vJ2Pz5hYX79^IuF zO>ZKbDMVZRh^>#ks(+~!v0~YQj3HVD+oRX9^_^p{0I+C#P~lJh=j=0YBg6tGoIpHF zjKcdu#GM-SdW;fHbR6Lx$o9Psc{ToG#(j`APecKit`edz7ts(#m8IPuPiq!ZU&v7( zOpABkXPg`wp!~&uLrC@$-~yC^t~Mg5U;!fl`EhJunpy(1L32_5D20?#@Nt)r4=J8N zmRG9yXQYgX3Y{@zKdfyHR83Cgo%Rch1~u%4Sw8Gd^`r`wTI_K`yl3Tg-@QYtvAFp-o^+sFziUxWC zBY_uXKBpmwy*f)-0!cwjfQM93D~pOe4De{4jRkz zn?#t$rU-8Miq2yt7~|HrWYABDIwiIu0TUy3Z+5opriT{eCGN>4Zedbpt3Izf0hF}8X2ATj&=|A8 z3F4|D08lsd!=kkBkS9+OK%r1|z#xoG_IWOC2SJG$qy)8_-8>Hv_!O=kA-K^7sRzwr z2JU!%RT}5vP)EHz2rjJqg`qNBfSX|%jnY;o=&=Z7o zVlJ$7$PAaB8LTsIf(aQ%Qu7}2#92OrHXHg{HiKy&(34O;H^&g`kCJsaNFKIB9s6X> zo;V~BN9iV{KPV<(=tm0NC{Q7rhdX&Xq2ir*laHq4297{m3nfpSd2Z@T9K>lK=c`Fu z&9)FfAPM=5fr3HwOCF~+d*~w);YkkZEdaZ8s9%!s^Pel5jm6ZV^-YZI z#8ve1n_)ikqbbkIR`kz~Y_nXQ*+JgD>!+}mX4zm{Fbe;MQ_&Bvx=9&lVEB&aOt~D` zOdN{i@FhE%S&44`J3pJ5>c~wIRkI1z@S@cai(MXAoWY;c$5rE17pS^ZmZ%k_7jr|{L{(o9*V`c0j${l+4 z&X1XqQ?S1J$PF(>rXw97<36Dzt+`Bd)D$p9U)>ZcDc=CR6*R|Ou?;RCFAKBJCQa22 zZp+qe9#sqVy%yr=B(k|wELbdqb`qfLNq1o5`~tmIE>x5 zGXtEO5OTFiUB+mv`of0FOd}l%2`mL^u4-z&av!SNX{U{stR>O^3sYA=K5pE&q#|C% zGpT&V{R?uw?VR&OY*bdtk;ujwIY1lw@%oj!PM-^r%S%!bp>Y0T8(CKmOm&;^_rPx< z0CoCE0FJshgQg8?$yc;`z?2CjCiY!QX&l)i#0S{`Brx>OElWD-qFODtTm{9wj#M)e z&cEO|N1w6F`r3l+lc*(%s5NL`(XT9NfRD zC%6e&zgV)AB6^@aDef}!#kDY+6q*COJm~ciC)dWmKjACGu+&s29!Q41Ho@aZjeJ$3 zAW<{9{qC-8q8&?8%dY_<*$sI;y8U!{1J?Ij< zRGDcLDTqckDwjBH1_Q#~WBPy0P33p~yhnw2HTo+LT`tNt6x&x-+*Pu0eoK6h#+TF_ zA11j?s*frs&bZVx9gcF#WH#LmRi7=XpwQn2kdMh)r*8~X)RzI;kyF}fs~vbZ*L7qo z6?}o_r1A9$K3{?_xrYqld&s6({s9}tpJ_>Z6auqGZ@K0WIZQ2YMHsiVc&|oZQtvbs z8yK@~3cG0}d}A4Sxvnj5q^ptG92RjDI+U!at7{i<9$w)bJF43NMl*{MI+TGya3qY_ z370@mUF{>$6L@nEV#=|`f@chjtRDI-Qh}kh^scdr_4CY6we4}OlG5-gU(M|Xj(l5B z!iYZOz3*s5=bZOUc6U)OlipxIu|mn_h&J5dvzzH^YUZxBAy?%v**10$|;2-O1< zn6kONLiDwazYvL`z`uVrNq=npVoU!;TJGER%|2709g;J<=pLlb^_TNeJN+Sh2|kX*+62DPM6hso!%1Ikd-Ojo zS=G|)Hq+m3vCqtw6)AKRQ~KIDO~PAp7mH-MsO%LIE7HzetJA=krdfUMO7*GggLs$h zRukGkv>Tek5uR^X8J4q~((Txf6v@fmNJFaioMw;$N?l(tZs!ztg^S3)l6V->F>v{b zD5xT--+33tyWf9gT|S0py7>JQ)0c(*XAG2HQBs3saYbaOO)bAdf+;enO)=01K}^RX z=k(uf6&{@RMlUFmrs8)rH z)^Q-@*dV(8PIzKE%xj0J4}F+LGd_w0f4wH<{H(4b1N^zCB_HET+#r7I>ij-Pk*&y~ z)-Br0fzpCy%Qu^rE%9&(-~{_$WW5DboZ+@^n*@S8!L@PM;1(JU?(Q0BoZyz=?(PJ4 zx8T~1Cj@tQcWrL(wNBkS``#*k0aU%rZ_e?IXOgp(DN)?MK$lYgH%tgogqSd|Kt%kf z{_*5{gZnz=mDUWEKxyhWFJmARZQj#vifWA;q`mcnJcWJlbQp8pNgph?Qukpp(5%R^ zR>n5g4xkq@V*p4g3XJ!Lq*g@Ae%oHzLIilCt5>v#`WM($UaIjt z#5i3UG>?|Z73GdMElg|8>T)$-VB*D?x~3ocOu=j}oVv9Jj;h<)bb}Z@ioRa3S+W+0 z-bNb4Y2y_DLp}Zu|BAxmaTzX$c^$C7rCkSycovejD~@7Rj0$Q)e9Jp=bC|zvbHSW) zbvtVaRi0%S@)RuKNEzn(n|h|5nhFVTQFCJ^6Z1=Hz-y@5`)h3z7K{%(b(w{o(nFN~&bYTHV-( z+pjSNx=i+U_|1tW3JX zZlsE7u9f4iD3Kp{p&wHmKcF*GBbC`mn(>iVcFJ5ykT8iWSHm?@`P1cC%gy`@^r~y& zZ}6aj&~`g|`QlAVb$CM+-&UeCrDhgF`GWYHhpB3A{YQsR4ZG#m=~Dd!D#_|yx}BLn zrOkEh_L7^U(p8>61P0UfAF;OW7o}@tC>kb+hu>{$AbBn+Omg6>>1jSx-o`uA9e)5T zB)h5YihD4u(e^CHwX%&MX6MV6xz6icc5M8uiW` z%Z?{3&EA3wV&L7Hq>-S7&I+=C#4(~Q-t2al%;sC$XTyiR9`5k-%&)DSi7`Vv2nwk^s>s(cYzd2=Gu;zZCAF$hh;Ory3w z6uf);VV=UE&+cwFVD`*bvn$kw@D+m#lg2&6RSlVSd5@%?rJfa&S2kA?+&p|5{C{6g zR^E5I_JLLo&&Bvo^|pDS%-Tk0qMf*|6ExK?^OG0n>Gtu3NWlkbU!A1F!weTZZQ&&% zX?TqM<4_SXDF%-<0*1OBB>fd;2R_~hU-AXM zC|4GUHaV_xHpkfz7>kYm>cQ-bMEbmUvAs~>%Fj!zW-xp%fJfwbKxOZWf%r(_az#OR zgm+_JR*OhdSu$yAnRY?yV|4*8fKwmlxP&=QvMIPNv}%#X*#3uoQSeb?tMvZ|W5;6l zE!G&oSO1MmHy)Y)EQhB17>wu+!IIK1;CThtDe1Y)yYL5-Q2z9fsE2usWxs!1%hgaS zQPj05b-ME=H@_16IvEsDzS(Y|ALYAgjI0hVeFj8Nxc2yRG?U(y5Vupc5XBdZ&fJ5%X2M3;_|eP0B5&^#JD-kxVXbkj$kcx*9COqE zcLAQ*g@GwbLQ-Xe=KtOa34iS;dm?zYNj_2V-;aFJVbBArGcmHic9 zrprBjpFj17RNefa1KE{hH|3$vZ;b=lA`(+THoF3!}z=Q+k?5hu3y&S& zC$bctOx@|WsIT)(%(ive)FLOTAaCHra`*5Odfs;0R10N5M!W@WQ)4`ey$+2tLM5GShSe{^6Y( zKML=Lj9B$BiQ}oH+qJ6i%?KW;5NBlL3*Slzh%LKaI8uThvHr0TRY%|V-IVZp_zLZi ztTx^R@CULu?W_ZE)Ft=DyAY^?WL5rDh`IHto$;v!Af8~vDmw*Iku*Dt&yV^rt55;k=J5@1~&TkOlg>CNBJlx@4n^JdF~}QA>H0kZo;e z!_uOuKNKp?Tjb2A3BKpKN2#jv0gX(kXSiEJf`2kyc;qoQ zk9=sqY4dJ1P1VTfQ^4yp`O5{E%n9i+nbx9RSf!WHjC56^M@~3m@~hWOn!jT4Wcg92 zA@@EoK3n};vE8@`AdTU9T1M|;*az{Vd$b^~zQmJ$%_{(t+`ki_2pGFay-z}7QE^~h z^JA+RMp&wT`+s)(}saik=UaW9=&`=9^B1-tOjmuY;fd$YYdP zM2wB&oAHg_A(Y9@zwk0{cDbh<`h1SXsP9yi_PqX*3*QE2XBiATXKLsNRp9|OTUt*| zR@}I{m*Pz;CC{d*grC)z*VZ49GkN_YUh^w5geDVC|iZDXstIvC{ugL`!_egZp99&Vf)dR;ZY0WLyT^E_&GI zm2n%}YHO^sUVl5`KcGukrBLycv9H83qZrap22Az~A6j#CwX3m&=AuN98XWX?PV{qg z_RyK~lk?33q4`RPy0rnni`^$7u_GyoZK9XgypD^3Qd?7VrIJwzdav0V`^EXH$&HVW8^1lyqx4l@l2;V1`^-sYs@nq zNmT0^NWDTx>g}Yk*Zi#s5W?WnH-1^0;K;<@Zf8?CK)cBA z-^!3eFg2)nY7^V(HHU#SF7}(}AykUAqKu6d(R)j&N*(+BqxDy7E-!nnWI7#}>dkxP z{QN)IGtTL0-@>ObG4p+%1$=dGh;jqGn6I=(gAiTFuV8o(1pna51mU%pbC=W%rruq; z?0c~1n#@Wyz+UA!ga5xzuG>l**Wy76>C$!S)@`F>F{|p3xFCK)Go(q1)E;xl)G2|p zcW+1m7X225>n7KmsNYupks}U?e|r!mdz`-EIr^3(}8q5q5TjLkR0VJ5+ zU_86AS=i4alX4^C1nTbOakZLa$|v$5VC#qMcpP) zr)%H^j@B!mbk;j_pyH2;X?;8A(|fMf!!CG+g<;zqcA7TcwO~rRjEgXJN9-WerHdJ= znzMZOmATD9NvbL)1M;dgNP)YuxD<37-Sbb>4*EWIkMr0J8{n-_@~&u41#eG}IyP7l z6)3(9Vl}(Qrjb+?V>TH})jC^F3VrwwO0h!oUu=^(c;NmcW30FELlRxKpjha}j%0Y1 zRCpEHa3Z2@eg&RuvEHnAG|2#^&CZJC_PO560m1CSVH_>!b>Uu$!X*`%bEaU4eh>Bi zu;`@2=x=13Nn)0OGBlYU;z1n~9HTqeYYJRLp#{f~l{!b@T!YyQwE6Vms)~dSO3lz4 z(4_Dnl8)xo{R2@H`mFzS8-wtt^Oh=ARHwW`THO*=RVsRhy4nOTH=vxzN0h9$_W)j4 zoMJQ3QSIb&Yy>hpc(=#=gFl)Nozv4a;o9m0ql>mLQu({2(IHQLzQikcDz+YyC|99! z86mZhDts;-$kIzm88;~ANbiyUQs!C4q^Fe_dGT1at^%ntud*-K&ySE4&1v$TTSors zg8MYwThWWYZQvVQR&Sf*2kmFyG8_J%GI^iW)LJy{CB6IHi*}~{y~rY0 zoCa!)=b)^cOmVixE?xGO%sEal_frrEYgzPpp>sf#2K zv&3ZZdU=6Hu}jw-K?N-YkK)-R)z;`}{?xeee$(?OvXh_N0E;mL{l=WLyH2Fv7J{z| z!(QR!0>oY=y0A7n3ev*74G(XBH9RqBiF6_?j*Y@V+5Dbh*&|6H%&v|H`-H=5RI`*@ z4SpFbWZ&&n0;mQLx;9ab>4xM9tB0JC?K>5(qo%FP7_0dY2dl20XrGIYelm#;&)x2( zWV>xwU3Y#T_geMg@DY??q!ZL63>f9dJY{$U?Efg);W0_*B0|3L;;Kb`Y(D9`^}Nm@ zdw9_idy@H({V$I5=&<-T8C?SF)ems}HCXa?J)moO!8h))C=uit$=Uir7Q^>oh3aH8Ea*{?Cj% zM!Wo&MmF6T(I8M#kw~IKDGSduOYINj!Bz^W#FM(x^M2XgxR=n}#NaB5a5I1+c|JG9 zm2uajg;KmlEA`T%>cSJ~6!FThU850;g1!C&(SN14+2qU67Qf|p)oxLbcL6>gd|)Q) zXZ&4bDLVY`0MR@stDTIr5iRLQlFJuI{krEb6g3!+9HUV4(X<=xSNSQf$q!79l8$12 zBA5BWD( zN`|Chem^WEPsX%77b34?)0eL`ax2e-Z|2*${EsQ9Bx4wxYclc)&B>g@I!U$<@Z151 z%n^p+vdX|z@SSMgMGen*t?1L}MSNlsf z#}WI#VwC%6V@sAhJ;I;4C!3oc8Gdx--EJ=uENzUl?+H$RPm(TnSeB* zFKB&{z2Q)!1j5o^m1G{l$T^I&ou}B-l1yj6n3s$MO%mJGkt;Lycui=}Cme%VYRiMS z-ZvRX9n=rMK=C0g{!y=g2h%AlDwJdwGY{mzHRLy;;g#Rkbr&typk-#`3;}~Jant%n zu9Tqp^psT~6F44pp3T+Fy=~_{u8(=?6;64Ld8<%9Z15l9i6NWRi|KA*IK>OUNb#uK z|2S4iidF`Zmi7wuo)A@WeX4UVspbQdxo->?i~lU(vYo`%+*JvNpFvfe zq{Ptb{#=SskH4f4T;KNAK$>A96nmUDRezt;;IFa6O>a&FwhB1fkbU>-XCyBXR$kG) zB|<&dai(3J9w~A*WU~X{_y7VQHoKOyX>U`=f4@Qn0 zaNnavE1O)?6Vz`d$XV=-@HX?*vFe9;@cD;|#%|ui^tMF@So_Dj&v*(7chnr5qnuqw zp*`_mw%?1@#6A3Jctq0@ZF+y$jyLLne5a&Y;O-H-VB%nL3P!8}c+BeS+-~33)nDNn z98-j?gO6c$xQDLD@44B8B}T~+zdzD_1Lx}}NCErXR^F3}at2%Ho&%+8>^kIp1O*x6 z;!71}H#!?cT;Os_cuAZMadz{SEop zUq43At~{xvlxuXgP|_;5+}NA0%$OX)X~G8Q5cw`6&jUWkUWvEZX{%phgWd7GO|_9k zNs@RO7E$_Q2D!+jVmyJZkL${lyT^y-i$|JFy&>bj0xY{%q@{>Q1$tVF-8|2Vl}=ty zxDaGsBayCD3D{3}Frrlh7I{5_U8mEUOyfCu`=|A&TK3vUUK`-Zw_*3n_ z*cu7II6-XoU>_qsw@(!A)G<&+*YWs5RY{NwxvM}ezHZ3*ubNk+VP6DsQ2-{T%6;u* z+*Sfb8i1!2!-cMF)G)~aJtj%-&nT#Y$AcQjj`c=@EZ4sVP5Wv0MU}#QZ~JLlyv%^+Vr~Mo0mp_7G+h&2a3}!ZAr~>VN zrJ82($Vbx3d^qQup6t@h4CBBs^7S82d+eHL-XC73$ZMF*n>r$wzd~DwXe@WqamUj( ziV)vN2=ypqyQ{4Vd_Iv--?tII@MJWXp2SXN{cDN3r6i?C$Lx}Q*J3XvcQ=Wp`^+f~ zrnPF<;;4BDXmekUGlu>q5_o*;U4Q!*gIkKoah4Mtcdh6I?S&of*T7!S{Ej_W_we&r z5gqT$C%|qGl~E3zjqYL%SE4GIn}V-%({iegbB61-iaJALXsE76|;G1mvB{emez8FzwJ%%UOCzxhvi zqrZ%+688^yH~-xE?Hm8#dREMgjYvZ(3K6VJpr3A%{*rW*@pjphxhIa8?|)s=+o%_? zrQjv8xd3L?5PK}5GkI`{;lP1rXGwR**9P}C`WZ14m`=B*b1~7(E_X5`;pSFYS7_abWz}yAmgWq)x$UPGo>uz#RQ)lY9SXL6q$MFs1yM33 zhH-aU;=(fS9}Yx7&6eK>Wi~I}gHMQepTEr*6g%(Gjnfv&c}1@OVseq1FZW(G=+qes zdH)aJ;RF+R;y=h?>&O54I?1?`n){G+nS*;z=|FJx7S-`4z&W|0BD;Z3WX3y1h|`?O zF5I#6R;3aA!!pbZ-M7Kt-MtcLZTx~Yahhj7i2Gw~8~hNA*!^z3OElW6^T-eh74Xr| zpYJ6Ji13l~1li1QvDE2PXG|a-=yDy?qmrAxSZ}=TCwoyfg+pz0AE%$F)F`~bq{W{x z-fdf9xbW>4+O%jzGLVjdYdLUhP7#GCnJojD->b)JOx{gotylN-6p&x zo=r6Z@cD{+c8W)<^YQIEJqur;yqD=&$omEyMcr&<8qt=ZSp^R{c! zG@m|KT(c&*wgM}5QdhKtmGACNf!NdzN83_w`6Ob`kAe%XZ!lintm2Y3oB1z-Z z^I$0Oq8%Ohj~#FP{bwGEz-klp>6!M-9Ecv%YzN8Z;J=iG=JUh~HFVjKJY~qQ9~EU} zrEensfxlyY=pH7|k;~yV^d&0^k(rEr7WW$2Yc|8gn4~kSKOA~xVLLi%!+$puhY@+D zE$oVos2M~2E~9sqc($lpiWG*bv$<+Kl@Q8duw?w5*$Ywx&t$!!gP63zAcwuIZqbse ztU~#ZPr#|M1!B_6!e3B+(lMKPgGG1E7PC{eLDh=*p*y`DHg*_$?!m=IL;!q{UqOBx z_r!he8stCa*}EO!VVjM~j)Q8zyQx5U0Dq-9urC;h5Trja)CdRTVG;mnYd?K`Y>@Iy ztEfuJPP85Vyx5(7C3!U|IpY!e9nZ{_+Q_pVyUWFjVcSCu$!sYa@)RXH_h(gh=l#4j)VOjD=W@} zUQVo{9agkpjm<&jY?#m?Jc_=(9=^ zfnzR0>ycH#lyO-NSJW1O13^@;}ZHl2X6D-#sv7!mwR;*M)d%7#nU>IL-wlHZuI*OgX&Ywrf=Ab ztY7AEhH0+-)#h+@Tffa06uj$xS_)B*4yyGYcCv@a`&_gJf(H2Q&y&IkX&lni?3cUy zD=5;OV%;DNWtuyliH39PBO;H6XuDx{5mj4y+e%;lmv;b*%34!;vYICx4;uD3g7qGk z&WhT45yKG4e#k4y;`Gx8{^*7JJ1Iz1BX_)^WQ>IPCn(iNt!g9(z@K% zFIKusObT;)xNeOx)=~(Q%M_(mNOO=*K01(N@Z+O}zqjNIE`Y(@bdsW6Dc9j21JKLy z`#Mtp&RuWJsq-;3gKRTB8~7xZ!%BqDW)WTvCr%kE#bR7xS);}nZP|q{Smax3Qw-$ZJC3ltp=R3* zvt(JkFz^b&=_(qPc30-I6qXd&6|);U4p@yXxl3yEbc;5B;5Z`*nG(V{Z;Q7F);(Mt zt^bZcdtv8F(-5CLP-Nz)*eGh?bw+><8_1ay*6ar0{V+B&&+%F&IK$-4mtxiL_5x7> z-LITR59+8!53VFeZ};GD4kA(4#;D@VJINZ67#FL>Eg0mtk9C&!+B$c=2t^Qqs7WiD zUA~HnasFn@ef%N;*oCwkeWCG<_;l(KPOV)iVpE*Y$oJCk<#H-z23%c{TpY+xX%QM_ z-VqqtL`r4*bA2`{Vr#ANg=%O0n#u zt)%xFJ`IwWu8!hsQDR$$^K=A_KKFJ9;TXl*k2AxxKj(L5zCc+|fZ2ze48&Y#3iE(Z zvoYX{ClW)?JHA=Zvk61m!=PpYyP{oVNwHt}n-}cl{>o@h^bu@oPs7 z2yjI_B39Z!+jh0fK0QkbvkkAlS%P#vA;>B9^g8AUsiVk7^{+ zA1h&D9BKfM)x9xn>o6JZz7PF6yqJ#Z*xeQ7pK_hvjxX>VdrDZ&O1N~9`CV4wN5eWEx&-SwvBJPHA?Dhsu7Y~7j8 zcawKsuAe?E)*fFZ8MkbfTQ6PSxT1SLHsgQx@Q;X^H;7iRv202aR=8Y@5U=tEwq%y{ z(Bx(tju$FMXSmn&O~_8!_saJ?!#nKt(cEShbtXmUz}k@g@1pEGjbx1HC^=h+b-fH4 z8#6D%wC^go%h`=d26ijiZk#56nl2_9&B1$Zgm_JQQrtc`7f;2I+YH>^qO8{%k7yA&eB_%BEC!QK^#9RnY3+x6O;w@ItWZErK;2|&X86FW zz^j8R&5e!5jf)uwvz6{eg)Gtmc_$n(#Ak%BsX&EDHH4Dd`4#65KgSzp%zqAd*aVDQ zlqRvwns-~A${QlqUq(eO_*Gz*?%HWwcm5H0vgj7&Tb_~>MD4c+2ETmH3T4)ZiJCbk zadQx^?RJS?KE>$YPoX>YZbjR=qV61=CMZ&1+>a}0W!jG;3g8QNTT9CB6GiMm;6B=} zkU)w}T99LGXpikUZo~aYyujSrz$tbktCpmUIM*9k6$~u3`#=3bD}f2kk(7`AUm#0i zxpqyIAWM=R0E<_?9=6&MLb=pid*R2gkG|S`dZ5c~hTee_WEu`6dK{?f*GM_Pz#zsT3sQd>j)44&>5@jmVgO#djLKy6%ZENh3 zKz2ddl0Fuwx*bC_pcp1D0I0ZU9%N_k-R?m;I|05-vOd}{(28ZTjB}w8jEYxP!SM0N z&h@N#pQ348&^m>A9*o+(f%T!O801U(T4>by+Q)0LWB)}jHygAF^!aY$Y=j6t)VMQf zuobyGft{&9uML{tu*|8=b*{yUy7|B3boT}?@p?MVgaw5ms;K**y*-^^NBb{oiXz5X|7O_XiFetl| zxM;z$a*mf~n)hqSOO|&@1U*XvQY@BwEzrViZJf_6EWOU>s;+fT3CaeEzBKVnpbUh25A|L9_y^W z0c#DHW^?MrS{vI9MsQ19AiP{W3=wR{Gi?=Yz7rIh+8j#bEin1YdE(V9+c*mt(hAZ* z^c(ALzqyPHSPD$M+P*2pPHV8NR%H~7I1Unh*{-g(>&SJcnQcCuX@Af7=o0F{3IkbY z#|1!TuG)_d>~=t#TN_PH7HdpuN=(6r%g2OcohKC{d!|7Pg6Gea8QWv+13)Z#PJbLC zFmQ=Z$o3*>f5~~X!j4%8IWEf_el^)m13Ol2k!^7CDoie3OQ*O3q#pdDNs~56xocTP zvyk~sXiwXSG1sde8AeK(GA++O2^hWGXODw@9+gXG7NWUKy6E*;(eN*H$Aj)(Ef3cG z6E4Y3$WaQ|m(hGUgo(dczM2X{H5gCi=hf!W;kQ{@$qx0~<62qZ8%HS6AC+ovj)kjDH}&{w$WMvJUVx&@eh>W!M`VL#w*>qNlooun^Y zH5{k*a;p(0}4ieNZgYC^(0GrvP3 zSO+h*uGj21ay^ClBwLwD4+=kFSkHqS39)|cc4ZVbzw1cMo4Jw|ehuGVqHFqLrG}<1 z^Z5;~TfpURj#C`+SCB>(3IYP$!y$XS^#1&`kxK~(ciNSYTBH*!*|(he~pmei@3q5b(A&+SAMc_O>W{4Z63A!6Om5cV~KgcLFCRjW4Zv zLXV@Z$gbm1BD#+En{;On6xHCAr&Y?mZ})nGYWuR*(QnZIT%8_DzQo79&Zmwr!ni0R z?n{NqqcGK~Q^cSX-^_XX*(&URVNIOrd@mEDGgw5wWYftCDmt)qZ4=Q=uVBUEXr>&v zeH>y}Hf%H%i*#IjFMC+ymbv8|d+CTak6o0YiJtv}`>KVIOjouxiI>zjdUm+ zB~lvg1K0kk-~aOo;qg65pB+0)f+qA?3u_+}ER5uobjj72101}u`)%_-7grXv|8sEN z-|}?e+*^z*ct^l|?R7zs@`VL>GPN9^?0N^SsI+HaJbH z))pwns!4JgSPN3d$h5F$o_5jKNJ+IT&q`j89eiOc`ZQzqSSZC0)vTrRmeK(TSb`=l zH{d6Y?>63`Psny3EoGS*q|{79mZSv|UXxJt7V@@tQ#VKQTDKlXOdsflNv#d+8-;kc z`pSGrU3j;CfIhtGvg7?cPB_`o0alIh=EuSkQM>?G8#qgYxZ=1^rt{Fs3;3c6ccdgy z09!s2FfX7v#vWEJ%4{tcDSDDcFKOT5+}NJ4t2ri})I1aZmYu6YGptP@eK`usif{du zXpS^OYhA|+;K^&)(f(JGBKtk{Us#M2o6YdjuR_A_sD}Xkh*A9FCdOMqA9r}n7bj}2 zU4!`*44NJL0ujLkwFRJ8Mg0ymW|$XZC)Vd>$*j`@j=}}U^=}u)d}v_3f}bOx*yneH zjOz!{bl6=g2wWWr1fbh7>&5%@9B2kZZ9~3Hv`Qf%LocH-i zEhoJ7!n7R8`FYoTfLX@nMP6*cD@p~!K0@c!RL%hfN}26QzHy5|%Bg-3LoF1oeJm=0 zDJ9h_D_%z>u87twjqWMhxuxhsrSZvNifFkV-iPs!%U%Y9m-Ccsk-~@9%3G(s`W}rB zT*GSDnG)YNUy}3OCm8G`0;>}_b%WMl>v3;S(=Nu=o2fuU-bMJlX7ycB(3PLT*$%@p z)K^+H;59$(Ly5(sS=6aP%I)b8f9-dcnldVNououc5jFzPNq43S#d4M`+k#&;b6Ti! z)_3tVwj2Xii3u|e0I^6MTM^ld1T#Z)b=N2S(5FoN%%`LK#dZU*@_nA zNTyF6Jtq=9u*M2{KbJG7A9uvye^cuCrSWUanw_-lj8=JcgZqxsq<$&A?L|ji+_h+L zFD9tc!v1>+7hP(aM}brF#++iszdSt$;|PpSq@}yD4sWH&cetR0By!eItTF95Hs{i@ z)o3JRqT2e{h_BKqRah_j?uG@mV+l$fG`rfAZsk}hE=CSS(APP(=80MjD>=>DIClzD za^E&nvDCFGo?fHDw%U9Q;GQ~xR264hPEO>Eax1cK4?-=}k9pEKh0|i$u$(Jzu$;T_ z;qMgf+h|z;qTBj7)ZSJ^*21@hh1E3I!`#9E$xT;O$|_AyT{!n$=rCPf%@fiU#a?Hu zpalnCBH2tD=ttE@U}oiQ3a`=>`w&dJANp_KMr@H-SJOhCG^WyiG4J`6t=XMUE`-bc zvt|o@32RzS#c=nlNHng14@_U}G_ZaBtNWCnl(`rs`8YJ2jFpCae`JGDjfiEL$eKSZ zLE5Xqh4~Vq&g%JKZ4WVGf__8W4}^UCA}cj)EzaZrJjxsWci5KM^GT+n?3r;}z2|7- zxBi&>wDz1Zz*9;~x1-DlFdy^b>91Dg?qHS86n1R5WjYRg}=Mx)qude20*IJKUlh!bGsKC>T z`M)sN@+zKX7*;bC9zV&AliaGJOJZyOp9%f~^L8VrqO2|T^4C;n*NA7vgwoN{|NW5L zG|YWyOl%HXN74o9J7`SmBsPc4SyYSh|E%>f^gKOZPOz+%3|(27Dn0q=b}}#h-6OJxtlnx{ym_KNyOqHr2tsAeh@#qLKQFMeZX8P^Q*6t=&o`P;JJNv1a2wG& zPwDrSOwDC}Gh}_fz{7;p<*rntST3b*WyM(EAB(5~y`k%U#z(^$8AygeeDlw**-%@g zo`B|$8IwG+4I_7%4HIW{cgH_85{h>t{n2Ih>8v;0DXCk@#>iK~&*G*`gf|8xRl+}& z>!E&`#CaX-Y57Z+lH3Ce-Rmc4d`oPG2@b61jI=GPsXh+9`9Dc8{i72(=n#z!=($Bc zalt4q#3zzx{-m3D5Z{J19ns>(ORbtSwLE?dEaH)9F;pt7p3dfy5r96fiB{E$!lqZp zK>I_%BbB~mmpxErLj)H2FKwph5~i&}666;)YcHbTe8$03iiGs%SXI{)J(H}H78eCp{)$mt2a!{d@=+8PAo zP)K*80IahMmm-=zj8eh-IS@6V@KS+vv2jr4V0p4yB$Dz6rSbAoF}{u6d3|TUKb0r! zvw_>VY|&35WsYKzFDVptVy9LFF0t-~vE?_0w&Z>=o)`B3{3$jA)?YjkKrlqxv8iUk z(n(58M`z$DTX;CUKF(v}Bci1lU`;D`Y>>K5bLGf;Y7AI;82wTXt}Ak63Sg&WUyt z#}OKQa|4_dV5=7X0OlGU>C}KHf5lUrE17=FxKsMX#ya5eG!A}AIL)v;KIR;~&BMH7 z^5aIaeBMW)30FALe^5b>%_US>PJOnFI?j)3c=+3Xi*}V(EiR{ozI*;7!u9j!@LXQrhDe*^HQ;zF+2TocWGg~OYyyK2lb_T&d_6L1=+PRU9j)@ z`Tf@8I%jP*tt2bBB*w-Xps;I-t1D5Y$D2~mygVk~O~*xn>pI4$O}1OGTEzNF8j}S8 zp}QC{m9=YeiX|NmeD>k7C7vuBHC_A*fbb)$%qwG}n+(D2%DSpZ?}Z9`0`3xCl-x$= zuBsy~Qh2B$V2)6GUVnnN77?fgx>7FbFLXko_m7H5y+gj`Adv!hpsX`Qf@n3`Cqe3F zz285p?GAD-A!IHwiML+PbbIsv`U>vsRSc zfubddE2*5VPSEWi7HAc?&1&wa+&#ao`G zQbNk{1$^H*M;NtOYX67~ToOD0b(j7Lm==xUDiLIwdCbl5YQSSYwJIH-RB8dqbYk^{ z+{Uv;tHX>2yKTUVUHk23`z8-E=tZe}G{z&PwYgj;L~B$Vq3dDDF~kYym!uu_@7YE_ zxSq-Z*IM_DObzhkha(mhK(d9;amy)v!hNqG%|fx+^o4z5e50@OC*W5m<&XzFzZ10> z(h3~+&s^k0n3FC=Yz3Wm^fca?@ju%wo3@u1UJvIZ7dXRPzIqaE?AJtZjg&?u9InWU z@u=|vI%&FtAyx{gx(1XfnYXrCt26zq*@a{_EjU%a7i4>zJk3&e@t1f-*avw3uy$NF+8E`1HNn&BiN{+7$zzIH0k#YI@yU= z_%T~2x+D)Vj0<)vNrXD1`#e@hd|GlXT-q8LGVTd0G^4P-*ElDgBVwio>rEq%0@ zI2^{oZQ1GZ*T%19WunoYyP$;jro`*7HIN{*@m1g+_dFfoi6#_{BP~s~3U9NUB6VY@ zUG+(~CH1b4eP7kJTF7-IBrMOYd!G|(q4;a6xB*(e|ND=t;?h^1#w-_wjeaiz|EtfZ z$=Y&0^>GW)?Flp;aI#VkMu?VNOqMZ`et@WAxm;*M7+s0Rj5MYFfW;}{c7ijb;Mf2b z>=&k+H8Vi)!JK8J^ntb+LH8J|L5m4gEC&7=-|X+}{SAxxe4n_0$;Ofo9&o+8i5jE> zV>c$p71c3Ao2K)oOEP+hc0H{p*qZU&f7BmXvxHBu-FaUwsPE3myMNd?|KUoqwX+%N zE8ytf*bwr#OodrLxY(+C&uW|VG}M@Kkiz}PQUnd2bC__s>6(RfJc?#d%7yJ3=8h_n zE9Tv89_5Ky{@*A^5>gT`HGeIn?Hko#=ibM+)p70MPdP3kp&XeJCh0l(8KPS0{6t-m zd?igh7sHEKe{rO67(WEn!YU3+oB3M(a+uC1lA3{XN1y&>qT1l@ z-8D76v}RVtT!p2qQIK;^3Sk)Ld9xyvyl`X1R4Vp6#ln^b!thifYQ28ie&U?4O)=Fd{xV`ir{lr-f&ETYgLE6^&eHmM0NX($2w41 z+AUY6gzhT1s2oLEmJ^`w&x1ZrhNyVo!_ibt(me0o?*RI=`sZHaleaCLP9Pxye~kvc zTI;qk`qr9^9De|w8p>}0CB*e*%9L68Gv)#M=O>#tP=)0Rp?eg_LmiynXJ zmWcw$WQ~BYMIXGr5~5>b#wt?HogN1v8(#H1mc%Nc+*s~EOv za0PH7WIn_}%%<;S^9O0eC+|r9if;}<(CvUswin@Ke(Aw`{-XpD#!f0FaH(?VlfZL;ArzZy;Q0hA3eUO8ETv;%CwGp~$cbB0jS5LyV(w zs8=&XXMl((v`N{Xgl#t2Wv+3VL~?%bAH?_$;M$q!Y7f&sx7e=*^HYh>VZ*S+FHEkW z1T6;mPAvOd*q5;r?nxUaT_#ctoLVT8K*3aRi&Hc(fyPdIQuDB0K15H` za*PKESt`y}PH5&Sv*)k2$ldYg7GTtT0nTBV?7reP)$TOy6klG1ROo49mdm2e{qnR`97;#N}#(b4C>pD+U`0kz!QjD0N=ijTk@R+{0eQTugxxG!#w*F`>XQ*H+{xZ z0l$^aC(BjK@)Ub3QX^I)QztD%(kkpLiZ)*hHOf`*!&)?K-~QX8ahn^7#aSDIydpkR z#_EP%wYG#y4yx$fTkKTD8{+#>j)*n5tBy!LC_gKHLe2#tU8Ld#a>yXntR39BI8^Eu zL*}zbsvN_sVl>c)56B9^=p#$+ja1$h=kV&U-?LyRXI7D;u|Ids33rvPM!k@!SJz0hz@i{R(kUPfi?b*R>xhiKc#sey+KP>J*WzOqqjhu#YYwoNR-g`joRzvw(B4KCcTpm&jMCDS&_N$Tk>2 z*+AdXTzbtUvZK)7cJDJM?^&!7Q&;t)mG2CO;lT;@AAnCzok3vlIt$ALs*h^Lk@B*r z*7VPAREujrZ(b(<=l~r)0~WPHuYMQCyUNiQQ>j!O2a5V$?oy@->tP5Ka#7c2y@sqL zqcrl~<`zPhT(KK?8Lr_d0tDfo{hDP9x^TV;0m5;LiEHar6Hpq^8#U-l#$M!)KIvwr zcA)Dv>1wSBYRpm$ryo!a)>CcJIr%Nb<-PvS^#1ghK+Q(M2Wj!h4!G%ux6s8WIoB`o zpt*ar@$FqLv>i^si&nPrFMX^7t$HHXnlAyDYKtH~khkj(rHdqQQ1I5hyreRKS_lmo z>z>S-m6W4@xSrFr?%wUFMx$hAN~Zc11|rXU-w_bCQd+{^6XRG-<<21WEmuI%%-y(n z^aI`Huuz^#jb0Iot~^CK|5&vYv_g=SpGp#S`I*pK9N4+xdKqvMet#(C1aQN3ikWO%v~0**|+Z0Ex z52iAm&l0oEj|#+!)t1ot_REj?k)OMEWk;)}y?+k!J(n4Dyywr$#?GR#hTvT!omQ3 z&u7jv1IHrWnk#;?oR2DfuS1)kQhR`yPmnO z`}yO&pY?u#bIrNVHOGGJwQWCv&F&YW(bkZb7x0mmX*A#~ND{+2ELOeWo_I1N@?3_e z){~v7^9_T!ahK?!#1}0yRnvikKf5av+QAgW3-9$;3)P}rE4jXUMWURAp&trS=X-j2 z*o5;I{l)bT&$KdYIGH6}yuMvzAezIg2-9&8FI;#FeeT7H|BDCCmuFLBjgD{lVdva_ zX!W5^DlXO+5@rJMnB5Q5@8omapdyBmamIMPvOZqE9JkR&^&YUTINg)v^eesIONc#B zXn}&3vyMH(2(JVyA_dLbi!h>=L(U)qa?0@`Oz-T?qF_uz&JqEgh~WkDK6bm-h--H0 zz^%AKJWtO3qB<(N;dpJT7ftu((<^X~n519nS(Q0XlJ7?9sP5p#QH)(MTae?adW}Ap z-_0GL!Oj(H?(7f19EQmC1@eO4sKH0yJ-wQsSs;6P@qd z)HgUDo+VsBUg7CT`wvv*`H9@H`Nz$Fwg-(i%WIjjUldd(qPnO0|GRri%1BF7HD6(3 z*~&*`^0xBZrnsXIhJgUMhlc!nh_Bwr(?9+j)$8`=;S&yMit)4m0DZNWKif;$jQXcM z(P(o*vD<%zr3r<4B{DHWPOfCL)~ugP;R)`+{%w1>;9l~SLT^qZvxSu&Np(Tm1*e;U zi0^>DOsVu7uO*H1%g}vl(JJ2mf#6h&dP`kuYW)TE%i1m!u3MaY zW=E`yy=D3z=FM9*OLGmkOO6L}TPVxP;N?XAl9Dd-(-OY$Ek1c-&xJ{(RvI4Ox4TdA zxOwXU{-rG)6!7`Ull6IfHcFbJl(A_Mb^C3g|AhEzILS^`q~Udz*zb>VcBiO8c207s zKCPcr(8KwBwipxez;YUBAUb---0s#3-BpT>7TsZj7q-fNACIWrOE>ip}|X6f0d%`qU8s zR>@h}(`Zl%ltMYe=e=L_*ivNpmPDtQDEj+3Y}6poIEE!Yr8X+^?u)^NAZqwFFnS;v zLg!YTrD=|}5dB_%=5@dqRd8y|p;hl>!sdJjGPhJu<4jdf%itMC$2ED>&kJ;vZ5ukR zMR0z2SGj;jencKR;2l7Hru}(V5{TeAKWZiF<<(<#?3orFk3$@tj(HnB?W^ld!|@=L zop1@eaqtq+^$lJD)!p4%v+*dR;BRn+T=p^{w(ZT=umsj!nKVbEz#qlDX0Fb@mQ3cA z-NsK16c6`T(43?J!Y=$LzXyPRbc{~9nF>u%G{LFR(_iQP`+QaVsy!UY6uOb;y;!;s zKZN+o;Zq?#$^zh015<2)aX#AEzCid7OoMjL99u8=Ui*>=oL^fR5KVDt|I1On`ozIc zg+1PdWyhoB8}ZX%B5M6FpQEJbLDe@b&)6tWEX2qU&fkCK-`R;>!be-h2b|#8$im;( z@;ru}e)xg!xehhy52v7p0vHmqXv?Y%Vk&oD>BrFI7hiL+HT|OxI?yzHSt=>i86{S% zEe%a~V=;5FFhWD3bPV>QGK*@BKSFDEG@LU9cz>asHNJGb-tBG9$$ArOj0q@tR)j~- zBv6Ha67Ea#Q>^Awqj`Z!I`Ha|d|${h9O)JRNO(k86sm$t_Y`m;mqe9TXmW;Bt-Ohb~(_)RCm3CRU9F9#A zdNMsGE}eL`vfH)|S&AHPH68s5Pj@ggn8CkKZ;H~5c!Q#V9B2&;lx+I&)(})ZmJmuw zQBElWyk9sv+235<3CGCm_m#bN-qQQ~F0kDEd)xJ02B}-P@x0~Fr*>ui^GlS$tFbzN zrSR!$Kmous`pfu_Kd)+mT^4Nq)h~=Ql3e^@1gpR4E|0mkgoRXl7>S=GS>e5SUMRn! zb1A!reY*bn(LIV_A76YVBw@{olkecLdo0s7z~$9JbZ3lvvBsi&8LL0S&>biGU_FvO zT7PDC35(C`Q-~KSTs5$mIBbR9f%T*Zzz1^GG&LCgmq2-z=g<{cq|F1xP6n*&U&ioQ z6maW{4JCFv?G7Wz^CxGu8kpiMq??|(^usQ$y1E}x9?5;^=K0D&<-`<>Wy?4a9@`PF z0&>BcZ)lGdjfy zK5KrUW{v(1+_#N3_rZ9&IpW)8Ibrs514Y*y?}|6lMx5BDOK{l!Joyx37h%7t^Z#}- zrZ9DUpC_sI8SpegHf_B(cisf4&2a5gV`>ntodFyYeNk+4N?hC%z$k$V+J6{ZPrf#8 zdZhPwe;(4smyE)q%1Ekf;7jOyiOs^HpggspaIe|@Hy_UNV>g~5d~)U3MtP>^0wdLk z+X?o&`jLUOwey}gqLOa_U1&M>8rw=1;6SsARfb25MX$$DrR&YJ_4^VK4}L07Kx6B_ zpNsTLH?cghk5WKm`jZZyBI*XP1eHvZgJs4*%^gEu7C2{N*Mi0$M>U$1_yh zhN}~8{!23ZFJ^tIC#Jz!T5N-x?w&#fy4q}dp)vQ7hR1?tR;FTc7X-GDv(=Qh#(epTzRVtAz8~UtnDn(T&S=@8cIhH`#4Kj^JszSS?ibXV- z`oilLiI@Z%ioZ*rH>%jWFAa6p3aR?rLGY_QBfLw%VK8_{4-xBJ#zVfy5-|XZ=5zU} zG0;2`eIQB1;=ev=O3%qIMdzkSNEqEXFkEndsbY%FeUoW#E0b6enI-&oA#Rts`xIjZ z+1d2ZWg^_!+ZRcC;(5GvCp=$8YMss`KcLsI&A9D#d9_SRX(4jghx@RP>{-pmsCqa6 zHkyklx|tY}5R!pd8H)z&3$mhB>)reqK-C6+ax`Bn@S6UvQ_(`B7VwO0nuF*IAQ zzxa5n^OiQ4%QU)yyK258v5_B>nph{tt50S9NIKjDp2RjY8JtjDE?z39bW$+KGn#y{ zw$4jJeJhW}Z7vM*dL|J=TH~z$X@rxW%LUkp?zCX;`7p9fn%z!M;!9mJe7-tV_n`YY zfIhHLFPU3}`Bi89$1p?f!I|FuS;oOXzy)(l8#SQA^iI}KH$;g7BwY29VaE8IS^85u zpIGjC>2@i$xIVkI1M&7|vLdPCc}lcV%5anTQ#&yl5b4;uJZv8|)B!lUdHw4BUyYd^ zd9O4EnUMCkM;)EmAnL7h%b{fsJ-5h)3N9VR~&H9(%OAW za9Xr!5#>1&yK^Oq)?Bzh6@RLJZAOeg)Aw_j*8-yfD+lnBzpM!q(|57@eG5c~^xJ_e z>9E+%h5^?By=lp`4}VcM(pito6$9$wI8YB#jxqetqP?Ww z9Q%r(gT|!wg(9h~%jA zNiWtohfo@D@f(J-hU{NL3JokEZlzgrJYXO3tg~|7(ScTRx!~uo zWMe@a!_EG0P~E8BUs~$H90_Ih`T_Ts<697&g;Asan2P!-8IIj5>V6i3h+G63HdiEC)er9$oZZ2{TchZcp8@9 zlXmOw+}|6)5Hf6|F=mkG+XoQx`lw&E#r@19{51Sctn4WT173&jjTZ9qe<@l}XuLp7 zqEvpGR^ATzqm{Xh{quw`c9k^hcx($#}?BalTH#3yS`K5x}f zjm6$WG#%9HlXGK9-Jvk&G*FE--}#l+^~4l$v!mCuOfFO$ixv{TG?pIark#SoCqBZH zQuPD-+AQb?aPIC|*}$IcxL_}=@0S-*&|V}NYrp)!$9%zEwdP#Rw5CjCTR*8Yj~~Q&U(^xzvh707Qh&!bI{?3BxDzPns<}FX zcV+4rkA#Hd7?NH!JMM4L9QriBV2R=$m>t@+(~6245R>;EgICEa&dE3O%DoHlS&FFe z;pnX?4H8OXt)*L7cp*5&6YL(%W213uW^1GIu48*bTvA9#C_W1B-U>K+^~N;aJF+!| z>yR3Txmj8%jJ{nPDOal_HF}o7!>Uo7XNTQpuLGqMUOMDLbVZt6E`yI*DTny!3>&|= z)tBAG{wX}=s6Ic_EOuck5I2vnV<3917-mY(&MvbXs{sG<3(`iHzn~D4sD;~V4@{5Z z9T+nX?J<|pt*w3eUZ(;!)wvWV70O{^upZ1MG0nC{TgL|k%-BUk6}xwf51e)KhJ z+}OXea`RSd9dGQz0YX(DvcB6uaDUo@+bzbgH~ z=Gu_R{Ag<_LHELur9TD9O8m&>C$;IYwOKXKKGpS&AB224Ppr>)8 zJ6>L?*fDVJ%pS+xad9a222aDG0JSMfDGJU*jRkF^M@Yxssw)kW0h@^D`@>{zgIbvL zZyv6RD{y>A z_)>Ze6_@3`+qv2FTuab4$c2EA^;l;%$&c4#cL1Q6B@VJ!NlUlivWXinpY9$le#Y+w z$u<=Lpiv{NKs84U9=1JVB|}=b_WgVZ{|lk?Vfht-`_0ZS%$}iNl$4BG_Gy*$Y&=q8 zjuib`Y{QhT)xa^bnG4=2D+?2-j5tF7eC-vqf*nF^u;1%TMwU|{yK3XXNn&iShYiL?Q7-hR@*?Z%B(Rg!wRAX#@2=IBtSU#rbWqV*29>M_H;z(7)y;Z~8k zwOo6Heg2PpzxH}L(go+B6~dgW(5EJ{vO~_mk*|>WH(R-N=qZY+Es0v{@4~SvS-3j} zsJ(TvHlGvR9^NDgaebiiBiGm{9$*n>5V?WiTN4|sKrUF68w0d!`rTspmQDL@2c4`QMSbB!$yKt*m<;@{e7%X^YpYRLj>Y2Hw3|fHV{whR8TQ9us83n}OJ1tv+U*R@ z<`y2f^m9CH9&UPq&lj@k>=KM`7HK-Da*kyCws)7qB2aac1{wdZlj3uJu?5CX%+=G@gJ;C$da#O&+2JcV}B*wcvkMF*JN4}tl z^WuG^{S>otX&reuB~T))vQ2@_%M+(Vz>k3Ak_tef@e=ej&ODoVB&Gf6ZC0H{xA9g@ zzq{tTshw=covbPm{~OsJCeS6e>mRHM*_LW_k0GVf?{|C6_! zo*HiWOfda5`pGZ86!{p#1&JIF$>aXZ97TNu1LGx>!Bw@e3NgdH>1$O9SL#l8$ETen z3Cxg^$Le@<^8$^B9WS@R6gz3A#rA0j6>>TECBL%q39B+6CYK(Jyiy|$yCxV(-A5rTz3_uE`9l`^vX?B8>rjfSzMr@oma4Tr6f|i1mZ?Be2YCYzfYdSj|$38XCVc zZ4h=&hQbYlibjxh;;x2K+<{-+8S8P;oX6^|TR#S9_`ul&QnTU$e#!Y%K$SA;Z1$R^ z-!q}6XpkDaQ9e#^KQ?Ytj-?pHmY7|0K#DFKB6!Jsu-SvZGDMEs-I)J|MX=VbZi9F; zciHdW6=&2}G)yg=YwPe+C$>X-U7%pyyOLO!DD{Sivw&V5O_fNjuL_+F_7ATYhUU25 z@o{GjMJF#y-ZhwDAq`m(hLX|T9`v}JhSWV(nN?=#b68s7W8_B5onBTX1P&no8%3_MxXdF|VcevEK5 z_E!xC4nu2f%%3&RxZnbi34(snO)3jYfA4CNA#E+%8SP-{Te^Ubc>7IrpEH=BL6ov# z(To&U;IvcFUP(?WJ!-CvGGXb-$F_mEuXmxgZ2|Htqp`Xx=C-+<k4vS@G03Pq4a0sHgy24k~zwD>{;Zy3X>o-5g9rkZsxqbi+^x#IHOH42^*;DDr0) z>{8t*!gC@jeg^mzk|MO4wx>yUn>St^o;g*>mKT$%Kwc?jC7#Y2H@C-A5ch-#8)_a ztY&EB)Y*X=eP^!UWt$|`h&uLi?F0BO|BCv%h8*~J&iv2gA^rUSpF|A9CYm`P4*VnF z`0sT{NGKP#$gddM5;pSw%(2REH@)U^)mooQ@hxS+m^e8eE!{>`k~nHZEfDv?OKucD zQ$4+Xyljh{YAqeuOG>^2n>DnIG1M&x`#@WvPG#;}^(8+jog^h*KZF6#FKjHz=-Y}~ z^XGYg*Ozm5q1A=1{M;_)i$*OIoQs98t-p-c1SJ#pXm?b7&eiBImp(kb`1emN(uAyc z21=jvfh&j9Rqr73L&i9CHfF);pn5X zi-V+a2U8F&cF?nYu=D%kr1_>7US*E~aoc~g&`7E1&}9V=KM4I+=~1J(jH$_&{POqx zs=>+g#(fb7%{UgHDAVX8pU&ntKHcPqip1Io@uBE+eYhBHmTCl(HE6)nmk+ao9`Qc> zl;v(gA$n~o%p5NsImcNKlG-8p1rc@00f>ToNlB^m%jZ}W#nG+e_8^1L;bOyMKnPUr zxxGkFa?7ah!=3(ObgG6lMFcy&m_oD+RfNrGHq*iB*&vL~Z{JV8(2%NYhjtl{DcDR&rTaWae1R!^J{ z8j_eT@5m!u=!Hw8vu4+fz6ajq25)j_k5xn zJIOor7}42CGouapc&SK46`y5l27R@NS(6qm)qbW}qf7m|I%#$D$+o}1cFy|gd4f(a zQ0jVp$OzR|i}#)-eOW6N)~J5JIRbS$xWz$CqU;Qlg84We&-1Ro#-(Zv z0>U_uj+mh@WjEVHk2IXF{}EG)^w`RJJD$&LQEuG@sB$6~w)L&+BEy=<_!3`FOMk_1 zjyNeJ5q8|Xji$T&Oxk1$t>QF>5p_l%$AL~N)5)!lGwZ9 zB#BDp-eHoHooDtUeOEaqeub(WQ-}KEEn&tFDvcKYB+iYtxp`qu%*5B9jRp`Evy^@+ zDE-)Nll?#Q`$$L134P4XDo#9SLlU~kliXR^%9UXPuMdo0*CS87p!nyfKVE{0^Y5|Y zW*esi%;wHGtH}1G>V2cFx{QYuTbqOEP`Bi|+K$0nCZs$yoSd85uJF!PQ+Pf9$z|yo%2a#H(G)B zcgMt(qI5`u{zFyHwL#;#5AQZSWJNRkD<98Kb+g>=5B{&n>SM=qls&!vhuT@A3()M32;F>GCrL=pU_%x#+T_j!#B&UOd_`; zz)I3a8-=~Q&eRAtQ|lT^eD>_=TwYp2^A4R}kdG$d!8~H%dY@IslfjY%8N4#Hem~bv zN=n+ZI!=QgQnhybMf^8kmULk|ro5n=9Dc5L<4%1N%TJ!aYGYS)Y~WQiU-y4)bd?*0 zZ3D|bV0>EzF-gX4#U^L>Pg?dkm{-t zyWJRm8vE<>L&quK=kM5I)5>8}tH)JgN{fq2a*FUE51)jfWlXo=wjES-G$lRgB_=** zjEf37a=w^@AfOF}^mSjve&=gM7`7*QneaD5io7$7cax7%o zm-ezY=f)~i5Xm>h0+a*OWwB)0wEP-Ug)4g~MK`;)1v=$~NIlj;n29n(^<#xb5@j5c zZcaUd@b23!dY|u1+qU(;pS&GYZylZTwiOAZS(xI@NU?F5H=3Hh{l-N3(n_NVvM_nE zWw79X9OPSma9wh`aHHB_lm&-tX~iy(ZGN?KXN7&6OGPxDMZT(a2WMcNl{5-iqZ+RMD6}o#l+|==-csr1u;3HJt0|8X;R%NkMP- zFVh`P75{N7$F^EgyIcM;38-;=h^De?e zew5yPV(Y`hHRZ9Cb43s~JczU$bjv%hlHTG7l-=Zf2gt9PwbgmV_h*>d5ts)th1puY zZ-{ApKM9$6L|ZLmG$`8fp5`0N1i7MPtTwQL3~)VA)%Ba9yU=dXzb^X<>?NJtc26=Db$LG{Dd8HMom zP2zr8e02LdE3L@ViV^o8FzC1Du2r#Tthb54|hzsOs|X4ul$4)^b;ly6`@AvF+rX zx7kN6m7jcXcL_NE?Uw1f!>eNtX`FLcTa+(Z*F+H=ttMM%b?@hTJ zmq6>YeChA@M&Z&_Qot^oG=sJ8$gdAa4lpTj8rq|G%WXLebwGoWJR?D-UEC+b-kDJ-N(gj zc0&OllesAQJZ_7pJf{7pl6G%`W2en?*?cUkY9@-ZGREswQah76+7-XIRi`o3te2pMjZP2C+C?s{x$E&6?43M({iH{=`qK)<6IZDN$Swx zTMU4Q`jMBo{R&|QOm^fqWa}zo(ymF=B;reQ=xikp#0F*!G8qdBe;nCvJ=##sN>51G zW1cojw3~Q3zDwQP8yg#fd$5~SVlvMXq7sRhFWLJW;&mzFo=>dXd@CfdjcbL*6WhW! zmb~`Yg~~oji*nxKW+sOE@oSjYG0EGZOBV=Q5Kygy421fy!$O`}n>c|h`-<3Oucw2( zsUj{k7#MATOG`|{jp!#*&ge(kR#oHMCXUF~ww7+78~3u?8^cUR8yhVy+&+Hc^p;Aq zAFz2vPLt{8Be7!Wxm^M>)7V76Q!oif;0?gGY1p!O%tgI!+aOuLjnuiB6x4qwKHog} zsN6f2Xa!`nCF8N&CBT04{CHwFxGSifSSiG|EiT3h@b}dgdjSB`Q}E5n)glhHg0RGM@?n%^f6i3Xl^Ytkf{G_L$T_ms8c(H{UE#W^47*abC%V7yN z*rJu*o!UYY*W9KR8WxyyF`spN5C7~GvYSqAr`+e&S^N|9HKxJxek>H09qRavw9%;; zyO}x-PuxpK*leXQ$4k`4e6@fq0hq4l?t*fUQ$N$rm>nY>=LFld6p?<)u|12Xz%Vukw4u_FWv#!_pHqa!rTaxxHarI z=jj-2bMsv@SwTgb@NgG=!ZjcutrFPda)y#0NY5vB)*7d45zZ`kDd#;WLWvx~s2Qt}XzKRK3sKiTh@#di)f!j5wGu^4Q(tn7UHjkY#k7YCZy;$Gvb%AtAy~+U&!Ev?HJ=XxJC9 zK-9g7R$PY|A+v4p?|$ruZ6~`5xu%vs$Q`5#eJxa4G4~t)(M;+y#N{fZdd4_!o6hm8LX|)&2GB?UM2>ws)_E)sVUE zT<*%V+{$Vzk6xj4tqVR)-66X+spl4n}gaUyCD&n}$%B@dE*)pW9~C{+;kyG;u= zgXL}i8v}a+P1$LK@Fg*6gQ68x$4w0s!yEALD&OVS70MZ0TBV5jx2B7@Xpj24>ZxQ2 z(OHgV#`nU;;9)%%gh{*#DHiUo{U%J=)HP{Ss+S+bhtj`yaj>$DQ%ERQrDUirDAKcn zQa&khLo-L%qHh%42TSUGL=DMj41LvW3mu&nX3Xugk59%~R|D$GxW zz@RFLhfR@j2d!5_H+A^&qofl@8-sP~0_N@cX3FvTZ?@Hj=3kNLZMwN<-N5bLH;1RW zhhxh#HOvQvF{rw?@2xi>iQDPrE4o1W1sOjILrmao)B+7m)z+(CZ1rB&(oE+>ZO6?g zr?0ToaJceALl%LpWvQ}-H8qb}cdY5iN(ovJURZM3>_O6gri@LXJc2J3qt9XllYU1_s{V#AjzYtDY4x&Mo62TZM@C6skcp|;by3fPZyx;Tk-8f>4T}49N zE2TYp4y&zWmqF=mt?r#6GtOB$qgH9f_TuyIpVVt%!i~~o(RkE*HoG`ne@pyn1fZ@a zBh5CS$Hv22E#Rq>MQEo$I@fsZaofiG-};oCM=YlT1MVG_Fn%cTAYWL ziRkYN)naGe;U$jWy4}hxVw#JVJo0#6`w%9*TnTi1dBVc-?9D@^`-jJR zC85IMM2e#n##ROBAX&v+OI^`4|Jd$|rTOVO9(}=-6%N0QeKDAJ>SB+q5GTVoU@X%@ zhwgN|vj#aE)}UeTxn=?Ul_?x3<}!P2eGsE@dX0@=MPoBM<6gmOiyU^pEq;v5Xs~E% zv_?vj#dm(jr54WvpO&XvX7UMQ6B;MyA{f-`P9Z^C<7_FF^C#c9WNGR$b)}MdYW_nV}->UoK}Q zKTW$&qH-Y<{_o373;fVntNm)FnHr#Nqjc%fAM3Bk>Axo>!Q5<5R2R?Lw{J9dtBTz2 zg_r<#D@^>$Uzty=@$YH+%Gzrv42FpF?BAi$PJ}sk5$sEjJFy8Fg8O`B{ilvnKbu{? z)j)UI|0r{Zc6%Z1we_dKSqTO|v*CdNi!u7PFaT;kv}5>pive9^1qXylzcq!fm?y=) zet+p-e_>4pRLv4*IVvxS9p(_?v%Z0hJNRPQhXY=G8`kjubolij^XJzBVkT@E|ga#^5K&q5|(HmYZeld1Zra@GGeF ztg{5$AKgk2?#tbk&T6H-@{UT-b_-M`#i>o@?g|azPZdJ~mOgs5<@bz$DEEjBINOux zgb>pxJUE@f6Gu$kCtUH*$~UD|-vPv@Pa+*iuWFBh=ta=fnz3g&+IMYH1TuAE(NnwF z+oM_IAEBf^6?!@a7o+?pC(Qoy7*J@G;@tfdZEl`@y zF{Z}H&K=sn?^+xNh>g25Gu@UyDkIQ;H3Z=kQopsu`oAH}!29PrB=c;@&kQN96r%jA z=md3->-=;v9|e_6LAIhX$`}yS*ud^Z!sO=X{Ws~wO2i_s`GhEhoofU{H3F(XDzDcv zDvG!pTBs21H~y(K40}7_S!KD!9j<`JLvM8U`zABI*4{E>%L%c+B~;**Dd3_GzoL!{ z%}QrHDM^i5XbC#@^v~IffGL}L*v!)J_}K>7Eq?`Cs%G)_%rDegZp?>IsS9{z0A~w1 zqdg-jY+n+`_YxFVml5}%2ay|$?Q?y7S26CKE?QxouBk#+W50}{rHpS|gJ%2l4RwQ2 zRQmL(6}W4`rN|6+*gLt`=tLOzOIA?$rbkQ-KX5uq-loYb!kr>54|jVsBZkM@pv67Q z>?--&OPn@+{(j6k&mfLIL`fl)lHs_!07j1LUV8Cb>{QW!tpi6=V5n+|eL@{f84(K2 zOq{!An>g>cdDKJS$L#~zPZcR@H%WfIIrPKv|J-Y{plXeZU2{mM@rB@@86%z$7CWqo zAxxhx%m|||;`1+aU%yObK_zqLZ-$J4cTm)I%Cx5ME#hXd8v(;l>!nFJjjJte^ z{8VPA9iq)}OOgSJktqUI+ST;CqZx)f z_$Rc}xd4fMO(g_5qhXc#FfY_Aqs6KyU8F+HTMsNVC6?#LStZ8Wv?Tr))5ZeUcyiR` z%>U9oJr{@e5jnArpPkF|db3jYmzm{)iQp@M_F{$zSW=-hYT)2XHL-8HC3dzzF0oUe z7FLfskm=)>BJ4xjiHb#;#Q?wY=iQ2n>^L2KI=Uk_OXtL|j<^WACqk4$kPlvwK$E1c*F!!L+-dW{=2;5wFn7{P&0bYqLv_3+2 zyo=gG)dt*d9estvNtsPisB7G&!3g$Iv>_vk>7TI6_Ca)gIhI9I5l{c`jtHk0_P+r2 z|C()s%rJ}Qzm{irun3{P0i*4W&yvt*^v!m5z+v%BjRZ`!0a=sBwDB?u@tKFjE^eB` zD>j-}1&rUr=V$eUs^A}#XmepZ$tr^?=6<+^sBrmmE;ITL5FjA@)jqK1TU5xa>azE< zr3c4W|E9yat#@&GwrDtZJr%w-nRL3g5{PS_gilxu_d@-qi-rZF0Bx%<)@m|8*W5KB zXj}kL2TpK5@Chco)T)v$#<=JXm^{(BGfHjLC#Oy;2k8pAo9Eie0j8T;2gjHug}(U) z8Iss8ncFDdV`3r&`o-fV9+p?O$I<`6Bn}kyaQ=VemYza6j=@rAYzoWPM2dCX=4j|I zGu0ajLGN``DdYAD^}94MmCWec-QLqa9&!%bbnZb+a7;=ay`)pn8#ZUD>4^6!sdN+8S&h2OtA`rH@v4eEJ-;ft{SAZ6&4*rhhja?QU zW2=-h3k$doglSu>5+u5O?DR@Kl-}{v53pOP(NW3j`(91ttcRo)bXV_J@m59EmZUX& zqx)gKqb!&>_%rn#%p~r%*1z%5xPPn01`l0P5bW0{Zq^sN?M}0NZOu`St$m##Kw|cL z)}`$Y+?Xje%GOIokfy?37>|5{fl=m+=SGq()y6JNHj~jpC7}hIiU8M5z-22weG&=h z<(({ny$qNC1B}=X^I9tEhr)kaJ%3K#`jM*U`4Ji)ofN`XUMY>CL@#jy#6Oe+od4sk zu96{GXq}bV-T>S9D;rV&1~i;!2CQF-Nzr?(--%sl|DxTd0doJHiO!@lgw=3xmv$x3 z-A9hegg-_=o!d^}@OEkx70R|#fgzBj(9Co?bFI)BK3U!o9_Q<8f)Y_@X~q$Q_sb6C zj5RF4mr$)p#Wa>0J&d|Em9ucAtcs4hPq{PVM8e83Mjr15evi!Trr9vP%KaA;S7i3- zFKf7b-{>S6VMYj_j) zPCp2!p;UA38Y@DjP8P$)OPR zbbbFPL~+K~mCfsT2TQ%>sJLI4ktvFL`jk560Rsvza~PT8`j+0;`xoIs*Pw*2PX&;9 zaI@<$+16t_+OgjmdbI+9|v%DDq;VFBpo3x#TJBW050*>M{y?$~`FA zhdc)Q)q6ZSwH(nl1crpGVAq466)OEAFruaB;I?lTQrJhTX%|T1^bXRC@7VOwZLF|8>OdA%(6&1rg$~p*xD9 z&3P=UKxhfO+Z*9>*j3Yh9CZ^k@%r2s_y)Ef`WBy~fdh5XZKP~}v83X3YwIBmeAKNw zN?y7;X2Zc=ao^n#;WmDneGCQ=k=DEuSCC7iAu6();(C5inLf)m&E+|AOMbu^>}_}u zA%?Z`5^+^6JWHm3EQJwvtOULo#lE_nF58@0y~uAeg@iA@8kN0YdQo-&`l4z2#y8= zfJ_^GCm?6_sZZW0!~6uJrnQqAjRtCbisR;yK|Q<=GKA*>iuOMH&HYnts+rUGs_D^9 zI$8=vMxc6#r}4gBxPrt@%@kg4!_h>>jwke(9@T7rb@IWhk$&%rL-aHJG@-TrKxLpN zuXv20;SB3*lXaErZ|nF%oos961UVp|gjq81>vDwI0=(UMK3?D6`#zt*;qRg*```jn ziQ?1CpUDJqU(I&+MYyL+po;MXdo%pgcNcA`J^%^3Eu9QZtqCT zk5ZPJgH?yBz($Kl#XmDHL>nCd<_KQDj-QFI09_g|KF%+PVE8PV;uk_B3L|lP| zJ4lPxsA{y2Ufqh8PMNU>-g?@^K(dPusb75ZDKY5Qb6V5aK?q z#T1WZknc$(nOq&%yW_msvfK`l18QmPHfb;F62GDnVVv5sON!qo= z-u>d)nqFLvClTkCd{UaLksJEaL7u>;FGRmqv*|hA44f2t@Tffr(AAKQACV8N$N5jW zNiXu>aln7$Tg&FZY;Kl4dMlvOs0iq~{^tv58k za4YN$U^^BN_pBrO+Qj`eP&U^O|hApa5{Kw1vu~Ez$5H1KW2dvu{i* zr1J1x_TV@j`DGL3s{sN*=Z)ko7hM}DWpsvl=thTZp`zU>X*j=dCTf&`%KzBH_EzQx zZD01%?YO&i_#T_IP)=RL8X&Oxa<|Z^fqy4u3}mJi1kp7E#%4ipESutIzfOg#WaTI& zUPDS^7eKkghP66FKR%|rM%gUuRIn%X4Zpy_2w<50{@hAPjVze^+ci1RkxJNGI!fw% z{Jha_kxA5n>OB|BJXN{*kFIP!Zqvp@1_>z7wx3lW;|5MQnrZLiQKF*vl|h9^z&Dbw znztXrr`zae-k}6JfnPqzk3p0EsSq)6yZuIZG}4t-D(@65p z&#}T#wN?m`h{C(0zaQ7N5Nv~od`5}o<FnW? zRP?^reWBmfRpT35SR4?ZBcM_<*DU6;Sxu{l@mW3GitR@!+0Dp~2znN()=P`jkIL<} z)yT?ExwW$L(wC$=$)ajPpMu~$Q43toNJF66%w0ih2mVwb4Z8i;EcB>(Q7iyN=}*fJ zVM35cd#N}BadA7iwX?1o`4!b?7!rlPm6Mmrn7xWF;oJp(I!hPyPcw6+Ds}2taD9ER zx(9KcqTyQuXQSTTN2y=8;X?YtOEjq*Oj{r~*}6r>RdJbJ=(d_YD+N9upj{{epWY;G zThBX9a=AfHu!_W}SM2aH%k;#73fAqAmPuZ%W9oKxy2! z-rr&@T8@e$Pw7tBEl?NQ@r>qBvK+kI5?tG<0#;hQE52pykE?ADZQ!&?ulKc2lk`V0 zs$MxLQawoFQ?D+l1#-N^LUFzde zw5Y@pj*ytuU1V1ELOt2b^*q@RTBB}LhT`_G*!eyclo>E%dqfkuxXAIkh7 z08uLhR>sU+?L}rHuL_}1jta8AovB1s@Jg^LDrx|l2Lep;eJN)Mia!4Dko3Q~+r}hO zJ?WgODf_$bzz?P}_>GS2k?h9buqohg!Do^+ZgW-to47QEfMvVW3{z4U)oTPoy9sLNiTOQv|S1(tg!x; zWcDTqGmgYP`JKXCnk@WQxj?U@*LkBl@#NTKLB~h#6jl+xab6Sq&0X9^kQ;XQZn}m@ zdgt99+N%WwRFL&Mt+nEuQB6pkZ@9(OS zU#0|dttrKvzwm)|*+m^#J{&@q zfnn<rTrJTiFO|7R_%Jhw$m-NsN?)KIW$=F(&+2Z9% z8a`FtpRe36K1<0>abHiIk8joNlBjv^7jI2mB$m{EmrA&u6jQ#+CfGREJ=iu*;dElb z=de_;yJQO=_m(!d);A}XbG;-DALbZ$v0>W(Hr2L1d6qwS5NNhsNI0e4-vRf#nCOs7 zQc$WzbYU{vP}GOtn*L0@saY9`i9HQ;#`N>8))r)QBex{mU#$B?SgWSez`4Ks`a_4i z%!;G*?-HApovkB*wlf}HRg^mM+=1QpwfmiN;sDzLw%%1dN3Z$pPxjiX!)Qv)l_h`2 ztbK6ep_|kaITg8;F7!r)l-T@bj=eiKczbKyS;PyLxoxy$uDHLgOmjcBJ z4kZDK6%A4-F2RaxaMzo@=ljmNW886m-#_{HWF%|vXYIY_nsctvy7Bd~thzbrH_)B= zq631hdhH^#F{=>xZqrRf*{A5$7H~Q85B@6>h$Cuxa-y(#K0O^LRv4&3)(Wa(=l})pFEHkR+ex@n?a|PS!)X4sqoLGHvvo3 zajiLz;wv^P`g3ZS?FsZ>7ytQosSYuPBVJ|dP686CCA`0VKc$+&^4D5sFr%h9tGHoB zB%D$m9b;W9J`(PTVXYzw_{uny8z0 zJZZBTPJ3x@Xyp;f#)T?w$zP5_P+UJbF@d+3Tot0Y-tX<7`#Y2K*wl+cM9$ zX4ri-3cmvZF?_^SIZuM=%4a)K-)m^n_6H6X0UkU;M!Ge*VZ z0t(Jw=kBo4ZR23)mZtN-1{XjB;Yy8&({DSaKspC0w&V&CywQ3RCYDDr>fKgiQ2tkC z9xs6}2bMLT74)kyuG~a*xo-TV7xODt$ET5C6S^Yk>8a*qVsDlqrYp>Ul^A01%viK> zf_f3Vv4{m{zBF~-qv@BC0gp!*eh+=Z;QfS&zPF7`^wzbZc<}N`=%CmRm@~Gep)~); zX)N`KAie`-82)50wsA>5av&Wa%2Q+=RyLs&@sNT9-tvau|5RS=z2-8&Rqjo=-wdYc zQfanRGFg*}=)yN=d~9LIEhh!%en>vW)U3(y{h6A7Jb!l&2ER#)@4GR|rWAW`(OSJ1 z0DrcHbwA(#BO*d0@r$l8hRR>4nh?ojZ8JQ>Tw@NoM|4w_jJ-5ja@NnxN76__kN1+0mcT1*Ms7i)f7g5_({tkK!#!uqLtA z$FY{zO}BrDn8KVCtiTrz`nFaO+R4ZQ?XN zI#ZvOem7o?I97~mXxdah?Q96DJL5S7-HhdvMH@0{+y?yEnKfmE8zGwEzP8zjF0+#Z z!=t*Ms5(+bRjZuo@i{3_} z)z)!UYdR*qjj#097GvFgikN;wllIv&sQtI4=QZ88#g@Ixms=sipEO>Zct9s|qfw8y z2-wr-f97!JD<91T+Gme}E=nCvRfanow6)Bbu{|V2zul0>yldHhb^h?Mn}9f0xYGz{ zh!BTQST&_SWHY`5E$Ox^4}*=myxDe<*{;59=03#8)C*26$`PD?D<1-QQ>dKvfv?I0 zHaCfYzs7~-HG`*M=m#!b{Qga+qkd^GZJRgm*z5*wIZnPCu~(KP)LmkxN2xbZ29$Nn zUgdrz-rN2gF@!ooNDkivb^yPsfUd-h;z>t&^RgQ%EJo)yLfPC-V*^8bl zs=fk*I>hlZ3K3M;=#4aMSfzmnMPri#t7fP=7w1Z+;xY?vi*H0Lbb{7Ij7GZ>?stPP zhIlr}2J7#)k^0jvn>(WHPZlM-R|g(xeAZ?V8+?gYkz(4cqs3CMMrkeV-tSk%>MUr}CHNS3y3W;)g_@Zk`xv zM5e)g%!~EROXJQEx*Iodt{%u)O=0IYQRrKE;=oaXs=#kN>1N%ko8K@GdepiP^EvI# za{C0nl7@{6o`Ejm+9ov`X8vx``F|8h_gzkW6T8sQSZE`qd$9erAz@dz-MtS1vb$b3 zWldwA(Z@gZ_q;(3@k10XVWL~u6uSh%)H4%j)jqSgliE{ z!zeDZ2H7k>(2xB2RL&=+u1vy`3QMDhO!OZ0O!<+?^@(xuUnO6QW3VGklQLL+rsyXSm1F+W<#}Cr@c6|G+JQwvw8nq4K0gYD$5viB0qFG6h~L9txm z;gkHJ%x_vS@aRf!{4ldQDc2mcP*qSjZ1nof0iajL9VZ9Jf?kWo<>_=rm{l5Lmh54VsG955gAj)^>b%ZiyflIY7@rA~SR|2!}BZz=9 zjhAbp<6O>dsCW+Um1VZk^bbh(F>O`%PD|v3xV(e$H+(I^2gAF)kK(_bM9AJL4kTsl zrg6EEI;PAOjMw<<7f9TVP@jwwf$yG-s2}a5iYYLR?Tv`9_a0C0mGbVSG<%F|7p%^e zu5ynbF5fiI`G97amrTFeW1~IK+hiZpBmrMv4IAh<;lM$e^2&E#S8HUCW{gX3)?|_p zUq-R@TfVFLoKlu-ep?ufkKW+4&(p;Lm@VLT9zQy-PM)qM3wRzE8X$zB|AH*BIp)37 zC5)UJSv3%7SUe^7)vZ6a;DQl5H!L;LPlmpEsVp_YcIN5D35*4I49ul~hypVTAUiny(G%IWGx`Ad8sW5|;k zamdawRT1ry%N!qUxfZ~;8x?ncOcX!ukciuB%tIw4c|P0d(7#e~g#?=e3R^y$K^ZH4 zXBjO_9SoetR*Ow6l~cPNH=>k5YS88`dYg&dME&BB>wX;N)Mnz==rr9z!M`OV*akV zSw&uBnn`3%Quzw43HSnESSH$eCsH{oPYz_Tzy=g83%KTgi5_+%a}+=aRXems%VG@H zN1V_3xs9_9VtU4=<-bPuQI{XU%V5^4y+!MawvW11qSmQ^o+&#Cz&+%k^|8asCl?K* zJ6dPIQ4y|h^B8&u7Vl-WHMpgO6<3U(PWo&~TAG^{?6AR-k=dDrE}^B61KAhwG~xnu z%7{m;&9O{t$a(oXKWi~};r4mZDO+NFKGETZ^`{zRWD_NPI^ZO@SyA8rqyyr+8YQK| z#Qdz~9{tS0{Yb;XU7zDXz|6klL9GdVKy%Y|o18+>r`&N?i<#L++T?QAso`SRg*fNp zo6}S;{;`-=GF0zdnj| z2K&n^78k>kC0E~K@KZ^Cr$gmU0k6=e3A@my!*1No8P8-~8bOUh^#F|tXSSr8&y-OF zISBdFw~SHBFpOO1shV?t76(Oaqg*@?FP>aNPuTm19Lw)9an-o!%}*nI){*YNsM(1q z@*+h^GWo|P0uTNxF)TBjCaSk&I0wJs;N!U(Iz0-rbS)i z^l-_hyJ|+h_dxtF^<~?^+4A&3GuS7Y2SGahaKA37k`fh&hJ@1I_>1X@iQ|aDriguk zu5KO|VZK8?0%0WVSR9)r5}lNq-}@0+_nIj}Q70Zl!9KK6Ql{cbC~V~&HwvQ+FB7^N zlfR0J>Ob2}DhG1f+O#P*>@7Zt|C+>kU{shorj_p8B4@V(n+xqL_gqt&@3ECHE2)_0 z6cSSReXI9Y$#7MQLZ?~9w2Ks4GE=}Y2j@*Cy2OurRB;&{<`9LSI#7VM z@VPO_=T6*8q+i5vjXX?^o+HS9stxDmJ_XLFd#4}vqI9U1i*GAe0g?gbiF!K;%C#5s zPYaY0yCw0HSD^V#X9}W1Q~vqJ&kFW=Q3|DyL#9TBEQy<0UBeo`utfA5?=c?V(j<=Q zO5xYOZR*Z=2KJp@8_&b{37`0_4%b@oBbEFn=z0O)N3MImy)%#6!H^cmF2{=@%256O z&L^Ch*7(!$crVJN&5b&rh5QPVtF^B*$LEz{nm{h&8Z|R-@8si+B;F?=Oqr9$ zdXUz^tQ4a}Aq(erU5R65=^HcLhR4v~nw8rXOtdP`cxGS9B}rV&K8FwEpgF6i1y58? z?9S=sYUD2iB`F`j7TXC4h(U~7%heR-2!GK9GPwg71mIVp$8qvjTg$Kj zt;;Pm{#N^~A-k`8WE$U*zxU;IM7)0;Nm6NZbrhr*Wmvp?STx@2zis;nUMkUNCgI zwNk@c>v3lJ$kAyVago0iKLs?k!a6tFn&Q!=XUnX+T~L{ke%Z2XRE_>bORMbVNd~jX zDK%HbW(P9^D8E{V>C&(!`ukR1HB8KPdrtgT)tH+Z>=_9pZ#*rT)2rl-bE?BAJ;ZMd z9i(771F00SmSEc77GVd=8oaTtI_u2=r#rA@OsB0JBx`^a{U98oAqshX_mk%o2T~b+ zOznLM_pWJ{yDCVYo-&4MHphdCSap=M0A5o$7S$eRaW96B|=H1%Vn_ElSIHx>qrY_~0=7 z`s@w==hpYSn}1%t5%sUm8oK%pIR5g-ue~eT*}XvoFyi9rL4|o zHpDZ()~`}mH>r1it6AIdE&B`K{sLF?PrAA(+ZV*J5)S>6{F)l&J|Ra#?*gKyrKh`Z zO9mE_d{qi^YhIUdob}E(U*(&`7(>xX_r1R`^DKJ|1ctk-lII~|Mvt2mJU_aR)p+!f z7s%jJF%lWXYP3c7YK;`wMK?7%H4@oYB|Ha0`#DRPL;@o^?Qmm7!)4c8`UC_4T=_Ba zJ+;H~5+DAc_|&$`E^MHb+yZvaW9}RU^8Lo;Cm#)}kI@9o%pP9N+`JZ(8=YDsc0)7T zMg^-d7dhP(N$MF%YRvz(;qRSy=jRPOqweK2;B+H(PEi9Y=jSV<%?x3P@-YP4 zs4!RJ6&IusoY`LsD6QSQcbs5V-f_vz%3r?PVUD~p`3>o<1Qg4L`6{XsYA^2e zd<(mG{@(t#wtbreNO~Uc+WdTiM9YSL8_y>J`5yvsgVd45eXi5hMXIoPAu1J{?vLF3 zRy)cR>26|J`E16fxbv;(wIt%ov{Ax=iy?Avz`=nU$3X9dRMC zE{Xv(a;y$sd8jH4Ojg-@a*N1WjlNTFT+AYgpl!FoODW56v&BekL{1-3bI>KWZ+vn4GI%2lr(lt^nfJ~g?b=!o#E@%$zv`dLJ+skZ z-<2iTf%C%DI5=M1_$s(0HPyM)scOx{kk=VKhArUIHY*qYnktj3SCN`s+z#CL;MRZJ zkgPOAVBJ;hQp&{R5Gz+QHv==Tn{1kKpkO$5UPoe)UI)yI=A799CnVat;+;z|85VQ@ zHT=KydH>LddJ0(W`6>!JjqHl_>4?}3%J4c#D++>QiN5jSC|@l zg3^V^3a=CO#Au#q1U5-$crj1DynlF zXL?VeE@xSmV+41p{~A8h`v;;%ZpqTFUeepP#`w zvHOd1M}=9rGe0!eN}szEYpT$&#cUX8nQTP;s1?8^eM<)J() zQSy*O)Q2=9WKKGnA5x#@y1a!tDDwxK^Onq}2hj1RVh5FXTio)1s7QM|{8Shk>|7GF zJFmmzD|ojQ&%fNr7A#f*+4po&`qb2XDC>O=f`fbl(VQ1x6^IVpE@bVQv4XQr!}FlmsW&t?z2`ykPc2_O81fqZZNXdX=HC6jVR`YO z#)IqB)a!kiby?{^7x268 zC~vy-lOOeL+go$m`MoyG9l!O`-Dmv$yk|Gw6@A6rEv0CEkn3@{<#160?NFaC@P2Mh zt=otmb^yX}fkM|6+5_1B?UB;wd|yy`;1onFO7_V7VvxprYcmaldZ;dq;a4#S*bnn4 zL7W@~%+PP?D$fipA1-L0WV-4nb}krcoKGM!3u?3=HM_x9ct!q>S2O~liJI$@(4OvwwpQGHEJ58;&VFm`w)Pw$`MdjwyK_hHR!zzL+e;ubGd@~^nPxNbDzy^4$@xd3r{iha4K zv%IgbMQ#amGIYV4?;x!qLm84)FB>c zfO1eL6B%V2=>xJ(7OtT>4S+4p9%Yimukd67Dd9Koej9SmAd(dMLTX*P@>8CM%pAIE zzH3=F&@wDT&S@L9$o6qSRa`D;rr+xE%$y}s<$Sa6qijHDExs!<@Vk7!NtnX;BrT7b zLFspa)q3FsJ*1WhgvVBw{3Q1|^d2%FKV`=(cm*w#QBa?&d#bxLETL>`=K{l}yhU^t z;t2xFa^tJE31cL9hTH}HJ?*$#idMJa!|@ZKV%4;RmPCsU##$IveTclmAXYgj=!fU( zX6%iEza_!n<3C$5Ry18qs46M>8-}j&B%Vo6G5XRumT>oTK<$4t!pov>`UPqFo)MAl zu(PKO(31A=YpE2dRMHb?PM9-{x)oUS_lX(x-?PMm$~1re<@+ixL0-jYou1!qp41vU z+ zn{~|ClEh?{PnU9UD7JELbI}HcXoHFqf}=vF*N4rFaYl(Riki_IE>k^DWvNM{bhu6KBsEiNfp$)n!sr|KoIe}9EuxOqH$gkG-j#5H82aKGNhqAoK;M+^MUd3?VZ+D zA}kZ(%$s!aWdd_`#!u-iyFVhesTT2zoMVzT>Saq5;N3Ncdh zY`%3?LRD(Zx=LUkNqIj`eN+QOp3`VGU{cX@n&4CDFZH(YlK~8|a=thUCK*Lk!J`eU zM7H#rRM?Zs8K_1K|hEw)J|si*&^8WG|E37wCq-cN5DrH!U7Wr!*nE z;Mu#MOc4?N3Fl){pguf@MN?-tu=|n46#L)l**~3*1VK{_?`8aO4ouhkxYRu$h7KJatT(vjxHf3i$ooSQ^j)1FS+CM{NWyFAFbF zjNVPrAaH5t1Em2={|jSn>QFlQ6b(AEVR!aOsoPAOfG10I~tJ9)I6P9bDX_9sdz}Dh(WLUTc52KK$JA z0@H3iyv~qEQGX1vCpz0M1JRJ(W7$OBF=Vs<(C6hjx z2(`hK;?4&V>eQTCN?yDrYhh>a)8~rvemxL{a#2(Zzik^VTX7-IjAu2J4DI{4YHYK; z>pK0T=vO$uF(O5&_3J8ef_M)sCbY|%J*q0M0%ZM)b~8VE;?k0Jk4;=R0FLc)_BU9L?-<$j&CuU9g&injyYXeyxQrWQ#m|PCi0MXN*AM-8 z)uWxEz>1k=b7?{G_Bh&c`fcF}o6ze{6kgZi&%6XUzAO`cbF0L;T+pwtjq1XX;3@r* z(@)=u|M2xb4VeW{5&+i=)dS6Ge67mzZBO*C@Z+O<34b2QJ{SX7J?M+&B_bS&e-;&G zaaF4xY}@xst#G&TIS$pi??f)QQ8zs${sEExcHDy*^_MOK3-bB*z}V#}L|m$7mvs(} zWAyR!Xl{yF0c4Yd7n0{(ts#*#1uXfzT*qaTr@WsB)3VSNc0@6fuv8=|&~nEo9xoDS zN@$K!+IOBP2~75#0@#WW&B+H{b?-LeCK3FrudcxJg*UABH>^s&U&DGZgySSZgLr;l zOcq-24X^%UgT@Bh%;2w-uWDs;f4bXR=qjjkXds$H>`vuDYGmbK@FZW+(y}W}H#2ki z$6gL;Zhi|GH$%@1hldvfw@Un3l^_{r`A8xZenb4%34I!GF7s|u?i3FyXfGnO3zgiX ze-!K$cI{91+Z3EVkm1??Rcx={?YBlE&s$krJUHJg{&T(~Np^*fv4@oysi(<<~#RZ`c5B zoP~O39q>*40Bk*zK7!XN&HOok6P8HSjm^04b)tS_I~xM8dEswcbSm-kVdBzfu!X+g=r6?P==Twq2f( zd>6?!Ed1%7Ss?^3yTjnoFgXxbhh|GUq4EUN`sfGTf#WbB%N(kiSr3h8Eb46?W}hPm zy5;*hC8KjqY9mhe5XN_F&F26m^PD zjUxKQHJ2b$xY~Fn&>jWQ`I2~$o-$gQHvsfKFgUh6{AoQZL{N_1t!7(v`53x84;9J! z@Xea0+d#m~0{4@%J?$%V-MiNr6d5IZ-34n(m1Yh6(CZm+hvb@q2w}!B&l=zU2AR<= z8mRKiy5eYj|jZ{UFB*lj@NX82n4&6U~L%Z{kJl^)|8mj0R-#x`G2 zUPUMy4H)W8%+%tZb}kh4y{HqXmg<;B#Bzzldu`f9Jd|MKN;&YPI%tHCQ6B}$Lc?3B z+#NUV5A|mcq6G=E*#IAyss9`PXq9tOLdR~N8y~77r=1mmY-9~n@+~k0XVt1uu%iD+laF#G<@dMSv91k)k0T!;|~&2`Xd`kZRT^~{DHk!{LYJy(}dmN z&()21WW#uqky&~(CqrJFH-b_3KhFKo>SbhR$dL&maF(A@PS+-m}G4TCO>oN(~- zFh)Po#6c4NOPrl@O(`Ng)~OQ5$AaGFXA<7%fk%gZ8Ez}^mM^PBYE)LBt4<-`SS11Tbx193&>sr0bv;!+gvTeQ6#C)d`tr(|~_eu6J;21_NT zzu79JV>awMd$lhYp+;M1iyZ8gkUUMO#kleYA-ns2e(mB1VZcS9XHAScMdh(BZ~9lt z1HP{!fJaQsdD)%JCkY!X)aC0qQO_)~fwc5H_F@*#+ye4PD~#}QR$Mk^S8|F9Gk&z5 zPCPgooSMA+HR<-93EyRD5zFXwCFe6jBX^WX&-mdmy?5E{w+pxi6`NLCrAlRESWl_{ zJHU`rd41ny<^Jtlj;9Fm)#ws0P+cjL$DRCE{#W) zliLnw`$uh8QknT*-FT&=+)+Dk`ITZGk)-r|u*A#@EqYdP6h(M%K|AAQ@_3AQ>@j+r zN4}Qt78dYs>scU0&U)y!$2$4_SM2l(R>YT7!-&ZN*_AV1_4uZ1W`36u# z=32bhLA*c7hFPh#UbNh!@=)b^|6!o^+SF&Y=SyX&MyYvgNx+TK-WylsjWshpmOn+z z%Sl)IEM8M!)iXb*kYu-T_g3#nlttVn<@JEl5g$5?oRNVf%>D;Tp`+~C&b)d@@TpPE zX^#SuApB~$w;6tSf@xMzu{)n+@_zc%Z__un%J09%0YBqN<39pWPba0H<%RpdntcpXyp(Wevmywvoy`Nlr%DDZ|c}gA+e~Veq+3CW^VC zclG-AqH3&4+tB{ZhIb0CuZD@!BusD2{UKYwlK4R=Ait)e45H0qP4MBh7I*`Il~x>f&D9~sug59tQ-d$x%K@)lAI zk0$%hVf{8M^#zBsrK9;7r$JsP=xA{#x%?G-sjWtq$_KVzYc)8At`}(;h0qe*1X<5x zSxuce63K?4H*4GVA}VH+%X{XTtcG*c88V7*jMQfwj4v)Nka9brG>m}SK!!QCDONs( zC6ApScd!Q({60CVsnsU$c#T-yNXs$vob`I`o26U#m!5A55c;hbkN#eO(%%v~wT#{`YQw%_;m3?}4{(GzC~8dwRH zr>;;(sP`rH$Z-{~JNT*bT9y%T{c$jiKN1Xtm*4+#%|?4DdrtH@Kx61UVv0VkXcP3q zXd<=qHeDl7NfE$B^aN|5f~V8Da`9K5gpMH3(6NbSULFj|rpBp1N}hk<>)?&8Wa4Vh z?I3MiT$ogJ0$5}ngMz8tq|A?~OL5~;$L5K%`DG~BT-Yl){h29k)!AI-p6c*M$T}`qpPTHb%;Ytcqq6Mw_@9^T)=fac= zCz$C0xi*0i+8vz1w+q2{AZp0(g~F9yXYG?zandE(W{ z(O0~x(#IEg^@w`v!QPc>JCBpZrEj8lrLFGuJ;q%5QeI@ySxVwyaAHvWl+q0SvRZ_C z@P|);@^qdML%1~%M|cfm{TN;tVBz4hU&FV7w2%Zy!?|%Q94>0B-Tp@IZQnQ01V3 zx!Xjwqzm>*|7ki4jYia2v-}2mLhP{d2#_Gw{p5Qh7od@UXqTK-p#;(m zLghvMmf87q=b;-YB3<~Z@#_6G^=-kbj2KC+etsfKhp;X8(^R2Ut@SlY-I!vbwgFMXb@FCw zm32P*v%X^6H`(qpeJ5J9fU!ZekfU!TU%HtufJD5onS(E_QdzmKEq)$wTXZtSCr)!i zBOLXrm0Q!CYsBv*59lTe@O-7f77`=%tTD~yCsE3>ph;OWyOd>WClVuM7EMX!lNm=&1;v!}J;%l5rG0`+)7tu^dMOM%SXloxw80Nq8p z>&p1cRp)=jFg@ep>Sj)W?}|T8saQ6DOEW(qIEya^G8Fj#&h9(Oyfv%nKc~9z*fNiI zcwQ@geed>O>xaOf8h?2Asni4hn$x%{?elc9WBSBa_r=K-G;za*Fz}tmZ*_YUW51nZ zz|#HppPCVh)bB_efGlfIpdA!JY%Y zLSTM3R6rVf!7ZZ3ZyyRjnHoi>E)hNW6|ES%PBLAk)BD7^!T~@x_Szy!afrX`RTDM4 zmLd>;osPkND#V0)?`4Ey*D?oOid~W5HTTa!DI`81HhDt&K_d-4ilL=DYJZXIClGp! zDx1%0ag*mFFZT$G6&s46&0yub^knK}<+etO;>b*~;}~-gezc(CR(bgFQ%KIGq<${u zvYC%6$VBagGI6(7ABmP9iQ?&evqe@&MUhF%9Z}>j(sO(;VWewoQU5`h`(g_JHRNds z4fg0-OO1j(4I19epm`e7mR^VA)?3cQj}XN+wpcHDaOGgkSXSLSF$4dECqf{heN_j( zTL4qgH6gH#LZRu;ZaCEa6(BFLvO|jVrAE!RX9r*E z4hK{mph~$9=4Yr9pEhyAYn;esz&3SUx-UkOKF`kDbZ-MSZx1>StEBlb6*r{1uM*H;AO( z^0#tAvZYzYlV{ul-LcQ%VVHsoLJIN2TYXJCay?GFm;hMPA}h!4!_6LU@eRH_ab8CD zog55$*`W-tUP8TPWA{>v4F*{Vw;=U=RqT^;jMq!&nk`20oK~pr4+(2TGkoM zG8teus5OE&(VqFi@;$%bDXjL2IiBMK;JsSB!ADni%ggyHvMw3HM}iSD zj^1^Gh#J99@B7vMT8RE*pQry!+;UUcB7{lWqf&1EQsqMJ(p+W9|Bgwd`Bulf>CaG$ztDmRFK+BO;qfMsx3zxFL|eGiU^IWY%wVp-Aw|h~$fGgi zj>UscHtdJ|i8B}=*oc%--102Fu*gFgxTIa%ls}N_FO^AChPBH8-|nD%`>V(eAHkSoXA2D za@1pXbgPWfj^wX~I=9)WW^_9kz#{@#c|+(1XdCAkmgto&CuwPP=8&~^sv}CtxcsE>w%11+F7+d?|fs2Q3EiCF@#i&6Lo znWo{2I{mO)hnInj{%^LQZ7pM9`fP6-4ybPtm>k{!at@c@(5bILy!6N3^XyvwBvgLN zhJ{k<551D{++OO4r~wSJJy{K4#JDJjEG7hmH&@_#V{z3N!X*7h=cJ!mRLs` z&OI{8-@eC3O5rkZ;&$DCAhZ(JWMRx5wpl7=sS{J|kbla0B>Ox>XjR@v{Ynh7QCmqH z(k3<<5RM%KfsjzX6A90(KV=VL7IQUKMcD2x-c@xOv%&i{ZyIKcqHv#cd z=#RXS-|LONmSpGm)Bi}!+W@p?cGfSWvG!^zjIJ)cS;XGQK7VwL74RT1XyIqzABBC^ z^B3380=kv>{(1-)z1VyGbwt~$yb;HLHMr}Rx{GxpZBCx?#SRA*{X1l#;aBAHd+cp* z2^w-sH#|ZFoqVckC_5pppd?qUgAbwY*EgQ#m-6p_E+O39I|p9jD-nLAZWMoz_$8U$ zC4@aCft7S6NXKkPUcicubf`Kudt*obi{e1sDSNsTN2gTCxDUvOkfQ3RQ(wrOenfC5 z&Rc^&VfMuyVT4h0mh$I8{;|IwefTy(?;S1&Zec0+dIX$~f2`sg-XdQm51=EIvF}tD z4Syb9dGQV7Uc$8V@e&r5r|KV@l}r@#Se<$Um}^ojA}6ngWu@~OWqjn667K-b7tiJD zbjFdew}zCi_)ujagoQ)6!@!228$#vSBOz+T@>2t0*Onw>*p>;8x5Rd+Lp~7M2Z#Q2 z0@l$0;$o^nEwhAQGW`kVVo9NGc-qpGe-gVA@oe2u)CU8MA@q(EF8VX0J72f+0!#g? ztcie6)u_XJ)3Xtls!fca-?Xtt{>Gq$_}%MO0*1dW>nwrrZ9Jm|s$U*O06GqMm<(() zt-i$_B8m=$x^JT|iBJZk!`tYwyXw)#W`qC~*BaXr8zR6+{Nq6F0+1~nkO#^Dd{Npm zM%~5{s=KH|z))ez1%)dHK$FTO+`0LN>cPeNBbM+uLf<&`mxZQ78V7aDD(5Z_E^qKq zEb>2vK)KhJ-$01TfFNXfUSKY*IHUp;HIr@_~v#J;tJ#)2==nob&l?J@VO zf=6(&jIb3_Ll;0agrREUY_#pZknP0DNR54wBgLg0V%S2S=2~J9Dmr+KG(7AuH~U`X z6Sgm*ul&cM_MUa+!=Y1)pFJy=oRMLI5XNh;v{nW%0GED1G{xXV-|7K`)E%#`^RVN2=Vq86H{mppJx z-3R|1sn7+(Oc?~2dq}+RR!D5?rCN4S7!BC+1d}OLP3BF|wh&~$JbSSG8zoKR{&nb} z*t*6FrPPsn{bBUhUOKU@);#s5f*VE_yIuXMaTcd;_TNq&uFSa!BoZ~4*)dEFIY$I5 z6Z3cMSo(z+gGE0O0R7Yk-_4D*r9Ii;_I0Xw+a@Q??-W>Jn6SaL!!RA1K#6r{+Qfa_IlDc8sawUPEq33 z&bEjMBI5e^8^fAFwO#D?j+&eO7Bl}^CF5sqO6}53x}ZjO^4&y%S|szs;dy)5SAwU` z6&HiPGMQR5I1bVEYl*`RPBA1;+YR?qkPtHS8%eL_JnHDZairV++GNn;8U_W9Bbf%cy%W{i2 z4+;ZDkB7nwmGlG{;5_CL2NVsZAiJdpKn zbX;*ppd*d>m&{ng3He>+j=E6 zKS4l$?OYVSFhbvz&lUx<65uQ*iCGnt=UtqH)Y@altSIhXt_~=M;R=yBoT5}Xr??&n zM{EV|%bqh{6W@Z)jQ@d|SP1{|N+|cvX2o3M95PSWBmjIoaT4;4IvuA0jd1)+?PJ5za|QJa<>wa_LpNk(EYEg;EYrN;lJ!= z9{yX7++&N&!Zg)P{`W|t`a)b#mESnMXiqZy_lv^z70#KjNdmwuL!{Dww=K?-XP84~ zi46Qopc4f>!1{+>R{=sH32@smjJlkEgJ=EmN#dY1wz#@mZJ(xNT7KA$Fh#Y%bhr(c z)O8eX!1|fW4FL1|LbBV<7wi1E`2YSYp3i?RzK9)WkY~=14Q6q%jb{soz6xfL)Ct+E z8-83CmQz8(hriYjbS2kCyg1s4%42z|niE zs_P%&_0$rostYgW{pj~k4u6H%Q%j-!t64NSB5KB>REyp4PYyf?zmL^j4miesRET@t93;|9}3(zPb9hzg7B( z&HwBh^wK5KKP#$o@81m<6ZMV!yisHS)k#<&`){>~SiZ*Z1$W8Yk#yaRF)3F>w@+I? z-L=PvMf{T^68@*&pC_CtqBzDU`FA`Ds*@f~wPXGke0anKBFO6GR=o;goULCB{XU$C z`NR|XiU|gH!~=j1&stZoxC2eg8y6(zyPwI-L-4zUbOegx#(- zN;)WC?*ds&$LQ8WtGenezc_S|PKI(j)lZE$;PFT~|GRPCU^4VXp-AMa&w1p|$SjkJ zlhLyQXL;2%WT8E95xH-tp8q!%#KQBRL1 zONedlCkM{geIp@<50MZY2NR1YRFT{jQ7WLxKYmp0lw>A0qL@8F$7F(K8QhUpWf}V2 zGU}PpOKKc^ySxSuC;S0OD<+Jf|A~~rD3)c2!_&6EadxV&b#IvI!^f-%=8<-sNt2I9 zRl|B`98`;^c2pRqR`A-&f6BiUa#e8#=bHiv(Q9#vYR2hsvk()!pV^C(`_2Llh;!+` z(F>>jzuvuJUXuT3bG?4KsOVK+bnLY$%@k<&K{U= z^Wpq>pv`p4q|L?cd`&K*Qfvu0xGdiODZxyICXN>aE)GTr{f!c3=f85Dum9MyzZr{u zg;?g_=R!(IlIu}%!Dq^Rr^mA%Ezgi0l}+jl}^tTFb<780Y#k}XM_oh)M; zJJ}OspRvwl9s3xw{q9lU=Xu`uJ%0bpabVo{b)EZpe$Ml{VEIYEVEOlUQpM|M)eFT1 zn#6@>#53GCz`fj54p1br8Be6{pHpbeX8H=OP@=fuw=Z*^Z2$Bj$Lk%CIL*enooI$8 ze?2nJ>&RH3$q#dmlLexL3cQM$o&D`mjnch_yXRHvt{n|7wa_GPdJy+&Kzho;;X1x8 zI^-)Xo_G9pK(8vW!}l>>6>X!2ncurZWWiugnod+%+`W?o_?T=mjV48HbL@dl!oqPpPc?MFbL8gy%?jqp*U`qb&fvh%vT8f0Ng z!<{M_%Kk%#&jD{~l^YCw5><{|*gY;fS32X&Uf~{Y?rbhtPnohKZrs3}I+nKaVOv#H zKjfbfVC-s=`rY?ddBn}&4I#urY}QR=?C=jWz$%AJ@de|c0;Iq-y;I*2VciA3rU2b+ z!++_mYt?taT<7t3{QTX%$mLbm@@)!I;la0P}jSO`-jZSmWQ|TevWMg?j4wUVNopWvg|GhWRxVKlmUw7h3(<5QR;9ajXp3cweTy>yNf*zKE7$*AiGg$_IHeV1 z>n1mFa>zH0DqaP{m15Y?iYG?9Gbb&eFm6E|0Q? zk~zGMRU|(iHN2B|m!H`58@I_bbn%KbKeu+rkk+#qeC*wrzL9k)hC+^>47c9dGGHd_ zP@%>7<*~Xxqp&?gca3$8-7sIYywOFj%sSz~$_TK`KhF1~O#hE-l?VNf1&zZUrm#nE z6pOXAjaX=WT;4iN+!zOa-&1=kx1~ir$I=<*IocUe@?Q8o=)IMDsXpBqhXE?=e7f?Y|*1(hMAt90zmq&et9Fa+0kLF7~A>{(Q6U1O^k4#B(ow*;KIbv2x zMc>WY&t5{B-r2a3Ump3@F;QAI{359nThQFg^k#t_XSliPRT>0|kIm#T00NCd%@4=2 z02{OWN)V}jraQKhuxWAP)H^k~xxM+LK0m4*koec;IyaJy7@DSP0yw7EwA9^Fq*B%J z{9>5ES+YNy?*BzCj)oQncwk+5pJ74M2~q2j$o0}dD`8@@5pEtZMVELMP*iKeayv{@ z0*6#yR^!>#Qn@RX$Ua~8mSn31o63o&2U9cuv++ktc9K_wp3*7Tr4;s!_DaUol_Q{p zy!hg-c5|Ir891J#VnTAE5W8Q;DH9#m-@KUJyJi{n6KnbI@mH{M^ME}f!!7*AOVBb`)^j2e2iwT1xj%v!pWvFWkBl6GYsJ3OA!uCe z4%by5-^R`evQy?u!oki1sz_-h>}$UOWZ3Mm8RcJL9P;2z27;#ubtPBD5pA4j zF{5W=E*7budOSt}DN9-flfJqHim%loyRjrvDZ$XHEBQ*^p(gT7>_zd%I=?xT4OvBv zl#8}ArR@$U6ThMY9;~t0$~4We+VD1I^3z&wZ7MS*#09M0Za4wP2PwDvYn%*kW?6R` zzV++hlnix4@>u07OOfGRTKSPN0h?8_kEyvf8x>n&!bDWqd!gOXIH0y^jwMu_y za8k0lZkn>r*J;ADc1h(fxTY5`L#d;+@!RW9$`hBnF12kG5Q(cKxA~YN(Ccqyc@Fp2 zEe7ymn9hC~h0^znOez}-LYu#5r#L$!0Gyy=!>Swl$1ECD?dJx?06LLwOuCxZA8))A z{G>0yYOGb=HI`qKV8(j*(zBvbEfTTUPiuHJxyf_cKtoEZTE)Z5hx#M2z%`ZU$vv5R zt^TdH2SON`_N|u**gK;y2(_nwDxFJrb6hNWE60?{*_1fj;)=j{_H^ZR89eoey@7~d z(V&cTgX?UtKNL5m?etPDRt3%zr3_VTUV@db#N+flVKjonxU(a{)mn&8tV+Y&#ioeY zWt(aGMR|mH_;-myr_qtm*5r#kyt;uX$hn<%XrGKleJgDB_Eb4K;m+tURpb|pochsR z@8BPQq<2p7BCpcq6WsJ@fBaJT-%v`$ zc4eDT&Xza4y4CaUG&Nn7^162IY4(-inAb~D4 zplffh8+3@#5dIT;seREG7ht+hCt;J_IKxsX)?M!;;J!;o5jA5#*e_U@P@bH$ut=k?!3|Vfe24j(ENgu_kHiG ztUH(mOT6f%9eBbwP%xJLy%ts8WP@QK+jtz+o;&2$@w4ytt0A+^FkRu<*KIi!&^PtM z=AVgbHRku?Dp54^J=fjXe9%J?9Q9cTUk=r4>zA!bDWUwv($7J0z+6P82Ab`0(kWUf z`fqXt3orzX#>!Dl{z6k06g~Mwe>RldrtO{*YFbuP?&{p{$B|anEQvbmRnKBhgMds9 zYHV#@0Bi`S=2~>Q@NW!zF5{0BWLVSuV`9sgO7^h1rQBPu8_&wky%tp4m(i5_o4$h@ zm4he18q=~@sUPl}l-MS_WEE^Yo`DFO$|LE`+`_)J5mHW$B=vkcL*GKg-NgQS?HfUeabu?wuRhrQ2QtE11#cU&>}6G(w*J(G~88nCQ1DpPeEkkw9OFxh>#)lG+u zO)3Ajd>5#KjCj7uYKAOB2|=?*P0Y^fg!R(MO53(8eXvXIqdop}I=9%5;<|w8d@qK+ z0N;c7@^b9-M*8ujAeoJMHj~}&xLPUH(am%)1H8}!TZvON{BEiA%mmB&6C;#lVj(@u z-!LwuSYsLcFC~Shqsr~tWcDfPN)8Ybu&);vBuu<*n!n7I~`m{2^SwG%X z&RDT`?|+RUH^DPz#xJYI?`OW7QD;ENjI3y`EE%%r4^tBJU&FaqNpkZY3SHg<5=SNm z?|thnd`L}8#bN0p~Pqo;1e^x8~!PTgg_{JK2-s(52H@T#dZAMyPa*DA6Yt654G zrw7xoQPJU7tS_M`pOSVfC$vd`HZQYPz_ZVOjs*$W%NRAVXccn=KN92TxUzv^$s}C5 ziOS?6mb#?Qzw2V|vy0~6Gw$>itqycr6k$;sDI%R*#00q@UB&Z#5S^@*z0)rMqbjQg zU1?<<`R&+U)hZz!x0`Q<92drDRBo;4Q@xBBit0`5J2R8ENyTm14>=;&q8w|`$9&sc z*x!E6eSTHV3?~|Q7tHzVKI1U_pZv&_2h(()lnHvv$4l;vdQenE`kIB>t6$=La#Utx zh^4f}lhTCY^A!pc2-Gma3Xh67B6p(vFhLTIeTHuq@HOj;_Q{fUkLm?$VN~C!xyN_j zyaNSGV5;!HC{#V-X7Z!^)kOh3ol4h^?pl8J-}$IPE(EC#&%@c(hbMi%7?nyZSLA8ie+CsEBd~@V{~Rt%Z!Uf8_XPGsgZxWzC$JzhOQvLayi}?Y=3Jt} zEHCkEp~@?6g{iPj)|gowY&YTK6IDA+We)}=E`^0ETp^?R>%B}CX5%83F!x=N%oSB< z)qlX3fp;kpx$~YupM|^fq{a;Ldo)ZPB$9UnH*vP3j{@LxipMm!0(5L4FRgs9WZ{vC zZuO4>o0gQU1TNvfJiVJw`Cy<4y$4 zsHmn+zc{+wc&#D=Vv+gU-lz zoMScO=)qwPXl^m!q0p48u%&HluA{;&WfsW$w|ad|GyQ@;(jys(|C>J+ZJ3UwJlZeT zhedUS1Vv>{=^Ez9g*Xmxj303ZmMS-d)Ru!@y>=qKrf;9faqSx zfkvOLkqA+nYRpzC{#(cU>|ff2R;$Y+^Da+LD%-!C@V2tj@x(qjXtOq1_kymIO5Ja} z3!wGqfiyRtFctNGl}aRxjZfE@2WRXhGh|B(tbd!2o3tl>RV9`=wmUVj%&Z72bzonf z(F;s7CVd+OEazU&XFC~Nyw3f-2(LPulAZj)hfM9H=()^`oM(O+TGzgS%ZQ+Y&7}D? zkHiw<%pTX(qrB>`!11V~Z!f_v%dwUP*HftAvL$anebA|rD-W36UM798sO&=7U3w)F zqw&2_7$;b+=P5+O(!{^P!99<0=T?buz>@?&Qe(PD=gi>{zt~7y@l1Zr8KiL(2`}A zffq&Y)EO^Dr)9_`K+`>1ECTDvIfHddy8ga1r(9FdbP;Ix>Yp_SQKOId^&}@wxd(sZ zx7l8P5!h8O@7_9=jovhPcO!rM1&1vEVzDzqJ!^$+Gf#4!xNyR=y9EloMDtu1OWhos z4v+~d34T~jSUin$X3J@pWvxjW;RKR;J~vo{m!LW3>ktK!tDMb@4q~NaY$JXAE!gPu_8hv7~(bb6cBWpsLiWb_Oz|Qj-zlZ6p%1{EX ze%qWclQRV0)Gcn!fs0P@W|@mUc!^KeTqYEwSi=?R_dOY?r-CR$`q|`*ciwS9=fBCkN!h8|Hck5#?pdikjpY|8 z6m{`P(*e(MyZSdypJv|&ecWfqnk@9qzk1hCbWRQcPc1??S3L9A7oDhW=HQc+$;ceg zT(lG)i4#)8d?d8|Qt>2Lm0bw$o5|(RUw?PaJ(a(SxAN4Tw2}eVB1_BQIuQ}WK+dCK zz7<>V!X-IDGJ>*4m~qNA5tE$tY2XU=t9Qv*?SGJof@lLV*X`)?qCyJ%K*-{oAljO1 z>LaxWPu1}*5!L}S?r$UmzZjDiJ)pSH;$KXE(bgbY{a0;ZrosgX{6}G ze2$~S(kN9R4&k!pzm1V)RI<#(23eKEZicCWk>nlt{b2vxBV>_*W$o=YAl$I(7!jd!w$WuNO4d!eEV-IHcmM5plAP1+5o8+NoZzUS9YNEhGbvo7)#RXy3co5i^-O&nl$M*w%+2W<-_3I|oK z4CX87xG){wwtT>J_TKP8^Ln93iYrJ zn~#YJ|68!vFD}09gD}S|v~Q40VVqpwOk?dHZE!G-;PdPgR{XhwMTf+j6fdCm!j0Wd z2Uk?7fe$qg#*}Y2IUfivsd)YUP;pGTrHd^jNZqhb`&_(uJ=E+5SQw+}KKo zU78t`0t*1=&&FLTTqEYDDIWoeJ$jl))EB%TEd)w{IzQ<)eJ!UdUjoWBTb5t z?wd{qRoDS$;=iCB*p@dbNpEn4d&B)6e{?yRnaFgDSZ%C$Lg`qr9z}M*P4ma5d1X{N z*z)zeqV8Kn>@S8NY`5g@DF#t&1BKJH&t=!|T!T4th_7439 zvkglHUdzbrx`*i|GMGTzrQ-R`6{uC$PeVP21+-Gn>Ztob>w0;4Zw@^9VVzC*SW!JC zL9X=^>~8&S8Alq2U{fzmTbB;7&}H@?DJW|hE8LfX{{p@R(I&>Gvg-iys^&=@Wqk*CnvCrzxC+>5oYMi7%-u6m5<-Vrs zFS8qnX(f{PGuUwh3jFM_s`WFMO-n>%%4LCyHB< z3a5GEKkIg&`uMW?;t^?+U<-%Q)Ew$whKkQ;Nz0`&;+j2iS+9LDHt1+jtzOb{kPdSY zmz{n)yHJGs?=YuSBWn6+DrvhixTxw2XJ@46*haN+zg$0vUiJonSL;8)2^W|~am?6n z!|6Et{QpdV$M9M4vU21w?$4H%6gP-xx~DrlkXmQx0A4;+;^k(07qES1D;inGaTC+aKC?B{DQjpM{aH(+QRUg#!D1k(9%w5gN>BYd( zanVL{sNnTSK^nE*4Yzmqg zugC1|T>QLzN`=&Zh>sFyif5VEQGpOGmbn1~c!(07;0kPSjt*%5b>y_2G8f=iK+O6d zJpFO2iSgoqV^qr|#ZLTg`FS&|*91fSYk2+PBldEf*)Hc6%6yi%;osI zj?K-_miHo_t1q>VU25mCUx>awOoxb7C=pcq7!7yHL{wpTUZ7y7i*7ux6iyuZ;63t!ViEp7j5;d#xCj{l8319Y1W; z(UXJi@?L;BoX9J@u(+cPIPs#y*oviOfg)pYP4Gg4>?m}H<8@!X`pWS&2I1NO-q4kS zI=56^v6=;IT?pPA`MNTX^iEeoiSV<1m1SO=c-O!Uk;YC>XZE5CXmq1FcUsIzVRfc; zj7`fHB0;ZYvLgO%5W6WAcB{3(E?I9*1{ohIK~1RLT1B3Iz1XQ1_qrJ~^SaS7w-6=d zy4_wsSz%QxbvcNMp=%|OXg-+fMfk>U(<}3I-PKU`j z-@fhM(lw`C{Jl0VZM-}#E!hejSPA&AVYwAT2>%EBTSI9Zkwv{-1WbTc$M`M|z&8>S zvhZ)K;T7*DE9fv1y|Nx;lt%aq(`_bIBDSyZSJ$V))94gE$nKG%6TqgEzoPK$#(QIu zX}yUEIhl5|&Yrvk`xs%(?wF(E!G5zXxteeMIFw#7_dLBR5`iN#5{!MDbm{J(HI>dz}-LEGqt_4+D1zyyWh)lCg6J|lh zl(#prVRqWN%}R5(<~)fTX`l|m9{zrCJg75d zMkOTbH6brQm&uRCww#^w3<qr&1;4^wzjS^O8~(bDzl;Ur(?rq z-sLEL`@i|pUFbF27NBXknLOGR(K0siqIC?mH@y2;L{^;|v9HC)?9y_KOM3j?MM|N3 z7B%AN-rzC=(8(~yO1RgdKseJO6Gk(z^u=YxIz{BL1Fb&<(t8et()@2lKpX=1JL3UH zHuEls3(rLczD8E6%RB-B-6A2Wft%d>(Uu3jz3E}TVA*#-J{6GnN_K>4S1KZ+N;c&b zHaPcH(dcAKvoTJQdEETV!pV}I?R%OfKH7Bv4V0qFeRCtY!QQUAfM9#d0Ij<56;09? zWs-Y?UfgVn1wDP(Jp&DfB9Vxl;fs*I9PDI?Rq!SYks5&S3N>2|d-hs$Lo2wW@@%IY z=_pMXbQLyrZC};s%t}!UD0x{PqtiOp_#ju07X3tvi#=>XZeE4`b&rH&2rZ7E1asDE_yL%GIEBzm=es?p@2050vbzaFtXT ztqPQ_4F|1VUQlh|2A9Y?wU|n)T3+TpN;@tJ6TaGh<9EL@?IwMx1Gh)8LI+2%va;J= zg55#nO_3#m^Xd#OV^p3)Eo1!W0V^Cu&m_K|t&fnnqdFtJESh0Oe$8FN%9gA&Ouccq z0u59`c9JvNd2g-|Ip=fa;@&}fUTkV9188ZBuIf$Bg|Q9rtttFkfa5@2Xu`hZXPg0~ zzIIeE$95$YSglu<_78u%@AkD9C&~_tK2&ED^&AoJUHHsqty!h}hrH4y+m)%WPkLV<_~~5#8cDYougXTgo4X1q=oRA0;s_WS zV-_K!eR{Th2$Vb#yKpgQm(9dT?Z$1xLV1SeMz~LBblV3saf)AyKCr z60hQ^x#hy1K;qfx+IiiLiI=d;R|h?5SZJ_YCt=u#cKe0P%|x=yq`m9HW@$0`k;%jL zcYoU^M`tQ`pt~yM$vag;G-Ba?`(ii{iaH;Z%*a*>q85<*``lz3y!Xitc?B_;X-#dnHsFz-tKJmujtIRz z@#(p6uZ_VA#HrxBk)Pk61dO4p@7q>=B0I%)rGTlcTfI+i@IFw!G1mdokGcC(X6{XA z7~v5;yB2lUdL2W|%coG#5+1{(0Ur#^9QmD=}hg zk)$K;LJ1~<);eY%d4*dwBd2jsN_+mcp*8_3hA2&Dk1lV<-RiR`%WdyJbt8XefD?#b zegp<3!mz`l@<|no?f58Ln8Dl$z;C@cGX^t`1M3YFK^epw z)V1G2E#=JX8r!=ZtDigzgJzKX*T9^}!(316LRTgUn)|I>o~;Ar;~Gy2d6Wqr*lSec zYw!Pqk|}xH-5C(H(bCKElwbSHTH5Dv=&eWtO?mExiGX6V>bBf`ra~OR>bFP8C#gq} zJ`!VrHvUfuV`OXC)1&nL^fx<3f{*iNnc8Lu@r38O<^K(oCCUH-va>?Xia%j4C0+*cIN66mW0dix>a{KLF)=0U|PMUW;4 z3>X2ZsG1vSu6U~EQc>~0o_E>e@K$q4>($vb9zWd8C%yJT>7M6I++HbqUF`0u=Ez*E zEmDNWrPfTdKzFAt=>AO|5RZ5;JpwU*D!=~RI*;eg@-XJj(g3ZK)uOMSLO3|XNAFGF z5Tvq$UVxg5&JXUVangW=5Mp35101xL?Mf8!$#h>-IdJ^D!JFQocDT#&9Xh>Un8lYUHW&>%z6aJ3qDiyjEYOC|MAu3q-ac#eRlvir4~S*Pia zHku!yuXrs?6=}Q#vs(GEXHmXyKIDN<#1VJitYSUuRPL%`@%6Y`;Zp}+#Y?g6%8-Y- zpAs|oO~U1acx`hoAP&Ob>mbGmlqk9tZV4!M)v|NouX$n2z&=rzqqF$CZF8qV8ss~w zH$MFs@pxcA-&y|R>jPY8f?=H)bdthI&nP-h+`<(?JCIZo$6smDStWO9LZ7BAS03(8 zKLWqn#Ya!nj3KmxgDw!7m6@wm|*exaCg0e8Zete7~08l!amv662v}DDNEHA!O3kzm1}9s z08Xmo3N!F2E567yUYXk-uN_@Ak9)JOrdu5JWEAc<$2v;*?@u0VZ5|fzKfJlg=v8O+5-ai@Kb}q)0#0{0>6ebcs1xs>A)-Zt!pU3ZJxF>0qTSR~b1srt5~G{% zEgT`RhBl?;#D69Nr4KFY9t+4>j5duc66roo)rdzDm56#E+UY2hGZa2z7xL)=bM{DV z3o!Yza3#Wh(>2B&IK#FNC}!!5%#5=txmHcPjLax9nY~jS6Z_8(`%^ucKtfY)qgQl( zWZ+10l7XDL3o+EaSy9qlkH@vX!W|eaGSu_>3f$M&bKXv`oeAsTpWZsv?fB|B7^`d< zC|2m`YM-Tc<%m$oD|*(0A`Hb@+G3yWYZM)-MjY|r`yhV{;n02YN8rNsP2bUF98APe zj#|Rq8CkuRu+5(^+c|9PjIA?8G7QRUT>K3B;W_Lr^6*IGjBKdlbI8v`dN}*>N=eTx26wDN%C8iJeuH^? zD$QDUE{o3ucPDmM6X4XPO;&ph>FFWi5CJUdX$Yhj2;+q z9QbLpZlrLDbFPgFa`IS@#Sk?n@PEh1oF#@9Kd%`Xq|-S!VC&0^UA8U2)s+*s;o5C+ z9Lp08vpdBJIhHPv!`m@$L*U%sS--=!9HozNe(CtFu@fOBUAUuTCYr|_-!u0tJ;Z@p+i7j zJ4QwW_{y7+4MqSYkWdzK7D(f;aG4G(p+6n?w}S+KO8VKm{oB;t{NQ??b2DSuJFz@u zR(lfZ=_JPizL7`lE?zh2pf`}HcFeyr&`!U8-cjpt4PVVx&+FecAAqYvL0d5u;oq6o zly(KloWaJ(G+u2P$)0^5X){4&!ZusBsTjUz3p~E@AzoKBZL&PkHOIqQ^e~7Z`b(pR&hX`^@`*=4Oi5?1+DQfheS z_6%TPA>9C4IABs0wShs4PW4q|$`N1&(o1rHKKLiuy}#`f>M>pb$WB=ua{#hAkA_v# zln-+JIhvs3R-wsw}$;gh#ew3s^bmq**OE1UoWgJ6q1%IFAtM zoSXNQvwBc z7@Q^rRCXTG?@TE?xybi9T~}P~0|eeUduCz1=3@{6_NF5Zb}qwm&kXT-Dsp4%jqs_G zSY4qs|8QCZe9CZ5YL}1PeZsj%93GV5xSKm^wQqjjMMFc5ZdwBg5K3}n=3WPNvYb7z z2AlyMW?tn*oTUCV{4M(ywht*Fn%L4YzBtVt#Jyc}Un5Arcs#_m0Fp^pq*HX-4y@@L zGh8#n#4)J9<83l+kpU$GZvVFJD*3g&Ch5?^5Z-ORmn_^7mH;~g@1oex?F%+_0ha{W0;Biu~LV_OUUYd5Rxrr(-?ORIECb?f@JfAbpBtDe~!M? z`|JAV41C`fBgWHibSuE~^@Da4q63O+uAzlQR|2Tl3h`TZ2-#V;Ibb~TR^h#V>e`{* zLu3Z(K~M-V$jrbr)&PCs{^rl=BCQ!P-{Rg71(-q&m~R+gxUF$?6uCPhMplleZQ2pp z{{$t+_wyK(N`I@3&(L1@Sj-q*2d@D-*h$yH6L84SZ^6kSHNQl-GLGBWUMtk^r)p_V z@4Z~-FAGyNem_5#Lbr3tTu_5h6*+glEqOvKXZM6kQLi_-2CUny1fL+q&^Dnm-Ei6N z{aL7R^Cu%%Y0(j^CLetCQB1q=(nNPf9*P?rw5bZs#HDQ#OL{oyUW*R48J);v%GZV- z>@sPo?qRLc?gmdxmcR59@T7{Bg&hLk zjDfA^JjO=S)kM_jTm?eEE5xEamc4vCjmdmMC96!)A(e+Ny{vTUeaaxIjE;tfN%g)4 zM_v_P1KLSU_FsVV#mYR9ou!WCXHS;bw~Nw>Xp}?rzW^0)`5Iu3V%HApic7;WS*QK; zH2PnGuOx#qBh+XgEc;hY)2vBI>M+Lg30a@3LLSmg`)w(+#+H*_7W~E>} zp)%5<;ooH%?LKgrsk@i_5BW}t8$a&i{6f#k|8cgWuTg<+@pdoaNQH_hu>A-+CPaT1 zupHv7NfrBX@JeWbpTNeK>l+{%&Wc{>2#?o$PFQcx2J8+L<&X0ZcJb1to7w&5^ZkFG z+h{Ly$MJzfjPkF97C@mZwnQ2gXSH9$i`Tmvb$7g>&=jxU2Zw0V73(}8t$%hHZcg>( z#cQ{k!matYl;>#cG>X+<+EjgM7aqrk0PA|YKl!~+la6`Aer?My)=TOJa>m6JJZ)C) z&+pGR$POxQ?AnbB!~>nW2k8al{XeiG$ZVF~4}dyZjWr2FBhmKfoB<%Q=x&z<5MB<@ zW99#?ECBB2ocDm(K+L}ZBgy+$`T@bH zB8!<25L5z<21uEzhYlt4>@GHc2buxLutAStn{v-DTmgV$2zO;}^Oa=moLvkU7!3xZ zo3j&vF7!8yRXy}DI|$XhK@U7m)9W99_!}<;pNi0Il^CH8)AlfbsrEkD;LrE|V$;B{ zK4(q_gl&7xNFf(z5VCC_|NnB`+(kOpcWTSn@5uOPf-L!dabvs7C3=D zFb-e?J-q)P8#dOZ5BT#jbJSZ@9POG%mAG{kFv)h!B`N650~Lum?7f(`*FC+cVhHCs z282iW#Xz7x4B_<=S3KG&z3}?dgKExH*+~||1lO=nH-|$Ka+jV*59DGP7bYris%{HO zj=IIZT~=a0vlRRD4RP<>k3jE_KnY2Ez)DEgS?*}UcRtTE+r;cQ8zikanUL zsj>PN^9-pQ{AVDKwiO&sdeb=Z zxjL1UbdVrlmy94>nV6j*39beqyQ@bh*gXte>eh!d+z1#s4}43|;CsTu2{R9PYu(NZ ze&Ndm%Zae@$&Dz4 zxF^LuvvknwzmhN9W&0kQ-9N?ca_G8Qmi2gwlbUV4_!ze53VUjy)41L5BMX}L@1F6i zKdRDQI{bz5`;h-6r@NtDV+j~ww0%fc&S_(Rck8dS=_Ap3=n@Lys zx0*?J*xK;2e`hnSb>Ich3I$lq2>JDJy9xWN+-!KXN~ybsKEzFc26OYVH*-W+S&9<& zG6|7U2t_Tvm?6;*vb^8J!Y8dgDlMnBqiZ#@hhxO|m=7Z@U$HK?o(OMlw5SDeumRPP zHgp^7>0e>(fwZ~?$x{DyjM@Y#+UOZm6^${v=*IJ*fJeowU>;i!yca&~MwEA}ah=gj z{lekW8;N!E++J=F*pi**y&bmAL*M-G?Le_;7oH~`a_t&|1fL1uSgJe%xvj;d`;>r( z;&AubHM?T}5T946UMD>s<3tLt#vs_R=Th>ldqWZISoye{d7G!BzN@w?h!ynuy}Fs_ zC6acNzwjBG!X zD+`}5O@@H4P4J!F3*lq%nP!fudLrriJf4*DsJk`vyM8|huXjO{YjM>Qk1s{6h)+6` zbj=F6w$v)lpmYNIGZV;Zmu&gN(q1_(L-B0EuZLpr)aerzA>5W4Gg7R))*P#G#zkB) z0U5flyrJ!?w)u{c`DnFCi&8G^c%nr^MgL)IcnzQIj4^K@UA~^|L`u1*EDu|8*3p!``TN8>C1?G;*+3)eBbH zL|4VdgMDVug!D50;h>MDQdso%v#9qmtqWZD_}E7*ZIp~B%2{h=Z~XRNm(3)(hg<2A zIofIt025?$iz3fzp{s`~0>T@ioNQIdstwtHHcm(FmBEKDK}I#UJ-#B;3dzAygX^ZTS-=H*xwWirba)0dlCRpk^G! zS~-$>OnTzNllFq^wcb9H25T#|g2Kg{ic>+A)X7SpgG$CN`a988t9FT#8C9z}i9I#$ zVd3U!DNC^LrMmszJ~-y+>PET*@QbYhvyObyDI`{|Ad3kmAK@FUu1BCAfDClZhd}aO z!=HO#JgwHyN{e_&p`SyNwWydPEe2^;E*pq;KANO%n_r`*c=c85(NSwH6peKj;IfO5 zT|U8nA}#hDDc>;B8``ZX)?JOy*j`P)0xwrhL}7!Bta`(1zh+#)l3 zjirZ@G2K2K)Gm_Rsov!spft(J&lK_D83NA*zXqb{j*w%|%<3HmW&5K1i>QD%w;uT9jqe zuiVxEmv(L|pC_u&j-;MH&f3V>?$R3Mk>PR{UY36pFw5a5AD_Np5 zwj!g_PNT-{5R>^PtAqGVHNK(8i*bVan)&kDIy)jZ8o{fjWIV{h>qD6-)SW8e^E(t_ z$p_`uxVpO?jkF|dyW3U8Yy+w#%TZB+I2hVad>-%|hn}i)+{KI6lU`cUw{>tvszIYu zqRBtP7}Gn#rGTo`QM?-8Dr?d=8&mfoU%b1T{xKsYc&@>OK_ek9e;iu9daS9zGFZ5%{6VY8TMa3Lt<+RIkU; zUJ}q;?tN>Mx}i))*4K>SYl}0i#Xj5>qN1n@9Tc}+U5&klnuE?Y6KJJN-MR5%dH!AF z*}aUikePh({=F8HT37{lh@$aF4qhiMV=b7oQrj}-8KdCXw?QcPqO^9{~&+#&#&pqO?kqZZ}c?e!}4xQYs(K*S+ zzCI+`z#LP2P}{}Wb~%E{1gFrJ{UIOPo^O=Gaok}EzyQU2QS4=L%3vO+N#V?hv;7Qx z6CH}M4ZAciKzk5$;QVixY927cdoqmmgiA_C{y&{Wn}%n%Gr0C$GOf+v{ljQaHAql40xp0e;l4-iOfZ2?&7-( z77dqu8O^4+A!*VR%*)jr$K14{eEBa-?X`}-pew?}0nthYg<;9xs5G$8o|RFmBt-;q+X{=t?6Yq#+=D2Cc@xXq5H)v~(>4q5imZlYh7|^5ha4uWl>- zh0jihY1H~&g^dkLyqB51jMoDtN0%Dp)uj{8VN7EpuNAMp-;VmeJ(JIeAxrpDb4IW? zfh^h-(6FY^e`0#BnX^voKP#L@zc}%WOoYB@HG_r>Nul?c%rT+)R<)2j4dp8h99$k@ zKGTZl=2UH6-@j)!*HXGm*W(cJRewgytd6CD_z`}Q-D+RHkvd<#>E;%>(|`^*pK!5r z8)1ZRY7q|M>zby}I_kE0R_@;GtVNA8d3wdHz=2(3Eyh_QOMG^9q4|!LF2(2AwSBr3 z&vmQLxJ1b>@i}Uxs5xmc$gpxh2`lOL3&mYWA$S1kf1*Y2rTLTWv9(nwFNj-nU$W2s zWx-g-y3V`n(>ij^9Dj6z`MSCE-rlu|yP`@*=u{uOHrW>pq9tvt=KaAe2aU6$RpT0 z0Nvkl0Cj^u>lQt8a-6||OO!nwef@42G-NPaVV##zuHp1)Zg+~9>+|RQ=VtaI%-s)) zDqZVls%Khwam^z6fX8sF#nujY#mG2UFn87Yzw6elD5+vIZlg_+u2X_qA_HLS(@26Z z{?=+xXCzGs%WcDd%r+z->-*u-Rd{Y7Vf^Yn#hWSHFH2+D$|_VsW-^o*W6A*hpR=zP zKvLJO)0V=m(=Gu@>a6&$l5+7^T<;WdiOFEb&wLS%aaytkG?o23m1%-Kx>D$%k_&g` zJyE{PB3OS9zN$kllOnH&#kZK{(pjXxjjypH^+kQTv*=-)H4wIiLzY>z2<*uI#nyl< z1t69M?%*-1Xy9ov`v(F2A*l0Vt(fErrhYD!(n>pQlQIajQ9UvMBkV@xA|C$C-{nm=A z(E}9`_m@JyWglGU_2qLt#QTh&%OeD8W9)plpUH;3x}nCYfKl#gK=I*vS#*TwSzl2N zM*Igg`hr--Q}Cj@!Q7sp^<&TQYzQSLOtU&c318P|&0}N1u$qG=fgkvEF;8MN2tofJ zd*2<^)VA(x1uJZ^AktKtf+PY`0syl8n(@2NX`514wDUTX8J~!1r zG+wFPg{i+UhEX-d-*EhHUYI(f`Uucs=EnEg&e}@Id)4;WVm?v@ymk);!fUTu-esIW zVEP_#k6gXYx$D5Ms6)q|QBy3c)VXdf*w@mO0;zm<=T=Msh&n4N8%}eZts0h5x7{^R znSR#+!42>pYTsYuYuK9`pIv=u?0mEq^Tht6_?rAa@DchVh>!KR@+Jr4R~U2S-nECu zN7(BzuaL)jPfY_t0*35u`2O)D>E>MTye7*))!d$a!veexG~IgFg`-tE1M}0ta5m@N z4u}w-c8nQHL!JDKi6V&&7_T$JnCFJdnCC;ge&>8STO=+_FA`T`eP~?b@lo8hj0>a6 z+-wTPkCCX1{Yc6^)8Ns*{HVgr=Of8}_8?9f7(mGZ@l^Ox;!A+ouz7zO0?$fhF!f!+ z=EmRPuScGb{^k(U{IvH}IyXRqqzjnmOOua`e=gj{L+*;iaB2$S0LEAE_(zh!%_5S$ zV()x6p95`M*dj5I+3(!n``wRG?Y4esJav?N;JoVr%=4*+B5`NgVEFYa)sNzHOmkq|KpaiaKa%d90a)%+vu%;)*=x95Rr_MY-E{%zp1 zYj5wVa$tUMwSjJ72L==~k2%otgdbLzVNPRwnZ#;;=&!fk6#D{RRQ9|`T(9f`rrr&B z6hW8+E$-A84<`o~2bvdfp@-*h?@H|0K$;UbKmyG8VZjLp8b+qx!-+|Hw|}C1e#!CG z-czrEhxr}CoLN!tytH^Q)l?H`-1;$>929U;6|=s9LbCIo=2hQ6xc}sxuH7f@d@?zv zYNh{MpXKpA`%d)jwH!Xqalr5ZwD-DIynm|f@=ziP-d3nXQv?cq*S@lxi}bTmGFza2 z=*wFwWkJR{?p?b^tc9kB<#+9RGJBxeXs2n{)EUiyIhI|! z%KJ1nW!Zpx$=bG=+b|< zWmna%KL^`scw+j*Qv4t8xdy)W=b$?cZ#mBz9{z`Wz8#Lt+y4(&{{Q3rwH*I{b^cn5 z|3_$NFN>0_`d_nRo{eluKK%BPzV9Ee7J&D%uy2EZG5fE!C$oqDFR|T`^~DI*Oj$m! zhp#Hv$5h^hO14}`|K}fhHh2x9t{Rus>%0H-WAz3X{wyF^{`U8OO`=>LdCn=)@;c|Z z<;K(TGv_qhhu&R7XPn%q2iLrYqS~7##B9cUYOojno0>=!5dtBoos!21?N9{BgU+7ik@+rq(2Mxh9@g{UeI-tF!Oi+64BA)#T`8F zc@PzP8s_X`;app9?p&+d0f#wD0Ow(~`#D2^L$%DMw*J$8PFWUC*d^dNL2B5~xt9|* zcpBzIw0gn0^RKA zgdN%G9q5qr&oiJm7%(Dm4LAdCaH-9-F=4UIeAhQ%d(8sZ_Dxb&jTY3Hq`-O0cnuPs zs7PG*QUsNkkNh6;^e~78RDQaAWbF4p&dhYsbXY(4SZ1I}CWbfhTGuS{@1m~BH~nTG8gv?$KVigQ(sL$9e`kvSY}$V;0CW8_ zMNG~&8`Z0n6sk)c<3K%%uhubUiRL?m(#P5m2*4xnSc+G|&I|3!=C} zCA##?+c4WF3iUnp`JKIjcCiOuX)j9eG5mT>Hrs;av-A2~fCbrkPt3>sC$H3pAjD`j zO7^i=u#ab%@;!WiP%^B@E0K){e3)p-hFPs@_<|p61bWzy`gnvBmIoYzk}&6@za1`k zV2GB#9pZKSImLb+6Pws0-+m-1^PjjNoNb$I?NMr~*&;W9G%9po3@zsSCfQu;A}Q78 zD9puteZPo{Nx*r0KZ*Azkpl!@KLZdZlh}bd{n`9xmMS^2G(mQqXbB44b(8zs-zl5h zGKvhV^kOnlh7XAy)#}3}*?)0SoTm*rqe~C2{0b9Xe1Nbxb=id*PZfVn$e}F zW54YcE`20nROr&jd?jJELJ$_z_-Ru`3U*hL_nFa^m5m;IZUxRR+)#L#_3#D6Us9c8e0u+ zzWCIw1R&qP2>PeA{HLVnL$Lb9R0}P!$G2Z_|HdM-u^L>h6WrlnYC0hAEA!eN>$Uib zKfO?M6~_;X|M%#!7_=8;B0tIcI5KhZftzu0rO}_NCX;CBF)OZ?{o`?Hb;H0Nw;E`< zC6ju&0n%lXZ?Gfzr*LMHumNyfz=i!3;N?tO29C5TnH{;_FhT%^xpGIU;!K9UNX7N* z@qE{M9y)#>wvXpNp4XYjYOBHDl?=*bC7?&@WY!CD)I)Zaaih$o{Mi>UCR18=1H&=L z2DAlpI0L5sU=H>7W<-?hGbi<$miiUVJ0Q8S!r!D`PVyr1WbD$Fx?%E$N|U-=&nCi z=YMQmNrK87+V4i`+KaMw`lZJ|@-MWKQPsB~6Kbn{BF_rsNw}ON5nc1y`#VeDrNei+ z{o`F4aPKVaAMcv@OGPuq6Z2h^?r80D3B_s2PkYD;Gr7%%Hy7F86$;x7pv?I{$97WJ zUw)I**9N3NuyQLWcOO{Jua~Rn9y5j|QUsFQe_30SVN_|CC3AZ&KVeMeIqRMxMlXB2Okp z=SsNrT^4@Bmvn{N^UXECr+l4N7wGvHYy6^mfLoaS^9P;(7md>plm=QR(oQqR?J~eZ z(MqrRn!`_D`tn?q-x@%^{xoN zN#p){!@e#-TJK<3gw4Cv2W6$O*;W6mhXFCgXqouDJ7=ImE3R7lx|)&)>Ik3Q9hR)q ze(eI1OYsz|wtk(Ar8^_v(m_3WW**I#D2P_ksS5JM_f41Sc8K$sq}_}vr{aqS&oVP3 zT3ak6wR`Y4kp2KTY_>tI4Z1AtZ09&d=1g16vhRKUa)u)p#OIk-ijod-zAc7q15xkko)|=4Z1=t!cVcK4hzLF! zVs*nOG!&JTmFo#XyZFgX3WI11F7gx6!Ps+~LMH*DXHq&-KOF)AHtmlj#oXPsKCPG- zj@Q!(Ek~6$P4RVD`f3LU&GY~bi?Vpf*b6)K;6(Q6qsbt~Eg(V%t08&mQ88>x>z zRXbN4w~H6%1NZS3R*F4A)Dv_$Kcn!;fb=O;GC&ByzG_ z2d2QL=0w{qh-fipW;XzurB z;d#*%f}=%evr))&ICN|1Ud@HUi=2g~1Gsa*q?z8|T{rF>&&$GjS{cx`BY?H=pG6zA zxK2}o6U?{xmuy2-Pw9%KR-J}+4SArn5*DNUObrCZMcA98;zaG>Igt%B;%I-;5%1}s zheV5}hu(Gw)dm;GBxKOg6??RdRF+dHYW?VPhpAgoCl;B58l-$iObFY@&d$10Hz(G! z#x3&+Ca5W_sW3d*4GU~T`Wuw^Sj!13$W$Z0vsye^t0fWicZ)XE^>YQ0nLi5mKr zf;!?$@tNI0*r-jRCG`eFW1sE`wHbiB|MIQwrb*ccTEbDVw%A*3%N@_CZys#O`qx~L z&4Ny%o{49H*PvGnE3UXIrwzWLT=>&O07S$Q*e0L{0k?PXC26J$HqhsRh9}PF7Oh<~ zArUdZyC(&*F3ezv(<^2J>Spf7_)?|Fqx|o40qO^A&|8yovJ14^F;(znPsrxKin6?E}n#t~SL9^TB7{SBn2FJSPY;G3{SagD;&$Wi|0j#%Xj)I|qr_!!eHPpnl@& z9IA<*%f@N;0cU+bm5KyJ7t`5dT1BWe*jRJ_*nBz9@Yw~N8G04T39o9VPc*m(DIsmF zk;C(-xFna+@>~Ai_h(~gsjdR6f0@ouGiR>1`(LoYZsk|yh2hXI;^Ln)7^Q=rx<#HN zo<1(&#+;5Vc=MVGFj#2ygf53>DCtK>K>;?YA9Q%(FpYn`&Bhg{vjP}F0Q>O9v`-LM zgOEWYdaK^rXAsh$uk-xs=1{RRiaD$h8MGDUVrp85+ecq}IeTH>uP6ne=TO`OLQ8T% zPn~Xgm%$!eH5xlAIBE9X9s;+7O`{)7X3-%UL?bP;Ig|yqE!{K;9C4gab*AaYOH3T&Lh5_XDe&=~voMQ4XTJ7v9R)?T3wg8nJmYtT)e(=ynx#{HujkI!o#8tQe1e`bHYX zcf$C%W!HBFUFy;3a}nMYpGEnc$4AW%krt(V?bW!0F{DxVuBRcg3UFFM^7GPWD$qq&)^AwpavPdx$7lYydYKOw?a`Ca!#o5+Xsib@N;z>fP z>Xi4zpk#h<`IrC7OP{p%3=*`LzQ*0L%QLtz#5lW1lOTHRx8yPVedvUzj@pg5Rlv+R z?T^pAq2w!3`HoA@I;zWT3WA!fDz>Ub?2QdmNJ$ozo3}I?KuxiFHHW^RwgA&M;6MR8osI)Q;3jr-y+#>4}6_i0} zSR;nOE-$_9=g57|X?!w!K!XRIEt>JrMcraTUDCVTF(+8ao(yg0+GI^bPw05|PIi^n zqXYccl*7N!RST<%+W7m?E{*H)(LHZm?G_T0V!_rT8?B8(J7VuQ#i0g0hN7cAU~CJCoz1?O4RkhE3Pi6O zer^^SH9c-4!_wSj#}6gtcx+Cb8Op`_D^xTosI%$=)=zpn?dzuso5U)yg!_7I6*VXu zi?;AQ&@I2p5`TG#K^jJ1s4!p3!m})okCzWYXy|vY1cVWpVF^zQ@r<}vKHki>pq`aC zB(};;iZ7)O=Oz!-+{jWqC2U(Pv0lVE5!2G|#=VHV`#Y{*J6sIDyuUdI@@-q1N@_1a z7RAtt+x^Z8!3&@ojg(iZ?&Z&RbT?D%tze*=@ul*sL=U3m(QmX<@5`;uSS-r$%9)@3O~3G&Yyf&!RJ{hPNcj!1)U>0fxc;N9NL)o`4YqRyqTU>OXX7@ zzlfeJ3Z!L2&jmNX5s`rr$C_!Ms^r2MRwC^Ul#40TNT}k&NG+HdPq`eWNzrL>d2}s= zBf#+vVv9!_j0&12@0Xpfg|sM{p2zpL_06MH0ZrY4ql^Xgesg-unktnu%)%A`y`?Qr z&UCwuGaD>=%gD5n*H*jTzKCL<*RJ8&n#&ADNPKT&-Kz}u^&*6Aob~qgg}c^xrFzeD zvs=$08ozhhXouB4xh}ai>id~`5Xx9KhxdCyJaOObm(SVM?6U7(RPo zY8QV_bX!zhW@C;z&dl6uarvD@5T(htu+S*A4@`~NiDSS%?*wNHYM?9erB0igdSTPi z_;*5WC}~AgQ!#kXoA=P0OABF`U|qsOSXl(>LH8=P{EAoVxn-KMNr&({?~mHhjFAya zT+6%r(b5EP&$?;8t;cEE*%%?o4u(V7fKA&9x7_!0hWEL6!TH9fYjhF5!eWI^8aLj< zQdzx7@`qnibF60)#(M69PNO9^m{XL}#F+L^iT$b`=miI-!$oEa!Q$!<^D8<9=)_F}CSFe(4QoB9UdhQy;d4(sT0r_Cq09i6euZ6IJ9s$0O z!LOs-s@!c(^4br?w%?t%Z<5m76Z*P+gf5aD=yp}adZ{*_Yj{D{#^zSJig-(y^Yk)^ z5@NafrZ?=Rr^V8^{X#RY(huUdIb#y;F9UH!qz^kVGBVE3j8QwwJySvvPF;?^+L$b- z%XP@0OJ(Cy2EzF*F%~vAP{&!92++Qn;=oC{#p00Y%}hN^)!5M6qj6E4C`~))X)=ux zuiHl-y%&{OQwuJL(<@XWfU`09IeOij(L(XHf#B41Oz^}~R$?oT`k;@p>h0MGwZxJ% z`RP(}(!&1X=VhnKmUW}yjnHXW2<=UUSe=k$B5m#NQf>7ih_}3qXAg4{IK=I z?`~SX;FIV!!zKIAIA=RkMaQzuiEp>!M}(iGrd-^3$)-kEZJf_Jbg|pXrXt`ySFr}0 z&;eP930|<_K+<|qiP!2P z(vGwRTj}TCh#r64!@@A{S;;ZV8CDdN4;)*&h-P>Zq)CEwYx#iJ9kb)4h)yWqtjp?p zV@q6f$;;%m(5@vXE=m*Z>KKCqqJ9h&-so7?a2Pbr_!)HCNd=&0XE`<${YI`_{BDjL zC&Yns1vKAZUs@}8h_M>XgyUa_4s-YDPw_h^AtAokW<0)z7W9rWhSt69(a_EpQ-?GH z)vGUYi|$nq0eBU5=+srdAYTGj=T5;!RRYaBE$I9GISa5ivX(z5&#YQbU&wn|U2Th{ zx?C+B%NVO?@b8J0EHNNdY^DU# zFGy-SaJgi6zW$28Zs>gOYCo~B`1&bGTYZT7)@lFSA9@(h&3TQP5xA1cmP(H}!9ytm zS9Fy6a3(WG_MKF>mWdGRQVJsQiWk8=z)mbg(=~ot(0gU$s?WU-t3+_rvy28UGZD&w z`;LRj*NK^ZKxwf5s0A}lI+orGkvG{2M|5&+b<~+}A#)OrV?2koF1jlr8XzA$kH6o0 zuNYDxYkJ;a>QNC-7!5jSsA|tG&j+q=D{EtI8{*3aM}@_F-sDtLe(e#2STv70(T)W> z*mv#8ah(a=abMR40hcuydC_E~^;(rv!Z@#ez#Ind+4#8_jg=;X8;Q*Wj!T|Pk0D;d zA$Y8Ab21OzLd~Jse0XAuvg8;yD`-)f)Pm9(D?TKADF)+JQ!=5Zm}&-k3C1ih*H^4f z%9-&vr-oT2BU6OKd4CE}OJ(uR=U)PHa?3tX9|( zkwL@7U;8hbeK8rU3Gu0slJ$?uH=D^Y->#cBFkb7KDFmpP^PW=s%snlGk$}l@#C@^- z#Yw)wPh+eo@fnL8RSQY_$XK$_kJ}W4PE@7)znec^H5(_ZCYtoz5`N>SNB<_|$5v`lJpP!73nfs}dvi}8;`_sw zphj6pdlA=qo`YL8BTo=pGNFSvsMeg#H%n{ozrHPHJFtKXk1iEj3X)1hjNl>LvYF`; zyGJ4Nm!8ibrFTUzoIv)W@+EK|nLO@U(v&>hG9}%pPsu;>h_}PDP=Bk0OM?lie&ObV zVW`>Eys$Ou;22xO{JROsTPQ{D)x1hYzz>rPa6Yg(VI*Sj+46aXU))W`={rxqM`MWR z%^$j=$dOO<@$?V2H6@esl(jWZD@qOJ^<8>0vTvm2MsQ{KC3uOzMr+Peh(E!Z+_ z0?awr;(Nw^UH3~@!)G}RFE(!Qeyjq5I>m}$V{J9M(2~OPCmTVUEi1#-5eV6>6Re>L zCUjrvupnXkg{bF3*Zqlz`&HM}vd9auneLhl*RYtyTWo6;<=^LGIvS@Nv=G7s;} z__U!&T0pTymu6$MZt;sCmD4O&pbZR-8)zc8z#}wdiu|3&YMOHaDGkHWhgQ4~zK^Zs z(w3xcdkX!qZ0zaCF)38wdvspGxlaty>Au&>+O#A&6p=x`#-AO7OBKILD7BZDH@zW0 z#~H!a2*ni5{)(yZn5ZxKQmrC^YJ@VA{#zN2jp|EnuQMo>mSf;tqf+G%X#TjCoB429 z+h_bdS~2>euN5@etk8XPBMpDHM%0@kKZ9b6yT0alpibx=3;xIgOa48|d+X|D)?kVy z{uqUanwTQ0&$r^Z`8)S)3LiLXAIaU21!Csf@O(8e)mZp8XMy#cDcLGgXFfW1K@n`B zJ}vdTG=y{z)tNZJ1wOgd7xIWS;;9sSFWLEGJh`>twvc@tvJaeEGgkt!xVI^9=Tv#3 z)ph$$RM8Pv)$s@;AL{gxRkxaqh7jxvkawHx5^D=IRWHk;EqOpFBw6{CA~x#^)!cTV z19AWO2G=Larg8&jdiQV1=0&T>ie{7a2~wEvL{p9f=wyd4rfWvj1=Wh|1Mx#@xU13i z{#|M-p4KLx^#g1iYs}c1+R6ec&$N>lQ-18%Q_d2Z@2-5)B-w=H(ETDb%2S#jQ`Sk{ z59P682C;nI@n=~B1Bl%e*GfYzC@l91AO&lu()RkV*= z`S3`SqNd9VQbszxT#RyI2u!W`UaSp7q?j?5+(u?H3B_G!^@QqGeASW@C`>>pO}T#1 z3!fW4S0QsL(lhJo`J01%Pmi%Q$Ar+`D>#uN=SPdDZlMK+~II5*T5^me0jY z6e}ARkFoX>Ogu!>Ty8E1ClNHFT?j8eyb7s)%pGhzxprN*#@2AFyZ|4Mk%!#DnG(hQ zZ)dUnxI4bA(uj|1GC(_Rd5*i9H|9P{JRY}6sW)#+re9rB=dIF~qzf(csP-q7Us5#g z@my?}3^hnho<+&`DJc#*jU@5D3z7Bs?1UW_2oX(3I`U7sv}QWSF0%?3DuzubL2VkK z{99N+%ntc7BYr^XMrJ^TprU@M)DbQky49@e#-R_;@$qRkSU*t}>C^?D6~dNVUFW~j zRKV5dB5?2{Tyhx8nNa?&)hS(pK@gxlHr0w!u;0L*BoN*~SCp>ldlCSb!&++)JjB|s zR>43AyepntPzfmIfp;o8x;0PxRt|)*QlKhg z$d^x#vruUYwWaa<%67f)mcJioVRaQU$57%t!7*2Vvf|36SQotlDR;blz-@hyM+!y3 z5t}L}gJMQtEgr?mUW~~rcVE;(KVpTp2#Vq0Ts9%@vnPSD?`8!)KF~Y5Y!M#stTV?Yy_dB) zBW&U>kTZDneQw}xgtDlBx^gs<7xGx;^?i~vZR1vvm4!faza~HQ-b)5rAo@sWqIH>B z8Xn2ec+m*^tl!v4sco7gYjWEI;@pvBV1vy(T}BeJFpU=$b1lO^CHKtps47A8hPRLq zAVA{Gom#Z@fZ%oUjnyI_U|isMhR=9gKS)w|p%Yz(x)fJA!(j&%Z;bVyQ$s-#ONwM% zul77>cDA#b+wAGUp2=xzkJ35S9vNR4+AQ}{Q>6jgDVhD_vohfV75DnuSH>5`1aF`Q^) znHC!@u_Bj@a0}eZs}nl&H@k*_07VVgu>x_DOCTGz`N-~0{-8^%@~-`3E9gcl?#n{o zi_$%K_?Bu6XH`e`SL4^dSmtx2)KH^N`V5}7ubCxh zlIiIfY8y(f@ltd{MiDoZID_)&1QkhKma2)NG$mKf`FUSCn^4Z@r$d0Wxavr@GK}jI zhst%ZD)Z{UfAR0nOrF(%B+VAIN#6|4Gka}e++UOGzi#O5yJ+5b@17_H{}>!hY@N1%TDd*ELJjRm4Gr@W>K63SA{0Q+rO+Z`6*n#&>ptNNvR}!%d@X{14eACFt+2x&FK&D?Oqmva z^ReJcT{?)ipDW&7&9#YF=PFpt1J$xvtnV4#4<&9&425~Ezl>?MIeBq$kwb?lj4N@B z5+bKd=^n>YLGhREi%xhoc6&%RI<7<~DzYGYYubv8omJFFY z2N8{rfI56aYK4rPBpA&?33>h^2@hQ_qq1(tq}41a%`w{IZrNJ7V;g7=)lf^-I9meR zgp+j^m4ed`S)mS^Bs(|b6Y{zlzb{5}#=kog(P80cQ>l{jgZ||ufrks+A(Y*iC#u0$ z5#<|Rghb0wIV$)&e3KkNAPSrK!PG$R8k)nFT=cGarOu3Ru=CCRcDf@xg;lc}K|}aT zuD+heid2*Sc)DS-JMb%bujRz<*H3?|7lU3^XFJnLT4WY50_6q&p`K5+0x+L)?>S3f z+nX;@W-4*azBOxi#lCp*!)4@i0lrKW>tGhCNhms&bKJ=b4G*6OsQ zT4G4b>bzg`!i2e{Y>2{PK)e*Ah$7CwHY|z7lAjrI{^!|SR^X!?_M^RF!uF*)CY%c4 z9XUw5O#@-8+izwOMJccKZQ7%|6U(3`h(Kj}FQe{;WhIZ%*w*O9ggkhUP+VTO(B~@+ z{NO0%@T(WOjpe;>SAdETyo{R-4@OMPW@aj0S5mw7H}{u7eJM@u@hFsEIC{%ZVykF2 z*7Ji|fk!1!BXMYlU4ViE)a)q7ZDRGsiDYNHHh*EC_Qmg4E?y;usW8tAYz}CJ;3>v`AF~kc!jI#^HrIi5yv%&K5*PY`uy=w-(evrn#c>*?1|za(ReRn zkS^ca`}E3GT_?5XzA)x)E=>}bLS^J9#%LFnXUBfk9sNu+!U9k$QugjP$*%T$&b+^V z>U}Seki#_KI^9b1feO@+gDJ;y+}C#J0~tG@+J@*7uFci3A5}e#R*lPu<0aU1gwr#= zMNH%Hj)v1$L)2ot?NAzo*^7q5UhvIK_dq&~Xtmv{4CMEu=t4N2?zuGEnkyCU-n0BAbzfn4^t+&D0_#NG(t2;0Qn8*55eHOviD5_uc&y3NwlnRG za`YlXzbU2P)lM;Pf=5~%^;>u-sv+X|kMCXYLgt}Ib-GJ0jJ}u#Fu&88#Akrn$(!7 zu}4(vBmvkKP{RCE>()**xCAK`dnBYjocT84P~_mHB+u>sU5tC&ONNu?d24~D#*iF) z09aPRO$%kkhj7DSMfbu}-q!iP?1|l0(6PKerg32dlb=T!_0b%?v>WqUXtWM81_+y* zD1EQ*-uBNZ<(@`q-0(=sQyeen*${M%kjl=8p}cpo>&^P{p3}2(?p3QwO6kHGnEHO; z$F3-y?O?X{yK6<e;}o zsr;)#ykV7@nsyg{lno2_p*@NkCydP1STxM{4GozlPNlh3o25m(a|y7~!x4T`!t_9> zZ*=50q0RUeAf|Q$H77yEo~Et=mdU7p*Zcjt6ZJ{TX7hszN8>!#WGoj@O@yvdvhyC) z6ysG&p?0zW4QctA&|5{}GjucSootHm^xWX#vO{gwOSXl}emC8CFZ!On{q8kFZ~pq! zP)W#8MBmJH5HEI$G1p=zkVY%c0ZVZwyI}i^?A>N~GG|W0_Uu$l{j8!tXu<-k_Jb9` zAfry@yB|ILtI)qRzu4xcAu5D3VqIc0;eH`~G}ZHyQAV(S&85Ls|OH(EZn8|~po>_`6 zb|Y&nhpwp4QHo__m#OQjhQIJAq zaRL7AyPNEMYGaTONffywuMMA*xWS9nkTVM?1GESHraIZGEYHpqy4^39iXWz^;bxl1yOR~(5zG|BGjNxkFQ8~dQwtCwy z3~+i&-~rNujRNwfY3tj|-nd*_;jT=OBRhCr$7+d02(JH#fg$vs-m^y)2661fDc z)nB>!(aZxMeD_hJ4>eiyG}r}XniuJ=!xr~WfSEz|#t!hJs7vpbSy6X$51pr<0bFEm zYGD`u=jaBC{|9kGE*SCBHK%*T${=iMN&(jt-ga| z^E{Blo(p~b3#cx|fhKj!mBXD@qm<{a=cyd@V#z5?jWZ zcNo~Qev^5!P-Y?k@ z?n!s+^Zk&Fgy7`;s`FyH%(D*4uQ z-5T``oM;r_i@Dpb9UG5#t@F*kXZl0lEQyz)={?8uT&1xKuH5z&;AgSTtWfb$kt)oaY{Q9|LTA7|&FtFd-$= zwBh*xH5tD7PZJ@El06$Y0_pKzCsx)tlVsA(k~H|h#+F$za@`Z3RwMQ~)^z2c;j+7D zbC;D7&EQEEi$BMnLF2j*gAh9}F)=SoSO|cw@!+>wqYx(yJq9d@r<9rD;DKgj_#O^= zeNMacv~%SSN+4}uCm_rnh+lQlOfVeq=ByG45`Q_Dmo<*#F_P*JIy~Pu23ll>fU7=c zo*U!9g1O{0F-ddp%_`}+@!?MLkG%31x_?KU@IF-#llK)Fo)*-LwbEonbEU(rl+{hR z!QEnN83RPXC@MS?JA{1b@`!FhYxME{|OmCbk!Rw8MrpRO9^eo|%}p6ienT%g~ST@zl9>dHJeY_eP7z%BozM zITT|-fu<~ARljYkphgq$|uv$gxo z`*@S1gwhz&+qYWmZ|yJ3t}m3fh8-l@5%=zsJ%p+Z#C1Mjy=HXEub1V=gEEtIVLd?p zbD9ovANs02$Fg0-X?fG?x1It#>ZmSuJ5vMQbNfc730uHWiP0eCly_rSV)`20DzUZHi~V+WJ)N0IYC1ZY(Oti-r6Sv)s4jAN==Cw} zM4GScx=0ejP0;fOPCL~~N~(tFBrpIW^d*fhW;d7Fl;ZoIs`ty-%^`e@c7a8OUy zkbB)d-|T#Q8jcF-BM^q%?~7%IsL4~#owca+O5G5kN$D6}Sj{djPs)u^EanR>p$Lb8 zGwD_~mhqP>v^g5_&-X@iIw1&$?1E`f{A2ItjmeD>igNUf1r^q5vuuf>`wi2Fqdp%m zN(GA$TTbNCPA?8w+g&}0v>tA6>&W>WO39q&|BMbZu@@kKO|@2dAOPvPv`49bsZW<8 zPjG;gcF1+7lHb+e<~luewi zMnmCILaR3Tsb7Sj0im`RZZLKgEo~%68)tMdQl_KYz-WpO;{bm`g@mNF|nn{%YRf6 z#`b)wlgjL>2+*X3c=DfO42ER3<+l5TYfm&EqTu(kUlMPUH06L@1xiFr8PdF9pgI?d z`xC!pH*EFfyOAl&We^ z{`cHGtemjTkNCy>j(xX-YiXgeW%~Y?yf-Q`GfUO9y<{IZM%>r9UCYw<@!^M1tQe-9 zO18Xt4-F;ZiaPf7)`44Q(sUsR(2Q$|TTmsJ3)iJWhrWdXwvY}PW7$x43*r1%e#P=w zGY?g3Vwl(M%rr9+pJjn&o1b47XOjnssocK!%$_1t6#kFIS zzKH51IerCoQ(yPgYN7N&Wy{J6Rc#zlf-u~-=;~D!)09%)n(Cgn>R9s{>{er?WS~}E zp*_=|MxM}UHupwY&ZupyT_4>@tdgz+93O;Mgo3G;*)48v205o<6(6+M*s{5cA5s*7 zZ^5m51&PPY*u8trJH74hCc04C)XTlKqSe>)8e*!=*L#UyiHv*R+Mft9Z97qQGC6j; z7aD!<0jE18LB!rHLg>NCg~}@mK>Su@iKKkT8y@bbNz`Yh5S7}obqYe1uxBzNmx5aF zV30ZO*kK!p1R#bN2=kEs^To*?Hk0af)edk2&djnZVDs^hkTBk40sn3) zkp9nfaMn9_E5_#qyh}*NLm;A#3k(@jygR6B1GO0>-v>aDMi?7xqv8B8`C0W-=vKAe z2sPbuh)5!wnMK90%Hmmd)N7_7ejVY@kan-fXz7joTPqdOo@b}j>012-Tj6C7zgndSu~uN|Kc zaF#xkM+gs4ZfKb!M?_DS9lMDiJgrZ>b5ORy@~Hle4zDs(;Lda%91s2eP}vulXE{8> z&w%5Souvv;RrGNC)zsG-S2}51>e=g2&xRQmwz#|ebCEFz863AYKsq9VVL-NnkNyG? zhlF5MCl%x39})n0c!u#Rl!x(l@K`Rl7hPZpdAB#tH+)RCVs~Jm&EgCNIakoC#I+rF zqRc&@QiY?hP0I%Ga@7&$!yol^+Yj(jlMl-t3!uww2)1L3QcHz8C*0ooNnSiB;n{N& zS#vQ;#-F7*<7noz%-|x2_gWObH*?yi?F{c)NE;gxgm7Tzi<4*NyLsMU!az;iOz?2_ z3oH2wS-Z-v{2<0CzOJF={b-qqWs2x1Ub0^k$(^cDefVMkNSjp9SLEa`%0gira~0Z;U+YL zMPzej7X4GZ3CvmZXOeLDPn41Fi0}#4Y9S$0EtE;+@XMYCq<&4nWHwj3prU61h`tb( zGn`n=7@ESIbhnHAoI(Gz;{W+(JWZcnCnk-25J(6vbf5R1WrTlNrKYCy1~nTA@c@PL zt5(@2oQ3UQZ%)s9+0ot1)dno|CbBKi;Uo>TN79d1Cqi6I&?K^(pE8)6i%gv8bPR~H23>8iiVD zWh&8Bx#FV)wLVqkAeW1S^B4pkARV}zbteet@Ku9oP32rrgOf|1DPItL3ss{KO9R6D zZ%sCrYp+f}I)>*Hdyc8>qc0 z&)C5Z0p5X7=(IP=7VYukwOdanvZ#1p!P47Su_Guhz1Ga>Vtx57ldi@J8()F4vxFDX zJH#(byqx{ZVD7c$#32;?-g(xo* z`!(k{tN0Cjur8SvkMe5{=_>S;$YL;+ea-Z~3N`#3Z>_&Y#?gp8i=K0{kl-&Xg{kh$ zI@cY%F95LV84ya&D}4gZk&X?ttL|w1SluI;n3h}QGX2m@Q6usg@lAOo6JE$lo$mkE z!NguoErZN38aFpY4Iw`s#ODp45BnNjK^|4N?CO%WvTM`JfhyLiO_wl@&?@-5N`=*q zDOuYEzdLH-0j5L4A8#hK0Xax@8KvX%vUXOMSRtWKEB#A`13^f;<`@(Ep~##FtvmUCiK<1t%6fzJmZ!$EH?9pG%9>q!azTD}!^grAX7xl}88(dl4#Kq(oBu7?d> zwpqbH58TFj`7RycGMB{yX~^^x|Lbv%_?Q?@T_9iz_XWXMjV-Cs`cj+l?}|eP30oiX zG{n8TN4@O&1@Wf-x71V|r&6O!S#dpJGp`>_JeOdih$uV}U5KK|^{kq(Z&LiKO*`QSL49pewC&GP zetpY}hb4*eLIo6`Ik9C+Uw73J-4#8rJa6y5_9)L#kHYkDSfz)wuT)|_=g>7`vue{~PtXf;<#8>J!sMt);1RJM|G*!$h#U#|3%%P6&*F|re zc(3+N`KN?GZ|>xLMicDYtnXhOvLCQvqei+z&0;vmXvMhxj`1E#>U^)iMP8V5r6pIz z5WNj&JJ<~rjgI}XG5}@?z}>#X?>Zd1@E!nq9<5h?R-KRpHw*SZps!s<=D$IPL73=% zU`2ZpYcreuhuSh?k-B#*D5QGq_Yf+O^J7*c{DCv=WqJibF#RX)o#`4-1A!nH z*V~hvU>4R=wIhjZxvST;CRZMk)M)@R6DVK5uba(ytVLLP7z1o#!88=!a1Up8+$L%p z%z(=VjDemh2Y!NfnQ=Bi7BMl8OyKS>bRw|lh4VoG=ePsPEg1T@VW8MW*bFh$CAu_Z z;sPU@i8I}aP3}~C@6;mwfzV}M0~Bh**Qw8~Mliphz{pH7koQ6sM`_C(dj&O-Agw~?*-vL?xvu+` z|0@V#H8U5@{}w+={H+DQYuAqzO_l5Scd(>yhTQF7%0$g?X9BIpUk+r56JLCWeEw@O z{wd-V>kaG_(0?sU=r*CYq%}-)^N!D1S>f$>ZUgx}J7(kFpRntJ%o(zTq-*cn`_XIa zl3Vc?(SA;`{GF+ECY<$;El&Ok3^lZRELxk$vO7VVEo;N*ZQ@30UQwDv?Fo|YDI;!T zUePUEzpIDy3z>U|6fTerZU4w;Fxle|E0;;W00A(+p4cHvATKn+EIeMzW7#(=F`#|x zPL{o>?D~{1fRo*0$Jlig8Hm!Il`yX2yMx~|&5USJ_g*+tX!X<2U@{f67H$Xo_@DQZ z_>avnr+*I}`F{@m|Chmt|IWq;%)M*$&LmWYv8Vu$xAIQElOz#7ask<)k0R%|CTEZh zF#rHs^8 z;PTz&89i$q`ag4dmUXN%kAYSFmo|j3efo|G#s}M{1Mqb#;kQM^_t3Mvman86RF3T6 z@I#dD=mWIyE4I30NB#5NAy6r907B>F@s5TuR^5_Tl`Ar)P7-Ui(fuD!A8-C8Xa7Sw z`hT?7OzYQqrjh(aCT;ip2{Xkd`P#q{dDO zMd_hM1&nkEy(Obq2I&L{9YKn8DFH&uC_)HV-;0dH3{_$y6|DUvS z-$*k5hA8s~(B~V>hfb?Hd@12|$t7}9jHdBmwU223yC4w&HZxQaTGsf@CH7y?a#k_{ z#e~BXEJ$d14`*F#Gv!1zdmb9z;EwNl(fGKo$@UvE;{P392H?|tGrM^nEZYD0wftm{ zr0B!2e!2VDv+jc0L*2gz^td}f2k%eL-tWu$-!JfgsSdDPsKim!UgPpP2%Gmxly>ok z|7}0{>g)$fh;RT4MQw&U(^;)$G-E6{iRn@G-q!|`+vnV0`e10>WT_PTSENxM_q zl6_sqJm#SXypRxMhUf?MKPl||%Uk>|H``gD(dc790O%?X690yE`_kLTI<{`l`GW%Y zEDPj$o@Mp&YeXe;ZI66e{`G3FQh^gOQ$KhdncTly7l*(6Ua8IR=NBv2ho(OGos~YM z<`}e_H&7J$jcs6rb!S9;W5%sG%&>p)mj{0F&q*)WP}u4yR51{{(jR&9-QV|~MjCB! zmcQ11=R^F$gGzp$=Kb7VxYMdtsy-&;t7o4$o_+iMWFI;(y&r%%VC(5i^XOf!uUGvV zZoRHPn9pJA4XTu{*K~!g_zQum23tW>HcqEc8%j8ze*s)6a10!G4khsyJNfWW|__OxIZ|7Ay7anFIv37tWn!T>%GCk+%4HB;8|FKc!N>G1y^c6~?m zaCZDZhnaxQ{m<{s*Hj{&$^4Bg#sz6Ua*2}Wvh;Tw|H>XdiHtvb_Ww-;qRRXuPxu|6 z@;_a~KV}VE#fPW`K*70dO~hiy)vC5zg6)tMNa^L^J}TkQz1bV$G! z>Uf$*n_D+=&EYW~5I*kg5&ylQ@?SxXF2Dqu%QH2V;(=R8Q&{5pjX(cc6S3^mRvu?_ z-cn0_4&~|@QOX)1_#Y5p!*vG(c`;8s+CqUOXs?#4WDJP%!zY2AJ<3z4JseYy0X3`!wc6m;T5*HXg z{wN~IGx5!TL^Nv`!fp#!@w}#5j}sskor@e2TxhBX0ME1kdHbDtN}_}EfNq6TXP|t~ znYZ}^G-H6~w(uFyXKkIjV&%(Q_saF~dvaw49WH5#{{06JU_#4moX>i-E>vU>bR>8ULlrO6>1Cv;V|8`rP&t(wd zSLWH5Pq}nH8Ml3(*!sSrzBk?nFg*Y)xzESrhJFF@QWVG~ajcHJFmcb@bbXA;Pjqu= z)?PS{Sv#qiKI6_-#%Z#8O8z)W_cD5GvNNVyS2K1OXP^w$c9y3wJtGbVx z`r9sy1H}=Aa5BCu47sH7Mo_9aI+}XWmb|TO+Zdxq4{B%HvaJvYccm--OmWJ{B`S987I!OWs}`r&}(nx46ypeI%{r~xnqzE_(5WmNB8hL0?G zULP9nD>SYeD73f?^v57IhpPfMs{p?1x%0n%+Fx$fzOH%sD?trG-4C0%`u89pAoup8 z(N}W)6o;$fi4IJg-i{w(GAMVY%lW}Q_y$1l|FWlL=0NcoC&XL>^Xc9>YbKp_k7@gU zoM}5NkOtkXc&ON6C@D5D4b=NG|8*i8>M;6!9e9SWuXtuIa4wZl9a*6B7BKH%>*tWu zHg$qdMX?>y&r8>E(xo;5MFE%W>mULZvcdg|+=a`SB6nd*lyAdH7dUUR1yiobVAj`Z zYG!~tZSbtH9^23hG$ck8NSX*)R-c&RYx;AV^gXmHA4e9LS#4Z`J3B<^F^hwsbph3R z+Ie;H9t63#7902G!Y{^z6LcEmVoY+ABS=2FtYd7+*6MbJ`$W^pmK>t4#=vmK3d)^) zgPTrUIb^LM4(tGjE&O_)+eok2db9#^ngY&?aiD(yOjw^gxGgEEb}<+tzs+vF#HI&D z7q-+Y3b~#rosbu7tW#UR+q{4C%Ocfgvva_9RklV1(V^CV34aZlbAmL zcmoUd;|-+LkIt?m2B(pvz)iugWW~S7CnAqnB$92lB>MY6l4Sa0J$!i#*>Lx&i2hh( z=60h_k8|GQI@6wTLYYKc)#7K*us>9cw=G3le#`4iDb>l!ofp&vm|6F4 z)))9K%KD-wwm$AH6h$y1Ou->{(9>d%rS9AYFD zSHo9WVaV_mz%>dSsj;Nh!{W=WU?3fQa|Kr2Lk1w+X?5d@#sF7)*&M@%xz>5w@6GA08t>Pc(Mr0@@9z{{Y-- zGLKwa`AM0d(P)8gwAGaXG9d8&$y zw#rZAu$${NgfI!zfiA z+k%P~`5bx_@Eb$tsyyUj`N6bZZ@s9U`x;S$N|}cHhcVziFXMdY4^6yWpCHYy&qlw$ zd1&H*cWev#i1f;|T(H0emmi80lqRKN`719S_<=$$fU)=wYX$LZ7AwBxPU=TBMz@Zm z#UBKoag>|NB?~Z`KM=2IQrtID87qDOzS25}xTcWDqQ_uW@$yV0sXAbJ8VkWpR@*DO z4O*T_;25(19kzK08LYxvA@e@##-tgmMc>ZL;)BQwA*AF(5RT$*6_WL~;A*JlJt@pg z;IoI~YqU@Fs7`9iui9U;+BFZW^AHg!R~T_QlzVag?eivXLXFmc@1!Y$Vi7&l+WkM#k<3p4 zcw5tSm8*IB!*CCcMDAUE6fm4NlE7Ye*z9)M)swIXwdBwDG^a$w?d2NCtoV!HX`yB3 zQsXIRuLodO`ik=f5On{ArKQ(WH!W|S2b*R7%673z2NqqB zf2LNXFauLJ9L;rT&H>&@f_4S5#r0Puc=a8Am9^sJtw1#QTTvd^R#D>sj?Wx33Opv6 zMMx`e^3{Oq*`kyN5 zNJPw@YRP^xteAIElPI!yUA{N!YXPp8l0_!b9^6Jnuf;tOk#R;A3OepQ-(imI#_a~I z7w$0pBX$GE7YhTJPP-!`Y|)xSgy@$|F)f8kJiU6fY3+ebFIC5Wn|$xevSW7VV^2^n z>PeFXC4=fC!hIEB1HwgiKo5m}kzEz4;Tzg~OUa zB)k1{Ptn)LGxMr?&S6e0GUTloIQ_HW#lpyLuuJd-*^@f1)3OgB3GdV^>dm6!Pt>)y ze?-o8orB3tE{8rVEd9KAq|{rdKG`vUee1>I!&#tZ2T*=F+c@XpV%0~B($*I3hxS&V z*6>TNUOANE!xr{7b+Q76h?4!F1IhH~s`^mrmmp6*YJtu=)F1()QKYjPg895cD@6rU zU*S;VVZhS9N2mf_?@(}6{1Q-cT-=)yl@ya=o~ooSO`o!H_=3DxI_M6Y7JM#?4)W?2 zInS4pNXkEBM=(V8T28{YRZfGu9|+sk1bWW+4FHY#&mI0COPwD34@Ou8l&fK^obYB= z!1k=d($M;D+&qD0#a>R^)mR|xHm{GM8O!r%w6yYiDrR6_JkGo}&_&4j>{fxfaNxX{ zslnmJ@XNQ-g7UdWe>Sh1y?(P?cfH+@TW4$Q>io;8WhBnY1ybw;Ne|GgSAVjLdJRk> z8kSrU@MtwJtq}Wqu4N3chHQVXyEg;OM*Q3(+4D>K_D5^O57S2Htcv54k87xZW$0rm z_+%9?4KL{tvE?&u7N9=84z(I0`lyrs@s&q6F%?Nx7vn_q0zmE$(~Q#WY96-au$LXF zsiYZYKw$yA;NR0(ATsWFX=x@=+UguuQu+aH1$66eb;mwEs!Ua`ghciTJY)pzVly_DI&$lK-EC#Vf^0EE^@jreJ!-G6Z1s6^s`~(J zrGuV;yBT8pIZ_{1Uvayhy(X|ZFtRH`*qGgI_8#^J`hmCEtW^c%CKer6OkiVoX47`# z7;p)!c`Zxs!FEu(QfEb%zw{!eA(?@KB!cFZO-T2HPp^)P*%aV zUrED~YQ&F_seCG#1%@2UFZ1fwNlRhYZ3SBv9|`m-suXIS#(jLZ40}y|V{JvO3fl#8 zDB@R(?*B&A?nrR_M?@wN8JFU}loAu;E!cyP5|mYx2D;*udoIkjy&H5h=~FB;=ENd+ zgAjT{RMPo0bDoN7xusNj|EyUJ)p3#Zf5Ha?3L+vv(kpp1`n;}fw#M)!7x6FaiurS) z12Pa_z9B*rOcbx3H-vJ-;P5A5Ta5{JNjCxu;U7LCK6gDJ_z<jO<5GFoT+BY>IqK^p5b8v%*WkI$mH1xplt@GayRG^{d0A*#hZqqA z;sXL6w>pbzOaW_@wTWCrpn+Ru*J_&EDhiupLLOnSac@%5^?F(MyXOh)+1-}6Icv?0 zP;`t7VcTq)A1w+wt^Zlf;J{Fg-W;mHaQ_j>n4cozf`K?I{6Gl(iCBxuD|#xicKr?6 z_S2_xzMF+NW&Gd&#CN&g6y@QPzOzvO5I;T|;Jc8EbV<7bt~WfxXAY_yf?up0wv_S? zzZiK8B90Y?+?5Ja?R}Y65b0lQeV9LkH1LeNCy-xgS*gi?OG$rY6X1rz0SisFM=N*N zS%vZZFBOk`ald6baIM0!nI7{{-QDiffnk;DUr<#p&&}4e=JezFY_y|h1ds9 z^p{uPS{M_n*dPn7<1RP}vH}L+#c?>E^)1qrN5@(^PG&yJlO6p@>?qT0A(S)q;-5!t z03WG({s$W;XWKj4SFoY|X~$@KfQ&L@)d(00SWr%ssc1Fb_@)VNoiJX)Ej=ckw&)|?Nr zam57aM*nLuzg#Bwv@UPY9y{2=1A!frA+P6hRvfrEwg@i>#N^Cur`XL1`bMxOw1XmC za{Y=nXhs%##`_cyQ21t9#5JWN^2@?_fo5G|pe>SZ@lLmPU{}>Q{B+GXcsM6V{G+7i z>FpLbS?7cS6$&)jxCc`wyXgM%O#pvI#DSVtjM2$2ut@9X_s$JgDXZvn5E}vm=vn}x zO;u1`Hd;iy@neli1*!P{Xnwp(e2r9FZ5 zg{V}(Oh~KKn4C28zYfnz(@Zj#n%|~Z>_vXkoe+#2XdSpHZ0Igz`JoZ0--bHSJLopE zpU!QPVoEI7#1VZem#Z@BYn=35gEo9kgo3#(8HeEN5Z7%Ln z&f08tnMhd|$ShdOVM`4ObAw|{hVvuk1tK(1{U>4XcHYGpPaU?JM=%1F=`F=<(KkeF zvshABNy~CCgC>dweM$Nf-+Otuvo|V^QKQuw z;%lkYY$t9V{owYe3M%^ z{{?V;mS^*Tjzl3^?tu)bGwIZvv5}h__m%tivJOmA-?DsA+B)XZzgp6c*;N zZ@H=3fZO%dWJ8hXBG`#G#UrJj>-&6HQ}`3`?~IHKA<_}-OhbNi^m!MmOJqkL6iNOR zxU`mhN?eMirDhs%cP-X3N>NxSjuu2%z}~5MxD{nlwS->UVS1MOGO#lAF#F9XYG8%Y z_7WmrS(UAf<&?!Q{-rW9Zk z>$2F|_q_Y9Q*>%3`)dUrUYVV%Tq74vkvw}3=@`49(r=v#+mcJRP4Ww$U5i+n=yIDs zu<$%pQGLI)!tZe8ui*wTKf!fsAGTS)!6+);2J0t=&x5XJTO=nGn$?#yT1=c^t6^s;N%hm0w$=95a|m&+G5Fl zibO>%LzadrM>HG;z&kcmzdm@5>}73dR*mJ9=6|l8z@mThhLr0~f|bujs2WKKyId8; zSSg+rE>Z#Uz~9D@T)If9AHa1RX{52(LK!bDd_d{qvymPHYH#y!N3ji~zO3{y{hse* z?Wh^)%^OQ(5b2}I8rfV}PUBv;NWYcO^*JFJN!DTer+><<^N&nX5;wyTVPUU-YTLO} z*3=$<_K*;jzlPJpNp2#33uk|&PXznr_T7^b4(;K4Gg?X%R!Ni;$T_jP;Yb_mT+bQd zZB@It&s|{WqhtHd&5n0dnKOZvR!hUfVB(r(7%{G|$2JO*QfHtm#=7{G$5_&1kVm^OK6XUTFHZbCB)Mn4ZF%?rQCLn6&UP@x^TNM?eN~zV)JM1ljn4(uIjwHLx1^`eTg}&< zArI(TYxb-ud$iV&Xuk!&T-N^w?OhR9#lWT4X>Yp|(&Ie3Zp}U=B3X>`wObj+m|S0% z*>y}&3mZqwvbp{S&SsXOV@BXRWix@rR%Twwu>|&_u>RHJ>ua^Nx>Cb{%R$Q56^YRgdDDrXWJ(08}+PEv}V

    UEzxW_Et)P0-13vM}fMZi-Ni08M^S)B;fOzsXgRLDf|xs*Ze$mz`T&|LP)7=E+fQ zYM0bdalO)nN`nz_mQNr*1>bv`fQRFZm7KfNp&uMOwTkO5U3QT5;Z`J+oz!x6P}pu9 zQNY8;NVH}}Esab{els$B5U~hEfN#P>k~X@n0nnTl;)PQ)P+LrgPG4;?3gZK1JNNSsC-8H_Wl7Y0k*&8!~PKA3?~PD)Ab|M&U|Lm!eWcd*V68Ax>c)zoc_-H z+anG$KzH)rcKM-QK-(cmzph4q5^_qX3$?O=V7ImdT~qJ&kGW~dt5(Yh;TQv3Y^JMo z(2Q@6E_*8n-JCTE-;}jZsz{DI@5{T>U%vfFD6%vnk%iQmn4akmobTR-{=_UW*IBTa zsR(cjv3R?ikoLO!!aRY!g-b4~o$19nLL}vL`>SY8INiZHpEq}|sKEcG*(c#()jtLf zE*SB`C%StCHbGOmW+bB9xzNvkdG}TW$$xa@Z`Q!a72eWLlYv?NO-&tYeQx9zI83~a z;^s%8Kib+v-bJ1#l{$jvfZ-^@6Ge5qk8r>Dz?^_CncWBizx%AE z{drllm52g<9yhzf=+!in<_DBxUuD6+vSy-cU^C5bD5)}sDsC#*Q} zZMRH{bUta|9Aq?ab&GwV8m=_l-|Hl%lMA1m&(Zw+Km>K;>Jr~;_-pIoXq>9AkR2aj z{ci7N16*85kk#R%_F<>5%$hKR;#;TQS4VI#pmCB8Z!<-2$cftdz0(AwYfqtFx6|&K zR}@~2erx1m2T!@27!zO1FSnT|Yb$@xylna{1X|%nwu3w|!_T~f_^+9%L>OaAstrp) zIR(L=(LTh@&EOGI{rXXjZepQ6)_o@tvTlqJX6Q;s`!@8dZ|NiYQdMYYc{>@4cLc$! z`h>De$(jSlLV$+bsKA1f(mk+1&pz3wLyX6pAfq|=!j>I|8B9QR446Uy&9TTRllFLI zT^gdCf7W!mC}*oNW%QD5FMBVR?Zx?sq6?&>md>~bgCK9oO4*hap~$6_+cJ-$Oe#ye zb~E-d{>mw1|C6xX8H9BfabSJ4%Uw6S=*>MMo#d4o1=*nsFAaH*G^5$exPWCKLn|BE z(NQx+X*d&HiU*Z$Sz~BZKWVhyIQTuY9b*84T(oyR`CK=b-0(>HGvSH-rx{d*zn}ZH z_2lqLz)JT!a1~vXtY!&5sT@LQMYT_iE#*|gmv0q{Jm7YGj6t*K30V)8H6hpY>8d!D zk`PKoH-ctgy1^@k2Jf<#caNk#VG5bUF>6yt6WlTSppbm@kQuZ>oUI>D_ zMPy`BB1zbLigf+JiN`JU*X1}vGNtXgOlvUS-MTQKp9gdqfNq?ml;YzGjQkpaDHuSZ z3y8hQj(jw2Uc^)#_aTv-62=zLPnzDGNkL69#yM|uT;8y2aO*4ZD&g^a#Sed9=>>A_ z%g&---&2tg&uquw!-8g@%A*5f>ng@)dElyN!GwW}kOX~62+9;I+9MJM{m@_jmtMYq zC=tZNLPEGfz_<-dH+;ZG*Zu@nq{zu$(o#-^WhbN4{#?b>a_7=2q&_P8xei;usUp)& zKOjQZl85**fY(xD6PtqqquKOb%T8E@Cf5L`7h06Hi5#671*M!<$Yub0grk`gDL#O& zq(qByp}Gs&R&j$5U#+3mZ+>297=d2{ne+k&{|9Q+<+3#;PD8gtk@r!LM8Cyg{ID`` z)F6i*^}M*u2RbP-<@PJ!72qVc9LW|({`*aolm)KxP=@70dAG^DOj(=N&9Z8XlAe8J z?(G4TJ8xPp_p!3SXf+)WK%^#nTn3!6=88%ytXi zo|a+YjGj@?-MGC^=8xvDn%=o38l7|`N=U`U)Jk@eoWv;B# zKohcR4cdd~F>cxM@XeJ=83xO5W-Tp68zy+ymZZgKwMTufy}g}vFA)l*uhPXKV6Q=% zem~O^E>Z$Zuhx4BP;XLpec{1@!(t{U$V3s`1H#65V+xnKXx6m;Sd~wxndP}8`!#Q5 zt;MXYgF~{7OL_ssP>k;XN_MMcBHo(RQI4@>BE~lbyytcadCwVU>y^nox^S;g#mDglu_L}c~yYyOo zopGX`Xv!NuMda%n#zoRG?G+KdlLo28xaylz^@lCX;nP|83@K!?GDIR0>)w*N(HGV1 z=^;*5RJvyvvsU927?$iBzI+?{TpL%-eaHr8xuTTUryn`o+ccU5RiAK$!E6dt-j$n9 z&KAXG^IXPm$U4+r&VwG0Fc*xOLinyb?%-u30hO?|6#mmM|JYio1$Tg;gT zptWU@sRW#S>3i`I{R>Qi6nBqOt1FCCEgFnkZ8H;)GWQI(MKr2DlX~x+Q1#x+nh>T( z4U5?<1kQCoG0*!=boRTR49Kv*3eIu})gF?tL#~+Doce3{dTMQWd1xBA>Wc#~)$;W| zP30!~nDVrLm?vGTN$r*e#T5cP(16VD4WznUC>PTW4xFQ|mEW3u`Q{3_qBs9IPlV-z z^_8DnvR=}Q(K|1@iqxjX?yznZifZz#P3d?{7KQ-4;w zPp#beluEso{aUOaV`4u)IF?doVPZ&1cdn`mCf$QJOhk%mPoC=Dbg}?GN^k57H@7Co zq7}r-3jj=`rJ(2}vTy@s{rR}&#m09Z9WTI=v_5a86<*QqL0MdIH^~|%!VE7a8IaOn z!;fkhSlx>^4EuPh`818q| z4QgXd##cg=mn*N`QD!{oiN<9^R)1% zc`a^zOu?l-t2W<#q^j;jUrL=VdwWX){GxXy;W)y=KeXRCg=SLx#-3Di%hR4TEt}(D z!>pbepP|?`>U*@h*@3*H-#=f{kE6OXmh{Dy`NDZ;NA7XC+0`=bFbtl6qd*<`k_`K) zZPgoUNm%rj%5aIUVQh1il=aPawVrW+@iV@wEHuMO+4jzk{%*Jf1ZjY%C9w0k%`6V_ zN%c8$o25)2J|;NT?a`+9@QFv z1$(XSQ>_l@a>~cH$g4x(Ze1kR`d)fL(eV6wH!m@t9w^qYFjm&GAZvuZN_zVvwN96& z>rZ#;F12%#LB)~PD?Y(ur3Y<{OL~WShXF^pq@r_&uMWQ4 zk7$pst&+7~wnf=iq=6~gHYwMWbng=bYEc%(L#F|>(4vjsliIq<9&c6#PX7_@uzAG# z!G?s=EJ|rlOJCbbb}LmjXMMX&xq*$y$o8YwwaF-q%_xPi7N*ToJnX@&xjzmKcm#Qm%otf7+jiNRqS}ef7@ymU9+i zBtf>jR7o`nuTdd)pq`f^7*mJWO)Dr~7!OJVFD49KM{nFJ8agw*NMwvOYT5>;G1XX59M&yE+B5IyK=Zb=h|Grf~@aC2{(N)#|rB< zo))z@P9*z4t~;1!T+!~6;D1xXiKU$$o6{b3l)PU45?=|h=!J`>d^i~A2ijB)PV|X3 zG%+*CEu$#i6#QW^-1W0pmbn#AB^vM+I?j@3-0$3x^}J?o3}oUzP>O`4f9Y{36;a(IFXkiaOv}pBwkoZr zzmFzuacjbq?(vGY#T=5J(-aq{A^B?3 zOqU~6rvp#qFS(tTGra;eza4*VsoB--uatXh)cmp+4SOHv#`wtKlz2FL^6-wH`}5z_sR6x<;B!SN}Ygavq^V)9(5?vp;28Urbqzi;Rf7ReVh0 zhrBbi9(+)i%oU?-E^-PnqqjYwWr6%xr8lMok59w$L)8j`FTFy+^?hJy@-6Rc>5j_4 zUffgbnpQH9Pj9s=cIg-|HC@tuK~(bhBFG-9y4EA8fxi_8qhQxxefU@k@e*jUwWzMw zP;=>4VhBDi-MPQv(t*be6>;kj(l2((gEh z1tA17?a;AOf@Sa1bn-PDd>h;^Fz^9r{BY(4YlLFl?sGx#Mh9HYlqbc17{7(6UlUbI z@`6v7#ef{64;?_wiDh6ODg!6Kgl+pTHw(OpV%g*?;WrM8MIWdIq(N3iq^ zZvA=CFlF?(uk$2G^#xO3I=>S-d5RQX@r?P!G^{HIOMX$b;%>2ASGT-wSPF@j>a=n4375LF-8fr(uD|ag z$7i1c3uul2n0J>ugn8=Nu9ht+i*L%Xh48^8G4H)l#TrnQ$j>GwTKOa3Ihp2R##{Ta zwUG7UrjUB8tDR@n1%TqXWtNP4>~g_+Yw>)EItt7b>0_L}2CK~R%d|o>F+B-b2 zVIm8}U8Jd32_MW{7TDZURKaG;FvvePmX@`tm4yxY!N#S03wu8#$WmHu8_+KtgA0aC zBo7QcWt)6J-6~lg9)eRyz?2V{?(euY?oL??w8bDOL=E3 zgefbI@8jD+)ae$-!qc|j?ADs>!iu@v6l6UeBFMWtYcBfrnT=_x1s57UU$lW^ns<&d zS?pd$F9i*d6rnA252XhK(D6o{X8{%xIzz5*Y0`PJC&xiie9^P|XG8K0>T}kiIw(6S zMS&bs2_aquJ4ac$P7vMsLykWyPo4$g2V5&ym#2$ojpx2{X_;iIb*K`%M zL$M<(aQ!2u-R)IYbI6e<@_P*=6x(z}O%GVWu^1c4Mb7Gr#vgVX15&cXm={X2OYvb? zR*6m0_?Qq;RRKI>w?b|cDUES)wylPb$!5t~3^JsPrB-! z3OI`hO#JA@k3T6~YW||QgejqBJ?an@GcP{rcUU#A^8Z-9u>jaJ@8m=YO1z6EkMByC%`*C?4^MjXtY;&7 zrw=nu8mPr$oIH_h+Td_(lZ+Uj!NnwQ@1e$&c7BkxK(&V&%t5ohx_Md6(|GuhfP_t; zU7_5R?2XRF_e=GYW1`Ki=Vy;=ZuA|7HCkS&)VLxXW~mOKIg&=eo>9+Ui&ErzX0dxH zO9gx&KE}n(W#=Nt$c6)NWNiS6<@RHwXBlRuY~pP?Lw*3+ey1x-QD)mHW%cT81lHA; zPR1skBdPbQ4+JMCS+*ni)l+?I@t`5FGky-x*C{Gwb37o()kmBv{j?h)fwJc-Ga+VBjr?g3588ui{leTK&l)IYBQmIc+y zqA+(?d`yic=(lh4K~>>JZbeVRn{`yv6r&4{M6;)lhYz)0aHxhKH6anxPBgP9(Vy=f zw9yO;47wycmG86xVLoKQiicjq`Oo)W+peOT9KE}He`ZPfrV3CfIWYuSbAXE6Z{{Xo z94so=QGN# zM9B5Fywr2i7PDulC7(~LH%*McJ9Aj6#t;)X61ZI_*sAJlRHox{%0qKv1in?at36y> zS(6q&%=U|w5?c1%vUvQ#Ydx>7s^}8Nu+XY{1a?2FN)>B6fjm z`VEPu7tv_(kVNAdb_2nkf01HMi;C{SR(#xB5$zNHFwOg>fps6aErDbjO*RbUFb zQAiA~A`Lp2wIeI`ptf4utS){-(O&W}=I1Rb3nzusHEpw^5oIX?K-G>VS9NNPUaf+R zhWZiY>Gj2;4!owY8>Pm?Z4hI#4C7q|YJWERl-8x#fvC%FDQK&LuAFX1-N)GuK(^ydT5N|Gx{%Fhgn?Q`cx4xvmp6m4=ogNyc=eFaj`X((PVKeF zrlbwIWLh{gWN})vbg&{@pQi6rC5w3wVY%Tfdg30ER zI{{{V0LwDpCQdf#Q#1xf1;&lU-BL4{z!&7&I4vyG?@#cRxs$EOv$D=b7j$1y<_G6M zL(Y?bgy2i``Sr3d0su~kAdC5RRN zvLy3X-i%;Mu2++7)Qrj`KtEzpWIYbq&ZfrzqUIzpc>Yj|OjFUi;vve%qV;AR5XoQ4 zof%D;e+|ruGGqD+uhUpnhDViH9bYaq5(AurM?Nz`lzBEON4k+MMRr7yz|a$OiU*sZ zCxe6mKo4*oq+_? zP7{|2kp$K{By)pxGk8@fJ$MOFz-3c|OYM4e72PFHAF7kJI=Vq#s1C07f*DRg2D)is zYH9B1Z1N^QtU@l-*H=BP+-_`EJ7wZ(+2xUof9?6wn~?32+2T<#?7vxkq1d~iNh@Kr z{7rBhG6!xpc;QnuFm#Zj%;uVvq>4m)6t1NC^KF>ij`mk_keT5v9%@EiA0t83!%jYs zp|~f*426^5oCh-W3b}mH=)jz!lJRJ3fpjG7xfvYnRn zRcGE@G1Lq+uY(wrq2MKX3)-Wpu53bdF z%V!FudXymhJuVM%20GrH5PeV(WRg}O9W8uVM`B*`1c?;^ipoLB7&Sp;L6?1L0&hc< zas{C05bA&~$gOU_-;xrikySl3V!8i6hM&9v*Cb!{yJoCAbX@bGbFzNdEDX0*&{KN5 z4e2q$JA`s}fWHn1?q$ScSy@q-Y2_f%R)`=@G0!zvD9Vs99FM=_pCda`zokiB*fiZw)oA4HWK@;xS_uvMX*qkIIw;K=N}k444CVN z(0js-NcM|Dcttr*nNp;L-Cu!O2N7%VGGxDZ$*!NXn!r2cU z55<)xtIA_u%9dkKwoFJ_k5js1JAB@6Zg$)Sxp-a*UrFqRt!*iem%SJg38SXwM$@NY zgoMjZ!?+aPL9zR?13_wZ?-xGboyeboX+8VO_P6}{qV5LU zdNk9d(Tsq_+p&)ECqAlR&3heK8GE;7tiH|6=s;T*Nx+m1d2k|ZW+8j~gl36mId)>! z=En_V@LW&&^Y;}5z3IA;CR6?Xh|4bAgyBJh#iQ$?rXqUN9Ylq@89jH!JPn9d3VVO6 zjeR#qMA;NRJV!I#x%Mh9;g_Z+rgW2vR2IJ@8WwAO=-l%ldXotN(>$BTgf% zbUdtxn%8ZMPO40as`vnA_2W#ITYKt%R(oTzo$1Q{Nzu}+AI`5RUZg7bAXORHhkjI; zlGY7Ii#n+T6Msrfnw$-?CLBT0T+T?FdrwsG8K$S`zSh?fWsNjf9=AmiXP|3b7#lbM zwaMsQV{IKCj6R!i+zsHhwRoQ*^+o8Hq&7U$)3R|{e$w2LV_j*aOni&odiv0pWQXo5 zec12Yl^=4!0h$FsM(4C!FTs+$aw%&C=3$Cw3vF#>X2-hy>4&$Rb;n`AiUVfPF)+?wl~#pSXxNbPvrlEvr+N4WHS7qBJX)AGhPL&+IbUZIMQ z+X0GM`mR@Z)FFckvH)q31LDk~#2mF8v>}K%ob-NFC_0&_r8VJMT-;{YHGQ1q;P?w3 z7@W=&z!bglvnv#jU5|TNMpE}5_s{Bmi5RjC#A3B{rVpL?x^{`&MlC=%-=cxI!iev_ zU7DSF#ZPFH$Q9mgXeHrp!rRQs4V<$OTzQi^a0&E!+}%*xAsLo`zTz2lSEA5ArJoLM z$r^L~Kv3so&)0KnOU})ZIW4kYNO5E~&x7Ro4l_Pchq^`hh?z(d@{p~zeeyKQ-K&>0 zy37TE>vlB{&o(YC=_7jTN8pXo24{5i9ZIh#0JB~q6z~2tU(6NgDMgW{2{-vbDtj2G zNCqJdSMK-``we-TzPLqG?`eGQ04AYY|BnNTs%|l*vl$jz6Bw@R`f`-k9oLa2Pir3Q z6AHR^BO-pa!A!~HfrnBi7C$C0h5FrIX9_be-U2ks9H@{&wgN|dUw0dB5KP@xH)(e7 zTqBo(=K#_BTibo8F#}9x;@NJSY3VJcf=}QYThk|p12YYsYk+-<&r+tu*McSiu3Pxyf=a;e6`b*}noem@s4k*5v!N6(~RV7Ed_> z0Au3kXu(b)j=XM9`LQFeIUChgp8QD{3XlKLE?$4jJJ-xyx>S#}ear@)og6@3oGNB>hJV78%#UGqNB`~sHJOg*F=VR zJj+Gv34wsQpHgLE#;5XWdizJp^j@gx11<&gF)@>Q)Z4pr ze(wxXD?quIhSZuv`9##pyt(rt6cjr!zdn8DVwCW(!G)j~Cz?OKT&)u|3i>#0$sOAw zG>i&*agyY;PWPR)$NQaVc|oN#hx$sh%gjS0i<=j6T3BmXx?$wfUX)UCs%;I#Lw)a{dSPG~Z%)j1H3-RB^4U|`G2ddzll z9I$?M^jd-}9!Djr(%Bu=ac?cxx+_nX`GgYRehXV`Q#$KE zoC}zYMH_9c8RcgED^Dp!mRMb&1M8oZeD#!6LcT@BA~2TREpK&E#zKjyFIJOGf9%=g zFpqZ)|3+NkB0GBkh#vkrYq{+&6-{6K0Z?@HFj4x@;8UME@$M}jp!@UGDX{qRqD)ws z(-0iE(7;~$q!3sk1nRdr9!%c3P%z)|&Qx?WxC0m#c+c{~-s#LEMt0bqBjW~K-Dh(J zqy?Ds0&a`6lz4mMrv%(&#wyRl)mLW>tcwtY$8}?IUq{t%0gj!mGAI@UxLiGdp?D36 zxkKz@Pbx|ynX3C_7KR`4tzu*pm+A91dTho1jVVoWiCwLV8C5ZtTJO8|(`fONtB_c_ zgBcw`U}FmU{j_@=mChB{T1qeoTNuH|EPSo13&C+X@J5~hNXu=Ax-&6_q0VE+TELmJ zAB1f>LK;hVKa1F@EkR-R)ke-jrFs=}n>QXw+s9pRSh7WT7TdOdykTe0N)S|AJCr+& zzMfaNF;zA_fgtR_bBmS(D$-(C@nRDT?P;16gi~qp%+s#Q9qr*n_q$#*EPX8r3R%B+ zR)k#9(#2~PiE#dv9)Z~)^)cx6>T0@b2-ax<4naU%p+&wBz%Gm;Sr+@hpebqG2Tx!O z%5`OH%!)7ACObg@hqq4?jQerI#OJFCe2B10Z5dG2$^mSr7&ocOy8`Iw9IpX<`crEK zwB=zi9Lv31y-h`=oKaz}Jv!S?;OSzNlfb%ctAmpsE{ZmmskGx2!l7p11JL}5d@vrc zLHE-iTSb}57^fYnew_hw#ecdejk6u?C<%FG>tar=b`AgD&mz?&@A-Fe(R!Jik>!gW7?6h;(&EF!%*;8@+{onM+$t`pe%WKFP2sFE!k z9wB$m>Y18EBNw-_++Y$3+Z8bueP@F4^{fxyNajLe0Y40xR^b{YN^p zUL3ORdM0D1yzP%)AN?^`X~6)taIda_=BjPwQ)Xth3``p;Z?$sOIC{k@N?DjD$%H8X zR9t5uenc9A<;^x~d8J3oe7JiOR+6VVoZ^3N|41QJkhdk@C9Wl^BCTcH%K!i4>^*~; zY`b^w+g?yn5fEugN1A~2CJ53&5Fw#Ox)^#1gcb#*6M9o1B2A5;_9Xdkro0 zp7zH3dG>$yp4l^d=KYp$4A(X1x{hI4PsS)G|2tLTzQBl-iP|EJ0S zzgRKbi}xp}V45>U{uh5it{a=<52ILc|0h*!P|9LGs+*LH=>1_qY)xrZwQ`U)*?(0# zcAz~@upCXOgo>}{9<=Zjn)#UDa*}snteF33B;=YLI3p5ap*tn%B+HK>toKj*K}r(j zh6$I><{tu!aA4d*fXuSI)L>p&>~wA#^GF`joM+NgdvZQcVZK6!p1N-NUrXfx$lNR6 zf%M@#u+ko>jl%6-^%^x7GW z=yN&A>-jFdeSEkN-Xl`&kxzE>Qc0fQaP9VskE5rH+zaETaKRr}o5m+I>sECpn(XxJ z1iPN{`|Zt7mzTYa@`2srxWH0ANa*h!xIRsL)3ZX}56oToa-Z=u7zucX1qqu$GE#{PBDSj` zYAEz-LeE*brlhNLqGQFau7zRsl&6NI^ z^W@&YC)m4uj*6+b$u)F%&W|n z+%-R5M*6?1`)S;n->W8O1^jTs^X^X{;UgD~k>u{a3k30rRYq!L`+x9?_iGOH8Fl|j zN#0KK!8P(ySMwhB3!4kLZi17cLa;cXE+)157D>-iX~zs&yCt>vi#*%$hlB}bdqyxO z00^c8bAo06hb$TeUO$%umbKbJ&-Sr~2dSl8;Ek5_pTcwu-2-s*2Pqw%LBxuLp<-cR zLZv0M)^8Ci9OyriX8DEt+B>Qhf?m!oO_3IYpgL#^Z!lX5=|`6(havb<<=FTV)U)`K z%o;ob**2-}u;s>qPaenN983}r%oGJsICc1}Fggfj&UP>}OVId0JZV;eu10X2BCEGa zu?(HNo|r^h#y_2Xfd$J~sFa4jut>X;p*AsVqr54STj32>gNIb5^pG}McxU~%^J_N! z-tP{v{%q6G8zPAxjyGxGr*4f?`+)4J)34S2JBCbT+eY~_+rk@620YK%1X3Q+GX4cX zBx2iFx*KBYJIcer@(2znaaTDCf;2v zl~_bDQJ;9w>mc9lnO4tH_5o3Slw`$U8*XVbP4~ma;BIe-jCZ|eitbf9*tQbNfNI~( zOyhEj&F|Nz>d}1@e&ARVV3w_pWrsp0ZwH+}P@?Rfkd>q^onf{ygxEjDiWAEhD|z1a zZ&M11y9Ja*C5$A0z5;cDe2#bIFr$|lsdwEoa(N2)7cc%-VE(;>uDjRPnjZjvhM5)F zHh(+aTgvU+BYvJ1D_ir~b6MP88a|ut+LyqjI0(S_`;AGDKjJs)NCAgsM9*xTt>ymq z^64;|Gf10#D{PSk+z@pG{Iyr7ADcd;Y-gQUa`fN$eg3p8 z`*enI7Zdb5?mW}#@brQ+Zar@zH%AwQ^Yn~ zgs}rOR+osbH;no;+5zGz(UWG|!u#v>zGY5dt1*5znX(r9U+QXwLKt*M`qKB|#io_2 zDI%1YEBy$5*T&NyI-d`8tcjJX(_yzjUwmiIIR7?JsbHbjeyU%Ry06{@aoTRK+R`(o zqNU0R?*i+KdD&1=+JMmR-ZjHBU_=k>sm9sbU>%ruOIPO>MD_IU_P5eHj?)TSo{?(x z&fpiPI0|V}|2=sPN8x2O3-WB)-+u+u;B{hFk`qGDu1^?t$W|Qvb|_df$Lpi(%TV}A zt#m1QK%FU&Fkvj?uLbMyVEqqshl#rD#w0A28a3j48ju;yB&EkA*q2s=7RPjw{8$MF6(Ifc$87n78I@ z?U7Q;hCk|wRoW?nJ5=`nVH=yp1K>3EqS3HZap>vvFVAU;Z}eyI-^Y9C`Tx$!PUv2H zb%w6w#Q+q#z-L9y51%88)1YpS+2QA3d%*!@cac zD;E?SH83&1Zl8BIpIUjXiom8RTIFz>EIDeVbiRew%&nssd4%N3V7+{UD@rDE6M@8J|21A{{SPONy7=|~&XGO~?jBe%1s){Etc|Bfu~T|rZ0`)MpD;sRM>|23 z6WZFTGce3?Ha89KmRN~f4|BOm*Uw$^wfvzj!|*?uyav6Zax zh~!1#<$b{jS)pXro2hCexh_T9h8yxNBMY}Q7VD6OC*4SJPHTMvWGwr?Wl6hRlqv#?`pbmibNvw3AN|$C<3E}SOMz%*Kgp82DH}-Qa=i13 zlZwvWM$dQlcnjK-{icS%dr%qwcmkAcKbY zm`~Rtln!JWX(=xv74$P@>L(XXxxvTvuXu4AK|IS*W_9ucK!i~J4)V`_D7&eEKtTYH zgZ>rp$cD^zx6SBZqwIfo5|>w~5f<4%y-eAMW%Y+C@)dJ*(CT@qy?{dzQts@D(O&H6 zm+iyTAD|9&Sdc(}z)nQHJV{r^$C4ub+iiGJZSjokZFE=o6H5!|yi6r5?PIShf*4bOZ39eXvbdAz0?W7Rym;{x}Z=<@bf z$2_23=C$%-r8;auKXgK)f8%=BD{Lj0K9{>nUA>FqX8W8peAKe1e0;Afu|KtYDDj8w z@7pl~M+n_XgKsAzR-g9TGkBm|!w;Zu|11<)o(Hb+0l|WxMvax;FZ@IK4IKRnQuCj= zoe#z3PsSEn`zL3A|79BzS|nnqBe~I8Zc>lwG!SFq{C~}D{=br$2N|g}BgKb^dU9U1IR~?~8fD^XTL0GZ$Wg<1ff;&joUk3vZiUi^cWRzsNEw?odI@ z(#s6#46eq2)ay$AJC&ibeLM$LOBzSVQ$PRlC(OAnrSBn5uVLKn>Ss2~`i+U^GqO8i z%9NhJ&kH}zr7bws*TkCKbM0X+DtwcG?*7L=XY9kx>E;rX;ycfeBe35;4i~A`TZ+nX$HD*7s??RyoNzt?aHH^wDg}XCTsB5F}zg}7EgWUhY z{f*@;Gr^4g)c?@crw+iczJ96G;*{B`yWaDzG zg(v)#`P6#**R>|=LH)Xy2#3_0=phKn<|li{dmUq1N^5>pb=5UP|DTj! zAM?l6ue<8igPGFzLvbDXg>4a?O-^qOk#G8%g?Skh---YUsk0>AqtuM}AH>9lu6YvZ z5P&isARRZFi1^!kIrH0Q-YlUWBKgNOY#ZsAi^M#fqGNbF)oOQFF#Z^xH0^}@4vh+s-mrnm zn+8@}JYeX)=z3$)b4JYK+ak!OZd&AYh`3>AAH={|a1&ghP4ZCa8(32r-x*Qi*Qt*8 zYtI^0>c!VN#iyTDSoa+jd0fjHmNJ%PX>2~rlQP$Pt+7_eXsc;;e<(0@j;I4L@v}M9 z9x6cDl4WIr8qDi=GsOcxh&Q%K)=i4UpzXVQrks>O6Yjg#sH4B0;JP`F-30^3caIZA zZLpmJ=r4BGP{B?t7~!8em$_)t;8}vJMt$Dr6N!Zj#Iq}=i73_hAmop=lBqgYZ_DrNpGlvxdYO&)#BB;udqu=KZjybB z(`O2?&06&G@~jzOEHPK*1$=aI1J$i&`K7H9dm$%kdAWLH`SAFGJXVYf8jJuHhz6mK z^p#OmcW;?-?Psc@3OEfDbDidR%kD` ztX*p8f>(z5Jp~p8xbHCTEjJ^yXQE4mKGl0nm3mQyn6?zYtZrpdZ6o>3rmzB^ZyYuF;@wVI35A_j>BGcMq$s)_9?gUTmheY)E7i^OL4*aUHO%$=tW7 zs!8D(?V-*I+f-TLMl_{poskzfNkAdsR7t78dPl87Ke-nag-_o5KCdS^qs%w{q4Xr{HGh3#+2LGABM7x>HNubW$DdE|I!y%vJePHsI1>Lj@T5y z@KN@UVVyo8Dv{vuP-z)KIeQVbPk?pNZjV2rjTTIJg@XwxQQBs0f0qX+X+n!|RbH=) zh-)I0gNakU#?vk4Qv`+ZrN{F3YJdA-Vr9!w=Qiblwh&Bov>vRGGmo+@`KHYYJDHb< z;ww|@WmxYR7CYf6{i=&yQWUt+En(0ZJ_$};ZvO}_SL!1RASO(|Nh`?ioEHa ze9OC3a)vu_UG+WvKWoYG!i@E`hQ{pDRczaWH56Sg&$Om&>c*CkLKD1g+rf2QWT#?_ z7s;Z)siQ_CC8l&fpg%_y1JmxIvg zYPmj$5K&-DF+5y%R0P-&~7Isg%09&>k!EGL@E){>%j-&2<9I&_| zm`IHr4zhPu;*#pw8e^r60*pVt8uTF#*h70Ky+*tR@IA|N?L>F-)4BsoRP=P~=g|*p zacin0de^$2j(>{vKK{K5b*TJ{xOo`WA z8HPD01Z?e^`4eUKWlkFlYcsIFx);>i{y2qO<@MKr1cVOR z#!7-MmV8kkb8^WzXoTn0{ir|Goi4K-^ep9CFCH{c;`R>sv`Gq6!q!fmbDA1_pLTLf zp0tNM>C~r$zxU?IbJrNtB_5VhniAs?UtQL26*=_$GO$ zK#9{WkZ#Da2__`gX=)m?t{R|cYOHg%Hy_UQtD+}Phs4{BsCVBOth6bpN*Bw~{NUFaH zxa{ZZVW?ly-ZSwM4jzzVjd+F-i!f>sNsLISH1YJ?{Q@Fi!%*;`KrQXz=Tq+j*8v4f zj7p~prS`{j4oYXPSU+ysGfZ=5$f0-@Dy940rXSRS&XCkbZYexh`@OGpxiPD8?6qx= zmAMZ2aZ1$h^zc4ZS%{L9w$Mi|xs`_mkDW)tPMa@@>7$Nce&-(r2F_{M| zZ{|bkR+F4>RAs3;h09Y&m#)qvckQl`#;`w629$2p#;8dnPoD>sIvCux_SAavM9_<` zO}N?_#ds5IVxwqfb|)s`oUzi>`^W>`t7f9HHb?vWZ>-*2go7MFZ;X_>gr!P3rCcN! z`nVgQJF!|SZO(<9%j4538Dpr7^1LlbP^2XWDDgW@L0#_SqkX zk9@E|mT=a!^H2mxl`~P;D1kUB-}UeXu(6^^gf+)5=VUB z09K)5mcd)dY3hozrn24k2_oi~EA_* zNUmIHftm}jVtpS8UQm;6P>(jj)DB|ltp)9me@iDwX1fRKoQ&TeEsh}wF-d<7Xes@& z@JG=SF~e^gSS(Q*b#^UU>&fBLW9L^#a`{^l$b0i!hqg>*o2Jhpiz=_8>{AUxjGj*H zh+bhWdWSlA?l-FcA|2VxX=GC!}^%8TV(aN?JI8WiGv z2=e6U4-AyD92G|-Zu4K}W3XfpsjFWb8*Zb16$}=r)s62zr&&|5jCuwK8Ka(dC=utk zZzCqcbkVZNK#-K41MPeiBc@3t=x}z-zx>NaAILa%xmow5Oif~Ek>9V#oyX@k>~u(} zTq%#8a_TO@3#OcwQIz{L%aE&ymm5`5j*z6-*s?_>hLQQ5Lc+<$EIG7w(MNjx48blb zp6MqD>}_%s_ZpMGPW9aklG~=ni65`67P?w9cz3WJLQ1UHlsknwMYi2 z?HCtPeA5Ec8Gn*dOfAX&M^2XqhhiV{ul)nrnu-h$FTB%%_~c?O$*Dq`<^l7s&;zyi zgrgl9qi!>H_t+rgD*xQh)afb9lrZLaz_Bvg^}x*gB8{^{jCZ!j4_<}A>e0Vtur6Q} z>GemFi7?C~(%;;sI}GRgDpIJs)?87_?(u7|FbE}PfU26BjD?Z*XPYR^1zr*g&7>Jd zxVKg#X+!B{$}HA}jj{zOTZ)QDEE=h_M8{Vqkx#5zOynyMY$woXP-b}Po(IhE-3IYO z-Vh5~cL7W85D&1MZ`tB7^3A!kiVJHx(J@Mby6=}h-<&u)FH!E5^#&*W!ZhS9;_7n_ zA!3f9!AoFxBvJa~0PUIQbN6iRg}7W>NSQOs>sW3ue(}3dqQ)Zhs;-XuwHDKPg~-*) z15V5pbfj#ag{>*>7}o^rH%Llx;3)e3`B?nr{ST)>p0{fh=ue46qfLNB*kU*SP$B;k zQ0_`rE!)Mm+(lD0HsRJQkzfTQF3rfx${J5HPd9G;GVAm5h*5hCJNI zp`FRd#Nx&LS_w-SuNZ5l>bDNxG53h89BVme0A;`_{zYe8tL$KK_atz<&qIz=;&1Dj*1Xk`jTgcblsP~xTS4_OtCqUJ297#i*2LMR{42W%Ji3{_lKl@ zA-XukPqWIr8iL~vn)a0+8a8+dt$nW@a&Fx_OVUYtO`naLyMGjVbuVU9%XjU8zi{Yo z5YBZhcC+Zx6hpS^S!ww5n-%+f`0m>DfEpGvy{zYUP+?)N%btb?r`?M1@AwbKp;B4a z_MBq(kA5&q0ZF=|NF^jJCkn|E^q%T$C z@Hk2PNIi}Q-2P^BM_^<)Ep>?$86%za1-r0y*MrW4S#or;ywAJ(WgQ4!<|P`Iywqyd zeSL(18MG#ajYz%HrooXxGx8|@uyEx9jDhw#qr#j={N%?|DE{1v0|QNfc?Gl?ZP3H( zQE$x1)~xqge`a(A-OSQDFm`P!xTm|#iHPGQ#D&vg=&!xa-SsNSIEAqX1I9AYYWLz0UaCo1b(=`p*#>!{KuVK3+_fMt3yX-76x9Tp5D zZ6K&J@FNvPuC#NEq0lH1#@UfljWnJNCM^}^mpvIq7L*h@f~y%QhmTl6>V^{*0o{Ev zUVGXzi;e8>?ZEtQnr<~i{7NOD0nl%Z1A3_BhCrjk!+$YGtf+EP*lXp zx@`24JHbk*#f??YW?~0TA#)0+M(=q{R2-RL?%3k%%2~(Ctvmz(nYNE@h4SPTy&vBU zyTv`X-|xdA=8%&t6EN!yDe}qMzmo1l$5^2h9z82~{IE{<*b zQ}Lt_>5-$VZ*0sALsgYO&kHZyi&b|?y@Hc@q~e}Sr_>)-KLxv|-k(-FtxlXmJDgPh zj{L=F%gBblOGDS9KF=!yBrK=mt!d3ruBmTBCIXGsXm35ap=omR&Tt^M#@r{6hz zSvKoJDzsie@Hw|FMn=QsHssF7T=s8ek?a+pl6C;MG)kJvT^Jd1kUt|+$CGWK=6t14 zm~ia1!9~)PbmSY;Y_o~T>|a+$$ktp&kR7lwgo%$qx&zdu?zegOma?x}PG2}bxFrFwUNEo(b;RO%cGAL^EU3EXB2$?PNFT!DGUL&Ms8jb!ezHU zR)F}wyn}E4^<8Jt>e9OwG5D56>p7Tc<3Ui?tgKbE$e?#*D)YSx&r!|-^@{F?%)A-( zIajoVo`^fapd!lt~^#jGDsyidH- z9ODWV9N2+)>$R{3A5@fudImU#5e+XBEwPnFzMLK}_9|8iV6(az-1G`%?7z*1nZ|CU z|0^)Vix25Vj?(-Rk>JsPr6v6Dah`Dd_s&RFnJ-2L8_Qqchwi;1o;YAy)@VXB!=p1 z_amX6A8o!Q#_#Oh9AnP>_zCf}e&1H8t)2tCMnXTyw-6L&@YAmok6Bj8d#e<0NiRJd zN8(t0{oxf>#ECIGB*%uJ7MFDk-eoQ*oKk&L`?awU=tJkw${9#?ppQrW?(fvw@xBV# z%*j_|SvPnEgn^}Mn{r~chV&@q9Gt%Vu*g#|Wn?i5Xz>%^-l^Gn zm{C0J-RKm)xExvkRgzZ{zO>#!s!iZ3y`5`o9X~8AU%7UEQx5d;^M=XEkH>fYV4sa) zXLxbLtDfj`PkKq^$7)Uf*w8#2m&zKJ5OB8JIAlGUO3>I8U`l$8jim>EF~Zw2DsdSN zxnDvl*#)+)cv=IogFz7Pp{N%P{l4*#h~tTJjk~Fd(-*#nJ8Uz$v_S1s-|o2=WyN<(idWHY3{2X+2Sxf|o4MV|CQT6m25MGIXK`{eu z;KEz(KA+f39~lFDHFF+qU=KR5Ao>bz#$wx64ukScXuhY|?{XT@a<7x6Bdhupm2*xn z8|7Bq9BNnd5C5il{~cwgANMAny0o{KP7B`!>D=Otz&Pp6+QlHlX?3A<@4e;K~|%B<5xApj(c&5v`7&&fSL1BK#%R-sj9qmwzUbi8@ZD_elFu) zf#mDWgtAN<9~MC!_2Rjie_YvFqeOLcmjLKhz{NsluhLNVQMS()Ftt~H@3fBAo5f_j z9HF$U-b)6Fm8PRE{h?=_V|ws*^K{SPRb-Q%=)pVWud@YX!?Sz#RJWMQiqZb9v59J zk27MLyZTL`KdkO@s8AMLUg&)uj08?hN(xo5>tl!#rI!A|V@c@nDNh>UrIrBht?Xz5 z50IdrSX_Bz64H{+1Jt$^jgKFB+5xj#4(5Vut~L!hV3eJ^O{9Gf6u%uE%&D$CB=2A` z_icsnJ^~#RuH}!VZ*GiY&KfJ}sHFZ3O>6{RnETF~8&ysb83&C&8$WhT2$)30B}=t# zK3mK8W^Oc75iRSOSYuH)TImy^7JuzeXL>|v6gDmQb0n;ossZATzBA|;pN;E(4nNDjTa~2EQEMV_}ZXO{R1O)acv9Z(H zG#SO>N6JoGO@!(_7s?kd&1?Z%z)en(rVVoZ(b*54JV#kaT2mM|qek;YJDb}1d)yr;&r z4R(A%FDDssuhOGufpaC6kZJezC(7X#{zcM+xM;2FN%&+NZG?m#WcRrTrxh~cy4Kb1 z76G$#OO^+L?NJpLH&Bvm*9BbZb6Hpk3BAA?eTZYY4Ftq*{N~p3!<4r3CErW5-pIPA z?j)`Kv=a=SU0=+IMp}#Fe|1jm+;9>9!5B2rvha4ZUSR!?mVFp>RK3n+@Xlh#7H4gk z^Ab~#Zm0#9yKuO;CyPXZ*mU@-RR_CwpH2XR_;0YaKrx z*71xJQW+-y5fQ2Sz?L4(IqL2gGI7CZvq9U@{)<0rK(5uDs%tH6a=(PD%Qo*iVhS^l z9YLdSZBtF=niH?}c;{3_WQ)y~!JK6Zn22xwpq50R&gWYfC-;+n{ zVr@-b+#Bx?C0!oBE7J4gSguT_M>(&!k@eG;af188a#7h*PA0y_3+KY7uQIVV<5)T<~M+x6+^Tc^Y7_Q>5iolFJD zCyT&-5xxDbi`JuJ`3}dVtwdghn&F{vYJ*)>GBBo60_3r<<=qIOq|auJlgSZV*Rr;W zXX?c0%DoD9T~$i;eNyV`YYKrHQsDhZqTQ!U zy_&|IV_BZUlCCK@vVCs7agOVzw}?v}?( zc>R5nMalL(ir&^+{ixRL)7Quz9%>bR$3K(;Rnj^05lD;=sGV-&U^`;jCJgw@3jb}M z89u1kmda6Ts}Ko_d5x%?S5o>mobgVLwST9(trr z+~I}I7sgP)2J~4llAJutDN{;`WAH48Ru8Vp3S&wqD-IIA?i|09_X0)EmLo$m%2rp4lnP`c`#FsHY zQ68G-AB_9UZY!T7Jz;CR`w&I$~ioI~VCW!8CpW6Pn_7(^yT@rHNuL&}tk zYDog^%M+pJh8DDCJ`aZ0&sNXf9Gq8t;G%2>lr{9Z)Pgu#vBUdvh`ZsmL7ouAmFJH{6-^A zWS-Md^q*|>xAi)I_H)?p5UdQ4 zkwX(bx+l9Q)VS<101-HxzU24ydBs!Y(;T_1FPgZM~g6bj=x71 zXRbmQF>r1$FJ$JV>>f>?-KYDkmE`cRwpFddozd3R;?;~^jQ8W~OG=B`t8kXlgXmpg zU_Tb&sK?#rtCO zx##ApUY~@+9Lz$;?(TagE?JaECBl8foieuH9hW{N0PYULxfgfhLwZuaoIvP-W= z3SQD#!;EuV0@mre5ab(VuhsfYR8YZ7fF+rK&=SAOZyx!^`1if{y_f)EEuOc z5?bjNtn+86D2`(7N7-Jy9Rz$0eX$ta_N|FQ)u|z3(kCd|6+@DPXVgbgY;i$# zNH!P+rxc$tK!a)1-3c%fn6wEDG!Hw;A)PFO$W11=(p%0dt)<2@yd}kfdz-ibJE1$} zs$+_zJt^O#Ws&kAZ2`qw@7fFIr3_vlM{h&TjP{Z$O=$YRJ*aiSOP%=I(JRtSE@`~i zdl3*{X$_jNk@nzXLckg?%+Hsl=DtRW28f5MH!9m7DcCb}`?^1Y~6=1YW$RPhx@-<+wG>tn=^Z?X%Gjb@l1{KCqQbvCnFRD7{07 z3kFm+TeE0~U?Th-L^m99tS#6rc0#@vurRrPI%AZ$o)-0~9 zN)WsNSZ2I?$T9ZNV9_8l=dIrL$-vgdWh-IcIlf`>$~>%aZ0fwcHmRtrn7$}N2#`g; zKOCkV8|5{ye&tek*F^I^M~V&Vw`O6p3+?|ZJ>q9BiAqMNqp$~s^m&@EQ5%TN1R5Xlh2BE+UCNO{7=q3 z$(1W16?2fl@2fXf+_Zo;q{*q!l8+?{COT^QTcksJ569C|3{>sH4sG@Tnwdncj|GruCDIj_oD^hDIft&3O=6#-7q_LLxHGGg&ZKTT+Wa*d73 zjqrW-kK6Z2u)wII#h-HHCYiJtR8St>7F zH>L#f?b(sg){MM@3zp9H+wUNPZ3}Xr-9-qH3A+G6>kay|Ocg7riSdYRyg6M$YH#d0`|?8ETPfVVi&(QGQWW! zUlU>lEw;SBTzm@-T{h~_quvv>{fQ@!T3Z9)J3A)&m7CgpmpnYWto}R=`p|}mBaKOD z5gMXYM7K+ey^(R$QoFIhs}sr53a+a z&!aW6V)t{=tpyQ5Av0B`t}^1(HGlF2{7=Y5UZw zmW4ta%_pZ*6_Ac7fZs20-!wG~NEg$vp~vK*w9M@#kP=aN0qJu%Pj?X%uF{v}K=-MYzA z&l5+d)C-DcM@Kdptm*N?`KFHsa|JF(wA+}R^;f9hehp!7nA;t^wQY=g&Zk%9y({L) z;yphiv$x2y*)YX{>`(x6UvnH&!voEnS=Fu8!WtcfTA=0cvFKleZAAR8S@2>n2Za8S z<9LN}{)tvGYCLZv?N0X}Y-!e<+g6SlVN-7nRiGC%i>n`)Y29K7DErt$qP4o_W= zxR=O|d$?jsORZ4fsj}vS+8fWY3dx0gmnGO^Fb>WVd(|Q>L_AJZ6%vn=XDWThbH`uK z^R%YGW8DP%ZJYWCSi_psy5rni9*D$h`#j0ymY=R``i6C>W&wfYM;)lf7p>#S-L{2H zugnE%GM_a=PIk@jym7lF*}h^coF?LQiZ`W=vlo01ZILjQyNAn(nKIsg9{$nkHiSkl zMmQqX1`46EbLaRZ(ssX6rceP448R?|1B7b3{X!(WVw$j_4~E|Lo6h6jxNxG*DTP&n zdz3xc*Ta^*HkHlOn>6imaxA`UoBqOj^tws8*j++arIe4+b4jel>m!C)n+9uXZkr8? zwW}X!*^MZGL60C|WgOna=TF!L5+U)sVrfxtAqulfz?S|yqt07E0r>MJbEo$19MoG* zV_&(gtV;7ufJT-AI!ZxwU~ILaIil_j2mWdLI`R`2_rj2&E4PQt!1v+FYsL*TTndLu z5X>3C71Zh4bAY`YVn6|yxf5_oC^7aWv9cV`jCD$c@Gu))<|=;BjZB~{F_ZMM`?XQFhuF_vu`hB|L|Z3 zU%mgycLde)4%(k*rw<{HKm<}IEm@+jH>sQvt@b7I-s=lcbEtgkU{<*Mcws=y*slj( zd#7&f2zJd_8yk{?lZ7w=fjx^29SsukE{IzT;2<#aug02G)lUiMIDeP9<7nHHw#^>F z6&kYTT%+g7aUO7Lcm!2F4(bvvS@S|P+$gM+SRjA2p;MVe#oZdW`^wLX1lt+M*0OW> znmm5&0tVDrsKig3eweBm_Gsg^usQ#3YdqkO$$KxmFxvCA4QHpv@9+QdU`+d=k$GwnMjgD+x?1xw?Dag}%#wvqvwPV-Kv3Yw$uA#n z8|xz!x`ZD?CReRGYY8U}lBaLK^3z51jLvdyc7>I&+HY#fEgek;w04hjZkOIyU)UF8 zu=D1>n(xf42nhW+XdHBF{?*ub-5_?62yv{t*Wwe(jCwj`mE}`jnf&ln*Nc6owW}CW z!IqofHD*7?sV!u6R`6Yw8*Es$Ikxzy7Ka#^68V#lifZcL{DtiBFUVE7F~a(ym17Md zfsXgDU>0e7`^g6uw{xxK4)j}Eby?}|>04fxC3WVYLqXFRi-Jf&S!;o>q#H^x`i`)= zeA3!m=6jHN+5p4agg=qjdPMBneWc)O6M6eA1bCa19vRiHeF^rxuVs6qwc%l#9k#9i z6FXFgD_f7Er=ocF?MkodWu|33gGs~ zUiFuQbB2w*-c_-KBfH_CElzgCxy>}&AAsE@-Pwi8 z8JD0x)OK&|thF-;Iym1>KL$lH?>HJU8-GH1ru?y4<8`=Gr8pITHS_zbEq=UWO+#NP z_~hii)5O6$yq>D0OLUV%JPtXRXy0>MlQOPTJ&WeOw|{T(-u93T{JRrXoj>-Z4v$v7 z^Qn#1OM1K$&ExvH$GJrzuVmLbHs_L78Lh4q{CB=|6L72KZZ2DAZMj$yikX9#+ID#N z%71rO>6ETbWOdD8DtmgGSZ@+NGH!hb);$*Wdq%7TAoK% z3V|{i=$VI%5di5ItqW7b8hx0LT}5jeX(rw{KtT8cb= zi|EgN67bYVape{JX7`)|TrDAXFRH{PwUKzpf^ZmyWbiW()Z6#&<#oqTJu6bl!2W#r zF{Nb|#`Y^g?;DDTnF{|duUh&4n0o7=w)XG)`&NNVi@Uo9DA3|kC=SIXcnMbA-C7(1 z1SwXm#T|mXLvV^a6fY3m3GzF=pXWRC{K*W%nK_)d?6uc=?KjO4Z;PdJ(btc1X%@a2 ze#iUGg&Jn#kfO{`GzRUAn$kI*`oFE3;c1_mzdR%bN%G+GV$RTU^JBYhG2^x>_%`NK zgZ>l+?0BA-6VFg3R&xQemg754DRmzg90Hf8gtHYLKKAv;IRUS%(LOedG^U2qtW=+Y(js=<6<3YFcXHiaQ>3!SfO2iFY{*Z%mVGJ$R={ zjD3}o&0|Q7bN5NOU{I$o>ya0!>#f6%)ZIpWNg_uYrNPcw;~z)_3F!OoAa%6iUNauQ z?9*HIzI-3r73jD+H0VYwO z?wMzC9or6M`x>xi_bCdx=BgXdNA3q*4J}6s)C|0C+x|WsQ! zbb3|5u3f^cto0s#aE}bT^u7oGCOwnAzom1&$)d3>q7)tgJviC(vo8GV{lxbh)@0BnxQkdG2-k zkJIt(558%z8*)gju~C;8j3>6^NTqiN194g!Xjyt(x)^bm3{}$|-L7Q$j=4iqXMpE? ziAomUfd|R4xF7ir>wnqn%9*3Q#^|Ddma_8Xtz7e~X{KWz=*|8WeC!0GnVcy@_b8$t z(?gaj5$LDPtomrS%PhOpKGZ1oWu#eZ zZsJ+&YuV@AilmC3!p@_YDivm8eI5FnSi)o!dwjGhcZJHSNoG9OXNnkx8%>iN9 z%Y4}@g&EEJb(c@O0L{bb7hifdO32>w))%uY70XMs`(6LCRF+28Cs`RL>p4qRylQw@ zhOAkB6Ln<|CTuy0`>L4E-NwI0_sM*kK&QcQ$$1UmzP8-Sx|LI3lzFD8f0Y_i+uCv)^s z^d8WCI2#}~CpO)@>Qz1K!g#7tL_*#Cj_$Oah(fAw#}VmlmY&% zxcYOIsJBCR5MK|6Z##pYyMhC4id=p0m)3|VMeJrv5jAj6g%7#m)zTZ&Jl=Ukb9DI$ zK2k*f%1xR@MD(&v*!)t=n(fsr!XuyIScvx9RmY6#J6(knYf; z0v4t!K5lL-W|e$eMn8Eln&59g; z{$D;u5MfUvs$BXlqjZ=+S3kiQ(-`~iRapTVll%-H-SlI&#LNuwR7}K+_*wksk1t6- zl=OHat26nPW+e3#k}^t*c*oWRgvq8)o5fA zpV5wuQVDZSiI0oZr{%CagE7QUIhL8LX4}}@7_e8-;+DJg)9fhbxMUMQgO_Bt`qE^o zH;g*>m9kc`9N;J|ykcsLWR&^#;6FDEP6MoGXqXeE!2KCX7g3+fE`!>Wzx;G_E_lNN zx+M61IKR_`7Y8(rxCXOQPA0s>QnHBk>HNbf_}!bUaGGW2`dq%LzlF|iIpy96c?OV? zy<`$N!um$b%u4Y!{)bkHI9>}Q3B@=Ztf8YpzQh?%Q(wTP33v)6h>VTPEwDWCfdD1 z;(A@`DXd2kGCS#!-Lhfhbu^qY#Mf|h0VPUmQ}4>>q;V5{X`_(e&@_lYNwrR4<9ZVM z(9W15(6^O7<=zFw^bwg>=wTC;-&4$wlh zkCk%Y{NkSyrC!c0+3zZR$j%TZ-YxFvyuljBjqls23c|KV4*!&Y#R{k{|48l^T{zdO zkeoW`qiDzBnncBfI1qEy7v0ti(ot3lL8YT^=|Q)8r7k!aYa?^ErI6HiItnYonbvKY zmqThDeL7!Sn8vdIQB;bb0~##=W)7S1q>2@B=!j`OYUMK>Pg$4yLp^|{3vYGD6N#l+ z@CnMHZS74KOc|*11GY`P_>2cIvpI|#1t0HUf-ljuUHThbDDh>R=Uf{M&&U2ThVPpZ ze>CDJvWB5I##X)w){X|FH|xYBR@W=;VwC9Rm}!`tZX6PP?|h_ zb%Qhi2vp(O^T0cz4NrV1aTT$NSxUG8J>_9eftvv3@Zdm9uvUESR1Bm0jcD0?TO}}8 zxgxU6)D@&zp-7pRf2luKU-QOPCz;6LCyKirY~McKY$?r@?^%J%OEDDWo7p;m&*jU| z<}k|LrpVIlYVJ39mZEUT{ib}*$^uxo@TK!u>jtNdk3Ej*n zWj_7RXs&mNbZ(&bM!3|xFhj{ohvb>LG(|LHt>NgLQ|_ov_Ik)-FSk4MI=vkQDY#Tf zqf=5UDPz-nmhsa?oQ|HMBKzm7!{vzO=6aKjzTNrc8F_SG6OX2R4=t9zxe^}3jeaAQ z)BL`g*32H@%;9#+$A*TK5`H=)S)U>W(sRnh(v-VGm(Xm}*39z@@Bg)$7Qaa2)-vqy zYb!;TGP1&Ue+TDjENhxI^)GCoY+nDow|~6d3HWh4_z$yv#yKJZs8r?q+Y)H4H@+`#K?K!(+&+K+UHV`pG$OrsH`h+Y+7*V-*!{7}e1*Y_oo!SRg?_(g>w}Kx zdX40{@oF}>0=P%lTn?YMKWyt{4_l(tZ4td_N z_wc5W@1ph8p}?XP`_e6o^=||;7W)X)y`mUDx2qsaGWl9Ken_V_PBUq8FQCF8f>~Qq ztlcfJp!;Ig=jrQZZ3+eoOy*^&q@)6siVY>4{h>O3;Wea4ef;it=E^W<>7%N<@}Hle zm7NQP!E0Ja0|f?A`E@rOukPDNk=L*5hxe&gIiveuo09NRbePZZ)mG#d(}Y@D{siIV zD(<|R?(1B2zw>q>UIe}Osi{QXAQoQKhGMr85*t2U082SX+Ec?(2b z6Dq!ht7l|pxN3;%E-;YVBfo^MndO}5+A`Z<6M-v>r*76e>xkmqEZoS1-ciQnNq$ld zPBKLfmRS&(Nb@;-G=9~d$NHJl9KM*|ud~Aj(SRAkw>lKk8-JGTTu)%M%uQv~)0`zx&Kh1&a0MN%~CO0Vq zZ}1&!GfUA&hQ&T73c?fD=*2ijM2ldIy4P^THDPKk3;WF41lg;oxxTn>aIvO7YPuf; za|U4r?~I^JT?9lG`G(f$Fbb7DTJ!JSg|GcE|DA?a^4k>X{9ysH*|WxEtV?H9^w<*@ z%uVlS_~k~^GvQYc4Z(5ZE*>WOSfO;iOnPGYr^WaFm3L$_A@l%&Ut} zZxo0CSf1UmP=9)(l^dsAxehWkP|j-sMVA}YqNlfNEv(fcHK_Y_a31yuDcv+PmvQB* zpUvuVtM7fp6+j{xWpqLcUPMtH!_E=2Jw^5q>Ij8LOj38Ls5+X91Eb5$;$Dq{Z2pD-$BFD~)vP-5WMoF^_jQ$&wV zkVis;(P=FZf}c>1&ALrF+)346H~W4hvx5>^=0y62gdj*(t)=XrNQ#{^DjiXE^Tb+? z5ad*bU%&dWVrW8~SeGhi28GS}?A+u@*=lt|-0(cGR6$acTs7Bsd~JR^V+ZxQo({M#JvWM=Wte%vLIRkIt=oJ)d?V?ZmR z)3Qy5e?)gRL=jzo^=LZ^E3i^VkqItPAF}hE7-xk3szgUqcXj{QgmGAT_LLLzuUEdn z<$sIK3EsjAIvNkCNya6N4HSxy`lhD5Ma6lZIp|9Hp)J_GP5nz-39~%tG9ze<=qO`0Le73N@bHUW0cgcxVLwD`~$6RWg zBIJmPlWFqc3L~hd_;PpBKlAi*(gt>HwKX}*Kz720A)_XSrCXA5eB)hrc4U<3`7D$+A^@R0n;S{>&;6b6uA8iB=`!2<>rGJqnLVUQAtI zN(^rt-!nhHK4(!nmoi!ge_p!$%_bNu&Q&{9t^L+(5{I1dOGwQQyD&dZ?Nb=VL3a4C zx(Tti10p*Z^|>arAUL1zUQ#*RuO~83Ffq|3Uh@;K&#JzB6|u5d)toex*p4u(OCc8* z(RD5tw&1NT?QNlFsO%`6nW#V5KMfmxIpf*Lc1iw`&0;GNGF{%bg^nMybx0~d6GPn` z_z7Ef{KIz6j2Y-czvt>|OKhFH2G7z#s0Z3|`Ax=xSa~?i8E@u1ZbElVUb@Lbg3bQ7 zH*n@P8yZ#m?|G4#tvy3{dUdwJxJ-oNJqh(cAwTTqz)!OK`RHr}X{j>O2$%ZwaYd*)$rOwj!Jyw}`seAJ2l}kg!?4PTBO3$DY zRF~+@=<%AdGp@GLz(K=-zY&K2aM@V?nz0$YdFdwGLy3t2Z&OP9k~)O5xy^o63~x98#n*-O?X{wB(+V!$ zs@-#z^}2mfJ2B0Ta5>8m>A6LUt3ggW`ww0e!X`g?tUp}E6??=i>s-J3bivSuJmmp# z>h6Qik_-{wYklDU_ujJ3u6!6K45eqJ76mq5$sv$Th;I`DH*qA1`=j}PE^{SQFBn1l z!|hjKNN#X&OwqGqX55UJ>7On|4cyhx))ybpozHT<=3-e%VB%p`vV zE~x5Nr|+5BHh^f#e``#AZ(}kdnxyTK{?#gKjUBki@=DLB3(sP^|AfR}axATU(R?%r zDlNOv27)SHesFzQwFDA#W(gafepkxgItEQ>*sdYa;3rMaCWB=GvOf$3w`nMaO(p$Y0<7*c^k-P9A4VIzn{8EM+sk^F% zaSVAv{5{$iA-zhqAAMvdYY$}RH%?4-%FsvKEi;S>bW6gKJ~w8w&pub($PLWRC1MNr z&tH};zg!|`VewT0N7C}j0S zDa8*3Vm_9_jcL0*-v5**ANPbSdZ4bQPGY(r7Fq%Zu(`676 zNe}LE%icp9mOD1)a53wLJT}h4!%G`i9UOZl#Eep5wIY;Nyz)Z&!Ef-i3v4`R|8Ifq z4g(A9KRV0=;4VLk>*8M(*;Hr>j4x0@d5U7RdQ1QdEOUX*eNKL-q~g$t(%Y@L;LHGI zx^D<_KugLgIg4e`nazCN8amO+Pl55CnKr(T7xl#6V%Y_d9F=x5Ynie6lx}G`@efWroA-nNO3dWH-2AcT%yD(GNYwnd-uth#B>rnkr7#jxmO#%SS%s^eMpWC~w14(KKH zicxNe#oDsfiK$)sQ!1 z)MHfm!dMpYV=voR&^Rh8dhg-bmg#{6BvKjzIV z(J|Ny10=*I+NuO;k)FFxG_m&Ftz@O|=sd+%q6gP}8hpHjpAt!t-LqQ>OG|BA_;V<` z?}`xj?-A3Uc=J~<(}F$_j)QL>p7tc6pIU78skJdXbQB5s8-7G!`1~+;&`^FQli3-2 zIvz_5uW8~Jq0Df0(6CSDk|tZe*;huFoU|aOH_FY@^wMvdV^6-Mdbe&~GXdesC~Y0v z$QxwV9g3*?kk~>A_dxQ@=rrd~#@N)fzM53D^VdbLd@y`ExeUj~kYKtQFmHGc7#NMy zs(xJ=K$q8?%~Wm6WvIh-SOXg?H*Ihg6^7wro??HO(R7GD;b_ z`^FvNmCL9!N8R4&rGP8c0ONJwF3AZ`Y`5R;JiT@#mX0qLEDH^-Vs#Qp2T?yTXQ%Q8 z2S%kWq)?sHebqiy2=KemYL+V+UJs>m#Xoq%4e1ifzq#lSTMr#{ccBxdYtEcaa0D6d zqF<#Ud}*kdaB`8}o=5sS#2J9C43%CQEqfNcL(HzL2|494Vwcq}?PGnVM{|Ux3ZUqWZ#Bm- zntu2i_wS9S+(~Z#Lh&`{-RaO{A6NTz#$QVTpxVr`0!Lt7dJ|OqVXxw|c)%(UX7H?^ zqBRczbAL3mv(fEN0n<1k;{Gm8;L(4DqW|bCe@>g=IJmOL|H3ROI=^ou10~zT=0&Tu zS#E`RklE%=^oMe`r&DUMe#5YbT`guIzdNTYt-Z9|;ycvj5h7{+Vd{pc>e5_b^TPE( zo(gu85d2PjRbg1@UiaYI8gQEv;OFGjr-HLy1r#9SlsG7=c4+=eEK?txB-izJ0 z?k3rz-KnOLLE`LZC>jz(%Zoxz(dcg9eOzq1GqT3fgiNJi{M1@&e5@@aDYr!8Mp?RR zuLoI$la$KOQfP?NLIU}R(&ZO6ao={NwFaD!hSDWix~ax*RS*hxus1C&0r?)KKmH-? z-IZIW>bT7^J%4Nw$Bc8)ef+8)`#k{~Sw&$WP&57~K*|U+qL(vBT5i*9Ma=GfYREJDDQ0D~kz!S+A-~n<@HeC1?J+++DK#7)0Sj_N;}{ z!n9b0v$hwi1REaoGR}F||F5ZCEA`)I-mrhFz^J45cI4%>e-n@-m76vyKRUtW2^S=6 z9t_KLL&fRq1uHnPxjPzjeSmx{=uwTpC%|?|ea*G)BFB8>H@eMVK9nK=TAebR$O{N5{N-bw2|a)vWn9#%lU zO|sb2jXPl+3Nuq;X=b2xU(Ia! zJeFZWCJ-Bc-q=FYJPMz)K1%PnQ-{#naKMN1(6rFNA}wQg!+rA1liYp`8}SjA(-vl) zt%b)-G~X&wN3z}Y^Pwg?g6L6Vk?}lSExJBE@5sDGf$IS_&+v!O!)lwn8O4DcbM-M9 z{2rp51N)bR%^5q|&J_MG*xAY>&Chh_I#0YDe<(D&3o;Sv3JZC^X8t1){QDlHtuQ{c zjpj0D_%jEYy`FUUW<@}qr!4Eqccm9l#hDncv*cNmt?wVIogekOq~_3b@ZEKK95M(t z*d737XMSIPW$OPh6bkwHLq2;_>c9A#^SJEy%-rIIw2k-VbnFTh5mQP18z8=wJk#Qw zt@b?%?>tks0`Dg?ORCAP|4VESH6BR6)b&}P9AdfgT{p9nwq^dVe4cXx&icCph*Vwj zi{H=#V6z`@s?VYoCTr0?4>WY2C^PHoXUs*nts@GRoBk#@PqVF4R2X%ed58@!$^fUX zg$A+-C^7$@-oU;fxemEGH2JBsP+j*&fm0F!bI#^0wB4+27mCk#yu)OE3uwVODFL_l zB%(fP;`g0%?!&Xjkj*T0wMY6c*QmB=^dtdcPzu0atujt|Ufg5(+uc@Yawp*NeL*qx z2Nn&~<=KHdEzi}}b&<#|aEf!w1QY|CL^7xGr;~BSdgS^9r7Q)MA+T>yJXbFBxxCmiaQojg*M7uk>6FX@Fxu}aa{>1`l}cv>XGjQW>`rV6pNF%nt-$t@w9mi|KYihGxZM&VD&V3ARc<+5t>e`oJ0-=~3S zR+%b;5HHt6V#cg`LA)<*xqF|8zfT@HuFn8$uXSiCqu0a@P~u*beHbxr)3v(At1S|x zIC71zeJ5Y9n&4|Qaj+$0wDZ6qcrMTRvdN(}@&Aw)e+65GzpL8N091`Oq+`5nd2soo zwe??G+%#N<0immlW&b?zj}#KBL$ebZaf*hG{_?-1NfxIbb%|i7H^yoTLK_fLPRTBm zfB0~_peWcD_&M$r(0KECODd-h!VnJ6s(cQ>!vupzxrS{UV1QXsI+~c=k2b^(Kb@pU ze+^`zGDmZRL#3TT!2=j2?D?vHy%C#+B$J#(w46z)2w-QIC%~~DUcm+46-}-UpaJZ4 zr7x%o{Tt3j`L~9cz2P)%jMok&2mmsv|Mqt$8gj%u|B=&EvvHY-xSp(dhzzZnt!|o$ zD76z54$e;q3dFJS6Uw;CHxn9IpccJj^hX7WAGg|M>}71~odcI37XE<+t;U8`hy2J1 zbG8#mMFEcoAg}={0Ki%UC?UE43#k-%4KrS8a2(pJV-sOM`^C^7>3q+Pe1zwfPB_%3Xc)x5)sfczi3f3ZTt9+IC zi>jD>t##wJ->AZMg#&cJvMi3~zc^~*`HCo^G=mgWJ;1r@2a+=LbMR_q$B%u%UT)gE zrvWBznvRpo!1&pQ@yx`j>rW)m?Q;WOpdIyO8*n6y0#%=7M$sn#C71g?IySJaM~ApI z#x>(TK056TW1GTrFysg7wc-C-f@;9m)|lx+$@+xHy!=s`z}~@?;fWtc-h2PKou z-V-Tin=FN@y2H=n%+^DuLKa!bqmB`mtAdcy11_r0Pt&|@{FNH53BNMC3uY5Z%nstF ziBEdZnkNaGrTbRiZD8iL#-mVD7TFF4AZKxk)OE#yeQMdVeyG`fp=fY!3srMeka@$4 zXu-u;HR0xMViy&vE@us7hWYjT!@NXwK6EI8S}38D)W}vCg_( z-(AsUYx?EdhL%bQP0zABTXX%SCWhxkFk-s)ao*gvMd|6#GDIv1?GxSqt2*A? z@p}%!pSX`)@`<6W-pgrlDC?>l@ZaY+c5pQhJT-aG(MJ8J_q!YFKV41IO(^&_Tdc^T z>v!--A{;K#mbt*ceFrwmok&?m2}Dfz_@izb<$GLck-n(bB!3kW1M0;54}< znnm7{+1$%P8Pb(m#hHmn!wC8z=sWj)HQ!AdEb0hZ zHdLU;b-$4mr@8TZQZQ{2C6uRF{OfI}g~WHM^uB*=5d29cfi3c!84O7SF*!^U%5OyO z#o$WQoEx8ZYg97Z+NaYyUtD{%T0v_L!;6tZ7O zf+B{6<=xlNxDg-9eb~vF4U*=XMEQ{t2_^3xm;*ayk9tg$mdmwKd-Le*Z#X@X{7ltR zP_eCdWrLWyc?CWuv(2+Tct<-G_4Vvpcj9YgN^qi8_MkjM&th8Rly)-D+pzD?fEeN% zFZWQ{j&qczMK_PVa4B_x5M%CHr=nXhU?TLbIVF2Klit(x>i{6}>=W#DKTamJs3=ca zH@FI;E*HV5KeHmK`#OHnvjv<@F@I#k4P_(#Ag0ntI1N`9>i%Q*GE|!@0kpMY9)NIZ z;stx~xz!|yWpQNClpW@rP7vT8-4iJ;5E9-{qGV&zJ?Bkwnn^VSw)ri)9_NA_=#fpa zHe_2$Q!pMl26@^r$AkjHsj==)Yjat&%{U%W;+IE{4@bf@PdV>fIjidK@BHqr$1AQg zYn3nBay>oRu_}h~H=6^nB7p%~opW|?{Eyqa_licNmR}msRPl*WURgXJ8tRL4>s^jA zY4rOS7YVg@?zYV|ChINU*uL{tsE&x{P=hncgvubJxhO{eu`@5#5>fHOt$1*pW^LasN1&_(n<#d{v^3ty1A zp5sBkKBvM|$vm&}bVlI*SFHc70Eo1XfN$rI5dL3t2+h><#yosWWggs&h(S+3<=mxN zA4A{7eMup%$w{{!l#uVa{JW&*L~9AZH^9V~xAOXQR^k|9eJF6lsn8K12+^&(`k7W( zuFr~Vso6!%#+0A&7{({>Y5><7l`8?~9YDj2_aGheF%G!@XVv%2F)9$x`pcgDpVkDd z48@BnqPzv?iJQF=AA>NXj6Fcx8k+M46!Nd;*Am!RXhv`Q7kGcpUbht}OZ`aD>~VwS z9+3O`U0DLeJVH!e6y=?dp_$!mFD;;9tbY7n$}u<7F{zutrJ=K(z2;oDw!aHAl<${G z@53pn?<)s980=VE73D1J+<_IDF(0km8?56-CSX)`;YsEr%O;u@%HU`p%MDo|7fp(T>d6o2P&qk56Qnv-@M=&{F8@Cz6N`)$vb% z&?oHZTk5~Z;gd6DIzE0P&5rSQ(my1F^-UXGPp=$|GsxTno0Xn?lpTvrQ&tS zQ-XsB94c>b|89&L(hK$Pc$MF#^Z54NStSIym?#?@;5YDp01>mG;QG^tz!q zz@fiVTx(tzyZe3`@2`*Rq|2R{{QU&w=+_T~*;>NQ;T!U7Yj!E%9wWnTH{Rw~TI+*9 zNA!kmYi@o@#0G>F+iu9MoAEhP$yQ~e4Eyr~?R_UH##WiXY2`3*YxZ4>T+1^4@b0*K zrOK|ZSd5Qz_hixpo~SxO_r`Ub&Z|UEOJYZczP&c%ioH^kE^%6VyH*~gAf+U|S(oBY zS}fBRN}u98{yj!6UzXb(V!~&`)|G1bHGB1nm}aws^jz#hw0#P%v6ow6?IgRenK+|& zJRH2a=C+DC7qu~~Uut(uu-=SI=OzLb?*)j(roOw7Q8$a0DNP2NJ5z-h!+l2!qWwpI zYH!2)KHV|}m*cqL_a4ehq&Zbd4Eq!xES6>zYGKZim z0M_xyS8fkz5YB?B7&HFJW#(=>kGCgQ8Cw5(`0QI}r3*F#G$z~lij2>!Cm zdf3)6#jOb2+D6p&%R_p5G$ORJtp*(Y&rwDHL?)xvp@e31Ldg_C`F!RE-S-OuPHj>2 zjH72zE#E#UlWVyNF(s5~TfmuWvH}ycto(kjM51Q7P{y&x;@94SiUO4hA^wA&5R$6> z0)gFlL{46D0=~Z8|9K?!pE&SeCGnr3i?jL#6kg^2vWK{HyJU$|L1lItcHmaQhHrJ$ z{Y405pc~R#5()Rc05H1@L(_F8rv0HPb4Zmm~T$ zQPX2N|DP(l{uf@wc*I7OT022(nQfZ7Qp3IZ{spe$SShJb{e0;s-T=sU zARwy1Wu2|b&y>{cp!5fIn+{|w)nICR^Y?6>)HWciz1o=;u146ZfNERUE`m9f;`N zxw26;rhw6C6S)@Whq^(oV+&kL{& z$jgpU5_v>Bq5n9W?Ol`PCZ}G}ME(Fn;Hj$1oN%Ss()&FoXFhK6w*SP@LKc9_OOBmM zIFvGmG~?**dK1Q!pA!tZ|NI7~qq6=^$%f;-+9@+~X+&V8PfePAK^Sy=ncZNgJh|7Q6IVXiz*tU~@?tQj^3Zln|4f<&r zdTRa|UJe@!gOrnhn2GsDo4D^ww`k!)0%PYU7WJA4_Kht1G9r*J>tcWfaIH@pFvXZJ z({ntx#2}DiH@3^viX3qBw3d-4wqNK`95o$p!^hC3l#JGKbTjj>C#kkE>@r7{la^ni zjD>ZFe2>Pq^MWZX_=)s=SM>2h?$yrVLYHsLwKid$Y;uFWzMOYP*Cv_X^J2vDnHi;& z#UFn=i3j+-g>4O%kjh~cpqXjY6e;_~gnQ}^Iu?008sWfdrO3jLI#vilOfUuVp|OZ( zTB1w##sSMODxzq&Htt;E##xqUq)X;5&*r7CVTSy*y&J-4^AWUN<)Aj%%qwsoPp`yB z9pN)5zHW1PeNNwHo`!zq_sY<8$>dvG%`B~n(OPM%x$brGjsQX7$7Na@;}*}3g$C$1 z`UrG|L7st@5@4R-n5e%EEGT}IcFXZ;XqdwZ*l|FwCW<1(t2YDtFt~za5gH{jT+V33p&4vOrg~@@7=uY^x1>%9;IHre_$a?9L2GRbpiQt$NJzw1~}c?$zd03C2d(h_C6)&#Blv290zJ=NAY+H zjHYm(dWX?ZNM)MWRmM1@9yVYZPWnv$7BMi*B8w#5{qGEQrbNccAVqfm&~> zr!h$;b7)DUE?2sLVjtFi8`3)%6$W1taj0B~Uc5cc3@dU82f);vC4zu%!< zhd`&|+;?%L=*tST>)H!p=5{xo)w=}t;_u+U20zl7hrju8mOeq_QtIN7vmQ4sn?pE` zG>`_%H~W4MjbYxnDJ0)=QsTNJxOy_b1q6ogl0ZR^DE~R9BI!(>AeWN+%5$*bm0J6f zWkUGZqFf0o*43d=V+TA;Kuebnj&4Wu7p~@JfxD&~vdS&5*}u&M!s(CqpGkl@1gHPt zszRnu8mwZ&N?v^B=YQqp2gEnG&Dz!l;M&k+#7($4U-W4t8kru9YkM|!(lmOxPJ=-4 ztH7ef#-IG~6NUv-EoxbwwuDFycev?E;>&sbw2HEo1DT_n=~CaauhO|xm)$Gt?nYyX z^J=!X>{Q=n;bIe$4SLhp?8Yvy{3sMLV3c$=W$vu&KB+R>%bVbrm~>$3p*T&;bsEVx z9@XFhg}O=j^P%Z+h<{`Bp63KqqBcglE@!>hl5F$JBM15O7_(k+)+xC1v=Zs<|DZ}5 zo%253o_Hq?3xIsTBoEu}CVUDNi!o~f#ynuNIfBOa;s`;uvOb^1sr#jokzT$c3BaTQ z_#2A1qXROUefPxQW0doAd{O6pxX(Gkq4cl)TI{4}EUwT&UC9!@ncN4Gn{U#fd=wvM zmwA1ax(^8prS984)8?r-08gxE(O_5&txQNvwU78S*K%UyKH@6lowQxw+p{7cY8Wucc$2kOjym+F_glBW7Ma!9M;?b7Bh&S+U;__gK9L|N}44vL}xO*ZA8HHN@wl5_M7 zGXl4{G*hYo%nS+O{{`qAD_Xd~HuJaEILyjfmt~u^ufT_*@$4^{ zsX1y()NS3vJOTJ^-EGK?y-B0m{AZ+oS`{5JF~62@{MWYJ)Az)y)t4m?Swb@^GJCM4 zzSRc-6d^xR*9`4c{8adKkeKE?y^ApE6 z5t~~882k*f2`3e=U^gnvl;Xm7T43`3jV(S9&_QIL9bKT3_JS10{rlq|dx#Ye`ig(d z78`TyUA*E8BKgSMBhjy+`l9$f6XA+!(rF%ZZmO+>n9=m}T-}p)aA;HLEB|t#FjEsD zVB)W!6^>`!cWNm0_72U@1pq^fE?;vC!+-e-%Ag#-N020B7FPAZMJ4bi!SHuP!ag2bmFd}p;U9rn0 z^EA7WHP9MD;aSU;R~Dwk-Ss7f8lOxqkFO78I~hZ_?mthx!Y7jW$17g3A;vmrF{JkA z;PWI=7QeSxN#QyD%Grr7wEa!y-Row_;|dhUUAIZWyos*~?M!xLJAA@!%LsZbZ8McV zmaLHrKsk^Lfuqxv8+^EkQp$Y+Ye}p`MbvHAM6A-Bii>2_UhkeT5%%=00OU6QINLLu z$0XsRzp>2kWli2OVFjG=fDa@}0z$XEWxwhES0xiYke#l6{?|{wh@QNZY&2XM89hfY z;qJOy0U_Pi7mBs`M0D|GS+W4NICqoV3^H!_V?uD2+#Eu2!$@#yx|h5tjW=MX!d4>E zzrwW?0pgP>X8U)9TiuO7U!H4skAz%RSf<5xtjmu)sT`A*!l9Eg%+uuP1(AvHyHTG} zG`LHW$?A>zxfmIFGeck$rnJ2{WqoIJ#07Qc=nj9LDI9Y@hzjQdt?5c&TFg(X7>q7=U>RmMiDLE)+L8V3vZ$^}EXRawO*LWd4sI>sMZ{fADZzd|4ha@%@cDC^> z#VDnwz@-H}&_HDBgL(F<%w{OJArX15DU23Zd}>ThtZh0)`y^vT%%QK(o`pKdbr`|Z zY(X~kR57BXZvj46tX}=(MlRaxfs|&OvHhOdtI1+QO>A%bq%qUD{y6TPG9X;$-~B{N zW+&_3Nr1tvt;1BnU*}500>P*~oJdJ`rN{do;_8XxkaNF z5_IX3u_BxpU7(1#eCYMDG`w$3n7b&0%*^j!IICG+7ObFv$t?2~J6l^b{+i7SIsr!v z?)L-Vgr^sK6?pHk9nggn#uK2oU)Z#oq}K}ix3 z>7?D{E&89dvk5c}R=u8u1=aZ3h_h!*wbjz+7r{ph{gNiMDX*d$COU{&$;E1i_Y7uU0J=fuX1_G zX$P@80>-0!mW}(`cu&B^|5{T0oZhdeeA=T$E~7!wbNG#GCMvk1kn)d$Y@tH?u+HM` z+WTI+7>yCP56@nIF3F#2E0UWdWV!4Fx-M4abRl%Dm*;Jx?zrr8&z+Pu8JL^h4SSx& zNS8)x`0TR5ufq++d&3kw{vTU!71n0kb?rWNC{PG3uEm`~ixe#siWZ6ohoHqZIJ6W` z3GPj#Tll>($=n`{oeg8X47{!^=?!lr25&<4scLL- z(&l7>&EV2ea4V$dwGz7b4Kg-*rlK##P6S=pdeZAG=xiyFHFksSUzp`;(-1^T#Peh} znX%^DWmBGw)sQMwJ4IK#cp0av6A?6nkJ2O6NtKwtVOpjH% zDF%L;>=pW;g_4BgMtUXK+mhQC%+_triJ8_ zF4Ab7(X%jXr0?Sm1T7?K925IiP<>C>Kpnk$x`|*HkEq+xFb{T=D#IntDM|Emq1in6 zcxo3tp;)}~h?uNuWTIE|O$|m+RV>;h-S6@DuwcU0Nm3x`=J0jklBFWr3esM77-dev z=$ZBi##H39WsMd*q-yxt$VN=JNiDi%wCCl(as5gx{O$KI5Q#}P$B2b8lfwhV^I))d zXxw;ML7HqMOA;QUxV?i{f=cxLmq47WI4O9E1=ll7zajHD^3OIrO!h-3uSxq4!wm+U*I5Sh>#j zE{M;VS>{{I-0Xn-Y3^}*`pFo4NlI=8@h^D%*ZV&-b&17xR9kG|FE z@?The{xVgM_u1!sHQ_c~{PtA$YSqmzCHnW)?CtegJNAO#^|c@6Oj5zs;<{hwr?~|0 zIK-&yN2!fziior9W_MG0evxKG>tuO+_u0+qAQ^nl9P^+#?VsF9TW1EDkE*n3x4)Ie z|Je|Cr{Gl&U-LH!S-1#gI6C%`3QPpENeRh&QK-s%r?-G4?e8CUzfRq7KMcS~(ZfV( zp3pj6GclO&wDGgW6ie-xmWJl4)iC?Tj&$pM%~ij8xB5i`N$Io~e%YG*@KNqs_4DWplKF$BT+Y{D_U5Lpq?w=cV_qKL z-zn7fuV(c1wpWt>CVv@6EFO8_w0-~d@LEHA#`owi&5JJuiRzRy%Iup4{$_Unz~5BV zMI2R}r8r{XL^wU94F%Uu6yWQ3#Lx;~HzFhsM|Q_73R(#*iBQzt5PG4U8Zy%BssbLf z5}{wiUFtj~`vDTlv4~W;p0@aBf(J0Se+|TRKhZ8WQDMI)T^~Y5XI+SgL(FOJ0~zi; z;W3IJ$)v{;`kG71T4HNL+2fRUP6vtJ+bp7XufR@Y?yMfw6Hr3ypeNvKxCm}mnsr#a zpt2xII7{faK{cp{OEE5H9ZGLCe*d>`=^Ay5)#}0HB-9`IzfqBcq#O)woR;hgGFxRv z=iHHk{ArRC71zlH;U7TuPq>yrm~K`3!NNDeJ|1VdXBpQr8idbbdOUXRc~c*nLEJW! za;h2~{#M_*TvxQqtTS-p;0I*1>yio_-R}9v`=~V%Lc@bBNQ8}DXW5m=QjI`)a0q1K z08%4;6anv`UT~FLO8#tC`WtbfGsTvx0;iusiPdC?^sg2sPpsE`@1WaZ8Ts7Y&viQV zkF{u=c4u{|!RB`hlHAvG;E)muKqydNOW;HMOyVH_VUOGD*UO9erfB;!>PdWgAH|1F zqQtU5vYWgGe|y=8BLch~2Zu{5({sDHICY&w>06u{gBIjcci9cZi7}$T2)Tvg-DYKo zT*_ZPX$fvOxI)fVkGJaFxvLf`+?_*=K;v*(BaL14S zHO*7`ru&7V>nZQ`WCBpW4R+P@dQVK45gFUZ^My7d`a+s!sQK-m7hcSWZRKhM?ul)* zr)RzXgn{_D(|8%%=z?&lz8~+Z(h1aYBr|cMM<=@0NAVK))Pmb};8fQ<{|?DNBZPXY zw9?~=2Fh7q3OdJljr1P^0T#Oeyn%p9?d>@1^fAW?!<}d7g&OGfB{)^Qn<(|^)7^4u&7Km42! zTDZt=cr7LxO0j%lc^^9LJq9c+uKeLyQCK6ntaTD#>eZL&$SAN%$isTSQY#tsXkB`_ z;%hAPZ0^nMv9N>XTt2dev&)AT6onZbg2Nxc3_O&3($Y(m=R5r!^t;&)^``Ut;B$ zpEnTp2>hE>L&CYd2ziG@YC5BXAA=fMCZOU2r4%0KPzw1_D>(fr8SPmmk}wCtSIm=_ z@;v-acTRR!-=~*5;tfi>0&Ko-v^`T#ugB3&d;WTka^f{TZ@M|mSxU>Oa6r+^5M!Th z)A(|X^hOAc%R^#}Q6RZYiC)N6CUbpknu6Cy08)GDVC!C)5zcD>T|Xik6N(=^YAN~1 z6D(qzHF@&BeUn$jGY{xm-g+CFgo!(rnUe%%Y|r*c-0ye>3zaFcMOO0PQX5Adg{E4# zG~l{_<_ePzXz+G?B2dMWR!J_SNhSYHuM&oAxFEIL1j`0>JRpn}N}b8wd%=&e zcF@tjY~7E#HYS(0OK+zgT|AIn?mi^=La+rqEZiSY5FxCA9mT9ncCHBH)tU02ebfoq z-RX6BzPHw9UR;C=88=Yu3!h*CwQwDjA-p28QkxQvIarbwt*iVxBrZfOio#ZKE~+y> zhy(#43dml~P`(=XVPI6=9DAwMwYHpu2iuBR>K22$fS_cTWIten6EC5Bi((K@6dDqq zu-PUFQ6mm<`s|`WY-pq&?WSKrtf_?1|^D1yX1zzD^zNv)rpLYYiYvbXb>3@s2 zTmwNA5xhoYs(7V5#@eU5+Guibj;QEAA=u%fYp^K<;?Wq8U1cx<{dY>vh86bg7C(VQZ zIGLVxLk%MJbQ!>)rdsAUX;Gb+zw0#-0$B1-Zm&)aqr-eK3lnaBLYviX<+>s0ru511 zyyfednuT%EQo%-E!wYVTw;3eMJ>8|BVI+jECDXY+_#ReDNo#S_ye74BkxXnFd0%s< zWQ7$Ob~iSN=m!|n7CaoEUy(@taQGdT``VfD5>nSeYrO-uGaH_dE{+<{49~W3GVI*P z{ga@VMC|dQ{LIP=|8%Lw z?fIzg_vf5WiVBtd^(~a6`s-NR5Qd3Uvhz*XYW`;m>%JkABbrbfBn;j$EHge_vhc}f zZg}!3=Z2;w@(gn|%g6uxQ>Bo=2enTpzKl)(DYv{4&ye)|_thk&3_kmr<5H~6 zn|VQCe{brkBlM?7XVq)uI!i1*;d$nJTWnr^G^=9Q*lxm5*)nOA6NhF4ABS=fyMq%R z`B&pMuWG@O64mPDFkI7_H}F_C;z3yy}hNY0TX^qg-oxZW((DjaZ=* z4T>BkH}e{;=oVBl)s<&P#am{7n*?Pq3igIcABMBjIM%SwWq-RsNu4O*^1)xJX}st- zuoUT{fgaI2kMw5fQt@js53&Zq1-1_)z5Wo!6Ppg#8CK%Q;U8mi9}peD{%Rk;?WMVZ zlN^}jx_^16pMBub-pN2E&XK?q`+oBma&kww4c!LW(0eO>W*~OG(Y+KnAZ}tZp@`Ju zE>98@e@F~Cj>P}ibaYi8Mo}JZz5emm7Id{%3H1VU%y?YmJ1ZE%ca}roo5{!SnI^mR z16&MSlhu7G^<4}}EX1ygtWlvAxkNP?yTaeUuz%Z6FwM9G7Ff+UdtoZ;g=G5=mMJcS1X3jpC(2R=JV8>M0XAHi+LoCOOxYWnlm=mq^5uQ{64vem zn)0*gWW?=mS}UYk%)hoY>hf$1x%^Ig@FiNAqhCgY`(U_VaNQQj6Z}0UIz}RctHb` z^6o#2Xh+B&d?MGUppl^;02r#K8=r7@WX}#sd3UPu8OO1)m=rmDqkC5#L;}~k1vXom zDZi}K%)d<6=Y`>$T>}Mgn~039tSOt{f=Nlg9s~c@0cJm#h;(CZEsJ5Cth4;;%B?0I z)p&8A7lRBpJ)^laj-JSNA#wJ!uNdNQpKIWQjUFv4eqmt_iv9P{1n(uSN)nXYiB_EQ@4ZL5m8zBPkCsiWO3AGIs6Bo z^Do4WS#(1oIiMu0-+NZtE3JlbZ~bn%2GP3y#eF6pO9z=yd|x<0#%`xw@7`(61$QH=JPp){M<_8dkm#6+)bNiPPM%4CHG!zUafog0kLLY}CXGZ_b|) z5=RVuG+wbN)rO@4;a=bKy64)t(v4|q4c}hfUVA7eQeUce0ie#rd{OmpP-6eEQ zVaGkOWl6pve|PX#4}EkKc16C99Lh%pB^s}`gDxe>p(3!8Md{rrPOPkLxS|ZR;jncT z>_vtc`N1JgB9@wzZ*dEV|*l;9QNXLBp$E)?qN0=!FMATYQr|{L*$)ph=oH8?X>++ zGBHBLSu~`$Vki8p!c?(8br$r?Po0*A@IcBIu+oFfbm2>cZ94;#-+$ptf(HFw5EPTS z4kNHGpS&!rz`|?l58|~Ww6@K-*Xf&(g?I2Rx&nK=m`AjAaQ&d(PTWb`Thmhw@hv~z zAgDcA>A`#J3n$Gr35QnJ*x#h`rigmF7og(J;1vE$0iACpujJXAqW9Y5FJI@EW^~!| zfjF}Ct`a4>l#Xzw;8@-I>y353F`b$992`Mz2IZo=T6 zH0gC+4TQ$(aVc0a>Yx%rb|sGW;eN_{Hk@b1TD1DiZPV<>=}0CV;j-zV*Bu7xcbG`g zVje#(iuL371TgVd8GLH@t2J5&FUl&nmqiN7%lpKYJ5H2#4ABi;;MI4gG+p~4`Y>Xx zxYgFOmF)K?{WA2qf{G_Nf0lk>IP}U*oxAF7vCNNPGBh&D1jM6EeHE)KZ+Yw)%2%D? z7Du05fZQP5!+W5%q2xrd%Aw#9yTcZW%(l)by@OK7*MN$R;^*qWeF7;*E zcG$T@3YCwD>Ar@r>?no@#Oe&N<|2QGUQ=7$%$w+@2AcZ^bkrYeQ;55C6NT*@)Zr9 zCrCm33l|pXNNE!rZF0ccIp;|&vz45>u218f#w23!hUx)~i4s;qBMc7^4F9Zez)T$X zED397aZy(gy7bDwcDJ*)>Lm62sM&kL=NjHrCNlHOM;6790slU`B*tXeY}HtBF-6c& zbmM9Qa{ldfe(6O}w^w)05rO~Wj9x~5<+>uZVd{#ySJr6Sju~TB>rEzE5ro zJvg&Co9xMVETtQ2Ctv4ljuABa+=pwr9(L57Hy((7{h3O?_KEOQT}Fe0G^shQ-%T5; znlzNoshBC)Qz$pN^n&%;t^~4?TVOBH|GbHG&cxg%;cOD^tadAAfrMRA8_i~f3{B^v zQFcI5c(+kTOQ#Q&XpWac^#NM0sZj>V?rC?id*B+8gA$)##19|%y8i85P9?OLD_!!z z(TS|d)7xhse7jLPU&5AL7`iX{J%6bDMMvo(D!kTkqx|a_n4jsMpVhCfeS`M$qfzgt zg0}nTtfzy*^Opk*=krx<$iRFv;GL1L^BaC>XN1BAj zwIMLxVnSwXk`})Xk!6FO5!QpbQSNg=8gad$bFtD+2(i+USJhi@SjtyTD7R~5O?l|A z&tVDBi`|!d!7J`eo8}9zcaHFzZ=;X!H$yI&lKm7Ft!8yQU6_3mUU$ivVaQTLiJdbo zx;$_Xw&RW>8kw{2@=3_3c2;Vt2H#hY#CP;v4i`i%%T9)0^&i(*96aG0KZ)!=w)n!O zp0};|5ZKKqh?k~Sa>PKmFHxm7LhbW=>e5}pYLg4nNd>lY>l!}A(?0;QnAU;#|A%;{ z!kY%3zr5Ifa=w-leDzN27194Tzh~t`(_By&ThtSoTKS$rLmj*|^Bsq$#;o$3GGWb0 zPcesZCK<@@gx^-bPfIREt{p6Pe}4z1kJ$sema8Sq-hM>$70&IM-}8lH&D-qJo3n-6 zKDD>vC71rse<@vm3?9onT~cnoVMn1ZUw2&`1gO&Hm$JPIIsK0JsBU3FtaDImCy3C z;zMbq7?k3~w7+k9ZFJAlW)MGMkC?|A<- zKkE66FZOggz(k9k=l46WzCj5Nzn^nYhzGqAospf|HaDm-sA zgVQgXoh+*spXjhgYjUL9XbBnmj0eyAlh#*4o)HJ3*Bm>r+0C;ZyHvD@Arrsx#rnIt ziuOM`i};meQN3T;Y8W$Lq(>GhgJk91`=M)eQ-{ZX_vMA8QYpZwEn;?~bF~A>{3R$~ zt(lY^PM7?lOGsRl@;NxAOUt;LNEx@!2Sw*dfB3jF$?$`iL!-&265(jdNOcDB{rafSj_wP->w9Iz-!}bFnyB4V#m(n(zDdfVyFBNrr1i zaCBL<3o>=4uvt;RkFFttJHHGKNpOE-4Q`jm=JAV8vs4n)W?xgvT&CoH|EQWx&lKmA zE!jk@Uau<)Gy_*a8!ZieX2#>|JPEwBAHz!alSg!@(2~{F3$U2fieqTv`ZEpe23g?^ zla#VH%A@26JFlp`GOyj>$yi6c0g}RI#Bx9BDDK|5bK3hx%T@$SL-!;Sw&xDwoddrx zzTAIV`m{N`n9-mF8}GeQtM<7estfxUkqfp)QXQThP}{q-l?n9@3GGW$MBQGT#e^LM!p&%(Af&!@ zdUQM$tDmT0W`o5Tajd*5ppP=TYOj{yU~|0LJaQE zrF&ak3DpdhiLx{KBKOehghRT;$RH1WdgHeuz&7)fL zC2HZl1EQbJ`u+?)yXJJf4*e2((gJ%j=W-=K#!tq=W;6}KL5-~>Pq?&wq$c{siV5X) z94-&-pc(Hr4@#kn+9uUQI1-W<#%f}vS#NyWdsynPzf|eVM}n%qh=ZjMjM{fcA@G4l z=I1w0hdwW@*HS}Vjq^YHN96DkeZ@U{c}k{a>tf1b>;psd1wD(YQ48?lbGq=s$oj@p z9H=ru%;es%Ro8ir#I)3UPpZ?FeQYOy5!Gv8VNYe9wUT>t)24To?T6Bw5~m2oN(Z8t zKb@v|T{OLjcw#Po+EgBa=2idVe(PbPDiPuG={q5u%XiLO`S$lQqDH#{_wzt2N`zwU zvZ2cc#-oZ#&~GC*t-91OLta6q%{uBXb20q*u;{DSeD){eSYvaNRtY*t*LOyc zu8pGG*1<@R4G%uf1kLKgb^uj2=9+SoR7~}NZapLS3C@11Nfg35#qUMlUKP(rlXo3u z*QgRcXGSrIn2kr-Odz$lz;ep&ZBq*AV-rQ)byA`7z$K^}u^-l#?e4vdEmZi$?HY_- zuzPSu)u=Os>v^&vZbKum(;1K1Fwsd!Fb0-(9uC*BX4(!^BuC)5@Nu8CL!ryznIvrV zUXkKhO?g{w5nhP-|s`ikxVTw z3I>;X9FjiLI~GuIZtV#Z+}A2kQjAO$E&B}4yvjr6?YgB{rkE?%a2T|2wxE2Ds^{Kq zO!n@WCbhk70rHYe%cs>5XTYt?T{6eBs2QxGz#7TTsNc3vzm0D+3gX@sFVvLFSKp?kX1K5S>TQ0X7 zRn@YXy5&QGo(6Lgx+B?ivD|#Gy`|F~;v7n)cYx5lL?kwtDDXilfu4%{(2FzocuIUD zGb`#dB23ApCe_(8iQ%mCRpugK>l#T4Hvv#pAx}Q^k8K3Od(;2gn%IVTQO5CVZiYPB zyzhYW;)w6ej%73wkhfel#~WCn7W31sz$JP4RW|OuG_Hc^;e;BE97`F8l$pmpLyhhZ zitu->(d!gA*ve_-9zo)i3>Dze*f94~-^FL96R|(w*rg>z*Evoj!N-H5pMQ?JiT4dsXpet^z@&x{ z`i4oA;=$a1+luRW8yAKzuRxsIUMvO1=-s&-ng zo1-$2?I1kLm|qY^>jC$|SkqEjB3qG9nxCs+S7Pi~eUIM;No#Td8K`Kml-|z!7!bE+ zrRIQmH5FExvJe~e1k+XLS5iCBFx_VFf@X(4g3qz|$RcLADkx^2Xy2W%w{cW5>B|$H zu9M(ATN4%{UMjWQ2n9=p=#MOQXKUgQ3ewvvU?11b?qXi>%iKERYE}O$jEfqyAsfy4 z*EF1#)P6|KN?4^JA1kb_MQAp5Z`Ejbaj#Hu0_2fg_yBP`jq|4vrI#p_#p{T;gXy`x z%Td0=g7r0gF>_gYRw>TSuW325HN7+kID8lTa$c|B`=HaDPKXgCdRZBxN~=ZfE-Lvs zH0{D;PEzV9{PhF(v2&vB+CG(aGs#Pw=k-cr!j$eHeLg2~^38R(m(T^l_#i=y^av6b ztsS~*PVRqA{IY2ri4zLX-8|>@e&LRVH*H1ksoKQ!ndfS4S7xVzqT$W}{Dc^_o|%ZF z-;gLY2)0`~JoVULU_5=A#|t;B(=4%pi?E*&qyzr&2^m8l*NpMG&iz-Q+Ujy8ajWez zIyH$C;fTY8Q?7;_HrRI!fHG0U_*r&mMz@xC-rNT#0SA0O^tJ> z@3R3iIOCeQIQ+qc0U<;RQL{9avB+VD(9)_--(`laSzaYe9R$n$h>`AQOOapmqv>-{ z4kuTW_Rq6wQvHHUZo|Esb+#$ojOWNKf|=>Ya`E7?kpoR{2(vDKP1J+YTj7Uw5ex?Kk@U3p5i zvwInH3YcFb2{P-fyf=&ohkqacBoFBq{z~u2W*tmhwc+{bt4vM_A2hD~XcyJa)kZ~% zng|I3@=PqyZDmNOW)1q8AX)~Z&~wv$a;2kE^M`N@yFUg>UV2Rj%@C}q*;1V@lR+B9!h2&FY+-26a?R(<)p@;8*hmSwho-g-)+!0|1 zCYK=uGJ5pxKgbZza{B`Ii#ufNya7jSe90+!^!Bl&GNyugV8%aEzse#hSLSY|Bm zSny8+U4ZOb=1*=QpXlcK!rp|Og~&_ZG+9^aii{awvWUm_P0onRPQ?B=))H)m0^lot zq$0sN5m0x#AN*`jg5~-LQ9AraAS5v0_+y&(9du#O%Y64DQK%l2GS98vcdHU5Ri1A+edEV=aiT+`dwb zkli$an%!bGI%g^=Ja|@SU`Yq!v~P(^TrZHPC&6)5Jv5o3Ib}v0fo>dd}eYR9D*lnV=urJxL+kG zKq*lnb>o1*3b)yh$xo$!xL0TVv3+^%{lKXUO;BGH_`P!tZSVadbuw_Qe!4g}!p4i| zkIc>pip?PGVSS3K`E=mrMiFts$LMz?_>zTUatrM<>^(XNfksfn^jSTy%%}QD1`+oi zIpcWx?r#tagMLT{ap?Q0z}gwDjC*xol!m|Z6F>OQ`+&3mT?&ZLRgnE)n3XH^bXhYi$Kes zFP{!aSpU`nXnEnk?#VDFvR$RhN!QoCw1pg3qnJKf$l)NfuUEG_c`hVFTTV->)T7-IV^)|2&gIkZ=5aMX3o ztEpekdwg>hN;RHG*rYg-5~heu>q%W#u&-SGxpBR{=d-DpqZe94qa19SwR7%iPjcy@ z`QOv}UkV7Yl_oVUEo5PnJN^*+DXA>`n}#H<3)Lgd&}aSu|3h96S@kt!R5~nv&i9q;LiV9sdBK(6Zh!FleS9OoBGv+Qix4tPd70VANQ;6eI1{!lJ%>!N zXLp?;AxYmugr&F(8`T8YvI$v%{IKt@T+!U@sD-h^!5QgLxO60P?3vGE&Z*bA=+NK4 zcz{jt%b6-MoLZq}*C)fIZEXMx8>ejxX^jwKXpfs7m&Ytijy>eDW3FpY<-K0 zBG#L?GpKshXUPaxBR5To*TRHqu54Y8QSqORy0nkDM~c^F`$3=5#4YXnUq@-b{u ztx`9YdlOcOJ|Dm!$Td^->J{BcAK{d!O+-S2g}c@E@1yY#!kRS5P@?D$jon1i(X$L7 zvC6#q)zkEbjPghZDtd$e04>Fc+iyyw3=}v_`zT~Q*!BQ&^%D-A#{KJ$Nq9oSpLsA6q{=*{>)G zucM9b&!r4?17R_3{7htX9J0w&fXfXuWea2!&dTR8ce|O~82kR-kxY!$f1#}~VSZ8Y zSexSy@aT&v-X8Ff4X0;(eiCKCU6FV~Oe073oSO~Gm-LjFu2QqC^uN6&(Z7KP|JijB z03-nu0B|x!kfzvQp2nw1M^3jk(MzuD`Vhy~BHT68sfbw=P-HjU@mm^g!5@O`GY|Fn zRIeW0la(^ETXB`i+BcJ2p)ak-y*AWug_gLi<1KDCh`+y%nt`8iKc^dx@Q$`8*k+b& zsvGtBc6p%x{mu>YA41-pD+F@Kp?%CDxz1I*x6IB*BWBa}`;#!WNL|m$W53+7h6tLo z$_XxC?_1v#>40aY$7r*4H>YUF5+&hL0GQ-}Z^&p>&isEqrCP(-%}mJZ!7_DOwvCb) zt)Yl#`|hpB)6$0ip%*xIXtpFaVhJD|;L02MNMRdcR^m;6xc3{wBvHg0;=u91;_b_t zH}mXglthOvukfF&U9?mQkep$|7_4H`Tb=d}HQj+|4siCb5f84&O-@Nk>4ryr%iBC) zA-8)Fg_3r}Bb)}`GzJiOWlJ*2?nDJceY5{mzqqv*ahxuhvmg?XTHdme%`U5t{O3kS z0T+;kMUh-?kdO2+?`6ZYy^FuM=iG%#hi`#KWdNU1C*QUhIoow=Oofx0oc+?0z*hHuNn=NKPjxFI%nHk9Rh#5{!SQtC|)yP@Tuy5INM&_L&aVZRlT8`r+o(EU}sI`PuO#RcVVHo%`FDg{L2$ zNuP2Ka4DX37Sd{>aLG#fIf5cqip+(zQ(WREV$%1c;!1qLs1!`cxAUhL2-WaxsCql> zO)X#B+{O^2aNxnU0X8fo!75d|Z5nVdg-KBL*{U;g1g$U6v55dSz>Z=qXBBT zAN)DxNiSExsv{$B$d9-hm1Wk#WXc>Kj0_3`$g}@6_x1_ydDW<1`fD@6m zV%y1qTM)uID;$<)t`*bcs6CQhhrT(N1L<-|(PnF<>Bm$6nH# zlr6RjjEL4+`EhvVD&jfGc)bm$zdLKy>kt*&|1oo}H-rU-yt{~&3)tCrU=I0_tEDq8 zC-pKaD3;g5G$5qwnG(a(&A(>qGJ6@K4Smyfd>?{G&Z6h{Ux{Wa?znzFk&;(sifL#x zsGb-a8l55Vs-9onTLAQzu1}|~G0w(*W?nj*ic*|AeCW>I?KXg_tm8uy?@dlL!M$kX z@(*(k9oL^esG|RII-Y`?9Vv6vRkmuB;hOa4U9l3wUoPuGFKe|RQH3h39d>`=>gmZ% zEIw32HK0h<&NJ)PYh2=&#)0ilA~<}w3a6O^B0gmnqpU7?5fQnVhoyNqQvMULWG*^y zSO;~2oK~Q|Wpj_LPH3-#6pi#}k9$uC{kZnaCWG_3fL3vgnl8(eTG9mG+UH`4KjE`2 zB7)}xTBwc2$QnEcy=%<_%$ejC6BX8p+h5n;WzJ@3URc(VlL+RSO*$P?Zdq~B3#;U` zoY;tQmM0+{nQ??!!Ylk9@^TwWm_6j6-^mDBq|l)ji=ye zH9i?TE&J=S&yhGZ^!zhKzRQhF4dI_v+0yK{fhXAz^Ia>3b;BiH z+tjI#y0#VDA31oj5CCiY@(}>VU_Mo2cL(x94x{A$s8S52kI{>V$)e3BJugIxiW{98 z`z6jh9+ze3OZc{+%R7%hxxQH-Znu}f8sR3%{(1c7*^XY%;CRiWDBWOp&7F7r4QoYV zRf0_xd}~8yHFOm6(UGTgc}M9=47hY9lgJq`}qMUJ7w5vwIa1{ zy-XH?EGhyJ2&9a5O-r|zDg7zJOjM$HyvTv_ z(28!SFh(}NgB(et6pDa=R7#Y<9uG>R4OnNR7r{a0b|zgg1bxhSEg?eWkBkq7BA{Hu zW*z;WG{cXdwjre~yrYc43@Crs&bR#ShfdSV7gJTx7dt;3yKP+G#B`|KV>?_XsPArr z#5y2OJwGd^m;$Zz?5JS9dMAz z{iAQe1_lD&9|!R}Ardyb?7s=>ue(X0a1sqWYLwQCcr|v9(;)^?$YbB1ox?Wd0Hlos zr-^wksq-*hwK_w#{AsFHw=d|p=vUz~Ne%3G%P``aPFDGe%zwu?fmqGf%sjHh#7>6@=|A1)Qqev}%o)z0n%aEA44Z zE2Ee#2Yj`BP*-5K36lnhYI+=7l>dD>&&A=QSO_Khs?a4xsY+J*E7$j7(qzv9Oru`^ zD$!tEUf)%5vVbP{{pDJibWUtK?(k(3!GQir>WSpW8gq&XSCdo#lFb z?+p*l$+~y%@gq4CfLcaw_wJ;S6HA*xv(i)SnH0L74)?pxvRO6#=sswor|=hxVNYE~ z404PZxf!rJ=sF;SPOi<-Z?%>CBkDEc|MU1`(7^g-xwJQw?BZhZsEO~}(6~cGfzP|p zU!x`yA(;&*6So3BDo5)9Qta>YzmV`0OY!;usy&Ggf;9ROP5Z-)Y1$p(TN)lE9cHC2)a_OEnoLO3`rFSdpFK5yH?WmEK$3I1(ws zZ%K(KkmWzc?j9AAiMffAEhb>Ez)GOC{-~-;Gm5YKI;v9R`#oRLVoP8b;LT>RtEb$_ ze~W3fZN`sBoGZS6Z-^uBR<+Fc+56EO9TCItp)=#&Gz;C{pb5{PCa?$w9{J@! zIIxnNz-e~0ao!)cxQy)ErvOvOE-JCmgy)QV9cARUst&c@0DK(D2k? zcs$v}(TW^irDfditR?jxF-Oo~zu)8EJU!|_W)Kmn{K}uc9D}eXMR8w>_D!K?oJ0Lz zS8O$|LRxW!hloAa|46_>dd>S1^LT+{5olmR4ge<)#*vI~4+gl+24M$Q>mf zuw4g8i&!qnaV0$h8)WE*bn7&s{`VB@zxQg$RzFAl8S3WZ9tyMeQfq`L_O}{JU0D*a zR&3}2!|#nALuRV`l0wH@>dNc&;7%Y~Y~GF|B1lNZw^Ol7!HMa3I#z3fub_VB+Z@jHMU zizDK^lUMznSDu~J;LhiEI<1Oa{$^=0^3s;6NWSjflz-yaPrRE)a;L@W7|QYbY$}1T zs&eNGBddRTS|&Ds44ncbe-vB#j;p0F{(lxyu!hP%9j$=ge62!+bmN_8;sos@HO-YQ zON$u#uY#bLS(UFX2*k;5h>G%M)qS-B%Y61PoWEE5g!k4J?ky;6MvP9pAQOA}nWLy} zRAsTNmL1x6o-SM6+~03hA4*x@9A1<`1SMl>3EWU0L*e!rVJm&$jA3mMkuA$T4tg!p zeC!?-pV*@o=h)C4s|ktg#5Lh@X`h#i@+fUI*yw)|uS$>17+HiSNj7eHMMe#dMx|Kx z%>=$4P(#9ka-&9$RD`OvYGJbMB<6n^5JqHz-(>%2N!eB9h8Iq*?n+19eB84>6!Uyw zq7!!4Q39qLJ&rtJ`rbh&W$dW+M+u~$@U$ka5k7oSA;QrXSpAT4QkGSvtKQE;z6LD_No+{n>32zTa-kvDpfKyM#0pQ*fJEoUb8Aq zTEI5yUJMF^y5?P;xelBA{51m-G+4Tstt9s`+G1ozFRi3x})+Z zKj%InGj3W)djd8nzA3Qn{A8k8##TNedvJ!$WoPK8ZwSro?OSD>otz`yOpO5#6+Ul# zKBdgf7Er0suaI$>C&}!*fa71dvcf^G-7t8Nolf0$w$(PA2$Z z6PX!Q&n00nx%^S6zj@gaaYwu+d)Y}{S@7|BohXa|hNq|Bn3V{hQnoU__Ytb63#O## z#BnxACpitZf(}=7Hx)-y7|d}&ZcFgGcTc|NGN;8LJ5k!IUB6o4a!il}3GQomsvtDA z1xL9J2~?3+g(lqMzef;~sde|w(_WKttode-hDh&d_wBNGwn=s|*oQ|vKB`E-N`53E zTe#(2b;rrPW6_;nlo{2#xeELJ^|(p)VWDup1gu$_4pK2pc*z^9s2r6r;D^r#O1u7q zoQqGx`N;54M!_eF<&#_(+zS||eV@nxxD8r+C%pMkb&NZ&wvYbt%?Z@yAaF?QZ7ADB zpo`0a#=63UNFFc^&v(xlbd>s^d3gEj@KsSZ2ch9-gT8c4%=%QRBPt}uPx7Ujv4jQ3 z|8q&v|HaEY3!C-nkc|%D1O>hYX|SY83YikpaeiKyetPP8HqEjXF~4S}^wa*^Z{(>y znZ)&?fzn8HY?t6RN-+$|zx?T4y2MysS$|7ficKX|lW1pz9a`xTY%;r(8wt^zl8!XI z96l!G_{fSYJeo~Z_j7Q&{gAieO+GK~;%1$|187oRM6aMWMf#}aa1t4ZKTBRB;ZDkJ>0;eu|IFp6;Z%{_hbJH z-ue%n_ut+Kx%i)F5EcLpEu9-Hkc(k5_mDMxK;o6;i*E3?Ny!quZW8R`uwN>Ns;uMa z8?Kt)UU<3MkWghzr6c>N(+%=#b2GM!#q(>%5rSQtB29y1nG=Zht*ngVWr}ir#-DIc z?)K^U*N;`qx57&)yx>UXrheZmUMj{HM`0zoXM3%QcO?bL-Wq&E{H1iQ9c3Kefehm)ciEzJcwbC4)nEemkd+9EzGSMRkDNk+-ELUo4syyXftVsb$`*)%grp)e& z?=@L#$C?kh5BG%t7sF)KZinsW6FcX0c>!V#x2I8gs>0TZ{gXQ_1O7fCI*iwCrZ-_m zyO&)b(DD1~?Tc^mI+3K{ZY}|Qu(8+F4+Y(;^8EbL^PsJY=3 zh50?ympP*9!d9;CVm}YFL9N${o*d@LH(r1mU+9tU18JL!fjAS{(arUoYtOs&$yk_r zV4hTV(56GfY(3;+cq!YlvwDr$jwBuB`M}9ulitgZfEZOi9c?l&k!YT!dAl-u%F_%y z+Pa;;N=I&j>f4ADdl7kYVq|Re5Uzok)Nq$eG%)Kl4=6}9bM68lgY@S0xUs)d zUX+EeI`n}xA)UK39z%cc!WaK7>;QJ|uCr16_oRi~l_%4mcViSg=Wmf88NwBlSBg3O zGN91Ci3x-ySljd#Gu-m%IbI3`5k;K2h&QD7UL;q!5koXNRtRcLcuQ=II;0}ti$ z#+x$uJ?0JeT?n1rd?1f)IrG1NC~dP10AW8$6b=$}{b2SJJ}Rvu^AmoZwE-??_W3{b z<}xD>k=ekl*=I6njKHs$S0QURI?KwHyyR>mlKbh_GAAT+sJaH;=XhgEUn zkE3y<;b?f(*{3v@J{31Q$((acIFa{|QKipe7^SHlTYI(y&%Nehce38Ldvr_>YX7s&M5UbZ zz5)6|!`d1FqcecBe6gE06**2CZOR#CzU3(xPtIH!Z_|cO@J^m#66Oh5-f#D)x2+r6 zI(2T2E?3rvfD<{Pk(~4R(!R>VKeurn28~}jhAtNFZIZwLBSuyD9uS8$#+z&xa)7uG zlSQL8H)0Ryx~Equ)hr=G^1V)qO?CIbcUy0Y)FyATQXLMdpz(|o6NjKguD#a8mz~o+ zIwoZlW{w>Y_svji^CpHD*H@Z!#iP~wqX*Lax~)seo4Dglw2^57er>)h@x+Fv*`XS@eCuAoT9(4vNS7r?F5Dw9Bgr!zrP0q!JdEyUoLH~fRs>( z4v!bs;2X5+i^tY#?sPqEq3x^lJ)O;AZmn2B+%yg=~CE=Mg1{3HB&u;LWAh=6gAV9HFq``ta!2<+sOK}LLP=Zt3-MvU~cY+lS1S?($@`XP4^M3EQ{(r5r z)?Se0$Ub{!&s=lO3~!2`YZ1Bd6j|#zi9i0`B>%Rb z3J#SGx;|Fx1O0;vhWeEk*a$+c*OoL+M4160!FxVuxI{}FAMB!Bjm2}0{6JJ2#}$T8 ztoa*kz@wq5uL?@RYx(4`wGX8oOc{(Z>pI$&*0Erdo3GDYDdHg;_&WZ{^E29(c%x}m zAGPmLLRO0lJq=M&q2d~B$*ugLwtq?}_t}wm|Htve^UG{s5S~Y@CWzv1DVMd({2h9k zvV>9fZJSqx`sy&tjIG({@{KY82RkBvgsxlFif}BM{lY^20KtPNVPmB($q!e)gzM-F z-3?{3C1r;J^k2?ww#exYEK_v8=tgI7kSfLrL+TjDBa{HpxPJUeJ&#g^6i>$ivWQ1Lgl z%Mo_V@NUZ`wYCz}aQpEuyFLdb2Jv<4M4C?%lT07c*0;V-kiV_TubO|pr7h8H-Yn2L zv?mjaY@u!UDY;>!{hjuqDvCB4@sAm$%A@=z35`_jVTPTdaSLL%DX4+BP%iz>k3S5f zW+>X34y^1#jVN2$xlzBPhtku{ge%XacSeooxFR0ZEObSCElNH>JPLSS5YFP*ybsDI^;H!`V<$_4pMV{88@8OLk8;oV4 zRB}dMFra>MNhr*RBsaM2tJ`Gfd25H{b|p>RBztL>#;~p42TAVE;eNignyji?eGtCM zyIHcdv43sI+^_O+3V_hSPz}-Q!AQ9UXIFY-&V}obt<->3R|?|~eNh>u=15)E$E|1$ zd{QWj@xd#Ra3N>fVZWOPAGVe`TxcS=mL|RSs>ZqK;?B zMdq}p?HoZmEP-09OCGMA2HRUJ>DpvK@o~EwWu9J!aJ`_ZTA$ze4r6Ajtn@@;Mr<)` zri#oI3iBPFoZ#Cc6^LRNP3Yse7)q7_X1dqzcE46iM;5_5NvrK@?hvwa#fSUBV`{kp z96>+N9`lGW=Kz}9Gd>nK<=6V$q1FvPC&{&-+ve5j9$hD;mV=U9rlxUjB|5n8ev8nF zB|lc&6MMPE*C3Tql^2k{N%OX0La~PGptUj==g^Qhey$$<2HVm1qe^vB?&P_ z>b{)s#`+=B!pEHf?2v%sMXF3XNryPH;-z@M$T?`Z{wJ$jtcznuVW<(7uG(1I+BCJV zpCV7UTe+0BN_)Gtn+spklP>3QSrMIoD^vUVo1J0g*4>12arrzGa2?;{4zylM%%Jy& z*ZCfC8k*#3FE_|0w5Y0qB&g^#kBwo{bf8hbXO4Im_khIDi*e6nt^2^XYtALD3;pQl zSaPO%`g&7c$*kQ(*_UEO647Rcsj>Jv3iM1%&Jz1OXH=u&TIXM9pKYgUp|z$;gf~zftFF*y2CU)c#XG@NePbq}`_!uO~=L$G_lv%I04*uEvs;EKMoM zeGfkAr=Y__u5q>t$RO9wkSHRliQl3dK~67l1xKztFz?VP1bg}9bgyQTx=66-AlLE+ zdO?hCrq`>{jkHl^18dC2Dz)BpbOZsGBWHR5-ua@+f!KcunQC!j&DTJm8NLtX(xidZ z*QEIHuR}brS4T`~qotxQT;t7Oldwl`14S9>jBeP_Fky}L|8_R556-MleIlo2P_bo@ zz@T~Z7B|VBD?Su_jcxcG_(}cXZ3?A}YC!jlZBV>02{z@5*!XF9HB(f;~%-X z?w;#<26a6)Tj~iv3&(hkuz<(`3fa_n*k~mcMWunS2u!jk$M6X6ms>*0O;5(^XHzR9GjJ%UdVaE|?YFG3243}5s96qsA*YL z8+P7zYpPOZ2gmN1QxjY>^shnZvqcVrgf?b z>;sKhMxtzcJ1dy zgF0#!2pezO+`u~pj%**A%lFQ%s!v#VG-;>nSo?g3Eox3?B@Lu5To!zqb~kqNol<$L zTKYQfCbZnO{n=;8H}x^D4_``2+w#Wk`(GYEtzIJ_AiV$O72}lQq6A*T&K+Z`I3kl^T3?9rBYPG*B}=K)*^!nNtFEF8PYA;fch zkm=iG@t6V#0)O$BnQ46iC}=`Csa$yq3gNpt#hi^ji52}8Q}OPqNjX#+aU^-vU7FJ% zyelHOA`JL+!jiP=zW^M@8Jzu-;^SK@GH2u%V^lhy@8fepdu%K6iKcNJl=9@c*{aN= z%vJiaBPFr;jSd$Mpm$cYxD~}!#O7A4oVnvX*#S;dbnR?4e9EP&ECJxn47?naYl%%Z z&K0gCj|v>M1z~5g^v%Z^2k()elQxNE@EP<6BcV|8KjPcIO=DsynE6RQhH03Cgle?x zhU38-&;;(`0nfoLMvwlPbMy?N=0S(^quu36*RTsTqVxogxxX;jdE2b>?8LJZMnML6 zsP4AZYV4j;C^x5CwplT*Z9BC&a6Aoz9g8ZtQe#Bi!=~5DxMdkOftZV7+&Lzk;=6iE zw&eWi2?^@(yJx)d7g?}ymXP+{cR!H^^AoRKZ{(+^Yayf7VcfO=C@r}awiGpN@S8S=^6*bP~92rh02mvbeF?#q+wDyRe22Pmnh(l zjr4w6M)Owur;LQG=Ge&Y;We}}w60&~jh}I8)3fD$Zi<CW?}|I$Te`^)*Zh zaD>cq?+b?$cNXV0<R2ut&ug27T{qjcO75e!Cl$ z78~)#fe~$AsGUo9emnJLd(*ss(y7VRpJ{S(+VsviuEA8;e0w#=$*1XYvA60B)|EyC z9=uZzvZKkZ%NZ!4vST#bQ^X4`GoZBq0x$y0*|ArX@~ey zO*La`dFFZ)Q#OFA@tM411iesKjCHTNA`B=&Tn>6UmpZ?CEHlh_TofI@SFNP0Tum@wE zo@bITj_?x1bo~^{G5=_Ey*Qa*_+{`8X-a&+Jj~NV`}wVM4AvNehE=w6Hj++Q?6 zTL;KF%J6ODVT@flKQi?XxA%>wpXN{%3k3pi1M-bZmFXf-1*;-$La0(3Y>r7|>>c@9 zYQx-_V!~o(wkPaGQ?$!eITfw|{aeMF-B=Zf5)JjOuUS7Ezw;W5S3a^Tq>b{IjvA{? zR7=ob_3uX~23AD!*hsymM{dI8M6rkNx_S-r_ z8Yjk|kaiTQwsNA36Dmc41L*8A;+?ttpVL42yJih6(d%>R$~(Dsm(Ti|b3-{fxPnX-#4tWFZ=liuoG2I0-fn z&nm}M$M&Ao^Qdj7xC{3l>SrU?ab1Ut!}SeTUu&C9-xnnw+}3u1*s&PhS~YbPkJnJr zZ#Y@~IOnEpM@XieBC+_BS-+EUZd6Omiegidt2(@(=14nfVbp7P)MJd+q`YP@fTM3| zc9LcQhvk88UzPq7K7eQ{#w;pHe_TcTK<^)TLw!#%W$Um^&1PW-?c%*&j3rbwbrQAe zyaElC?fdb)3rbj_Hm}nlZp@C*5cYP1k?!Qw)#{bcihuUcE7}K; zt#bHqiudOQK6k(|W|iK;@lY84oKcaUBEW;K&>JK9`k2t6`+7J88Cfu`5Ufg&@*LC@oJ zqXgId%V)cF{0Q1Q4K3OSoiOKt*qX>74rYqZ_UTw`NurxllCvbm0W*oO{89t?uZ&Bl zj#yLk+sS8NizMCA0Oopw54iq#(%7*=2qrW0@Sv1a}dE2DLZG=ffJVX8;7=)5~Q0Wy$zRX1CtJR zY{n*cjb+(UZ z_V*cr?`U#8mW^7a)w={7i?O<9wbg?h@CTvYM$Dlt*&C+$P;=wJ!{H}1n~vuXfB z0u@gUF{sPMk8*R)g;5onaGg)R)mxr*v>P^ZFS8;XH(XgyDh}?vq-j1zSImN3!V(S= zxsrjC#8!U1=Es83{CAUq;Tu!Z9UDJng?G!S_>!9CGeza+k#Sly-dfnpAFZ49c~^A3 zRbcD!MsCn{O73J})<%Cn(sv9fLE&tm3_2IM@^(2mmowKWUrOE1;>RYGp2^X8h11b} z@6wZcuiwe)5r1$_$H;GUF5nAcCvGY{j%Z1KVaEu+dI7)-CH{!$9MN#OK||3HoZ9fE z>laUKlQob%J`SaQ({xmu-_)-4riISc6bV_WAP=RR7ohT`)F}^3#E+BBTRbkwXF~PN z%FTl;Q7mDo^ZKpC8Inf(U(5tf+YK75MwoM+fvqP%qpkBN^6dNbyYu1_s#m&VVog7L z6iMDw42$lKI-b?_gyNFhj2z8vw0$LS?d7w^)oBu~*{i;huAc<0Ik&hZ7O+xSXi*+D zwN$7@;%*gf<|#GrPKJS;NkbjXI4|UF?l^6o)Q^D%B5K!|qFv_=p1yaqUbYQ`#rVNb z!|~0#z3xCofkdG&Ne|x?x^V+bE4&|My;6DSOcBR+!T6>+T=Z>Zsaunn8FVX10bB;W zBYidU@3TF({+de7Wfwi9!lar-nJho0J_1~uVa>##GEaSP`9T`Yrm z-pN~C{8Ps=lsx%bVep6Xiqta-s8-JuxFcbxOn!>2PTFQ#%AKo0RfHmw4DzX zXFUXZk4E!+!<~2TJmE7Ua)t2r+N?L^oE*9kUC^JR=`U{G0%EWS{s(^J$1yiE>{B*) z!jr;b3P=ZCeWa)ALS5K0M>cp?y#y=6Zdc{vsJhu?BiZ?9hwoK^w#{ZcSbvBU1@ z5nUFJu>ZawSv^<6U`f*a=o#O)6A8bo)7Fz={v+zhE5e*t$1#rBv(B8seKQqE4ny*r z**8bSkFfd)_ifu89lt=HYzy2daU0Qiq7IK4p(YSI@UKLp}0PV)1co< z{%GGFBBHn>?yv^QdJ6?pY@6H&S$zwowp@O!{>ZPyGT~UgHg~Z32bTig(i<<<-kC@* zEh1%=6y4>c=q~XlRey0WQ*OepF(6E}c!{;Jxm6W?sa$NKm_|}<)aj)=+%>(`Z_d9P zen=$oxoYJXp~ReHf1J7IrRn5oCP^hO`|P0B%uD&QLO?szyf6*OG4|;U+96O8A|(Jim=>Eklq{ zc0D{-IWe`E(e?bEusavQhQdtgnfICDx#)yN9PvjZc&c}NrZH<)-g!Gw2r93F*Psu> zX*INfZ{xJwR7PQhygCRg6e{;}J>S(pNU~(wA(!awLJYO5};y z%T7NQBa({h)*>d(@nsH1xy z>efQcM-BP{_cr7k7I*9WWN^Fl!U*O=BhRk-smKg8%l4N%o2LOye@G!&#J`=1tVUxe zfXr>tzRw4oW`cIp*KS|jiM?F^{M?pdeKb!-Y1S08Z=3vZEM6E4{x=NZAd^XqXrb`ts5KJ zNZp%+9oOWjlB5jSHN`f7Rsmrxt>Y=iGsiG+wdv<_$r;61-w|^Wi>wE(eQFdZih^Bi z_()-kL7fLrvB?&=uJ|O^V#skze?=dN8lsf;cu+fyJItXz(MC2899qEa8B`<+lV4+} zGRgM#pN;$G7>M8vyn*&okwe+ZO>oUsY@I4uqJ><+jH(XJczI9lq#zU1V$W)ua80za zF}K$Ea?$XX*PfD;9ruOmeDhblb!STuT2k@_Wz05>=*BKYAT0oL=l9AW~An#?Vyf ztW(g~9c`Ur{dc<;F$vn@6Y*?b9Cj08Hsi&wK1Ct3wqR$CfKqz(-K6pnB11o)U2#xj z@h^jYOs;Rjcyl3eK=y58_ru18OkZ7Ovh%)CqtGy5;Az!i^4aQ%&<2|h*|K@OZ*OIs z89K;!$^z6XBI0h29V$*9LH<|vFMG) zM~%egxQBd05lR~u-NCi^8-W3)oaK{t$(MvwjvBMG>iRsf<6Q)Y`UmtqVL`43X->Ev z&&^1g6a|$G;ftOHw*$dEXT*G1kowvhILU2kI0%U}j&Cu=qX79-N455y?&I^=i`+}4 zw0T8lJD(5b9=lPA9^}$nKZHupEnhfs(Y4m)9@6)DO3k{8-AMrD+a%WAms1&SbRhRU z^fWJysPFKJF}4EAKssC{Xd*VM*>c{c=<-qqV zKR}(PR-EbKTR0SpIlgJ0G{{CWJq@bVUOSZrtnqEVQu^aij-5HAR?we$c4Yfw+E6f& z58CcMsitoBfLFD6to)wxpTn=0UXZM_`WYXrvslvTj?MBI#+leXP zfg~<7IY|1F^ZP*;i_$x|r`g(5TB#JcOYBor|v;&6%-ZAIh9c>wnpq}wKsLkMG>9~pqbbhK^Hl2CZRV~XeE z`)au-p=FI$z=dTY#s3C;B?p#!68d$-Pyvwg?bY)vgVbwZnd zen0v!Ct%Zt_0UVYs-f~^Nr7ccx`v}e;Wf@PeAXgYcsP+?&cO_0yZNEYv?=RH)>@F@ zw?BTiFBPR95b4;Aj})6w?!0|n$QLp$Xk(S2M5m(|D%a#BasE75j#hFAPQVA#=vz$( z9~7Nd0x!_sa`Dh#aD(+Jc&@@in5?=x;V_chwd4K8LwnJ|w%zm>d^ZnJnez4_h*~$+ zhuK2?j=qJ;o8}|;|GAVEM|sUV-N9i*n%^Zm{}eJK51x@%Wm`RWn&&Jo1qtSyb4@uu z5ctmjRM2w5gW=7o#};u4-l3c6jWBAviTTh1Bx+evU3#}gg~&L@2YVJ7TsjG>$}5t`~rRchj7YsJ#m3eR8E zgPxfW$#vB#LZh(=^3u%_Koc(Kv4vy?EuyW36o@xDsOiKP4eNH@NyDAAF$mh=@#dl9 z6SmPni%yFlTR-)(lMGr{m}eqamF5)F4m1q@+-6W(F-RkBA7WE<1T64j`sLr5K;Dac zFOmc^I>#?r>FcXU6o=;|-%wx2Zy;pb^$E+~-KfsfW%^66-2ULU4u5+%<3|@9KrRiY z9KbvmCh5AP88ZW~(>q>jcxn{Eai6+(Op`;JMJHfO{^W%9sd7}s{L`e@gOn(v z;=#VtgedUwb~4^3Z)(D0xUqqiB-_;~Fr(|`?iyC|rSra``}H7Bq-eSz{3w$Fo_q4G zVz6W^fh2avqtrG&_e9|XXN>s~PD zkQ9W>Yywv$0|JyjGenOfWEgYev~o;&aT$LiHd!yIz|aY=b@qw$0E&^} zlgDd$u;|?8Z`w8>zXYF-zQPHKB5gZ*$6ZI9x239maTsK_3Tc)%jMjm$$E26?Io0kP#n>^QlvZ@mVGBdi%@R#8!>k?E&tL(X(7*-Y^+5(jmZ&BJp9+EQ8#b6Bl=sj z#cwHt23%Yf2bp;uJ}n08?USk*conz4CM!V(Ea3Or;Tw*eF%Y$3tc<{g&bj&VBuN?+ z#O5^7e8rOhHEB!OZFJ9VDFXL0)C`#?ceo589jDIZ)) z7aCls;cp=Mr;wh+6ArtB1y*cKnpRM3HzNk~d@}my3zWzIj8ittUYu%~+U2x1U#$@T zL1CJQ9Ww*%e`&2rWaKYz=$$31PGvAB>FNX}k*Ug3SISa89GW0ax{`x3Zq(1;W8-D= zM52^RDe4#XG#*V}@gKC3QWzQiwa@;8!c~3A+%1V!D`a@CdG&0F$2AMJ7$1>2c5d0t zQ{T7V=P2wU@N>kaHOaVIJ?5jfBF^1<#H&YfoL)(Nb+n3hn9*J#j+#v;d!jja$^4H` z&0@{F`{#WHJj9KaaueC>*9Uefx9x8PPPBOtvk!E)OWo``-+aUoWO+6qD` zu~9WbBSWyXU&k&zO}}EStmQnTRR!G@o6nPyI0X8xe|%bK0{($m-S}9K zi<1GCa$9~kc0lK_&6_#+8VXynvikuL!@U3&hCF)XR6(b+BIrcGD$0ECNFP-y;}{$H zEl;mfy4W7Itpe}S!_QX^$N*iVypXb?OomlUsbL3xMlXhvYFA~_>&2cCX9ZgBB zI{SS;{w6#Z-z5#Bbj4lj6$sfe-71^w%1_J1z1d;xoWihGr2E#y1^?N=>hVolvGhA_ zL~oQ2tUHDVa*RoJs`B`f+4R@}Z$O46*dI?>6zoaZED2dE{oVYe*_eK!i= z4q%>vHuHV*jF(#+5H-sBVSakB#4UCa+0!pkEq7E|(%{a^QWU2d1a=Rm7emCv#1&Cx z*{72phH;w ziHlhxPKim-xUWyxM1t&Ma+EogvA%D?K-|&yuoS$C_o@~DwOn*tN1C-~1#GO=IT@62 zFF!(@pLNg6@z4&oee%QgCH9#oK-85S41PD@zt3c}cf1GRbsbv-DN`f36!r>@6a%)0 zPevop92IgDPMKuZ*b1!_i^~NyQqRHZf)-Y{w@&OYAB|_nAIZ<8z|LuW(0ew})`?`B zaYl11LLFX9-=RZi4d(d?bKBvj&6iW^_E^_PI-(ttm?+Y4amgbidRHa+<1n4?&4pwt zY0m^Gp@rs`F6_9*AG_xs=@?W%ogkqi*A0okh$+R!4 zm}QrdRe3O?V%Jv3OqMjwVP2ztY29Xi>;v6$2OzY0Z6XAjHkURe_INWY?`m^x9?5rS zV52i#Q*0*oB~2g&ujo;mR*J#7d?;g^_5sBvqfq#he4yr^!A$_&t4++Ncb%O{yd{MY z5T1oV?RmU4y7Kg~&!SVeFV$v|U2TmuIO>{yHPcYkI6X-}{c(6eqpQMu`A}RFqn8NX zDhLmwmJcYXj==Ta;q&VXIEb&FNl|!U^>h(jFvtrveN=;wlDxiP9@Oi^GF5;|g>9De zZ0d@ROXE~*miOT~k|w+&+Z5j@8A2-~obnE~!#;CKa;vOf3ddJi9kUR9XOGeCtW2#J z4M%szvE@D-wiVx5pAV-@J4oxFB$?8d$K{P+z!9DK^-n99B>dR ztiusuD01=cb;@YpQ2FyuSyqBja&J}2KUIx_PCNM2oioSrJ+{22?_IV+7}!DU;7yp+ z)P+Vl9yRlZ;f}g=cnt}0cgi2BQKsqD0yv*o=JmdTfJhO$+MiJBN!otoG!f>5nVti+ z0YeSkp?KUj;tj^kscV-1BxY&zm@oULzh^f1!u(Md=QO^(_Dzha-$`U!T0eT@%qP>k z1vfb>H-Bo38Q~RgY1;fQ$3czxpl1FqnPj(^e-2X+MCE?%4ovKf7RVk2 zBLp9V+^PnJOX9|tEvAG68L@$?D8M!Lnp8fkxf)*iU0yFLMA@W~BrRb+sIw^-bF@Cp zD#E$nCIjM#s}N@wbZ*l$wJ(}5<4+STD<7as>UC@p^>|+)2|Z6#vi0O3p`r8hT&7_y zv9W&f0O(;eCfO~B9rPCZ!vTJ;S~lA=?cc8(6JMz?XCSRegWnAB{sjIg`5Tzoe;k8d zj>$bB?NFf&JWa9fK&V=-P|@7;?+A)>ey0lTfqf;&%2r8gBtF856A~OIyNhtm5|yni zbusDGwG`yj_q_LgMI(X_74L-)xr9X>P0#i9CNUMj!nosEqCxYu@Zq~e;RqLS!ElHj zM1#&{j&-B%12c9RoX zJf`xlXpj|pDBj^EUq*8VmC3t=uMzukOwtLM^y=(9DvRI%W&-qA*BKAkH!+<^Q}A25 zWljAkV;;Acy;QO zf6kA9#)Von@OM6gsTw@2&u)yYGAGovOMek1R+-}SHI>js=PAbS_v!nsOZQLiO1=c* zn*|J}@4`+@{KnQBUQT->!?uHMZHcM<2*@mqHD^T&v<9El-96j8ktDa^Tz-;ZRj81( zf?64-fm`?KoH>S!gAmj`inZbeyHyL_pzb&caN{p!x7?Ug?0i^L1T975WvK-dE(Pet zfHGb><{#5Pzt4Y1BwW-@JF%(eIqMgHTxb;Kj-Q^&11MwVAYySjXSQFF6>2)bh*#?* z6k^wW7G{8c`J+Eep}K$eduP=C0pxw`Q8*L@1Rye<^70G&Yr0;~HTz0;4lR^8iK>9p zdj0XpkyQ-PE`3{tZosxFh|?ZbpKfb4_EPyEp@Ex{(qp(}J74rljf6;5wQa4GUC!1z zLgJHmxk~Db>KmM#mjc!)GnXTwfa-5n@xoX9(gn$eR>CKrE?0MYcL8$N;lUfBa1x5< z{|P^mQ0U@Cu3+ATtxcQvp`7pM@=qtF9nm};El2~1Y?`2L-+dk60FV0`tqhs|pcyZy z;pkKwTCKXIel!oWE2|Z(4;xo2Cw5Mv8VH3>RK?g%j;5)IY7K=q%>G;zDD~j%YiF`Z z8Xx1;FFN?v+`%J4O95RE`-$*U51av=0Im5P4!L**B>4R2528fA^MBCC#q<(|TDUqQ z9th@d*UCBY4S__f(OSymWYaS8SPqX4x-B~iH<2P!VP)(gHO~X zqqwCr=9StSuy6cF4XndIi93pg+=97OhyrMUSlT$RJ`}Y@qZ+Bc+^`Do)#S7Ks0Np5 zw}VNe3aoUeqPj*3wf`I{n$kjlp;AHKKB%LAX=ENXC$!N0tlFqqEp>(}zDX!8qR-GZ$M-hWv?`m%e#_D}KhXeEv z=R7NGC{#D^M7ZG6IE#0kAPv0n#|h}$O|-A7j4Ggt0a8O1vW%1kFQC-O_WyG1+Pe5I+lT(@gqH$c@9(QB>UTznEevNeqC6^I z(tP9R+z+0nmcOVG9&7iSmt_o9^`+WV^;Ckx`RF?-Qc#7WyGYKeTcYl>6SEa1NMxXP0RvXU(nRTyNG;k!2c^F+i&j5*YX1)-#c zdD=)Jvh51#`P$@q+c*&aB!1n!79S+lFrlys$xH#TM3gj!d92{5rZ&8Ybx`9dtQ{fV z_9vqcJ+Z$XOUrk2bHeva>}!s%IPJ-cOfTX%e?G@F^nyXiiSj#Kr=f4$1~B6A)_bH; z?m++Q48+$;R6=(=y=SD?3&x-2Q*cnn+aHGD?wGqTB$eUm_P!+U(Ojp1P4^*9##u{R zEmkjOovqTUS#T1h{L|D;6q+5rw4jE0N{vECH_@iwYYf5TdwH8qeL6kLnXsY`a$DN` zV<1AV9M4P>p)|QSC}Z46DGk;2{=*5gb?Zm#XwYW4?qMR(C*=*5?#eucb??Hm`o?3q zy~2QQb-NHP?=+6`DlZO*I!4#Mu9d@PfL}ywGP@r=$XjBv^e${}BQ8uQoV6tE?6jKO z=Jei8lgSj6#OCQ6#^j^u_6XAn2&ytYiu~lIZBL`!+^7n!QTTTL`-hHFZ*1On8k)HN zXeNhhc~9v{XPXxaUYV3UtL-zf>W3YSXKLpsi`?4~5w;c?nSM47ul=+|$T(+#n6r1G z5dl28XE`^;YBrG<`!-6-M`f+=<*crCDVXi;}@~;`G!5$OV6_KjNJ#JCGP(PAQAWo+2ZvQ7Rz$eE?U|$ zetPGW)O<@cgafI{c+~FH_f+yRkT}aqodNpP)EFN>`sZo4=we&HyprOZ5h8oePJ01D zUb?7qQj^@G=jtSGYqVS`3x53!h*3-e>_zX&stTzVaayh^@#cme3_=_A($(xHnhlsb z`Yht-ln|s9Z#+4OE|aU+a@!ygGtmJQs5gnWS+Q1c86*jv)M&#C5`qY`2cI=pby%k> z(R#@3JqnS%rYN-AX2Vl2N1{WH>~rewDYphh1>*vqsmjG5Cq;vLv%M8z% zqP+LQwVy4D5++GEO8@#?97}1!Ew%Gebb+AVp8qr`sh(J~P-UUfkv7zlf0c%>l$DJj zF1y;K`wNoWb7xuAZ+0FMd^pYyN#ZcyF>gm7BtEb73Ts2oR zQqjzBX1CRF5kH=E_cWY`O3a;iB1!mDuR=m;bk-F;zkb56_|-GDzO?0zL6mt&ZS==4 z+s-a2H1(C`R$qZeLUE%}Qm>sn*sakT5W8$+x=LhQbX??@KhTGVXBE-S=z4ab+kg=t z>SeNKAn~)!9_>WYI;to?@5%m9XVq%`R<50g1Pby}lz}ilNb8iyD0fTJ&I!9yHDVZ( z(qxTnA|8#ZGMSG4w=1QaKI`1x+8mjjAq>ag7V*0M&8gBm72{&g`L*igsX_t&ETmTn`;q{j|`WR{F9LTNuv3Vr=uj+SNyca z`gNqv5-={Ow3c>*bx|gt~jGKhxUSYR1=A^CqahEgso+ ze$h)=O6=sZ*W{Wqv@I45(cFy{Z?~&AJQjhPg2+3J$20c>t0UR%q4Ki(9n(8?S-@r< zvU;ElZTiF^rPM+ju6LX`a3TcrYnRzj%g3ZJY9tIK1iF+trEmt{DujwmWTwGzyhRm3a~WSRpBC`_SF zetwz;K#tG6rFn!1zF2ADF9 z^cO~PGeVH$bCRXrZ?lyi>1RdX=08*$Ts=e`^k0)en_CHbk?@b1XbOL$@M5in6p2T+#NK~VYtmIpY?x-}~jcECtls)Va4$fM3 zue2gInTS^_iZ)5uRoQ!O`wR2gdO3C3LT8XRJDi(t5FUgZ+ zwf(bR>9ZodU-+%W9fubY_mq+`;~Qp2AJ_VL(v)8O~DAtG0-xMnP5qzEK)oZ&y zro<&8v$FPX99DX9VsBows-V!GWvM3lX)V*(mX{VvoqjjYYr?HDBix>L^6qiC^%c5; zX#?1LjY^hYQ)&MfI%!ML8)Y=SHWb<$xf+|2F>h`qAB(`-B9W6^P#Mw~`<4->2Q((e z+!yXeE2wJ{AKq9(#rz$`@xim+PsH^6*pI)0T9@^pA|_1=ocbCxU&nRIfJqfCf^ZwwI$GOJRDPOOrX{DsWlJCxwc=Xc2*bPAy(o z+Nhn{Z|g$I|L+<8Z~WrlFvkBoSjHR!BnbD{w{z8a8aqZ35$RD++PHL_t0Pu2ft8UZ zGAPTKC1olxV_H{JTyKJ9_;l>2De_3c2XFC@gCL3dO=Uz7@$Uei(DpLtBy7pN@nEHA z%Zb#_!A$(oRE#5{e@H)s;O4O4cD9qcfnRarHJ_I>M$W{_sy1Y%n*Fgzf?v&sLTVOg zM1@3k1^3wf?fkS2gsS(~z#6yrhvb8=)A2=B+!N6b{}d`8S=#5fG}ez8T$42aTD15P z@b~5359P#<6J#baS{?;jxd0 z(1-s8LH+}U9J0me27^JHPDF7*gvgL&qTc@71rAgb`a$c$R*Xh)rkE@jrUIWy9TV3V zFkvDd>^{Q;|qST7~$m^~+97ih#H)1UzE!_pbjxuFwC{4FAu<6utU*kN7F<*_~+w zFu1CFHPeZ-ktj6PB=`Ii-(Z>k01uwFYrJk>LPSb;@(P@Gz1wfavbK!O>-fbaz`7Je ze*KZdlw52_sii};O=Ik+F|pO7Tubd+kC?c+S~iFoh3hlkCDi0HAT7(k%XHYhql}^E zi;>wg?HO60TOoF;r1o05P@EE5EufdEhua>KcQWa?x%KMqO^I<(TU6=EnA!bfC#1E0 z1W(a`WHkRrP5rg6sqnHydc9h%fw!&ezpnrNe7NdgUG~4eGRBrTAC3lFrqoVZUm&ZX&qA`V&5za*Pe5TIRg5i4ifHmB=ro6P z499H<^DdKKBQBS2>Le#B4_sBmGb7TM+a{7LWf?84;+N-knHSeb%DcppLaW5sNs=`B=tbfCGgCH}QP_62;#J-7+$cbF(gp7^8_Vlsn29^h**d~=o2Vj~ z$?h$vt)@?;cdJm5{|dFCajI!z8!vMGP+XWx41{CI)xK(MDTf z(ie5ubP^-WM?n8$AS_*TU;aA@wi1G&CKHI{a&q0OqLvB#h6KflUbu}XJ`d6~D;=#$ zubCb@*ap8ZQ5hH7lxa7^8xTbUQk*>n+oC{(Ha;Yp4R{jBn&Tm7_`wGQ58is3YHa@E z6!e^Q?W=Y@G0eL(9PsaSUo+bNzJCyYJr`JfLJ8Q2{QAU~T}HjO=@zgdu)X}ej-2L; zVCRTJ7^4!;>u1+1)DD|on|cBJcj5n!fG>*TSJt%(!&4vrUHx=PWy0p1)Hy}~=6kGp z`=7wywbp2HP;i*G7|zs4I8^;!Baz9T@xDW1A6nTeseFv#=S^7AfeXd(_B7sOj|tInd!xf4yb@#bHhG*Q-HTd@{Rn?=Eph^P|oucYvQSd1>vX?(2Oa zl$&V@{UJ<)IL1FB{-;9*|LUQ|>z`dqE8Ymfg8|o)Ah{L^rY(0>F}4!!t-Od`i>=kb z%+-HT`&M!Dpff?O+PrRs4Gdc%jn|KHHov`HYRUxk(Zna(uaCjqCxeA})2(b&mDGzZ zo-NiPk;nV#QzgHYAJMI}6H)t7=M$$b5n-4=%RD8h=NVrOA5diGDpuq1(|VRK!UV+D z1>2a=uQD5humd5|w=lBf!#YV{YW$0r&H8bq9Rmi4j5Me0a4wU3agCemi4C!Wyy>ue z#-6GD-vT7kO}G~g1JGR3-NBi$lE=&^=qzv2z_cujjOH9X3Hbg)2E3-iYs)vjc(wFb zKSjXF@wreAS4|>pA6l1;nl{Xew51z418w?4j2R0LE?KtKr< z92f!VQju~93F(d@hejGy1c4!>8>G8Sy1S%dD2V~-7={|+{|?69`+WQVednCtb*_tx zoa<%Y_gT+c_qx};*3+(EA;s3eOD~~H{c*6EPLFP*!N*Q_s749IZ8B zDOTxxTeLSu_}KzJNFMXR+40Jf5ktCRg%3GwSW3t_HaI+!KO#{_!`1DQe=J1S634>g z;369(YS#YAN>xZCJ9H#%-`*Xlxu1$r8i-tyD-RD>(R0g;5H)}P3>VoPsoU$qCfAlwNY^+H{Gn zwk@tux*w>{%4{Z}eq!Kv;LH`kJr-7S{>30+Ew334SPsjruw3QK&Rfk)&Id>s zr5+AIU>pApWE_CKgzpjwxixkyacO%qlm1gG@C&Z=UxL)Dz?ggd!M=>&gkq1D4VtwHbbj8C%(9o7p>hvU*& z92f*ysf4EYFDgrF96upvcR@cTF1sbn0}h3f&jUh-ZDb1fkguzH?EJQIm=nXkyrl#; zxurj<3qf8o*%t^Wlr!|1FETVO8Bf2S5&zKNu5>P{V+l*GN^AgG+JFeqi1`qDv85(K zM}RNUPhY3pafb;j+Yu|Wjw=!8i9>CVAp>sk>Tuk8bifw}&~JaqUw*h>M-pW{U@ETR zUwzN7P5txH0$L9KB2Z5oq6f_*z^%A{BTSa=YjIPS^iswr^`bW}FW=HjMwb-L;ZDpY zi44C93a{8-Vl*RTwtJ;f!C4qq+FjfP2}H~zkv);z#?#|mvds=xeY2}e3D}4heJQWD zb#b|Oh6e@4i6l7(fBNz!hUZPi>}%Ly43KV{iTfz`j!5KG-SHN;zRC8T@CA=o%Jm1t zCaa#PWj_C?&Rs4f z)~J1T0xr_6Gn`G&Hq;vgRBE}s{mV0!@l=Zxtl5c^=-9|I9&qSR26^939m$JL7%5+y ziYk%PV0@!f$g`L@AdC-T4PB(3h{2? zLtmq-I3HcO&ii}~UoxsY9IN4H_~Je3i=U~?-%-F{_eZvrvRVf4wgc7C|Yw`u*BPR5Jn2bne4YMS|Q9?U|i0g)~qYfgf+9l68_uHh)$8N|Tp zfx8DV@L5`oodJN|C>}#(fZ~k(F*>(FN(8eSkq=KK9Al}6C&DUY{=}F+Uiy#FFt$($ zx+bI?Gm00f;R|IzWT%neFDg|iQnTn*5rnf9atKWG*W7z2GAv~$p=6LVULx)aa1^U9 zqH6?EB@}Yiw^O80iOcG24=>|N#SW)psS7jTc1VHp1-o6>!Idh#*}JjkgI39$2$;NI z7n=4a?<{RH2iKyJLKisGp(V&QSi~eF?c%={h}f?JTP-pqW=|<%1&2n-P6C z4RUF%$cpv8N-)nNi`95rztFfCfXjb94Z!ey|Gd3rUjS@L{!!injR4~ydcc(}bUrLX zHpk3QUQ6V%JbUH*)g$$+DKka`M;#lF|M5dMpor`8>gxV^JGV3tUTeXJ)TdOe#Js`M z_f|R>n#^PT6Wlc#I^Bm(lr6vHD)+}2eUiHX%5Zf27SaC5^6(`&qq!nCbnW_`S`i0^ zrbq&#YxCicT}E!|L6g5VcoRpk(U5=%5|-Zc7wvvv!?UtO1(mUou;^;Gjz(}==F>%l z%d+8ZuO2&+>-m_=I*>s|9_w9u6EF2_!Q*(e%J7bkt`5tCdf(?9Bl4c`EcrXlJ^a~e z?}kCb6f9A@%@TD9R?rOLo?({5Luj_Ykkz44@&j0FA;WSMj$~s7PnuthQN$u0kqL=4 z)lwxE$^39OXS?J|C#sJ1?a9Ef$T_G0RKQDbw=bq+NM$E#cZ}t76!T{l#r?X-fXL3J z55>Jt6<2DDyGfrW+9Lqz3UHl&m$mWT!liKc)}PcdVjhFPmh-$D=G*p6=&|LDLUL&M zJ-3l7CC4mQ>$l)+&w(&R)L9auAHn)TqU+sgj0-XQgVc->woew5?T|TrfJdPaLRWkN z+6Rv$R=Mo1+W7!5Ljt6rp83j__-iZC6P37xGY2gXHyWF4(XY z#UwM2mmjWXYp2bfqGY5nGUeb1hvy?7tPpwt8uDe1E53l_fLPxv#P4mk(Z~uLM#k2j zi?mgs;J(ZgS>lpgdj+m41$dP+e0v5xuwh84p`X3;k84MOcA-bS`lVR0XIG@N&0PPyd8kZKO?1{)=!RM;-l@lbyZQ zekWx8gfuc$;PidP5B~XwFa7)7|H@|1gs=bd@En7h4Tghme_+Io^Ll}~{Xxead8d(- z1Yn9Eiy2@S^{*23zjM3)4?lGk^~|!FFuY|<_`}I7kEzmEr}6XEhBm>baDA=zce&QO zzu1Idoc8aV_*b6%7dZa8O8o7!xyleB^8+n}=((M!3*x&1J~Q@I_;)4@7W6pAccOIO zW8NBRf`J+EMexUY62y6!|eY7h8*zup$E1)h0um1J&O#$sC{{Mln z?KiW323^jK_*bTI264`6%~)y(8_}?T`9T`(aCE)}*L?8+*H%#y*Ck#{|8r*`5Wes` zgU1+7o9oATkATDD=_|0~DgLtZ|6Ek~FAuAszX+r=>>2XE+E#}Ia0&M_;a&|ExMKhJ zpKKO(^Z$cq`QaoQuuSS32{$NN9ge^w`0BMkR|0snKOVcz@0GyT5&zRFNqg%5@gJ%) z!>GET=y3X5-Y;kZ#pr-9$12<9eZfDW=HH%N*kUxWE3Ce`A9!hTd(VhnMri(%Z0En> zuN9;V|Hnl9Pxt@V+RR@T@n0GAusD6P&2P_=@RRS3Z_)R0lvl}1C5~ugX$?V(1?AFC zZcoosSztR2KTDjWx&o2MPPq8*2C;vQbimHK@bFWN`nAOJ;I+F&0a8z`A1khm6!-eG zpq>m|&72HIG-}fvM$qL&%=B|A<5~0sXvpBLrj?wkSrL^&b^|>;p zarqF0{d81Y*g}TyPYb}7(S9>d!2kGrJ^{E?tSvOdm$-qFIPxt{PfQ0iB5#^3b)-1p z<9Aup8;CoQ2Q2=NfA6}01<&1)dq4cwpPBf|jsF5-8vYHpDFN8?x4LidcEV@ABz_bA zs_8kmhVu@dKV!&if0M|dvG38XE{4iA$Okv~&^oe4l>!2bK&^TIN(|Aw=}K0&P6&o=Kc z|BgR7?yG+&h>GSgKj>S@zs(cYk&#=WJmHw92 zp7F)Mb3*JIVjstE5*mB`9~|3KEvOKh1H9#;W>GpYF8>+$m4<><;FIOQvdQ>AZ23>;@b3tV9lHPbydHbISoo=dT{)m! z^9z5%Ne8TfFfv>>Sb2??Y^_MQf!Rk&uk|9>r*zHAr|f5M)_-gF{cYiZ5`&C%;TLGm z)w?63*HOr);|Ka95ieMvUb)jAsXp!O_pkU6RD9hDFEtVj9a#B{3z*rNm-w%rf7>2# z`41idMf`u8l>sL5qn7rs=)*Bu|Bp+q01vyEtU*tQNF{v5-5&D5^zL+DO`rN>XIEJv;x1ED@sp`64CaOYR^QRbo^f=HhfgL zWXeIL04N9m4Yp#g!HZ>V%JcaIK^M|L39sh})&T=M+Nl;G*oyluU(c!lj(%k;G!E*9 zEiy7`J8&qeL_KAayb3SPU&%?)c}KWPu(1S#Pzl|B>*`@WW_zPDq<;=m2h$B$$6|5($Ksk>mX zuAe#Rsoy7X`Lj~)VAwkje3s_NSKwGHjy^oXT@E_C`F=a)D05&Yy7J{7*PU~_0e2F* z$0otGtAvrIP9O1`XA1I?o*Y~;<0P6x^(OoM80Ph3fBtlPzqTj#D*)-MJ87Uf-yKNM z4jd-p$1`yxKrmc#`Hvm$0AxfxQ7RT!wYS?XQtQGj~)6QG*iD^^~g$`Nvc zup6VmG_c8Qcbs*v&t4|LXV;+?@7ZbF8c4lsWy87tgeWPgIu%0VG(FJsXIA$gl0f8` z_RS)N9X>e59@yi_HCEEWXI)O!tyqSsPy5ZM+x{=~=T~L98M-VN=F($2-utt~eu~wz zjx%f>dlLkd*MJ7P{Nl1KoW9tXPlz<19i|R(aV@aJ@;%A(re&QxYkUahrbNWIwI`~= zveJ}Gl@Db#u#WRzfgfKbh+90;-txgC3U72kqwEJswblgZ31|FmomM^)h-Fi|(ftKY zkjoWF0x;*q=HYuptNs$i!Ql!-$dRLzXbj{ry1MZB4|H`~gRK>}cSoFv1{MW&4jBBn z#X~;yR$NWM`~gt!J?Uco1_ztXbb`%AFXgA7XZ$M!n4`h5Jw3sr{9FBMhyujK6l!Ra z+YlQ?qi1?Rgb@u`W(np<=g+J0(cO@Ex)n)lnB6^)no}J3v+wHfG|uo`!Heh*xC2>K z?#-EtuP)m5I%_2AQbp1Wj&w6bmdHF4c{Nru(x-Z=4`FDWklEO4G}w%;jDN;D`e;rsHd1db*uKfro}0#Zb~R8o=~ z40wU}Wuqo1;_u|=S~Q%_dA69?EIp37b1tF;e7(2c?qkMC3CC+Tr3yolpyNw?NW#Hr^MM^*lC z>n>tles*fou~?O$`2wlT4ECwY>{%iKOl%d}?# z^2uq3XyAZ8^p$Pu&=fE-g)nR-yl~QF2T*!TVkQ;hS$V3Up91j`Z^|d}Uc4b^uxVcBtfYB$C>xsQLClEg;J@Ci`ms;DTzl zuwjn3);pK31n0qz3n`QV%E*^*vcgy3-HP+7 z;i1E+=z@uyVk@d=aXh6ZC4;rS3$I7yff=99BOwNn99u>5_xf_c(q$Q)^Xs@PmBe0q zXq=Sf*>u1?VxwB+MuLFksXEvYw_FkXX->qciv*OWb_%a46Cx~v@B6JB|r0`yk!ga~us9;;VVpo+$Hbk4GC-?p1cv z!dsY)B%NJTwOBTsA=JWBt$q>)Pdf5Fgz&-a&S(J_hfY&cJc?NN%7%mOm0MHs zo^1)SUu2@ZhZn9*vqRkeF}%XV*j23SQ(h7~b+guVA<~H!4H%sEZK^+B^BXf9iC37> z-4fX$zYx+x2=hM_mYb^pp)V!0L`%1)@Nld;CLz_q?NmrIBI&-BLL%F4$wb??E+GFZ z4j&FWZjr?<@)U?jF$36-L!7c(`jNH&hNGi?T-;c`{N0S;Lq2`lB}aECt4rAz)FA=! zx6~m!{vwXg^NCV)6aB(b~9{mxp2j34Vdsvw)j)48w^b7AF(DVr~ zCPh3}^1pY5M;jQRBZMRxQT~}#&ag~s8&xa&XLhDpxHjwXcW=cddK=?DQAhIC3(V@)cBt*Ahma5; zya6fMZ#}WAJ4!KT`5O){Bg??phZS_Q^JLs1-!8CGzMaV4 z*q-~tE&j0_#BNe#+xhBCrNalENl_(wU;1}ibnlZSt+xbhp+_`l%%_hoO*@P&u8XY6SZq3cUZ?2OE!Z*@&HE+jVQdv=eYnZqX^}Vw7PbkJ`CTkD@r?0&e z%JB71u%c&mDajsbG^$q1RHaN?9`@Y!l1Kp^^LXyt#vDFc=KTM|eE)rAwSiH&oPSFc zpL{C)%+7o6Q9(z#T|8<}ej!hr&d-xcI{w$G{o#c7zx9Yx8|k9M{kb76E4Ak1p3`R2 zCpp6CPwyZLOhc!QwktbrYUBkFTD!*4_pC`U&E}e$jh35!EN!C|B$BUh0%^&sa+X?) z0+dM5$v+ig4lh8o{N$k-MXC4RNIVNjxj6o%i(}CX2`%8v$;k}BWAA;7x~}cSq&PAm zf2|u1b7Z6nPpSEXdegPDjy5b&uE&-95<+WRhvHo{Zcfz`qNSS^93KrBMbzXt+n#Sl zHAgKgNw=;JKFfrldc>iy5t#fcn+vaE4cjGFN&q)=JF4hvx@{qI#Ww6PaM&B(HHiVT z2h?wNxzP^UC)TmquN?{y6I2P1ktL~0=P$QyrKU@|5it5bm$Ctl!zz&DU_k{3m9k_~ zDMQ!>?H(Uvn8Ho&*50I-!7poZDL-9~Hj5lI6zyod=Hnak63^AJ34 zb(<9xJf%EI)o5flc~^Uce&oD0=hmuudKkYyaC(Hhz{FT*H)yFh>S}k}uh=iW)&b#5 zA6QQ=l)CI?isqr1ri}6f0>%uIMcH2ex@3w(Yv$-oqz^45x~5oT{q(B{$PYo!p~9

    Y1H&!x<6A)sp(o@6^Ds0ar#&6c^^>bs%}Z(wS6LT&9pvo^a9QDkhN2njF8D zTY)0tNw;N0J6Wo`&_^2B?2BTTBNo>xvsexpBOB9*J_Ml-YIiZ3W2Tec} z!_>NlyY58)cWrV@C(AXfLDJ-eWB(2pNJ`J-fGIEr<~J1j@r_Fe{bOO4H8#*tSV1WK ze00kFX*RuJp9`Sf@1iD$4Pd|CDu$5oZNY3*T-_2-*FU5EL}1}^3mK`f}a+05?`H}AwoCM}OwBhcA z-;D;wX_stA!@Zyd<5StvD@Y_Gd4Kg`TlTtrTk(*HLnc9Fl|2-Oe``4jlM6F5XDA(S zQ!yB2F>$%?ke1k2m|8n(i?K-;%Tv6gchx*8|AeNOR6s=OkN}G%rzv8+F@pPc&ZutA z^z6f1a6yLp_>&!jqvMTfE`_z}t%3McD#A34mSdb#&%D!JMft&_KY-;==^lJXoA+&K z>*n=4aefKrNcZ7d7Y7Mu4W|d145YLzStG&M9$P5kljK!-;*IBNPxz`;Jz=GorU-?H zPq#HiWL#Q~FeRq0j~=+TIs4tTYSWncazJOpm%VG79VX>oud~f17@Drw`o9xuufi** z>azyGpy}}LybB$`k0h*}^sv6w{IuT$;;CbPU`Y?+xqn;ehMLrkdaGNFf!B-A=BkcZOjeU*wiuweF=u$K$?oMQA|sJrV%-(cfblIY6KoIS;yep)rBfzN9a zr@1d$)}%R2pQ1#m@6D~1p$*4Hl~=-2Urq@c(*dcePjN}7OsMNMCQeA-)G{(`5PS&q z`JAz8Kb5~f+HsZzL9ZuS>BOJV4C)t%8uP5w7a|Zopdt=xJhMn!W>~Rus@`Y(>GY|` z8T;$`qb;lLD#4_7$!Q2t5p8=7vB@q!AaY%vl$~cWRQ9CtTUf2|TMg{-P&lbr26JS& zC9{Q&FEADyU?AnT*^%e>*C$_2%lAHcA5Qijy%gA{o_nr~rg7qqd0BmX)b|>b5owbl zD{f?qYSD1JWLcNWz=>Lb`L&JDF@4SIWq~r&RcZVH50LNZgOuq;kcLb-gQ?w)mra~e zd*+|)cR3b7xv$3Enx}_O58P@`2Q;^;WtP%24-(?=4+xAgp(9;aMmeXug{1ljSR9`- z)1(MCd@6_(6BvKDI_vbs8Wa97bN~E^*%6U>RXE(Xa@hj4+bbi#>q3|IM$3~&vAKkr zhC7E6H(c@CYKqfC(8(>QfXVvNGTc{AD~fH84g?mM9yQkJmdU7~U5FH1y*clbM)Z}v zTe-!6r9vO->^qV@S6}@{h zX=h>7_%bAp-#>c9$}%lOKA^&d3WF_#{or(dOR^i5%RqkgQ$!5}!IdZ3L9kD8jJWxu zP~D5RByfWUecF>mgU!HuqR3=_d=oupZ_!u7q>kCUPa4(p?PhcbNOi3q;X~0dl() z0miGGjt4QobszA80mI>2d4DU+ARZamjnL+{H-A>69K5?R{q3ta)OlYVujX)kM4)K5 z*X@8D>@O}V)4qrH8n1OdW*3oW>~F1QtNsJeueO0Ac-s=ylgF~tt(L6zy>4*K!|O#& zT_$>nD}I-ZBrmtllM+2zetKEMVU1?l?C82lsRC{7cZ_4m`Xk+{6NI-c{^rfMJ7wy_;_sUR!;PIfsRL9Ze%LVH6*Y!caX*DBSB-JxA{ze z%WK1IzjPd(?lLo4pQXqXonyx7*BnxlSG0{}s3+_$=`Oi*#J3)5oC!-&NZunG*8|m zcRK^^!-M{`hFfpqTD#$S()=%Wge{~CFY3lYHQxW!=}5;nb2L*iWB7xP&0Q`wbHHJ7 zR6bu!zLAIZf7;uFE~_&>n8ah5PS>baHc90j-uBC8LLuo5hh;U)4tycJ;Dsm>wM-l3 zRilst1Up2DVk`+Vgt=Dfx0+#h5XECo`>5>WwXgH}Hj|phIqcBmjjIn^_Tuj4$1x*& zV?_?-JsM@9ktO$~HKub)BupQG1sW%^DaKzMYR|hJqBJ+{Ou7;Ar`rLyxfm%! zM_fOcpX_oTZ3&(bx@)EdmW)L_$+=M$<>s-3OKWJ1VfU;Fg|m^a>vY8E=q>Ws`S=ZS z*)1`L2CVeK^*qd(*VW(*(*o@Uy%s1BMFQkpvRaGO-op1`w+5(EZie+JuTMN|oQ*go zjlNuc+w7^p3q9kYatCCr-Hv0ii+1LmIW4)-c(LA9DSs+Imw&^0)TMN16c2czJFZeu)j9Rc++eNRD4&y5H-+28AhHZ zl_GTM3$Yf11>P&#D2=gjQWFn0jSfHr%#YnwFLE1B^^tmb`)eWKQ z5-XS9O`!wF7x@9rWHS)pZ(AwU@5o6`7x9WnvUFrlHO7;|+phq@+O()t%=$YpDMquy z1<>XSS~!315gH&LUz;WSoFXt6I#om#W(>3iIV7T?-bvjCFQa!899L~UIElGjM&f#S zGTO8=N)Yr%)^FYX)GIesHdxC2pfc2DLIdO zx>lR+@yGaXn8Qa;o*ausr?3DVklqgQJc%o{kuqf)=*ve%&D!@&7&EP-!7KQ5Pjq^M zvPK=glR({GeK_c3wBW|D5uaXYqBO26zI2Hz%wBbb-ByEvl_q{}Hk4zP$A&OZy62h5 z6u;hrVBIP`QmH(LoV%IeQrgNvlmxbmFXzZ?FY7|^9n%}<6;6O`;}rojwQ;c9mUSCD zVdZ-t#le%7nRhT&8<49y@cd0m{YL;EZ=X@OE+HwyhjvXW zsvJJe96|)dGZme((CXUt7mPImZL;%zF)4dj^=@HMvUg6%>V^}}PkgINU$JnTSo9@F zR@t}YJJvb?Cn$xRWFz8av zBShOeco#Ei=#V7tjm+$I#tS#%1#;y&$7!k%huU7yuGiw%-gEcXgf16t@Tcm=tyB$? zst9gg@3@VgG)qd>5rjvd8hiu%GjIy(4i(lxJ5G)yD2u%;cgJQN&gil{i+hVyEz$v6 z-&d6F(df?G9P8JhT?~!r7V5by^An%bgOOUTv8b%&QBc)mKEi32(B-zqJ&o@AIz_gj z6K7|GCgG~bPjJ9hQ6D$bYgrnZvqpfip=4ELUSyHE8qp|%J7M0ZELBgN4OSQea58nj z+jed8HD$tPG3%esH%BLE43rOA5OL04m+2hS$X3(1Q>L zt)uy%_xZZF!}NtdJ)B~GfW_1wQmB~99u>@0i$`qN9)VQ`0L#>oCHAYRjj7T`# z(XkgGI7AQUe5usAG%Fh53Tk{ay{Vnv!@bz)HoXjvb(SgWq|i1}%CwwO5{n5scy&sr zB@PaFzF>tw53{9mD1KPWDyJamM~xiSYk!}J2a(=pt4dcs)Ux>4bmh$rs9q(Ol! z--r~iKhX&YS+I9P=*c=cm9wj`zpwK5Nq^IWtG~5J%rw-pOK>jTbv%1*)%vML={1y) z!U}(CC`E8Mv|x1^!QVng z-Qt?ZAn6s}M(YsPtyt}`m(bd{RC~i0)%WMvDNc3m!(4MD)oi64k10z|FEu}Fje@=Y z=qf1(%Gytm=ZtKy$!5UxZ3pPe zmXq6a&vDdsRg2?082o45&$`VIc_Hct#9ap)ryos*-?ZlY$t4;Em@}(t5 zz@ev;05ar{ooKMJp3;(-Hco2Q--=E;GTD0wl%-8X@OLFB4jc^Un+MwAn$kIbKC4E} zMK?9o$$I*g-b(N3&CJQ&)RT``BEW<5cbD+Nks%xfAr-Q*4z%pEDmYh6(6H3x?#SO+8H zjK)Mfu6|09g~+B{&!&K+f+LG|?6~|K>65~C`wW#?&8>@PULto6D{W#Z%qdMq<`@(A zmgd?nQpKg=X-~6z9eSkqjzeL;b5U^WqLNxs*aa#sYsP5p8drk|jR66wL`cCiLu*iM z6ITNf;l-aC>?jI^Cbn-WYr3d-N8(E z0*Acoq8y0H29QNi?debVWE_@WZf!`lTj~neRsh!P+>AL}|$wu}W0@Esi zA88&k`DlF*1NnTt8DZa3R4A> z(D$Mlee%(UB%Zv;ro*kV=OG;O6(fT=92JW0UDo9hMXfyHI?>K_q-h1Hf85o5 zuCPD?9Y~Rr8Rw}(msJ{T7@AWl?-Pc3qhT6%hi*_^NXYdfBzr|QBqX4LVj*15hVl?W z?o$|Wu7}cF{kF^6uNw=l+{)1~PI5@P#Gq7Yt1&^$kK2CLMYK`!nOPM)K zM>2bXhtbgsg1shA*7^5xh-~dD+@wiU?P;l7W0_fxh1WJt_+e<$Mc1U`1trHCHDQQ4 z89wD6!eg5SqeRuC!7dV(SG#}s%*JiY?}p4Cu4M1`0yR+~@pA(F-;kEGfqZ)GgR{^I z^c;S5i~0xv1*DSJfVecFWC!X0`B{Nd@itUd9flnO``C4+jg9rTf= zWO_uzuH%y>2hKo@fVi#X>qTB=rPN+g%X*WVkyoB{wqVHx-H`iKZS^O7x-H99qsIad zZK((ChBYgqthQg>TbB2Q&CBL8--kMt^C);_F`LtysWCOp5OSZWQT7U1WgK6i`)VF73SVWaNJc=}28egqi->B>#LnkpsR zFMBeIC1<>e)93GekYUi-^9X4uzmf8=Mc;CMA%z#TY@2p0Og*kR#r9J| z3g_Mx&zGl(H27cvExX#XLj?zF{8u2F`VOEX1&XwrXikbe|LPC(@SOc2^Hbm2N_=6d(aoc^7SIrx&ZynqQ(ru=YcD(H z-gPS95X-sEVDt(mR;H7tad&vOnTyXfqW9Cr9Bo&g5#=9uZRL_B5F zDvJAcHa{fJ&NqeM;UT!)ZccpsWkj=iOKf(5l1c}UdbIU^4XA3#EP5&2d&EFtwcSec zdH?sun;|7K8o9LK_NaBX7u0$@3sA{qTvSpUi^-!`jy)8y#3|}yT(;dTIMl-;dwDa- zm`f57h51=s>$t-Y7cX#+4vrO6T78n8jy;iGH4i{Y9m2t2jT4uF$&4fEl5KMn9cL;M zTZJ%L9c0Sas8UW`RDe=yCX=m;L0&W`II65gg;vs1ViWD|98!A2oc>x+7GeF?O zl6J4f6s6t6e_3Ly6MN7c-D$-{4d*RaU`li2JBrKAuZihwT5ukK2E36TPnz{pUg6hd z47AP+KH`aT&J@dotnG&LthC;|cZ?j?@3i5U_ljnQ(C4PwTJ@$ogLq7(TOqW3mFtze z4yku~TId8gJ|7shjLuh$(k?t$FX<_NgsY13yNX#u1qJX``WeIXOX2JvGjbKW7y0eR z;j|I`!qia_@*gTgNHML9&nOw|n1~4xnp8T&Q}Q4{8Kj*1T{!~tRgE}t>}0P^U~kG) zVtt-xF}`i-2@bU;%l*gd1C1NBuEXj=^+q-Rpj8HzT5>e9ncEWspK|q5?rfb?Qc^O1_UlAts?O{oIg$afF}|kj zkLqw6^R$}wL0uY-#PE^fZ`GId?U8sYjTbk1L;Rfzg0c!kubT-ArmrmBHJ?q@tnD97p+(JT z6?)O(H1W!ncXQ5%lG^L3QWf%eHLE;$RP#so?stZiZjY{85eud7dga#GnlDrPf8M-& ztSjTb(C^%}>2h^FCv;rHB+@3i+M(^sj55)dUmUrbryFz(uvNIS@&|1z10 z5MyZM2%p0(VbNR8N2L`%!fEZydZM{v`x+Yge6A;K1qDz>9oaGiQ(^`|d9@SyqMNpH zr}a3rZE|ZO2kFHq2qGF@#9plM9B-M`I(x~*+9D$or4w-RH6qjl=FoDZ+$rn2_?Ci3 zc3_X*eQ*xNqv8mqNIn;4+=4A5 z7)|H4o}SCx7cgdQ;K;%w0fv>M)Q8fD+_Y8j?{Bg&lIl&^0H@)$*y0B*Q!mEto^sI~ zT%H~ns#((Veo&pOFx2;UcSV2H@>2lIar|=sF|uNkAQ97vhA1!-5HAPDR#egTR_?|s zkA710!*6z$MzXFY52Yq2&wiXoGA^&70LT^-aDGuBySrm+UC1`~ICP<#8QILame>Cr z4N5{qOz>w^DXnyugnaw%Iu-B1u53K5-fUGwBnqN+RhLQ;sD+lx_<9^wjfeWt(zisI zD(-zF$uiG@+q0b?9VvNStuitY>vmza#LNNq%ypPpCFzqm3LNqUy;&>jw=7UJJd5Xzu&qv-THIMhTsJ6|AzMU-EKIAn&zVUQ2E#(|Z zMO@Dz+$^bu1~fAlK$KX|NU%VED8Pu8bgwFDS^-y7-KR!Px+O`Rnw?4%q`Migg4m)@ z)U(VM7vWW{#aOBBPxZbwiIblS`a}juf&GEsu12&1C*~~c@Vl_&+=Hz2_S-beLsO}T z$9aZtQa`$dPE7BW!>U)XB2Pf9t{HYt)7cVN)73#0XY5?IzrTw5ul^1>br|dfSLf!H z=D&_xW~LtZSUTMX&xqtCWt?sjM4<9ceQ<-PTY5QR*Vw_Bq_+I(GHg2MKWMV=8ChH^ z)gA5OlvCo8U%QX@oRwj{9BN83YxqG{=$yct4g>XvLkqr~w}w^cz=p$d6-)V}15265 z?P%Aq%kkWEkskGd`SA;z4oab6fzK9#LP@6wQ_3HfZtFx-$1wrkbEVb`cm%<(qjdlVW8!Dr@(w3-x28E(^yS|8<~nkIo1Em3Rd)!N^$=%1mPP*_~5 zs14DsRE?i@rY%2CDWC&}+D0coQR#LR`qr7JZL6$ubo{o*WLtJA+R8~K)8K|t*e?np zeH!P~?TtxMVxM|ew_b9&ppM4zhX_M-I7K-udD*)r?btTP%tk5d+EzwrD=o1ei3&(h zV9WA}PkH^IXzDSJnM>bsvml;T!hreOgn`aPq^t`SCzwgtt0?UcX+~!;joifD#8Zd5 zUfiUY<{`EH-Y~*(BP;TJ4E>;Ker91>rK(V*(vtSE$Ki`H<(07*q0~ab)D=wnpre9; zjuYARfV{#x-(Zcg9bDpbB&P+Bin;;}AExrch`M#=7lhk&w^n8xW)^evFJfEze#->` ziVIB~*2-!koM`ak7iacE8utk9n@vo@q`edkDl-q&nLZ*z_~Nk{DG!_;#9JD+-8iy8 zK72J$Si8)rTKWx@0+A6kA(67t{jm0KL?of+TR&|{AmxBH@N5g;$kq51h^R=3Gl{A; zVS-##6Lc~jZAPXOP%4`QH1V5?NE`x{gU7A>J($EP!9q5it7w9Dh&6i$+~1ormb<#|H0y+=&f;Du?q*Z zsId`E)1tXo_sEAFD%Qc$R(dezepRNhxA&s65eVG^j6BJ1h^5AAV2R!zmz0++n^{E` z(kN&r&B=jNZc@Pfd0G^^@0qZjvE zxj^(&-!;g))yI(hlkT)8xFEuYXFAhP3U=o{K1LRZ42OMd6A-vh$O{1u z*Xt+{wG>!xL(mF4uE|tZ<*>eIP^;<8-VkvBvT$+X!y|#P2SKFfdO7^8PTGg;i+mFz zZ#1kd615-kERf_wiVe(QDN=n7*rR~sR zq$gj}c{cLmk$GK`@QfHW8S48J9NYZvh3crXtg0`dwdHEx%5_^R)@W+9z_N}W6aV7G zBD*AjX(QIn7{J6O=zQSVEVI|>U$1>&SR?+`NbN~(LzHa-Z=zbr~=MfHgu#93YR8SIY z=tuqTm-$RksFv4LAM}nT;WE=owcC;Cs>>4nk=7cbh6TOlPr1Jq$G^WeRlUDf;LE;V-&y&Gq{WUVyi{WLt%?6oF72_gz28xcG zYoTkyIyxDfzMi!7Vz#18`g0SKK)f2|WLj$+&W4GV)pSWQ`a+Eu>n`tc>5|C$ns=)l zTAiASX{?VVJ){L|bzBM!Py^&;=I``%x}@1m42{F;uJkb5RuPp^0hrm?0%?k$ItIX> zk3O#!2m8?E$&B~4hJ)H6n5C+jDi2nc~382>{dZYFMd`VwUy1?zkLV+)u_d0dKuI51RN)Y6EKh5Cc%)|ei?Ns zT|#9pmWQ|2RXFd8sjrNEeXXGu7UbNkAl1j}h@KVO;5%JRCy0^yEM{MzK?G6U8xU^s*SadH# z4c)_foiBHK4 zmnWF!N^2qZ(^)?qAQ2ATua4NtJ2gochdAz0pPY+7nLg#D%2x4kn=WMI zRd@)xoN%AmoC=(bj(Sb6Pf=2h3l;hyh7V9BZTUIT+=MuqF6@Kp`t&_f{=9zlF4?sq zhpDNPYGNS8z`#08;p5P>50l{m#yS}#wRJsBspp{#{;UDt`2>nYqUp|srJi?QrXuZY zVH^@o^*u%ktnDqPoO4L4?t>LyUVguSB?zARN>e}J1T6yZ=Y|P+ie#390(6F{I!2(O zt+z~*WKCY`1Nog&oSK&$eTrdW8ZW>6TU9fPFGpO7 zB_SslKcxBmI?1F+%~F=+iF#Nmjj45KRjGds{(zu_)DhJ6x%v}0j3)40@(L<)H!O0s zP(HCODlzJ?{%D^srt49CH#tVB*ANw1lGb&lBfW}ik!4RtIK8ih08|+ zn9YE}8$Vw4o!fgh_HIiZhI5Xq)SxdS(Rrr^vxY=j#n_ha2o;y1sriloN<;H6IQtkX%eQ!PT9qx@d6z zTf|2+X?)}z`}IT7mHzT0P+#xr_eFT`3#jgRobbI(-|gttmVFxs7j6#0odoR3*V^UY z&rLp{TFHUDy>Vt}cuP92?s z0$Y>!Ys_QEQLy*Nd0B}Y!*G^H_eRg-LPNn&IknCA*o?6BkQM?#yXAf>NFUNsp}b5PaiH_6|F zhHjcTO0ek{^uW#KgISiG9gILWBmF~*SsW{j#v}lOj8ldbO8R;%EyVTd+n%71ZqXct zqFGpGpEAqueCne}ja0wYn;9A>6DP8!(dTzn%3=#b=Cavy9_2hBpVT}ud0S&Y>Kg&j za|RvOC*>Pq_qbjT>lR2l0TvetQ;6*IbPcCC7Cc?y=WH6K3U9J;;86w?_m6Ura8IZdgH=@>}>qY8iXdn z&}4`{KLjW>>V*aaLXRT1w1aX?#3>aw5U>B%bqgFdXO4BE_K7lijjdFz$qb#o;+UN4 z2n(55`MvSwJHRi414{$$VX1?l!$y8e5VrPY&%)mdjLN|CjXVh^dcz9Tr#`3?#kToh z)gXe6BZ~hI~zOtK-bLWnGO9A zpT$j9da4}6oKTWY)!Q%Al`9vA6fGS($!)j@rg9PKdxvmXw!XG>Mx#!&pFasS!ul{x zAO&0&net>XI|V$u#x5#nh5(%_`buUgjP{81sHswWR9F0zd$CzVbC_daY*(y=8#wKd zMW3FlA<64CGroF`b??xW#=CjiDa-hUh(HHsc+jMXBzGy9lGo+`ud?$DYclQI{MZI@ zC`0dH89{ncBApqKAWaB8^xi^1sfHGXks^d5(xeGU54{NlkdE{cij)LFKthRh2!ZU4 z&pf-&?!L#d@8;|ME%$XF*T0-eR5lQI}y|hqb>s z5pbLXkGQ!d9OdLn60$dy!v{>q;D+H2`0pDcn}cPeTX|5kQiwTYyCzJ>w0{66wVjf= zpR#I)ZkYO_5HLyE{IL+%yc<7B*iZQ+*Hx<|P=jj;q~(|j=)h74nQK~6@;Xf%x7@R% zrZK;&|o>YLtQFnW?Fh96wkc6 ztg#*Ztj{1dsk>-cQaO7_I=M>v{p{PTb!o(i@BN>qUu5zIv z)}p;J+-<)~IiyfaySb87+N=408bOs7b3LSubS&`$|^*ICko||G_=)0MzB)VC1 z?b8F)xm~)4>|?aQX^;U^Vqc#lE9KpX2fo#|f^^bxvva};9vq5c^la}xXk@BCyEdc( z!unWUz9WQql%CFpkL(u-dIv4&cN?`bh%pL8D1YXHXiTrB(@D3omkH_mbLt>e!S%3D zG`N(AS~)Y5_q;kMh}6E`%^_9Dsp@Q>v!C;_o?6oD3Uzx(S6lcNu)FsGI_O`d;os&b zGPT3z9gz@O@{E$T$!rp;W*CbmWn4;pTkyLdboMp*&ajAm8rU@O>_y>J0p=JeD{FjZ zSzMY6Ngm!DZ{p1P=c{hd1Gn$gaDM&%$_n^Wa`Ot7zHhYTk+;z;<5SXKR~Z^mLh*t9 za`>-7%=p`WlVHb_)DhXaq_E!}W}bdG&T%|+v^zh!{b1f$WGLyL#z-AW{pyK-6GGQ| zpf`8BK5o408)L0p2UUUfw^!wI8^kWmfcfzyfCZ%oTXICc{ zf*fy^f6ylu!s^xEk7I#|jO;aYU<}rQk0BS5w*B7PWly%T=Cdw4rQ1P*g+G&Qd#llI zaj(EBX5?(Aq;+nb0gbCbi-nH1WZvRBxz#mCmpNCX8|Q(>I(8L7v9Q+-6xvGUTNQp; zyf`zU<9{pctvg5IEe16p4RgJctO9kmOs2hB22)B;T=RLgUIMVYm!~n~@DEvP^-!&X zh7`6_Dn%zbcwBz;xjyR-jkka8Q66Q^g=;Bs1c<=Hf%xKQh3=%buT_%#)xED(kC;-d zxCJ}v=t5fiPA&iCRwgR^BTTom;{{yHv+5AKaFk-XdeeC1w1j<~KzE*d)JxM24z>EC zks9cnHQZmSlJY%&PFzbBZ{n5Nlk}F&j6dY~ zeu2V1x%`+}_X2J7cX#D{830JP7k9M-!EYLfI6U@22YI1y$%Ps zmu2GLwjf%yPx9eCV`fF+-5@{=S3PCtD%i=N{cP2BH^E)ox1l8=;k-_>rSA4gK<<C8&MqApezj@!W7|EV|J3CDo z&uioc^SpXZ)EHkDbu3eqNgips@y!%qnOl|DB+T2?LDXM)&d#|w+G;^iL}2zCZS%~e zaXvk)W-^JyzLdA8P>V9mdUy&R35RJ0F}O{pOO)pgoab&gL{mev5?FFwonP;}=%ugt zd5DEabiFCy9cpLB8K1?4IM~PtLDI4o)}QUsn>*!Y#WrkU=9}D6n)nnHy&S?LK1cIF zFZeC-{Uwewbl@NcJ9lSrFL)!_56ik3CPwP~`-4iYn^IhUi%h7XCAX?FcTt-s@Eur! z1{CO{#vCC#^jM|yho2e>#GVzgCzf)(EM9Dpd+dQXIx;d_QuRvG4`rS7{Em6o9RlVN z1GjYMj&Pa6QU}c*0(wjQ=}vFwcHZ0}&96JJLRba(Q-Su7(uUG8K?j(Y#BtR$GS+>O zO`SDL=jl`ZTDI7B>1}$(6MaezLuzpYQej@yVJh zO5E6#EZH%x4CSm~vx5v$m>jWhR>=*N@WAY#P$W@n13Nogb)`)n$&18zQz2d4yNHa8 z`>mrh0`ILoapXR*Xz6o;;U=x5`w<<_YjlfwlY1U+OZ@O{kJBTj8s>ac>&JYDU@wxo zksoLX4tnGHD=-&J$assQ9!|kk@bq<$-R|}VrWK)yKzGk}d=lUwVEtP(&8zW!g~3Sg zB|k^osVW5rtTCzJm#k-1{dSG7`_UF6)dkL(AH~_y;29~LSeBo9-k4SK??x@riP3sv z<1=TVCWG)81Ka@}u8icK@ui($Mq_T(`HS@9;ZQ zLs@iLwxh)8~Jb@QpqwXvOGJKKFO_QdL{j zB+RbortQT*%Q|X{jD`fE5!C##!#ol20|s~?fvpQuk*{V?-1Vc z6Axo^g0_asRR+#%tPJ_+6e{?)MpVu6+N|FIa_}cs9fM|0f=Vk%kn&Brdp)qc^p8-Z z$TJ}mGWSHI{>V&?$%YS*2PxC=a*Wcj3ED;J74TV_B6iNW7SrlNlE0rXnd6TQUuAc{ z$zjHplv zH*v(!-3K_?WeVD=Y2Lp8_;CL>pGV9qqSNmGh_3)XB~3Abi-M^FxB~W(Bmsw(Ge5kv z8`NQV8wbaRfw$U%f6Gh8=K6SHi@qPgCJ(MHlL|>-Ys`%bz$Ncm3Ty)#TJv z$tXK1N%CL2nAq4t_7ZWC)f4-KR^k7kk06>v@Hq4k;E{i|g|vDbHs-n2jy+p7iJ z9hxY-Wp|6;E>SQ+p6wqkU&6mw1psp82J{<_bmfBPv1!}-2Vg3)A6XvU_SUNpbYFEn z{OPJEc#1URvqO*0PqKr-qGblBJ4g!gxVu0nr)R~0Ev-86aPf#uY%xwp=XfH;+U=~W zj2789)a^;n8(BiDG74xe`c5_%g8{ z1tyBW|CP@)LEKyV3AW`k4T5R%2|WsXjVM9v=umk~VOLYFoTxwBO0GBo=5hC~6dE=z9qE@ZtYvuV!vBQ- z72deNkmVrwsR}9?85PwIaK6VxWQBdx%4lVc8}o)uIT@XfWAnWqRsEgO=_0qZf$@$f zIbTHIUStW(1el57`_VjLFg)x0G&E%Eo(M?WG7Yov;Dxo`GjW;$&>V?!Pz8%dr$(aK!{%?_`TxPekR~O?FO(*gM7-`M{qBmM} z!+Ws{fd9U8GFKhL;E6JYz6DeUpBg5mAlrxNm99&RWjFb4cM+GCcX|Vlew^<6khl97 z?1y<}Uf_9@V(^(tC}mtL3UA$L2c8R`+_@g04;C#(;1n#_AJPS0&VwD%1+yR`{KD%Y z)&z0g*nB`>Yq0KeiF1}axrZ?W)lg8}qBqqkvKs_U+}8(09!``UsM4=2uNn*u_+qVx zcM9l~P5*}JqSOE=f`YY3t))>?SYGdu?O{Z;gzxs{K~ug6MDO?xWL6q2))aj(sob$j zvKBhKVO~zrJXb1i^KI)2C-B+(+D7#I(ysF8OgCmrIV(98*UR`V{Zdk)mH|p^9XL=D zOva$HWaZ>rKlSPd+P!nkAgNVZcsh%G*^pPBaw=ZmSGfPXwJ;nYQm9<`If7rUJR6)P zj#~E~b1N4A?wyiizZ$Uum^!xx#(M*??@(Sj})8QW?G=cX++0>nE#|P~& zc$?=fld z+NrPDv{$=zXRRlV$xd2#Y935H>#3AR*6i%U3V#4|;cNnD9X(SO!?JKiW|W%%q}85hxh$PkodAcajt;oM?36D zO>b1}$VcLW4>rkXN`_5=_h&!WwlzS_ywC?GfcsxOP)LON&PB9PRxqnR6hSuyw~G6G z-`RdOmdVsF|B^WY`Rbsqt*Zpq*41l*jJ?aE+)1^fNg#IYW|vGW`=0k7CeEDeomry2 zn$ZL{Q^XeA%zH0gr|sQAt`eQtjrtsrkXU0baBIZ5b)L`ow<&7fn7TGN)~Lb48g0}n zIOHfeGq?i;fnizt^?4$o!#f*Nv|9G#r^8jm4ThRk1;lnAPL{em_@+2`)zlWS4FA+D z1116h=ZzY&z(`8-aUinok8pCE^9FHM2D?9YUGg86-}LKZp$V+{MLc$JVwF%@;cVZR zdfh5OllHAn8K&YARqroWpiWZEda=5)Yyvwj`?umRo zlaQ9PHJJ^VX@<=70g2`XSU({9|AnvBM%sR9SPaG-S(6QJj+{;-yEF5(REGu%Md2M* zZLxSB`NJQsu}8#SJ~y}hd-J2a5s_0xXPeYqbsv%udruMM>*>58-FeU3tKBG&&WaLKiLbhb!Z8ZlEH9LC!&OYFPrUUGJAYKnYWOBflB z$XD(@Ra5R6T*|g7*fXgQ^bhp-tZQga=7v?Asl>JBgK`;0%>CT4aCNv#gD-NuxjnVl zt}4dRT*1s(*t@YAX<5+yrm^FTGHq{(4*H?gRBELUuV=P1p}rxzlfU$dx7Y}CLGZs* zW_}`|Tq^O|E)nH2HAdojgh~ z-?;+MdXi=mJD(fq(sU|3cp|~JVnna!zuY^6{BTK}rX|!ng=l+LE(ds%qjqPr?RGca zu^{p<(_F~E-|RNugY0CZD?ZVOkOSWu-pj&*GPIje8xN5$j_>Pye1l|5I#B-9k23lg zzr(S6L%z~vvc(xMD?(npg27W2D$`8_POREu)2TY<(0tJ(41DTM)=^+n%|9H9)LvU) zGtB&FlHLo&uIXe;aFy-oRoicTO9N7s-~OC#tn!n+NC}$sG&L(<0$X17rc_WS9$wpR zrX0u3FmOd%d*Ha;Y?O?)W?tggzAYZr@^1}iewC~@Bom)xb@37B*R3#jrQEXjBhAbo zG#x&+@!86{r5a!3DXi4&Z%Hcu4_GFE^i@a~aoEkzP<;6r*dZ8ORD)bijL*3Dv`~;D z9o3V$!gDb__+FG--cU)I)7F!5;2iXY!+~?)chUf`I%ikd=y4ymNOBxSKs$s%r#v>YOd|;K1LGd%^{0H4=Td8I3<;(*iCS5nBMW z80R=efRxG3)GqVKW?){v>~t;p>aLxU6jxAhZTF1}dasof?2fmL>ZC>;+o(}1={NZ_ zUgN5_Ry7(*VJ8Rt`Xs9n6*tA4({vtjY=dB+fX*-%{(}|IR0N ze)YbS0vA{`sz5cwnV?U@nZ%0oI5Whq!E5T3=O-@sq%9-=U6S;HIxA;OTD7+&w#dw^ z^l)~*G3VD+gX!&sV^w$=G!KLZ(jShN;&^zRbml5|0nd8xgIv&{L$H2s9n94So*~_o zY{eJiEn?=8w2WJ5Qkt~BnA!YHo%}b(Xu+{DFlA|@5;kItX?EdIY6{{hEkVYf+*R&5 zeWlz%b64uu^*Z;XA-ELQ#E3$}S6ZJ3n&)UxtJ{)ZsK-v}R=54|v;N+UIqNd*yJ?xd zwAl>wFx1_01>VUu9`1u^#aL={RQT1APl^!x;f?ZF^1^fnVp@{1@&>%U?id?WGy?|m zuEm;f4u*iN{1IsV0|T6k{R{q(a*aYP^t7Y$dh30W-#m3h|MWXo{G*_D$;R$JtBCkt z!OOZ5E|2)1WHh3fG#aWLbwy+U0NuJj9*Yj8L*s&29;S!Hte6Wu+x1~$EfWL|OB}Y! zQRX?BU(C572Tkzal+lY|vl{AA&$d$av!&upM}~?vmp)zW($UVcd=a|Kx6}+=O3n}t zq4Kle1=-}{(*o%`d%i8|4_`s!q0t6w?<#|WS(akwAI+_`wO=wq+VzWO$WF)5%5(j| zk)@d5hQ#ircnH_s-qMt>-z;md)?Jcx-k#SpsFi)!*um|r6x&}c@?BpSROEG@LL)|#-Up*0xytW(L8!ByInpm<$t+*Y_5C3*^9_~87r5cn6^KaX|A>|K$ zq@Iq5KYVrG(F>IKKrQeevl`2)(d&bA4Ff+u7s4chExAFH=iJc)NJ3iZ?ok@4`BB{h zcrqNDENqxwUvGR`pmtt=_6m#K&NKAqT!ISh&M)Ue$*_5kzV&x^k%>(5Fg{KTR?pzs zR8%pE+{l%&^@R$EHHd!rN-9%*7HE2aQ=BherBDKhX1aT53J+{57MoS?uq)MHB@W)} zfC1a`Bf&p1TK;)-~Pntqi3m;wE$6 zD$7~5P8emLM7-r|B5LqDy!rgz|As#k*Sc~}5iU&&dVP?v_Y3gTP diff --git a/src/Umbraco.Web.UI.Client/src/views/dataTypes/delete.html b/src/Umbraco.Web.UI.Client/src/views/dataTypes/delete.html index 1fc9a2adfd..e27433c739 100644 --- a/src/Umbraco.Web.UI.Client/src/views/dataTypes/delete.html +++ b/src/Umbraco.Web.UI.Client/src/views/dataTypes/delete.html @@ -106,9 +106,7 @@